mastodon-BDSM/BDSM/views.py
2023-02-17 12:33:34 +08:00

268 lines
9 KiB
Python

#!/usr/bin/env python3
import os
import pytz
import json
from flask import render_template, request, url_for, redirect, flash, abort
from flask_sqlalchemy import Pagination
from BDSM import app, db
from BDSM.models import Media, Poll, Settings, Toot, Emoji, Other
from BDSM.toot import app_login, app_register, archive_toot, get_context
from mastodon import Mastodon
from types import SimpleNamespace
from datetime import timezone
# @app.context_processor
# def inject_setting():
# settings = Settings.query.first()
# return settings.__dict__
@app.route('/', methods=['GET', 'POST'])
def index():
settings = Settings.query.first()
if settings == None:
return redirect(url_for('settings'))
else:
page = request.args.get('page', 1, type=int)
toots_ = Toot.query.order_by(Toot.created_at.desc()).paginate(page=page, per_page=50)
toots = process_toot(toots_)
path=SimpleNamespace()
path.path = "index"
path.args = {}
return render_template('view.html', toots=toots, pagination=toots_, path=path)
@app.route('/favourited', methods=['GET', 'POST'])
def favourited():
settings = Settings.query.first()
if settings == None:
return redirect(url_for('settings'))
else:
page = request.args.get('page', 1, type=int)
toots_ = Toot.query.order_by(Toot.created_at.desc()).paginate(page=page, per_page=50)
toots = process_toot(toots_)
path=SimpleNamespace()
path.path = "favourited"
path.args = {}
return render_template('view.html', toots=toots, pagination=toots_, path=path)
@app.route('/search', methods=['GET', 'POST'])
def search():
if request.method == 'POST':
query = request.form['query']
return redirect(url_for('search',query=query))
query = request.args.get('query', "", type=str)
page = request.args.get('page', 1, type=int)
toots_ = Toot.query.order_by(Toot.created_at.desc()).filter(Toot.content.like("%"+query+"%")).paginate(
page=page, per_page=50)
toots = process_toot(toots_)
path=SimpleNamespace()
# Rule: /serch
path.path = str(request.url_rule)[1:] #FIXME
path.args = {}
path.args["query"] = query
return render_template('view.html', toots=toots, pagination=toots_, path=path)
@app.route('/context/<int:toot_id>', methods=['GET', 'POST'])
def context(toot_id):
def get_reply(reply_id):
toots = Toot.query.order_by(Toot.created_at.desc()).filter_by(in_reply_to_id=reply_id).all()
other_toots = Other.query.order_by(Other.created_at.desc()).filter_by(in_reply_to_id=reply_id).all()
toots = process_toot(toots) + process_toot(other_toots)
for i in toots:
if i.in_reply_to_id != None:
i.reply = get_reply(i.id)
return toots
toots = []
toot_ = Toot.query.get(toot_id)
if toot_ == None:
toot_ = Other.query.get(toot_id)
if toot_ == None:
abort(404)
toots.append(toot_)
toots = process_toot(toots)
toots[0].reply = get_reply(toot_id)
in_reply_to_id = toots[0].in_reply_to_id
while(in_reply_to_id != None):
toot = []
toot_ = Toot.query.get(toots[0].in_reply_to_id)
if toot_ == None:
toot_ = Other.query.get(toots[0].in_reply_to_id)
if toot_ == None:
break
toot.append(toot_)
toot = process_toot(toot)
toots.insert(0,toot[0])
in_reply_to_id = toot[0].in_reply_to_id
return render_template('view.html', toots=toots,)
@app.route('/grab/<int:toot_id>', methods=['GET', 'POST'])
def grab(toot_id):
settings = Settings.query.first()
account = settings.account[1:]
username, domain = account.split("@")
url = "https://" + domain
get_context(url, toot_id)
flash('抓取完成……大概!')
return redirect(url_for('context',toot_id=toot_id))
@app.route('/settings', methods=['GET', 'POST'])
def settings():
if request.method == 'POST':
domain = request.form['domain']
timezone = request.form['timezone']
if not domain or len(domain) > 50:
flash('无效输入')
return redirect(url_for('settings'))
settings = Settings.query.first()
if settings == None:
settings = Settings(domain=domain, timezone=timezone)
db.session.add(settings)
else:
settings.timezone = timezone
db.session.commit()
flash('设置已修改')
return redirect(url_for('settings'))
settings = Settings.query.first()
app_init = os.path.isfile('pyBDSM_clientcred.secret') and os.path.isfile('user.secret')
if settings == None:
flash('请输入相关设置!')
return render_template('settings.html',settings=settings, app_init=app_init)
@app.route('/register', methods=['GET', 'POST'])
def register():
settings = Settings.query.first()
if settings == None:
flash('请先输入站点地址!')
return redirect(url_for('settings'))
else:
domain = settings.domain
url = "https://" + domain
if request.method == 'POST':
token = request.form['token'].rstrip()
mastodon = Mastodon(client_id='pyBDSM_clientcred.secret', api_base_url=url)
mastodon.log_in(code=token, to_file='user.secret', scopes=['read'])
mastodon, _ = app_login(url)
account = mastodon.me().acct
settings.account = account
db.session.commit()
if os.path.isfile('user.secret'):
flash('应用已授权!')
return redirect(url_for('settings'))
if not os.path.isfile('pyBDSM_clientcred.secret'):
app_register(url)
if not os.path.isfile('user.secret'):
mastodon = Mastodon(client_id='pyBDSM_clientcred.secret', api_base_url=url)
url = mastodon.auth_request_url(client_id='pyBDSM_clientcred.secret', scopes=['read'])
return render_template('register.html',url=url)
flash('已授权过!')
return redirect(url_for('settings'))
@app.route('/archive', methods=['GET', 'POST'])
def archive():
settings = Settings.query.first()
if request.method == 'POST':
archive_match = request.form.getlist("archive_match")
domain = settings.domain
url = "https://" + domain
archive_toot(url, archive_match)
flash('存档完成……大概!')
return redirect(url_for('index'))
if settings == None:
return redirect(url_for('settings'))
else:
return render_template('archive.html')
def process_toot(toots_):
toots = []
settings = Settings.query.first()
user_timezone = pytz.timezone(settings.timezone)
fmt = '%Y-%m-%d %H:%M:%S'
if hasattr(toots_, 'items'):
toots_ = toots_.items
for toot_ in toots_:
toot = SimpleNamespace(**toot_.__dict__)
toot.created_at = toot.created_at.replace(tzinfo=timezone.utc)
toot.created_at = toot.created_at.astimezone(user_timezone).strftime(fmt)
if hasattr(toot, 'reblog_id'):
toot.is_myself = True
if toot.reblog_id != None:
if toot.reblog_myself:
toot = Toot.query.get(toot.reblog_id)
toot = SimpleNamespace(**toot.__dict__)
toot.is_reblog = True
else:
toot = Other.query.get(toot.reblog_id)
toot = SimpleNamespace(**toot.__dict__)
toot.is_reblog = True
else:
toot.is_myself = False
if toot.media_list != "":
toot.medias = []
#media_list "1111,2222,333,"
media_list = toot.media_list[:-1].split(",")
for media_id in media_list:
media = Media.query.get(int(media_id))
if media != None:
toot.medias.append(media)
if toot.emoji_list != "":
toot.emojis = []
#emoji_list "blobfoxaaa,blobcatwww,fox_think,"
emoji_list = toot.emoji_list[:-1].split(",")
for emoji_shortcode in emoji_list:
emoji = Emoji.query.filter_by(shortcode=emoji_shortcode, acct=toot.acct).first()
if emoji != None:
emoji_shortcode = ':' + emoji_shortcode + ':'
emoji_url = emoji.url
emoji_html = f'''
<img class="emojione custom-emoji" alt="{emoji_shortcode}" title="{emoji_shortcode}" src="{emoji.url}" >
'''
toot.content = toot.content.replace(emoji_shortcode, emoji_html)
if toot.poll_id != None:
poll = Poll.query.get(toot.poll_id)
poll_options = json.loads(poll.options.replace("\'", "\""))
poll_count = str(poll.votes_count)
poll_content = '<strong>总票数: ' + poll_count + '</strong><br>'
for i in poll_options:
poll_content += i['title'] + " / " + str(i['votes_count']) + '<br>'
toot.content += poll_content
toots.append(toot)
return toots