diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..850b881 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,54 @@ +stages: +- build +- test +- deploy +image: debian +docker-build-push: + image: docker:latest + stage: build + services: + - docker:dind + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + script: + - | + if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then + tag="" + echo "Running on default branch '$CI_DEFAULT_BRANCH': tag = 'latest'" + else + tag=":$CI_COMMIT_REF_SLUG" + echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag" + fi + - docker build --pull -t "$CI_REGISTRY_IMAGE${tag}" . + - docker push "$CI_REGISTRY_IMAGE${tag}" + only: + - master + - dev +docker-build: + image: docker:latest + stage: build + services: + - docker:dind + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + script: + - docker build --pull -t "$CI_REGISTRY_IMAGE" . + except: + - master + - dev +before_script: +- apt-get update -qq +- which ssh-agent || ( apt-get install -qq openssh-client ) +- eval $(ssh-agent -s) +- ssh-add <(echo "$SSH_PRIVATE_KEY") +- mkdir -p ~/.ssh +- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' +deploy_staging: + stage: deploy + script: + - ssh $SSH_SERVER "cd /root && docker-compose pull shbot && docker-compose up -d + shbot && exit" + only: + - master +include: +- template: Security/Container-Scanning.gitlab-ci.yml diff --git a/.woodpecker/.build.yaml b/.woodpecker/.build.yaml deleted file mode 100644 index 32ff27f..0000000 --- a/.woodpecker/.build.yaml +++ /dev/null @@ -1,42 +0,0 @@ -steps: -- name: docker - image: woodpeckerci/plugin-docker-buildx - settings: - registry: git.ar21.de - username: - from_secret: REGISTRY_USER - password: - from_secret: REGISTRY_PASS - repo: git.ar21.de/secondhemd/shbot - tags: latest - when: - - branch: master - event: [push, manual] -- name: docker-build - image: woodpeckerci/plugin-docker-buildx - settings: - registry: git.ar21.de - username: - from_secret: REGISTRY_USER - password: - from_secret: REGISTRY_PASS - repo: git.ar21.de/secondhemd/shbot - tags: latest - dry_run: true - when: - - branch: - exclude: [master, dev] - event: [push, manual] -- name: dev docker - image: woodpeckerci/plugin-docker-buildx - settings: - registry: git.ar21.de - username: - from_secret: REGISTRY_USER - password: - from_secret: REGISTRY_PASS - repo: git.ar21.de/secondhemd/shbot - tags: dev - when: - - branch: dev - event: [push, manual] diff --git a/.woodpecker/.deploy.yaml b/.woodpecker/.deploy.yaml deleted file mode 100644 index fb99a19..0000000 --- a/.woodpecker/.deploy.yaml +++ /dev/null @@ -1,34 +0,0 @@ -skip_clone: true -steps: -- name: deploy - image: appleboy/drone-ssh - settings: - host: - - s.ar21.de - username: root - key: - from_secret: DEPLOY_SSH_KEY - port: 22 - command_timeout: 2m - script: - - cd ~/compose/shbot && docker compose pull shbot && docker compose up -d shbot - when: - - branch: master - event: [push, manual] -- name: deploy dev - image: appleboy/drone-ssh - settings: - host: - - s.ar21.de - username: root - key: - from_secret: DEPLOY_SSH_KEY - port: 22 - command_timeout: 2m - script: - - cd /root && docker compose -f shbot-dev.yaml pull shbot-dev && docker compose -f shbot-dev.yaml up -d shbot-dev - when: - - branch: dev - event: [push, manual] -depends_on: - - build diff --git a/Dockerfile b/Dockerfile index f663dcc..0fe06c5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,14 @@ -FROM amd64/python:3.11.3-alpine3.16 - -WORKDIR ./ -ARG PUID=1000 -ENV GROUP dockergroup -ENV USER docker -ENV HOMEDIR "/home/${USER}" - -RUN addgroup -S "${GROUP}" && adduser -S "${USER}" -G "${GROUP}" -USER ${USER} -WORKDIR ${HOMEDIR} -COPY . . -RUN pip install --no-cache-dir -r requirements.txt - -CMD [ "python", "./bot.py" ] +FROM python:slim + +WORKDIR ./ +ARG PUID=1000 +ENV USER docker +ENV HOMEDIR "/home/${USER}" + +RUN useradd -u "${PUID}" -m "${USER}" +USER ${USER} +WORKDIR ${HOMEDIR} +COPY . . +RUN pip install --no-cache-dir -r requirements.txt + +CMD [ "python", "./bot.py" ] \ No newline at end of file diff --git a/README.md b/README.md index af469a1..baebe92 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,22 @@ # SECOND BOT -[![Build Status](https://drone.ar21.de/api/badges/secondhemd/shbot/status.svg)](https://drone.ar21.de/secondhemd/shbot) +[![pipeline status](https://git.cxservers.com/aaron-riedel/shbot/badges/master/pipeline.svg)](https://git.cxservers.com/aaron-riedel/shbot/-/commits/master) der Bot für den SecondHemd Discord # Latest ## Build ``` -docker build -t secondhemd/shbot:latest . +docker build -t docker-registry.cxservers.com/aaron-riedel/shbot:latest . ``` ## Run ``` -sudo docker run -e 'TOKEN=' -e 'PREFIX=$' -t secondhemd/shbot:latest +sudo docker run -e 'TOKEN=' -e 'PREFIX=$' -t docker-registry.cxservers.com/aaron-riedel/shbot:latest ``` ## Docker compose ``` services: bot: - image: secondhemd/shbot:latest + image: docker-registry.cxservers.com/aaron-riedel/shbot:latest container_name: shbot restart: unless-stopped environment: @@ -27,17 +27,17 @@ services: # Development ## Build ``` -docker build -t secondhemd/shbot:dev . +docker build -t docker-registry.cxservers.com/aaron-riedel/shbot:dev . ``` ## Run ``` -sudo docker run -e 'TOKEN=' -e 'PREFIX=$' -t secondhemd/shbot:dev +sudo docker run -e 'TOKEN=' -e 'PREFIX=$' -t docker-registry.cxservers.com/aaron-riedel/shbot:dev ``` ## Docker compose ``` services: bot: - image: secondhemd/shbot:dev + image: docker-registry.cxservers.com/aaron-riedel/shbot:dev container_name: shbot restart: unless-stopped environment: diff --git a/bot.py b/bot.py index 3938732..117762a 100644 --- a/bot.py +++ b/bot.py @@ -23,7 +23,6 @@ def mid(s, offset, amount): intents = discord.Intents.default() intents.members = True intents.message_content = True -intents.presences = True token = os.environ['TOKEN'] prefix = os.environ['PREFIX'] @@ -56,7 +55,7 @@ def is_gm(): 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" : "🇿","0" : "0\u20E3","1" : "1\u20E3","2" : "2\u20E3","3" : "3\u20E3","4" : "4\u20E3","5" : "5\u20E3","6" : "6\u20E3","7" : "7\u20E3","8" : "8\u20E3","9" : "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") @@ -73,14 +72,6 @@ async def on_command_error(ctx, error): @bot.event async def on_ready(): print("Bot ready on Version %s..." % discord.__version__) - activity = discord.Activity(name='%shelp' % prefix, type=discord.ActivityType.listening) - #activity = discord.Game('%shelp for Help' % prefix) - await bot.change_presence(status=discord.Status.online, activity=activity) - -#@bot.listen() -#async def on_presence_update(before, after): -# if not before.is_on_mobile() and after.id == 274197471515639808 and after.is_on_mobile(): -# await bot.get_channel(512004326382632961).send("https://cdn.discordapp.com/attachments/512004326382632961/979468921985982514/unknown.png") class Confirm(discord.ui.View): def __init__(self): @@ -100,8 +91,8 @@ class Confirm(discord.ui.View): self.stop() @bot.slash_command(guild_ids=[261575556708040705]) -@commands.has_role(member_role) -async def roll(ctx, +@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""" @@ -133,8 +124,8 @@ async def roll(ctx, await ctx.response.send_message(embed=em) @bot.slash_command(guild_ids=[261575556708040705]) -@commands.has_role(gm_role) -async def gmroll(ctx, +@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""" @@ -168,7 +159,7 @@ async def gmroll(ctx, class MyModal(Modal): def __init__(self) -> None: self.message_id = 0 - super().__init__(title="Emojitext") + 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 @@ -178,16 +169,34 @@ class MyModal(Modal): 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]) -@commands.has_role(member_role) +@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 \"\" \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||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 | | ...\n\n!vote = Ja/Nein Umfrage\nNutzung: !vote \n\n!love = zeige einem User Liebe\nNutzung: !love <@User1> <@User2> ...\n\n!roll = Rolle einen oder mehrere Würfel\nNutzung: !roll W (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=" | | ...") @is_member() async def survey(ctx, *, arg): @@ -201,8 +210,8 @@ async def survey(ctx, *, arg): 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=None, icon_url=ctx.author.avatar.url) - ask_msg = await ctx.send(content="||@everyone||",embed=em) + 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: @@ -226,7 +235,7 @@ async def surveyedit(ctx, *, arg): 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=None, icon_url=ctx.author.avatar.url) + 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) @@ -235,8 +244,8 @@ async def surveyedit(ctx, *, arg): 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=None, icon_url=ctx.author.avatar.url) - ask_msg = await ctx.send(content="||@everyone||",embed=em) + 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") @@ -256,14 +265,11 @@ async def start(ctx, role_mention): 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) - move_members = [] for c in ctx.guild.voice_channels: for m in c.members: if role in m.roles: - move_members.append(m) + 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) - for m in move_members: - await m.move_to(pnp_voice) 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)) @@ -378,25 +384,16 @@ async def purge(ctx, *, arg): 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> ...") +@bot.command(help="zeige einem User Liebe", usage="<@User1> <@User2> ...", hidden=True) @is_member() -async def liebe(ctx, *, arg): +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("❤️ von {}".format(ctx.author.display_name)) + await user.dm_channel.send("❤️") -@bot.command(help="zeige einem User Hiebe", usage="<@User1> <@User2> ...") -@is_member() -async def hiebe(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("HIEBE :punch: von {}".format(ctx.author.display_name)) - -@bot.command(help="kickt Member ohne Rolle, die 7 Tage nicht online waren", usage="") +@bot.command(help="kickt Member ohne Rolle, die 30 Tage nicht online waren", usage="") @is_admin() async def prune(ctx): await ctx.message.delete() @@ -409,8 +406,8 @@ async def prune(ctx): await ctx.send(content="Zeit ausgelaufen", delete_after=5.0) elif view.value: await question.delete() - deleted = await ctx.guild.prune_members(days=7) - await ctx.send(content='Ich habe {} Leiche(n) beseitigt.'.format(deleted), delete_after=5.0) + 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() @@ -446,4 +443,4 @@ async def roll(ctx, arg): em = discord.Embed(title=rolle, description=rolltotal, colour=0x009933) await ctx.send(embed=em) -bot.run(token) +bot.run(token) \ No newline at end of file diff --git a/clear_commands.py b/clear_commands.py index f65dc72..ea9ddd6 100644 --- a/clear_commands.py +++ b/clear_commands.py @@ -4,7 +4,6 @@ import time import datetime import random import os -import sys from os import system from os import environ from discord.ext import commands @@ -23,9 +22,6 @@ bot = commands.Bot(intents=intents, command_prefix=prefix) @bot.event async def on_connect(): print("Bot ready on Version %s..." % discord.__version__) - await bot.sync_commands(commands=[], guild_ids=[261575556708040705]) - await bot.register_commands(commands=[], guild_id=261575556708040705) - await bot.close() - os._exit(0) + await bot.sync_commands(unregister_guilds=[261575556708040705]) bot.run(token) \ No newline at end of file diff --git a/renovate.json b/renovate.json deleted file mode 100644 index 7190a60..0000000 --- a/renovate.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json" -} diff --git a/requirements.txt b/requirements.txt index 62f4ab2..981d2f7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -py-cord==2.6.1 +py-cord==2.0.0b5 \ No newline at end of file diff --git a/survey.py b/survey.py deleted file mode 100644 index 7a19419..0000000 --- a/survey.py +++ /dev/null @@ -1,42 +0,0 @@ -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] - -token = os.environ['TOKEN'] -survey_channel = int(os.environ['SURVEY_CHANNEL']) -mention_id = int(os.environ['MENTION_ID']) -guild_id = int(os.environ['GUILD_ID']) -runtime = 48 - -bot = discord.Bot(description=None) - -@bot.event -async def on_ready(): - print("Bot ready on Version %s..." % discord.__version__) - # build survey - po = discord.Poll(question="Habt ihr nächsten Dienstag Zeit?", answers=[discord.PollAnswer(text="Ja", emoji="✅"), discord.PollAnswer(text="keine Zeit", emoji="❌")], duration=runtime, allow_multiselect=False) - # send message - msg = await bot.get_channel(survey_channel).send(content="||%s||"% bot.get_guild(guild_id).get_role(mention_id).mention ,poll=po) - # await msg.create_thread(name="Diskussion") - # close connection - await bot.close() - -bot.run(token) \ No newline at end of file