commit 75ed0bd64f8a961358a412d3ceb9336ae3ab2509 Author: Ben Harris Date: Mon Jul 13 01:25:26 2020 -0400 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/envs.py b/envs.py new file mode 100644 index 0000000..67c43cb --- /dev/null +++ b/envs.py @@ -0,0 +1,18 @@ +from src import ModuleManager, utils + +URL = "https://envs.sh" + +class Module(ModuleManager.BaseModule): + def on_load(self): + self.exports.add("shorturl-s-envssh", self._shorturl) + def _shorturl(self, url): + if len(url) < 18: + return None + + page = utils.http.request(URL, method="POST", + post_data={"shorten": url}) + + if page and page.data: + return page.decode("utf8").rstrip("\n") + return None + diff --git a/tilderadio.py b/tilderadio.py new file mode 100644 index 0000000..f899002 --- /dev/null +++ b/tilderadio.py @@ -0,0 +1,213 @@ +import emoji +import json +import random +from mastodon import Mastodon +from src import ModuleManager, utils + +CHANNEL = "#tilderadio" +NOTIFY_CHANNELS = [CHANNEL, "#meta", "#team", "#club"] +LISTEN_URL = "https://tilderadio.org/listen" +SCHEDULE_URL = "https://tilderadio.org/schedule/" +SOURCE_URL = "https://tildegit.org/tilderadio/radiobot" +RADIO_API_BASE = "https://radio.tildeverse.org/api" +TOOT_CREDS_FILE = "/home/ben/.bitbot/tilderadio-toot.json" +SLOGANS = [ + "The soundtrack in your cat's head", + "Your cat says she likes us better", + "radio for the people", + "radio by bots, for bots", + "On the Internet, no one knows you're a weakly superhuman AGI with a really good speech synth module.", + "We found your cat", + "cats.", + "a hacker's excuse for radio", + "0::1 is where the heart is", + "now with the longest slogan in human history", + "reticulating splines", + "Hold the shift", + "a very serious place for very serious happenings", + "sorry, this extension is invalid", + "This is the radio you were looking for", + "Not The Illuminati, We Promise", + "the radio is coming from INSIDE the house", + "Dont Sue Us!", + "it's radio minus radio", + "where your passwords are stored in plain text", + "Like radio. Only better.", + "tomasino 0wnz y0u!", + "that escalated quickly", + "music for your brain meats", + "003 Days Since Last Workplace Accident", + "*heavy breathing*", + "Dizzy? We stop the world from spinning", + "Where Disney Princesses Go Slumming", + 'any slogan but "eat the poop or die"', + "that's not what she said!", + "not product placement, we promise! (tildestore.com)", +] + + +class Module(ModuleManager.BaseModule): + now_playing = "" + dj = "" + song = "" + listeners = 0 + mastodon = None + is_online = False + + def save_nowplaying(self, jsontxt): + if jsontxt == "": + data = utils.http.request(RADIO_API_BASE + "/nowplaying/1").json() + else: + data = json.loads(jsontxt) + + self.is_online = data["live"]["is_live"] + self.dj = data["live"]["streamer_name"] + self.song = data["now_playing"]["song"]["text"] + self.listeners = data["listeners"]["current"] + + def format_nowplaying(self): + ret = "" + if self.is_online: + ret = f"({self.dj}) " + ret += f"now playing: {self.song} ~~ {self.listeners} listeners" + return ret + + def on_load(self): + self.save_nowplaying("") + + with open(TOOT_CREDS_FILE, "r") as f: + creds = json.load(f) + self.mastodon = Mastodon( + client_id=creds["client_id"], + client_secret=creds["client_secret"], + access_token=creds["access_token"], + api_base_url=creds["base_url"], + ) + + @utils.hook("api.get.slogan", authenticated=False) + def httpslogan(self, event): + return random.choice(SLOGANS) + + @utils.hook("api.post.radio") + def hook(self, event): + previous_dj = self.dj + self.save_nowplaying(event["data"]) + + # new dj online! + if self.dj != "" and self.dj != previous_dj: + newdj_message = f"{self.dj} is now online playing {self.song}! tune in here now: {LISTEN_URL}" + + self.mastodon.toot(newdj_message) + + # TODO: send dm notifications + # TODO: send email notifications + + if "tilde" in self.bot.servers: + server = self.bot.servers["tilde"] + for channel_name in NOTIFY_CHANNELS: + if channel_name in server.channels: + channel = server.channels[channel_name] + + self.events.on("send.stdout").call( + target=channel, + module_name="Tilderadio", + server=server, + message=newdj_message, + ) + + # post new songs while streaming + if self.is_online: + if "tilde" in self.bot.servers: + server = self.bot.servers["tilde"] + if CHANNEL in server.channels: + channel = server.channels[CHANNEL] + + self.events.on("send.stdout").call( + target=channel, + module_name="Tilderadio", + server=server, + message=now_playing, + ) + + @utils.hook("received.command.np", alias_of="nowplaying") + @utils.hook("received.command.nowplaying") + @utils.kwarg("help", "show the current song on tilderadio") + def nowplaying(self, event): + event["stdout"].write(self.format_nowplaying()) + + @utils.hook("received.command.schedule") + @utils.kwarg("help", "show a link to the tilderadio schedule") + def schedule(self, event): + event["stdout"].write(f"you can find the schedule here: {SCHEDULE_URL}") + + @utils.hook("received.command.un", alias_of="upnext") + @utils.hook("received.command.upnext") + @utils.kwarg("help", "show who's up next to stream") + def upnext(self, event): + js = utils.http.request(RADIO_API_BASE + "/station/1/schedule?rows=1").json() + if len(js) < 1: + event["stdout"].write("nothing scheduled") + else: + data = js[0] + start = utils.datetime.parse.iso8601(data["start"]) + now = utils.datetime.utcnow() + total_secs = (start - now).total_seconds() + event["stdout"].write( + "dj {} is up next at {} UTC in {}!".format( + data["name"], + utils.datetime.format.datetime_human(start), + utils.datetime.format.to_pretty_time(total_secs), + ) + ) + + @utils.hook("received.command.subscribe") + @utils.kwarg("help", "sign up to get a direct message when a new dj goes online") + def subscribe(self, event): + # TODO: save subscribe to db + event["stdout"].write("i'll send you a message when a dj goes online") + + @utils.hook("received.command.unsubscribe") + @utils.kwarg("help", "unsubscribe from dj announcements") + def unsubscribe(self, event): + # TODO: remove sender from subscribers + event["stdout"].write("ok, i'll no longer send you dj announcements") + + @utils.hook("received.command.emailsubscribe") + @utils.kwarg("help", "sign up to get an email when a dj goes online") + @utils.spec("!string") + def email_subscribe(self, event): + # TODO: add email subscription if not already there + email = event["spec"][0] + event["stdout"].write( + f"ok, i'll send an email to you at {email} when a dj goes online" + ) + + @utils.hook("received.command.emailunsubscribe") + @utils.kwarg("help", "stop sending email notifications") + def email_unsubscribe(self, event): + # TODO: remove email subscription if there + event["stdout"].write("ok i'll stop sending you emails") + + @utils.hook("received.command.dj") + @utils.kwarg("help", "check if someone is currently streaming") + def showdj(self, event): + if self.dj == "": + message = "no one is currently on the air" + else: + message = f"dj {self.dj} is now streaming!" + event["stdout"].write(message) + + @utils.hook("received.command.slogan") + @utils.kwarg("help", "get a random tilderadio slogan") + def slogan(self, event): + event["stdout"].write(random.choice(SLOGANS)) + + @utils.hook("received.command.toot") + @utils.kwarg("help", "send a toot from the tilderadio mastodon account") + @utils.spec("!string") + def toot(self, event): + status = event["spec"][0] + if len(status) > 8: + status = emoji.emojize(status, use_aliases=True) + uri = self.mastodon.toot(status)["uri"] + event["stdout"].write(f"tooted!: {uri}") diff --git a/ttm.py b/ttm.py new file mode 100644 index 0000000..cf5ec1a --- /dev/null +++ b/ttm.py @@ -0,0 +1,18 @@ +from src import ModuleManager, utils + +URL = "https://ttm.sh" + +class Module(ModuleManager.BaseModule): + def on_load(self): + self.exports.add("shorturl-s-ttmsh", self._shorturl) + def _shorturl(self, url): + if len(url) < 18: + return None + + page = utils.http.request(URL, method="POST", + post_data={"shorten": url}) + + if page and page.data: + return page.decode("utf8").rstrip("\n") + return None +