2019-09-25 15:11:57 +00:00
|
|
|
#--depends-on rest_api
|
|
|
|
|
2019-09-15 09:43:46 +00:00
|
|
|
import urllib.parse
|
|
|
|
from src import IRCBot, ModuleManager, utils
|
2019-09-18 09:18:49 +00:00
|
|
|
from . import ap_actor, ap_security, ap_server, ap_utils
|
2019-09-15 09:43:46 +00:00
|
|
|
|
|
|
|
def _format_username(username, instance):
|
|
|
|
return "@%s@%s" % (username, instance)
|
|
|
|
def _setting_parse(s):
|
|
|
|
username, instance = ap_utils.split_username(s)
|
|
|
|
if username and instance:
|
|
|
|
return _format_username(username, instance)
|
|
|
|
return None
|
|
|
|
|
2019-09-15 10:06:00 +00:00
|
|
|
@utils.export("botset", utils.FunctionSetting(_setting_parse,
|
|
|
|
"fediverse-server", "The bot's local fediverse server username",
|
|
|
|
example="@bot@bitbot.dev"))
|
2019-09-15 09:43:46 +00:00
|
|
|
@utils.export("set", utils.FunctionSetting(_setting_parse, "fediverse",
|
|
|
|
help="Set your fediverse account", example="@gargron@mastodon.social"))
|
|
|
|
class Module(ModuleManager.BaseModule):
|
|
|
|
_name = "Fedi"
|
|
|
|
|
2019-09-15 10:06:00 +00:00
|
|
|
def on_load(self):
|
|
|
|
server_username = self.bot.get_setting("fediverse-server", None)
|
|
|
|
if server_username:
|
2019-09-15 16:11:45 +00:00
|
|
|
if not "tls-key" in self.bot.config:
|
|
|
|
raise ValueError("`tls-key` not provided in bot config")
|
|
|
|
if not "tls-certificate" in self.bot.config:
|
|
|
|
raise ValueError("`tls-certificate` not provided in bot config")
|
2019-09-18 09:18:49 +00:00
|
|
|
if not ap_security.has_crypto:
|
|
|
|
raise ValueError("cyprography library is not installed "
|
|
|
|
"(https://pypi.org/project/cryptography/)")
|
2019-09-15 16:11:45 +00:00
|
|
|
|
2019-09-15 10:06:00 +00:00
|
|
|
server_username, instance = ap_utils.split_username(server_username)
|
2019-09-16 13:23:06 +00:00
|
|
|
self.server = ap_server.Server(self.bot, self.exports,
|
|
|
|
server_username, instance)
|
2019-09-15 10:06:00 +00:00
|
|
|
|
|
|
|
self.events.on("api.get.ap-webfinger").hook(
|
|
|
|
self.server.ap_webfinger, authenticated=False)
|
|
|
|
self.events.on("api.get.ap-user").hook(
|
|
|
|
self.server.ap_user, authenticated=False)
|
|
|
|
self.events.on("api.post.ap-inbox").hook(
|
|
|
|
self.server.ap_inbox, authenticated=False)
|
|
|
|
self.events.on("api.get.ap-outbox").hook(
|
|
|
|
self.server.ap_outbox, authenticated=False)
|
2019-09-16 13:18:58 +00:00
|
|
|
def unload(self):
|
|
|
|
if not self.server == None:
|
|
|
|
self.server.unload()
|
2019-09-15 10:06:00 +00:00
|
|
|
|
2019-09-15 09:43:46 +00:00
|
|
|
@utils.hook("received.command.fediverse")
|
|
|
|
@utils.hook("received.command.fedi", alias_of="fediverse")
|
|
|
|
@utils.kwarg("help", "Get someone's latest toot")
|
2019-10-18 14:43:17 +00:00
|
|
|
@utils.kwarg("usage", "@<user>@<instance> [!]")
|
2019-09-15 09:43:46 +00:00
|
|
|
def fedi(self, event):
|
|
|
|
account = None
|
2019-10-04 12:06:29 +00:00
|
|
|
url = None
|
2019-10-18 14:43:17 +00:00
|
|
|
|
2019-10-18 14:54:36 +00:00
|
|
|
strict_cw = True
|
2019-10-18 14:43:17 +00:00
|
|
|
args_split = event["args_split"][:]
|
|
|
|
for i, arg in enumerate(args_split):
|
|
|
|
if arg == "!":
|
2019-10-18 14:54:36 +00:00
|
|
|
strict_cw = False
|
2019-10-18 14:43:17 +00:00
|
|
|
args_split.pop(i)
|
|
|
|
break
|
|
|
|
|
|
|
|
if not args_split:
|
2019-09-15 09:43:46 +00:00
|
|
|
account = event["user"].get_setting("fediverse", None)
|
2019-10-18 14:43:17 +00:00
|
|
|
elif utils.http.REGEX_URL.match(args_split[0]):
|
|
|
|
url = args_split[0]
|
|
|
|
elif not "@" in args_split[0]:
|
|
|
|
target = args_split[0]
|
2019-09-15 09:43:46 +00:00
|
|
|
if event["server"].has_user_id(target):
|
|
|
|
target_user = event["server"].get_user(target)
|
|
|
|
account = target_user.get_setting("fediverse", None)
|
|
|
|
else:
|
2019-10-18 14:43:17 +00:00
|
|
|
account = args_split[0]
|
2019-09-15 09:43:46 +00:00
|
|
|
|
2019-10-04 12:06:29 +00:00
|
|
|
note = None
|
|
|
|
type = "Create"
|
|
|
|
if not url == None:
|
|
|
|
note_page = ap_utils.activity_request(url)
|
|
|
|
if not note_page.content_type == ap_utils.ACTIVITY_TYPE:
|
|
|
|
raise utils.EventError("That's not a fediverse URL")
|
2019-09-15 09:43:46 +00:00
|
|
|
|
2019-11-28 07:31:06 +00:00
|
|
|
note = note_page.json()
|
2019-10-04 12:06:29 +00:00
|
|
|
actor = ap_actor.Actor(note["attributedTo"])
|
|
|
|
actor.load()
|
|
|
|
else:
|
|
|
|
username = None
|
|
|
|
instance = None
|
|
|
|
if account:
|
|
|
|
username, instance = ap_utils.split_username(account)
|
|
|
|
|
|
|
|
if not username or not instance:
|
|
|
|
raise utils.EventError("Please provide @<user>@<instance>")
|
|
|
|
actor, note = self._get_from_outbox(username, instance)
|
|
|
|
type = note["type"]
|
|
|
|
note = note["object"]
|
|
|
|
|
2019-11-27 15:16:46 +00:00
|
|
|
cw, author, content, url = ap_utils.parse_note(actor, note, type)
|
2019-10-04 12:06:29 +00:00
|
|
|
shorturl = self.exports.get_one("shorturl")(event["server"], url,
|
|
|
|
context=event["target"])
|
|
|
|
|
2019-10-18 14:54:36 +00:00
|
|
|
if cw:
|
|
|
|
if strict_cw:
|
2019-11-27 15:16:46 +00:00
|
|
|
out = "%s: CW %s - %s" % (author, cw, shorturl)
|
2019-10-18 14:54:36 +00:00
|
|
|
else:
|
2019-11-27 15:16:46 +00:00
|
|
|
out = "(CW %s) %s: %s - %s" % (cw, author, content, shorturl)
|
2019-10-04 12:06:29 +00:00
|
|
|
else:
|
2019-11-27 15:16:46 +00:00
|
|
|
out = "%s: %s - %s" % (author, content, shorturl)
|
2019-10-04 12:06:29 +00:00
|
|
|
event["stdout"].write(out)
|
2019-09-15 09:43:46 +00:00
|
|
|
|
2019-10-04 12:06:29 +00:00
|
|
|
def _get_from_outbox(self, username, instance):
|
2019-11-14 10:53:34 +00:00
|
|
|
try:
|
|
|
|
actor_url = ap_utils.find_actor(username, instance)
|
|
|
|
except ap_utils.FindActorException as e:
|
|
|
|
raise utils.EventError(str(e))
|
2019-09-15 09:43:46 +00:00
|
|
|
|
|
|
|
actor = ap_actor.Actor(actor_url)
|
2019-09-17 16:41:40 +00:00
|
|
|
if not actor.load():
|
2019-11-14 10:53:34 +00:00
|
|
|
raise utils.EventError("Failed to load user")
|
2019-09-25 15:11:18 +00:00
|
|
|
|
2019-09-15 09:43:46 +00:00
|
|
|
items = actor.outbox.load()
|
2019-10-15 14:24:57 +00:00
|
|
|
nonreply = [actor.followers]
|
2019-11-26 14:31:22 +00:00
|
|
|
first_item = None
|
2019-09-25 15:11:18 +00:00
|
|
|
for item in items:
|
2019-10-15 14:24:57 +00:00
|
|
|
if item["type"] == "Announce" or item["object"]["cc"] == nonreply:
|
2019-09-25 15:11:18 +00:00
|
|
|
first_item = item
|
2019-09-25 15:14:48 +00:00
|
|
|
break
|
2019-09-15 09:43:46 +00:00
|
|
|
|
2019-09-25 15:11:18 +00:00
|
|
|
if not first_item:
|
2019-09-15 09:43:46 +00:00
|
|
|
raise utils.EventError("No toots found")
|
|
|
|
|
2019-10-04 12:06:29 +00:00
|
|
|
return actor, first_item
|