You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
3.1 KiB

#!/usr/bin/env python
import sys
import json
import datetime
import os
import os.path
import functools
import contextlib
import asyncio
import concurrent
import logging
import selectors
from mattermostdriver import Driver, Websocket # pip install mattermostdriver
import config
logging.basicConfig(level='INFO')
class MatterLog:
__slots__ = ['driver', 'logdir']
def __init__(self, driver, loop, logdir):
self.driver = driver
self.logdir = logdir
@contextlib.contextmanager
def channel_file(self, team, channel):
current = os.path.join(self.logdir, team, channel, 'current')
os.makedirs(os.path.dirname(current), exist_ok=True)
with open(current, 'a') as f:
yield f
async def __call__(self, event):
event = json.loads(event)
if 'event' not in event:
logging.warning('received none-event: ' + str(event))
elif event['event'] in MatterLog.IGNORED_EVENTS:
pass
elif not hasattr(self, 'handle_' + event['event']):
logging.warning('no handler for event: ' + str(event))
else:
await getattr(self, 'handle_' + event['event'])(event['data'])
IGNORED_EVENTS = { 'emoji_added', 'hello', 'license_changed',
'preference_changed', 'preferences_changed', 'preferences_deleted',
'typing' }
async def handle_posted(self, data):
post = json.loads(data['post'])
with self.channel_file(self.cached_team_name(data['team_id']), data['channel_name']) as f:
if post.get('root_id'):
print(post['create_at'], post['id'], 'REPLY', post['original_id'], data['sender_name'][1:], post['message'], sep='\t', file=f)
else:
print(post['create_at'], post['id'], 'MSG', data['sender_name'][1:], post['message'], sep='\t', file=f)
@functools.lru_cache
def cached_team_name(self, team):
return self.driver.teams.get_team(team)['name']
async def messageloop(driver, loop, logdir):
selector = selectors.DefaultSelector()
for team in driver.teams.get_teams():
for channel in driver.channels.get_channels_for_user(driver.client.userid, team['id']):
sayfile = os.path.join(logdir, team['name'], channel['name'], 'say')
if os.path.exists(sayfile): os.unlink(sayfile)
os.makedirs(os.path.dirname(sayfile), exist_ok=True)
os.mkfifo(sayfile)
f = os.open(sayfile, os.O_RDONLY | os.O_NONBLOCK)
selector.register(f, selectors.EVENT_READ, (sayfile, channel['id']))
while True:
events = await loop.run_in_executor(None, lambda: selector.select())
for key, mask in events:
selector.unregister(key.fileobj)
message = os.read(key.fileobj, 1024)
os.close(key.fileobj)
if message:
driver.posts.create_post(options={
'channel_id': key.data[1],
'message': message.decode()
})
f = os.open(key.data[0], os.O_RDONLY | os.O_NONBLOCK)
selector.register(f, selectors.EVENT_READ, key.data)
if __name__ == '__main__':
driver = Driver(config.driver)
driver.login()
def listen(driver):
websocket = Websocket(driver.options, driver.client.token)
loop = asyncio.get_event_loop()
loop.set_debug(True)
loop.create_task(messageloop(driver, loop, config.logdir))
loop.run_until_complete(websocket.connect(MatterLog(driver, loop, config.logdir)))