From 6710e7a95099f588cf1e19933229cb21b8615938 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 20 Aug 2023 21:46:53 +0000 Subject: [PATCH] share to mastodon = reboost --- boofilsic/settings.py | 9 ++++++++ journal/models/mark.py | 24 ++++++++++++++++---- mastodon/api.py | 50 ++++++++++++++++++++++++++++++++++++++++++ takahe/utils.py | 23 ++++++++++--------- 4 files changed, 92 insertions(+), 14 deletions(-) diff --git a/boofilsic/settings.py b/boofilsic/settings.py index 6b579557..5ab46f96 100644 --- a/boofilsic/settings.py +++ b/boofilsic/settings.py @@ -341,6 +341,15 @@ if DEBUG: REDIS_HOST = os.environ.get("NEODB_REDIS_HOST", "127.0.0.1") REDIS_PORT = int(os.environ.get("NEODB_REDIS_PORT", 6379)) REDIS_DB = int(os.environ.get("NEODB_REDIS_DB", 0)) +CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}", + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + }, + } +} RQ_QUEUES = { q: { diff --git a/journal/models/mark.py b/journal/models/mark.py index 684fe836..48499f5a 100644 --- a/journal/models/mark.py +++ b/journal/models/mark.py @@ -21,6 +21,7 @@ from catalog.common import jsondata from catalog.common.models import Item, ItemCategory from catalog.common.utils import DEFAULT_ITEM_COVER, piece_cover_path from catalog.models import * +from mastodon.api import boost_toot from takahe.utils import Takahe from users.models import APIdentity @@ -88,8 +89,8 @@ class Mark: if self.shelfmember: return self.shelfmember.visibility else: - logger.warning(f"no shelfmember for mark {self.owner}, {self.item}") - return 2 + # mark not saved yet, return default visibility for editing ui + return self.owner.preference.default_visibility @cached_property def tags(self) -> list[str]: @@ -181,8 +182,23 @@ class Mark: Rating.update_item_rating(self.item, self.owner, rating_grade, visibility) self.rating_grade = rating_grade - if post_to_feed: - Takahe.post_mark(self, post_as_new) + post = Takahe.post_mark(self, post_as_new) if post_to_feed else None + if share_to_mastodon and post: + if ( + self.owner.user + and self.owner.user.mastodon_token + and self.owner.user.mastodon_site + ): + # TODO: make this a async task, given post to mastodon is slow and takahe post fanout may take time + if boost_toot( + self.owner.user.mastodon_site, + self.owner.user.mastodon_token, + post.url, + ): + return True + return False + else: + return True def delete(self): # self.logs.delete() # When deleting a mark, all logs of the mark are deleted first. diff --git a/mastodon/api.py b/mastodon/api.py index 0f5f1d69..7fd1149a 100644 --- a/mastodon/api.py +++ b/mastodon/api.py @@ -67,6 +67,56 @@ def get_api_domain(domain): # low level api below +def boost_toot(site, token, toot_url): + domain = get_api_domain(site) + headers = { + "User-Agent": USER_AGENT, + "Authorization": f"Bearer {token}", + } + url = ( + "https://" + + domain + + API_SEARCH + + "?type=statuses&resolve=true&q=" + + quote(toot_url) + ) + try: + response = get(url, headers=headers) + if response.status_code != 200: + logger.error(f"Error search {toot_url} on {domain} {response.status_code}") + return None + j = response.json() + if "statuses" in j and len(j["statuses"]) > 0: + s = j["statuses"][0] + if s["uri"] != toot_url and s["url"] != toot_url: + logger.error( + f"Error status url mismatch {s['uri']} or {s['uri']} != {toot_url}" + ) + return None + if s["reblogged"]: + logger.info(f"Already boosted {toot_url}") + # TODO unboost and boost again? + return None + url = ( + "https://" + + domain + + API_PUBLISH_TOOT + + "/" + + j["statuses"][0]["id"] + + "/reblog" + ) + response = post(url, headers=headers) + if response.status_code != 200: + logger.error( + f"Error search {toot_url} on {domain} {response.status_code}" + ) + return None + return response.json() + except Exception: + logger.error(f"Error search {toot_url} on {domain}") + return None + + def post_toot( site, content, diff --git a/takahe/utils.py b/takahe/utils.py index c44368f0..b2f7d9b0 100644 --- a/takahe/utils.py +++ b/takahe/utils.py @@ -345,7 +345,7 @@ class Takahe: post_pk: int | None = None, post_time: datetime.datetime | None = None, reply_to_pk: int | None = None, - ) -> int | None: + ) -> Post | None: identity = Identity.objects.get(pk=author_pk) post = ( Post.objects.filter(author=identity, pk=post_pk).first() @@ -373,7 +373,7 @@ class Takahe: published=post_time, reply_to=reply_to_post, ) - return post.pk if post else None + return post @staticmethod def get_post(post_pk: int) -> str | None: @@ -390,7 +390,7 @@ class Takahe: Post.objects.filter(pk=mark.shelfmember.post_id).update(state="deleted") @staticmethod - def post_mark(mark, share_as_new_post: bool): + def post_mark(mark, share_as_new_post: bool) -> Post | None: from catalog.common import ItemCategory from takahe.utils import Takahe @@ -427,7 +427,7 @@ class Takahe: v = Takahe.Visibilities.public else: v = Takahe.Visibilities.unlisted - post_pk = Takahe.post( + post = Takahe.post( mark.owner.pk, pre_conetent, content, @@ -436,15 +436,18 @@ class Takahe: None if share_as_new_post else mark.shelfmember.post_id, mark.shelfmember.created_time, ) - if post_pk != mark.shelfmember.post_id: - mark.shelfmember.post_id = post_pk + if not post: + return + if post.pk != mark.shelfmember.post_id: + mark.shelfmember.post_id = post.pk mark.shelfmember.save(update_fields=["post_id"]) - if mark.comment and post_pk != mark.comment.post_id: - mark.comment.post_id = post_pk + if mark.comment and post.pk != mark.comment.post_id: + mark.comment.post_id = post.pk mark.comment.save(update_fields=["post_id"]) - if mark.rating and post_pk != mark.rating.post_id: - mark.rating.post_id = post_pk + if mark.rating and post.pk != mark.rating.post_id: + mark.rating.post_id = post.pk mark.rating.save(update_fields=["post_id"]) + return post @staticmethod def interact_post(post_pk: int, identity_pk: int, type: str):