First stage in refactor: implemented schemas

parent 4f3f7c54
......@@ -41,7 +41,7 @@ class PyreQT(QMainWindow):
......@@ -253,8 +253,8 @@ class PyreQT(QMainWindow):
serverTimestamp = message['serverTimestamp']
# TODO: we should check for an attachment and include it in the database
attachment = None
self.dbConnector.addMessage(thread, name, number, messageText, attachment, timestamp, serverTimestamp)
attachments = message["attachments"]
self.dbConnector.addMessage(thread, name, number, messageText, attachments, timestamp, serverTimestamp)
# show tray notification
self.trayIcon.showMessage("PyreQT: "+name, messageText, QIcon("pyreqt/res/icon.png"))
......@@ -6,70 +6,95 @@ class dbConnector():
connection = None
cursor = None
# sets up connection and cursor
# query templates
listContacts = "SELECT name, number, color FROM contacts"
insertAttachment = "INSERT INTO attachments (type, filepath) VALUES (?, ?)"
selectAttachmentId = "SELECT rowid FROM attachments WHERE filepath = ?"
insertAttachmentMapping = "INSERT INTO messageattachments (messageid, attachmentid) VALUES (?, ?)"
updateContact = "INSERT OR REPLACE INTO contacts (name, number, color) VALUES (?, ?, ?)"
insertMessage = "INSERT INTO messages (sender, recipient, contents, timestamp) VALUES (?, ?, ?, ?)"
selectMessageId = "SELECT rowid FROM messages WHERE sender = ? AND recipient = ? AND contents = ?"
selectMessageThread = "SELECT sender, contents, timestamp FROM messages WHERE recipient = ?"
selectContactName = "SELECT name FROM contacts WHERE number = ?"
selectAttachmentIdsFromMessageId = "SELECT attachmentid FROM messageattachments WHERE messageid = ?"
selectAttachmentById = "SELECT type, filepath FROM attachments WHERE rowid = ?"
def __init__(self):
self.connection = sqlite3.connect("/home/"+os.environ["USER"]+"/.config/pyre/storage.db")
self.cursor = self.connection.cursor()
# metadata table, should eventually contain all relevant thread wide metadata
self.cursor.execute("CREATE TABLE IF NOT EXISTS master(name TEXT, id TEXT UNIQUE, color TEXT)")
# rowid for autoincrement primary key
# sender and recipient both refer to rowid of contacts table
# TODO: fully constrain this by marking them as foreign keys
self.cursor.execute("CREATE TABLE IF NOT EXISTS messages(sender INT, recipient INT, contents TEXT, timestamp INT)")
# number for primary key
self.cursor.execute("CREATE TABLE IF NOT EXISTS contacts(name TEXT, number INT, color TEXT)")
# rowid for autoincrement primary key
self.cursor.execute("CREATE TABLE IF NOT EXISTS attachments(type TEXT, filepath TEXT)")
# both IDs refer to rowid in attachment and message
self.cursor.execute("CREATE TABLE IF NOT EXISTS messageattachments(messageid INT, attachmentid INT)")
except Exception as e:
raise e
# returns a list of the threads in the database
def listThreads(self):
self.cursor.execute("SELECT name, id, color FROM master ORDER BY name")
return [{"name": i[0], "id":i[1], "color":i[2]} for i in self.cursor.fetchall()]
# TODO: order by last update
return [{"name": i[0], "id": i[1], "color": i[2]} for i in self.cursor.fetchall()]
# takes signald contact data and updates master table with it
# data in arg comes from signald list_contacts or a modified singald list_groups
# see pyreqt/ for more information
def updateThreads(self, arg):
for i in arg:
updateMessage = "INSERT OR REPLACE INTO master (name, id, color) VALUES (?, ?, ?)"
self.cursor.execute(updateMessage, (i["name"], i["number"], i["color"]))
# adds a message to the table corresponding to the thread's table
def addMessage(self, thread, name, number, message, attachment, timestamp, serverTimestamp):
md5 = hashlib.md5(thread.encode('utf-8')).hexdigest()
createTable = "CREATE TABLE IF NOT EXISTS '{}' (name TEXT, number TEXT, message TEXT, attachment TEXT, timestamp TEXT, serverTimestamp TEXT)".format(md5)
addThreadToMaster = "INSERT OR REPLACE INTO MASTER (name, id, color) VALUES ('{}', '{}', 'black')".format(name, id, name, id)
insertMessage = "INSERT INTO '{}' (name, number, message, attachment, timestamp, serverTimestamp) VALUES(?, ?, ?, ?, ?, ?)".format(md5)
self.cursor.execute(self.updateContact, (i["name"], i["number"], i["color"]))
def addAttachment(self, filepath, filetype, messageid):
self.cursor.execute(self.insertAttachment, filetype, filepath)
self.cursor.execute(self.getAttachmentId, filepath)
attachmentId = self.cursor.fetchone()
if attachmentId == None:
# Maybe assertionerror?
raise IndexError("Could retrieve attachment id from fresh store operation!")
self.cursor.execute(self.insertAttachmentMapping, messageid, candidateId)
def getAttachmentById(self, attachmentId):
self.cursor.execute(self.selectAttachmentById, attachmentId)
self.cursor.execute(insertMessage, (name, number, message, attachment, timestamp, serverTimestamp))
def getAttachmentFromMessageId(self, messageId):
self.cursor.execute(self.selectAttachmentIdsFromMessageId, messageId)
return [ [self.getAttachmentById(i)] for i in self.cursor.fetchall() ]
# returns Message ID
def addMessage(self, thread, sender, message, attachments, timestamp):
self.cursor.execute(self.insertMessage, sender, thread, message, timestamp)
self.cursor.execute(self.selectMessageId, sender, thread, message)
# retrieves a thread from the db
def retrieveThread(self, thread):
threadhash = hashlib.md5(thread.encode("UTF-8")).hexdigest()
self.cursor.execute("SELECT * FROM '"+threadhash+"'")
except Exception as e:
# probably no table there
return None
return self.cursor.fetchall()
# WIP: stores an attachment and returns an ID
def storeAttachment(self, data, type_tag):
# get md5sum of data
md5 = hashlib.md5(data.encode('utf-8')).hexdigest()
self.cursor.execute("CREATE TABLE IF NOT EXISTS attachments(id TEXT, data TEXT, type TEXT)")
self.cursor.execute("INSERT INTO attachments(id, data, type) VALUES(?, ?, ?)",(md5, data, type_tag))
return md5
messageId = self.cursor.fetchone()
if messageId == None:
# Maybe assertionerror?
raise IndexError("Couldnt retrieve message id from fresh store operation!")
# WIP: retrieves an attachment cooresponding to an ID
def getAttachment(self, id):
self.cursor.execute("SELECT data, type FROM attachmenst WHERE id LIKE '" + id + "'")
return c.fetchone()
for i in attachments:
self.addAttachment(i["storedFilepath"], i["contentType"], messageId)
return messageId
def getContactNameFromId(self, contactId):
self.cursor.execute(self.selectContactName, contactId)
def retrieveThread(self, thread):
self.cursor.execute(self.selectMessageThread, thread)
return [ [self.getContactNameFromId(i[0]) or "Anonymous"]+i for i in self.cursor.fetchall() ]
# call this at closing of the program
# syncronizes changes made to the database
# closes cursor and connection
def sync(self):
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment