summaryrefslogtreecommitdiffstats
path: root/users
diff options
context:
space:
mode:
authorAndrew Godwin2022-11-05 22:49:25 -0600
committerAndrew Godwin2022-11-05 22:49:25 -0600
commita2404e01cdbeef2ba332e147a5f2f1ca0a0310d7 (patch)
tree9aa1ae2ffad20a7afe8eac8cbe99ab9a53dcc0ca /users
parent56de2362a01089c8a5ca3c6e1affcade00ffdfce (diff)
downloadtakahe-a2404e01cdbeef2ba332e147a5f2f1ca0a0310d7.tar.gz
takahe-a2404e01cdbeef2ba332e147a5f2f1ca0a0310d7.tar.bz2
takahe-a2404e01cdbeef2ba332e147a5f2f1ca0a0310d7.zip
Queuing system and lazy profile fetch
Diffstat (limited to 'users')
-rw-r--r--users/models/identity.py26
-rw-r--r--users/views/identity.py5
2 files changed, 30 insertions, 1 deletions
diff --git a/users/models/identity.py b/users/models/identity.py
index c20ef60..5586f27 100644
--- a/users/models/identity.py
+++ b/users/models/identity.py
@@ -59,6 +59,19 @@ class Identity(models.Model):
fetched = models.DateTimeField(null=True, blank=True)
deleted = models.DateTimeField(null=True, blank=True)
+ @classmethod
+ def by_handle(cls, handle, create=True):
+ if handle.startswith("@"):
+ raise ValueError("Handle must not start with @")
+ if "@" not in handle:
+ raise ValueError("Handle must contain domain")
+ try:
+ return cls.objects.filter(handle=handle).get()
+ except cls.DoesNotExist:
+ if create:
+ return cls.objects.create(handle=handle, local=False)
+ return None
+
@property
def short_handle(self):
if self.handle.endswith("@" + settings.DEFAULT_DOMAIN):
@@ -69,6 +82,17 @@ class Identity(models.Model):
def domain(self):
return self.handle.split("@", 1)[1]
+ @property
+ def data_age(self) -> float:
+ """
+ How old our copy of this data is, in seconds
+ """
+ if self.local:
+ return 0
+ if self.fetched is None:
+ return 10000000000
+ return (timezone.now() - self.fetched).total_seconds()
+
def generate_keypair(self):
private_key = rsa.generate_private_key(
public_exponent=65537,
@@ -104,6 +128,7 @@ class Identity(models.Model):
response = await client.get(
f"https://{self.domain}/.well-known/webfinger?resource=acct:{self.handle}",
headers={"Accept": "application/json"},
+ follow_redirects=True,
)
if response.status_code >= 400:
return False
@@ -126,6 +151,7 @@ class Identity(models.Model):
response = await client.get(
self.actor_uri,
headers={"Accept": "application/json"},
+ follow_redirects=True,
)
if response.status_code >= 400:
return False
diff --git a/users/views/identity.py b/users/views/identity.py
index fff521b..456fead 100644
--- a/users/views/identity.py
+++ b/users/views/identity.py
@@ -10,6 +10,7 @@ from django.views.decorators.csrf import csrf_exempt
from django.views.generic import FormView, TemplateView, View
from core.forms import FormHelper
+from miniq.models import Task
from users.models import Identity
from users.shortcuts import by_handle_or_404
@@ -19,8 +20,10 @@ class ViewIdentity(TemplateView):
template_name = "identity/view.html"
def get_context_data(self, handle):
- identity = by_handle_or_404(self.request, handle, local=False)
+ identity = Identity.by_handle(handle=handle)
statuses = identity.statuses.all()[:100]
+ if identity.data_age > settings.IDENTITY_MAX_AGE:
+ Task.submit("identity_fetch", identity.handle)
return {
"identity": identity,
"statuses": statuses,