shbot/bot.py

446 lines
No EOL
18 KiB
Python

import discord
import asyncio
import time
import datetime
import random
import os
from os import system
from os import environ
from discord.ext import commands
from discord.commands import Option
from discord.commands import permissions
from discord.ui import InputText, Modal
def left(s, amount):
return s[:amount]
def right(s, amount):
return s[-amount:]
def mid(s, offset, amount):
return s[offset:offset+amount]
intents = discord.Intents.default()
intents.members = True
intents.message_content = True
token = os.environ['TOKEN']
prefix = os.environ['PREFIX']
bot = commands.Bot(intents=intents, command_prefix=prefix)
admin_role=261603488331595776
member_role=261603747711418371
gm_role=511893805956595722
def admin(ctx):
if ctx.guild.get_role(admin_role) in ctx.author.roles:
return True
def member(ctx):
if ctx.guild.get_role(member_role) in ctx.author.roles:
return True
def is_admin():
async def predicate(ctx):
if ctx.guild.get_role(admin_role) in ctx.author.roles:
return True
return commands.check(predicate)
def is_member():
async def predicate(ctx):
if ctx.guild.get_role(member_role) in ctx.author.roles:
return True
return commands.check(predicate)
def is_gm():
async def predicate(ctx):
if ctx.guild.get_role(gm_role) in ctx.author.roles:
return True
return commands.check(predicate)
emojinumbers = ["0\u20E3", "1\u20E3" , "2\u20E3" , "3\u20E3" , "4\u20E3" , "5\u20E3" , "6\u20E3" , "7\u20E3" , "8\u20E3" , "9\u20E3"]
alphabet = {"a" : "🇦","b" : "🇧","c" : "🇨","d" : "🇩","e" : "🇪","f" : "🇫","g" : "🇬","h" : "🇭","i" : "🇮","j" : "🇯","k" : "🇰","l" : "🇱","m" : "🇲","n" : "🇳","o" : "🇴","p" : "🇵","q" : "🇶","r" : "🇷","s" : "🇸","t" : "🇹","u" : "🇺","v" : "🇻","w" : "🇼","x" : "🇽","y" : "🇾","z" : "🇿"}
bot.help_command = commands.DefaultHelpCommand(dm_help=False, no_category="Befehle die du nutzen kannst")
@bot.event
async def on_command_error(ctx, error):
try:
await ctx.message.delete()
except:
print("message not found")
print(error)
em = discord.Embed(title="Error", description=error, colour=0xFF0000)
await ctx.send(content="ups, da ist wohl was schief gegangen :( traurige Bot Geräusche...", embed=em, delete_after=20)
@bot.event
async def on_ready():
print("Bot ready on Version %s..." % discord.__version__)
class Confirm(discord.ui.View):
def __init__(self):
super().__init__()
self.value = None
@discord.ui.button(label="Confirm", style=discord.ButtonStyle.green)
async def confirm(
self, button: discord.ui.Button, interaction: discord.Interaction
):
await interaction.response.send_message("Bestätigt", ephemeral=True, delete_after=5.0)
self.value = True
self.stop()
@discord.ui.button(label="Cancel", style=discord.ButtonStyle.grey)
async def cancel(self, button: discord.ui.Button, interaction: discord.Interaction):
await interaction.response.send_message("Abgebrochen", ephemeral=True, delete_after=5.0)
self.value = False
self.stop()
@bot.slash_command(guild_ids=[261575556708040705])
@permissions.has_role(member_role)
async def roll(ctx,
dice: Option(str, "Würfel den/die du werfen willst. z.B. W20, 3d6", default="W20"),
):
"""Rolle einen oder mehrere Würfel"""
rollt = 0
rolle = " "
roll = dice.lower()
if "d" in roll:
rolls = "d"
if "w" in roll:
rolls = "w"
rollc = roll.split(rolls)[0]
if rollc == "":
rollc = 1
else:
rollc = int(rollc)
rolld = int(roll.split(rolls)[1])
for x in range(rollc):
rollo = random.randint(1, rolld)
rollt = rollt + rollo
rolle = rolle + " :game_die: " + str(rollo) + " "
if rollc > 1:
rolltotal = "Total: " + str(rollt)
else:
rolltotal = ""
if rollc > 12:
rolltotal = rolle + "\n" + rolltotal
rolle = ""
em = discord.Embed(title=rolle, description=rolltotal, colour=0x009933)
await ctx.response.send_message(embed=em)
@bot.slash_command(guild_ids=[261575556708040705])
@permissions.has_role(gm_role)
async def gmroll(ctx,
dice: Option(str, "Würfel den/die du werfen willst. z.B. W20, 3d6", default="W20"),
):
"""Rolle einen oder mehrere Würfel verdeckt"""
rollt = 0
rolle = " "
roll = dice.lower()
if "d" in roll:
rolls = "d"
if "w" in roll:
rolls = "w"
rollc = roll.split(rolls)[0]
if rollc == "":
rollc = 1
else:
rollc = int(rollc)
rolld = int(roll.split(rolls)[1])
for x in range(rollc):
rollo = random.randint(1, rolld)
rollt = rollt + rollo
rolle = rolle + " :game_die: " + str(rollo) + " "
if rollc > 1:
rolltotal = "Total: " + str(rollt)
else:
rolltotal = ""
if rollc > 12:
rolltotal = rolle + "\n" + rolltotal
rolle = ""
em = discord.Embed(title=rolle, description=rolltotal, colour=0x009933)
await ctx.response.send_message(embed=em, ephemeral=True)
class MyModal(Modal):
def __init__(self) -> None:
self.message_id = 0
super().__init__("Emojitext")
self.add_item(InputText(label="Dein Text:", placeholder="Jeder Buchstabe nur einmal!"))
def set_message_id(self, message_id):
self.message_id = message_id
async def callback(self, interaction: discord.Interaction):
await interaction.response.send_message(content="Füge Reaktionen hinzu...", ephemeral=True)
emojitext = self.children[0].value.lower()
original_message = await interaction.channel.fetch_message(self.message_id)
for x in list(emojitext):
await original_message.add_reaction(alphabet[x])
@bot.message_command(name="Emoji Text", guild_ids=[261575556708040705])
@permissions.has_role(member_role)
async def emoji_text(ctx, message: discord.Message):
modal = MyModal()
modal.title = "Emoji Bot"
modal.set_message_id(message.id)
await ctx.interaction.response.send_modal(modal)
@bot.command(help="veraltet", usage="", hidden=True)
@is_member()
async def yesno(ctx):
await ctx.message.delete()
await ctx.send(content="Sorry das geht so nicht. Der Befehl hat sich geändert in !vote... für mehr Informationen schreib bitte !help oder frage deinen Admin oder Apotheker. Liebste Grüße, SecondBot <3", delete_after=20.0)
@bot.command(help="Zeigt alte Hilfe", usage="")
@is_member()
async def helpme(ctx):
if admin(ctx):
admin_text = "\n\n!add = Hinzufügen einer Rolle mit Textchannel und hinzufügen von Usern zur Rolle\nNutzung: !add \"<Rolle>\" <User Mentions>\n\n!labor = bringt dich ins Labor :)\nNutzung: !labor\n\n!start = Starte ne Runde PnP\nNutzung: !start @Rolle\n\n!stop = Beende die gestartete Runde PnP\nNutzung: !stop\n\n!purge = Löschen von Nachrichten\nNutzung: !purge all|<Anzahl>|x minutes/hours/days/weeks\n\n!prune - kickt Member ohne Rolle, die 30 Tage nicht online waren\nNutzung: !prune"
else:
admin_text = ""
em = discord.Embed(title="Hilfe",description="!survey = Umfrage mit mehreren Antwortmöglichkeiten\nNutzung: !survey <Frage> | <Antwort1> | <Antwort2> ...\n\n!vote = Ja/Nein Umfrage\nNutzung: !vote <Frage>\n\n!love = zeige einem User Liebe\nNutzung: !love <@User1> <@User2> ...\n\n!roll = Rolle einen oder mehrere Würfel\nNutzung: !roll <anzahl_optional>W<seitenzahl> (z.B. !roll W20 oder !roll 10W6)%s" % admin_text, colour=0x00FF00)
if ctx.author.dm_channel == None:
await ctx.author.create_dm()
await ctx.author.dm_channel.send(embed=em)
@bot.command(help="Umfrage mit mehreren Antwortmöglichkeiten", usage="<Frage> | <Antwort1> | <Antwort2> ...")
@is_member()
async def survey(ctx, *, arg):
await ctx.message.delete()
answers = arg.split("|")
question = answers[0]
answers.remove(question)
desc = ""
z = 1
for y in answers:
desc = desc + emojinumbers[z] + " - " + y + "\n"
z = z + 1
em = discord.Embed(title=question, description=desc, colour=0x00E0FF)
em.set_author(name=ctx.author.display_name, url=discord.Embed.Empty, icon_url=ctx.author.avatar.url)
ask_msg = await ctx.send(content="||@here||",embed=em)
a = 0
for x in emojinumbers:
if a < z and a != 0:
await ask_msg.add_reaction(x)
a = a + 1
await ask_msg.create_thread(name="Diskussion")
@bot.command(help="Umfrage bearbeiten", usage="ID | <Frage> | <Antwort1> | <Antwort2> ...", hidden=True)
@is_member()
async def surveyedit(ctx, *, arg):
#Nutzung: !surveyedit ID | <Frage> | <Antwort1> | <Antwort2> ...
await ctx.message.delete()
answers = arg.split("|")
survey_id = answers[0]
question = answers[1]
answers.remove(survey_id)
answers.remove(question)
desc = ""
z = 1
for y in answers:
desc = desc + emojinumbers[z] + " - " + y + "\n"
z = z + 1
em = discord.Embed(title=question, description=desc, colour=0x00E0FF)
em.set_author(name=ctx.author.display_name, url=discord.Embed.Empty, icon_url=ctx.author.avatar.url)
survey_msg = await ctx.channel.fetch_message((int(survey_id)))
await survey_msg.edit(embed=em)
@bot.command(help="Ja/Nein Umfrage", usage="<Frage>")
@is_member()
async def vote(ctx, *, arg):
await ctx.message.delete()
em = discord.Embed(description=arg, colour=0x00E0FF)
em.set_author(name=ctx.author.display_name, url=discord.Embed.Empty, icon_url=ctx.author.avatar.url)
ask_msg = await ctx.send(content="||@here||",embed=em)
for x in ["", "", ""]:
await ask_msg.add_reaction(x)
await ask_msg.create_thread(name="Diskussion")
@bot.command(help="den Bot etwas sagen lassen", usage="<text>")
@is_admin()
async def say(ctx, *, arg):
await ctx.message.delete()
em = discord.Embed(description=arg, colour=0x00E0FF)
await ctx.message.channel.send(embed=em)
@bot.command(help="Starte ne Runde PnP", usage="@Rolle")
@is_gm()
async def start(ctx, role_mention):
await ctx.message.delete()
pnp_info = await ctx.guild.fetch_channel(435501602485305345)
pnp_voice = await ctx.guild.fetch_channel(435869507123281920)
role = ctx.message.role_mentions[0]
em = discord.Embed(description='gespieltes PnP: %s\nTeilnehmer (zum Start):' % role.mention, colour=0x00770d)
for c in ctx.guild.voice_channels:
for m in c.members:
if role in m.roles:
await m.move_to(pnp_voice)
em.add_field(name=":white_check_mark: " + m.display_name, value = m.mention + " ist am Start! Juhu!", inline=False)
start_msg = await pnp_info.send(content=":game_die: **INFO: PnP Sitzung gestartet!**",embed=em)
text_file = open("start_id.txt", "w")
text_file.write(str(start_msg.id))
text_file.close()
@bot.command(help="Beende die gestartete Runde PnP", usage="")
@is_gm()
async def stop(ctx):
await ctx.message.delete()
pnp_info = await ctx.guild.fetch_channel(435501602485305345)
pnp_voice = await ctx.guild.fetch_channel(435869507123281920)
move_to_talk = await ctx.guild.fetch_channel(801869864745697280)
text_file = open("start_id.txt", "r")
start_id = text_file.read()
text_file.close()
start_msg = await pnp_info.fetch_message(start_id)
now_time = datetime.datetime.utcnow().replace(microsecond=0, tzinfo=datetime.timezone.utc)
then_time = start_msg.created_at.replace(microsecond=0, tzinfo=datetime.timezone.utc)
dauer = str(now_time - then_time)
for m in pnp_voice.members:
await m.move_to(move_to_talk)
await start_msg.edit(content=":game_die: **INFO: PnP Sitzung beendet!** Dauer: %s" % dauer)
@bot.command(help="bringt dich ins Labor :)", usage="")
@is_admin()
async def labor(ctx):
await ctx.message.delete()
await ctx.author.move_to(bot.get_channel(765601577334865972))
@bot.command(help="Hinzufügen einer Rolle mit Textchannel und hinzufügen von Usern zur Rolle", usage="\"Name der Rolle\" @User1 @User2 ...")
@is_admin()
async def add(ctx, *, arg):
await ctx.message.delete()
try:
role_name = ctx.message.content.split("\"")[1]
text_name = role_name.lower().replace(" ", "-")
role = await ctx.guild.create_role(name=role_name, mentionable=True)
overwrites = {
ctx.guild.default_role: discord.PermissionOverwrite(read_messages=False),
role: discord.PermissionOverwrite(read_messages=True)
}
channel = await ctx.guild.create_text_channel(text_name, overwrites=overwrites, topic="Dieser Channel wurde von SecondBot erstellt.")
for user in ctx.message.mentions:
await user.add_roles(role)
em = discord.Embed(title=':loudspeaker: Ein neuer Channel für %s!' % role_name, description='Herzlich Willkommen! Es gibt nun eine neue Gruppe %s und diesen wunderbaren Channel hier! Der Channel ist nur für euch und die Admins sichtbar.' % role.mention, colour=0xffa500)
await channel.send(embed=em)
except Exception as e:
em = discord.Embed(title="Error Code", description=e, color=0xff0000)
await ctx.channel.send(content="Das hat nicht funktioniert. Syntax: !add \"<Rolle>\" <User Mentions>", embed=em, delete_after=20.0)
@bot.command(help="Löschen von Nachrichten", usage="all|<Anzahl>|x minutes/hours/days/weeks")
@is_admin()
async def purge(ctx, *, arg):
#Nutzung: !purge all|<Anzahl>|x minutes/hours/days/weeks
await ctx.message.delete()
by_limit = False
by_time = False
try:
if ctx.message.content.split(" ")[2] == "minutes":
by_time = True
delta = datetime.timedelta(minutes=int(ctx.message.content.split(" ")[1]))
if ctx.message.content.split(" ")[2] == "hours":
by_time = True
delta = datetime.timedelta(hours=int(ctx.message.content.split(" ")[1]))
if ctx.message.content.split(" ")[2] == "days":
by_time = True
delta = datetime.timedelta(days=int(ctx.message.content.split(" ")[1]))
if ctx.message.content.split(" ")[2] == "weeks":
by_time = True
delta = datetime.timedelta(weeks=int(ctx.message.content.split(" ")[1]))
except IndexError:
try:
if ctx.message.content.split(" ")[1] == "all":
by_limit = True
limit = None
else:
by_limit = True
limit = int(ctx.message.content.split(" ")[1])
except:
print("List error, ploz ignore")
except:
print("List error, ploz ignore")
if by_time:
after_time = datetime.datetime.utcnow() - delta
question = await ctx.send("Would you really like to delete all messages of the last {} {}?".format(ctx.message.content.split(" ")[1], ctx.message.content.split(" ")[2]))
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) == ""
await question.add_reaction("")
try:
reaction, user = await bot.wait_for("reaction_add", timeout=60.0, check=check)
except asyncio.TimeoutError:
await question.delete()
else:
await question.delete()
deleted = await ctx.channel.purge(limit=200, after=after_time)
await ctx.send(content='Ich habe {} Nachrichten gelöscht.'.format(len(deleted)), delete_after=5.0)
if by_limit:
if limit == None:
count = "alle"
else:
count = str(limit)
question = await ctx.send("Sollen wirklich {} Nachrichten gelöscht werden?".format(count))
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) == ""
await question.add_reaction("")
try:
reaction, user = await bot.wait_for("reaction_add", timeout=60.0, check=check)
except asyncio.TimeoutError:
await question.delete()
else:
await question.delete()
deleted = await ctx.channel.purge(limit=limit)
await ctx.send(content='Ich habe {} Nachrichten gelöscht.'.format(len(deleted)), delete_after=5.0)
@bot.command(help="zeige einem User Liebe", usage="<@User1> <@User2> ...", hidden=True)
@is_member()
async def love(ctx, *, arg):
await ctx.message.delete()
for user in ctx.message.mentions:
if user.dm_channel == None:
await user.create_dm()
await user.dm_channel.send("❤️")
@bot.command(help="kickt Member ohne Rolle, die 30 Tage nicht online waren", usage="")
@is_admin()
async def prune(ctx):
await ctx.message.delete()
count = await ctx.guild.estimate_pruned_members(days=30)
view = Confirm()
question = await ctx.send("Sollen wirklich {} Leichen gekickt werden?".format(count), view=view)
await view.wait()
if view.value is None:
await question.delete()
await ctx.send(content="Zeit ausgelaufen", delete_after=5.0)
elif view.value:
await question.delete()
deleted = await ctx.guild.prune_members(days=30)
await ctx.send(content='Ich habe {} Leichen beseitigt.'.format(deleted), delete_after=5.0)
else:
await question.delete()
@bot.command(help="Rolle einen oder mehrere Würfel", usage="<anzahl_optional>W<seitenzahl> (z.B. %sroll W20 oder %sroll 10W6)" % (prefix, prefix))
@is_member()
async def roll(ctx, arg):
await ctx.message.delete()
rollt = 0
rolle = " "
roll = arg.lower()
if "d" in roll:
rolls = "d"
if "w" in roll:
rolls = "w"
rollc = roll.split(rolls)[0]
if rollc == "":
rollc = 1
else:
rollc = int(rollc)
rolld = int(roll.split(rolls)[1])
for x in range(rollc):
rollo = random.randint(1, rolld)
rollt = rollt + rollo
rolle = rolle + " :game_die: " + str(rollo) + " "
if rollc > 1:
rolltotal = "Total: " + str(rollt)
else:
rolltotal = ""
if rollc > 12:
rolltotal = rolle + "\n" + rolltotal
rolle = ""
em = discord.Embed(title=rolle, description=rolltotal, colour=0x009933)
await ctx.send(embed=em)
bot.run(token)