toxygen/toxygen/history/database.py

231 lines
7.2 KiB
Python

# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
from sqlite3 import connect
import os.path
import utils.util as util
# LOG=util.log
global LOG
import logging
LOG = logging.getLogger('app.'+__name__)
log = lambda x: LOG.info(x)
TIMEOUT = 11
SAVE_MESSAGES = 500
MESSAGE_AUTHOR = {
'ME': 0,
'FRIEND': 1,
'NOT_SENT': 2,
'GC_PEER': 3
}
CONTACT_TYPE = {
'FRIEND': 0,
'GC_PEER': 1,
'GC_PEER_PRIVATE': 2
}
class Database:
def __init__(self, path, toxes):
self._path = path
self._toxes = toxes
self._name = os.path.basename(path)
def open(self):
path = self._path
toxes = self._toxes
if not os.path.exists(path):
LOG.warn('Db not found: ' +path)
return
try:
with open(path, 'rb') as fin:
data = fin.read()
except Exception as ex:
LOG.error('Db reading error: ' +path +' ' +str(ex))
raise
try:
if toxes.is_data_encrypted(data):
data = toxes.pass_decrypt(data)
with open(path, 'wb') as fout:
fout.write(data)
except Exception as ex:
LOG.error('Db writing error: ' +path +' ' + str(ex))
os.remove(path)
# -----------------------------------------------------------------------------------------------------------------
# Public methods
# -----------------------------------------------------------------------------------------------------------------
def save(self):
if self._toxes.has_password():
with open(self._path, 'rb') as fin:
data = fin.read()
data = self._toxes.pass_encrypt(bytes(data))
with open(self._path, 'wb') as fout:
fout.write(data)
def export(self, directory):
new_path = util.join_path(directory, self._name)
with open(self._path, 'rb') as fin:
data = fin.read()
if self._toxes.has_password():
data = self._toxes.pass_encrypt(data)
with open(new_path, 'wb') as fout:
fout.write(data)
def add_friend_to_db(self, tox_id):
db = self._connect()
try:
cursor = db.cursor()
cursor.execute('CREATE TABLE IF NOT EXISTS id' + tox_id + '('
' id INTEGER PRIMARY KEY,'
' author_name TEXT,'
' message TEXT,'
' author_type INTEGER,'
' unix_time REAL,'
' message_type INTEGER'
')')
db.commit()
return True
except Exception as e:
LOG("ERROR: " +self._name +' Database exception! ' +str(e))
db.rollback()
return False
finally:
db.close()
def delete_friend_from_db(self, tox_id):
db = self._connect()
try:
cursor = db.cursor()
cursor.execute('DROP TABLE id' + tox_id + ';')
db.commit()
return True
except Exception as e:
LOG("ERROR: " +self._name +' Database exception! ' +str(e))
db.rollback()
return False
finally:
db.close()
def save_messages_to_db(self, tox_id, messages_iter):
db = self._connect()
try:
cursor = db.cursor()
cursor.executemany('INSERT INTO id' + tox_id +
'(message, author_name, author_type, unix_time, message_type) ' +
'VALUES (?, ?, ?, ?, ?, ?);', messages_iter)
db.commit()
return True
except Exception as e:
LOG("ERROR: " +self._name +' Database exception! ' +str(e))
db.rollback()
return False
finally:
db.close()
def update_messages(self, tox_id, message_id):
db = self._connect()
try:
cursor = db.cursor()
cursor.execute('UPDATE id' + tox_id + ' SET author = 0 '
'WHERE id = ' + str(message_id) + ' AND author = 2;')
db.commit()
return True
except Exception as e:
LOG("ERROR: " +self._name +' Database exception! ' +str(e))
db.rollback()
return False
finally:
db.close()
def delete_message(self, tox_id, unique_id):
db = self._connect()
try:
cursor = db.cursor()
cursor.execute('DELETE FROM id' + tox_id + ' WHERE id = ' + str(unique_id) + ';')
db.commit()
return True
except Exception as e:
LOG("ERROR: " +self._name +' Database exception! ' +str(e))
db.rollback()
return False
finally:
db.close()
def delete_messages(self, tox_id):
db = self._connect()
try:
cursor = db.cursor()
cursor.execute('DELETE FROM id' + tox_id + ';')
db.commit()
return True
except Exception as e:
LOG("ERROR: " +self._name +' Database exception! ' +str(e))
db.rollback()
return False
finally:
db.close()
def messages_getter(self, tox_id):
self.add_friend_to_db(tox_id)
return Database.MessageGetter(self._path, tox_id)
# -----------------------------------------------------------------------------------------------------------------
# Messages loading
# -----------------------------------------------------------------------------------------------------------------
class MessageGetter:
def __init__(self, path, tox_id):
self._count = 0
self._path = path
self._tox_id = tox_id
self._db = self._cursor = None
def get_one(self):
return self.get(1)
def get_all(self):
self._connect()
data = self._cursor.fetchall()
self._disconnect()
self._count = len(data)
return data
def get(self, count):
self._connect()
self.skip()
data = self._cursor.fetchmany(count)
self._disconnect()
self._count += len(data)
return data
def skip(self):
if self._count:
self._cursor.fetchmany(self._count)
def delete_one(self):
if self._count:
self._count -= 1
def _connect(self):
self._db = connect(self._path, timeout=TIMEOUT)
self._cursor = self._db.cursor()
self._cursor.execute('SELECT message, author_type, author_name, unix_time, message_type, id FROM id' +
self._tox_id + ' ORDER BY unix_time DESC;')
def _disconnect(self):
self._db.close()
# -----------------------------------------------------------------------------------------------------------------
# Private methods
# -----------------------------------------------------------------------------------------------------------------
def _connect(self):
return connect(self._path, timeout=TIMEOUT)