def del_contact(self, account_jid, jid): """ Remove jid from account_jid roster """ try: account_jid_id = self.get_jid_id(account_jid) jid_id = self.get_jid_id(jid) except exceptions.PysqliteOperationalError as e: raise exceptions.PysqliteOperationalError(str(e)) self.cur.execute( 'DELETE FROM roster_group WHERE account_jid_id=? AND jid_id=?', (account_jid_id, jid_id)) self.cur.execute( 'DELETE FROM roster_entry WHERE account_jid_id=? AND jid_id=?', (account_jid_id, jid_id)) self._timeout_commit()
def add_or_update_contact(self, account_jid, jid, name, sub, ask, groups, commit=True): """ Add or update a contact from account_jid roster """ if sub == 'remove': self.del_contact(account_jid, jid) return try: account_jid_id = self.get_jid_id(account_jid) jid_id = self.get_jid_id(jid) except exceptions.PysqliteOperationalError as e: raise exceptions.PysqliteOperationalError(str(e)) # Update groups information # First we delete all previous groups information self.cur.execute( 'DELETE FROM roster_group WHERE account_jid_id=? AND jid_id=?', (account_jid_id, jid_id)) # Then we add all new groups information for group in groups: self.cur.execute('INSERT INTO roster_group VALUES(?, ?, ?)', (account_jid_id, jid_id, group)) if name is None: name = '' self.cur.execute( 'REPLACE INTO roster_entry VALUES(?, ?, ?, ?, ?)', (account_jid_id, jid_id, name, self.convert_human_subscription_values_to_db_api_values(sub), bool(ask))) if commit: self._timeout_commit()
def commit_to_db(self, values, write_unread=False): sql = '''INSERT INTO logs (jid_id, contact_name, time, kind, show, message, subject, additional_data) VALUES (?, ?, ?, ?, ?, ?, ?, ?)''' try: self.cur.execute(sql, values) except sqlite.OperationalError as e: raise exceptions.PysqliteOperationalError(str(e)) except sqlite.DatabaseError: raise exceptions.DatabaseMalformed message_id = None if write_unread: try: self.con.commit() message_id = self.cur.lastrowid except sqlite.OperationalError as e: print(str(e), file=sys.stderr) else: self._timeout_commit() if message_id: self.insert_unread_events(message_id, values[0]) return message_id
def get_jid_id(self, jid, typestr=None): """ jids table has jid and jid_id logs table has log_id, jid_id, contact_name, time, kind, show, message so to ask logs we need jid_id that matches our jid in jids table this method wants jid and returns the jid_id for later sql-ing on logs typestr can be 'ROOM' or anything else depending on the type of JID and is only needed to be specified when the JID is new in DB """ if jid.find('/') != -1: # if it has a / jid_is_from_pm = self.jid_is_from_pm(jid) if not jid_is_from_pm: # it's normal jid with resource jid = jid.split('/', 1)[0] # remove the resource if jid in self.jids_already_in: # we already have jids in DB self.cur.execute('SELECT jid_id FROM jids WHERE jid=?', [jid]) row = self.cur.fetchone() if row: return row[0] # oh! a new jid :), we add it now if typestr == 'ROOM': typ = constants.JID_ROOM_TYPE else: typ = constants.JID_NORMAL_TYPE try: self.cur.execute('INSERT INTO jids (jid, type) VALUES (?, ?)', (jid, typ)) self.con.commit() except sqlite.IntegrityError: # Jid already in DB, maybe added by another instance. re-read DB self.get_jids_already_in_db() return self.get_jid_id(jid, typestr) except sqlite.OperationalError as e: raise exceptions.PysqliteOperationalError(str(e)) jid_id = self.cur.lastrowid self.jids_already_in.append(jid) return jid_id
def write(self, kind, jid, message=None, show=None, tim=None, subject=None, additional_data={}): """ Write a row (status, gcstatus, message etc) to logs database kind can be status, gcstatus, gc_msg, (we only recv for those 3), single_msg_recv, chat_msg_recv, chat_msg_sent, single_msg_sent we cannot know if it is pm or normal chat message, we try to guess see jid_is_from_pm() We analyze jid and store it as follows: jids.jid text column will hold JID if TC-related, room_jid if GC-related, ROOM_JID/nick if pm-related. """ if self.jids_already_in == []: # only happens if we just created the db self.open_db() contact_name_col = None # holds nickname for kinds gcstatus, gc_msg # message holds the message unless kind is status or gcstatus, # then it holds status message message_col = message subject_col = subject additional_data_col = json.dumps(additional_data) if tim: time_col = float(tim) else: time_col = float(time.time()) kind_col, show_col = self.convert_human_values_to_db_api_values( kind, show) write_unread = False # now we may have need to do extra care for some values in columns if kind == 'status': # we store (not None) time, jid, show, msg # status for roster items try: jid_id = self.get_jid_id(jid) except exceptions.PysqliteOperationalError as e: raise exceptions.PysqliteOperationalError(str(e)) if show is None: # show is None (xmpp), but we say that 'online' show_col = constants.SHOW_ONLINE elif kind == 'gcstatus': # status in ROOM (for pm status see status) if show is None: # show is None (xmpp), but we say that 'online' show_col = constants.SHOW_ONLINE jid, nick = jid.split('/', 1) try: # re-get jid_id for the new jid jid_id = self.get_jid_id(jid, 'ROOM') except exceptions.PysqliteOperationalError as e: raise exceptions.PysqliteOperationalError(str(e)) contact_name_col = nick elif kind == 'gc_msg': if jid.find('/') != -1: # if it has a / jid, nick = jid.split('/', 1) else: # it's server message f.e. error message # when user tries to ban someone but he's not allowed to nick = None try: # re-get jid_id for the new jid jid_id = self.get_jid_id(jid, 'ROOM') except exceptions.PysqliteOperationalError as e: raise exceptions.PysqliteOperationalError(str(e)) contact_name_col = nick else: try: jid_id = self.get_jid_id(jid) except exceptions.PysqliteOperationalError as e: raise exceptions.PysqliteOperationalError(str(e)) if kind == 'chat_msg_recv': if not self.jid_is_from_pm(jid): # Save in unread table only if it's not a pm write_unread = True if show_col == 'UNKNOWN': # unknown show, do not log return values = (jid_id, contact_name_col, time_col, kind_col, show_col, message_col, subject_col, additional_data_col) return self.commit_to_db(values, write_unread)