Add support for private message #1 #70
3 changed files with 346 additions and 116 deletions
397
appservice.py
397
appservice.py
|
@ -8,7 +8,7 @@ import time
|
||||||
|
|
||||||
from matrix_client.api import MatrixHttpApi
|
from matrix_client.api import MatrixHttpApi
|
||||||
from matrix_client.api import MatrixError, MatrixRequestError
|
from matrix_client.api import MatrixError, MatrixRequestError
|
||||||
from models import Avatars, Rooms, Events, Users, DirectRooms
|
from models import Avatars, Rooms, Events, Users, DirectRooms, ControlRooms
|
||||||
from database import db_session
|
from database import db_session
|
||||||
from sqlalchemy import and_
|
from sqlalchemy import and_
|
||||||
from flask import Flask, jsonify, request, abort
|
from flask import Flask, jsonify, request, abort
|
||||||
|
@ -77,6 +77,9 @@ def query_alias(alias):
|
||||||
db_session.add(rr)
|
db_session.add(rr)
|
||||||
db_session.commit()
|
db_session.commit()
|
||||||
|
|
||||||
|
except pnutpy.errors.PnutPermissionDenied:
|
||||||
|
abort(401)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("-couldn't get the pnut channel-")
|
logger.exception("-couldn't get the pnut channel-")
|
||||||
abort(404)
|
abort(404)
|
||||||
|
@ -85,7 +88,7 @@ def query_alias(alias):
|
||||||
|
|
||||||
@app.route("/transactions/<transaction>", methods=["PUT"])
|
@app.route("/transactions/<transaction>", methods=["PUT"])
|
||||||
def on_receive_events(transaction):
|
def on_receive_events(transaction):
|
||||||
|
|
||||||
access_token = request.args.get('access_token', '')
|
access_token = request.args.get('access_token', '')
|
||||||
if access_token != app.config['MATRIX_HS_TOKEN']:
|
if access_token != app.config['MATRIX_HS_TOKEN']:
|
||||||
abort(403)
|
abort(403)
|
||||||
|
@ -94,7 +97,6 @@ def on_receive_events(transaction):
|
||||||
for event in events:
|
for event in events:
|
||||||
logger.debug(event)
|
logger.debug(event)
|
||||||
|
|
||||||
# TODO: route event if it's in the control room
|
|
||||||
if app.config['MATRIX_ADMIN_ROOM'] and app.config['MATRIX_ADMIN_ROOM'] == event['room_id']:
|
if app.config['MATRIX_ADMIN_ROOM'] and app.config['MATRIX_ADMIN_ROOM'] == event['room_id']:
|
||||||
return on_admin_event(event)
|
return on_admin_event(event)
|
||||||
|
|
||||||
|
@ -109,8 +111,8 @@ def on_receive_events(transaction):
|
||||||
elif event['type'] == 'm.room.member':
|
elif event['type'] == 'm.room.member':
|
||||||
if 'is_direct' in event['content'] and 'membership' in event['content']:
|
if 'is_direct' in event['content'] and 'membership' in event['content']:
|
||||||
if event['content']['membership'] == "invite" and event['content']['is_direct']:
|
if event['content']['membership'] == "invite" and event['content']['is_direct']:
|
||||||
return on_admin_invite(event)
|
return on_direct_invite(event)
|
||||||
|
|
||||||
if 'membership' in event['content']:
|
if 'membership' in event['content']:
|
||||||
if event['content']['membership'] == "leave":
|
if event['content']['membership'] == "leave":
|
||||||
return on_leave_event(event)
|
return on_leave_event(event)
|
||||||
|
@ -122,81 +124,44 @@ def on_receive_events(transaction):
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
def new_message(event, user):
|
def new_message(event, user):
|
||||||
|
|
||||||
if app.config['MATRIX_PNUT_PREFIX'] in event['user_id'] or 'pnut-bridge' in event['user_id']:
|
if app.config['MATRIX_PNUT_PREFIX'] in event['user_id'] or 'pnut-bridge' in event['user_id']:
|
||||||
logger.debug('-skipping dup event-')
|
logger.debug('-skipping dup event-')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if 'msgtype' not in event['content']:
|
||||||
|
logger.debug('-unknown message type-')
|
||||||
|
return
|
||||||
|
|
||||||
|
control = ControlRooms.query.filter(ControlRooms.room_id == event['room_id']).one_or_none()
|
||||||
|
if control is not None:
|
||||||
|
return on_control_message(event)
|
||||||
|
|
||||||
direct = DirectRooms.query.filter(DirectRooms.room_id == event['room_id']).one_or_none()
|
direct = DirectRooms.query.filter(DirectRooms.room_id == event['room_id']).one_or_none()
|
||||||
if direct is not None:
|
if direct is not None:
|
||||||
return on_direct_message(event)
|
return on_direct_message(event, user, direct)
|
||||||
|
|
||||||
room = Rooms.query.filter(Rooms.room_id == event['room_id']).one_or_none()
|
room = Rooms.query.filter(Rooms.room_id == event['room_id']).one_or_none()
|
||||||
if room is None:
|
if room is None:
|
||||||
logger.debug('-room not mapped-')
|
logger.debug('-room not mapped-')
|
||||||
return
|
return
|
||||||
|
|
||||||
if 'msgtype' not in event['content']:
|
|
||||||
logger.debug('-unknown message type-')
|
|
||||||
return
|
|
||||||
|
|
||||||
cross_profile = {'username': event['user_id']}
|
|
||||||
matrix_profile = get_profile(event['user_id'])
|
|
||||||
if "avatar_url" in matrix_profile:
|
|
||||||
cross_profile['avatar_image'] = app.config['MATRIX_URL'] + '/_matrix/media/r0/download/' + matrix_profile['avatar_url'][6:]
|
|
||||||
|
|
||||||
if user is not None:
|
if user is not None:
|
||||||
token = user.pnut_user_token
|
token = user.pnut_user_token
|
||||||
prefix = ""
|
prefix = ""
|
||||||
else:
|
else:
|
||||||
token = app.config['MATRIX_PNUT_TOKEN']
|
token = app.config['MATRIX_PNUT_TOKEN']
|
||||||
|
matrix_profile = get_profile(event['user_id'])
|
||||||
if "displayname" in matrix_profile:
|
if "displayname" in matrix_profile:
|
||||||
prefix = "[" + matrix_profile['displayname'] + "] (" + event['user_id'] + ")\n"
|
prefix = "[" + matrix_profile['displayname'] + "] (" + event['user_id'] + ")\n"
|
||||||
else:
|
else:
|
||||||
prefix = "(" + event['user_id'] + ")\n"
|
prefix = "(" + event['user_id'] + ")\n"
|
||||||
|
|
||||||
pnutpy.api.add_authorization_token(token)
|
pnutpy.api.add_authorization_token(token)
|
||||||
text = None
|
|
||||||
embed = [{
|
|
||||||
'type': "io.pnut.core.crosspost",
|
|
||||||
'value': {
|
|
||||||
'canonical_url': "https://matrix.to/#/" + event['room_id'] + "/" + event['event_id'] + ":" + app.config['MATRIX_DOMAIN'],
|
|
||||||
'source': {
|
|
||||||
'name': "matrix",
|
|
||||||
'url': "https://matrix.org"
|
|
||||||
},
|
|
||||||
'user': cross_profile
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
|
|
||||||
if event['content']['msgtype'] == 'm.text' or event['content']['msgtype'] == 'm.notice':
|
embed = [crosspost_raw(event)]
|
||||||
text = event['content']['body']
|
evtext, evraw = msg_from_event(event)
|
||||||
|
text = prefix + evtext
|
||||||
elif event['content']['msgtype'] == 'm.emote':
|
if len(evraw) > 0:
|
||||||
text = "* " + event['content']['body']
|
embed.append(evraw)
|
||||||
|
|
||||||
elif event['content']['msgtype'] == 'm.image':
|
|
||||||
text = event['content']['body'] + "\n"
|
|
||||||
text += app.config['MATRIX_URL'] + '/_matrix/media/r0/download/' + event['content']['url'][6:]
|
|
||||||
embed.append(raw_from_event(event))
|
|
||||||
|
|
||||||
elif event['content']['msgtype'] == 'm.video':
|
|
||||||
text = event['content']['body'] + "\n"
|
|
||||||
text += app.config['MATRIX_URL'] + '/_matrix/media/r0/download/' + event['content']['url'][6:]
|
|
||||||
|
|
||||||
elif event['content']['msgtype'] == 'm.audio':
|
|
||||||
text = event['content']['body'] + "\n"
|
|
||||||
text += app.config['MATRIX_URL'] + '/_matrix/media/r0/download/' + event['content']['url'][6:]
|
|
||||||
|
|
||||||
elif event['content']['msgtype'] == 'm.file':
|
|
||||||
text = event['content']['body'] + "\n"
|
|
||||||
text += app.config['MATRIX_URL'] + '/_matrix/media/r0/download/' + event['content']['url'][6:]
|
|
||||||
|
|
||||||
else:
|
|
||||||
logger.debug('-unknown msg type- ' + event['content']['msgtype'])
|
|
||||||
return
|
|
||||||
|
|
||||||
text = prefix + text
|
|
||||||
try:
|
try:
|
||||||
msg, meta = pnutpy.api.create_message(room.pnut_chan, data={'text': text, 'raw': embed})
|
msg, meta = pnutpy.api.create_message(room.pnut_chan, data={'text': text, 'raw': embed})
|
||||||
revent = Events(
|
revent = Events(
|
||||||
|
@ -235,13 +200,63 @@ def new_message(event, user):
|
||||||
except pnutpy.errors.PnutAuthAPIException:
|
except pnutpy.errors.PnutAuthAPIException:
|
||||||
logger.exception('-unable to post to pnut channel-')
|
logger.exception('-unable to post to pnut channel-')
|
||||||
return
|
return
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception('-something bad happened here-')
|
logger.exception('-something bad happened here-')
|
||||||
return
|
return
|
||||||
|
|
||||||
def raw_from_event(event):
|
def msg_from_event(event):
|
||||||
|
text = None
|
||||||
|
raw = {}
|
||||||
|
if event['content']['msgtype'] == 'm.text' or event['content']['msgtype'] == 'm.notice':
|
||||||
|
text = event['content']['body']
|
||||||
|
|
||||||
|
elif event['content']['msgtype'] == 'm.emote':
|
||||||
|
text = "* " + event['content']['body']
|
||||||
|
|
||||||
|
elif event['content']['msgtype'] == 'm.image':
|
||||||
|
text = event['content']['body'] + "\n"
|
||||||
|
text += app.config['MATRIX_URL'] + '/_matrix/media/r0/download/' + event['content']['url'][6:]
|
||||||
|
raw = raw_from_event(event)
|
||||||
|
|
||||||
|
elif event['content']['msgtype'] == 'm.video':
|
||||||
|
text = event['content']['body'] + "\n"
|
||||||
|
text += app.config['MATRIX_URL'] + '/_matrix/media/r0/download/' + event['content']['url'][6:]
|
||||||
|
|
||||||
|
elif event['content']['msgtype'] == 'm.audio':
|
||||||
|
text = event['content']['body'] + "\n"
|
||||||
|
text += app.config['MATRIX_URL'] + '/_matrix/media/r0/download/' + event['content']['url'][6:]
|
||||||
|
|
||||||
|
elif event['content']['msgtype'] == 'm.file':
|
||||||
|
text = event['content']['body'] + "\n"
|
||||||
|
text += app.config['MATRIX_URL'] + '/_matrix/media/r0/download/' + event['content']['url'][6:]
|
||||||
|
|
||||||
|
else:
|
||||||
|
logger.debug('-unknown msg type- ' + event['content']['msgtype'])
|
||||||
|
return
|
||||||
|
|
||||||
|
return text, raw
|
||||||
|
|
||||||
|
def crosspost_raw(event):
|
||||||
|
cross_profile = {'username': event['user_id']}
|
||||||
|
matrix_profile = get_profile(event['user_id'])
|
||||||
|
if "avatar_url" in matrix_profile:
|
||||||
|
cross_profile['avatar_image'] = app.config['MATRIX_URL'] + '/_matrix/media/r0/download/' + matrix_profile['avatar_url'][6:]
|
||||||
|
|
||||||
|
embed = {
|
||||||
|
'type': "io.pnut.core.crosspost",
|
||||||
|
'value': {
|
||||||
|
'canonical_url': "https://matrix.to/#/" + event['room_id'] + "/" + event['event_id'] + ":" + app.config['MATRIX_DOMAIN'],
|
||||||
|
'source': {
|
||||||
|
'name': "matrix",
|
||||||
|
'url': "https://matrix.org"
|
||||||
|
},
|
||||||
|
'user': cross_profile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return embed
|
||||||
|
|
||||||
|
def raw_from_event(event):
|
||||||
url = app.config['MATRIX_URL'] + '/_matrix/media/r0/download/' + event['content']['url'][6:]
|
url = app.config['MATRIX_URL'] + '/_matrix/media/r0/download/' + event['content']['url'][6:]
|
||||||
|
|
||||||
if event['content']['msgtype'] == 'm.image':
|
if event['content']['msgtype'] == 'm.image':
|
||||||
|
@ -335,6 +350,46 @@ def get_channel_settings(channel_id):
|
||||||
|
|
||||||
return channel_settings
|
return channel_settings
|
||||||
|
|
||||||
|
def create_room(channel, invite):
|
||||||
|
channel_settings = {}
|
||||||
|
for item in channel.raw:
|
||||||
|
if item.type == 'io.pnut.core.chat-settings':
|
||||||
|
channel_settings = item.value
|
||||||
|
|
||||||
|
# Matrix sdk doesn't include all details in a single call
|
||||||
|
room = {'room_alias_name': app.config['MATRIX_PNUT_PREFIX'] + channel.id}
|
||||||
|
logger.debug(invite)
|
||||||
|
logger.debug(room)
|
||||||
|
room['invite'] = [invite]
|
||||||
|
if 'name' in channel_settings:
|
||||||
|
room['name'] = channel_settings['name']
|
||||||
|
if 'description' in channel_settings:
|
||||||
|
room['topic'] = channel_settings['description']
|
||||||
|
if channel.acl.read.any_user:
|
||||||
|
room['preset'] = 'public_chat'
|
||||||
|
room['visibility'] = 'public'
|
||||||
|
else:
|
||||||
|
room['preset'] = 'private_chat'
|
||||||
|
room['visibility'] = 'private'
|
||||||
|
|
||||||
|
url = app.config['MATRIX_HOST'] + '/_matrix/client/api/v1/createRoom?access_token='
|
||||||
|
url += app.config['MATRIX_AS_TOKEN']
|
||||||
|
headers = {"Content-Type":"application/json"}
|
||||||
|
r = requests.post(url, headers=headers, data=json.dumps(room))
|
||||||
|
|
||||||
|
if r.status_code == 200:
|
||||||
|
#pnutpy.api.subscribe_channel(channel.id)
|
||||||
|
rdata = r.json()
|
||||||
|
rr = Rooms(
|
||||||
|
room_id=rdata['room_id'],
|
||||||
|
pnut_chan=channel.id,
|
||||||
|
portal=True
|
||||||
|
)
|
||||||
|
db_session.add(rr)
|
||||||
|
db_session.commit()
|
||||||
|
logger.debug(r.status_code)
|
||||||
|
logger.debug(r)
|
||||||
|
|
||||||
def on_admin_event(event):
|
def on_admin_event(event):
|
||||||
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
|
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
|
||||||
token=app.config['MATRIX_AS_TOKEN'])
|
token=app.config['MATRIX_AS_TOKEN'])
|
||||||
|
@ -345,26 +400,31 @@ def on_admin_event(event):
|
||||||
|
|
||||||
msg = event['content']['body'].split(' ')
|
msg = event['content']['body'].split(' ')
|
||||||
|
|
||||||
if msg[0] == 'help':
|
try:
|
||||||
if len(msg) > 1:
|
if msg[0] == 'help':
|
||||||
matrix_api.send_message(event['room_id'], cmd_admin_help(msg[1]))
|
if len(msg) > 1:
|
||||||
else:
|
matrix_api.send_message(event['room_id'], cmd_admin_help(msg[1]))
|
||||||
matrix_api.send_message(event['room_id'], cmd_admin_help())
|
else:
|
||||||
|
matrix_api.send_message(event['room_id'], cmd_admin_help())
|
||||||
|
|
||||||
elif msg[0] == 'list':
|
elif msg[0] == 'list':
|
||||||
matrix_api.send_message(event['room_id'], cmd_admin_list())
|
matrix_api.send_message(event['room_id'], cmd_admin_list())
|
||||||
|
|
||||||
elif msg[0] == 'unlink':
|
elif msg[0] == 'unlink':
|
||||||
if len(msg) > 1:
|
if len(msg) > 1:
|
||||||
matrix_api.send_message(event['room_id'], cmd_admin_unlink(msg[1]))
|
matrix_api.send_message(event['room_id'], cmd_admin_unlink(msg[1]))
|
||||||
else:
|
else:
|
||||||
matrix_api.send_message(event['room_id'], cmd_admin_help('unlink'))
|
matrix_api.send_message(event['room_id'], cmd_admin_help('unlink'))
|
||||||
|
|
||||||
elif msg[0] == 'link':
|
elif msg[0] == 'link':
|
||||||
if len(msg) > 2:
|
if len(msg) > 2:
|
||||||
matrix_api.send_message(event['room_id'], cmd_admin_link(msg[1], msg[2]))
|
matrix_api.send_message(event['room_id'], cmd_admin_link(msg[1], msg[2]))
|
||||||
else:
|
else:
|
||||||
matrix_api.send_message(event['room_id'], cmd_admin_help('link'))
|
matrix_api.send_message(event['room_id'], cmd_admin_help('link'))
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
errmsg = "- on_admin_event -"
|
||||||
|
logger.exception(errmsg)
|
||||||
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
@ -496,31 +556,111 @@ def cmd_admin_unlink(id):
|
||||||
logger.exception(errmsg)
|
logger.exception(errmsg)
|
||||||
return errmsg
|
return errmsg
|
||||||
|
|
||||||
def on_admin_invite(event):
|
def on_direct_invite(event):
|
||||||
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
|
if event['state_key'] == app.config['MATRIX_AS_ID']:
|
||||||
token=app.config['MATRIX_AS_TOKEN'])
|
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
|
||||||
|
token=app.config['MATRIX_AS_TOKEN'])
|
||||||
matrix_api.join_room(event['room_id'])
|
dm = ControlRooms(room_id=event['room_id'])
|
||||||
|
|
||||||
direct = DirectRooms(room_id=event['room_id'])
|
else:
|
||||||
db_session.add(direct)
|
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
|
||||||
db_session.commit()
|
identity=event['state_key'],
|
||||||
|
token=app.config['MATRIX_AS_TOKEN'])
|
||||||
|
bridge_user = event['state_key']
|
||||||
|
pnut_user = bridge_user.replace(app.config['MATRIX_PNUT_PREFIX'],'').split(':')[0]
|
||||||
|
|
||||||
|
user = Users.query.filter(Users.matrix_id == event['sender']).one_or_none()
|
||||||
|
if user is not None:
|
||||||
|
# TODO: need to handle if the user isn't registered
|
||||||
|
pnutpy.api.add_authorization_token(user.pnut_user_token)
|
||||||
|
channel, meta = pnutpy.api.existing_pm(ids=pnut_user)
|
||||||
|
|
||||||
|
dm = DirectRooms(room_id=event['room_id'],
|
||||||
|
bridge_user=bridge_user, pnut_chan=channel.id)
|
||||||
|
|
||||||
|
try:
|
||||||
|
matrix_api.join_room(event['room_id'])
|
||||||
|
|
||||||
|
db_session.add(dm)
|
||||||
|
db_session.commit()
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
errmsg = "- on_direct_invite -"
|
||||||
|
logger.exception(errmsg)
|
||||||
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
def on_leave_event(event):
|
def on_leave_event(event):
|
||||||
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
|
|
||||||
token=app.config['MATRIX_AS_TOKEN'])
|
|
||||||
|
|
||||||
direct = DirectRooms.query.filter(DirectRooms.room_id == event['room_id']).one_or_none()
|
direct = DirectRooms.query.filter(DirectRooms.room_id == event['room_id']).one_or_none()
|
||||||
if direct is not None:
|
if direct is not None:
|
||||||
db_session.delete(direct)
|
|
||||||
db_session.commit()
|
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
|
||||||
matrix_api.leave_room(event['room_id'])
|
identity=direct.bridge_user,
|
||||||
|
token=app.config['MATRIX_AS_TOKEN'])
|
||||||
|
try:
|
||||||
|
matrix_api.leave_room(event['room_id'])
|
||||||
|
db_session.delete(direct)
|
||||||
|
db_session.commit()
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
errmsg = "- on_leave_event -"
|
||||||
|
logger.exception(errmsg)
|
||||||
|
|
||||||
|
control = ControlRooms.query.filter(ControlRooms.room_id == event['room_id']).one_or_none()
|
||||||
|
if control is not None:
|
||||||
|
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
|
||||||
|
token=app.config['MATRIX_AS_TOKEN'])
|
||||||
|
try:
|
||||||
|
matrix_api.leave_room(event['room_id'])
|
||||||
|
db_session.delete(control)
|
||||||
|
db_session.commit()
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
errmsg = "- on_leave_event -"
|
||||||
|
logger.exception(errmsg)
|
||||||
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
def on_direct_message(event):
|
def on_direct_message(event, user, room):
|
||||||
|
if user is not None:
|
||||||
|
token = user.pnut_user_token
|
||||||
|
prefix = ""
|
||||||
|
else:
|
||||||
|
token = app.config['MATRIX_PNUT_TOKEN']
|
||||||
|
matrix_profile = get_profile(event['user_id'])
|
||||||
|
if "displayname" in matrix_profile:
|
||||||
|
prefix = "[" + matrix_profile['displayname'] + "] (" + event['user_id'] + ")\n"
|
||||||
|
else:
|
||||||
|
prefix = "(" + event['user_id'] + ")\n"
|
||||||
|
pnutpy.api.add_authorization_token(token)
|
||||||
|
|
||||||
|
embed = [crosspost_raw(event)]
|
||||||
|
evtext, evraw = msg_from_event(event)
|
||||||
|
text = prefix + evtext
|
||||||
|
if len(evraw) > 0:
|
||||||
|
embed.append(evraw)
|
||||||
|
try:
|
||||||
|
msg, meta = pnutpy.api.create_message(room.pnut_chan, data={'text': text, 'raw': embed})
|
||||||
|
revent = Events(
|
||||||
|
event_id=event['event_id'],
|
||||||
|
room_id=event['room_id'],
|
||||||
|
pnut_msg_id=msg.id,
|
||||||
|
pnut_user_id=msg.user.id,
|
||||||
|
pnut_chan_id=room.pnut_chan,
|
||||||
|
deleted=False
|
||||||
|
)
|
||||||
|
db_session.add(revent)
|
||||||
|
db_session.commit()
|
||||||
|
|
||||||
|
except pnutpy.errors.PnutAuthAPIException:
|
||||||
|
logger.exception('-unable to post to pnut channel-')
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
logger.exception('-something bad happened here-')
|
||||||
|
|
||||||
|
return jsonify({})
|
||||||
|
|
||||||
|
def on_control_message(event):
|
||||||
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
|
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
|
||||||
token=app.config['MATRIX_AS_TOKEN'])
|
token=app.config['MATRIX_AS_TOKEN'])
|
||||||
logger.debug("- direct room event received -")
|
logger.debug("- direct room event received -")
|
||||||
|
@ -530,26 +670,38 @@ def on_direct_message(event):
|
||||||
|
|
||||||
msg = event['content']['body'].split(' ')
|
msg = event['content']['body'].split(' ')
|
||||||
|
|
||||||
if msg[0] == '!help' or msg[0] == 'help':
|
try:
|
||||||
if len(msg) > 1:
|
if msg[0] == '!help' or msg[0] == 'help':
|
||||||
matrix_api.send_message(event['room_id'], cmd_user_help(msg[1]))
|
if len(msg) > 1:
|
||||||
else:
|
matrix_api.send_message(event['room_id'], cmd_user_help(msg[1]))
|
||||||
matrix_api.send_message(event['room_id'], cmd_user_help())
|
else:
|
||||||
|
matrix_api.send_message(event['room_id'], cmd_user_help())
|
||||||
|
|
||||||
elif msg[0] == '!auth':
|
elif msg[0] == '!auth':
|
||||||
matrix_api.send_message(event['room_id'], cmd_user_auth())
|
matrix_api.send_message(event['room_id'], cmd_user_auth())
|
||||||
|
|
||||||
elif msg[0] == '!save':
|
elif msg[0] == '!save':
|
||||||
if len(msg) > 1:
|
if len(msg) > 1:
|
||||||
matrix_api.send_message(event['room_id'], cmd_user_save(event['sender'], msg[1]))
|
matrix_api.send_message(event['room_id'], cmd_user_save(event['sender'], msg[1]))
|
||||||
else:
|
else:
|
||||||
matrix_api.send_message(event['room_id'], cmd_user_save())
|
matrix_api.send_message(event['room_id'], cmd_user_save())
|
||||||
|
|
||||||
elif msg[0] == '!drop':
|
elif msg[0] == '!drop':
|
||||||
matrix_api.send_message(event['room_id'], cmd_user_drop(event['sender']))
|
matrix_api.send_message(event['room_id'], cmd_user_drop(event['sender']))
|
||||||
|
|
||||||
elif msg[0] == '!status':
|
elif msg[0] == '!status':
|
||||||
matrix_api.send_message(event['room_id'], cmd_user_status(event['sender']))
|
matrix_api.send_message(event['room_id'], cmd_user_status(event['sender']))
|
||||||
|
|
||||||
|
elif msg[0] == '!join':
|
||||||
|
if len(msg) > 1:
|
||||||
|
matrix_api.send_message(event['room_id'], cmd_user_join(event['sender'], msg[1]))
|
||||||
|
else:
|
||||||
|
matrix_api.send_message(event['room_id'], cmd_user_join(event['sender']))
|
||||||
|
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
errmsg = "- on_direct_message -"
|
||||||
|
logger.exception(errmsg)
|
||||||
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
@ -560,6 +712,7 @@ def cmd_user_help(cmd=None):
|
||||||
reply += "!save <token>\t- Save your pnut.io auth token\n"
|
reply += "!save <token>\t- Save your pnut.io auth token\n"
|
||||||
reply += "!drop\t\t\t- Drop your pnut.io auth token\n"
|
reply += "!drop\t\t\t- Drop your pnut.io auth token\n"
|
||||||
reply += "!status\t\t\t- Status of your pnut.io auth token\n"
|
reply += "!status\t\t\t- Status of your pnut.io auth token\n"
|
||||||
|
reply += "!join <channel #>\t- Join a private channel on pnut.io\n"
|
||||||
|
|
||||||
return reply
|
return reply
|
||||||
|
|
||||||
|
@ -636,3 +789,31 @@ def cmd_user_status(sender=None):
|
||||||
reply = "Error! There was a problem checking your account."
|
reply = "Error! There was a problem checking your account."
|
||||||
|
|
||||||
return reply
|
return reply
|
||||||
|
|
||||||
|
def cmd_user_join(sender=None, channel_id=None):
|
||||||
|
if channel_id is None:
|
||||||
|
reply = "You must provide a channel id number with this command.\n"
|
||||||
|
reply += "!join <channel #>"
|
||||||
|
return reply
|
||||||
|
|
||||||
|
try:
|
||||||
|
user = Users.query.filter(Users.matrix_id == sender).one_or_none()
|
||||||
|
if user is None:
|
||||||
|
reply = "You are currently not authorized on pnut.io"
|
||||||
|
else:
|
||||||
|
pnutpy.api.add_authorization_token(user.pnut_user_token)
|
||||||
|
channel, meta = pnutpy.api.get_channel(channel_id, include_raw=1)
|
||||||
|
create_room(channel, user.matrix_id)
|
||||||
|
reply = "is working?"
|
||||||
|
|
||||||
|
except pnutpy.errors.PnutAuthAPIException as e:
|
||||||
|
reply = "You are currently not authorized on pnut.io"
|
||||||
|
|
||||||
|
except pnutpy.errors.PnutPermissionDenied:
|
||||||
|
reply = "You are not authorized for this channel"
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
logging.exception('!join')
|
||||||
|
reply = "Error! There was a problem joining the channel."
|
||||||
|
|
||||||
|
return reply
|
||||||
|
|
|
@ -18,6 +18,13 @@ class DirectRooms(Base):
|
||||||
__tablename__ = 'direct'
|
__tablename__ = 'direct'
|
||||||
id = Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
room_id = Column(String(250), unique=True)
|
room_id = Column(String(250), unique=True)
|
||||||
|
pnut_chan = Column(Integer, unique=True)
|
||||||
|
bridge_user = Column(String(250))
|
||||||
|
|
||||||
|
class ControlRooms(Base):
|
||||||
|
__tablename__ = 'control'
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
room_id = Column(String(250), unique=True)
|
||||||
|
|
||||||
class Events(Base):
|
class Events(Base):
|
||||||
__tablename__ = 'events'
|
__tablename__ = 'events'
|
||||||
|
|
|
@ -12,7 +12,7 @@ import os
|
||||||
|
|
||||||
from matrix_client.api import MatrixHttpApi
|
from matrix_client.api import MatrixHttpApi
|
||||||
from matrix_client.api import MatrixError, MatrixRequestError
|
from matrix_client.api import MatrixError, MatrixRequestError
|
||||||
from models import Avatars, Rooms, Events
|
from models import Avatars, Rooms, Events, DirectRooms, Users
|
||||||
from database import db_session, init_db
|
from database import db_session, init_db
|
||||||
from sqlalchemy import and_
|
from sqlalchemy import and_
|
||||||
from appservice import app
|
from appservice import app
|
||||||
|
@ -22,7 +22,7 @@ logger = logging.getLogger()
|
||||||
_shutdown = threading.Event()
|
_shutdown = threading.Event()
|
||||||
_reconnect = threading.Event()
|
_reconnect = threading.Event()
|
||||||
|
|
||||||
def new_message(msg):
|
def new_message(msg, meta):
|
||||||
logger.debug("channel: " + msg.channel_id)
|
logger.debug("channel: " + msg.channel_id)
|
||||||
logger.debug("username: " + msg.user.username)
|
logger.debug("username: " + msg.user.username)
|
||||||
if 'name' in msg.user:
|
if 'name' in msg.user:
|
||||||
|
@ -36,7 +36,30 @@ def new_message(msg):
|
||||||
if msg.source.id == config['PNUTCLIENT_ID']:
|
if msg.source.id == config['PNUTCLIENT_ID']:
|
||||||
return
|
return
|
||||||
|
|
||||||
room = Rooms.query.filter(Rooms.pnut_chan == msg.channel_id).one_or_none()
|
if meta['channel_type'] == 'io.pnut.core.chat':
|
||||||
|
room = Rooms.query.filter(Rooms.pnut_chan == msg.channel_id).one_or_none()
|
||||||
|
elif meta['channel_type'] == 'io.pnut.core.pm':
|
||||||
|
room = DirectRooms.query.filter(DirectRooms.pnut_chan == msg.channel_id).one_or_none()
|
||||||
|
if room is None:
|
||||||
|
# Do do an invite from the bridge user?
|
||||||
|
logger.debug('new invite?')
|
||||||
|
# create room and included matrix recpient
|
||||||
|
# subscribed_user_ids from meta
|
||||||
|
logger.debug(meta['subscribed_user_ids'])
|
||||||
|
pnut_user = matrix_id_from_pnut(msg.user.username)
|
||||||
|
profile = get_matrix_profile(pnut_user)
|
||||||
|
if not profile:
|
||||||
|
new_matrix_user(msg.user.username)
|
||||||
|
invitees=[]
|
||||||
|
for pm_user in meta['subscribed_user_ids']:
|
||||||
|
user = Users.query.filter(Users.pnut_user_id == pm_user).one_or_none()
|
||||||
|
if user is not None:
|
||||||
|
invitees.append(user.matrix_id)
|
||||||
|
if len(invitees) > 0:
|
||||||
|
room = new_room(pnut_user, invitees, msg.channel_id)
|
||||||
|
else:
|
||||||
|
room = None
|
||||||
|
|
||||||
logger.debug(room)
|
logger.debug(room)
|
||||||
if room is None:
|
if room is None:
|
||||||
logger.debug('-not_mapped-')
|
logger.debug('-not_mapped-')
|
||||||
|
@ -245,6 +268,27 @@ def join_room(room_id, matrix_id):
|
||||||
|
|
||||||
logger.debug('-room_join-')
|
logger.debug('-room_join-')
|
||||||
|
|
||||||
|
def new_room(pnut_user, invitees, chan):
|
||||||
|
dr = None
|
||||||
|
matrix_api = MatrixHttpApi(config['MATRIX_HOST'],
|
||||||
|
token=config['MATRIX_AS_TOKEN'],
|
||||||
|
identity=pnut_user)
|
||||||
|
url = matrix_url + '/createRoom'
|
||||||
|
params = {"access_token": config['MATRIX_AS_TOKEN'], "user_id": pnut_user}
|
||||||
|
content = {"visibility": "private", "is_direct": True, "invite": invitees}
|
||||||
|
headers = {"Content-Type": "application/json"}
|
||||||
|
r = requests.post(url, headers=headers, params=params,
|
||||||
|
data=json.dumps(content))
|
||||||
|
response = r.json()
|
||||||
|
for bridge_user in invitees:
|
||||||
|
dr = DirectRooms(room_id=response['room_id'],
|
||||||
|
bridge_user=pnut_user, pnut_chan=chan)
|
||||||
|
logger.debug(dr)
|
||||||
|
db_session.add(dr)
|
||||||
|
db_session.commit()
|
||||||
|
|
||||||
|
return dr
|
||||||
|
|
||||||
def on_message(ws, message):
|
def on_message(ws, message):
|
||||||
# logger.debug("on_message: " + message)
|
# logger.debug("on_message: " + message)
|
||||||
msg = json.loads(message)
|
msg = json.loads(message)
|
||||||
|
@ -254,8 +298,8 @@ def on_message(ws, message):
|
||||||
|
|
||||||
if 'channel_type' in msg['meta']:
|
if 'channel_type' in msg['meta']:
|
||||||
|
|
||||||
# TODO: bypassed other channel types for now
|
if msg['meta']['channel_type'] not in ['io.pnut.core.chat',
|
||||||
if msg['meta']['channel_type'] != 'io.pnut.core.chat':
|
'io.pnut.core.pm']:
|
||||||
return
|
return
|
||||||
|
|
||||||
for d_item in msg['data']:
|
for d_item in msg['data']:
|
||||||
|
@ -265,10 +309,8 @@ def on_message(ws, message):
|
||||||
if msg['meta']['is_deleted']:
|
if msg['meta']['is_deleted']:
|
||||||
logger.debug("message: delete")
|
logger.debug("message: delete")
|
||||||
delete_message(pmsg)
|
delete_message(pmsg)
|
||||||
else:
|
|
||||||
logger.debug("uh whut?")
|
|
||||||
else:
|
else:
|
||||||
new_message(pmsg)
|
new_message(pmsg, msg['meta'])
|
||||||
|
|
||||||
def on_error(ws, error):
|
def on_error(ws, error):
|
||||||
logger.error("on_error: !!! ERROR !!!")
|
logger.error("on_error: !!! ERROR !!!")
|
||||||
|
|
Loading…
Reference in a new issue