123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- #!/usr/bin/env python3
- # -*- coding: UTF-8 -*-
- import sqlite3
- import os
- from datetime import datetime
- import time
- from collections import namedtuple
- SOURCE_ID = {'wechat': 0}
- NUM_FIELDS = 8
- ChatMsgBase = namedtuple('ChatMsgBase',
- ['source', 'time', 'sender', 'chatroom',
- 'text', 'image', 'sound', 'extra_data'])
- """ source: unicode,
- time: datetime,
- sender: unicode,
- chatroom: unicode,
- text: unicode,
- image: string,
- sound: string,
- extra_data: string
- """
- class ChatMsg(ChatMsgBase):
- def __repr__(self): # repr must return str?
- return "Msg@{}/{}-{}/{}/{}/{}/{}".format(
- self.time, self.sender.encode('utf-8'),
- self.chatroom.encode('utf-8'),
- self.text.encode('utf-8'), 'IMG' if self.image else '',
- 'AUD' if self.sound else '', self.extra_data)
- class SqliteLibChat(object):
- """ Interface for interacting with LibChat database"""
- def __init__(self, db_file):
- self.db_file = db_file
- exist = os.path.isfile(db_file)
- self.conn = sqlite3.connect(db_file)
- self.conn.text_factory = str # to allow use of raw-byte string
- self.c = self.conn.cursor()
- if not exist:
- self.create()
- def create(self):
- self.c.execute("""
- CREATE TABLE message (
- source SMALLINT,
- time TEXT,
- sender TEXT,
- chatroom TEXT,
- text TEXT,
- image COLLATE BINARY,
- sound COLLATE BINARY,
- extra_data COLLATE BINARY
- )
- """)
- self.conn.commit()
- def _add_msg(self, tp):
- assert isinstance(tp, ChatMsg)
- self.c.execute(
- """INSERT INTO message VALUES ({0})""".format(
- ','.join(['?']*NUM_FIELDS)), tp)
- def add_msgs(self, msgs):
- """ each message is a ChatMsg instance"""
- self.c = self.conn.cursor()
- for m in msgs:
- self._add_msg(SqliteLibChat.prefilter(m))
- self.conn.commit()
- @staticmethod
- def prefilter(msg):
- source = msg.source
- if isinstance(source, basestring):
- source = SOURCE_ID[source]
- tm = int(time.mktime(msg[1].timetuple()))
- return ChatMsg(source, tm, *msg[2:])
- @staticmethod
- def postfilter(msg):
- # source
- text = msg[4].decode('utf-8')
- time = datetime.fromtimestamp(int(msg[1]))
- return ChatMsg(msg[0], time, msg[2], msg[3],
- text=text, image=msg[5],
- sound=msg[6], extra_data=msg[7])
- def iterate_all_msg(self, predicate=None):
- """ predicate: a dict used as SELECT filter
- return a generator for all messages
- """
- if predicate is None:
- self.c.execute("SELECT * FROM message")
- else:
- self.c.execute("SELECT * FROM message WHERE {}".format(
- ' AND '.join(["{} = {}".format(k, v)
- for k, v in predicate.items()])))
- for row in self.c.fetchall():
- yield ChatMsg(*SqliteLibChat.postfilter(row))
- if __name__ == '__main__':
- db = SqliteLibChat(os.path.join(
- os.path.dirname(__file__), './message.db'))
- #msg = ChatMsg(-1, 1000, 'me', 'room', 'hello', '\x01\x02\x03', '', '')
- #db.add_msgs([msg])
- for k in db.iterate_all_msg():
- from IPython import embed; embed()
- print(k)
|