|
|
@ -1,12 +1,14 @@ |
|
|
|
from flask import Flask, request, render_template, send_from_directory |
|
|
|
from flask import Flask, request, render_template, send_from_directory, abort |
|
|
|
from flask_sqlalchemy import SQLAlchemy |
|
|
|
from mastodon import Mastodon |
|
|
|
import re |
|
|
|
#import html2text |
|
|
|
import re, random, string |
|
|
|
import html2text |
|
|
|
|
|
|
|
BOT_NAME = '@ask_me_bot' |
|
|
|
DOMAIN = 'thu.closed.social' |
|
|
|
|
|
|
|
WORK_URL = 'https://closed.social' |
|
|
|
|
|
|
|
token = open('token.secret','r').read().strip('\n') |
|
|
|
th = Mastodon( |
|
|
|
access_token = token, |
|
|
@ -16,35 +18,26 @@ th = Mastodon( |
|
|
|
|
|
|
|
app = Flask(__name__) |
|
|
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///ask.db' |
|
|
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False |
|
|
|
|
|
|
|
|
|
|
|
#h2t = html2text.HTML2Text() |
|
|
|
#h2t.ignore_links = True |
|
|
|
|
|
|
|
def PM(msg, name): |
|
|
|
th.status_post(msg + '\n@' + name, visibility='direct') |
|
|
|
h2t = html2text.HTML2Text() |
|
|
|
h2t.ignore_links = True |
|
|
|
|
|
|
|
db = SQLAlchemy(app) |
|
|
|
|
|
|
|
''' |
|
|
|
class Record(db.Model): |
|
|
|
class User(db.Model): |
|
|
|
id = db.Column(db.Integer, primary_key=True) |
|
|
|
s = db.Column(db.String(64)) |
|
|
|
name_hash = db.Column(db.String(64)) |
|
|
|
full_hash = db.Column(db.String(64)) |
|
|
|
ip = db.Column(db.String(32)) |
|
|
|
cs_username = db.Column(db.String(32)) |
|
|
|
|
|
|
|
def __init__(self, s, name_hash, full_hash, ip): |
|
|
|
self.s = s |
|
|
|
self.name_hash = name_hash |
|
|
|
self.full_hash = full_hash |
|
|
|
self.ip = ip |
|
|
|
self.cs_username = '' |
|
|
|
acct = db.Column(db.String(64)) |
|
|
|
disp = db.Column(db.String(64)) |
|
|
|
avat = db.Column(db.String(256)) |
|
|
|
url = db.Column(db.String(128)) |
|
|
|
secr = db.Column(db.String(16)) |
|
|
|
|
|
|
|
def __init__(self, acct): |
|
|
|
self.acct = acct |
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
return '%s[%s]<%s>'%(self.s, self.cs_username, self.ip) |
|
|
|
''' |
|
|
|
return '@%s[%s]'%(self.acct, self.disp) |
|
|
|
|
|
|
|
@app.route('/js/<path:path>') |
|
|
|
def send_js(path): |
|
|
@ -58,52 +51,52 @@ def root(): |
|
|
|
return app.send_static_file('ask.html') |
|
|
|
|
|
|
|
@app.route('/askMe/inbox/', methods=['POST']) |
|
|
|
def api(): |
|
|
|
username = request.form.get('username') |
|
|
|
if not re.match('[a-z0-9_]{1,30}(@[a-z\.-_]+)?', username): |
|
|
|
return '闭社id格式错误', 422 |
|
|
|
|
|
|
|
return 'okkk' |
|
|
|
|
|
|
|
ha = request.form.get('hash') |
|
|
|
if( not ha or len(ha) != 64 * 2): |
|
|
|
return '哈希格式不正确', 422 |
|
|
|
|
|
|
|
ip = request.remote_addr |
|
|
|
if ip in ip_count: |
|
|
|
ip_count[ip] += 1 |
|
|
|
if ip_count[ip] > 50: |
|
|
|
return '该ip告白次数太多', 403 |
|
|
|
else: |
|
|
|
ip_count[ip] = 1 |
|
|
|
|
|
|
|
if Record.query.filter_by(s=s).count(): |
|
|
|
return '暗号重复', 422 |
|
|
|
if Record.query.filter_by(name_hash=ha[64:]).count(): |
|
|
|
return '一个名字只能告白一次,\n重名/哈希冲突请联系主办方', 422 |
|
|
|
|
|
|
|
ta = Record.query.filter_by(full_hash=ha[:64]).first() |
|
|
|
def set_inbox(): |
|
|
|
acct = request.form.get('username') |
|
|
|
if not re.match('[a-z0-9_]{1,30}(@[a-z\.-_]+)?', acct): |
|
|
|
return '无效的闭社id', 422 |
|
|
|
|
|
|
|
r = th.conversations() |
|
|
|
for conv in r: |
|
|
|
status = conv.last_status |
|
|
|
account = status.account |
|
|
|
#print(account) |
|
|
|
if acct == account.acct: |
|
|
|
pt = h2t.handle(status.content).strip() |
|
|
|
|
|
|
|
x = re.findall('新建(\[[a-z]{1,32}\])?', pt) |
|
|
|
if not x: |
|
|
|
return '私信格式无效,请检查并重新发送', 422 |
|
|
|
|
|
|
|
secr = x[0][1:-1] if x[0] else ''.join(random.choice(string.ascii_lowercase) for i in range(16)) |
|
|
|
|
|
|
|
u = User.query.filter_by(acct=acct).first() |
|
|
|
if not u: |
|
|
|
u = User(acct) |
|
|
|
db.session.add(u) |
|
|
|
|
|
|
|
u.disp = account.display_name |
|
|
|
u.url = account.url |
|
|
|
u.avat = account.avatar |
|
|
|
u.secr = secr |
|
|
|
db.session.commit() |
|
|
|
|
|
|
|
th.status_post(f"@{acct} 设置成功! 当前提问箱链接 {WORK_URL}/askMe/{acct}/{secr}\n(如需在微信等无链接预览的平台分享,建议先发给自己,点开,再点击分享到朋友圈等)", |
|
|
|
in_reply_to_id=status.id, |
|
|
|
visibility='direct' |
|
|
|
) |
|
|
|
|
|
|
|
return acct + '/' + secr |
|
|
|
|
|
|
|
rec = Record(s, ha[64:], ha[:64], ip) |
|
|
|
rec = Record(s, ha[64:], ha[:64], ip) |
|
|
|
db.session.add(rec) |
|
|
|
db.session.commit() |
|
|
|
return '未找到私信,请确认已发送且是最近发送', 404 |
|
|
|
|
|
|
|
if not ta: |
|
|
|
return '' |
|
|
|
else: |
|
|
|
if ta.cs_username: |
|
|
|
PM('叮~ TA也给你表白啦! https://closed.social/meetLove/result/', ta.cs_username) |
|
|
|
return 'y' if ta.cs_username else 'n' |
|
|
|
|
|
|
|
@app.route('/meetLove/result/') |
|
|
|
def result(): |
|
|
|
rs = Record.query.all() |
|
|
|
rs.sort(key=lambda r:r.full_hash) |
|
|
|
|
|
|
|
lovers = [(rs[i].s[:-4]+'****', rs[i+1].s[:-4]+'****') for i in range(len(rs)-1) if rs[i].full_hash == rs[i+1].full_hash] |
|
|
|
|
|
|
|
return render_template('result.html', lovers=lovers) |
|
|
|
@app.route('/askMe/<acct>/<secr>') |
|
|
|
def inbox(acct, secr): |
|
|
|
u = User.query.filter_by(acct=acct, secr=secr).first() |
|
|
|
if not u: |
|
|
|
abort(404) |
|
|
|
|
|
|
|
return render_template('inbox.html', acct=u.acct, disp=u.disp, url=u.url, avat=u.avat) |
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
app.run() |
|
|
|
app.run(debug=True) |