comparison src/memory/sqlite.py @ 512:862c0d6ab974

core, bridge, quick_frontend: MUC private messages history management: - history now store message type - sqlite3 storage: fixed resource management in getHistory - bridge: added message type in getHistory return value - quick_chats: (ugly) hacks to manage private history filtering/nickname printing
author Goffi <goffi@goffi.org>
date Wed, 17 Oct 2012 00:35:48 +0200
parents 2a072735e459
children 2c4016921403
comparison
equal deleted inserted replaced
511:62f7f2403093 512:862c0d6ab974
44 init_defers.append(self.dbpool.runOperation("PRAGMA foreign_keys = ON").addErrback(lambda x: error(_("Can't activate foreign keys")))) 44 init_defers.append(self.dbpool.runOperation("PRAGMA foreign_keys = ON").addErrback(lambda x: error(_("Can't activate foreign keys"))))
45 if new_base: 45 if new_base:
46 info(_("The database is new, creating the tables")) 46 info(_("The database is new, creating the tables"))
47 database_creation = [ 47 database_creation = [
48 "CREATE TABLE profiles (id INTEGER PRIMARY KEY ASC, name TEXT, UNIQUE (name))", 48 "CREATE TABLE profiles (id INTEGER PRIMARY KEY ASC, name TEXT, UNIQUE (name))",
49 "CREATE TABLE history (id INTEGER PRIMARY KEY ASC, profile_id INTEGER, source TEXT, dest TEXT, source_res TEXT, dest_res TEXT, timestamp DATETIME, message TEXT, FOREIGN KEY(profile_id) REFERENCES profiles(id))", 49 "CREATE TABLE message_types (type TEXT PRIMARY KEY)",
50 "INSERT INTO message_types VALUES ('chat')",
51 "INSERT INTO message_types VALUES ('error')",
52 "INSERT INTO message_types VALUES ('groupchat')",
53 "INSERT INTO message_types VALUES ('headline')",
54 "INSERT INTO message_types VALUES ('normal')",
55 "CREATE TABLE history (id INTEGER PRIMARY KEY ASC, profile_id INTEGER, source TEXT, dest TEXT, source_res TEXT, dest_res TEXT, timestamp DATETIME, message TEXT, type TEXT, FOREIGN KEY(profile_id) REFERENCES profiles(id), FOREIGN KEY(type) REFERENCES message_types(type))",
50 "CREATE TABLE param_gen (category TEXT, name TEXT, value TEXT, PRIMARY KEY (category,name))", 56 "CREATE TABLE param_gen (category TEXT, name TEXT, value TEXT, PRIMARY KEY (category,name))",
51 "CREATE TABLE param_ind (category TEXT, name TEXT, profile_id INTEGER, value TEXT, PRIMARY KEY (category,name,profile_id), FOREIGN KEY(profile_id) REFERENCES profiles(id))", 57 "CREATE TABLE param_ind (category TEXT, name TEXT, profile_id INTEGER, value TEXT, PRIMARY KEY (category,name,profile_id), FOREIGN KEY(profile_id) REFERENCES profiles(id))",
52 "CREATE TABLE private_gen (namespace TEXT, key TEXT, value TEXT, PRIMARY KEY (namespace, key))", 58 "CREATE TABLE private_gen (namespace TEXT, key TEXT, value TEXT, PRIMARY KEY (namespace, key))",
53 "CREATE TABLE private_ind (namespace TEXT, key TEXT, profile_id INTEGER, value TEXT, PRIMARY KEY (namespace, key, profile_id), FOREIGN KEY(profile_id) REFERENCES profiles(id))", 59 "CREATE TABLE private_ind (namespace TEXT, key TEXT, profile_id INTEGER, value TEXT, PRIMARY KEY (namespace, key, profile_id), FOREIGN KEY(profile_id) REFERENCES profiles(id))",
54 "CREATE TABLE private_gen_bin (namespace TEXT, key TEXT, value BLOB, PRIMARY KEY (namespace, key))", 60 "CREATE TABLE private_gen_bin (namespace TEXT, key TEXT, value BLOB, PRIMARY KEY (namespace, key))",
167 d = self.dbpool.runQuery("REPLACE INTO param_ind(category,name,profile_id,value) VALUES (?,?,?,?)", (category, name, self.profiles[profile], value)) 173 d = self.dbpool.runQuery("REPLACE INTO param_ind(category,name,profile_id,value) VALUES (?,?,?,?)", (category, name, self.profiles[profile], value))
168 d.addErrback(lambda ignore: error(_("Can't set individual parameter (%(category)s/%(name)s) for [%(profile)s] in database" % {"category":category, "name":name, "profile":profile}))) 174 d.addErrback(lambda ignore: error(_("Can't set individual parameter (%(category)s/%(name)s) for [%(profile)s] in database" % {"category":category, "name":name, "profile":profile})))
169 return d 175 return d
170 176
171 #History 177 #History
172 def addToHistory(self, from_jid, to_jid, message, timestamp=None, profile=None): 178 def addToHistory(self, from_jid, to_jid, message, _type='chat', timestamp=None, profile=None):
173 """Store a new message in history 179 """Store a new message in history
174 @param from_jid: full source JID 180 @param from_jid: full source JID
175 @param to_jid: full dest JID 181 @param to_jid: full dest JID
176 @param message: message 182 @param message: message
183 @param _type: message type (see RFC 6121 ยง5.2.2)
177 @param timestamp: timestamp in seconds since epoch, or None to use current time 184 @param timestamp: timestamp in seconds since epoch, or None to use current time
178 """ 185 """
179 assert(profile!=None) 186 assert(profile!=None)
180 d = self.dbpool.runQuery("INSERT INTO history(source, source_res, dest, dest_res, timestamp, message, profile_id) VALUES (?,?,?,?,?,?,?)", 187 d = self.dbpool.runQuery("INSERT INTO history(source, source_res, dest, dest_res, timestamp, message, type, profile_id) VALUES (?,?,?,?,?,?,?,?)",
181 (from_jid.userhost(), from_jid.resource, to_jid.userhost(), to_jid.resource, timestamp or time.time(), 188 (from_jid.userhost(), from_jid.resource, to_jid.userhost(), to_jid.resource, timestamp or time.time(),
182 message, self.profiles[profile])) 189 message, _type, self.profiles[profile]))
183 d.addErrback(lambda ignore: error(_("Can't save following message in history: from [%(from_jid)s] to [%(to_jid)s] ==> [%(message)s]" % 190 d.addErrback(lambda ignore: error(_("Can't save following message in history: from [%(from_jid)s] to [%(to_jid)s] ==> [%(message)s]" %
184 {"from_jid":from_jid.full(), "to_jid":to_jid.full(), "message":message}))) 191 {"from_jid":from_jid.full(), "to_jid":to_jid.full(), "message":message})))
185 return d 192 return d
186 193
187 def getHistory(self, from_jid, to_jid, limit=0, between=True): 194 def getHistory(self, from_jid, to_jid, limit=0, between=True):
192 """ 199 """
193 def sqliteToDict(query_result): 200 def sqliteToDict(query_result):
194 query_result.reverse() 201 query_result.reverse()
195 result = [] 202 result = []
196 for row in query_result: 203 for row in query_result:
197 timestamp, source, source_res, dest, dest_res, message = row 204 timestamp, source, source_res, dest, dest_res, message, _type= row
198 result.append((timestamp, "%s/%s" % (source, source_res) if source_res else source, 205 result.append((timestamp, "%s/%s" % (source, source_res) if source_res else source,
199 "%s/%s" % (dest, dest_res) if dest_res else dest, 206 "%s/%s" % (dest, dest_res) if dest_res else dest,
200 message)) 207 message, _type))
201 return result 208 return result
209
210
211 query_parts = ["SELECT timestamp, source, source_res, dest, dest_res, message, type FROM history WHERE"]
212 values = []
213
214 def test_jid(_type,_jid):
215 values.append(_jid.userhost())
216 if _jid.resource:
217 values.append(_jid.resource)
218 return '(%s=? AND %s_res=?)' % (_type, _type)
219 return '%s=?' % (_type,)
202 220
203 query_parts = ["SELECT timestamp, source, source_res, dest, dest_res, message FROM history WHERE"]
204 values = []
205
206 if between: 221 if between:
207 query_parts.append("(source=? OR source=?) AND (dest=? or dest=?)") 222 query_parts.append("(%s OR %s) AND (%s or %s)" % (test_jid('source', from_jid),
208 values.extend([from_jid.userhost(), to_jid.userhost(), to_jid.userhost(), from_jid.userhost()]) 223 test_jid('source', to_jid),
224 test_jid('dest', to_jid),
225 test_jid('dest', from_jid)))
209 else: 226 else:
210 query_parts.append("source=? AND dest=?") 227 query_parts.append("%s AND %s") % (test_jid('source', from_jid),
211 values.extend([from_jid.userhost(), to_jid.userhost()]) 228 test_jid('dest', to_jid))
212 if from_jid.resource:
213 query_parts.append("AND source_res=?")
214 values.append(from_jid.resource)
215 if to_jid.resource:
216 query_parts.append("AND dest_res=?")
217 values.append(to_jid.resource)
218 229
219 query_parts.append("ORDER BY timestamp DESC") 230 query_parts.append("ORDER BY timestamp DESC")
220 231
221 if limit: 232 if limit:
222 query_parts.append("LIMIT ?") 233 query_parts.append("LIMIT ?")
223 values.append(limit) 234 values.append(limit)
235
224 d = self.dbpool.runQuery(" ".join(query_parts), values) 236 d = self.dbpool.runQuery(" ".join(query_parts), values)
225 return d.addCallback(sqliteToDict) 237 return d.addCallback(sqliteToDict)
226 238
227 #Private values 239 #Private values
228 def loadGenPrivates(self, private_gen, namespace): 240 def loadGenPrivates(self, private_gen, namespace):