fix detail page 502 step 1: async pull mastodon follow/block/mute list
This commit is contained in:
parent
a3960d4639
commit
879c21ca05
5 changed files with 106 additions and 0 deletions
|
@ -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'
|
||||
|
|
21
users/management/commands/backfill_mastodon.py
Normal file
21
users/management/commands/backfill_mastodon.py
Normal 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}")
|
24
users/management/commands/refresh_mastodon.py
Normal file
24
users/management/commands/refresh_mastodon.py
Normal 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')
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Add table
Reference in a new issue