2021-03-08 11:49:10 -05:00
|
|
|
""" responds to various requests to /.well-know """
|
2020-11-01 14:09:16 -05:00
|
|
|
|
2020-11-01 12:16:49 -05:00
|
|
|
from dateutil.relativedelta import relativedelta
|
2020-11-01 13:42:48 -05:00
|
|
|
from django.http import HttpResponseNotFound
|
2020-02-15 14:31:35 -05:00
|
|
|
from django.http import JsonResponse
|
2021-09-27 19:04:40 -04:00
|
|
|
from django.shortcuts import get_object_or_404
|
2021-03-29 17:36:24 -04:00
|
|
|
from django.template.response import TemplateResponse
|
2020-11-27 19:24:53 -05:00
|
|
|
from django.utils import timezone
|
2021-03-13 13:58:54 -05:00
|
|
|
from django.views.decorators.http import require_GET
|
2020-02-15 14:31:35 -05:00
|
|
|
|
2020-09-21 11:10:37 -04:00
|
|
|
from bookwyrm import models
|
2021-11-18 17:39:22 -05:00
|
|
|
from bookwyrm.settings import DOMAIN, VERSION
|
2020-02-15 14:31:35 -05:00
|
|
|
|
|
|
|
|
2021-03-13 13:58:54 -05:00
|
|
|
@require_GET
|
2020-02-15 14:31:35 -05:00
|
|
|
def webfinger(request):
|
2021-04-26 12:15:42 -04:00
|
|
|
"""allow other servers to ask about a user"""
|
2021-03-08 11:49:10 -05:00
|
|
|
resource = request.GET.get("resource")
|
2021-03-13 13:58:54 -05:00
|
|
|
if not resource or not resource.startswith("acct:"):
|
2020-11-01 13:42:48 -05:00
|
|
|
return HttpResponseNotFound()
|
|
|
|
|
2021-03-08 11:49:10 -05:00
|
|
|
username = resource.replace("acct:", "")
|
2021-09-27 19:04:40 -04:00
|
|
|
user = get_object_or_404(models.User, username__iexact=username)
|
2021-03-08 11:49:10 -05:00
|
|
|
|
|
|
|
return JsonResponse(
|
|
|
|
{
|
2021-09-18 14:32:00 -04:00
|
|
|
"subject": f"acct:{user.username}",
|
2021-03-08 11:49:10 -05:00
|
|
|
"links": [
|
|
|
|
{
|
|
|
|
"rel": "self",
|
|
|
|
"type": "application/activity+json",
|
|
|
|
"href": user.remote_id,
|
2021-11-27 02:32:50 -05:00
|
|
|
},
|
|
|
|
{
|
2021-11-28 05:38:28 -05:00
|
|
|
"rel": "http://ostatus.org/schema/1.0/subscribe",
|
|
|
|
"template": f"https://{DOMAIN}/ostatus_subscribe?acct={{uri}}",
|
|
|
|
},
|
2021-03-08 11:49:10 -05:00
|
|
|
],
|
|
|
|
}
|
|
|
|
)
|
2020-02-15 14:31:35 -05:00
|
|
|
|
|
|
|
|
2021-03-13 13:58:54 -05:00
|
|
|
@require_GET
|
|
|
|
def nodeinfo_pointer(_):
|
2021-04-26 12:15:42 -04:00
|
|
|
"""direct servers to nodeinfo"""
|
2021-03-08 11:49:10 -05:00
|
|
|
return JsonResponse(
|
|
|
|
{
|
|
|
|
"links": [
|
|
|
|
{
|
|
|
|
"rel": "http://nodeinfo.diaspora.software/ns/schema/2.0",
|
2021-09-18 14:32:00 -04:00
|
|
|
"href": f"https://{DOMAIN}/nodeinfo/2.0",
|
2021-03-08 11:49:10 -05:00
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
)
|
2020-02-15 14:31:35 -05:00
|
|
|
|
2020-03-29 03:05:09 -04:00
|
|
|
|
2021-03-13 13:58:54 -05:00
|
|
|
@require_GET
|
|
|
|
def nodeinfo(_):
|
2021-04-26 12:15:42 -04:00
|
|
|
"""basic info about the server"""
|
2021-09-11 10:52:56 -04:00
|
|
|
status_count = models.Status.objects.filter(user__local=True, deleted=False).count()
|
|
|
|
user_count = models.User.objects.filter(is_active=True, local=True).count()
|
2020-11-01 12:16:49 -05:00
|
|
|
|
2020-11-27 19:24:53 -05:00
|
|
|
month_ago = timezone.now() - relativedelta(months=1)
|
2020-11-01 12:16:49 -05:00
|
|
|
last_month_count = models.User.objects.filter(
|
2021-09-11 10:52:56 -04:00
|
|
|
is_active=True, local=True, last_active_date__gt=month_ago
|
2020-11-01 12:16:49 -05:00
|
|
|
).count()
|
|
|
|
|
2020-11-27 19:24:53 -05:00
|
|
|
six_months_ago = timezone.now() - relativedelta(months=6)
|
2020-11-01 12:16:49 -05:00
|
|
|
six_month_count = models.User.objects.filter(
|
2021-09-11 10:52:56 -04:00
|
|
|
is_active=True, local=True, last_active_date__gt=six_months_ago
|
2020-11-01 12:16:49 -05:00
|
|
|
).count()
|
2020-11-08 00:07:07 -05:00
|
|
|
|
|
|
|
site = models.SiteSettings.get()
|
2021-03-08 11:49:10 -05:00
|
|
|
return JsonResponse(
|
|
|
|
{
|
|
|
|
"version": "2.0",
|
|
|
|
"software": {"name": "bookwyrm", "version": VERSION},
|
|
|
|
"protocols": ["activitypub"],
|
|
|
|
"usage": {
|
|
|
|
"users": {
|
|
|
|
"total": user_count,
|
|
|
|
"activeMonth": last_month_count,
|
|
|
|
"activeHalfyear": six_month_count,
|
|
|
|
},
|
|
|
|
"localPosts": status_count,
|
2020-02-15 14:40:21 -05:00
|
|
|
},
|
2021-03-08 11:49:10 -05:00
|
|
|
"openRegistrations": site.allow_registration,
|
|
|
|
}
|
|
|
|
)
|
2020-02-15 14:40:21 -05:00
|
|
|
|
|
|
|
|
2021-03-13 13:58:54 -05:00
|
|
|
@require_GET
|
|
|
|
def instance_info(_):
|
2021-04-26 12:15:42 -04:00
|
|
|
"""let's talk about your cool unique instance"""
|
2021-09-11 10:52:56 -04:00
|
|
|
user_count = models.User.objects.filter(is_active=True, local=True).count()
|
|
|
|
status_count = models.Status.objects.filter(user__local=True, deleted=False).count()
|
2020-11-08 00:07:07 -05:00
|
|
|
|
|
|
|
site = models.SiteSettings.get()
|
2021-11-18 17:39:22 -05:00
|
|
|
logo = site.logo_url
|
2021-03-08 11:49:10 -05:00
|
|
|
return JsonResponse(
|
|
|
|
{
|
|
|
|
"uri": DOMAIN,
|
|
|
|
"title": site.name,
|
2021-09-10 14:44:01 -04:00
|
|
|
"short_description": site.instance_short_description,
|
2021-03-08 11:49:10 -05:00
|
|
|
"description": site.instance_description,
|
2021-09-10 14:44:01 -04:00
|
|
|
"version": VERSION,
|
2021-03-08 11:49:10 -05:00
|
|
|
"stats": {
|
|
|
|
"user_count": user_count,
|
|
|
|
"status_count": status_count,
|
|
|
|
},
|
2021-09-10 14:44:01 -04:00
|
|
|
"thumbnail": logo,
|
2021-03-08 11:49:10 -05:00
|
|
|
"languages": ["en"],
|
|
|
|
"registrations": site.allow_registration,
|
2021-11-16 19:17:38 -05:00
|
|
|
"approval_required": not site.allow_registration
|
|
|
|
and site.allow_invite_requests,
|
2021-09-10 14:44:01 -04:00
|
|
|
"email": site.admin_email,
|
2021-03-08 11:49:10 -05:00
|
|
|
}
|
|
|
|
)
|
2020-03-29 03:05:09 -04:00
|
|
|
|
|
|
|
|
2021-03-13 13:58:54 -05:00
|
|
|
@require_GET
|
|
|
|
def peers(_):
|
2021-04-26 12:15:42 -04:00
|
|
|
"""list of federated servers this instance connects with"""
|
2021-09-11 16:30:27 -04:00
|
|
|
names = models.FederatedServer.objects.filter(status="federated").values_list(
|
|
|
|
"server_name", flat=True
|
2021-09-11 10:52:56 -04:00
|
|
|
)
|
2020-03-29 18:51:43 -04:00
|
|
|
return JsonResponse(list(names), safe=False)
|
2021-03-29 17:36:24 -04:00
|
|
|
|
|
|
|
|
|
|
|
@require_GET
|
|
|
|
def host_meta(request):
|
2021-04-26 12:15:42 -04:00
|
|
|
"""meta of the host"""
|
2021-03-29 17:36:24 -04:00
|
|
|
return TemplateResponse(request, "host_meta.xml", {"DOMAIN": DOMAIN})
|
2021-09-10 19:47:59 -04:00
|
|
|
|
2021-09-27 22:05:13 -04:00
|
|
|
|
2021-09-10 19:47:59 -04:00
|
|
|
@require_GET
|
|
|
|
def opensearch(request):
|
|
|
|
"""Open Search xml spec"""
|
2021-09-27 22:28:50 -04:00
|
|
|
site = models.SiteSettings.get()
|
2021-11-18 17:39:22 -05:00
|
|
|
image = site.favicon_url
|
2021-09-27 22:38:54 -04:00
|
|
|
return TemplateResponse(
|
2021-10-05 11:00:13 -04:00
|
|
|
request, "opensearch.xml", {"image": image, "DOMAIN": DOMAIN}
|
2021-09-27 22:38:54 -04:00
|
|
|
)
|