mirror of
https://github.com/Mikaela/Limnoria.git
synced 2025-01-13 05:32:33 +01:00
Fediverse: Add @featured command.
This commit is contained in:
parent
cb679d8599
commit
79f13f3051
@ -167,9 +167,10 @@ def get_public_key_pem():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _signed_request(url, headers, data=None):
|
def signed_request(url, headers=None, data=None):
|
||||||
method = "get" if data is None else "post"
|
method = "get" if data is None else "post"
|
||||||
instance_actor_url = get_instance_actor_url()
|
instance_actor_url = get_instance_actor_url()
|
||||||
|
headers = headers or {}
|
||||||
|
|
||||||
if instance_actor_url:
|
if instance_actor_url:
|
||||||
signed_headers = [
|
signed_headers = [
|
||||||
@ -209,7 +210,7 @@ def actor_url(localuser, hostname):
|
|||||||
def get_actor(localuser, hostname):
|
def get_actor(localuser, hostname):
|
||||||
url = actor_url(localuser, hostname)
|
url = actor_url(localuser, hostname)
|
||||||
|
|
||||||
content = _signed_request(url, headers={"Accept": ACTIVITY_MIMETYPE})
|
content = signed_request(url, headers={"Accept": ACTIVITY_MIMETYPE})
|
||||||
|
|
||||||
assert content is not None
|
assert content is not None
|
||||||
|
|
||||||
|
@ -33,17 +33,19 @@ import json
|
|||||||
import importlib
|
import importlib
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
from supybot import conf, utils, plugins, ircutils, callbacks, httpserver
|
from supybot import utils, callbacks, httpserver
|
||||||
from supybot.commands import *
|
from supybot.commands import wrap
|
||||||
from supybot.i18n import PluginInternationalization
|
from supybot.i18n import PluginInternationalization
|
||||||
|
|
||||||
_ = PluginInternationalization("Fediverse")
|
|
||||||
|
|
||||||
from . import activitypub as ap
|
from . import activitypub as ap
|
||||||
|
|
||||||
|
|
||||||
importlib.reload(ap)
|
importlib.reload(ap)
|
||||||
|
|
||||||
|
|
||||||
|
_ = PluginInternationalization("Fediverse")
|
||||||
|
|
||||||
|
|
||||||
_username_re = re.compile("@(?P<localuser>[^@]+)@(?P<hostname>[^@]+)")
|
_username_re = re.compile("@(?P<localuser>[^@]+)@(?P<hostname>[^@]+)")
|
||||||
|
|
||||||
|
|
||||||
@ -92,7 +94,7 @@ class FediverseHttp(httpserver.SupyHTTPServerCallback):
|
|||||||
return
|
return
|
||||||
pem = ap.get_public_key_pem()
|
pem = ap.get_public_key_pem()
|
||||||
actor_url = ap.get_instance_actor_url()
|
actor_url = ap.get_instance_actor_url()
|
||||||
hostname = urllib.parse.urlparse(hostname).hostname
|
hostname = urllib.parse.urlparse(actor_url).hostname
|
||||||
actor = {
|
actor = {
|
||||||
"@context": [
|
"@context": [
|
||||||
"https://www.w3.org/ns/activitystreams",
|
"https://www.w3.org/ns/activitystreams",
|
||||||
@ -119,6 +121,7 @@ class Fediverse(callbacks.Plugin):
|
|||||||
def __init__(self, irc):
|
def __init__(self, irc):
|
||||||
super().__init__(irc)
|
super().__init__(irc)
|
||||||
self._startHttp()
|
self._startHttp()
|
||||||
|
self._actor_cache = utils.structures.TimeoutDict(timeout=600)
|
||||||
|
|
||||||
def _startHttp(self):
|
def _startHttp(self):
|
||||||
callback = FediverseHttp()
|
callback = FediverseHttp()
|
||||||
@ -132,11 +135,9 @@ class Fediverse(callbacks.Plugin):
|
|||||||
def _stopHttp(self):
|
def _stopHttp(self):
|
||||||
httpserver.unhook("fediverse")
|
httpserver.unhook("fediverse")
|
||||||
|
|
||||||
@wrap(["somethingWithoutSpaces"])
|
def _get_actor(self, irc, username):
|
||||||
def profile(self, irc, msg, args, username):
|
if username in self._actor_cache:
|
||||||
"""<@user@instance>
|
return self._actor_cache[username]
|
||||||
|
|
||||||
Returns generic information on the account @user@instance."""
|
|
||||||
match = _username_re.match(username)
|
match = _username_re.match(username)
|
||||||
if not match:
|
if not match:
|
||||||
irc.errorInvalid("fediverse username", username)
|
irc.errorInvalid("fediverse username", username)
|
||||||
@ -145,20 +146,59 @@ class Fediverse(callbacks.Plugin):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
actor = ap.get_actor(localuser, hostname)
|
actor = ap.get_actor(localuser, hostname)
|
||||||
except ap.ActorNotFound as e:
|
except ap.ActorNotFound:
|
||||||
# Usually a 404
|
# Usually a 404
|
||||||
irc.error("Unknown user %s." % username, Raise=True)
|
irc.error("Unknown user %s." % username, Raise=True)
|
||||||
|
|
||||||
|
self._actor_cache[username] = actor
|
||||||
|
self._actor_cache[actor["id"]] = actor
|
||||||
|
|
||||||
|
return actor
|
||||||
|
|
||||||
|
def _format_actor_username(self, actor):
|
||||||
|
hostname = urllib.parse.urlparse(actor["id"]).hostname
|
||||||
|
return "@%s@%s" % (actor["preferredUsername"], hostname)
|
||||||
|
|
||||||
|
def _format_status(self, irc, status):
|
||||||
|
assert status["type"] == "Note", status
|
||||||
|
author_url = status["attributedTo"]
|
||||||
|
author = self._get_actor(irc, author_url)
|
||||||
|
return _("%s (%s): %s") % (
|
||||||
|
author["name"],
|
||||||
|
self._format_actor_username(author),
|
||||||
|
utils.web.htmlToText(status["content"]),
|
||||||
|
)
|
||||||
|
|
||||||
|
@wrap(["somethingWithoutSpaces"])
|
||||||
|
def profile(self, irc, msg, args, username):
|
||||||
|
"""<@user@instance>
|
||||||
|
|
||||||
|
Returns generic information on the account @user@instance."""
|
||||||
|
actor = self._get_actor(irc, username)
|
||||||
|
|
||||||
irc.reply(
|
irc.reply(
|
||||||
_("\x02%s\x02 (@%s@%s): %s")
|
_("\x02%s\x02 (%s): %s")
|
||||||
% (
|
% (
|
||||||
actor["name"],
|
actor["name"],
|
||||||
actor["preferredUsername"],
|
self._format_actor_username(actor),
|
||||||
hostname,
|
utils.web.htmlToText(actor["summary"]),
|
||||||
utils.web.htmlToText(actor["summary"], tagReplace=""),
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@wrap(["somethingWithoutSpaces"])
|
||||||
|
def featured(self, irc, msg, args, username):
|
||||||
|
"""<@user@instance>
|
||||||
|
|
||||||
|
Returned the featured statuses of @user@instance (aka. pinned toots).
|
||||||
|
"""
|
||||||
|
actor = self._get_actor(irc, username)
|
||||||
|
if "featured" not in actor:
|
||||||
|
irc.error(_("No featured statuses."), Raise=True)
|
||||||
|
statuses = json.loads(ap.signed_request(actor["featured"])).get(
|
||||||
|
"orderedItems", []
|
||||||
|
)
|
||||||
|
irc.replies([self._format_status(irc, status) for status in statuses])
|
||||||
|
|
||||||
|
|
||||||
Class = Fediverse
|
Class = Fediverse
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user