playlist_of_the_day: post playlist on demand

This commit is contained in:
dece 2022-09-11 23:14:25 +02:00
parent 91deeca19b
commit 404f5bb673
4 changed files with 65 additions and 8 deletions

View file

@ -148,7 +148,8 @@
"negative": ["I don't like it."] "negative": ["I don't like it."]
}, },
"playlistoftheday": { "playlistoftheday": {
"commands": ["playlist of the day"] "commands": ["playlist of the day"],
"not_fresh_reply": "It's not from today but here it is: {url}"
}, },
"plus": { "plus": {
"commands": ["plus"], "commands": ["plus"],

View file

@ -162,7 +162,10 @@ class Bot(irc.client.SimpleIRCClient, Logger):
def get_plugin(self, name: str) -> Optional[Plugin]: def get_plugin(self, name: str) -> Optional[Plugin]:
"""Get a loaded plugin by its name (e.g. 'mood'), or None.""" """Get a loaded plugin by its name (e.g. 'mood'), or None."""
matching_plugins = filter(lambda plugin: plugin.name == name, self.plugins) matching_plugins = filter(
lambda plugin: plugin.name == name,
self.plugins,
)
return next(matching_plugins, None) return next(matching_plugins, None)
def say(self, target: str, message: str) -> None: def say(self, target: str, message: str) -> None:

View file

@ -1,11 +1,25 @@
import datetime import datetime
import re
from typing import cast, Optional
from edmond.plugin import Plugin from edmond.plugin import Plugin
from edmond.plugins.shrlok import ShrlokPlugin
HTML_TEMPLATE = """\
<html>
<head> <meta charset="utf-8"> <title>🎶</title> </head>
<body> {} </body>
</html>
"""
LINK_RE = re.compile(r"(https?://\S+)")
class PlaylistOfTheDayPlugin(Plugin): class PlaylistOfTheDayPlugin(Plugin):
"""Collect music links from other platforms. """Collect music links from other platforms.
This plugin requires a working Shrlok instance to post the playlist.
Plugins that want to feed the playlist must do so by calling the add_link method of Plugins that want to feed the playlist must do so by calling the add_link method of
the plugin. Later this plugin may feed its playlist using links unhandled by other, the plugin. Later this plugin may feed its playlist using links unhandled by other,
more specialized plugins (bandcamp, soundcloud, ). more specialized plugins (bandcamp, soundcloud, ).
@ -27,12 +41,26 @@ class PlaylistOfTheDayPlugin(Plugin):
def __init__(self, bot): def __init__(self, bot):
super().__init__(bot) super().__init__(bot)
self._shrlok_plugin = None
@property
def shrlok_plugin(self) -> Optional[ShrlokPlugin]:
if self._shrlok_plugin is None:
self._shrlok_plugin = cast(
ShrlokPlugin,
self.bot.get_plugin("shrlok"),
)
return self._shrlok_plugin
def on_welcome(self, _):
if not (self.shrlok_plugin and self.shrlok_plugin.is_ready):
self.bot.log_w("Shrlok plugin is not available.")
self.is_ready = False
def on_pubmsg(self, event): def on_pubmsg(self, event):
if not self.should_handle_command(event.arguments[0], no_content=True): if not self.should_handle_command(event.arguments[0], no_content=True):
return False return False
self.post_playlist(event.target)
# self.post_playlist(event.target)
return True return True
def add_line(self, line: str) -> None: def add_line(self, line: str) -> None:
@ -62,5 +90,29 @@ class PlaylistOfTheDayPlugin(Plugin):
today.isoformat(), today.isoformat(),
) )
# def post_playlist(self): def post_playlist(self, target):
# pass playlist: list[str] = self.get_storage_value(self.PLAYLIST_KEY, [])
if not playlist:
self.bot.log_e("Playlist empty.")
self.signal_failure(target)
linkified_items = map(PlaylistOfTheDayPlugin.linkify, playlist)
html_items = map(lambda item: f"<li>{item}</li>", linkified_items)
html_list = "<ol>" + "".join(html_items) + "</ol>"
data = HTML_TEMPLATE.format(html_list).encode()
url = self.shrlok_plugin.post({"type": "raw"}, data)
if not url:
self.bot.log_e("Shrlok returned None.")
self.signal_failure(target)
date = self.get_storage_value(self.DATE_KEY, "")
if date != datetime.date.today().isoformat():
reply = self.config["not_fresh_reply"].format(url=url)
else:
reply = url
self.bot.say(target, reply)
@staticmethod
def linkify(text: str) -> str:
"""Put links in A tags."""
return LINK_RE.sub(r'<a href="\1">\1</a>', text)

View file

@ -1,5 +1,6 @@
import json import json
import socket import socket
from typing import Optional
from edmond.bot import Bot from edmond.bot import Bot
from edmond.plugin import Plugin from edmond.plugin import Plugin
@ -31,7 +32,7 @@ class ShrlokPlugin(Plugin):
self.bot.log_d("No socket path specified, shrlok plugin disabled.") self.bot.log_d("No socket path specified, shrlok plugin disabled.")
self.is_ready = False self.is_ready = False
def post(self, header: dict, data: bytes): def post(self, header: dict, data: bytes) -> Optional[str]:
encoded_header = json.dumps(header).encode() encoded_header = json.dumps(header).encode()
try: try:
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock: with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
@ -45,4 +46,4 @@ class ShrlokPlugin(Plugin):
self.bot.log_e(f"Can't post data: {exc}") self.bot.log_e(f"Can't post data: {exc}")
return None return None
url = response.decode().replace(self.file_root, self.url_root, 1) url = response.decode().replace(self.file_root, self.url_root, 1)
return url return url or None # returning empty strings could cause confusion