import logging import argparse from sleekxmpp import ClientXMPP from sleekxmpp.exceptions import IqError, IqTimeout import os, urlparse import urllib import datetime import ssl import base64 import cStringIO from PIL import Image parser = argparse.ArgumentParser() parser.add_argument("-j", "--jid", help="jabber identifier", type=str, required=True) parser.add_argument("-p", "--password", help="password", type=str, required=True) parser.add_argument("-m", "--muc", help="destination muc", type=str, required=True) parser.add_argument("-n", "--nick", help="nickname of the bot", default="archivist", type=str) args = parser.parse_args() class ArchivistBot(ClientXMPP): def __init__(self, jid, password, room, nick): ClientXMPP.__init__(self, jid, password) self.dbfile = 'archive.db' self.datadir = 'files' self.room = room self.nick = nick self.add_event_handler("session_start", self.session_start) self.add_event_handler("message", self.archive_msg) # by using 'message' instead of 'groupchat_message' every message received can be archived (also personal msgs) # self.add_event_handler("groupchat_message", self.archive_msg2) self.register_plugin('xep_0045') self.register_plugin('xep_0030') self.register_plugin('xep_0084') self.register_plugin('xep_0096') # Transfer files.. self.register_plugin('xep_0066') # Transfer files.. def session_start(self, event): self.get_roster() self.send_presence() self.plugin['xep_0045'].joinMUC(self.room, self.nick) # XEP-0084 User Avatar # Requires SleekXMPP 81b7b2c1908e0f6a5435ce67745b5f4dafb59816 with open('mary-ritter-beard-writers-photo-u1.jpeg', 'rb') as avatar_file: avatar = avatar_file.read() avatar_id = self['xep_0084'].generate_id(avatar) info = { 'id': avatar_id, 'type': 'image/jpeg', 'bytes': len(avatar) } self['xep_0084'].publish_avatar(avatar) self['xep_0084'].publish_avatar_metadata(items=[info]) # XEP-0153: vCard-Based Avatars # Not working ATM #self['xep_0153'].set_avatar(avatar=avatar, mtype='image/png') def archive_msg(self, msg): # Always check that a message is not from yourself, otherwise you will create an infinite loop responding to your own messages. if 'mucnick' in msg and msg['mucnick'] == self.nick: return # in case of a whisper, nick becomes archive@muc.complex.local/ccl nick = msg['mucnick'] if len(msg['mucnick']) else msg['from'] nowDate = datetime.datetime.now().strftime("%Y-%m-%d") targetHtmlFile = os.path.join(self.datadir, nowDate+".html") if not os.path.exists(targetHtmlFile): with open(targetHtmlFile, "wb") as f: f.write("Archive of %s at %s" % (nowDate, self.room)) now = datetime.datetime.now().isoformat() content = "
%s%s" % (now, nick) if msg['oob']['url']: logging.getLogger().debug("received OOB from %s with %s" % (nick, msg['oob']['url'])) filename, ext = os.path.splitext(urlparse.urlparse(msg['oob']['url']).path) targetDir = os.path.join(self.datadir, nowDate) if not os.path.exists(targetDir): os.mkdir( targetDir, 0755 ) filename = now +"_" + nick + ext targetFile = os.path.join(targetDir, filename) targetThumbFile = os.path.join(targetDir, "thumb_"+filename) targetUrl = os.path.join(nowDate, filename) targetThumbUrl = os.path.join(nowDate, "thumb_"+filename) #needed to disable certificate validation: ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE urllib.urlretrieve(msg['oob']['url'], targetFile, context=ctx) logging.getLogger().debug("saved to %s" % targetFile) size = (150,150) img = Image.open(targetFile) img.thumbnail(size) buffer = cStringIO.StringIO() img.save(buffer, format="JPEG") img_str = base64.b64encode(buffer.getvalue()) content += "" % (targetUrl, img_str) else: logging.getLogger().debug("received text from %s: %s" % (nick, msg['body']) ) content += "%s" % (msg['body']) content += "
" with open(targetHtmlFile, "a") as f: f.write(content) # if msg['type'] in ('chat', 'normal'): # msg.reply("Thanks for sending\n%(body)s" % msg).send() def parseHtml(): return if __name__ == '__main__': # Ideally use optparse or argparse to get JID, # password, and log level. logging.basicConfig(level=logging.DEBUG, format='%(levelname)-8s %(message)s') client = ArchivistBot(args.jid, args.password, args.muc, args.nick) if client.connect(): client.process(block=True) else: logging.getLogger().error("Can't connect.")