mirror of
https://git.sr.ht/~tsileo/microblog.pub
synced 2024-12-22 13:14:28 +00:00
Allow to disable certain notification type
This commit is contained in:
parent
e30e0de10e
commit
ec36272bb4
4 changed files with 167 additions and 98 deletions
190
app/boxes.py
190
app/boxes.py
|
@ -50,6 +50,17 @@ from app.utils.text import slugify
|
||||||
AnyboxObject = models.InboxObject | models.OutboxObject
|
AnyboxObject = models.InboxObject | models.OutboxObject
|
||||||
|
|
||||||
|
|
||||||
|
def is_notification_enabled(notification_type: models.NotificationType) -> bool:
|
||||||
|
"""Checks if a given notification type is enabled."""
|
||||||
|
if notification_type.value == "pending_incoming_follower":
|
||||||
|
# This one cannot be disabled as it would prevent manually reviewing
|
||||||
|
# follow requests.
|
||||||
|
return True
|
||||||
|
if notification_type.value in config.CONFIG.disabled_notifications:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def allocate_outbox_id() -> str:
|
def allocate_outbox_id() -> str:
|
||||||
return uuid.uuid4().hex
|
return uuid.uuid4().hex
|
||||||
|
|
||||||
|
@ -168,12 +179,13 @@ async def send_block(db_session: AsyncSession, ap_actor_id: str) -> None:
|
||||||
await new_outgoing_activity(db_session, actor.inbox_url, outbox_object.id)
|
await new_outgoing_activity(db_session, actor.inbox_url, outbox_object.id)
|
||||||
|
|
||||||
# 4. Create a notification
|
# 4. Create a notification
|
||||||
notif = models.Notification(
|
if is_notification_enabled(models.NotificationType.BLOCK):
|
||||||
notification_type=models.NotificationType.BLOCK,
|
notif = models.Notification(
|
||||||
actor_id=actor.id,
|
notification_type=models.NotificationType.BLOCK,
|
||||||
outbox_object_id=outbox_object.id,
|
actor_id=actor.id,
|
||||||
)
|
outbox_object_id=outbox_object.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
|
|
||||||
await db_session.commit()
|
await db_session.commit()
|
||||||
|
|
||||||
|
@ -447,12 +459,13 @@ async def _send_undo(db_session: AsyncSession, ap_object_id: str) -> None:
|
||||||
outbox_object.id,
|
outbox_object.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
notif = models.Notification(
|
if is_notification_enabled(models.NotificationType.UNBLOCK):
|
||||||
notification_type=models.NotificationType.UNBLOCK,
|
notif = models.Notification(
|
||||||
actor_id=blocked_actor.id,
|
notification_type=models.NotificationType.UNBLOCK,
|
||||||
outbox_object_id=outbox_object.id,
|
actor_id=blocked_actor.id,
|
||||||
)
|
outbox_object_id=outbox_object.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError("Should never happen")
|
raise ValueError("Should never happen")
|
||||||
|
@ -1525,11 +1538,12 @@ async def _send_accept(
|
||||||
raise ValueError("Should never happen")
|
raise ValueError("Should never happen")
|
||||||
await new_outgoing_activity(db_session, from_actor.inbox_url, outbox_activity.id)
|
await new_outgoing_activity(db_session, from_actor.inbox_url, outbox_activity.id)
|
||||||
|
|
||||||
notif = models.Notification(
|
if is_notification_enabled(models.NotificationType.NEW_FOLLOWER):
|
||||||
notification_type=models.NotificationType.NEW_FOLLOWER,
|
notif = models.Notification(
|
||||||
actor_id=from_actor.id,
|
notification_type=models.NotificationType.NEW_FOLLOWER,
|
||||||
)
|
actor_id=from_actor.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
|
|
||||||
|
|
||||||
async def send_reject(
|
async def send_reject(
|
||||||
|
@ -1568,11 +1582,12 @@ async def _send_reject(
|
||||||
raise ValueError("Should never happen")
|
raise ValueError("Should never happen")
|
||||||
await new_outgoing_activity(db_session, from_actor.inbox_url, outbox_activity.id)
|
await new_outgoing_activity(db_session, from_actor.inbox_url, outbox_activity.id)
|
||||||
|
|
||||||
notif = models.Notification(
|
if is_notification_enabled(models.NotificationType.REJECTED_FOLLOWER):
|
||||||
notification_type=models.NotificationType.REJECTED_FOLLOWER,
|
notif = models.Notification(
|
||||||
actor_id=from_actor.id,
|
notification_type=models.NotificationType.REJECTED_FOLLOWER,
|
||||||
)
|
actor_id=from_actor.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
|
|
||||||
|
|
||||||
async def _handle_undo_activity(
|
async def _handle_undo_activity(
|
||||||
|
@ -1598,11 +1613,12 @@ async def _handle_undo_activity(
|
||||||
models.Follower.inbox_object_id == ap_activity_to_undo.id
|
models.Follower.inbox_object_id == ap_activity_to_undo.id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
notif = models.Notification(
|
if is_notification_enabled(models.NotificationType.UNFOLLOW):
|
||||||
notification_type=models.NotificationType.UNFOLLOW,
|
notif = models.Notification(
|
||||||
actor_id=from_actor.id,
|
notification_type=models.NotificationType.UNFOLLOW,
|
||||||
)
|
actor_id=from_actor.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
|
|
||||||
elif ap_activity_to_undo.ap_type == "Like":
|
elif ap_activity_to_undo.ap_type == "Like":
|
||||||
if not ap_activity_to_undo.activity_object_ap_id:
|
if not ap_activity_to_undo.activity_object_ap_id:
|
||||||
|
@ -1618,14 +1634,21 @@ async def _handle_undo_activity(
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
liked_obj.likes_count = models.OutboxObject.likes_count - 1
|
liked_obj.likes_count = (
|
||||||
notif = models.Notification(
|
await _get_outbox_likes_count(
|
||||||
notification_type=models.NotificationType.UNDO_LIKE,
|
db_session,
|
||||||
actor_id=from_actor.id,
|
liked_obj,
|
||||||
outbox_object_id=liked_obj.id,
|
)
|
||||||
inbox_object_id=ap_activity_to_undo.id,
|
- 1
|
||||||
)
|
)
|
||||||
db_session.add(notif)
|
if is_notification_enabled(models.NotificationType.UNDO_LIKE):
|
||||||
|
notif = models.Notification(
|
||||||
|
notification_type=models.NotificationType.UNDO_LIKE,
|
||||||
|
actor_id=from_actor.id,
|
||||||
|
outbox_object_id=liked_obj.id,
|
||||||
|
inbox_object_id=ap_activity_to_undo.id,
|
||||||
|
)
|
||||||
|
db_session.add(notif)
|
||||||
|
|
||||||
elif ap_activity_to_undo.ap_type == "Announce":
|
elif ap_activity_to_undo.ap_type == "Announce":
|
||||||
if not ap_activity_to_undo.activity_object_ap_id:
|
if not ap_activity_to_undo.activity_object_ap_id:
|
||||||
|
@ -1643,20 +1666,22 @@ async def _handle_undo_activity(
|
||||||
announced_obj_from_outbox.announces_count = (
|
announced_obj_from_outbox.announces_count = (
|
||||||
models.OutboxObject.announces_count - 1
|
models.OutboxObject.announces_count - 1
|
||||||
)
|
)
|
||||||
notif = models.Notification(
|
if is_notification_enabled(models.NotificationType.UNDO_ANNOUNCE):
|
||||||
notification_type=models.NotificationType.UNDO_ANNOUNCE,
|
notif = models.Notification(
|
||||||
actor_id=from_actor.id,
|
notification_type=models.NotificationType.UNDO_ANNOUNCE,
|
||||||
outbox_object_id=announced_obj_from_outbox.id,
|
actor_id=from_actor.id,
|
||||||
inbox_object_id=ap_activity_to_undo.id,
|
outbox_object_id=announced_obj_from_outbox.id,
|
||||||
)
|
inbox_object_id=ap_activity_to_undo.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
elif ap_activity_to_undo.ap_type == "Block":
|
elif ap_activity_to_undo.ap_type == "Block":
|
||||||
notif = models.Notification(
|
if is_notification_enabled(models.NotificationType.UNBLOCKED):
|
||||||
notification_type=models.NotificationType.UNBLOCKED,
|
notif = models.Notification(
|
||||||
actor_id=from_actor.id,
|
notification_type=models.NotificationType.UNBLOCKED,
|
||||||
inbox_object_id=ap_activity_to_undo.id,
|
actor_id=from_actor.id,
|
||||||
)
|
inbox_object_id=ap_activity_to_undo.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
else:
|
else:
|
||||||
logger.warning(f"Don't know how to undo {ap_activity_to_undo.ap_type} activity")
|
logger.warning(f"Don't know how to undo {ap_activity_to_undo.ap_type} activity")
|
||||||
|
|
||||||
|
@ -1720,12 +1745,13 @@ async def _handle_move_activity(
|
||||||
else:
|
else:
|
||||||
logger.info(f"Already following target {new_actor_id}")
|
logger.info(f"Already following target {new_actor_id}")
|
||||||
|
|
||||||
notif = models.Notification(
|
if is_notification_enabled(models.NotificationType.MOVE):
|
||||||
notification_type=models.NotificationType.MOVE,
|
notif = models.Notification(
|
||||||
actor_id=new_actor.id,
|
notification_type=models.NotificationType.MOVE,
|
||||||
inbox_object_id=move_activity.id,
|
actor_id=new_actor.id,
|
||||||
)
|
inbox_object_id=move_activity.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
|
|
||||||
|
|
||||||
async def _handle_update_activity(
|
async def _handle_update_activity(
|
||||||
|
@ -1999,7 +2025,7 @@ async def _process_note_object(
|
||||||
inbox_object_id=parent_activity.id,
|
inbox_object_id=parent_activity.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
if is_mention:
|
if is_mention and is_notification_enabled(models.NotificationType.MENTION):
|
||||||
notif = models.Notification(
|
notif = models.Notification(
|
||||||
notification_type=models.NotificationType.MENTION,
|
notification_type=models.NotificationType.MENTION,
|
||||||
actor_id=from_actor.id,
|
actor_id=from_actor.id,
|
||||||
|
@ -2098,13 +2124,14 @@ async def _handle_announce_activity(
|
||||||
models.OutboxObject.announces_count + 1
|
models.OutboxObject.announces_count + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
notif = models.Notification(
|
if is_notification_enabled(models.NotificationType.ANNOUNCE):
|
||||||
notification_type=models.NotificationType.ANNOUNCE,
|
notif = models.Notification(
|
||||||
actor_id=actor.id,
|
notification_type=models.NotificationType.ANNOUNCE,
|
||||||
outbox_object_id=relates_to_outbox_object.id,
|
actor_id=actor.id,
|
||||||
inbox_object_id=announce_activity.id,
|
outbox_object_id=relates_to_outbox_object.id,
|
||||||
)
|
inbox_object_id=announce_activity.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
else:
|
else:
|
||||||
# Only show the announce in the stream if it comes from an actor
|
# Only show the announce in the stream if it comes from an actor
|
||||||
# in the following collection
|
# in the following collection
|
||||||
|
@ -2202,13 +2229,14 @@ async def _handle_like_activity(
|
||||||
relates_to_outbox_object,
|
relates_to_outbox_object,
|
||||||
)
|
)
|
||||||
|
|
||||||
notif = models.Notification(
|
if is_notification_enabled(models.NotificationType.LIKE):
|
||||||
notification_type=models.NotificationType.LIKE,
|
notif = models.Notification(
|
||||||
actor_id=actor.id,
|
notification_type=models.NotificationType.LIKE,
|
||||||
outbox_object_id=relates_to_outbox_object.id,
|
actor_id=actor.id,
|
||||||
inbox_object_id=like_activity.id,
|
outbox_object_id=relates_to_outbox_object.id,
|
||||||
)
|
inbox_object_id=like_activity.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
|
|
||||||
|
|
||||||
async def _handle_block_activity(
|
async def _handle_block_activity(
|
||||||
|
@ -2225,12 +2253,13 @@ async def _handle_block_activity(
|
||||||
return
|
return
|
||||||
|
|
||||||
# Create a notification
|
# Create a notification
|
||||||
notif = models.Notification(
|
if is_notification_enabled(models.NotificationType.BLOCKED):
|
||||||
notification_type=models.NotificationType.BLOCKED,
|
notif = models.Notification(
|
||||||
actor_id=actor.id,
|
notification_type=models.NotificationType.BLOCKED,
|
||||||
inbox_object_id=block_activity.id,
|
actor_id=actor.id,
|
||||||
)
|
inbox_object_id=block_activity.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
|
|
||||||
|
|
||||||
async def _process_transient_object(
|
async def _process_transient_object(
|
||||||
|
@ -2433,12 +2462,13 @@ async def save_to_inbox(
|
||||||
if activity_ro.ap_type == "Accept"
|
if activity_ro.ap_type == "Accept"
|
||||||
else models.NotificationType.FOLLOW_REQUEST_REJECTED
|
else models.NotificationType.FOLLOW_REQUEST_REJECTED
|
||||||
)
|
)
|
||||||
notif = models.Notification(
|
if is_notification_enabled(notif_type):
|
||||||
notification_type=notif_type,
|
notif = models.Notification(
|
||||||
actor_id=actor.id,
|
notification_type=notif_type,
|
||||||
inbox_object_id=inbox_object.id,
|
actor_id=actor.id,
|
||||||
)
|
inbox_object_id=inbox_object.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
|
|
||||||
if activity_ro.ap_type == "Accept":
|
if activity_ro.ap_type == "Accept":
|
||||||
following = models.Following(
|
following = models.Following(
|
||||||
|
|
|
@ -120,6 +120,8 @@ class Config(pydantic.BaseModel):
|
||||||
|
|
||||||
session_timeout: int = 3600 * 24 * 3 # in seconds, 3 days by default
|
session_timeout: int = 3600 * 24 * 3 # in seconds, 3 days by default
|
||||||
|
|
||||||
|
disabled_notifications: list[str] = []
|
||||||
|
|
||||||
# Only set when the app is served on a non-root path
|
# Only set when the app is served on a non-root path
|
||||||
id: str | None = None
|
id: str | None = None
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ from app.boxes import _get_outbox_likes_count
|
||||||
from app.boxes import _get_outbox_replies_count
|
from app.boxes import _get_outbox_replies_count
|
||||||
from app.boxes import get_outbox_object_by_ap_id
|
from app.boxes import get_outbox_object_by_ap_id
|
||||||
from app.boxes import get_outbox_object_by_slug_and_short_id
|
from app.boxes import get_outbox_object_by_slug_and_short_id
|
||||||
|
from app.boxes import is_notification_enabled
|
||||||
from app.database import AsyncSession
|
from app.database import AsyncSession
|
||||||
from app.database import get_db_session
|
from app.database import get_db_session
|
||||||
from app.utils import microformats
|
from app.utils import microformats
|
||||||
|
@ -118,12 +119,13 @@ async def webmention_endpoint(
|
||||||
db_session, existing_webmention_in_db, mentioned_object
|
db_session, existing_webmention_in_db, mentioned_object
|
||||||
)
|
)
|
||||||
|
|
||||||
notif = models.Notification(
|
if is_notification_enabled(models.NotificationType.DELETED_WEBMENTION):
|
||||||
notification_type=models.NotificationType.DELETED_WEBMENTION,
|
notif = models.Notification(
|
||||||
outbox_object_id=mentioned_object.id,
|
notification_type=models.NotificationType.DELETED_WEBMENTION,
|
||||||
webmention_id=existing_webmention_in_db.id,
|
outbox_object_id=mentioned_object.id,
|
||||||
)
|
webmention_id=existing_webmention_in_db.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
|
|
||||||
await db_session.commit()
|
await db_session.commit()
|
||||||
|
|
||||||
|
@ -144,12 +146,13 @@ async def webmention_endpoint(
|
||||||
await db_session.flush()
|
await db_session.flush()
|
||||||
webmention = existing_webmention_in_db
|
webmention = existing_webmention_in_db
|
||||||
|
|
||||||
notif = models.Notification(
|
if is_notification_enabled(models.NotificationType.UPDATED_WEBMENTION):
|
||||||
notification_type=models.NotificationType.UPDATED_WEBMENTION,
|
notif = models.Notification(
|
||||||
outbox_object_id=mentioned_object.id,
|
notification_type=models.NotificationType.UPDATED_WEBMENTION,
|
||||||
webmention_id=existing_webmention_in_db.id,
|
outbox_object_id=mentioned_object.id,
|
||||||
)
|
webmention_id=existing_webmention_in_db.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
else:
|
else:
|
||||||
new_webmention = models.Webmention(
|
new_webmention = models.Webmention(
|
||||||
source=source,
|
source=source,
|
||||||
|
@ -162,12 +165,13 @@ async def webmention_endpoint(
|
||||||
await db_session.flush()
|
await db_session.flush()
|
||||||
webmention = new_webmention
|
webmention = new_webmention
|
||||||
|
|
||||||
notif = models.Notification(
|
if is_notification_enabled(models.NotificationType.NEW_WEBMENTION):
|
||||||
notification_type=models.NotificationType.NEW_WEBMENTION,
|
notif = models.Notification(
|
||||||
outbox_object_id=mentioned_object.id,
|
notification_type=models.NotificationType.NEW_WEBMENTION,
|
||||||
webmention_id=new_webmention.id,
|
outbox_object_id=mentioned_object.id,
|
||||||
)
|
webmention_id=new_webmention.id,
|
||||||
db_session.add(notif)
|
)
|
||||||
|
db_session.add(notif)
|
||||||
|
|
||||||
# Determine the webmention type
|
# Determine the webmention type
|
||||||
for item in data.get("items", []):
|
for item in data.get("items", []):
|
||||||
|
|
|
@ -98,6 +98,39 @@ privacy_replace = [
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Disabling certain notification types
|
||||||
|
|
||||||
|
All notifications are enabled by default.
|
||||||
|
|
||||||
|
You can disabled specific notifications by adding them to the `disabled_notifications` list.
|
||||||
|
|
||||||
|
This example disables likes and shares notifications:
|
||||||
|
|
||||||
|
```
|
||||||
|
disabled_notifications = ["like", "announce"]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Available notification types
|
||||||
|
|
||||||
|
- `new_follower`
|
||||||
|
- `rejected_follower`
|
||||||
|
- `unfollow`
|
||||||
|
- `follow_request_accepted`
|
||||||
|
- `follow_request_rejected`
|
||||||
|
- `move`
|
||||||
|
- `like`
|
||||||
|
- `undo_like`
|
||||||
|
- `announce`
|
||||||
|
- `undo_announce`
|
||||||
|
- `mention`
|
||||||
|
- `new_webmention`
|
||||||
|
- `updated_webmention`
|
||||||
|
- `deleted_webmention`
|
||||||
|
- `blocked`
|
||||||
|
- `unblocked`
|
||||||
|
- `block`
|
||||||
|
- `unblock`
|
||||||
|
|
||||||
### Customization
|
### Customization
|
||||||
|
|
||||||
#### Default emoji
|
#### Default emoji
|
||||||
|
|
Loading…
Reference in a new issue