293 lines
8.9 KiB
Python
293 lines
8.9 KiB
Python
import re
|
|
import requests
|
|
from functools import wraps
|
|
from flask import Blueprint, jsonify, abort, request
|
|
from flask_login import login_required, current_user
|
|
from db.models import database, OrdersPool, Order, OrderAddOn, MastodonServer
|
|
from db.queries import user_get, domsubusers_list, orders_pool_list, orders_pool, mastodon_server_get, mastodon_server_put, user_mastodon_server_set, user_preferences_set
|
|
from settings import MASTODON_OAUTH_CLIENT_NAME, MASTODON_OAUTH_REDIRECT_URI, MASTODON_OAUTH_SCOPES, MASTODON_OAUTH_CLIENT_WEBSITE
|
|
|
|
RE_MASTODON_ATTN_LIST = re.compile(r'^(@(\w+)(@([\w\.]+))? )*(@\w+)(@[\w\.]+)?$')
|
|
|
|
api = Blueprint('api', __name__)
|
|
|
|
@api.route("/me")
|
|
@login_required
|
|
def me():
|
|
user = current_user.db_user
|
|
|
|
return jsonify({
|
|
"username": user.telegram_username,
|
|
"telegram_photo_url": user.telegram_photo_url,
|
|
"mastodon_server": user.mastodon_server.name if user.mastodon_server else None,
|
|
"mastodon_username": user.mastodon_username,
|
|
"mastodon_attn_list": user.mastodon_attn_list,
|
|
"mastodon_post_public": user.mastodon_post_public
|
|
})
|
|
|
|
@api.route("/profile", methods=["POST",])
|
|
@login_required
|
|
def profile():
|
|
user = current_user.db_user
|
|
|
|
attn_list = request.json['attn_list'] if 'attn_list' in request.json else user.mastodon_attn_list
|
|
post_public = request.json['post_public'] if 'post_public' in request.json else user.mastodon_post_public
|
|
|
|
if attn_list is not None and RE_MASTODON_ATTN_LIST.fullmatch(attn_list) is None:
|
|
abort(500)
|
|
|
|
user_preferences_set(
|
|
user.id,
|
|
post_public,
|
|
attn_list
|
|
)
|
|
|
|
return ('', 204)
|
|
|
|
@api.route('/mastodon_oauth')
|
|
@login_required
|
|
def mastodon_oauth():
|
|
server_name = request.args['server']
|
|
|
|
try:
|
|
server = mastodon_server_get(server_name)
|
|
except MastodonServer.DoesNotExist:
|
|
payload = {
|
|
'client_name': MASTODON_OAUTH_CLIENT_NAME,
|
|
'redirect_uris': MASTODON_OAUTH_REDIRECT_URI,
|
|
'scopes': MASTODON_OAUTH_SCOPES,
|
|
'website': MASTODON_OAUTH_CLIENT_WEBSITE
|
|
}
|
|
r = requests.post(f'https://{server_name}/api/v1/apps', data=payload)
|
|
|
|
if r.ok:
|
|
app = r.json()
|
|
server = mastodon_server_put(
|
|
server_name,
|
|
app['client_id'],
|
|
app['client_secret']
|
|
)
|
|
else:
|
|
abort(500)
|
|
|
|
user_mastodon_server_set(current_user.db_user.id, server)
|
|
|
|
payload = {
|
|
"client_id": server.client_id,
|
|
"client_secret": server.client_secret,
|
|
"redirect_uri": MASTODON_OAUTH_REDIRECT_URI,
|
|
"grant_type": "client_credentials"
|
|
}
|
|
|
|
return jsonify({
|
|
"url": f"https://{server_name}/oauth/authorize?client_id={server.client_id}&scope={MASTODON_OAUTH_SCOPES}&redirect_uri={MASTODON_OAUTH_REDIRECT_URI}&response_type=code"
|
|
})
|
|
|
|
@api.route('/subs')
|
|
@login_required
|
|
def subs():
|
|
return jsonify(
|
|
[
|
|
{
|
|
"sub_username": dsu.sub.telegram_username,
|
|
"telegram_photo_url": dsu.sub.telegram_photo_url
|
|
}
|
|
for dsu
|
|
in domsubusers_list(current_user.db_user)
|
|
]
|
|
)
|
|
|
|
def authorized_sub(func):
|
|
@wraps(func)
|
|
def wrapper(*args, **kwargs):
|
|
try:
|
|
sub = user_get(request.view_args['username'])
|
|
except:
|
|
abort(403)
|
|
return
|
|
|
|
if (sub.id != current_user.db_user.id and
|
|
sub.telegram_username not in [dsu.sub.telegram_username for dsu in domsubusers_list(current_user.db_user)]):
|
|
abort(403)
|
|
return
|
|
|
|
kwargs['sub'] = sub
|
|
return func(*args, **kwargs)
|
|
return wrapper
|
|
|
|
@api.route('/subs/<username>')
|
|
@login_required
|
|
@authorized_sub
|
|
def sub(username, sub):
|
|
return jsonify({
|
|
"username": sub.telegram_username,
|
|
"mastodon_server": sub.mastodon_server.name if sub.mastodon_server is not None else None,
|
|
"mastodon_username": sub.mastodon_username
|
|
})
|
|
|
|
@api.route('/orders/')
|
|
@login_required
|
|
def my_order_sets():
|
|
return jsonify([
|
|
{
|
|
'id': op.id,
|
|
'name': op.name,
|
|
'scheduled': op.scheduled,
|
|
'time': op.time,
|
|
'weekends': op.weekends,
|
|
'weekdays': op.weekdays,
|
|
'probability': op.probability,
|
|
'punishment_pool_name': op.punishment_pool.name if op.punishment_pool is not None else None,
|
|
'orders': [{
|
|
'id': order.id,
|
|
} for order in op.orders]
|
|
}
|
|
for op
|
|
in orders_pool_list(current_user.db_user)
|
|
])
|
|
|
|
@api.route('/orders/<username>/sets')
|
|
@login_required
|
|
@authorized_sub
|
|
def sub_order_sets(username, sub):
|
|
return jsonify([
|
|
{
|
|
'id': op.id,
|
|
'name': op.name,
|
|
'scheduled': op.scheduled,
|
|
'time': op.time,
|
|
'weekends': op.weekends,
|
|
'weekdays': op.weekdays,
|
|
'probability': op.probability,
|
|
'punishment_pool_name': op.punishment_pool.name if op.punishment_pool is not None else None,
|
|
'orders': [{
|
|
'id': order.id,
|
|
} for order in op.orders]
|
|
}
|
|
for op
|
|
in orders_pool_list(sub.id)
|
|
])
|
|
|
|
@api.route('/orders/<username>/sets/', methods=['POST'])
|
|
@login_required
|
|
@authorized_sub
|
|
def sub_order_set_create(username, sub):
|
|
# Create new
|
|
with database.atomic() as transaction:
|
|
try:
|
|
new_order_pool = OrdersPool.create(
|
|
user=sub,
|
|
name=request.json['name'],
|
|
scheduled=request.json['scheduled'],
|
|
probability=request.json['probability'] if 'probability' in request.json else None,
|
|
time=request.json['time'] if 'time' in request.json else None,
|
|
weekdays=request.json['weekdays'] if 'weekdays' in request.json else None,
|
|
weekends=request.json['weekends'] if 'weekends' in request.json else None,
|
|
confirm_delay=request.json['confirm_delay'] if 'confirm_delay' in request.json else None,
|
|
)
|
|
|
|
for order_to_create in request.json['orders']:
|
|
new_order = Order.create(
|
|
pool=new_order_pool,
|
|
name=order_to_create['name'],
|
|
weight=order_to_create['weight'],
|
|
repeat=order_to_create['repeat']
|
|
)
|
|
|
|
for add_on_to_create in order_to_create['add_ons']:
|
|
OrderAddOn.create(
|
|
order=new_order,
|
|
name=add_on_to_create['name'],
|
|
probability=add_on_to_create['probability']
|
|
)
|
|
except:
|
|
transaction.rollback()
|
|
abort(500)
|
|
|
|
return jsonify(new_order_pool.to_dict())
|
|
|
|
@api.route('/orders/<username>/sets/<set_id>', methods = ['GET', 'POST', 'DELETE'])
|
|
@login_required
|
|
@authorized_sub
|
|
def sub_order_set(username, set_id, sub):
|
|
op = orders_pool(sub.id, set_id)
|
|
|
|
if request.method == 'POST':
|
|
def update_add_ons(order, add_ons):
|
|
for updated_add_on in add_ons:
|
|
if isinstance(updated_add_on['id'], int):
|
|
add_on_to_update = order.add_ons.where(OrderAddOn.id == updated_add_on['id']).get()
|
|
|
|
if '_delete' in updated_add_on:
|
|
add_on_to_update.delete_instance(recursive=True)
|
|
else:
|
|
add_on_to_update.name = updated_add_on['name']
|
|
add_on_to_update.probability = updated_add_on['probability']
|
|
|
|
add_on_to_update.save()
|
|
else:
|
|
OrderAddOn.create(
|
|
order=order,
|
|
name=updated_add_on['name'],
|
|
probability=updated_add_on['probability']
|
|
)
|
|
|
|
with database.atomic() as transaction:
|
|
try:
|
|
op.name = request.json['name']
|
|
|
|
if ('punishment_pool_id' in request.json and
|
|
request.json['punishment_pool_id'] in [
|
|
op.id for op in orders_pool_list(sub.id)
|
|
]):
|
|
op.punishment_pool_id = request.json['punishment_pool_id']
|
|
else:
|
|
op.punishment_pool_id = None
|
|
|
|
op.scheduled = request.json['scheduled']
|
|
if op.scheduled:
|
|
op.probability = request.json['probability']
|
|
op.weekdays = request.json['weekdays']
|
|
op.weekends = request.json['weekends']
|
|
op.time = request.json['time']
|
|
op.confirm_delay = request.json['confirm_delay']
|
|
else:
|
|
op.probability = None
|
|
op.weekdays = None
|
|
op.weekends = None
|
|
op.time = None
|
|
op.confirm_delay = None
|
|
|
|
op.save()
|
|
|
|
for updated_order in request.json['orders']:
|
|
if isinstance(updated_order['id'], int):
|
|
order_to_update = op.orders.where(Order.id == updated_order['id']).get()
|
|
|
|
if '_delete' in updated_order:
|
|
order_to_update.delete_instance(recursive=True)
|
|
else:
|
|
order_to_update.name = updated_order['name']
|
|
order_to_update.weight = updated_order['weight']
|
|
order_to_update.repeat = updated_order['repeat']
|
|
|
|
order_to_update.save()
|
|
|
|
update_add_ons(order_to_update, updated_order['add_ons'])
|
|
else:
|
|
order_to_update = Order.create(
|
|
pool=op,
|
|
name=updated_order['name'],
|
|
weight=updated_order['weight'],
|
|
repeat=updated_order['repeat']
|
|
)
|
|
|
|
update_add_ons(order_to_update, updated_order['add_ons'])
|
|
except:
|
|
transaction.rollback()
|
|
abort(500)
|
|
elif request.method == 'DELETE':
|
|
op.delete_instance(recursive=True)
|
|
return ('', 204)
|
|
|
|
return jsonify(op.to_dict())
|