mirror of
				https://git.sr.ht/~tsileo/microblog.pub
				synced 2025-06-05 21:59:23 +02:00 
			
		
		
		
	Improve Delete handling
This commit is contained in:
		
							
								
								
									
										78
									
								
								app/boxes.py
									
									
									
									
									
								
							
							
						
						
									
										78
									
								
								app/boxes.py
									
									
									
									
									
								
							| @@ -629,12 +629,20 @@ async def _get_followers(db_session: AsyncSession) -> list[models.Follower]: | |||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
| async def _get_followers_recipients(db_session: AsyncSession) -> set[str]: | async def _get_followers_recipients( | ||||||
|  |     db_session: AsyncSession, | ||||||
|  |     skip_actors: list[models.Actor] | None = None, | ||||||
|  | ) -> set[str]: | ||||||
|     """Returns all the recipients from the local follower collection.""" |     """Returns all the recipients from the local follower collection.""" | ||||||
|  |     actor_ap_ids_to_skip = [] | ||||||
|  |     if skip_actors: | ||||||
|  |         actor_ap_ids_to_skip = [actor.ap_id for actor in skip_actors] | ||||||
|  |  | ||||||
|     followers = await _get_followers(db_session) |     followers = await _get_followers(db_session) | ||||||
|     return { |     return { | ||||||
|         follower.actor.shared_inbox_url or follower.actor.inbox_url  # type: ignore |         follower.actor.shared_inbox_url or follower.actor.inbox_url  # type: ignore | ||||||
|         for follower in followers |         for follower in followers | ||||||
|  |         if follower.actor.ap_id not in actor_ap_ids_to_skip | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -715,6 +723,7 @@ async def _handle_delete_activity( | |||||||
|     from_actor: models.Actor, |     from_actor: models.Actor, | ||||||
|     delete_activity: models.InboxObject, |     delete_activity: models.InboxObject, | ||||||
|     ap_object_to_delete: models.InboxObject | None, |     ap_object_to_delete: models.InboxObject | None, | ||||||
|  |     forwarded_by_actor: models.Actor | None, | ||||||
| ) -> None: | ) -> None: | ||||||
|     if ap_object_to_delete is None: |     if ap_object_to_delete is None: | ||||||
|         logger.info( |         logger.info( | ||||||
| @@ -731,33 +740,26 @@ async def _handle_delete_activity( | |||||||
|         ) |         ) | ||||||
|         return |         return | ||||||
|  |  | ||||||
|     # If it's a local replies, it was forwarded, so we also need to forward |  | ||||||
|     # the Delete activity if possible |  | ||||||
|     if ( |  | ||||||
|         delete_activity.has_ld_signature |  | ||||||
|         and ap_object_to_delete.in_reply_to |  | ||||||
|         and ap_object_to_delete.in_reply_to.startswith(BASE_URL) |  | ||||||
|     ): |  | ||||||
|         logger.info("Forwarding Delete activity as it's a local reply") |  | ||||||
|         recipients = await _get_followers_recipients(db_session) |  | ||||||
|         for rcp in recipients: |  | ||||||
|             await new_outgoing_activity( |  | ||||||
|                 db_session, |  | ||||||
|                 rcp, |  | ||||||
|                 outbox_object_id=None, |  | ||||||
|                 inbox_object_id=delete_activity.id, |  | ||||||
|             ) |  | ||||||
|  |  | ||||||
|     logger.info(f"Deleting {ap_object_to_delete.ap_type}/{ap_object_to_delete.ap_id}") |     logger.info(f"Deleting {ap_object_to_delete.ap_type}/{ap_object_to_delete.ap_id}") | ||||||
|  |     await _revert_side_effect_for_deleted_object( | ||||||
|  |         db_session, | ||||||
|  |         delete_activity, | ||||||
|  |         ap_object_to_delete, | ||||||
|  |         forwarded_by_actor, | ||||||
|  |     ) | ||||||
|     ap_object_to_delete.is_deleted = True |     ap_object_to_delete.is_deleted = True | ||||||
|  |  | ||||||
|     await _revert_side_effect_for_deleted_object(db_session, ap_object_to_delete) |     await db_session.flush() | ||||||
|  |  | ||||||
|  |  | ||||||
| async def _revert_side_effect_for_deleted_object( | async def _revert_side_effect_for_deleted_object( | ||||||
|     db_session: AsyncSession, |     db_session: AsyncSession, | ||||||
|  |     delete_activity: models.InboxObject, | ||||||
|     deleted_ap_object: models.InboxObject, |     deleted_ap_object: models.InboxObject, | ||||||
|  |     forwarded_by_actor: models.Actor | None, | ||||||
| ) -> None: | ) -> None: | ||||||
|  |     is_delete_needs_to_be_forwarded = False | ||||||
|  |  | ||||||
|     # Decrement the replies counter if needed |     # Decrement the replies counter if needed | ||||||
|     if deleted_ap_object.in_reply_to: |     if deleted_ap_object.in_reply_to: | ||||||
|         replied_object = await get_anybox_object_by_ap_id( |         replied_object = await get_anybox_object_by_ap_id( | ||||||
| @@ -766,6 +768,10 @@ async def _revert_side_effect_for_deleted_object( | |||||||
|         ) |         ) | ||||||
|         if replied_object: |         if replied_object: | ||||||
|             if replied_object.is_from_outbox: |             if replied_object.is_from_outbox: | ||||||
|  |                 # It's a local reply that was likely forwarded, the Delete | ||||||
|  |                 # also needs to be forwarded | ||||||
|  |                 is_delete_needs_to_be_forwarded = True | ||||||
|  |  | ||||||
|                 await db_session.execute( |                 await db_session.execute( | ||||||
|                     update(models.OutboxObject) |                     update(models.OutboxObject) | ||||||
|                     .where( |                     .where( | ||||||
| @@ -782,6 +788,36 @@ async def _revert_side_effect_for_deleted_object( | |||||||
|                     .values(replies_count=models.InboxObject.replies_count - 1) |                     .values(replies_count=models.InboxObject.replies_count - 1) | ||||||
|                 ) |                 ) | ||||||
|  |  | ||||||
|  |     # Delete any Like/Announce | ||||||
|  |     await db_session.execute( | ||||||
|  |         update(models.OutboxObject) | ||||||
|  |         .where( | ||||||
|  |             models.OutboxObject.activity_object_ap_id == deleted_ap_object.ap_id, | ||||||
|  |         ) | ||||||
|  |         .values(is_deleted=True) | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     # If it's a local replies, it was forwarded, so we also need to forward | ||||||
|  |     # the Delete activity if possible | ||||||
|  |     if delete_activity.has_ld_signature and is_delete_needs_to_be_forwarded: | ||||||
|  |         logger.info("Forwarding Delete activity as it's a local reply") | ||||||
|  |  | ||||||
|  |         # Don't forward to the forwarding actor and the original Delete actor | ||||||
|  |         skip_actors = [delete_activity.actor] | ||||||
|  |         if forwarded_by_actor: | ||||||
|  |             skip_actors.append(forwarded_by_actor) | ||||||
|  |         recipients = await _get_followers_recipients( | ||||||
|  |             db_session, | ||||||
|  |             skip_actors=skip_actors, | ||||||
|  |         ) | ||||||
|  |         for rcp in recipients: | ||||||
|  |             await new_outgoing_activity( | ||||||
|  |                 db_session, | ||||||
|  |                 rcp, | ||||||
|  |                 outbox_object_id=None, | ||||||
|  |                 inbox_object_id=delete_activity.id, | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |  | ||||||
| async def _handle_follow_follow_activity( | async def _handle_follow_follow_activity( | ||||||
|     db_session: AsyncSession, |     db_session: AsyncSession, | ||||||
| @@ -1222,12 +1258,15 @@ async def save_to_inbox( | |||||||
|         return None |         return None | ||||||
|  |  | ||||||
|     raw_object_id = ap.get_id(raw_object) |     raw_object_id = ap.get_id(raw_object) | ||||||
|  |     forwarded_by_actor = None | ||||||
|  |  | ||||||
|     # Ensure forwarded activities have a valid LD sig |     # Ensure forwarded activities have a valid LD sig | ||||||
|     if sent_by_ap_actor_id != actor.ap_id: |     if sent_by_ap_actor_id != actor.ap_id: | ||||||
|         logger.info( |         logger.info( | ||||||
|             f"Processing a forwarded activity {sent_by_ap_actor_id=}/{actor.ap_id}" |             f"Processing a forwarded activity {sent_by_ap_actor_id=}/{actor.ap_id}" | ||||||
|         ) |         ) | ||||||
|  |         forwarded_by_actor = await fetch_actor(db_session, sent_by_ap_actor_id) | ||||||
|  |  | ||||||
|         if not (await ldsig.verify_signature(db_session, raw_object)): |         if not (await ldsig.verify_signature(db_session, raw_object)): | ||||||
|             logger.warning( |             logger.warning( | ||||||
|                 f"Failed to verify LD sig, fetching remote object {raw_object_id}" |                 f"Failed to verify LD sig, fetching remote object {raw_object_id}" | ||||||
| @@ -1314,6 +1353,7 @@ async def save_to_inbox( | |||||||
|             actor, |             actor, | ||||||
|             inbox_object, |             inbox_object, | ||||||
|             relates_to_inbox_object, |             relates_to_inbox_object, | ||||||
|  |             forwarded_by_actor=forwarded_by_actor, | ||||||
|         ) |         ) | ||||||
|     elif activity_ro.ap_type == "Follow": |     elif activity_ro.ap_type == "Follow": | ||||||
|         await _handle_follow_follow_activity(db_session, actor, inbox_object) |         await _handle_follow_follow_activity(db_session, actor, inbox_object) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user