Skip to content

Commit

Permalink
Merge pull request #37 from Okaneeee/develop
Browse files Browse the repository at this point in the history
Merging develop in main
  • Loading branch information
Okaneeee authored Feb 11, 2024
2 parents 62da6bf + c521c31 commit a2130a8
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 11 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/spelling.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Spelling

on: [push, pull_request]

jobs:
typos:
name: "Spell check"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: crate-ci/typos@master
with:
files: .
config: ./.github/workflows/typos.toml
2 changes: 2 additions & 0 deletions .github/workflows/typos.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[files]
extend-exclude = ["src/consts.py"]
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ basic_model_intents.pkl
basic_model_words.pkl
basic_model.keras

# Logs
[Ll]og[Ss]/

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ OWNID =
**GUILD** is the server ID you want the bot be active on. You can remove this field but you'll need to remove it on the [`main.py`](./src/main.py) file too. </br>
*More information on how to get your server ID [here](https://support.discord.com/hc/en-us/articles/206346498).*

**OWNID** is the bot's ID. It is used as a prefix for the bot (when you're mentionning (@) it). You can remove this field but you'll also need to remove it on the [`main.py`](./src/main.py) file and set a new prefix. </br>
**OWNID** is the bot's ID. It is used as a prefix for the bot (when you're mentioning (@) it). You can remove this field but you'll also need to remove it on the [`main.py`](./src/main.py) file and set a new prefix. </br>
*More information on how to get the bot ID [here](https://support.discord.com/hc/en-us/articles/206346498).*
</br></br>

Expand All @@ -105,6 +105,13 @@ python src/main.py

</details>

Checking code quality with these actions:

| Actions | Done | Status |
|-------------------------|------|--------|
| Spelling || [![Spelling](https://github.com/Okaneeee/discord-chatbot/actions/workflows/spelling.yml/badge.svg)](https://github.com/Okaneeee/discord-chatbot/actions/workflows/spelling.yml) |
| CodeQL || [![CodeQL](https://github.com/Okaneeee/discord-chatbot/actions/workflows/codeql.yml/badge.svg)](https://github.com/Okaneeee/discord-chatbot/actions/workflows/codeql.yml) |

## Features

- [x] A `ping` slash command to see the bot's latency *(mostly for testing purposes)*
Expand Down Expand Up @@ -153,4 +160,4 @@ Some part are written with the help of [GitHub Copilot](https://copilot.github.c
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.</br>
This include all contributions to the project, even from the community.

Copyright © 2024 Okane
Copyright © 2024 Okane
11 changes: 11 additions & 0 deletions src/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,15 @@
"REALiZE - LiSA",
"Crime and Punishment - Ado",
"怪物 - YOASOBI",
"Witch Hunt - Azari",
"HOLLOW HUNGER - OxT"
"Scarlet - DAZBEE",
"Ambivalent - Uru",
"ZERO ICHI - Queen Bee",
"Be a Flower - Ryokuoushoku Shakai",
"Hikoutei - King Gnu",
"color - yama",
"Daddy! Daddy! Do! - Masayuki Suzuki",
"Whisper Whisper Whisper - Azari",
"DIGNITY - Ado",
]
4 changes: 4 additions & 0 deletions src/func.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import requests
from logger import Logger

LOGGER = Logger()

def wikisearch(query: str):
"""Searches wikipedia for a given query and returns the first paragraph of the article.
Expand Down Expand Up @@ -38,6 +41,7 @@ def which_function(func_to_call: str, query: str):
query = query.translate({ord(i): None for i in '!.?:;,'})

if func_to_call == 'wikisearch':
LOGGER.makeLog(f"Called *wikisearch* function with [{query}]", "INFO")
i = 1
while not done:
lastXWords: str = ' '.join(query.split(" ")[-i:])
Expand Down
2 changes: 1 addition & 1 deletion src/json/intents.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"context_set": ""
},
{"tag": "privacy",
"patterns": ["How do you handle my personal information", "How do you handle my data", "How do you handle my personal data", "Is my data secure", "Are my informations secure", "Is my data safe", "Are my informations safe"],
"patterns": ["How do you handle my personal information", "How do you handle my data", "How do you handle my personal data", "Is my data secure", "Are my information secure", "Is my data safe", "Are my information safe"],
"responses": ["As I can't handle the context of conversations ||at least, for now||, I don't and I can't store any personal data. The only data I have is my training data."],
"context_set": ""
},
Expand Down
72 changes: 72 additions & 0 deletions src/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import logging
import os, errno

def mkdir_p(path):
try:
os.makedirs(path, exist_ok=True) # Python>3.2
except TypeError:
try:
os.makedirs(path)
except OSError as exc: # Python >2.5
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else: raise

class Logger:
def __init__(self, file_name: str = "bot.log", folder: str = "logs"):
mkdir_p(str(folder))
self.log_path = f'{folder}/{file_name}'

logging.root.handlers = []
logging.basicConfig(format='%(levelname)s | %(asctime)s - %(message)s', datefmt='%Y-%m-%d (%a) %H:%M:%S', level=logging.INFO, handlers=[logging.StreamHandler(), logging.FileHandler(self.log_path)])


def __debug(self, message: str):
"""Log a debug message
"""
logging.debug(message)

def __info(self, message: str):
"""Log an info message
"""
logging.info(message)
print(f'{message}')

def __warning(self, message: str):
"""Log a warning message
"""
logging.warning(message)

def __error(self, message: str):
"""Log an error message
"""
logging.error(message)

def __critical(self, message: str):
"""Log a critical message
"""
logging.critical(message)

def makeLog(self, message: str, level: str):
"""Make a log message
Args:
message (str): Message to log
level (str): Log level
Raises:
ValueError: Invalid log level
"""
match level.upper():
case "DEBUG":
self.__debug(message)
case "INFO":
self.__info(message)
case "WARNING":
self.__warning(message)
case "ERROR":
self.__error(message)
case "CRITICAL":
self.__critical(message)
case _:
raise ValueError("Invalid log level")
47 changes: 39 additions & 8 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
from random import randint
from typing import Optional

## other programs
## other
from consts import SONGS
from func import which_function
from logger import Logger

## os & env
import sys
Expand All @@ -21,15 +22,17 @@
from neuralintents import BasicAssistant

# -- config
LOGGER = Logger()
load_dotenv()

try:
chatbot = BasicAssistant('./src/json/intents.json')
except FileNotFoundError:
chatbot = BasicAssistant('../src/json/intents.json')
print("[INFO] Training model...")

LOGGER.makeLog("Training model...", "INFO")
chatbot.fit_model(epochs=400)
print("[INFO] Saving model...")
LOGGER.makeLog("Saving model...", "INFO")
chatbot.save_model()

## const
Expand All @@ -38,8 +41,10 @@
GUILD = discord.Object(id=int(getenv('GUILD'))) # type: ignore

if not TOKEN:
LOGGER.makeLog("Undefined token", "CRITICAL")
sys.exit("Undefined token")
if not OWNID: # NOTE: Remove if changing prefix
LOGGER.makeLog("Undefined ID", "CRITICAL")
sys.exit("Undefined ID")

PRFX: str = f"<@{OWNID}>" # NOTE: Edit if changing prefix
Expand All @@ -50,13 +55,15 @@

client = commands.Bot(PRFX, intents=intents, activity=discord.Activity(type=discord.ActivityType.listening, name=SONGS[randint(0, len(SONGS)-1)]))

print("[INFO] Bot is starting...")
LOGGER.makeLog("Bot is starting...", "INFO")

client.activity = discord.Activity(type=discord.ActivityType.listening, name=SONGS[randint(0, len(SONGS)-1)])

# -- bot
@client.event
async def on_ready():
print('[INFO] Successfully loggged in as {0.user}'.format(client))
print('[DEBUG] ID: {0.user.id}'.format(client))
LOGGER.makeLog(f"Successfully loggged in as {client.user}", "INFO")
LOGGER.makeLog(f"ID: {client.user.id}", "DEBUG") #type: ignore --- no error here
sys.stdout.flush()
await client.tree.sync(guild=GUILD)

Expand All @@ -67,6 +74,7 @@ async def on_message(message):
return

if message.content.startswith(PRFX):
LOGGER.makeLog(f"Mentioned bot", "DEBUG")
cb_response = chatbot.process_input(message.content[len(PRFX):])
try:
await message.channel.send(which_function(cb_response, message.content[len(PRFX):])) # type: ignore --- no error here
Expand All @@ -80,7 +88,12 @@ async def on_message(message):
)
async def ping(interaction: discord.Interaction):
"""Get bot's latency"""
await interaction.response.send_message(f"Pong! ||*with {round(client.latency * 1000)}ms*||")
try:
LOGGER.makeLog(f"Invoked ping command ({round(client.latency * 1000)})", "DEBUG")
await interaction.response.send_message(f"Pong! ||*with {round(client.latency * 1000)}ms*||")
except discord.errors.NotFound or discord.app_commands.errors.CommandInvokeError:
LOGGER.makeLog(f"Error occurred when calling *ping* command", "ERROR")
await interaction.response.send_message(f"An error occurred...", ephemeral=True)

@client.tree.command(
name="joined",
Expand All @@ -94,10 +107,28 @@ async def joined(interaction: discord.Interaction, member: Optional[discord.Memb

# The format_dt function formats the date time into a human readable representation in the official client
try:
LOGGER.makeLog(f"Invoked joined command for {member}", "DEBUG")
await interaction.response.send_message(f'{member} joined {discord.utils.format_dt(member.joined_at)}') # type: ignore --- no error here either
except discord.errors.NotFound or discord.app_commands.errors.CommandInvokeError:
LOGGER.makeLog(f"Error occurred when calling *joined command", "ERROR")
await interaction.response.send_message(f"An error occurred...", ephemeral=True)

@client.tree.command(
name="song",
description="Replies with a random song and changes the bot's activity to it"
)
async def song(interaction: discord.Interaction):
"""Get a random song"""
try:
LOGGER.makeLog(f"Invoked song command", "DEBUG")
r_song = SONGS[randint(0, len(SONGS)-1)]
await interaction.response.send_message(f"You should listen to {r_song}!")
await client.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name=r_song))
except discord.errors.NotFound or discord.app_commands.errors.CommandInvokeError:
LOGGER.makeLog(f"Error occurred when calling *song* command", "ERROR")
await interaction.response.send_message(f"An error occurred...", ephemeral=True)

client.tree.copy_global_to(guild=GUILD)

# -- run
client.tree.copy_global_to(guild=GUILD)
client.run(TOKEN)

0 comments on commit a2130a8

Please sign in to comment.