diff --git a/boofilsic/settings.py b/boofilsic/settings.py
index 10d17464..e747f623 100644
--- a/boofilsic/settings.py
+++ b/boofilsic/settings.py
@@ -102,6 +102,9 @@ env = environ.FileAwareEnv(
DISCORD_WEBHOOKS=(dict, {"user-report": None}),
# Slack API token, for sending exceptions to Slack, may deprecate in future
SLACK_API_TOKEN=(str, ""),
+ THREADS_APP_ID=(str, ""),
+ THREADS_APP_SECRET=(str, ""),
+ BLUESKY_LOGIN_ENABLED=(bool, False),
# SSL only, better be True for production security
SSL_ONLY=(bool, False),
NEODB_SENTRY_DSN=(str, ""),
@@ -174,8 +177,11 @@ elif _parsed_email_url.scheme:
else:
ENABLE_LOGIN_EMAIL = False
-ENABLE_LOGIN_THREADS = False
-ENABLE_LOGIN_BLUESKY = False
+
+THREADS_APP_ID = env("THREADS_APP_ID")
+THREADS_APP_SECRET = env("THREADS_APP_SECRET")
+
+BLUESKY_LOGIN_ENABLED = env("BLUESKY_LOGIN_ENABLED")
SITE_DOMAIN = env("NEODB_SITE_DOMAIN").lower()
SITE_INFO = {
diff --git a/boofilsic/urls.py b/boofilsic/urls.py
index fe54996a..25f9967b 100644
--- a/boofilsic/urls.py
+++ b/boofilsic/urls.py
@@ -27,9 +27,10 @@ urlpatterns = [
path("login/", login),
path("markdownx/", include("markdownx.urls")),
path("account/", include("users.urls")),
+ path("account/", include("mastodon.urls")),
path(
"users/connect/",
- RedirectView.as_view(url="/account/connect", query_string=True),
+ RedirectView.as_view(url="/mastodon/login", query_string=True),
),
path(
"auth/edit", # some apps like elk will use this url
diff --git a/common/setup.py b/common/setup.py
index 6fecee50..e4536cfd 100644
--- a/common/setup.py
+++ b/common/setup.py
@@ -1,4 +1,3 @@
-import django
from django.conf import settings
from django.core.checks import Error, Warning
from loguru import logger
@@ -7,7 +6,6 @@ from catalog.search.models import Indexer
from common.models import JobManager
from takahe.models import Config as TakaheConfig
from takahe.models import Domain as TakaheDomain
-from takahe.models import Follow as TakaheFollow
from takahe.models import Identity as TakaheIdentity
from takahe.models import Relay as TakaheRelay
from takahe.models import User as TakaheUser
diff --git a/common/templates/_header.html b/common/templates/_header.html
index 900e3f51..0eeebac8 100644
--- a/common/templates/_header.html
+++ b/common/templates/_header.html
@@ -119,13 +119,6 @@
-{% if request.user.is_authenticated and not request.user.mastodon_username and not request.user.username %}
-
-{% endif %}
{% if messages %}
{% for message in messages %}
diff --git a/common/templates/_sidebar.html b/common/templates/_sidebar.html
index 95efb978..07046028 100644
--- a/common/templates/_sidebar.html
+++ b/common/templates/_sidebar.html
@@ -54,16 +54,26 @@
{% endif %}
- {% if identity.user.mastodon_account %}
+ {% if identity.user.mastodon %}
-
+ title="@{{ identity.user.mastodon.handle }}">
{% endif %}
+ {% if identity.user.threads %}
+
+
+
+
+
+ {% endif %}
{% elif request.user.is_authenticated %}
{% include 'users/profile_actions.html' %}
{% endif %}
diff --git a/common/templatetags/oauth_token.py b/common/templatetags/oauth_token.py
deleted file mode 100644
index 06a4b83d..00000000
--- a/common/templatetags/oauth_token.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from django import template
-from django.conf import settings
-from django.utils.html import format_html
-
-register = template.Library()
-
-
-class OAuthTokenNode(template.Node):
- def render(self, context):
- request = context.get("request")
- oauth_token = request.user.mastodon_token if request else ""
- return format_html(oauth_token)
-
-
-@register.tag
-def oauth_token(parser, token):
- return OAuthTokenNode()
diff --git a/common/views.py b/common/views.py
index bf4b056e..d01e8e67 100644
--- a/common/views.py
+++ b/common/views.py
@@ -11,6 +11,12 @@ from takahe.utils import Takahe
from .api import api
+def render_error(request, title, message=""):
+ return render(
+ request, "common/error.html", {"msg": title, "secondary_msg": message}
+ )
+
+
@login_required
def me(request):
if not request.user.registration_complete:
diff --git a/compose.yml b/compose.yml
index c04f2b19..f8b10751 100644
--- a/compose.yml
+++ b/compose.yml
@@ -67,6 +67,9 @@ x-shared:
TAKAHE_VAPID_PRIVATE_KEY:
TAKAHE_DEBUG: ${NEODB_DEBUG:-False}
TAKAHE_VENV: /takahe-venv
+ THREADS_APP_ID:
+ THREADS_APP_SECRET:
+ BLUESKY_LOGIN_ENABLED:
SPOTIFY_API_KEY:
TMDB_API_V3_KEY:
GOOGLE_API_KEY:
diff --git a/docs/install.md b/docs/install.md
index 8d4b83d1..2e841847 100644
--- a/docs/install.md
+++ b/docs/install.md
@@ -80,6 +80,12 @@ You should see the same JSON response as above, and the site is now accessible t
## Register an account and make it admin
+If you have email sender properly configured, use this command to create an admin with a verified email (use any password as it won't be saved)
+
+```
+docker compose --profile production run --rm shell neodb-manage createsuperuser
+```
+
Now open `https://yourdomain.tld` in your browser and register an account, assuming username `admin`
add the following line to `.env` to make it an admin account:
diff --git a/journal/models/common.py b/journal/models/common.py
index 7235d1ab..70535bf1 100644
--- a/journal/models/common.py
+++ b/journal/models/common.py
@@ -8,14 +8,14 @@ from typing import TYPE_CHECKING, Any, Self
# from deepmerge import always_merger
from django.conf import settings
from django.core.signing import b62_decode, b62_encode
-from django.db import connection, models
-from django.db.models import Avg, CharField, Count, Q
+from django.db import models
+from django.db.models import CharField, Q
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from loguru import logger
from polymorphic.models import PolymorphicModel
-from catalog.common.models import AvailableItemCategory, Item, ItemCategory
+from catalog.common.models import Item, ItemCategory
from catalog.models import item_categories, item_content_types
from takahe.utils import Takahe
from users.models import APIdentity, User
@@ -316,7 +316,7 @@ class Piece(PolymorphicModel, UserOwnedObjectMixin):
def sync_to_mastodon(self, delete_existing=False):
user = self.owner.user
- if not user.mastodon_site:
+ if not user.mastodon:
return
if user.preference.mastodon_repost_mode == 1:
if delete_existing:
diff --git a/journal/models/mark.py b/journal/models/mark.py
index 5cbde9eb..560a85b7 100644
--- a/journal/models/mark.py
+++ b/journal/models/mark.py
@@ -6,7 +6,7 @@ from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from loguru import logger
-from catalog.models import Item, ItemCategory
+from catalog.models import Item
from mastodon.models import get_spoiler_text
from takahe.utils import Takahe
from users.models import APIdentity, User
@@ -309,8 +309,11 @@ class Mark:
post_as_new = shelf_type != last_shelf_type or visibility != last_visibility
classic_crosspost = user.preference.mastodon_repost_mode == 1
append = (
- f"@{user.mastodon_acct}\n"
- if visibility > 0 and share_to_mastodon and not classic_crosspost
+ f"@{user.mastodon.handle}\n"
+ if visibility > 0
+ and share_to_mastodon
+ and not classic_crosspost
+ and user.mastodon
else ""
)
post = Takahe.post_mark(self, post_as_new, append)
diff --git a/journal/templates/collection.html b/journal/templates/collection.html
index a634e1ad..db5ff798 100644
--- a/journal/templates/collection.html
+++ b/journal/templates/collection.html
@@ -58,7 +58,7 @@