diff --git a/src/common/migrate_logs_to_dot9_db.py b/src/common/migrate_logs_to_dot9_db.py new file mode 100755 index 000000000..fb706747d --- /dev/null +++ b/src/common/migrate_logs_to_dot9_db.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python +import os +import sre +import sys +import time +import signal + +signal.signal(signal.SIGINT, signal.SIG_DFL) # ^C exits the application + +from pysqlite2 import dbapi2 as sqlite + + +class Constants: + def __init__(self): + ( + self.JID_NORMAL_TYPE, + self.JID_ROOM_TYPE # image to show state (online, new message etc) + ) = range(2) + + ( + self.KIND_STATUS, + self.KIND_GCSTATUS, + self.KIND_GC_MSG, + self.KIND_SINGLE_MSG_RECV, + self.KIND_CHAT_MSG_RECV, + self.KIND_SINGLE_MSG_SENT, + self.KIND_CHAT_MSG_SENT + ) = range(7) + + ( + self.SHOW_ONLINE, + self.SHOW_CHAT, + self.SHOW_AWAY, + self.SHOW_XA, + self.SHOW_DND, + self.SHOW_OFFLINE + ) = range(6) + +constants = Constants() + +if os.name == 'nt': + try: + PATH_TO_LOGS_BASE_DIR = os.path.join(os.environ['appdata'], 'Gajim', 'Logs') + PATH_TO_DB = os.path.join(os.environ['appdata'], 'Gajim', 'logs.db') # database is called logs.db + except KeyError: + # win9x + PATH_TO_LOGS_BASE_DIR = '../src/Logs' + PATH_TO_DB = '../src/logs.db' +else: + PATH_TO_LOGS_BASE_DIR = os.path.expanduser('~/.gajim/logs') + PATH_TO_DB = os.path.expanduser('~/.gajim/logs2.db') # database is called logs.db + +if os.path.exists(PATH_TO_DB): + print '%s already exists. Exiting..' % PATH_TO_DB + sys.exit() + +jids_already_in = [] # jid we already put in DB +con = sqlite.connect(PATH_TO_DB) +os.chmod(PATH_TO_DB, 0600) # rw only for us +cur = con.cursor() +# create the tables +# 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 +# to meet all our needs +# logs.jid_id --> jids.jid_id but Sqlite doesn't do FK etc so it's done in python code +cur.executescript( + ''' + CREATE TABLE jids( + jid_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, + jid TEXT UNIQUE, + type INTEGER + ); + + CREATE TABLE logs( + log_line_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, + jid_id INTEGER, + contact_name TEXT, + time INTEGER, + kind INTEGER, + show INTEGER, + message TEXT, + subject TEXT + ); + ''' + ) + +con.commit() + +# (? 2: + # type in logs is one of + # 'gc', 'gcstatus', 'recv', 'sent' and if nothing of those + # it is status + # new db has: + # status, gcstatus, gc_msg, (we only recv those 3), + # single_msg_recv, chat_msg_recv, chat_msg_sent, single_msg_sent + # to meet all our needs + # here I convert + # gc ==> gc_msg, gcstatus ==> gcstatus, recv ==> chat_msg_recv + # sent ==> chat_msg_sent, status ==> status + typ = splitted_line[1] # line[1] has type of logged message + message_data = splitted_line[2:] # line[2:] has message data + # line[0] is date, + # some lines can be fucked up, just drop them + try: + tim = int(float(splitted_line[0])) + except: + continue + + contact_name = None + show = None + if typ == 'gc': + contact_name = message_data[0] + message = ':'.join(message_data[1:]) + kind = constants.KIND_GC_MSG + elif typ == 'gcstatus': + contact_name = message_data[0] + show = message_data[1] + message = ':'.join(message_data[2:]) # status msg + kind = constants.KIND_GCSTATUS + elif typ == 'recv': + message = ':'.join(message_data[0:]) + kind = constants.KIND_CHAT_MSG_RECV + elif typ == 'sent': + message = ':'.join(message_data[0:]) + kind = constants.KIND_CHAT_MSG_SENT + else: # status + kind = constants.KIND_STATUS + show = message_data[0] + message = ':'.join(message_data[1:]) # status msg + +# message = decode_string(message) + message = message[:-1] # remove last \n + if not message: + continue + + # jid is already in the DB, don't create a new row, just get his jid_id + if not JID_ID: + if jid in jids_already_in: + cur.execute('SELECT jid_id FROM jids WHERE jid = "%s"' % jid) + JID_ID = cur.fetchone()[0] + else: + jids_already_in.append(jid) + cur.execute('INSERT INTO jids (jid, type) VALUES (?, ?)', + (jid, jid_type)) + con.commit() + JID_ID = cur.lastrowid + + sql = 'INSERT INTO logs (jid_id, contact_name, time, kind, show, message) '\ + 'VALUES (?, ?, ?, ?, ?, ?)' + + values = (JID_ID, contact_name, tim, kind, show, message) + cur.execute(sql, values) + con.commit() + +def migrate(): + os.path.walk(PATH_TO_LOGS_BASE_DIR, visit, None) + f = open(os.path.join(PATH_TO_LOGS_BASE_DIR, 'README'), 'w') + f.write('We do not use plain-text files anymore, because they do not scale.\n') + f.write('Those files here are logs for Gajim up until 0.8.2\n') + f.write('We now use an sqlite database called logs.db found in ~/.gajim\n') + f.write('You can always run the migration script to import your old logs to the database\n') + f.write('Thank you\n') + f.close() + +if __name__ == '__main__': + print 'IMPORTNANT: PLEASE READ http://trac.gajim.org/wiki/MigrateLogToDot9DB' + print 'Migration will start in 40 seconds unless you press Ctrl+C' + time.sleep(40) # give the user time to act + print + print 'Starting Logs Migration' + print '=======================' + print 'Please do NOT run Gajim until this script is over' + migrate() diff --git a/src/gajim.py b/src/gajim.py index 086230326..fce072226 100755 --- a/src/gajim.py +++ b/src/gajim.py @@ -71,6 +71,11 @@ if pritext: dlg.destroy() sys.exit() +from common import logger +LOG_DB_PATH = logger.LOG_DB_PATH +NO_DB = False +if not os.path.isfile(LOG_DB_PATH): + NO_DB = True check_paths.check_and_possibly_create_paths() path = os.getcwd() @@ -1456,5 +1461,14 @@ if __name__ == '__main__': except: pass + # Migrate old logs if user wnats that + NO_DB = True + if NO_DB: + dialog = dialogs.ConfirmationDialog(_('It is the first time you rin Gajim since the way logs are save changed. You can ask Gajim to migrate your old logs by pressing Ok button. This can take some minutes.'), _('Do you want to migrate your logs?')) + if dialog.get_response() == gtk.RESPONSE_OK: + from common import migrate_logs_to_dot9_db + migrate_logs_to_dot9_db.migrate() + del NO_DB + Interface() gtk.main()