fix detail page 502 step 1: async pull mastodon follow/block/mute list

This commit is contained in:
Your Name 2021-12-14 16:06:27 -05:00
parent a3960d4639
commit 879c21ca05
5 changed files with 106 additions and 0 deletions

View file

@ -198,6 +198,28 @@ def random_string_generator(n):
return ''.join(random.choice(s) for i in range(n))
def verify_account(site, token):
url = 'https://' + site + API_VERIFY_ACCOUNT
response = get(url, headers={'User-Agent': 'NeoDB/1.0', 'Authorization': f'Bearer {token}'})
return response.status_code, response.json() if response.status_code == 200 else None
def get_related_acct_list(site, token, api):
url = 'https://' + site + api
results = []
while url:
response = get(url, headers={'User-Agent': 'NeoDB/1.0', 'Authorization': f'Bearer {token}'})
url = None
if response.status_code == 200:
results.extend(map(lambda u: u['acct'] if u['acct'].find('@') != -1 else u['acct'] + site, response.json()))
if 'Link' in response.headers:
for ls in response.headers['Link'].split(','):
li = ls.strip().split(';')
if li[1].strip() == 'rel="next"':
url = li[0].strip().replace('>', '').replace('<', '')
return results
class TootVisibilityEnum:
PUBLIC = 'public'
PRIVATE = 'private'

View file

@ -0,0 +1,21 @@
from django.core.management.base import BaseCommand
from users.models import User
from django.contrib.sessions.models import Session
class Command(BaseCommand):
help = 'Backfill Mastodon data if missing'
def handle(self, *args, **options):
for session in Session.objects.order_by('-expire_date'):
uid = session.get_decoded().get('_auth_user_id')
token = session.get_decoded().get('oauth_token')
if uid and token:
user = User.objects.get(pk=uid)
if user.mastodon_token:
print(f'skip {user}')
continue
user.mastodon_token = token
user.refresh_mastodon_data()
user.save()
print(f"Refreshed {user}")

View file

@ -0,0 +1,24 @@
from django.core.management.base import BaseCommand
from users.models import User
from datetime import timedelta
from django.utils import timezone
class Command(BaseCommand):
help = 'Refresh Mastodon data for all users if not updated in last 24h'
def handle(self, *args, **options):
count = 0
for user in User.objects.filter(mastodon_last_refresh__lt=timezone.now() - timedelta(hours=24)):
if user.mastodon_token:
print(f"Refreshing {user}")
if user.refresh_mastodon_data():
print(f"Refreshed {user}")
count += 1
else:
print(f"Refresh failed for {user}")
user.save()
else:
print(f'Missing token for {user}')
print(f'{count} users updated')

View file

@ -7,6 +7,7 @@ from django.core.serializers.json import DjangoJSONEncoder
from django.utils.translation import ugettext_lazy as _
from common.utils import GenerateDateUUIDMediaFilePath
from django.conf import settings
from mastodon.api import *
def report_image_path(instance, filename):
@ -24,6 +25,14 @@ class User(AbstractUser):
mastodon_id = models.CharField(max_length=100, blank=False)
# mastodon domain name, eg donotban.com
mastodon_site = models.CharField(max_length=100, blank=False)
mastodon_token = models.CharField(max_length=100, default='')
mastodon_locked = models.BooleanField(default=False)
mastodon_followers = models.JSONField(default=list)
mastodon_following = models.JSONField(default=list)
mastodon_mutes = models.JSONField(default=list)
mastodon_blocks = models.JSONField(default=list)
mastodon_account = models.JSONField(default=dict)
mastodon_last_refresh = models.DateTimeField(default=timezone.now)
# store the latest read announcement id,
# every time user read the announcement update this field
read_announcement_index = models.PositiveIntegerField(default=0)
@ -42,6 +51,25 @@ class User(AbstractUser):
def __str__(self):
return self.username + '@' + self.mastodon_site
def refresh_mastodon_data(self):
""" Try refresh account data from mastodon server, return true if refreshed successfully, note it will not save to db """
self.mastodon_last_refresh = timezone.now()
code, mastodon_account = verify_account(self.mastodon_site, self.mastodon_token)
updated = False
if mastodon_account:
self.mastodon_account = mastodon_account
self.mastodon_locked = mastodon_account['locked']
# self.mastodon_token = token
# user.mastodon_id = mastodon_account['id']
self.mastodon_followers = get_related_acct_list(self.mastodon_site, self.mastodon_token, f'/api/v1/accounts/{self.mastodon_id}/followers')
self.mastodon_following = get_related_acct_list(self.mastodon_site, self.mastodon_token, f'/api/v1/accounts/{self.mastodon_id}/following')
self.mastodon_mutes = get_related_acct_list(self.mastodon_site, self.mastodon_token, '/api/v1/mutes')
self.mastodon_blocks = get_related_acct_list(self.mastodon_site, self.mastodon_token, '/api/v1/blocks')
updated = True
elif code == 401:
self.mastodon_token = ''
return updated
class Preference(models.Model):
user = models.OneToOneField(User, models.CASCADE, primary_key=True)

View file

@ -838,10 +838,21 @@ def manage_report(request):
# Utils
########################################
def refresh_mastodon_data_task(user, token):
user.mastodon_token = token
if user.refresh_mastodon_data():
user.save()
print(f"{user} mastodon data refreshed")
else:
print(f"{user} mastodon data refresh failed")
def auth_login(request, user, token):
""" Decorates django ``login()``. Attach token to session."""
request.session['oauth_token'] = token
auth.login(request, user)
# refresh_mastodon_data_task(user, token)
django_rq.get_queue('mastodon').enqueue(refresh_mastodon_data_task, user, token)
def auth_logout(request):