pnut-matrix/appservice.py
Morgan McMillian c75b7517ca use correct pnut acl attribute for public
When creating of the matrix room is triggered, the pnut attribute
channel.acl.read.public flag should be used to determine if the matrix
room preset should be set to public or private. Issue #58
2022-06-30 12:47:31 -07:00

841 lines
29 KiB
Python

import json
import requests
import logging
import re
import pnutpy
import textwrap
import time
from matrix_client.api import MatrixHttpApi
from matrix_client.api import MatrixError, MatrixRequestError
from models import Avatars, Rooms, Events, Users, DirectRooms, ControlRooms
from database import db_session
from sqlalchemy import and_
from flask import Flask, jsonify, request, abort
logger = logging.getLogger(__name__)
app = Flask(__name__)
@app.errorhandler(404)
def not_found(error):
return jsonify({'errcode':'COM.MONKEYSTEW.PNUT_NOT_FOUND'}), 404
@app.errorhandler(403)
def forbidden(error):
return jsonify({'errcode':'COM.MONKEYSTEW.PNUT_FORBIDDEN'}), 403
@app.teardown_appcontext
def shutdown_session(exception=None):
db_session.remove()
@app.route("/rooms/<alias>")
def query_alias(alias):
alias_localpart = alias.split(":")[0][1:]
channel_id = int(alias_localpart.split('_')[1])
room = Rooms.query.filter(Rooms.pnut_chan == channel_id).one_or_none()
if room is not None:
abort(404)
token = app.config['MATRIX_PNUT_TOKEN']
pnutpy.api.add_authorization_token(token)
try:
channel, meta = pnutpy.api.get_channel(channel_id, include_raw=1)
if 'is_active' in channel and channel.is_active == False:
logger.debug("-channel isn't active-")
abort(404)
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': alias_localpart}
if 'name' in channel_settings:
room['name'] = channel_settings['name']
if 'description' in channel_settings:
room['topic'] = channel_settings['description']
if channel.acl.read.public:
room['preset'] = 'public_chat'
room['visibility'] = 'public'
else:
abort(401)
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()
except pnutpy.errors.PnutPermissionDenied:
abort(401)
except Exception:
logger.exception("-couldn't get the pnut channel-")
abort(404)
return jsonify({})
@app.route("/transactions/<transaction>", methods=["PUT"])
def on_receive_events(transaction):
access_token = request.args.get('access_token', '')
if access_token != app.config['MATRIX_HS_TOKEN']:
abort(403)
events = request.get_json()["events"]
for event in events:
logger.debug(event)
if app.config['MATRIX_ADMIN_ROOM'] and app.config['MATRIX_ADMIN_ROOM'] == event['room_id']:
return on_admin_event(event)
user = Users.query.filter(Users.matrix_id == event['user_id']).one_or_none()
if event['type'] == 'm.room.message':
new_message(event, user)
elif event['type'] == 'm.room.redaction':
delete_message(event, user)
elif event['type'] == 'm.room.member':
if 'is_direct' in event['content'] and 'membership' in event['content']:
if event['content']['membership'] == "invite" and event['content']['is_direct']:
return on_direct_invite(event)
if 'membership' in event['content']:
if event['content']['membership'] == "leave":
return on_leave_event(event)
logger.debug("----room member event----")
logger.debug(user)
logger.debug(event)
return jsonify({})
def new_message(event, user):
if app.config['MATRIX_PNUT_PREFIX'] in event['user_id'] or 'pnut-bridge' in event['user_id']:
logger.debug('-skipping dup event-')
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()
if direct is not None:
return on_direct_message(event, user, direct)
room = Rooms.query.filter(Rooms.room_id == event['room_id']).one_or_none()
if room is None:
logger.debug('-room not mapped-')
return
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()
if user is not None:
cctag = re.search('##$', text)
if cctag:
raw = []
cname = get_channel_settings(room.pnut_chan)['name']
text = text[:-2]
ftext = '\n\n[' + cname + "](https://patter.chat/room.html?channel=" + str(room.pnut_chan) + ")"
mtext = textwrap.wrap(text + ftext, 254)
if len(mtext) > 1:
longpost = {
'title': "",
'body': text,
'tstamp': time.time() * 1000
}
pretext = textwrap.wrap(text, 100)
text = pretext[0]
text += "... - https://longpo.st/p/{object_id} - #longpost"
raw.append({'type':"nl.chimpnut.blog.post", 'value': longpost})
text += ftext
r, meta = pnutpy.api.create_post(data={'text': text, 'raw': raw})
except pnutpy.errors.PnutAuthAPIException:
logger.exception('-unable to post to pnut channel-')
return
except Exception:
logger.exception('-something bad happened here-')
return
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:]
if event['content']['msgtype'] == 'm.image':
value = {'type': "photo", 'version': "1.0"}
value['url'] = url
value['title'] = event['content']['body']
if 'info' in event['content']:
if 'w' in event['content']['info']:
value['width'] = event['content']['info']['w']
else:
value['width'] = 200
if 'h' in event['content']['info']:
value['height'] = event['content']['info']['h']
else:
value['height'] = 200
if 'thumbnail_info' in event['content']['info']:
if 'thumbnail_url' in event['content']['info']:
value['thumbnail_url'] = app.config['MATRIX_URL'] + '/_matrix/media/r0/download/' + event['content']['info']['thumbnail_url'][6:]
if 'w' in event['content']['info']['thumbnail_info']:
value['thumbnail_width'] = event['content']['info']['thumbnail_info']['w']
else:
value['thumbnail_width'] = 200
if 'h' in event['content']['info']['thumbnail_info']:
value['thumbnail_height'] = event['content']['info']['thumbnail_info']['h']
else:
value['thumbnail_height'] = 200
elif event['content']['msgtype'] == 'm.video':
# TODO: Need to sort out the oembed for this media type
value = {'type': "html5video", 'version': "1.0"}
source = {'url': url}
value['title'] = event['content']['body']
if 'info' in event['content']:
value['width'] = event['content']['info']['w']
value['height'] = event['content']['info']['h']
source['type'] = event['content']['info']['mimetype']
else:
return None
value['sources'] = [source]
elif event['content']['msgtype'] == 'm.audio':
# TODO: Need to sort out the oembed for this media type
value = {'type': "audio", 'version': "1.0"}
return None
else:
return None
return {'type': "io.pnut.core.oembed", 'value': value}
def delete_message(event, user):
# TODO: should there be moderator handled redactions?
if user is not None:
token = user.pnut_user_token
else:
token = app.config['MATRIX_PNUT_TOKEN']
pnutpy.api.add_authorization_token(token)
e = Events.query.filter(and_(Events.event_id == event['redacts'], Events.deleted == False)).one_or_none()
if e is None:
logger.debug("- can't find the event to remove -")
return
try:
r, meta = pnutpy.api.delete_message(e.pnut_chan_id, e.pnut_msg_id)
e.deleted = True
db_session.commit()
except pnutpy.errors.PnutPermissionDenied as e:
pass
def get_profile(userid):
url = app.config['MATRIX_HOST'] + "/_matrix/client/r0/profile/" + userid
r = requests.get(url)
if r.status_code == 200:
return json.loads(r.text)
return userid
def get_channel_settings(channel_id):
channel_settings = {}
try:
channel, meta = pnutpy.api.get_channel(channel_id, include_raw=1)
for item in channel.raw:
if item.type == 'io.pnut.core.chat-settings':
channel_settings = item.value
except Exception:
logger.exception('-unable to get channel settings-')
return channel_settings
def create_room(channel, user):
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(user)
logger.debug(room)
room['invite'] = [user.matrix_id]
if 'name' in channel_settings:
room['name'] = channel_settings['name']
if 'description' in channel_settings:
room['topic'] = channel_settings['description']
if channel.acl.read.public:
room['preset'] = 'public_chat'
room['visibility'] = 'public'
elif channel.acl.read.any_user or channel.acl.read.you:
room['preset'] = 'private_chat'
room['visibility'] = 'private'
else:
abort(401)
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 new_matrix_user(username):
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
token=app.config['MATRIX_AS_TOKEN'])
data = {'type': 'm.login.application_service','user': app.config['MATRIX_PNUT_PREFIX'] + username}
try:
matrix_api.register(content=data)
except Exception:
errmsg = "- new_matrix_user user already exists -"
logger.warning(errmsg)
def on_admin_event(event):
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
token=app.config['MATRIX_AS_TOKEN'])
logger.debug("- admin room event recieved -")
if event['type'] != 'm.room.message':
return jsonify({})
msg = event['content']['body'].split(' ')
try:
if msg[0] == 'help':
if len(msg) > 1:
matrix_api.send_message(event['room_id'], cmd_admin_help(msg[1]))
else:
matrix_api.send_message(event['room_id'], cmd_admin_help())
elif msg[0] == 'list':
matrix_api.send_message(event['room_id'], cmd_admin_list())
elif msg[0] == 'unlink':
if len(msg) > 1:
matrix_api.send_message(event['room_id'], cmd_admin_unlink(msg[1]))
else:
matrix_api.send_message(event['room_id'], cmd_admin_help('unlink'))
elif msg[0] == 'link':
if len(msg) > 2:
matrix_api.send_message(event['room_id'], cmd_admin_link(msg[1], msg[2]))
else:
matrix_api.send_message(event['room_id'], cmd_admin_help('link'))
except Exception:
errmsg = "- on_admin_event -"
logger.exception(errmsg)
return jsonify({})
def cmd_admin_help(cmd=None):
help_usage = "help [command]"
help_desc = "Show information about available commands."
list_usage = "list"
list_desc = "List the rooms currently linked with pnut.io."
unlink_usage = "unlink <room_id> | <pnut_channel_id>"
unlink_desc = "Unlink a room between Matrix and pnut.io."
link_usage = "link <room_id> <pnut_channel_id>"
link_desc = "Link a room between Matrix and pnut.io."
if cmd == 'help':
text = "usage: " + help_usage + "\n\n"
text += help_desc
if cmd == 'list':
text = "usage: " + list_usage + "\n\n"
text += list_desc
elif cmd == 'unlink':
text = "usage: " + unlink_usage + "\n\n"
text += unlink_desc
elif cmd == 'link':
text = "usage: " + link_usage + "\n\n"
text += link_desc
else:
text = "The following commands are available:\n\n"
text += help_usage + "\n"
text += list_usage + "\n"
text += unlink_usage + "\n"
text += link_usage + "\n"
return text
def cmd_admin_list():
text = ""
rooms = Rooms.query.all()
if len(rooms) > 0:
text = "ID\tMATRIX ID\tPNUT CHANNEL\n"
else:
text = " - no rooms are currently linked - \n"
for room in rooms:
text += str(room.id) + '\t'
text += room.room_id + '\t\t\t\t\t'
text += str(room.pnut_chan) + '\t'
if room.portal:
text += "(portal)"
text += '\n'
return text
def cmd_admin_link(room_id, pnut_chan_id):
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
token=app.config['MATRIX_AS_TOKEN'])
pnutpy.api.add_authorization_token(app.config['MATRIX_PNUT_TOKEN'])
mrcheck = Rooms.query.filter(Rooms.room_id == room_id).one_or_none()
pncheck = Rooms.query.filter(Rooms.pnut_chan == pnut_chan_id).one_or_none()
if mrcheck is not None or pncheck is not None:
return "- room may already be linked -"
try:
channel, meta = pnutpy.api.subscribe_channel(pnut_chan_id)
r = matrix_api.join_room(room_id)
rec = Rooms(
room_id=room_id,
pnut_chan=channel.id,
portal=False
)
db_session.add(rec)
db_session.commit()
except pnutpy.errors.PnutAuthAPIException:
errmsg = "- unable to subscribe to channel -"
logger.exception(errmsg)
return errmsg
except Exception:
errmsg = "- unable to link room for some reason -"
logger.exception(errmsg)
return errmsg
def cmd_admin_unlink(rid):
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
token=app.config['MATRIX_AS_TOKEN'])
pnutpy.api.add_authorization_token(app.config['MATRIX_PNUT_TOKEN'])
if rid.startswith('!'):
room = Rooms.query.filter(Rooms.room_id == rid).one_or_none()
else:
room = Rooms.query.filter(Rooms.pnut_chan == rid).one_or_none()
if hasattr(room, 'portal'):
if room.portal:
alias = "#" + app.config['MATRIX_PNUT_PREFIX']
alias += str(room.pnut_chan) + ":"
alias += app.config['MATRIX_DOMAIN']
matrix_api.remove_room_alias(alias)
# Kicking users needs at least moderator privs
members = matrix_api.get_room_members(room.room_id)
reason = "Portal room has been unlinked by administrator"
for m in members['chunk']:
if m['content']['membership'] == 'join' and m['sender'] != app.config['MATRIX_AS_ID']:
if room.portal:
matrix_api.kick_user(room.room_id, m['sender'], reason=reason)
else:
if m['sender'].startswith("@" + app.config['MATRIX_PNUT_PREFIX']):
matrix_api.kick_user(room.room_id, m['sender'], reason=reason)
try:
channel, meta = pnutpy.api.unsubscribe_channel(room.pnut_chan)
matrix_api.leave_room(room.room_id)
if room is not None:
db_session.delete(room)
db_session.commit()
return "- room has been unlinked -"
else:
return "- unable to locate room to unlink -"
except Exception:
errmsg = "- error while unlinking room -"
logger.exception(errmsg)
return errmsg
def on_direct_invite(event):
if event['state_key'] == app.config['MATRIX_AS_ID']:
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
token=app.config['MATRIX_AS_TOKEN'])
dm = ControlRooms(room_id=event['room_id'])
else:
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
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)
new_matrix_user(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({})
def on_leave_event(event):
direct = DirectRooms.query.filter(DirectRooms.room_id == event['room_id']).one_or_none()
if direct is not None:
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
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({})
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'],
token=app.config['MATRIX_AS_TOKEN'])
logger.debug("- direct room event received -")
if event['type'] != 'm.room.message':
return jsonify({})
msg = event['content']['body'].split(' ')
try:
if msg[0] == '!help' or msg[0] == 'help':
if len(msg) > 1:
matrix_api.send_message(event['room_id'], cmd_user_help(msg[1]))
else:
matrix_api.send_message(event['room_id'], cmd_user_help())
elif msg[0] == '!auth':
matrix_api.send_message(event['room_id'], cmd_user_auth())
elif msg[0] == '!save':
if len(msg) > 1:
matrix_api.send_message(event['room_id'], cmd_user_save(event['sender'], msg[1]))
else:
matrix_api.send_message(event['room_id'], cmd_user_save())
elif msg[0] == '!drop':
matrix_api.send_message(event['room_id'], cmd_user_drop(event['sender']))
elif msg[0] == '!status':
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({})
def cmd_user_help(cmd=None):
reply = "This is an admin room for controlling your connection to pnut.io\n"
reply += "The following commands are available.\n\n"
reply += "!auth\t\t\t- Authorize your account on pnut.io\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 += "!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
def cmd_user_auth():
reply = "Visit the following URL to authorize your account on pnut.io.\n\n"
reply += "https://pnut.io/oauth/authenticate"
reply += "?client_id=6SeCRCpCZkmZOKFLFGWbcdAeq2fX1M5t"
reply += "&redirect_uri=urn:ietf:wg:oauth:2.0:oob"
reply += "&scope=write_post,presence,messages&response_type=token\n\n"
reply += "You will be provided with a token that you store with the !save command.\n"
return reply
def cmd_user_save(sender=None, token=None):
if token is None:
reply = "You must provide a token with this command.\n"
reply += "!save <token>"
return reply
pnutpy.api.add_authorization_token(token)
try:
response, meta = pnutpy.api.get_user('me')
user = Users(
matrix_id=sender,
pnut_user_id=response.id,
pnut_user_token=token
)
db_session.add(user)
db_session.commit()
reply = "Success! You are now authorized as " + response['username']
except pnutpy.errors.PnutAuthAPIException as e:
reply = "Error! Unable to authorize your account."
except Exception as e:
logging.exception('!save')
reply = "Error! Problem saving your token."
return reply
def cmd_user_drop(sender=None):
try:
user = Users.query.filter(Users.matrix_id == sender).one_or_none()
if user is not None:
db_session.delete(user)
db_session.commit()
reply = "Success! Your auth token has been removed."
else:
reply = "You do not appear to be registered."
except Exception as e:
logging.exception('!drop')
reply = "Error! Problem removing your token."
return reply
def cmd_user_status(sender=None):
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)
response, meta = pnutpy.api.get_user('me')
reply = "You are currently authorized as " + response.username
except pnutpy.errors.PnutAuthAPIException as e:
reply = "You are currently not authorized on pnut.io"
except Exception as e:
logging.exception('!status')
reply = "Error! There was a problem checking your account."
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)
room = Rooms.query.filter(Rooms.pnut_chan == channel_id).one_or_none()
if room is None:
create_room(channel, user)
else:
matrix_api = MatrixHttpApi(app.config['MATRIX_HOST'],
token=app.config['MATRIX_AS_TOKEN'])
matrix_api.invite_user(room.room_id, sender)
reply = "ok"
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