680 lines
36 KiB
Python
680 lines
36 KiB
Python
import asyncio
|
||
from copy import copy
|
||
import datetime
|
||
import discord
|
||
from discord.ext import commands, menus
|
||
from pathlib import Path
|
||
import os
|
||
import random
|
||
import re
|
||
import requests
|
||
import signal
|
||
import tempfile
|
||
import time
|
||
from typing import List, Optional
|
||
|
||
from . import logger, glob
|
||
from . import flags
|
||
from .utils import Embeds, MenuListPageSource, role_names
|
||
|
||
|
||
class Chat(commands.Cog):
|
||
|
||
def __init__(self, bot):
|
||
self.bot = bot
|
||
|
||
self.flag_parser = flags.Flag(raise_errors=False)
|
||
self.flag_parser.add_flag('--all',
|
||
store_type=flags.StoreType.store_bool,
|
||
allowed_roles=['Mod'],
|
||
not_allowed_role_message='Nur Mods können die `{flag}` flag benutzen',
|
||
wrong_store_type_message='Die `{flag}` flag darf keinen parameter haben',
|
||
show_help=False)
|
||
self.flag_parser.add_flag('--limit',
|
||
store_type=(flags.StoreType.store_value, 100),
|
||
parser=self._parse_history,
|
||
wrong_store_type_message='Die {flag} muss eine Zahl als parameter haben',
|
||
help='')
|
||
|
||
async def _parse_history(self, ctx: commands.Context, flag, value):
|
||
try:
|
||
return int(value)
|
||
except ValueError:
|
||
await ctx.send(f'Der parameter der `{flag}` muss eine Zahl sein')
|
||
return False
|
||
|
||
@commands.command(name='export', ignore_extra=False,
|
||
usage='export [flags]', help='Exportiert den Chat',
|
||
flags='flag_parser')
|
||
async def history(self, ctx: commands.Context, *, args):
|
||
parsed = await self.flag_parser.parse(args, ctx=ctx)
|
||
pass
|
||
|
||
|
||
# ADDED AFTERWARS: This never was really active in use
|
||
class Economy(commands.Cog):
|
||
|
||
def __init__(self, bot):
|
||
self.bot = bot
|
||
self.cooldown = {}
|
||
self.cooldown_date = datetime.datetime.now()
|
||
|
||
self.shop_items = {
|
||
'color': [10000, self.bot.database.set_user_color_count, 'Nachrichten Farbe', True, 'Setzt die Farbe die rechts bei den Bot Nachrichten, die von <@!802659482693926943> kommen'],
|
||
'extra vote': [150, self.bot.database.set_user_extra_vote, 'Extra Vote', False, 'Kann eine Umfrage starten, selbst wenn man normalerweise noch Umfrage cooldown hätte']
|
||
}
|
||
|
||
@commands.command(name='buy', aliases=['b'], usage='buy <zu kaufendes item>', help='Kauft ein Shop Item. Tippe `$shop` um alle verfügbaren Items zu sehen')
|
||
async def buy(self, ctx: commands.Context, *item):
|
||
await ctx.send(embed=Embeds.error_embed(description='Der Befehl steht wegen bearbeitung temporär nicht zur Verfügung'))
|
||
return
|
||
to_buy = ' '.join(item)
|
||
if values := self.shop_items.get(to_buy, None):
|
||
if self.bot.database.has_remove_user_gold(ctx.author.id, values[0]):
|
||
embed = discord.Embed(title='Item kauf')
|
||
embed.add_field(name=values[2], value=f'*{values[4]}*\n\n'
|
||
f'<@!{ctx.author.id}> erhält:\n'
|
||
f'```diff\n'
|
||
f'+1 {values[2]}'
|
||
f'```\n'
|
||
f'<@!{ctx.author.id}> bezahlt:\n'
|
||
f'```diff\n'
|
||
f'- {values[0]} Gold\n'
|
||
f'```')
|
||
message = await ctx.send(embed=embed)
|
||
await message.add_reaction('❌')
|
||
await message.add_reaction('✅')
|
||
|
||
def check(reaction: discord.Reaction, user):
|
||
return user.id == ctx.author.id and reaction.message.id == message.id and str(reaction.emoji) in ['❌', '✅']
|
||
|
||
try:
|
||
reaction, user = await self.bot.wait_for('reaction_add', timeout=30, check=check)
|
||
if reaction.emoji == '❌':
|
||
embed.colour = 0xff0000
|
||
msg = 'Der Kauf wurde abgebrochen'
|
||
elif reaction.emoji == '✅':
|
||
values[1](ctx.author.id, 1)
|
||
embed.colour = 0x00ff00
|
||
msg = f'**{values[2]}** wurde gekauft{f". Tippe `$use {to_buy}` um das Item zu benutzen!" if values[3] else "!"}'
|
||
else:
|
||
msg = 'Hackerman hat den Bot überlistet, weshalb diese Nachricht erscheint, die eigentlich niemals hätte erscheinen dürfen'
|
||
|
||
embed.clear_fields()
|
||
embed.add_field(name=values[2], value=f'*{values[4]}*\n\n'
|
||
f'<@!{ctx.author.id}> erhält:\n'
|
||
f'```diff\n'
|
||
f'+1 {values[2]}'
|
||
f'```\n'
|
||
f'<@!{ctx.author.id}> bezahlt:\n'
|
||
f'```diff\n'
|
||
f'- {values[0]} Gold\n'
|
||
f'```\n'
|
||
f'{msg}')
|
||
await message.edit(embed=embed)
|
||
except asyncio.exceptions.TimeoutError:
|
||
pass
|
||
else:
|
||
await ctx.send(embed=Embeds.error_embed(description='Du hast nicht genügend Gold um dieses Item zu kaufen'))
|
||
else:
|
||
await ctx.send(embed=Embeds.error_embed(description=f'Es existiert kein Item mit dem Name `{to_buy}`'))
|
||
|
||
@commands.command(name='items', aliases=['i'], usage='items', help='Zeigt alle Items im besitzt an')
|
||
async def items(self, ctx: commands.Context, *, user_mention: str = None):
|
||
await ctx.send(embed=Embeds.error_embed(description='Der Befehl steht wegen bearbeitung temporär nicht zur Verfügung'))
|
||
return
|
||
id = ctx.author.id
|
||
if user_mention is not None:
|
||
regex_id = re.match(r'^<@(!)?(?P<id>\d{18})>', user_mention)
|
||
if regex_id:
|
||
id = regex_id.group('id')
|
||
else:
|
||
await Help(self.bot).show_help(ctx, ctx.command)
|
||
return
|
||
|
||
embeds = []
|
||
embed = discord.Embed(title='Items', description=f'Items von <@!{id}>')
|
||
embed.set_footer(text='Alle Items die mit 💫 beginnen können über `$use <item>` benutzt werden!')
|
||
for name, value in self.bot.database.get_user_items(id).items():
|
||
if len(embed.fields) >= 10:
|
||
embeds.append(embed)
|
||
embed = discord.Embed(title='Items', description=f'Items von <@!{id}>')
|
||
embed.set_footer(text='Alle Items die mit 💫 beginnen können über `$use <item>` benutzt werden!')
|
||
if name == 'gold':
|
||
embed.description += f'\n\n:moneybag: **{value}** *Gold*'
|
||
elif value > 0:
|
||
item = self.shop_items[name]
|
||
embed.description += f'\n{":dizzy:" if item[3] else ":sparkles:"} **{value}** · `{name}` · *{item[2]}*'
|
||
embeds.append(embed)
|
||
|
||
send_embeds = menus.MenuPages(source=MenuListPageSource(embeds), clear_reactions_after=True, timeout=30)
|
||
await send_embeds.start(ctx)
|
||
|
||
@commands.command(name='leaderboard', aliases=['l'], usage='leaderboard', help='Zeigt das Server Leaderboard an')
|
||
async def leaderboard(self, ctx: commands.Context):
|
||
await ctx.send(embed=Embeds.error_embed(description='Der Befehl steht wegen bearbeitung temporär nicht zur Verfügung'))
|
||
return
|
||
gold_leaderboard = discord.Embed(title='Gold Leaderboard', description='*Man kann alle 2 Minuten zwischen 5 und 15 Gold bekommen, wenn man in diesen Zeitabständen eine Nachricht schreibt. '
|
||
'Die gedroppte Gold Anzahl wird mit deinem Kaizen-Sub Level addiert (Server Booster gelten als Sub Level 2).\n'
|
||
'Also je aktiver, desto mehr Gold:moneybag:^^*')
|
||
gold_leaderboard.set_footer(text='Tippe `$shop` um dir anzusehen, was du alles kaufen kannst!')
|
||
gold_text = ''
|
||
|
||
for i, (id, gold) in enumerate(self.bot.database.get_leaderboard().items(), 1):
|
||
gold_text += f'\n{i}. - `{gold}` Gold · __**{(await self.bot.guild.fetch_member(id)).display_name}**__'
|
||
|
||
gold_leaderboard.add_field(name='Top 10', value=gold_text)
|
||
|
||
menu = menus.MenuPages(source=MenuListPageSource([gold_leaderboard]))
|
||
await menu.start(ctx)
|
||
|
||
@commands.command(name='shop', aliases=['s'], usage='shop', help='Zeigt alle Shop Elemente an')
|
||
async def shop(self, ctx: commands.Context):
|
||
await ctx.send(embed=Embeds.error_embed(description='Der Befehl steht wegen bearbeitung temporär nicht zur Verfügung'))
|
||
return
|
||
embeds = []
|
||
embed = discord.Embed(title='Show durchsuchen')
|
||
for name, item in self.shop_items.items():
|
||
if len(embed.fields) >= 10:
|
||
embeds.append(embed)
|
||
embed = discord.Embed(title='Show durchsuchen')
|
||
embed.add_field(name=item[2], value=f'*{item[4]}*\n'
|
||
f'```diff\n'
|
||
f'- {item[0]} Gold\n'
|
||
f'+ 1 {item[2]}\n'
|
||
f'> $buy {name}\n'
|
||
f'```', inline=False)
|
||
embeds.append(embed)
|
||
|
||
embeds = menus.MenuPages(source=MenuListPageSource(embeds), clear_reactions_after=True, timeout=30)
|
||
await embeds.start(ctx)
|
||
|
||
@commands.command(name='use', aliases=['u'], usage='use', help='Benutzt ein Item')
|
||
async def use(self, ctx: commands.Context, *args):
|
||
await ctx.send(embed=Embeds.error_embed(description='Der Befehl steht wegen bearbeitung temporär nicht zur Verfügung'))
|
||
return
|
||
pass
|
||
|
||
# --- #
|
||
|
||
@commands.Cog.listener()
|
||
@commands.guild_only()
|
||
async def on_message(self, message: discord.Message):
|
||
return
|
||
if not message.author.bot and message.channel.id not in [812436978809307156, # rank abfrage
|
||
822938804461502524, # offene daten
|
||
813135345725341736, # karuta
|
||
813886662841073684, # rin
|
||
813487848027193398]: # quiz erraten
|
||
now = time.time()
|
||
cooldown = self.cooldown.get(message.author.id, [0.0, 0])
|
||
if cooldown[1] < 120 and cooldown[0] + 120 < now:
|
||
cooldown[0] = now
|
||
cooldown[1] += 1
|
||
self.cooldown[message.author.id] = cooldown
|
||
|
||
gold = random.randint(5, 15)
|
||
roles = role_names(message.author)
|
||
|
||
if 'Kaizen-Sub: Level 3' in roles:
|
||
gold += 3
|
||
elif 'Kaizen-Sub: Level 2' in roles:
|
||
gold += 2
|
||
elif 'Kaizen-Sub: Level 1' in roles:
|
||
gold += 1
|
||
if 'Server Booster' in roles:
|
||
gold += 2
|
||
|
||
self.bot.database.add_user_gold(message.author.id, gold)
|
||
|
||
def reset(self):
|
||
for key in self.cooldown:
|
||
self.cooldown[key] = [0.0, 0]
|
||
|
||
|
||
# ADDED AFTERWARDS: I had the idea of implementing familiarly relationship and show it in a tree
|
||
# but this was never finished (not that I really started to try working on it)
|
||
class Family(commands.Cog):
|
||
|
||
def __init__(self, bot):
|
||
self.bot = bot
|
||
|
||
@commands.command(name='tree', usage='tree', help='Zeigt den Familienstammbaum')
|
||
@commands.guild_only()
|
||
async def family_tree(self, ctx: commands.Context):
|
||
self.bot.database.get_user_parents(ctx.author.id)
|
||
|
||
def _family_tree(self, id: int) -> List[List[str]]:
|
||
parents = self.bot.database.get_user_parents()
|
||
if parents:
|
||
|
||
return [].extend()
|
||
else:
|
||
return [self.bot.guild.fetch_member(id).display_name]
|
||
|
||
|
||
class Mod(commands.Cog):
|
||
|
||
def __init__(self, bot):
|
||
self.bot = bot
|
||
|
||
@commands.command(name='error', usage='error')
|
||
@commands.guild_only()
|
||
@commands.has_role('Mod')
|
||
async def error(self, ctx: commands.Context):
|
||
logger.info('NOTICE: Raising controlled exception...')
|
||
raise Exception('Exception raised by the error command')
|
||
|
||
@commands.command(name='restart', usage='restart')
|
||
@commands.guild_only()
|
||
@commands.has_role('Mod')
|
||
async def restart(self, ctx: commands.Context):
|
||
for thread in glob['timers']:
|
||
thread.cancel()
|
||
logger.info('Restarting...')
|
||
os.kill(os.getpid(), signal.SIGKILL)
|
||
|
||
@commands.command(name='transcript', usage='transcript', help='Schickt eine Datei mit dem gesamten Nachrichtenverlauf der letzten Stunde')
|
||
@commands.guild_only()
|
||
@commands.has_role('Mod')
|
||
async def transcript(self, ctx: commands.Context):
|
||
tmp = tempfile.mktemp('.txt')
|
||
with open(tmp, 'w+') as file:
|
||
for message in glob['transcript'].values():
|
||
file.write(message + '\n')
|
||
file.close()
|
||
await ctx.send(file=discord.File(tmp, 'transcript.txt'))
|
||
os.remove(tmp)
|
||
|
||
|
||
class Help(commands.Cog):
|
||
|
||
def __init__(self, bot):
|
||
self.bot = bot
|
||
|
||
async def show_help(self, ctx: commands.Context, command: commands.Command):
|
||
embed = discord.Embed(title=f'`{command.name}` command\n\n', color=discord.Color(0xff0000))
|
||
embed.set_footer(text='<...> - required; [...] - optional; <...|...> - or\nDo NOT include <>, [] or | when executing the command')
|
||
embed.add_field(name='Usage', value=f'`{self.bot.command_prefix}{command.usage}`', inline=False)
|
||
embed.add_field(name='Description', value=command.help, inline=False)
|
||
if command_flags := flags.get_flags(command):
|
||
all_flags = {}
|
||
for flag, info in command_flags.flags().items():
|
||
if info['show_help']:
|
||
hash_sum = hash(str(info))
|
||
if hash_sum not in all_flags:
|
||
all_flags[hash_sum] = copy(info)
|
||
all_flags[hash_sum]['names'] = [flag]
|
||
else:
|
||
all_flags[hash_sum]['names'].append(flag)
|
||
embed.add_field(name='Flags', value='\n'.join([f'• `{"`, `".join(flag["names"])}` - {flag["help"].format(flag=flag["names"][0])}' for flag in all_flags.values()]), inline=False)
|
||
await ctx.send(embed=embed)
|
||
|
||
@commands.command(name='commands', usage='commands', description='Liste alle verfügbaren Befehle auf')
|
||
async def cmds(self, ctx: commands.Context):
|
||
commands = {command.name: command for command in self.bot.commands}
|
||
groups = {'default': []}
|
||
for command in sorted(commands):
|
||
if hasattr(command, 'group'):
|
||
if command.group not in groups:
|
||
groups[command.group] = []
|
||
groups[command.group].append(commands[command])
|
||
new_line = '\n'
|
||
embed = discord.Embed(title='Commands', description=f'Um Hilfe zu einem bestimmten Befehl zu bekommen, tippe `{self.bot.command_prefix}help [command]`',
|
||
color=discord.Color(0xff0000))
|
||
|
||
for group_name, group in groups.items():
|
||
embed.add_field(name=group_name, value=f'```• {f"{new_line}• ".join([self.bot.command_prefix + command.usage for command in group])}```', inline=False)
|
||
await ctx.send(embed=embed)
|
||
|
||
@commands.command(name='help', usage='help [command]', description='Zeigt Hilfe an')
|
||
async def help(self, ctx: commands.Context, command: Optional[str]):
|
||
if command:
|
||
if cmd := self.bot.get_command(command):
|
||
await self.show_help(ctx, cmd)
|
||
else:
|
||
embed = discord.Embed(title=f'{self.bot.user.name} help', description=f'Der Befehl {command} existiert nicht!', color=discord.Color(0xff0000))
|
||
embed.add_field(name='Get help', value=f'Um Hilfe zu einem bestimmten Befehl zu bekommen, tippe `{self.bot.command_prefix}help [command]`', inline=False)
|
||
embed.add_field(name='Commands', value=f'Tippe `{self.bot.command_prefix}commands`, um eine Liste mit allen Befehlen zu bekommen', inline=False)
|
||
embed.set_footer(text='<...> - required; [...] - optional; <...|...> - or\nDo NOT include <>, [] or | when executing the command')
|
||
await ctx.send(embed=embed)
|
||
else:
|
||
embed = discord.Embed(title=f'{self.bot.user.name} help', color=discord.Color(0xff0000))
|
||
embed.add_field(name='Get help', value=f'Um Hilfe zu einem bestimmten Befehl zu bekommen, tippe `{self.bot.command_prefix}help [command]`', inline=False)
|
||
embed.add_field(name='Commands', value=f'Tippe `{self.bot.command_prefix}commands`, um eine Liste mit allen Befehlen zu bekommen', inline=False)
|
||
embed.set_footer(text='<...> - required; [...] - optional; <...|...> - or\nDo NOT include <>, [] or | when executing the command')
|
||
await ctx.send(embed=embed)
|
||
|
||
|
||
class Info(commands.Cog):
|
||
|
||
def __init__(self, bot):
|
||
self.bot = bot
|
||
|
||
self.flag_parser = flags.Flag()
|
||
|
||
@commands.command(name='info', usage='info [@user]', help='Zeigt Infos über einen Nutzer an')
|
||
@commands.guild_only()
|
||
async def info(self, ctx: commands.Context, *, user_mention: str = None):
|
||
id = ctx.author.id
|
||
if user_mention is not None:
|
||
regex_id = re.match(r'^<@(!)?(?P<id>\d{18})>', user_mention)
|
||
if regex_id:
|
||
id = regex_id.group('id')
|
||
else:
|
||
await Help(self.bot).show_help(ctx, ctx.command)
|
||
return
|
||
if (infos := self.bot.database.get_user_infos(id)) is None:
|
||
await ctx.send(embed=Embeds.error_embed(description="Der Nutzer existiert nicht"))
|
||
return
|
||
else:
|
||
member = await self.bot.guild.fetch_member(int(id))
|
||
name = member.display_name if member.display_name.lower().endswith(('s', 'z')) else member.display_name + "'s"
|
||
embed = discord.Embed(title=name + " Infos", color=member.roles[-1].color)
|
||
embed.set_thumbnail(url=member.avatar_url)
|
||
embed.set_footer(text='Tippe `$help addinfo` um zu sehen, was für Infos noch hinzugefügt / geändert werden können')
|
||
for key, value in infos.items():
|
||
if value is not None:
|
||
embed.add_field(name=key, value=value, inline=False)
|
||
if len(embed.fields) == 0:
|
||
embed.description = "Es wurden noch keine Infos eingetragen"
|
||
await ctx.send(embed=embed)
|
||
|
||
@commands.command(name='addinfo', aliases=['infoadd'], usage='addinfo <name, age | list | fav | waifu | husbando> <name, alter, link zu einer anime liste, lieblings anime, waifu, husbando>',
|
||
help='Fügt den Namen / das Alter / eine Anime Liste / einen Lieblings Anime / eine Waifu / ein Husbando zu einem Nutzer hinzu.\n\n'
|
||
'Tippe `$help removeinfo` um Infos wieder zu entfernen')
|
||
@commands.guild_only()
|
||
async def infoadd(self, ctx: commands.Context, info_type: str, *info_value):
|
||
if info_type.lower() == 'name':
|
||
self.bot.database.set_user_name(ctx.author.id, ' '.join(info_value))
|
||
await ctx.send(embed=Embeds.success_embed(description=f'Name (__{" ".join(info_value)}__) wurde hinzugefügt'))
|
||
elif info_type.lower() == 'age':
|
||
try:
|
||
age = int(info_value[0])
|
||
except ValueError:
|
||
await ctx.send(embed=Embeds.error_embed(description='`age` sollte eine Zahl sein'))
|
||
return
|
||
if age < 0:
|
||
await ctx.send(embed=Embeds.error_embed(description='Hmmm noch nie von einer Person gehört die minus Jahre alt ist'))
|
||
return
|
||
elif age > 99:
|
||
await ctx.send(embed=Embeds.error_embed(description='Uff, bei so einem hohen Alter komm selbst ich in Bedrängnis und kann es nicht zu deinen Infos hinzufügen :/'))
|
||
return
|
||
|
||
self.bot.database.set_user_age(ctx.author.id, age)
|
||
|
||
# ADDED AFTERWARDS: hehe
|
||
if age == 69:
|
||
embed = Embeds.success_embed(title='Alter wurde hinzugefügt')
|
||
embed.description = 'Ah, I see you\'re a man of culture as well'
|
||
embed.set_thumbnail(url='attachment://man_of_culture.jpg')
|
||
await ctx.send(embed=embed, file=discord.File(Path.cwd().joinpath('assets', 'man_of_culture.jpg')))
|
||
else:
|
||
await ctx.send(embed=Embeds.success_embed(description=f'Alter __{age}__ wurde hinzugefügt'))
|
||
elif info_type.lower() == 'list':
|
||
try:
|
||
requests.get(info_value[0])
|
||
except Exception:
|
||
await ctx.send(embed=Embeds.error_embed(description='Ich konnte mich nicht mit der gegeben URL verbinden'))
|
||
return
|
||
self.bot.database.set_user_list(ctx.author.id, info_value[0])
|
||
await ctx.send(embed=Embeds.success_embed(description='Anime Liste wurde hinzugefügt'))
|
||
elif info_type.lower() == 'fav':
|
||
self.bot.database.set_user_fav(ctx.author.id, ' '.join(info_value))
|
||
await ctx.send(embed=Embeds.success_embed(description=f'Lieblings Anime (__{" ".join(info_value)}__) wurde hinzugefügt'))
|
||
elif info_type.lower() == 'waifu':
|
||
self.bot.database.set_user_waifu(ctx.author.id, ' '.join(info_value))
|
||
await ctx.send(embed=Embeds.success_embed(description=f'Waifu (__{" ".join(info_value)}__) wurde hinzugefügt'))
|
||
elif info_type.lower() == 'husbando':
|
||
self.bot.database.set_user_husbando(ctx.author.id, ' '.join(info_value))
|
||
await ctx.send(embed=Embeds.success_embed(description=f'Husbando (__{" ".join(info_value)}__) wurde hinzugefügt'))
|
||
else:
|
||
await Help(self.bot).show_help(ctx, ctx.command)
|
||
|
||
@commands.command(name='removeinfo', aliases=['inforemove'], usage='removeinfo <name, age | list | fav | waifu | husbando>',
|
||
help='Entfernt Name / Alter / Anime Liste / lieblings Anime / Waifu / Husbando von einem Nutzer.\n\n'
|
||
'Tippe `$help addinfo` um Infos hinzuzufügen')
|
||
@commands.guild_only()
|
||
async def inforemove(self, ctx: commands.Context, info_type: str):
|
||
if info_type.lower() == 'name':
|
||
self.bot.database.set_user_name(ctx.author.id, None)
|
||
await ctx.send(embed=Embeds.success_embed(description='Name wurde entfernt'))
|
||
elif info_type.lower() == 'age':
|
||
self.bot.database.set_user_age(ctx.author.id, None)
|
||
await ctx.send(embed=Embeds.success_embed(description='Alter wurde entfernt'))
|
||
elif info_type.lower() == "list":
|
||
self.bot.database.set_user_list(ctx.author.id, None)
|
||
await ctx.send(embed=Embeds.success_embed(description='Anime Liste wurde entfernt'))
|
||
elif info_type.lower() == "fav":
|
||
self.bot.database.set_user_fav(ctx.author.id, None)
|
||
await ctx.send(embed=Embeds.success_embed(description='Lieblings Anime wurde entfernt'))
|
||
elif info_type.lower() == "waifu":
|
||
self.bot.database.set_user_waifu(ctx.author.id, None)
|
||
await ctx.send(embed=Embeds.success_embed(description='Waifu wurde entfernt'))
|
||
elif info_type.lower() == "husbando":
|
||
self.bot.database.set_user_husbando(ctx.author.id, None)
|
||
await ctx.send(embed=Embeds.success_embed(description='Husbando wurde entfernt'))
|
||
else:
|
||
await Help(self.bot).show_help(ctx, ctx.command)
|
||
|
||
|
||
class Kaizen(commands.Cog):
|
||
|
||
def __init__(self, bot):
|
||
self.bot = bot
|
||
|
||
@commands.command(name='kaizen', usage='kaizen', help='Alle Links zu den Social Media Kanälen von Kaizen')
|
||
async def links(self, ctx: commands.Context):
|
||
await Embeds.send_kaizen_infos(ctx)
|
||
|
||
|
||
class Vote(commands.Cog):
|
||
|
||
def __init__(self, bot):
|
||
self.bot = bot
|
||
self.total_votes = []
|
||
self.next_normal_time = datetime.datetime.now()
|
||
self.sub_or_booster_time = {}
|
||
self.number_emojis = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟']
|
||
|
||
self.flag_parser = flags.Flag(raise_errors=False,
|
||
double_flag_error='Die flag `{flag}` wurde schon gegeben',
|
||
flag_position_error='Flags müssen als letztes aufgerufen werden',
|
||
quotation_error='Es fehlen ein oder mehrere Anführungszeichen (`"` oder `\'`)')
|
||
self.flag_parser.add_flag('--duration',
|
||
store_type=(flags.StoreType.store_value, 60*5),
|
||
parser=self._duration_parser,
|
||
allowed_roles=['Mod', 'Server Booster', 'Kaizen-Sub'],
|
||
not_allowed_role_message='Nur Nutzer, die Server Booster oder Twich-Sub von Kaizen sind, können die `{flag}` flag benutzen!',
|
||
wrong_store_type_message='Die `{flag}` flag muss eine Zeitangabe haben (z.B. `{flag}=12m21s`)',
|
||
help='Zeit, bis das Ergebnis bekanntgegeben werden soll. Ist nur für Server Booster und Kaizen Twitch Subs verfügbar! (z.B. {flag}=12m21s)')
|
||
self.flag_parser.add_flag('--image',
|
||
store_type=flags.StoreType.store_value,
|
||
wrong_store_type_message='Die `{flag}` flag muss einen URL zu einem Bild haben (z.B. `{flag}="https://bytedream.org/darling.jpg"`)',
|
||
help='Fügt ein extra Bild zur Umfrage hinzu. Bild muss als URL angegeben sein (z.B. {flag}=https://bytedream.org/darling.jpg)')
|
||
|
||
super().__init__()
|
||
|
||
async def _duration_parser(self, ctx: commands.Context, flag, value):
|
||
regex_time = re.match(r'^((?P<hour>\d*?)h)?((?P<min>\d*?)m)?((?P<sec>\d*?)s)?', str(value))
|
||
time = 0
|
||
if regex_time['hour']:
|
||
time += int(regex_time['hour']) * 60 * 60
|
||
if regex_time['min']:
|
||
time += int(regex_time['min']) * 60
|
||
if regex_time['sec']:
|
||
time += int(regex_time['sec'])
|
||
if time == 0:
|
||
await ctx.send(embed=Embeds.warn_embed(description=f'Die Zeit der `{flag}` flag sollte in Form von __12m21s__ oder __21m__ sein'))
|
||
return False
|
||
elif time > 60 * 60:
|
||
roles = role_names(ctx.author)
|
||
if 'Mod' not in roles and 'A&M Redakteur' not in roles:
|
||
await ctx.send(embed=Embeds.warn_embed(description=f'Die Gesamtzeit der `{flag}` flag kann höchstens 60 Minuten betragen!'))
|
||
return False
|
||
return time
|
||
|
||
@commands.command(name='vote', ignore_extra=False,
|
||
usage='vote "<title>" <2 bis 10 "Antwortmöglichkeiten"> [flags]', help='Startet eine Umfrage mit maximal 10 Antwortmöglichkeiten',
|
||
flags='flag_parser')
|
||
@commands.guild_only()
|
||
async def vote(self, ctx: commands.Context, *, args):
|
||
parsed = await self.flag_parser.parse(args, ctx=ctx)
|
||
if not parsed:
|
||
return
|
||
|
||
args = list(parsed.normal_args)
|
||
|
||
if len(args) == 0:
|
||
async with ctx.typing():
|
||
await asyncio.sleep(.7)
|
||
await ctx.send(embed=Embeds.error_embed(description=f'Syntax für den \'{self.bot.command_prefix}vote\':\n'
|
||
f'`{self.bot.command_prefix}vote [titel] [antwortmöglichkeiten] (dauer)`\n\n'
|
||
f'Argumente:\n'
|
||
f'`titel`: Titel der Umfrage ("Wie findet ihr Anime xy?")\n'
|
||
f'`antwortmöglichkeiten`: Bis zu zehn mögliche Antwortmöglichkeiten ("super" "ok" "schlecht")\n'
|
||
f'`dauer`: Zeit, bis das Ergebnis bekanntgegeben werden soll.\n\n'
|
||
f'Beispiel:\n'
|
||
f'`{self.bot.command_prefix}vote "Wie findet Ihr Anime xy?" "sehr gut" super ok schlecht "sehr schlecht" time=12m`\n\n'
|
||
f'Um Leerzeichen im Titel oder in den Antwortmöglichkeiten zu benutzen, die entsprechenden Dinge einfach mit Anführungszeichen (`"`) vorne und hinten versehen'))
|
||
return
|
||
elif len(args) <= 2:
|
||
await ctx.send(embed=Embeds.error_embed('Es müssen mindestens zwei Antwortmöglichkeit angegeben sein!'))
|
||
return
|
||
elif len(args) > 10 + 1: # the +1 is the title
|
||
await ctx.send(embed=Embeds.error_embed('Es können nur maximal 10 Antwortmöglichkeiten angegeben werden!'))
|
||
return
|
||
|
||
roles = role_names(ctx.author)
|
||
privileges = 'Mod' in roles or 'A&M Redakteur' in roles
|
||
booster = 'Server Booster' in roles
|
||
sub = 'Kaizen-Sub' in roles
|
||
|
||
now = datetime.datetime.now()
|
||
|
||
if len(self.total_votes) >= 3 and not privileges:
|
||
difference = divmod(min(self.total_votes) - now.timestamp(), 60)
|
||
await ctx.send(embed=Embeds.error_embed(description=f'Es können maximal 3 Umfragen gleichzeitig laufen. In {round(difference[0])} Minuten und {round(difference[1])} Sekunden kann wieder eine neue Umfrage gestartet werden.'))
|
||
return
|
||
|
||
# check for cooldown
|
||
if privileges:
|
||
pass
|
||
elif booster or sub:
|
||
if self.sub_or_booster_time.get(ctx.author.id, now - datetime.timedelta(hours=1)) < now:
|
||
self.sub_or_booster_time[ctx.author.id] = now + datetime.timedelta(minutes=15)
|
||
elif self.next_normal_time < now:
|
||
self.next_normal_time = now + datetime.timedelta(minutes=40)
|
||
elif self.bot.database.set_user_extra_vote(ctx.author.id, -1):
|
||
pass
|
||
else:
|
||
if (t := self.sub_or_booster_time[ctx.author.id]) < self.next_normal_time:
|
||
difference = divmod((t - now).total_seconds(), 60)
|
||
else:
|
||
difference = divmod((self.next_normal_time - now).total_seconds(), 60)
|
||
await ctx.send(embed=Embeds.error_embed(description=f'Du musst leider noch {round(difference[0])} Minuten und {round(difference[1])} Sekunden warten, bis du den Befehl erneut benutzen kannst.'))
|
||
return
|
||
elif self.next_normal_time < now:
|
||
self.next_normal_time = now + datetime.timedelta(minutes=40)
|
||
else:
|
||
difference = divmod((self.next_normal_time - now).total_seconds(), 60)
|
||
await ctx.send(embed=Embeds.error_embed(description=f'Du musst leider noch {round(difference[0])} Minuten und {round(difference[1])} Sekunden warten, du den Befehl erneut benutzen kannst.\n'
|
||
f'Werde Server Booster oder Twich-Sub, um die Wartezeit zu verringern!'))
|
||
return
|
||
|
||
# send the message embed
|
||
args[0] = args[0] if args[0].endswith('?') else args[0] + '?'
|
||
embed = discord.Embed(title=f'**{args[0]}**',
|
||
description='\n'.join([f'{self.number_emojis[i]}: {answer}' for i, answer in enumerate(args[1:])]),
|
||
color=ctx.author.roles[-1].color)
|
||
if parsed.image:
|
||
embed.set_thumbnail(url=parsed.image)
|
||
end_time = datetime.datetime.now() + datetime.timedelta(seconds=parsed.duration)
|
||
embed.set_footer(text=f'Umfrage endet am {end_time.strftime("%d.%m.%Y")} um ca. {end_time.strftime("%H:%M")} Uhr')
|
||
async with ctx.typing():
|
||
await asyncio.sleep(.5)
|
||
message = await ctx.send(embed=embed)
|
||
for i in range(len(args[1:])):
|
||
await message.add_reaction(self.number_emojis[i])
|
||
|
||
if parsed.pin:
|
||
await message.pin()
|
||
await ctx.message.delete()
|
||
|
||
last_mention_id = message.id
|
||
|
||
self.total_votes.append(end_time.timestamp())
|
||
walked = 0
|
||
for _ in range(0, (parsed.duration - 5) // (60 * 10)):
|
||
await asyncio.sleep(60 * 10)
|
||
is_fresh = False
|
||
async for old_message in ctx.channel.history(limit=10):
|
||
if old_message.id == last_mention_id:
|
||
is_fresh = True
|
||
break
|
||
if not is_fresh:
|
||
last_mention_id = (await message.reply(embed=discord.Embed(description=f'Es läuft aktuell eine Umfrage, stimmt doch zur Frage `{args[0]}` ab!',
|
||
color=embed.color))).id
|
||
walked += 60 * 10
|
||
await asyncio.sleep(parsed.duration - walked)
|
||
|
||
self.total_votes.remove(end_time.timestamp())
|
||
|
||
if parsed.pin:
|
||
await message.unpin()
|
||
|
||
reactions = []
|
||
users = []
|
||
|
||
for reaction in (await ctx.channel.fetch_message(message.id)).reactions:
|
||
reactions.append(reaction)
|
||
async for user in reaction.users():
|
||
if not user.bot and user.id not in users:
|
||
users.append(user.id)
|
||
embed = discord.Embed(title=f'**{args[0]}**',
|
||
description='\n'.join([f'{self.number_emojis[i]}: {answer} - {reactions[i].count - 1} {"Stimme" if reactions[i].count - 1 == 1 else "Stimmen"}' for i, answer in enumerate(args[1:])]),
|
||
color=embed.color)
|
||
if parsed.image:
|
||
embed.set_thumbnail(url=parsed.image)
|
||
now = datetime.datetime.now()
|
||
embed.set_footer(text=f'Umfrage endete am {now.strftime("%d.%m.%Y")} um {now.strftime("%H:%M:%S")} Uhr')
|
||
await message.clear_reactions()
|
||
await message.edit(embed=embed)
|
||
|
||
reaction_dict = {arg: count for arg, count in sorted({arg: reactions[i].count for i, arg in enumerate(args[1:])}.items(), key=lambda item: item[1], reverse=True)}
|
||
|
||
result_embed = discord.Embed(title=f'Umfrageergebnisse zu `{args[0]}`\n\n',
|
||
description='\n'.join([f'{i + 1}. {arg} - {count - 1} {"Stimme" if count - 1 == 1 else "Stimmen"}' for i, (arg, count) in enumerate(reaction_dict.items())]),
|
||
color=embed.color)
|
||
|
||
result_embed.description += f'\n\nInsgesamt mitgemacht: {len(users)}'
|
||
|
||
await ctx.send(embed=result_embed)
|
||
|
||
|
||
# ADDED AFTERWARDS: hehe pt. 2
|
||
class NSFW(commands.Cog):
|
||
|
||
def __init__(self, bot):
|
||
self.id = 796873618026004481
|
||
self.bot = bot
|
||
|
||
@commands.command(name='color', usage='color', help='Shows a random colored hentai image')
|
||
@commands.guild_only()
|
||
@commands.cooldown(1, 60 * 5, type=commands.BucketType.channel)
|
||
async def color(self, ctx: commands.Context):
|
||
if ctx.channel.id != self.id:
|
||
await ctx.send(embed=Embeds.error_embed(description='Dieser Befehl kann nur in <#796873618026004481> genutzt werden'))
|
||
else:
|
||
await ctx.send(file=discord.File(os.path.join('/srv/media/hentai/image', random.choice(os.listdir('/srv/media/hentai/image')))))
|
||
|
||
@commands.command(name='lewd', usage='lewd', help='Shows a random lewd')
|
||
@commands.guild_only()
|
||
@commands.cooldown(1, 60 * 5, type=commands.BucketType.channel)
|
||
async def lewd(self, ctx: commands.Context):
|
||
if ctx.channel.id != self.id:
|
||
await ctx.send(embed=Embeds.error_embed(description='Dieser Befehl kann nur in <#796873618026004481> genutzt werden'))
|
||
else:
|
||
page = random.randint(0, glob['twitter'].get_user('lewdxsthetic').statuses_count // 20)
|
||
await ctx.send(random.choice(glob['twitter'].user_timeline('lewdxsthetic', page=page, count=20))._json['entities']['media'][0]['media_url_https'])
|