first commit!

This commit is contained in:
mb@mb 2018-03-06 19:39:30 +01:00
commit 9996d8665d
6 changed files with 251 additions and 0 deletions

7
README.md Normal file
View File

@ -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. :)

141
archivist.py Normal file
View File

@ -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.")

BIN
contact.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

103
streambot.py Normal file
View File

@ -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.")