Compare commits

...

5 commits

Author SHA1 Message Date
f164ddaa22 fix/edited_at compatible with lower versions 2022-11-08 02:29:56 +08:00
670e7d42ba feat/show other account replys 2022-11-08 02:25:06 +08:00
6793fda0c8 feat/show if edited 2022-11-07 23:58:20 +08:00
3eae1f36ce feat/support incremental backup
fix/fix edited_at typeerror
2022-11-07 23:49:10 +08:00
7fcff2566a db/change db model name 2022-11-07 22:42:20 +08:00
4 changed files with 237 additions and 170 deletions

View file

@ -26,7 +26,7 @@ class Toot(db.Model):
favourites_count = db.Column(db.Integer)
language = db.Column(db.Text)
class Reblog(db.Model):
class Other(db.Model):
id = db.Column(db.Integer, primary_key=True)
acct = db.Column(db.Text)
url = db.Column(db.Text)

View file

@ -12,16 +12,20 @@
<a href="{{ toot.url }}" target="_blank"
rel="noopener noreferrer">
<span class="time">
{% if toot. visibility == "public"%}
{% if toot.visibility == "public"%}
<span class="visibility-icon"><i class="fa-solid fa-earth-americas fa-globle"></i></span>
{% elif toot. visibility == "unlisted"%}
{% elif toot.visibility == "unlisted"%}
<span class="visibility-icon"><i class="fa-solid fa-lock-open fa-unlock"></i></span>
{% elif toot. visibility == "private"%}
{% elif toot.visibility == "private"%}
<span class="visibility-icon"><i class="fa-solid fa-lock"></i></span>
{% elif toot. visibility == "direct"%}
{% elif toot.visibility == "direct"%}
<span class="visibility-icon"><i class="fa-solid fa-envelope fa-at"></i></span>
{% endif %}
<time>{{ toot.created_at }}</time></span></a>
<time>{{ toot.created_at }}
{% if toot.edited_at != None %}
<strong>*</strong>
{% endif %}
</time></span></a>
</div>
<div class="content">
{% if toot.spoiler_text != "" %}
@ -73,7 +77,9 @@
{% endif %}
</div>
<div class="action-bar">
{% if not toot.is_reblog %}
{% if toot.is_myself %}
<span><i class="fa-solid fa-satellite-dish"></i><a href="{{ url_for('grab', toot_id=toot.id) }}"
target=" _blank">抓取回复</a></span>
<span><i class="fa-solid fa-up-right-and-down-left-from-center"></i><a
href="{{ url_for('context', toot_id=toot.id) }}" target=" _blank">上下文</a></span>
{% endif %}

View file

@ -2,8 +2,9 @@
from mastodon import Mastodon
from BDSM import db
from BDSM.models import Reblog, Toot, Tag, Media, Emoji, Poll
from BDSM.models import Other, Toot, Tag, Media, Emoji, Poll
import sys
import dateutil.parser
def app_register(url):
print("Registering app")
@ -14,7 +15,7 @@ def app_register(url):
scopes=["read"]
)
def archive_toot(url):
def app_login(url):
mastodon = Mastodon(
client_id='pyBDSM_clientcred.secret',
access_token='user.secret',
@ -35,21 +36,26 @@ def archive_toot(url):
# exit in either case
sys.exit(1)
return mastodon, user
def get_context(url, toot_id):
mastodon, user = app_login(url)
acct = mastodon.me().acct
statuses_count = str(mastodon.me().statuses_count)
context = mastodon.status_context(toot_id)
statuses = []
statuses= context['ancestors'] + context['descendants']
toot_process(statuses, acct)
statuses = mastodon.account_statuses(user["id"], limit=20)
# xx = statuses['created_at'].astimezone(tz_cn)
# pprint(xx.strftime("%m/%d/%Y, %H:%M:%S"))
# pprint(statuses)
db.session.commit()
happy_counter = 20
while(True):
def toot_process(statuses, my_acct, duplicates_counter=0):
for status in statuses:
is_reblog = False
is_myself = False
if status['reblog'] != None:
if acct == status['reblog']['account']['acct']:
if my_acct == status['reblog']['account']['acct']:
reblog_myself = True
else:
reblog_myself = False
@ -61,7 +67,7 @@ def archive_toot(url):
created_at = status['created_at']
toot = Toot(id=id, created_at=created_at, reblog_myself=reblog_myself, reblog_id=reblog_id)
db.session.add(toot)
db.session.merge(toot)
# cur.execute('''INSERT OR REPLACE INTO TOOT (id,created_at,reblog_myself,reblog_id) \
# VALUES (?,?,?,?)''',(id, created_at, reblog_myself, reblog_id))
@ -71,10 +77,23 @@ def archive_toot(url):
status = status['reblog']
id = status['id']
acct = status['account']['acct']
if my_acct == acct:
is_myself = True
else:
is_myself = False
url = status['url']
created_at = status['created_at']
edited_at = status['edited_at'] if status['edited_at'] != None else None
if 'edited_at' in status:
edited_at = status['edited_at']
if isinstance(edited_at, str):
edited_at = dateutil.parser.parse(status['edited_at'])
else:
edited_at = None
in_reply_to_id = status['in_reply_to_id']
in_reply_to_account_id = status['in_reply_to_account_id']
content = status['content']
@ -86,7 +105,7 @@ def archive_toot(url):
media = Media(id=media_dict['id'], type=media_dict['type'], url=media_dict['url'],
remote_url=media_dict['remote_url'], description=media_dict['description'])
db.session.add(media)
db.session.merge(media)
# cur.execute('''INSERT OR REPLACE INTO MEDIA (id,type,url,remote_url,description) \
# VALUES (?,?,?,?,?)''',(media_dict['id'], media_dict['type'], media_dict['url'], \
# media_dict['remote_url'], media_dict['description']))
@ -103,7 +122,7 @@ def archive_toot(url):
poll = Poll(id=poll_dict['id'], expires_at=expires_at, multiple=poll_dict['multiple'], \
votes_count=poll_dict['votes_count'], options=options)
db.session.add(poll)
db.session.merge(poll)
# cur.execute('''INSERT OR REPLACE INTO POLL (id,expires_at,multiple,votes_count,options) \
# VALUES (?,?,?,?,?)''',(poll_dict['id'], expires_at, poll_dict['multiple'], \
# poll_dict['votes_count'], options))
@ -127,7 +146,7 @@ def archive_toot(url):
url=emoji['url'],
static_url=emoji['static_url'],
count=count)
db.session.add(emoji_data)
db.session.merge(emoji_data)
# cur.execute('''INSERT INTO EMOJI (shortcode,url,static_url,count) \
# VALUES (?,?,?,?)''', (shortcode, emoji['url'], emoji['static_url'], count))
else:
@ -146,7 +165,7 @@ def archive_toot(url):
if status['tags'] != []:
for tag in status['tags']:
tag_data = Tag(id=id, name=tag['name'])
db.session.add(tag_data)
db.session.merge(tag_data)
# cur.execute('''INSERT OR REPLACE INTO TAG (id,name) \
# VALUES (?,?)''',(id, tag['name']))
@ -160,7 +179,11 @@ def archive_toot(url):
favourites_count = status['favourites_count']
language = status['language']
table = Reblog() if is_reblog else Toot()
if is_reblog or not is_myself:
table = Other()
else:
table = Toot()
table.id=id
table.acct = acct
table.url=url
@ -183,18 +206,41 @@ def archive_toot(url):
table.favourites_count=favourites_count
table.language=language
db.session.add(table)
if Toot.query.get(id) == None or Other.query.get(id) == None:
duplicates_counter += 1
db.session.merge(table)
# sql = f'''INSERT OR REPLACE INTO {table} (id,url,created_at,edited_at,in_reply_to_id,in_reply_to_account_id,content,\
# media_list,spoiler_text,poll_id,emoji_list,visibility,reblogged,favourited,bookmarked,sensitive,reblogs_count,\
# favourites_count,language) \
# VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'''
# cur.execute(sql,(id,url,created_at,edited_at,in_reply_to_id,in_reply_to_account_id,content,media_list,spoiler_text,\
# poll_id,emoji_list,visibility,reblogged,favourited,bookmarked,sensitive,reblogs_count,favourites_count,language))
return duplicates_counter
def archive_toot(url):
mastodon, user = app_login(url)
acct = mastodon.me().acct
statuses_count = str(mastodon.me().statuses_count)
statuses = mastodon.account_statuses(user["id"], limit=20)
# xx = statuses['created_at'].astimezone(tz_cn)
# pprint(xx.strftime("%m/%d/%Y, %H:%M:%S"))
# pprint(statuses)
happy_counter = 20
duplicates_counter = 0
while(True):
duplicates_counter = toot_process(statuses, acct)
db.session.commit()
print(str(happy_counter) + ' / ' + statuses_count)
happy_counter += 20
if duplicates_counter >= 10:
print("检测到重复嘟文达到十次,取消存档……")
break
statuses = mastodon.fetch_next(statuses)
# statuses = None
if statuses == None:

View file

@ -5,8 +5,8 @@ import pytz
from flask import render_template, request, url_for, redirect, flash
from flask_sqlalchemy import Pagination
from BDSM import app, db
from BDSM.models import Media, Settings, Toot, Emoji, Reblog
from BDSM.toot import app_register, archive_toot
from BDSM.models import Media, Settings, Toot, Emoji, Other
from BDSM.toot import app_register, archive_toot, get_context
from mastodon import Mastodon
from types import SimpleNamespace
from datetime import timezone
@ -53,7 +53,8 @@ def search():
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()
toots = process_toot(toots)
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:
@ -70,6 +71,8 @@ def context(toot_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
@ -80,6 +83,17 @@ def context(toot_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':
@ -145,9 +159,6 @@ def archive():
settings = Settings.query.first()
if settings == None:
return redirect(url_for('settings'))
elif len(Toot.query.all()) > 0:
flash('现暂不支持重复存档!') #TODO
return redirect(url_for('index'))
else:
account = settings.account[1:]
username, domain = account.split("@")
@ -173,15 +184,19 @@ def process_toot(toots_):
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 = Reblog.query.get(toot.reblog_id)
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 = []