mb@mb
7 years ago
commit
9996d8665d
6 changed files with 251 additions and 0 deletions
@ -0,0 +1,7 @@ |
|||
This is the home of Varia's xmpp.streambot! |
|||
|
|||
When the streambot is listening ... it saves all images that are sent to the muc members@vvvvvvaria.org and streams them to [vvvvvvaria.org/stream/](https://vvvvvvaria.org/stream/). |
|||
|
|||
*archivist.py* was written by Ruben van der Ven during Relearn 2017. |
|||
|
|||
*streambot.py* is based on *archivist.py*, it is a custom Varia bot, that will communicate one day with our Pelican plugins-custom/stream plugin. :) |
@ -0,0 +1,141 @@ |
|||
import logging |
|||
|
|||
import argparse |
|||
from sleekxmpp import ClientXMPP |
|||
from sleekxmpp.exceptions import IqError, IqTimeout |
|||
import os |
|||
import urlparse |
|||
import urllib |
|||
import datetime |
|||
import ssl |
|||
import base64 |
|||
from PIL import Image |
|||
import cStringIO |
|||
|
|||
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('contact.png', '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("<html><head><title>Archive of %s at %s</title><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"></head><body>" % (nowDate, self.room)) |
|||
|
|||
now = datetime.datetime.now().isoformat() |
|||
content = "<div class='msg'><span class='time'>%s</span><span class='nick'>%s</span>" % (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 += "<a href='%s'><img src='data:image/jpg;base64,%s'></a>" % (targetUrl, img_str) |
|||
else: |
|||
logging.getLogger().debug("received text from %s: %s" % (nick, msg['body']) ) |
|||
content += "<span class='text'>%s</span>" % (msg['body']) |
|||
|
|||
content += "</div>" |
|||
|
|||
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.") |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 106 KiB |
After Width: | Height: | Size: 299 KiB |
@ -0,0 +1,103 @@ |
|||
import logging |
|||
|
|||
import argparse |
|||
from sleekxmpp import ClientXMPP |
|||
from sleekxmpp.exceptions import IqError, IqTimeout |
|||
import os |
|||
import urllib |
|||
import datetime |
|||
import ssl |
|||
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.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('contact.png', '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 |
|||
|
|||
if msg['oob']['url']: |
|||
logging.getLogger().debug("received OOB from %s with %s" % (nick, msg['oob']['url'])) |
|||
|
|||
filename = os.path.basename(msg['oob']['url']) |
|||
targetDir = self.datadir |
|||
if not os.path.exists(targetDir): |
|||
os.mkdir( targetDir, 0755 ) |
|||
|
|||
targetFile = os.path.join(targetDir, filename) |
|||
|
|||
#needed to disable certificate validation: |
|||
ctx = ssl.create_default_context() |
|||
ctx.check_hostname = False |
|||
ctx.verify_mode = ssl.CERT_NONE |
|||
|
|||
# save image to file |
|||
urllib.urlretrieve(msg['oob']['url'], targetFile, context=ctx) |
|||
logging.getLogger().debug("saved to %s" % targetFile) |
|||
|
|||
# if msg['type'] in ('chat', 'normal'): |
|||
# msg.reply("Thanks for sending\n%(body)s" % msg).send() |
|||
|
|||
|
|||
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.") |
Loading…
Reference in new issue