Compare commits

..

13 commits

Author SHA1 Message Date
xenofem d8270f558f give a ring at the end along with the rose 2022-03-25 21:20:11 -04:00
xenofem b6a7d38bed lint fixes 2022-03-25 21:08:50 -04:00
xenofem 5e38af2b63 Revert "fancier falling" - doesn't work well with discord ratelimits
This reverts commit 26a4fa7000.
2022-03-25 19:03:36 -04:00
xenofem 26a4fa7000 fancier falling 2022-03-25 19:01:15 -04:00
xenofem b702aaa475 add privacy info 2022-03-25 18:35:21 -04:00
xenofem dc0a6ce68f much shorter deletion time 2022-03-25 18:16:53 -04:00
xenofem 8c2eeeae3c tweak channel topic 2022-03-25 18:14:43 -04:00
xenofem 7d9d6012d9 more styling bits 2022-03-25 18:10:27 -04:00
xenofem 9117f0dfa1 tweak elevator shit period 2022-03-25 17:59:53 -04:00
xenofem 5a658a107f custom status 2022-03-25 17:49:49 -04:00
xenofem 2d9d30f4f7 screw around with descent some more 2022-03-25 17:37:39 -04:00
xenofem 8b6da55729 refactor butterflies 2022-03-25 16:00:49 -04:00
xenofem f4235d8245 checker fixes 2022-03-25 15:49:31 -04:00
2 changed files with 70 additions and 42 deletions

View file

@ -2,6 +2,15 @@
Discord bot to give questionable elevator therapy
## Privacy
This bot does not persistently store any data except for the numerical
IDs of each server it's in, and the numerical ID of the channel it
creates for itself in each server. It does not make use of any data
except for the list of channels. It does not read message
contents. It only creates one channel for itself, and does not
interact at all outside of that channel.
## Discord setup
Required permissions:
@ -9,8 +18,7 @@ Required permissions:
- Read messages/view channels
- Send messages
## Setup
## Bot setup
git clone https://git.xeno.science/xenofem/mikage-bot
cd mikage-bot

100
bot.py
View file

@ -1,18 +1,31 @@
import discord
import asyncio
import json
import random
import sys
import discord
STATE_FILE = 'state.json'
CHANNEL_NAME = 'therapy-elevator'
DELETION_SECONDS = 300
DELETION_SECONDS = 15
TYPING_DELAY = 2
SETUP_MESSAGE = 'Welcome to Nemuro Memorial Hall. Please give your name and class year for our records.'
INITIAL_MESSAGE = 'All right, please begin.'
BUTTERFLIES = ['🦋', '🥐', 'Deeper. Go deeper.' '🐛', '🍃']
BUTTERFLIES = ['🦋', 'Deeper. Go deeper.', '🥐', '🐛', '🥚', '🍃']
ELEVATOR_SHIT_PERIOD = 5
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*',
'*a rattling. the elevator begins to shake*',
'*a squealing of cables and pulleys*',
]
CRASH = ('|\n'*10) + '***the elevator crashes to the bottom***' + ('\n'*10) + '...'
FINAL_MESSAGE = 'I understand. Your only choice is to revolutionize the world. The path you must take has been prepared for you.'
ROSE = '🌹'
ROSE = '🌹💍'
async def try_send(channel, message):
try:
@ -20,6 +33,13 @@ async def try_send(channel, message):
except discord.DiscordException as e:
print(f"error sending message in channel {channel}: {e}", file=sys.stderr)
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)
await try_send(channel, "Dammit, the elevator's stuck!")
def text_only(channels):
return [channel for channel in channels if isinstance(channel, discord.TextChannel)]
@ -27,18 +47,19 @@ class MikageClient(discord.Client):
def __init__(self):
super().__init__()
try:
with open(STATE_FILE) as f:
with open(STATE_FILE, encoding='utf-8') as f:
self.state = json.load(f)
except:
except FileNotFoundError:
self.state = {}
self.save_state()
def save_state(self):
with open(STATE_FILE, 'w') as f:
with open(STATE_FILE, 'w', encoding='utf-8') as f:
json.dump(self.state, f)
async def on_ready(self):
print(f"logged in as {self.user}", file=sys.stderr)
await self.change_presence(activity=discord.Game('the dueling game, for keeps'))
for guild in self.guilds:
await self.initialize_elevator(guild)
@ -51,8 +72,12 @@ class MikageClient(discord.Client):
if guild_id in self.state and guild.get_channel(self.state[guild_id]['channel']) is not None:
return
try:
(top_category, channels) = guild.by_category()[0]
channel = await guild.create_text_channel(CHANNEL_NAME, category=top_category)
top_category = guild.by_category()[0][0]
channel = await guild.create_text_channel(
CHANNEL_NAME,
category=top_category,
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"
)
await channel.move(category=top_category, beginning=True)
self.state[guild_id] = {'channel': channel.id}
self.save_state()
@ -78,39 +103,34 @@ class MikageClient(discord.Client):
if category_index == 0 and channel_index == 0:
await try_send(message.channel, INITIAL_MESSAGE)
if channel_index == len(channels) - 1:
if category_index == len(categories) - 1:
return
target_category = categories[category_index+1][0]
target_position = 0
else:
target_category = category
target_position = channel_index+1
try:
await message.channel.move(category=target_category, beginning=True, offset=target_position)
except discord.DiscordException as e:
print(f"error moving channel {message.channel} in guild {message.guild}: {e}", file=sys.stderr)
await try_send(message.channel, "Dammit, the elevator's stuck!")
if category_index == len(categories) - 1:
return
if target_position == 0:
await try_send(message.channel, BUTTERFLIES[int(category_index*len(BUTTERFLIES)/(len(categories)-1))])
final_category_channels = text_only(message.guild.by_category()[-1][1])
if len(final_category_channels) > 0 and message.channel == final_category_channels[-1]:
await try_send(message.channel, FINAL_MESSAGE)
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)
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
await self.initialize_elevator(message.guild)
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))])
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))
client = MikageClient()
with open('token') as f:
with open('token', encoding='utf-8') as f:
token = f.read().strip()
client.run(token)