forked from forks/microblog.pub
Enable Webmentions for public posts
This commit is contained in:
parent
4d968264f2
commit
018b7bf553
7 changed files with 65 additions and 7 deletions
|
@ -32,8 +32,8 @@ from config import MEDIA_CACHE
|
|||
from config import _drop_db
|
||||
from core import feed
|
||||
from core.activitypub import activity_url
|
||||
from core.activitypub import post_to_outbox
|
||||
from core.activitypub import new_context
|
||||
from core.activitypub import post_to_outbox
|
||||
from core.meta import Box
|
||||
from core.meta import MetaKey
|
||||
from core.meta import _meta
|
||||
|
|
|
@ -24,6 +24,7 @@ from core.activitypub import Box
|
|||
from core.activitypub import _actor_hash
|
||||
from core.activitypub import _add_answers_to_question
|
||||
from core.activitypub import _cache_actor_icon
|
||||
from core.activitypub import is_from_outbox
|
||||
from core.activitypub import post_to_outbox
|
||||
from core.activitypub import save_reply
|
||||
from core.activitypub import update_cached_actor
|
||||
|
@ -48,6 +49,7 @@ from core.shared import p
|
|||
from core.tasks import Tasks
|
||||
from utils import opengraph
|
||||
from utils.media import is_video
|
||||
from utils.webmentions import discover_webmention_endpoint
|
||||
|
||||
blueprint = flask.Blueprint("tasks", __name__)
|
||||
|
||||
|
@ -305,6 +307,41 @@ def task_cache_attachment() -> _Response:
|
|||
return ""
|
||||
|
||||
|
||||
@blueprint.route("/task/send_webmention", methods=["POST"])
|
||||
def task_send_webmention() -> _Response:
|
||||
task = p.parse(flask.request)
|
||||
app.logger.info(f"task={task!r}")
|
||||
note_url = task.payload["note_url"]
|
||||
link = task.payload["link"]
|
||||
remote_id = task.payload["remote_id"]
|
||||
try:
|
||||
app.logger.info(f"trying to send webmention source={note_url} target={link}")
|
||||
webmention_endpoint = discover_webmention_endpoint(link)
|
||||
if not webmention_endpoint:
|
||||
app.logger.info("no webmention endpoint")
|
||||
return ""
|
||||
|
||||
resp = requests.post(
|
||||
webmention_endpoint,
|
||||
data={"source": note_url, "target": link},
|
||||
headers={"User-Agent": config.USER_AGENT},
|
||||
)
|
||||
app.logger.info(f"webmention endpoint resp={resp}/{resp.text}")
|
||||
resp.raise_for_status()
|
||||
except HTTPError as err:
|
||||
app.logger.exception("request failed")
|
||||
if 400 >= err.response.status_code >= 499:
|
||||
app.logger.info("client error, no retry")
|
||||
return ""
|
||||
|
||||
raise TaskError() from err
|
||||
except Exception as err:
|
||||
app.logger.exception(f"failed to cache actor for {link}/{remote_id}/{note_url}")
|
||||
raise TaskError() from err
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
@blueprint.route("/task/cache_actor", methods=["POST"])
|
||||
def task_cache_actor() -> _Response:
|
||||
task = p.parse(flask.request)
|
||||
|
@ -319,10 +356,18 @@ def task_cache_actor() -> _Response:
|
|||
|
||||
# Fetch the Open Grah metadata if it's a `Create`
|
||||
if activity.has_type(ap.ActivityType.CREATE):
|
||||
links = opengraph.links_from_note(activity.get_object().to_dict())
|
||||
obj = activity.get_object()
|
||||
links = opengraph.links_from_note(obj.to_dict())
|
||||
if links:
|
||||
Tasks.fetch_og_meta(iri)
|
||||
|
||||
# Send Webmentions only if it's from the outbox, and public
|
||||
if (
|
||||
is_from_outbox(obj)
|
||||
and ap.get_visibility(obj) == ap.Visibility.PUBLIC
|
||||
):
|
||||
Tasks.send_webmentions(activity, links)
|
||||
|
||||
if activity.has_type(ap.ActivityType.FOLLOW):
|
||||
if actor.id == config.ID:
|
||||
# It's a new following, cache the "object" (which is the actor we follow)
|
||||
|
|
|
@ -6,11 +6,11 @@ from enum import Enum
|
|||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
from bleach import linkify
|
||||
from itsdangerous import JSONWebSignatureSerializer
|
||||
from little_boxes import strtobool
|
||||
from little_boxes.activitypub import CTX_AS as AP_DEFAULT_CTX
|
||||
from pymongo import MongoClient
|
||||
from bleach import linkify
|
||||
|
||||
import sass
|
||||
from utils.emojis import _load_emojis
|
||||
|
|
|
@ -9,6 +9,7 @@ from little_boxes.errors import NotAnActivityError
|
|||
import config
|
||||
from core.activitypub import _answer_key
|
||||
from core.activitypub import handle_replies
|
||||
from core.activitypub import new_context
|
||||
from core.activitypub import post_to_outbox
|
||||
from core.activitypub import update_cached_actor
|
||||
from core.db import DB
|
||||
|
@ -163,6 +164,7 @@ def _follow_process_inbox(activity: ap.Follow, new_meta: _NewMeta) -> None:
|
|||
actor_id = activity.get_actor().id
|
||||
accept = ap.Accept(
|
||||
actor=config.ID,
|
||||
context=new_context(activity),
|
||||
object={
|
||||
"type": "Follow",
|
||||
"id": activity.id,
|
||||
|
|
|
@ -3,6 +3,7 @@ from datetime import datetime
|
|||
from datetime import timezone
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import Set
|
||||
|
||||
from little_boxes import activitypub as ap
|
||||
from poussetaches import PousseTaches
|
||||
|
@ -40,6 +41,18 @@ class Tasks:
|
|||
|
||||
p.push({"url": url, "iri": iri}, "/task/cache_emoji")
|
||||
|
||||
@staticmethod
|
||||
def send_webmentions(activity: ap.Create, links: Set[str]) -> None:
|
||||
for link in links:
|
||||
p.push(
|
||||
{
|
||||
"link": link,
|
||||
"note_url": activity.get_object().get_url(),
|
||||
"remote_id": activity.id,
|
||||
},
|
||||
"/task/send_webmention",
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def cache_emojis(activity: ap.BaseActivity) -> None:
|
||||
for emoji in activity.get_emojis():
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import json
|
||||
|
||||
import little_boxes.activitypub as ap
|
||||
import mf2py
|
||||
import requests
|
||||
|
@ -49,7 +47,7 @@ def lookup(url: str) -> ap.BaseActivity:
|
|||
# Maybe the page was JSON-LD?
|
||||
data = resp.json()
|
||||
return ap.parse_activity(data)
|
||||
except json.JSONDecodeError:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Try content negotiation (retry with the AP Accept header)
|
||||
|
|
|
@ -40,7 +40,7 @@ def _discover_webmention_endoint(url: str) -> Optional[str]:
|
|||
return None
|
||||
|
||||
|
||||
def discover_webmention_endoint(url: str) -> Optional[str]:
|
||||
def discover_webmention_endpoint(url: str) -> Optional[str]:
|
||||
"""Discover the Webmention endpoint of a given URL, if any.
|
||||
|
||||
Passes all the tests at https://webmention.rocks!
|
||||
|
|
Loading…
Reference in a new issue