diff --git a/config.json.example b/config.json.example
index fcd7588..f72e903 100644
--- a/config.json.example
+++ b/config.json.example
@@ -148,7 +148,8 @@
"negative": ["I don't like it."]
},
"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": {
"commands": ["plus"],
diff --git a/edmond/bot.py b/edmond/bot.py
index 9255b54..907aa40 100644
--- a/edmond/bot.py
+++ b/edmond/bot.py
@@ -162,7 +162,10 @@ class Bot(irc.client.SimpleIRCClient, Logger):
def get_plugin(self, name: str) -> Optional[Plugin]:
"""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)
def say(self, target: str, message: str) -> None:
diff --git a/edmond/plugins/playlist_of_the_day.py b/edmond/plugins/playlist_of_the_day.py
index 202f972..1fc009b 100644
--- a/edmond/plugins/playlist_of_the_day.py
+++ b/edmond/plugins/playlist_of_the_day.py
@@ -1,11 +1,25 @@
import datetime
+import re
+from typing import cast, Optional
from edmond.plugin import Plugin
+from edmond.plugins.shrlok import ShrlokPlugin
+
+
+HTML_TEMPLATE = """\
+
+
🎶
+ {}
+
+"""
+LINK_RE = re.compile(r"(https?://\S+)")
class PlaylistOfTheDayPlugin(Plugin):
"""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
the plugin. Later this plugin may feed its playlist using links unhandled by other,
more specialized plugins (bandcamp, soundcloud, …).
@@ -27,12 +41,26 @@ class PlaylistOfTheDayPlugin(Plugin):
def __init__(self, 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):
if not self.should_handle_command(event.arguments[0], no_content=True):
return False
-
- # self.post_playlist(event.target)
+ self.post_playlist(event.target)
return True
def add_line(self, line: str) -> None:
@@ -62,5 +90,29 @@ class PlaylistOfTheDayPlugin(Plugin):
today.isoformat(),
)
- # def post_playlist(self):
- # pass
+ def post_playlist(self, target):
+ 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"{item}", linkified_items)
+ html_list = "" + "".join(html_items) + "
"
+ 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'\1', text)
diff --git a/edmond/plugins/shrlok.py b/edmond/plugins/shrlok.py
index 381e769..3751dbe 100644
--- a/edmond/plugins/shrlok.py
+++ b/edmond/plugins/shrlok.py
@@ -1,5 +1,6 @@
import json
import socket
+from typing import Optional
from edmond.bot import Bot
from edmond.plugin import Plugin
@@ -31,7 +32,7 @@ class ShrlokPlugin(Plugin):
self.bot.log_d("No socket path specified, shrlok plugin disabled.")
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()
try:
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}")
return None
url = response.decode().replace(self.file_root, self.url_root, 1)
- return url
+ return url or None # returning empty strings could cause confusion