bad therapy bot
This commit is contained in:
commit
2cd1a65408
19
LICENSE
Normal file
19
LICENSE
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
MIT License Copyright (c) 2022 xenofem <xenofematxenodotscience>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||||
|
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||||
|
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
README.md
Normal file
21
README.md
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Mikage Bot
|
||||||
|
|
||||||
|
Discord bot to give questionable elevator therapy
|
||||||
|
|
||||||
|
## Discord setup
|
||||||
|
|
||||||
|
Required permissions:
|
||||||
|
- Manage channels
|
||||||
|
- Read messages/view channels
|
||||||
|
- Send messages
|
||||||
|
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
git clone https://git.xeno.science/xenofem/mikage-bot
|
||||||
|
cd mikage-bot
|
||||||
|
python3 -m venv env
|
||||||
|
source env/bin/activate
|
||||||
|
pip install py-cord
|
||||||
|
echo <token> > token
|
||||||
|
python bot.py
|
116
bot.py
Normal file
116
bot.py
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
import discord
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
STATE_FILE = 'state.json'
|
||||||
|
CHANNEL_NAME = 'therapy-elevator'
|
||||||
|
DELETION_SECONDS = 300
|
||||||
|
|
||||||
|
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.' '🐛', '🍃']
|
||||||
|
FINAL_MESSAGE = 'I understand. Your only choice is to revolutionize the world. The path you must take has been prepared for you.'
|
||||||
|
ROSE = '🌹'
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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:
|
||||||
|
with open(STATE_FILE) as f:
|
||||||
|
self.state = json.load(f)
|
||||||
|
except:
|
||||||
|
self.state = {}
|
||||||
|
self.save_state()
|
||||||
|
|
||||||
|
def save_state(self):
|
||||||
|
with open(STATE_FILE, 'w') as f:
|
||||||
|
json.dump(self.state, f)
|
||||||
|
|
||||||
|
async def on_ready(self):
|
||||||
|
print(f"logged in as {self.user}", file=sys.stderr)
|
||||||
|
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:
|
||||||
|
(top_category, channels) = guild.by_category()[0]
|
||||||
|
channel = await guild.create_text_channel(CHANNEL_NAME, category=top_category)
|
||||||
|
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)
|
||||||
|
|
||||||
|
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!")
|
||||||
|
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)
|
||||||
|
return
|
||||||
|
await self.initialize_elevator(message.guild)
|
||||||
|
|
||||||
|
client = MikageClient()
|
||||||
|
with open('token') as f:
|
||||||
|
token = f.read().strip()
|
||||||
|
client.run(token)
|
Loading…
Reference in a new issue