mikage-bot/bot.py

137 lines
5.5 KiB
Python
Raw Permalink Normal View History

2022-03-25 15:37:33 -04:00
import asyncio
import json
2022-03-25 16:00:49 -04:00
import random
2022-03-25 15:37:33 -04:00
import sys
2022-03-25 15:49:31 -04:00
import discord
2022-03-25 15:37:33 -04:00
STATE_FILE = 'state.json'
CHANNEL_NAME = 'therapy-elevator'
2022-03-25 18:16:53 -04:00
DELETION_SECONDS = 15
2022-03-25 17:37:39 -04:00
TYPING_DELAY = 2
2022-03-25 15:37:33 -04:00
SETUP_MESSAGE = 'Welcome to Nemuro Memorial Hall. Please give your name and class year for our records.'
INITIAL_MESSAGE = 'All right, please begin.'
2022-03-25 17:37:39 -04:00
BUTTERFLIES = ['🦋', 'Deeper. Go deeper.', '🥐', '🐛', '🥚', '🍃']
2022-03-25 17:59:53 -04:00
ELEVATOR_SHIT_PERIOD = 5
2022-03-25 17:37:39 -04:00
ELEVATOR_SHIT = [
'*the elevator creaks eerily*',
'*menacing discordant music plays*',
'*drawers rush past on the walls outside*',
'*the lights flicker*',
'*the elevator jolts, then continues its descent*',
2022-03-25 21:08:50 -04:00
'*a rattling. the elevator begins to shake*',
'*a squealing of cables and pulleys*',
2022-03-25 17:37:39 -04:00
]
CRASH = ('|\n'*10) + '***the elevator crashes to the bottom***' + ('\n'*10) + '...'
2022-03-25 15:37:33 -04:00
FINAL_MESSAGE = 'I understand. Your only choice is to revolutionize the world. The path you must take has been prepared for you.'
ROSE = '🌹💍'
2022-03-25 15:37:33 -04:00
async def try_send(channel, message):
try:
await channel.send(message)
except discord.DiscordException as e:
print(f"error sending message in channel {channel}: {e}", file=sys.stderr)
2022-03-25 17:37:39 -04:00
async def try_move(channel, **kwargs):
try:
await channel.move(**kwargs)
except discord.DiscordException as e:
print(f"error moving channel {channel}: {e}", file=sys.stderr)
2022-03-25 21:08:50 -04:00
await try_send(channel, "Dammit, the elevator's stuck!")
2022-03-25 17:37:39 -04:00
2022-03-25 15:37:33 -04:00
def text_only(channels):
return [channel for channel in channels if isinstance(channel, discord.TextChannel)]
class MikageClient(discord.Client):
def __init__(self):
super().__init__()
try:
2022-03-25 15:49:31 -04:00
with open(STATE_FILE, encoding='utf-8') as f:
2022-03-25 15:37:33 -04:00
self.state = json.load(f)
2022-03-25 15:49:31 -04:00
except FileNotFoundError:
2022-03-25 15:37:33 -04:00
self.state = {}
self.save_state()
def save_state(self):
2022-03-25 15:49:31 -04:00
with open(STATE_FILE, 'w', encoding='utf-8') as f:
2022-03-25 15:37:33 -04:00
json.dump(self.state, f)
async def on_ready(self):
print(f"logged in as {self.user}", file=sys.stderr)
2022-03-25 17:49:49 -04:00
await self.change_presence(activity=discord.Game('the dueling game, for keeps'))
2022-03-25 15:37:33 -04:00
for guild in self.guilds:
await self.initialize_elevator(guild)
async def on_guild_join(self, guild):
print(f"joined new guild: {guild}", file=sys.stderr)
await self.initialize_elevator(guild)
async def initialize_elevator(self, guild):
guild_id = str(guild.id)
if guild_id in self.state and guild.get_channel(self.state[guild_id]['channel']) is not None:
return
try:
2022-03-25 15:49:31 -04:00
top_category = guild.by_category()[0][0]
2022-03-25 18:10:27 -04:00
channel = await guild.create_text_channel(
CHANNEL_NAME,
category=top_category,
2022-03-25 18:14:43 -04:00
topic="the he/they therapist - you know, the one who lives in the morgue in the basement of that building that doesn't exist? - is in"
2022-03-25 18:10:27 -04:00
)
2022-03-25 15:37:33 -04:00
await channel.move(category=top_category, beginning=True)
self.state[guild_id] = {'channel': channel.id}
self.save_state()
await channel.send(SETUP_MESSAGE)
except discord.DiscordException as e:
print(f"error initializing elevator for guild {guild}: {e}", file=sys.stderr)
return
async def on_message(self, message):
if message.guild is None:
return
guild_id = str(message.guild.id)
if guild_id not in self.state or message.channel.id != self.state[guild_id]['channel']:
return
if message.author == self.user:
return
categories = message.guild.by_category()
(category_index, (category, channels)) = [entry for entry in enumerate(categories) if message.channel in entry[1][1]][0]
channels = text_only(channels)
channel_index = channels.index(message.channel)
2022-03-25 16:00:49 -04:00
if category_index == 0 and channel_index == 0:
await try_send(message.channel, INITIAL_MESSAGE)
2022-03-25 17:37:39 -04:00
if category_index == len(categories) - 1:
return
if channel_index == len(channels) - 1:
if category_index == len(categories) - 2:
await message.channel.move(category=categories[-1][0], end=True)
await try_send(message.channel, CRASH)
await asyncio.sleep(TYPING_DELAY)
await try_send(message.channel, FINAL_MESSAGE)
await asyncio.sleep(TYPING_DELAY)
await try_send(message.channel, ROSE)
await asyncio.sleep(DELETION_SECONDS)
try:
await message.channel.delete()
del self.state[guild_id]
self.save_state()
except discord.DiscordException as e:
print(f"error deleting elevator for guild {message.guild}: {e}", file=sys.stderr)
return
await self.initialize_elevator(message.guild)
return
2022-03-25 21:08:50 -04:00
await try_move(message.channel, category=categories[category_index+1][0], beginning=True)
await try_send(message.channel, BUTTERFLIES[int(category_index*len(BUTTERFLIES)/(len(categories)-2))])
2022-03-25 17:37:39 -04:00
else:
await try_move(message.channel, category=category, beginning=True, offset=channel_index+1)
if random.randrange(ELEVATOR_SHIT_PERIOD) == 0:
await try_send(message.channel, random.choice(ELEVATOR_SHIT))
2022-03-25 15:37:33 -04:00
client = MikageClient()
2022-03-25 15:49:31 -04:00
with open('token', encoding='utf-8') as f:
2022-03-25 15:37:33 -04:00
token = f.read().strip()
client.run(token)