diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6b9f5ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +jeevesbot/env.py +jeevesbot/secret.json +logs/ +__init__.py +*.pyc +__pycache__/* +cogs/__pycache__/* +jeevesbot/__pycache__/* +.vscode/ \ No newline at end of file diff --git a/Makefile b/Makefile index ba4e07e..926a23b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ init: - pip install -r requirements.txt + pip install -r requirements.txt install: mkdir logs @@ -7,14 +7,12 @@ install: cp jeevesbot/secret.json.dist jeevesbot/secret.json clearlog: - rm jeeves.log + rm logs/jeeves.log* clean: - rm jeeves.log + rm logs/jeeves.log* rm jeevesbot/env.py rm jeevesbot/secret.json - rm -rf jeevesbot/__pycache/ - rm -rf __pycache/ - -lint: - pylint jeeves.py jeevesbot/ \ No newline at end of file + rm -rf cogs/__pycache__/ + rm -rf jeevesbot/__pycache__/ + rm -rf __pycache__/ \ No newline at end of file diff --git a/cogs/admin.py b/cogs/admin.py index b45adac..ae31731 100644 --- a/cogs/admin.py +++ b/cogs/admin.py @@ -8,23 +8,27 @@ from discord import User, errors, TextChannel, Forbidden # setup logging log = getLogger(__name__) + embed = discord.Embed() -class Admin(commands.Cog): +class Admin(commands.Cog): + """ Admin Commands, Use at own risk. """ def __init__(self, bot): self.bot = bot - + + @commands.command(name='purge', hidden=True) - @commands.is_owner() + @commands.has_permissions(administrator=True) async def purge(self, ctx, amount=1): """ Purge messages from current channel""" await ctx.message.delete() await ctx.channel.purge(limit = amount) log.warn(f'{ctx.message.author} purged {amount} messages') + @commands.command(name='purge_from', hidden=True) - @commands.is_owner() + @commands.has_permissions(administrator=True) async def purge_from(self, ctx, message_id: int): """Purge all messages after the given message.id""" try: @@ -37,15 +41,14 @@ class Admin(commands.Cog): log.info(f'{ctx.message.author} purged all messages after {message_id}') return True + @commands.command(name='purge_user', hidden=True) @commands.is_owner() async def purge_user(self, ctx, user: User, num_minutes: typing.Optional[int] = 5): """Clear all messages of in all channels within the last [n=5] minutes""" after = ctx.message.created_at - timedelta(minutes=num_minutes) - def check(msg): return msg.author.id == user.id - for channel in await ctx.guild.fetch_channels(): if type(channel) is TextChannel: try: @@ -53,10 +56,12 @@ class Admin(commands.Cog): log.info(f'{ctx.message.author} purged all messages from {user.id} that were posted within the last {num_minutes}') except Forbidden: continue + @commands.Cog.listener() async def on_ready(self): log.info(f'module active') + async def setup(bot): await bot.add_cog(Admin(bot)) \ No newline at end of file diff --git a/cogs/flairroles.py b/cogs/flair.py similarity index 52% rename from cogs/flairroles.py rename to cogs/flair.py index a83a212..15b92c5 100644 --- a/cogs/flairroles.py +++ b/cogs/flair.py @@ -9,6 +9,7 @@ e = discord.Embed() class Flair(commands.Cog): + """ This part of the bot is responsible for giving users roles! """ def __init__(self, bot): self.bot = bot self.message_id = 1084937456819908679 @@ -24,6 +25,7 @@ class Flair(commands.Cog): '🔞' : env.FLAIRROLES[8], } + @commands.Cog.listener() async def on_raw_reaction_add(self, payload): try: @@ -39,6 +41,7 @@ class Flair(commands.Cog): except: log.debug("Reaction not found.") + @commands.Cog.listener() async def on_raw_reaction_remove(self, payload): try: @@ -52,42 +55,11 @@ class Flair(commands.Cog): except: log.debug("Could not remove role") - @commands.command(name='flairsetup', hidden=True) - @commands.is_owner() - async def flairsetup(self, ctx): - """ Setup reaction post as embed. """ - await ctx.message.delete() - embed = discord.Embed(title="Kies je rollen!", - description="Klik op de emoji onder het bericht om de rol te krijgen.") - embed.add_field(name="", value="", inline=False) - embed.add_field(name="Voornaamwoorden:", value="", inline=False) - embed.add_field(name=":one:", value="hij/hem") - embed.add_field(name=":two:", value="zij/haar") - embed.add_field(name=":three:", value="hen/hun") - embed.add_field(name=":four:", value="die/hun") - embed.add_field(name=":five:", value="die/diens") - embed.add_field(name=":six:", value="iedere/all") - embed.add_field(name="Sta je open voor Direct Messages van andere serverleden?", value="", inline=False) - embed.add_field(name=":thumbsup:", value="DM: ja") - embed.add_field(name=":thumbsdown:", value="DM: nee") - embed.add_field(name="Rollen voor toegang tot opt-in kanalen.", value="", inline=False) - embed.add_field(name=":underage:", value="serieuze-onderwerpen") - embed.set_footer(text="Mis je een voornaamwoord of heb je ideeën voor een andere rol? Laat het de mods weten in de #ideeënbus!\nJe kan zelf je rollen verwijderen door opnieuw op de emoji te drukken.") - message = await ctx.send(embed=embed) - await message.add_reaction("1️⃣") - await message.add_reaction("2️⃣") - await message.add_reaction("3️⃣") - await message.add_reaction("4️⃣") - await message.add_reaction("5️⃣") - await message.add_reaction("6️⃣") - await message.add_reaction("👍") - await message.add_reaction("👎") - await message.add_reaction("🔞") - log.warn(f'{ctx.message.author} reset the flair embed, new message_id = {message.id}') @commands.Cog.listener() async def on_ready(self): log.info(f'module active') + async def setup(bot): await bot.add_cog(Flair(bot)) diff --git a/cogs/games.py b/cogs/games.py index 19d2394..ed1580a 100644 --- a/cogs/games.py +++ b/cogs/games.py @@ -1,6 +1,5 @@ import discord from discord.ext import commands -import logging from jeevesbot import functions, babbelbingo from logging import getLogger @@ -13,14 +12,46 @@ e = discord.Embed() class Games(commands.Cog): - - + """ Deze commando's zijn gerelateerd aan spelletjes op de Discord server. """ def __init__(self, bot): self.bot = bot + + @commands.command() + @commands.guild_only() + async def bingo(self, ctx): + """ Maak een babbelbingo kaart (staat niet altijd aan) """ + name = ctx.message.author.name + bingocard = babbelbingo.bingo(name) + await ctx.author.send(file=discord.File(bingocard)) + @commands.command() async def roll(self, ctx): + """ Roll the dice! + + Simple rolls + !roll 1d20+6 + !roll 1d20-(2+6) + !roll 1d20-4+(1d4+3) + + Advanced rolls + !roll 1d20x(N) + exploding dice, will add extra dice on each roll above threshold N. If N is not defined, will default to maximum possible roll. + !roll 6d6^(N) + highest N dicerolls will be kept, so 6d6^2 will keep the highest two dice. + !roll 6d6m(N) + middle N dicerolls will be kept, so 6d6m2 will keep the middle two dice. + !roll 6d6v(N) + lowest N dicerolls will be kept, so 6d6l2 wil keep the lowest two dice. + !roll 2d6r(N) + will reroll any dice that are below threshold N. The reroll is possible to be below the threshold N. + !roll 2d6rr(N) + will reroll any dice that are below threshold N. The reroll will be at the very minimum threshold N. + !roll 10d10s + will sort the rolls in order, this will not change the result. + + """ parameters = ctx.message.content.split(' ', 1) if len(parameters) == 2: param = parameters[1] @@ -31,14 +62,6 @@ class Games(commands.Cog): await ctx.send(msg) - @commands.command() - @commands.guild_only() - async def bingo(self, ctx): - name = ctx.message.author.name - bingocard = babbelbingo.bingo(name) - await ctx.author.send(file=discord.File(bingocard)) - - @commands.Cog.listener() async def on_ready(self): log.info(f'module active') diff --git a/cogs/gif.py b/cogs/gif.py index c162231..56721e3 100644 --- a/cogs/gif.py +++ b/cogs/gif.py @@ -1,6 +1,5 @@ import discord from discord.ext import commands -import logging from jeevesbot import functions from logging import getLogger @@ -13,7 +12,7 @@ e = discord.Embed() class Gif(commands.Cog): - + """ Ensures that high-risk channels don't display embedded links, but only gifs.""" def __init__(self, bot): self.bot = bot diff --git a/cogs/help.py b/cogs/help.py new file mode 100644 index 0000000..62c6464 --- /dev/null +++ b/cogs/help.py @@ -0,0 +1,55 @@ +import discord +from discord.ext import commands +from logging import getLogger + +# setup logging +log = getLogger(__name__) +e = discord.Embed() + + +class CustomHelp(commands.Cog): + """ Help """ + def __init__(self, bot): + self.bot = bot + + + @commands.command() + async def help(self, ctx): + """ Help """ + await ctx.message.delete() + with open("help/help.md", "r") as f: + contents = f.read() + embed = discord.Embed(title="Help", description=contents, color=discord.Color.blue()) + await ctx.author.send(embed=embed) + log.warn(f'{ctx.message.author} asked for help!') + + + @commands.command() + async def info(self, ctx): + """ Info about Jeeves """ + await ctx.message.delete() + with open("help/info.md", "r") as f: + contents = f.read() + embed = discord.Embed(title="Info over Jeeves", description=contents, color=discord.Color.yellow()) + await ctx.author.send(embed=embed) + log.warn(f'{ctx.message.author} asked for info!') + + + @commands.command(hidden=True) + @commands.is_owner() + async def adminhelp(self, ctx): + """ Admin Help """ + await ctx.message.delete() + with open("help/adminhelp.md", "r") as f: + contents = f.read() + embed = discord.Embed(title="Admin Help", description=contents, color=discord.Color.red()) + await ctx.author.send(embed=embed) + log.warn(f'{ctx.message.author} asked for adminhelp!') + + + @commands.Cog.listener() + async def on_ready(self): + log.info(f'module active') + +async def setup(bot): + await bot.add_cog(CustomHelp(bot)) diff --git a/cogs/links.py b/cogs/links.py index 97baa11..cdcf231 100644 --- a/cogs/links.py +++ b/cogs/links.py @@ -11,7 +11,7 @@ e = discord.Embed() class Links(commands.Cog): - + """ Handige linkjes! """ def __init__(self, bot): self.bot = bot @@ -19,12 +19,32 @@ class Links(commands.Cog): @commands.command() async def youtube(self, ctx): + """ LARP Platform YouTube kanaal """ await ctx.send('https://www.youtube.com/channel/UCTAnkjUOud_HdKhY_hi2ISA') @commands.command() async def donatie(self, ctx): - await ctx.send('') + """ LARP Platform / Stichting Verhaal in Uitvoering Donatie""" + await ctx.send('') + + + @commands.command() + async def agenda(self, ctx): + """ LARP Agenda""" + await ctx.send('') + + + @commands.command() + async def evenementen(self, ctx): + """ LARP Agenda Evenementenoverzicht""" + await ctx.send('') + + + @commands.command() + async def organisaties(self, ctx): + """ LARP Agenda Organisatieoverzicht""" + await ctx.send('') @commands.Cog.listener() diff --git a/cogs/misc.py b/cogs/misc.py index 208504f..500a1d2 100644 --- a/cogs/misc.py +++ b/cogs/misc.py @@ -11,7 +11,7 @@ e = discord.Embed() class Misc(commands.Cog): - + """ Van alles en nog wat. """ def __init__(self, bot): self.bot = bot diff --git a/cogs/moderator.py b/cogs/mods.py similarity index 100% rename from cogs/moderator.py rename to cogs/mods.py diff --git a/cogs/setup.py b/cogs/setup.py new file mode 100644 index 0000000..9cadaa3 --- /dev/null +++ b/cogs/setup.py @@ -0,0 +1,63 @@ +import discord +from discord.ext import commands +from logging import getLogger +from jeevesbot import env + + +# setup logging +log = getLogger(__name__) + +embed = discord.Embed() + +class BotSetup(commands.Cog): + """ Admin Commands, Use at own risk. """ + def __init__(self, bot): + self.bot = bot + self.botchannel = int(env.BOTCHANNEL[0]) + + + @commands.command(hidden=True) + @commands.is_owner() + async def flairsetup(self, ctx): + """ Setup reaction post as embed. """ + await ctx.message.delete() + channel_id = ctx.channel.id + if (channel_id) == (self.botchannel): + embed = discord.Embed(title="Kies je rollen!", + description="Klik op de emoji onder het bericht om de rol te krijgen.") + embed.add_field(name="", value="", inline=False) + embed.add_field(name="Voornaamwoorden:", value="", inline=False) + embed.add_field(name=":one:", value="hij/hem") + embed.add_field(name=":two:", value="zij/haar") + embed.add_field(name=":three:", value="hen/hun") + embed.add_field(name=":four:", value="die/hun") + embed.add_field(name=":five:", value="die/diens") + embed.add_field(name=":six:", value="iedere/all") + embed.add_field(name="Sta je open voor Direct Messages van andere serverleden?", value="", inline=False) + embed.add_field(name=":thumbsup:", value="DM: ja") + embed.add_field(name=":thumbsdown:", value="DM: nee") + embed.add_field(name="Rollen voor toegang tot opt-in kanalen.", value="", inline=False) + embed.add_field(name=":underage:", value="serieuze-onderwerpen") + embed.set_footer(text="Mis je een voornaamwoord of heb je ideeën voor een andere rol? Laat het de mods weten in de #ideeënbus!\nJe kan zelf je rollen verwijderen door opnieuw op de emoji te drukken.") + message = await ctx.send(embed=embed) + await message.add_reaction("1️⃣") + await message.add_reaction("2️⃣") + await message.add_reaction("3️⃣") + await message.add_reaction("4️⃣") + await message.add_reaction("5️⃣") + await message.add_reaction("6️⃣") + await message.add_reaction("👍") + await message.add_reaction("👎") + await message.add_reaction("🔞") + log.warn(f'{ctx.message.author} reset the flair embed, new message_id = {message.id}') + else: + log.warn(f'{ctx.message.author} tried setting up the flair in the wrong channel') + + + @commands.Cog.listener() + async def on_ready(self): + log.info(f'module active') + + +async def setup(bot): + await bot.add_cog(BotSetup(bot)) \ No newline at end of file diff --git a/help/adminhelp.md b/help/adminhelp.md new file mode 100644 index 0000000..a129657 --- /dev/null +++ b/help/adminhelp.md @@ -0,0 +1,22 @@ + +__These commands are very destructive and should be used with care.__ + +`!purge ` + Purge messages from current channel. + +`!purge_from ` + Purge all messages after the given + +`!purge_user ` + Clear all messages of in all channels within the last minutes (n is optional, default 5 minutes) + +All purge commands also delete their own message. + +--- + +`!flairsetup` + Can be used to reset the flair embed for Jeeves. Needs manual steps to fix the bot giving out roles. Don't use unless you know what you're doing. + +--- + +*To easily copy IDs of discord items, turn on Developer Mode in Advanced settings in your profile. After this, you can right click on almost all items in discord to get the "Copy ID" option.* \ No newline at end of file diff --git a/help/help.md b/help/help.md new file mode 100644 index 0000000..1353724 --- /dev/null +++ b/help/help.md @@ -0,0 +1,17 @@ + +** Games ** +`!roll ` + Rolt dobbelstenen voor je! De standaard notatie is xdx, maar ook ingewikkelde rolls zijn mogelijk. Zie `!info` voor meer informatie. + +`!bingo` + Maakt een Babbelbingo kaart voor je aan. Deze optie wordt doorgaans alleen aangezet tijdens digitale evenementen. + +** Links ** +`!youtube` +`!donatie` +`!agenda` +`!evenementen` +`!organisaties` + +** Misc ** +`!eirik` \ No newline at end of file diff --git a/help/info.md b/help/info.md new file mode 100644 index 0000000..da4a574 --- /dev/null +++ b/help/info.md @@ -0,0 +1,26 @@ + +** GIFs ** +** Flair ** + +** Extra informatie voor het !roll commando ** + +- Simpele rolls +`!roll 1d20+6` +`!roll 1d20-(2+6)` +`!roll 1d20-4+(1d4+3)` + +- Geavanceerde rolls +`!roll 1d20x` + exploding dice, voegt een extra roll toe voor ieder resultaat boven (N). als N niet is gedefinieerd, wordt de hoogste mogelijke rol aangenomen. +`!roll 6d6^(N)` + hoogste (N) rolls worden gehouden, dus 6d6^2 houdt de hoogste twee rolls. +`!roll 6d6m(N)` + middelste (N) rolls worden gehouden, dus 6d6m2 houdt de middelste twee rolls. +`!roll 6d6v(N)` + laagste (N) rolls worden gehouden, dus 6d6v2 houdt de laagste twee rolls. +`!roll 2d6r(N)` + rollt alle resultaten beneden (N) opnieuw. Het is mogelijk voor de reroll om onder (N) uit te komen. +`!roll 2d6rr(N)` + rollt alle resultaten beneden (N) opnieuw. De reroll zal minimaal (N) zijn, mogelijk hoger. +`!roll 10d10s` + Sorteert alle rolls van laag naar hoog, dit veranderd het resultaat verder niet. \ No newline at end of file diff --git a/jeeves.py b/jeeves.py index 19e1892..2bbc765 100755 --- a/jeeves.py +++ b/jeeves.py @@ -15,11 +15,13 @@ logging.config.dictConfig(log.LOGGING) # setup logging log = getLogger(__name__) + # setup discord.py bot intents = discord.Intents().all() -bot = commands.Bot(command_prefix='!', intents=intents) +bot = commands.Bot(command_prefix='!', intents=intents, help_command=None) e = discord.Embed() + @bot.command(name='load', hidden=True) @commands.has_permissions(administrator=True) async def load(ctx, extension): @@ -41,20 +43,24 @@ async def reload(ctx, extension): bot.load_extension(f'cogs.{extension}') log.info(f'{ctx.message.author} reloaded the {extension} module') + async def load_extensions(): for filename in os.listdir('./cogs'): if filename.endswith('.py'): await bot.load_extension(f'cogs.{filename[:-3]}') + @bot.event async def on_ready(): - print('### Active with id %s as %s ###' % (bot.user.id,bot.user.name) ) + log.info(f'Active with ID:{bot.user.id} as {bot.user.name}') activity = discord.Activity(name='!help', type=discord.ActivityType.listening) await bot.change_presence(activity=activity) + async def main(): async with bot: await load_extensions() await bot.start(env.TOKEN) + asyncio.run(main()) \ No newline at end of file diff --git a/jeevesbot/env.py.dist b/jeevesbot/env.py.dist index 2bff548..687a788 100644 --- a/jeevesbot/env.py.dist +++ b/jeevesbot/env.py.dist @@ -3,5 +3,6 @@ TOKEN = 'discord-bot-token-here' ADMIN_ROLE = 'role-to-exclude-from-gifbot' GIFCHANNELS = 'add-channel-ids-for-bot-to-work-in' +BOTCHANNEL = ['add id of bot channel'] FLAIRROLES = ['add list of role ids to correspond to the emoji'] FLAIRROLE = ['add id of flair separator role'] \ No newline at end of file