From 71cfe74f9f3211f475452f2e387daac1dc23bcd7 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 30 Dec 2024 15:34:18 -0500 Subject: [PATCH] index posts edited/created from Mastodon API --- common/models/index.py | 4 +- journal/management/commands/journal.py | 4 +- journal/models/index.py | 6 +++ neodb-takahe | 2 +- social/templates/feed_events.html | 4 +- social/views.py | 4 +- takahe/ap_handlers.py | 60 ++++++++++++++++++++------ 7 files changed, 61 insertions(+), 23 deletions(-) diff --git a/common/models/index.py b/common/models/index.py index 7e94a401..1a57226c 100644 --- a/common/models/index.py +++ b/common/models/index.py @@ -118,8 +118,8 @@ class Index: def delete_collection(self): self.write_collection.delete() - def update_schema(self): - self.write_collection.update(self.get_schema()) + def update_schema(self, schema: dict): + self.write_collection.update(schema) def initialize_collection(self, max_wait=5) -> bool: try: diff --git a/journal/management/commands/journal.py b/journal/management/commands/journal.py index 61205a40..36cd9860 100644 --- a/journal/management/commands/journal.py +++ b/journal/management/commands/journal.py @@ -157,8 +157,8 @@ class Command(BaseCommand): self.stdout.write(self.style.SUCCESS("deleted.")) case "idx-alt": - index.update_schema() - self.stdout.write(self.style.SUCCESS("updated.")) + # index.update_schema() + self.stdout.write(self.style.SUCCESS("not implemented.")) case "idx-init": index.initialize_collection() diff --git a/journal/models/index.py b/journal/models/index.py index 98200097..4f2ede26 100644 --- a/journal/models/index.py +++ b/journal/models/index.py @@ -137,12 +137,14 @@ class JournalIndex(Index): "type": "string[]", "locale": "zh", "optional": True, + # "store": False, }, { "name": "content", "type": "string[]", "locale": "zh", "optional": True, + # "store": False, }, { "name": "shelf_type", @@ -264,6 +266,10 @@ class JournalIndex(Index): def delete_by_post(self, post_ids): return self.delete_docs("post_id", post_ids) + def replace_posts(self, posts: Iterable[Post]): + docs = self.posts_to_docs(posts) + self.replace_docs(docs) + def replace_pieces(self, pieces: "Iterable[Piece] | QuerySet[Piece]"): if isinstance(pieces, QuerySet): pids = pieces.values_list("pk", flat=True) diff --git a/neodb-takahe b/neodb-takahe index df6f939a..616e9138 160000 --- a/neodb-takahe +++ b/neodb-takahe @@ -1 +1 @@ -Subproject commit df6f939a73512ac8a8c01e0e78bc0d5e8ffe3e6d +Subproject commit 616e91382829866531c62e1b24f0e6e4595ab27d diff --git a/social/templates/feed_events.html b/social/templates/feed_events.html index 24ba272b..1d17f88a 100644 --- a/social/templates/feed_events.html +++ b/social/templates/feed_events.html @@ -125,7 +125,7 @@ {% if forloop.last %}
@@ -133,7 +133,7 @@ {% endif %} {% empty %}
- {% if request.GET.last or request.GET.nextpage %} + {% if request.GET.last or page > 1 %} {% trans 'nothing more.' %} {% elif request.GET.q %} {% trans 'no matching activities.' %} diff --git a/social/views.py b/social/views.py index 660ea3f5..f37e4f1e 100644 --- a/social/views.py +++ b/social/views.py @@ -78,7 +78,7 @@ def data(request): typ = int_(request.GET.get("typ", 0)) q = request.GET.get("q") identity_id = request.user.identity.pk - page = int_(request.GET.get("page", 1)) + page = int_(request.GET.get("lastpage")) + 1 if q: q = QueryParser(request.GET.get("q", default="")) index = JournalIndex.instance() @@ -149,7 +149,7 @@ def data(request): return render( request, "feed_events.html", - {"feed_type": typ, "events": events, "nextpage": page + 1}, + {"feed_type": typ, "events": events, "page": page}, ) diff --git a/takahe/ap_handlers.py b/takahe/ap_handlers.py index 48a9fc98..31c12df6 100644 --- a/takahe/ap_handlers.py +++ b/takahe/ap_handlers.py @@ -14,6 +14,7 @@ from journal.models import ( Review, ShelfMember, ) +from journal.models.index import JournalIndex from users.middlewares import activate_language_for_user from users.models.apidentity import APIdentity @@ -92,30 +93,61 @@ def _get_or_create_item(item_obj) -> Item | None: def post_created(pk, post_data): - return post_fetched(pk, post_data) + return _post_fetched(pk, True, post_data) def post_edited(pk, post_data): - return post_fetched(pk, post_data) + return _post_fetched(pk, True, post_data, False) def post_fetched(pk, post_data): - post = Post.objects.get(pk=pk) + return _post_fetched(pk, False, post_data, True) + + +def _post_fetched(pk, local, post_data, create: bool | None = None): + post: Post = Post.objects.get(pk=pk) owner = Takahe.get_or_create_remote_apidentity(post.author) - activate_language_for_user(owner.user) - if not post.type_data and not post_data: - logger.warning(f"Post {post} has no type_data") - return - ap_objects = post_data or post.type_data.get("object", {}) - items = _parse_items(ap_objects.get("tag")) - pieces = _parse_piece_objects(ap_objects.get("relatedWith")) - logger.info(f"Post {post} has items {items} and pieces {pieces}") + if local: + activate_language_for_user(owner.user) + reply_to = post.in_reply_to_post() + items = [] + pieces = [] + if post_data and "raw_content" in post_data: + # Local post, extract info for Note if possible + if ( + reply_to + and reply_to.author_id == post.author_id + and reply_to.type_data + and "object" in reply_to.type_data + and "relatedWith" in reply_to.type_data["object"] + ): + items = _parse_items(reply_to.type_data["object"].get("tag", [])) + elif ( + not create + and post.type_data + and "object" in post.type_data + and "relatedWith" in post.type_data["object"] + ): + items = _parse_items(post.type_data["object"].get("tag", [])) + pieces = [{"type": "Note", "content": post_data["raw_content"]}] + if not items or not pieces: + # Local post has no related items or usable pieces, update index and move on + JournalIndex.instance().replace_posts([post]) + return + else: + if not post.type_data and not post_data: + logger.warning(f"Remote post {post} has no type_data") + return + ap_objects = post_data or post.type_data.get("object", {}) + items = _parse_items(ap_objects.get("tag")) + pieces = _parse_piece_objects(ap_objects.get("relatedWith")) if len(items) == 0: - logger.warning(f"Post {post} has no remote items") + logger.warning(f"Post {post} has no items") return elif len(items) > 1: - logger.warning(f"Post {post} has more than one remote item") + logger.warning(f"Post {post} has more than one item") return + logger.info(f"Post {post} has items {items} and pieces {pieces}") item = _get_or_create_item(items[0]) if not item: logger.warning(f"Post {post} has no local item matched or created") @@ -128,7 +160,7 @@ def post_fetched(pk, post_data): cls.update_by_ap_object(owner, item, p, post) -def post_deleted(pk, post_data): +def post_deleted(pk, local, post_data): for piece in Piece.objects.filter(posts__id=pk): if piece.local and piece.__class__ != Note: # no delete other than Note, for backward compatibility, should reconsider later