diff --git a/.gitignore b/.gitignore index 345bdbf..eefc475 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ -secret.txt +secret* data + +.venv +.idea \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 159e64a..2570500 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,15 @@ -FROM python:3.11.2-alpine +FROM python:3.12-alpine WORKDIR /app COPY requirements.txt requirements.txt RUN /usr/local/bin/python -m pip install --upgrade pip -RUN pip3 install -r requirements.txt +RUN pip3.12 install -r requirements.txt RUN rm requirements.txt COPY ./src/ . -RUN mkdir ./data -RUN mkdir ./data/log -RUN mkdir ./data/config +RUN mkdir -p ./data/log +RUN mkdir -p ./data/config -CMD [ "python3", "main.py" ] +CMD [ "python3.12", "main.py" ] diff --git a/docker-compose.yml b/docker-compose.yml index e81c9ab..e60cb5e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,10 +2,10 @@ version: '3' services: app: container_name: TuxDiscordBot - image: 'dasmoorhuhn/tux-discord-bot:beta' + image: 'docker.lan:5000/tux-discord-bot' restart: unless-stopped build: . volumes: - ./data/log:/app/data/log - ./data/config:/app/data/config - - ./secret.txt:/app/secret.txt \ No newline at end of file + - ./secret.json:/app/secret.json \ No newline at end of file diff --git a/src/addons.py b/src/addons.py index 77769aa..d052910 100644 --- a/src/addons.py +++ b/src/addons.py @@ -5,66 +5,43 @@ from models.xkcdComic import Comic class ProgrammerExcuses: - def __init__(self) -> None: - self.__url = "http://programmingexcuses.com" + def __init__(self) -> None: + self.url = "http://programmingexcuses.com" - def getExcuse(self): - page = requests.get(url=self.__url) - content = page.content.decode().split("\n") - for html in content: - if 'href="/"' in html: - start_index = html.find('3;">') - end_index = html.find("") - return html[start_index+4:end_index] + def get_excuse(self): + page = requests.get(url=self.url) + content = page.content.decode().split("\n") + for html in content: + if 'href="/"' in html: + start_index = html.find('3;">') + end_index = html.find("") + return html[start_index + 4:end_index] class XKCD: - def __init__(self) -> None: - self.url = "https://xkcd.com" - self.__api = "info.0.json" + def __init__(self) -> None: + self.url = "https://xkcd.com" + self.api = "info.0.json" - def getRandomComic(self): - response = requests.get(url=f"https://c.xkcd.com/random/comic") + def get_random_comic(self): + response = requests.get(url=f"https://c.xkcd.com/random/comic") - for line in response.text.split("\n"): - if ' None: - self.url = "https://www.reddit.com" - self.random = "random.json" - - def _getRandomPost(self, community): - response = requests.get(f"{self.url}/{community}/{self.random}") - return json.loads(response.text) - -class RedditProgrammerHumor(Reddit): - def __init__(self) -> None: - super().__init__() - self.community = "r/ProgrammerHumor" - - def getRandomPost(self): - post = self._getRandomPost(self.community) - with open(file="data/log/test.json", mode="w") as file: - file.write(json.dumps(obj=post, indent=2)) - file.close() - return post - - \ No newline at end of file + if url is not None: + response = requests.api.get(url=f"{url}/{self.api}") + return Comic(json.loads(response.text)) diff --git a/src/main.py b/src/main.py index efb9fe7..942e821 100644 --- a/src/main.py +++ b/src/main.py @@ -2,10 +2,9 @@ import time as t import asyncio import logging import datetime -import secretHandler +import secret_handler from addons import ProgrammerExcuses from addons import XKCD -#from addons import RedditProgrammerHumor from models.xkcdComic import Comic @@ -18,14 +17,10 @@ from discord import Guild from discord import Color from discord.activity import Game -botVersion = "1.0.23" -botDate = "02.03.2023" +botVersion = "1.0.24" +botDate = "16.02.2024" -secret = secretHandler.secret() -token = secret.loadSecret("secret.txt") -if token[0] != 0: - exit(f"Cannot load token. Error Code {token[0]}") -botToken = token[1] +secret = secret_handler.get_bot_token() # Init Logger logger = logging.getLogger('discord') @@ -34,132 +29,142 @@ handler = logging.FileHandler(filename='data/log/discord.log', encoding='utf-8', handler.setFormatter(logging.Formatter('%(asctime)s|%(levelname)s|%(name)s|:%(message)s')) logger.addHandler(handler) -#Init Addons -programmerExcuses = ProgrammerExcuses() -#redditProgrammerHumor = RedditProgrammerHumor() +# Init Addons +programmer_excuses = ProgrammerExcuses() +# redditProgrammerHumor = RedditProgrammerHumor() xkcd = XKCD() -class client(discord.Client): - async def startup(self): - await self.wait_until_ready() -def getDateTime(): - dateNow = datetime.datetime.now() - dateNow = str(dateNow).split(" ") - unix = t.time() - time = dateNow[1] - time = time.split(".") - time = time[0] - dateNow = dateNow[0] - return dateNow, time, unix +class Client(discord.Client): + async def startup(self): + await self.wait_until_ready() -startTime = getDateTime()[2] -bot = client(intents=discord.Intents.all()) +def get_date_time(): + date_now = datetime.datetime.now() + date_now = str(date_now).split(" ") + unix = t.time() + time = date_now[1] + time = time.split(".") + time = time[0] + date_now = date_now[0] + return date_now, time, unix + + +start_time = get_date_time()[2] + +bot = Client(intents=discord.Intents.all()) tree = app_commands.CommandTree(client=bot) -async def chnagePresence(intervalInSeconds=60): - while True: - await bot.change_presence(activity=Game(name="with penguins"), status=Status.online) - await asyncio.sleep(intervalInSeconds) - countGuilds = 0 - async for guild in bot.fetch_guilds(): - countGuilds += 1 - - await bot.change_presence(activity=Game(name=f"on {countGuilds} Servers"), status=Status.online) - await asyncio.sleep(intervalInSeconds) +async def change_presence(interval_in_seconds=120): + while True: + await bot.change_presence(activity=Game(name="with penguins"), status=Status.online) + await asyncio.sleep(interval_in_seconds) + + count_guilds = 0 + async for guild in bot.fetch_guilds(): + count_guilds += 1 + + await bot.change_presence(activity=Game(name=f"on {count_guilds} Servers"), status=Status.online) + await asyncio.sleep(interval_in_seconds) + @bot.event async def on_ready(): - startTime = getDateTime()[2] - bot.loop.create_task(chnagePresence()) - logger.info(f"Logged in as: {bot.user.name} with ID {bot.user.id}") - await bot.change_presence(activity=Game(name="with penguins"), status=Status.online) - await tree.sync() + start_time = get_date_time()[2] + await bot.loop.create_task(change_presence()) + logger.info(f"Logged in as: {bot.user.name} with ID {bot.user.id}") + await bot.change_presence(activity=Game(name="with penguins"), status=Status.online) + await tree.sync() + @bot.event async def on_guild_join(guild: Guild): - logger.info("Added to Guild") - await guild.system_channel.send("Hii^^") - + logger.info("Added to Guild") + await guild.system_channel.send("Hii^^") @tree.command(name='excuse', description='Get a random excuse from programmingexcuses') async def slash(interaction: Interaction): - logger.info("Command: excuse") - await interaction.response.send_message(programmerExcuses.getExcuse()) + logger.info("Command: excuse") + await interaction.response.send_message(programmer_excuses.get_excuse()) + @tree.command(name='get-latest-comic', description='Get latest comic from XKCD') async def slash(interaction: Interaction): - logger.info("Command: get-latest-comic") - comic = xkcd.getLastComic() + logger.info("Command: get-latest-comic") + comic = xkcd.get_last_comic() + + embed = discord.Embed(title=comic.title, color=Color.blue(), url=f"{xkcd.url}/{comic.num}") + embed.set_image(url=comic.img) + await interaction.response.send_message(embed=embed) - embed = discord.Embed(title=comic.title, color=Color.blue(), url=f"{xkcd.url}/{comic.num}") - embed.set_image(url=comic.img) - await interaction.response.send_message(embed=embed) @tree.command(name='get-random-comic', description='Get a random comic from XKCD') async def slash(interaction: Interaction): - logger.info("Command: get-random-comic") - comic = xkcd.getRandomComic() - - embed = discord.Embed(title=comic.title, color=Color.blue(), url=f"{xkcd.url}/{comic.num}") - embed.set_image(url=comic.img) - await interaction.response.send_message(embed=embed) + logger.info("Command: get-random-comic") + comic = xkcd.get_random_comic() -#@tree.command(name='programmer-humor', description='Get a random Post from r/ProgrammerHumor') -#async def slash(interaction: Interaction): -# post = redditProgrammerHumor.getRandomPost() -# await interaction.response.send_message("hi") + embed = discord.Embed(title=comic.title, color=Color.blue(), url=f"{xkcd.url}/{comic.num}") + embed.set_image(url=comic.img) + await interaction.response.send_message(embed=embed) +# @tree.command(name='programmer-humor', description='Get a random Post from r/ProgrammerHumor') +# async def slash(interaction: Interaction): +# post = redditProgrammerHumor.getRandomPost() +# await interaction.response.send_message("hi") + @tree.command(name="info", description="get info about this bot") async def slash(interaction: Interaction): - logger.info("Command: info") - timeNow = getDateTime()[2] - uptime = timeNow - startTime + logger.info("Command: info") + time_now = get_date_time()[2] + uptime = time_now - start_time - botString = "" - botString += f"Uptime : {int(round(uptime, 0))}s\n" - botString += f"Version : {botVersion} from {botDate}\n" - botString += f"Developer : DasMoorhuhn.py#2604\n" - botString += f"Sourcecode: https://gitlab.com/HendrikHeine/tux-discord-bot" + bot_string = "" + bot_string += f"Uptime : {int(round(uptime, 0))}s\n" + bot_string += f"Version : {botVersion} from {botDate}\n" + bot_string += f"Developer : dasmoorhuhn\n" + bot_string += f"Sourcecode: https://gitlab.com/DasMoorhuhn/tux-discord-bot" + + embed = discord.Embed(title=f"Info", description="about this Bot", timestamp=datetime.datetime.utcnow(), + color=Color.blue()) + # embed.set_thumbnail(url=interaction.guild.icon) + embed.add_field(name="Bot", value=bot_string, inline=False) + await interaction.response.send_message(embed=embed) - embed = discord.Embed(title=f"Info", description="about this Bot", timestamp=datetime.datetime.utcnow(), color=Color.blue()) - #embed.set_thumbnail(url=interaction.guild.icon) - embed.add_field(name="Bot", value=botString, inline=False) - await interaction.response.send_message(embed=embed) @tree.command(name="help", description="List of all Commands") async def slash(interaction: Interaction): - logger.info("Command: help") - commandListString = "" - commandListString += "`/info` : Get infos about the server and the Bot\n" - commandListString += "`/help` : Get this view\n" - commandListString += "`/get-random-comic`: Get a randowm XCCD comic\n" - commandListString += "`/get-latest-comic`: Get latest comic from XKCD\n" - commandListString += "`/excuse` : Get a random excuse from programmingexcuses" + logger.info("Command: help") + command_list_string = "" + command_list_string += "`/info` : Get infos about the server and the Bot\n" + command_list_string += "`/help` : Get this view\n" + command_list_string += "`/get-random-comic`: Get a randowm XCCD comic\n" + command_list_string += "`/get-latest-comic`: Get latest comic from XKCD\n" + command_list_string += "`/excuse` : Get a random excuse from programmingexcuses" - embed = discord.Embed(title=f"Help", description="List of commands", color=Color.blue()) - #embed.set_thumbnail(url=interaction.guild.icon) - embed.add_field(name="Commands", value=commandListString, inline=True) + embed = discord.Embed(title=f"Help", description="List of commands", color=Color.blue()) + # embed.set_thumbnail(url=interaction.guild.icon) + embed.add_field(name="Commands", value=command_list_string, inline=True) + + await interaction.response.send_message(embed=embed) - await interaction.response.send_message(embed=embed) @tree.error async def on_app_command_error(interaction: Interaction, error): - if isinstance(error, app_commands.MissingPermissions): - await interaction.response.send_message(content="Du hast keine Adminrechte", ephemeral=True) - else: - raise error + if isinstance(error, app_commands.MissingPermissions): + await interaction.response.send_message(content="Du hast keine Adminrechte", ephemeral=True) + else: + raise error -#Prevent Gateway Heartbeat Block + +# Prevent Gateway Heartbeat Block try: - bot.run(token=botToken) + bot.run(token=secret_handler.get_bot_token()) except Exception as err: - raise err - exit(1) + raise err finally: - logger.info("Stopped") + logger.info("Stopped") diff --git a/src/models/xkcdComic.py b/src/models/xkcdComic.py index 893f8de..b885345 100644 --- a/src/models/xkcdComic.py +++ b/src/models/xkcdComic.py @@ -1,13 +1,13 @@ class Comic: - def __init__(self, data) -> None: - self.day = data['day'] - self.month = data['month'] - self.year = data['year'] - self.num = data['num'] - self.link = data['link'] - self.news = data['news'] - self.safe_title = data['safe_title'] - self.transcript = data['transcript'] - self.alt = data['alt'] - self.img = data['img'] - self.title = data['title'] + def __init__(self, data) -> None: + self.day = data['day'] + self.month = data['month'] + self.year = data['year'] + self.num = data['num'] + self.link = data['link'] + self.news = data['news'] + self.safe_title = data['safe_title'] + self.transcript = data['transcript'] + self.alt = data['alt'] + self.img = data['img'] + self.title = data['title'] diff --git a/src/secretHandler.py b/src/secretHandler.py deleted file mode 100644 index 0b4a902..0000000 --- a/src/secretHandler.py +++ /dev/null @@ -1,69 +0,0 @@ -'''https://gitlab.com/HendrikHeine/py-secret-handler''' - -import json - -class __fileType: - def __init__(self) -> None: - pass - - def _loadFromTXT(self, fileName:str): - '''!!!DONT USE!!!''' - try: - with open(file=fileName, mode="r") as file: - return [0, str(file.readlines()[0].strip("\n"))] - except: - return [1] - - def _loadFromJSON(self, fileName:str, item:str): - '''!!!DONT USE!!!''' - if item == "": - return [2] - else: - try: - with open(file=fileName, mode="r") as file: - try:return [0, json.loads(file.read())[item]] - except:return [5] - except: - return [1] - -class secret(__fileType): - '''Class for load secrets like API keys or tokens''' - def __init__(self) -> None: - super().__init__() - - def loadSecret(self, fileName:str, item=""): - ''' - fileName(str) - the name of the secret file. - Valid formats: .json and .txt - - item(str) - name of the item in the JSON file. By default empty - - Return Values(list): - 0: Ok - 1: File could not load - 2: No item given for JSON - 3: Invalid file format (for example .exe, .csv) - 4: No format for file given - 5: Invalid item for JSON - ''' - try:fileType = fileName.split(".")[1] - except:return [4] - - if fileType == "json": - result = self._loadFromJSON(fileName=fileName, item=item) - if result[0] == 0: - return result - else: - return [result[0]] - - elif fileType == "txt": - result = self._loadFromTXT(fileName=fileName) - if result[0] == 0: - return result - else: - return [result[0]] - - else: - return [3] diff --git a/src/secret_handler.py b/src/secret_handler.py new file mode 100644 index 0000000..41e7fa7 --- /dev/null +++ b/src/secret_handler.py @@ -0,0 +1,7 @@ +import json + + +def get_bot_token(): + with open(file='secret.json', mode='r') as file: + secret = json.load(file) + return secret['BOT_TOKEN']