Boostrap stream customization (API may change)
This commit is contained in:
parent
bd065446bf
commit
2cc4eda143
3 changed files with 73 additions and 4 deletions
22
app/boxes.py
22
app/boxes.py
|
@ -32,6 +32,8 @@ from app.config import BLOCKED_SERVERS
|
|||
from app.config import ID
|
||||
from app.config import MANUALLY_APPROVES_FOLLOWERS
|
||||
from app.config import set_moved_to
|
||||
from app.config import stream_visibility_callback
|
||||
from app.customization import ObjectInfo
|
||||
from app.database import AsyncSession
|
||||
from app.outgoing_activities import new_outgoing_activity
|
||||
from app.source import dedup_tags
|
||||
|
@ -1881,16 +1883,30 @@ async def _process_note_object(
|
|||
|
||||
is_from_following = ro.actor.ap_id in {f.ap_actor_id for f in following}
|
||||
is_reply = bool(ro.in_reply_to)
|
||||
is_local_reply = (
|
||||
is_local_reply = bool(
|
||||
ro.in_reply_to
|
||||
and ro.in_reply_to.startswith(BASE_URL)
|
||||
and ro.content # Hide votes from Question
|
||||
)
|
||||
is_mention = False
|
||||
hashtags = []
|
||||
tags = ro.ap_object.get("tag", [])
|
||||
for tag in ap.as_list(tags):
|
||||
if tag.get("name") == LOCAL_ACTOR.handle or tag.get("href") == LOCAL_ACTOR.url:
|
||||
is_mention = True
|
||||
if tag.get("type") == "Hashtag":
|
||||
if tag_name := tag.get("name"):
|
||||
hashtags.append(tag_name)
|
||||
|
||||
object_info = ObjectInfo(
|
||||
is_reply=is_reply,
|
||||
is_local_reply=is_local_reply,
|
||||
is_mention=is_mention,
|
||||
is_from_following=is_from_following,
|
||||
hashtags=hashtags,
|
||||
actor_handle=ro.actor.handle,
|
||||
remote_object=ro,
|
||||
)
|
||||
|
||||
inbox_object = models.InboxObject(
|
||||
server=urlparse(ro.ap_id).hostname,
|
||||
|
@ -1908,9 +1924,7 @@ async def _process_note_object(
|
|||
activity_object_ap_id=ro.activity_object_ap_id,
|
||||
og_meta=await opengraph.og_meta_from_note(db_session, ro),
|
||||
# Hide replies from the stream
|
||||
is_hidden_from_stream=not (
|
||||
(not is_reply and is_from_following) or is_mention or is_local_reply
|
||||
),
|
||||
is_hidden_from_stream=not stream_visibility_callback(object_info),
|
||||
# We may already have some replies in DB
|
||||
replies_count=await _get_replies_count(db_session, ro.ap_id),
|
||||
)
|
||||
|
|
|
@ -16,6 +16,8 @@ from loguru import logger
|
|||
from mistletoe import markdown # type: ignore
|
||||
|
||||
from app.customization import _CUSTOM_ROUTES
|
||||
from app.customization import _StreamVisibilityCallback
|
||||
from app.customization import default_stream_visibility_callback
|
||||
from app.utils.emoji import _load_emojis
|
||||
from app.utils.version import get_version_commit
|
||||
|
||||
|
@ -262,3 +264,14 @@ def verify_csrf_token(
|
|||
|
||||
def hmac_sha256() -> hmac.HMAC:
|
||||
return hmac.new(CONFIG.secret.encode(), digestmod=hashlib.sha256)
|
||||
|
||||
|
||||
stream_visibility_callback: _StreamVisibilityCallback
|
||||
try:
|
||||
from data.stream import ( # type: ignore # noqa: F401, E501
|
||||
custom_stream_visibility_callback,
|
||||
)
|
||||
|
||||
stream_visibility_callback = custom_stream_visibility_callback
|
||||
except ImportError:
|
||||
stream_visibility_callback = default_stream_visibility_callback
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
|
||||
from fastapi import APIRouter
|
||||
from fastapi import Depends
|
||||
from fastapi import Request
|
||||
from loguru import logger
|
||||
from starlette.responses import JSONResponse
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from app.ap_object import RemoteObject
|
||||
|
||||
|
||||
_DATA_DIR = Path().parent.resolve() / "data"
|
||||
_Handler = Callable[..., Any]
|
||||
|
||||
|
@ -110,3 +117,38 @@ def get_custom_router() -> APIRouter | None:
|
|||
router.add_api_route(path, handler.handler)
|
||||
|
||||
return router
|
||||
|
||||
|
||||
@dataclass
|
||||
class ObjectInfo:
|
||||
# Is it a reply?
|
||||
is_reply: bool
|
||||
|
||||
# Is it a reply to an outbox object
|
||||
is_local_reply: bool
|
||||
|
||||
# Is the object mentioning the local actor
|
||||
is_mention: bool
|
||||
|
||||
# Is it from someone the local actor is following
|
||||
is_from_following: bool
|
||||
|
||||
# List of hashtags, e.g. #microblogpub
|
||||
hashtags: list[str]
|
||||
|
||||
# @dev@microblog.pub
|
||||
actor_handle: str
|
||||
|
||||
remote_object: "RemoteObject"
|
||||
|
||||
|
||||
_StreamVisibilityCallback = Callable[[ObjectInfo], bool]
|
||||
|
||||
|
||||
def default_stream_visibility_callback(object_info: ObjectInfo) -> bool:
|
||||
logger.info(f"{object_info=}")
|
||||
return (
|
||||
(not object_info.is_reply and object_info.is_from_following)
|
||||
or object_info.is_mention
|
||||
or object_info.is_local_reply
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue