first commit!
This commit is contained in:
commit
9996d8665d
7
README.md
Normal file
7
README.md
Normal 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
141
archivist.py
Normal 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
BIN
contact.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
BIN
files/SpYFTy_nQyyxcNkUKniWdw.jpg
Normal file
BIN
files/SpYFTy_nQyyxcNkUKniWdw.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 106 KiB |
BIN
files/jyTSOwDEQCaqKHnDdHeNow.jpg
Normal file
BIN
files/jyTSOwDEQCaqKHnDdHeNow.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 299 KiB |
103
streambot.py
Normal file
103
streambot.py
Normal 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.")
|
Loading…
Reference in New Issue
Block a user