feat: Add misandrist insults and big CS2 events matches fetch from HLTV.org
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -160,4 +160,6 @@ cython_debug/
|
|||||||
#.idea/
|
#.idea/
|
||||||
|
|
||||||
data/
|
data/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
|
*.disabled
|
||||||
14
Dockerfile
Normal file
14
Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
FROM python:3.13.14-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
ENV TOKEN=""
|
||||||
|
ENV URL=""
|
||||||
|
|
||||||
|
|
||||||
|
ENTRYPOINT ["python", "main.py"]
|
||||||
375
cogs/cs.py
Normal file
375
cogs/cs.py
Normal file
@@ -0,0 +1,375 @@
|
|||||||
|
import discord, datetime, os, re, json
|
||||||
|
from selenium import webdriver
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from discord.ext import commands, tasks, bridge
|
||||||
|
from setup.logger import LOGGER
|
||||||
|
from models.cs_models import *
|
||||||
|
|
||||||
|
BASE_URL = "https://www.hltv.org"
|
||||||
|
|
||||||
|
PAGE_FILE = os.path.join("data","hltv.html")
|
||||||
|
|
||||||
|
MATCHES_FILE = os.path.join("data","matches.json")
|
||||||
|
|
||||||
|
# Cache duration in seconds (6 hours)
|
||||||
|
DATA_CACHE_DURATION = 3600 * 6
|
||||||
|
|
||||||
|
# Match age threshold in seconds (2 days)
|
||||||
|
OLD_MATCH_DURATION = 3600 * 24 * 2
|
||||||
|
|
||||||
|
# Reaction emojis for match events
|
||||||
|
EMOJI_CREATE_EVENT = "✅" # Create guild event for the match
|
||||||
|
EMOJI_REMOVE_EVENT = "❌" # Remove guild event for the match
|
||||||
|
|
||||||
|
class CSCog(commands.Cog):
|
||||||
|
def __init__(self, bot:discord.Bot):
|
||||||
|
self.bot = bot
|
||||||
|
self.matches:list[Match] = []
|
||||||
|
self.message_match_map = {} # Maps message IDs to Match objects
|
||||||
|
self.get_matches.start()
|
||||||
|
|
||||||
|
def is_up_to_date(self) -> bool:
|
||||||
|
"""Check if PAGE_FILE and MATCHES_FILE are up to date."""
|
||||||
|
try:
|
||||||
|
page_modified = datetime.datetime.fromtimestamp(os.stat(PAGE_FILE).st_ctime)
|
||||||
|
matches_modified = datetime.datetime.fromtimestamp(os.stat(MATCHES_FILE).st_ctime)
|
||||||
|
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
page_age = now.timestamp() - page_modified.timestamp()
|
||||||
|
matches_age = now.timestamp() - matches_modified.timestamp()
|
||||||
|
|
||||||
|
return page_age <= DATA_CACHE_DURATION and matches_age <= DATA_CACHE_DURATION
|
||||||
|
except FileNotFoundError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_page(self) -> None:
|
||||||
|
"""Get the page from https://www.hltv.org/matches/ using Firefox webdriver and save to PAGE_FILE."""
|
||||||
|
driver = webdriver.Firefox()
|
||||||
|
driver.get("https://www.hltv.org/matches/")
|
||||||
|
html = driver.page_source
|
||||||
|
driver.close()
|
||||||
|
|
||||||
|
with open(PAGE_FILE, 'w') as f:
|
||||||
|
f.write(html)
|
||||||
|
|
||||||
|
def save(self) -> None:
|
||||||
|
"""Save self.matches to MATCHES_FILE."""
|
||||||
|
matches_data = [match.to_dict() for match in self.matches]
|
||||||
|
|
||||||
|
with open(MATCHES_FILE, 'w') as f:
|
||||||
|
json.dump(matches_data, f, indent=2)
|
||||||
|
|
||||||
|
def remove_old_matches(self) -> None:
|
||||||
|
"""Remove matches that are older than OLD_MATCH_DURATION."""
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
filtered_matches = []
|
||||||
|
|
||||||
|
for match in self.matches:
|
||||||
|
if match.date is None:
|
||||||
|
# Keep matches with no date
|
||||||
|
filtered_matches.append(match)
|
||||||
|
else:
|
||||||
|
match_age = now.timestamp() - match.date.timestamp()
|
||||||
|
if match_age <= OLD_MATCH_DURATION:
|
||||||
|
filtered_matches.append(match)
|
||||||
|
|
||||||
|
self.matches = filtered_matches
|
||||||
|
|
||||||
|
@tasks.loop(minutes=5)
|
||||||
|
async def get_matches(self):
|
||||||
|
if self.is_up_to_date():
|
||||||
|
# Load from MATCHES_FILE
|
||||||
|
try:
|
||||||
|
with open(MATCHES_FILE) as f:
|
||||||
|
matches_data = json.load(f)
|
||||||
|
|
||||||
|
self.matches = [Match.from_dict(match_data) for match_data in matches_data]
|
||||||
|
self.remove_old_matches()
|
||||||
|
except Exception as e:
|
||||||
|
LOGGER.error(f"Error loading matches from cache: {e}")
|
||||||
|
self.matches = []
|
||||||
|
else:
|
||||||
|
# Fetch new data
|
||||||
|
self.get_page()
|
||||||
|
|
||||||
|
# Read and parse the page
|
||||||
|
with open(PAGE_FILE) as f:
|
||||||
|
html = f.read()
|
||||||
|
|
||||||
|
page = BeautifulSoup(html)
|
||||||
|
|
||||||
|
all_matches = []
|
||||||
|
for section in page.find_all("div", {"class": "matches-chronologically"}):
|
||||||
|
all_matches.extend(section.find_all("div", {"class": "match-wrapper"}))
|
||||||
|
|
||||||
|
self.matches = []
|
||||||
|
for match_event in all_matches:
|
||||||
|
event = match_event.find("div", {"class": "match-event"})
|
||||||
|
event_name = event.attrs["data-event-headline"]
|
||||||
|
|
||||||
|
# Extract event logo
|
||||||
|
event_logo_container = event.find("div", {"class": "match-event-logo-container"})
|
||||||
|
event_logo_url = None
|
||||||
|
if event_logo_container:
|
||||||
|
logo_img = event_logo_container.find("img")
|
||||||
|
if logo_img and logo_img.attrs.get("src"):
|
||||||
|
event_logo_url = logo_img.attrs["src"]
|
||||||
|
|
||||||
|
event_obj = Event(int(event.attrs["data-event-id"]), event_name, event_logo_url)
|
||||||
|
|
||||||
|
href = str(match_event.find("a", {"class": "match-top"}).attrs["href"])
|
||||||
|
match_href = "https://hltv.org" + href
|
||||||
|
|
||||||
|
match_time_elt = match_event.find("div", {"class": "match-time"})
|
||||||
|
if match_time_elt:
|
||||||
|
match_timestamp = int(match_time_elt.attrs["data-unix"])
|
||||||
|
match_date = datetime.datetime.fromtimestamp(match_timestamp/1000)
|
||||||
|
else:
|
||||||
|
match_date = None
|
||||||
|
|
||||||
|
match_format = match_event.find("div", {"class": "match-meta"}).text
|
||||||
|
|
||||||
|
teams = match_event.find_all("div", {"class": "match-team"})
|
||||||
|
match_teams = []
|
||||||
|
for match_team in teams:
|
||||||
|
team = match_team.find("div", {"class": "match-teamname"})
|
||||||
|
team_obj = Team(team.text, match_team.find("img").attrs["src"])
|
||||||
|
match_teams.append(team_obj)
|
||||||
|
|
||||||
|
if len(match_teams) == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
match_obj = Match(match_href, match_format, event_obj, match_teams, match_date)
|
||||||
|
self.matches.append(match_obj)
|
||||||
|
|
||||||
|
# Remove old matches and save to cache
|
||||||
|
self.remove_old_matches()
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
if self.matches:
|
||||||
|
print(str(self.matches[0]))
|
||||||
|
|
||||||
|
def check_event(self, match: Match, event: discord.ScheduledEvent) -> bool:
|
||||||
|
"""
|
||||||
|
Check if a scheduled event matches the given match.
|
||||||
|
Returns True if both team names appear in the event name (case-insensitive).
|
||||||
|
"""
|
||||||
|
event_name_lower = event.name.lower()
|
||||||
|
team1_name_lower = match.teams[0].name.lower()
|
||||||
|
team2_name_lower = match.teams[1].name.lower()
|
||||||
|
|
||||||
|
# Check if both team names are in the event name
|
||||||
|
return team1_name_lower in event_name_lower and team2_name_lower in event_name_lower
|
||||||
|
|
||||||
|
async def create_guild_event(self, guild: discord.Guild, match: Match) -> discord.ScheduledEvent | None:
|
||||||
|
"""
|
||||||
|
Create a scheduled guild event for the match.
|
||||||
|
Returns the created event or None if it already exists or creation fails.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Check if event already exists
|
||||||
|
for event in guild.scheduled_events:
|
||||||
|
if self.check_event(match, event):
|
||||||
|
return event
|
||||||
|
|
||||||
|
# Create event name
|
||||||
|
event_name = f"{match.teams[0].name} vs {match.teams[1].name}"
|
||||||
|
|
||||||
|
# Set start and end times - use UTC timezone to match the embed display
|
||||||
|
if match.date:
|
||||||
|
# Convert the timestamp to UTC-aware datetime
|
||||||
|
timestamp = int(match.date.timestamp())
|
||||||
|
start_time = datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc)
|
||||||
|
end_time = start_time + datetime.timedelta(hours=2) # Assume 2 hour match
|
||||||
|
else:
|
||||||
|
start_time = datetime.datetime.now(tz=datetime.timezone.utc)
|
||||||
|
end_time = start_time + datetime.timedelta(hours=2)
|
||||||
|
|
||||||
|
# Create the event
|
||||||
|
event = await guild.create_scheduled_event(
|
||||||
|
name=event_name,
|
||||||
|
start_time=start_time,
|
||||||
|
end_time=end_time,
|
||||||
|
description=f"Event: {match.event.name}\nFormat: {match.format}\nWatch on HLTV: {match.url}",
|
||||||
|
location=""
|
||||||
|
)
|
||||||
|
LOGGER.info(f"Created guild event for {event_name} in {guild.name}")
|
||||||
|
return event
|
||||||
|
except Exception as e:
|
||||||
|
LOGGER.error(f"Error creating guild event in {guild.name}: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def remove_guild_event(self, guild: discord.Guild, match: Match) -> bool:
|
||||||
|
"""
|
||||||
|
Remove the scheduled guild event for the match.
|
||||||
|
Returns True if an event was removed, False otherwise.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
for event in guild.scheduled_events:
|
||||||
|
if self.check_event(match, event):
|
||||||
|
await event.delete()
|
||||||
|
LOGGER.info(f"Removed guild event {event.name} from {guild.name}")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
LOGGER.error(f"Error removing guild event from {guild.name}: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def create_match_embed(self, match: Match) -> discord.Embed:
|
||||||
|
"""
|
||||||
|
Create a Discord embed message containing match information.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
match: The Match object to display
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
discord.Embed: A formatted embed with match details
|
||||||
|
"""
|
||||||
|
# Create embed with title as the matchup
|
||||||
|
title = f"{match.teams[0].name} vs {match.teams[1].name}"
|
||||||
|
embed = discord.Embed(
|
||||||
|
title=title,
|
||||||
|
description=f"**Event:** {match.event.name}",
|
||||||
|
url=match.url,
|
||||||
|
color=discord.Color.blue()
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add match format
|
||||||
|
embed.add_field(
|
||||||
|
name="Format",
|
||||||
|
value=match.format,
|
||||||
|
inline=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add match date if available
|
||||||
|
if match.date:
|
||||||
|
embed.add_field(
|
||||||
|
name="Date & Time",
|
||||||
|
value=f"<t:{int(match.date.timestamp())}:F>",
|
||||||
|
inline=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add team information with logos
|
||||||
|
teams_info = f"[{match.teams[0].name}]({match.url})\n[{match.teams[1].name}]({match.url})"
|
||||||
|
embed.add_field(
|
||||||
|
name="Teams",
|
||||||
|
value=teams_info,
|
||||||
|
inline=False
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set thumbnail to event logo if available, otherwise use first team logo
|
||||||
|
if match.event.logo_url:
|
||||||
|
embed.set_thumbnail(url=match.event.logo_url)
|
||||||
|
elif match.teams[0].logo_url:
|
||||||
|
embed.set_thumbnail(url=match.teams[0].logo_url)
|
||||||
|
|
||||||
|
# Set footer with HLTV link
|
||||||
|
embed.set_footer(
|
||||||
|
text="HLTV.org",
|
||||||
|
icon_url="https://www.hltv.org/img/static/TopLogo2x.png"
|
||||||
|
)
|
||||||
|
|
||||||
|
return embed
|
||||||
|
|
||||||
|
@bridge.bridge_command()
|
||||||
|
async def test_match_embed(self, ctx:bridge.BridgeExtContext):
|
||||||
|
"""Send the first match as an embed to the test channel."""
|
||||||
|
TEST_CHANNEL_ID = 1305147782071451718
|
||||||
|
|
||||||
|
# Check if there are matches available
|
||||||
|
if not self.matches:
|
||||||
|
await ctx.send("❌ No matches available. Try running the scraper first.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get the first match
|
||||||
|
first_match = self.matches[0]
|
||||||
|
|
||||||
|
# Create the embed
|
||||||
|
embed = self.create_match_embed(first_match)
|
||||||
|
|
||||||
|
# Send to test channel
|
||||||
|
try:
|
||||||
|
channel = self.bot.get_channel(TEST_CHANNEL_ID)
|
||||||
|
if channel is None:
|
||||||
|
await ctx.send(f"❌ Could not find channel with ID {TEST_CHANNEL_ID}")
|
||||||
|
return
|
||||||
|
|
||||||
|
message = await channel.send(embed=embed)
|
||||||
|
|
||||||
|
# Add reactions
|
||||||
|
await message.add_reaction(EMOJI_CREATE_EVENT)
|
||||||
|
await message.add_reaction(EMOJI_REMOVE_EVENT)
|
||||||
|
|
||||||
|
# Track the message -> match mapping
|
||||||
|
self.message_match_map[message.id] = first_match
|
||||||
|
|
||||||
|
await ctx.reply(f"✅ Sent embed for match: {first_match.teams[0].name} vs {first_match.teams[1].name}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
LOGGER.error(f"Error sending embed: {e}")
|
||||||
|
await ctx.send(f"❌ Error sending embed: {e}")
|
||||||
|
|
||||||
|
@commands.Cog.listener()
|
||||||
|
async def on_raw_reaction_add(self, payload: discord.RawReactionActionEvent):
|
||||||
|
"""Handle reactions added to match embed messages."""
|
||||||
|
# Ignore reactions from the bot itself
|
||||||
|
if payload.user_id == self.bot.user.id:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Check if this is a tracked message
|
||||||
|
if payload.message_id not in self.message_match_map:
|
||||||
|
return
|
||||||
|
|
||||||
|
match = self.message_match_map[payload.message_id]
|
||||||
|
emoji = payload.emoji.name
|
||||||
|
|
||||||
|
# Get the guild
|
||||||
|
guild = self.bot.get_guild(payload.guild_id)
|
||||||
|
if guild is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get the message for replies
|
||||||
|
message = await self.get_reaction_message(payload)
|
||||||
|
if not message:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
if emoji == EMOJI_CREATE_EVENT:
|
||||||
|
# Create event
|
||||||
|
event = await self.create_guild_event(guild, match)
|
||||||
|
if event:
|
||||||
|
await message.reply(f"✅ Created guild event: **{event.name}**")
|
||||||
|
elif emoji == EMOJI_REMOVE_EVENT:
|
||||||
|
# Remove event
|
||||||
|
removed = await self.remove_guild_event(guild, match)
|
||||||
|
if removed:
|
||||||
|
await message.reply(
|
||||||
|
f"✅ Removed guild event for {match.teams[0].name} vs {match.teams[1].name}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await message.reply(
|
||||||
|
f"⚠️ No guild event found for this match"
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
LOGGER.error(f"Error handling reaction {emoji}: {e}")
|
||||||
|
|
||||||
|
async def get_reaction_message(self, payload: discord.RawReactionActionEvent) -> discord.Message | None:
|
||||||
|
"""Get the message object from a raw reaction payload."""
|
||||||
|
try:
|
||||||
|
channel = self.bot.get_channel(payload.channel_id)
|
||||||
|
if channel:
|
||||||
|
return await channel.fetch_message(payload.message_id)
|
||||||
|
except Exception as e:
|
||||||
|
LOGGER.error(f"Error fetching message: {e}")
|
||||||
|
return None
|
||||||
|
async def check_events(self):
|
||||||
|
"""Check scheduled events for matching CS matches."""
|
||||||
|
for match in self.matches:
|
||||||
|
for guild in self.bot.guilds:
|
||||||
|
events = [event for event in guild.scheduled_events if self.check_event(match, event)]
|
||||||
|
# print(guild.name, match)
|
||||||
|
|
||||||
|
# @commands.Cog.listener()
|
||||||
|
# async def on_ready(self):
|
||||||
|
# self.check_events.start()
|
||||||
|
|
||||||
31
cogs/insult.py
Normal file
31
cogs/insult.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import discord, json, os, random, re
|
||||||
|
import collections
|
||||||
|
from discord.ext import commands
|
||||||
|
from setup.logger import LOGGER
|
||||||
|
|
||||||
|
class InsultsCog(commands.Cog):
|
||||||
|
def __init__(self, bot:discord.Bot):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
with open(os.path.join("data", "insults.txt")) as f:
|
||||||
|
self.insults = [l.strip() for l in f.readlines()]
|
||||||
|
|
||||||
|
@commands.Cog.listener()
|
||||||
|
async def on_message(self, message:discord.Message):
|
||||||
|
if len(message.content.split()) > 3:
|
||||||
|
author = message.author
|
||||||
|
if any(author.id == u.id for u in self.men):
|
||||||
|
r = int(random.random()*100)
|
||||||
|
print(r)
|
||||||
|
if r < 5:
|
||||||
|
insult = random.choice(self.insults)
|
||||||
|
await message.reply(insult)
|
||||||
|
|
||||||
|
@commands.Cog.listener()
|
||||||
|
async def on_ready(self):
|
||||||
|
self.men:list[discord.Member] = []
|
||||||
|
for guild in self.bot.guilds:
|
||||||
|
for role in guild.roles:
|
||||||
|
if re.match(r'^([hH]im|[hH]e).*$',role.name):
|
||||||
|
self.men.extend(role.members)
|
||||||
|
self.men = list(set(self.men))
|
||||||
9
compose.yaml
Normal file
9
compose.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
services:
|
||||||
|
botmafieux:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ./Dockerfile
|
||||||
|
tags:
|
||||||
|
- nebulo9/botmafieux:v2
|
||||||
|
container_name: botmafieux
|
||||||
|
env_file: ./.env
|
||||||
239
main.py
239
main.py
@@ -1,164 +1,129 @@
|
|||||||
import os, discord, json, sys, random
|
import os, discord, json, sys, random
|
||||||
import modules.setup.db as db
|
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from asyncio import create_task
|
from asyncio import create_task
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from discord import option
|
from discord import option
|
||||||
from discord.ext import tasks, commands
|
from discord.ext import tasks, commands
|
||||||
from modules.setup.bot import bot, reload_feature
|
from setup.bot import bot, reload_feature
|
||||||
from modules.setup.logger import LOGGER
|
from setup.logger import LOGGER
|
||||||
from modules.cogs.productivity import TASKS as PRODUCTIVITY_TASKS, send_reminder
|
|
||||||
|
|
||||||
PARSER = ArgumentParser(description='BotMafieux for Discord.')
|
PARSER = ArgumentParser(description='BotMafieux for Discord.')
|
||||||
PARSER.add_argument('--guild_id',type=int,help='The guild ID.')
|
PARSER.add_argument('--guild_id',type=int,help='The guild ID.')
|
||||||
PARSER.add_argument('--channel_id',type=int,help='The channel ID.')
|
PARSER.add_argument('--channel_id',type=int,help='The channel ID.')
|
||||||
PARSER.add_argument('-r','--reload',action='store_true',help='Reload the bot.')
|
PARSER.add_argument('-r','--reload',action='store_true',help='Reload the bot.')
|
||||||
EXEC_ARGS = PARSER.parse_args()
|
EXEC_ARGS = PARSER.parse_args()
|
||||||
|
|
||||||
@tasks.loop(time=datetime.time(datetime.strptime('00:00','%H:%M')))
|
# @tasks.loop(time=datetime.time(datetime.strptime('00:00','%H:%M')))
|
||||||
async def birthday_anouncements_task():
|
# async def birthday_anouncements_task():
|
||||||
LOGGER.debug('birthday_anouncements_task started.')
|
# LOGGER.debug('birthday_anouncements_task started.')
|
||||||
for guild in bot.guilds:
|
# for guild in bot.guilds:
|
||||||
birthday_settings = db.select('birthday_settings',f'guild_id = {guild.id}')
|
# birthday_settings = db.select('birthday_settings',f'guild_id = {guild.id}')
|
||||||
if birthday_settings:
|
# if birthday_settings:
|
||||||
if birthday_settings['is_enabled']:
|
# if birthday_settings['is_enabled']:
|
||||||
for user in guild.members:
|
# for user in guild.members:
|
||||||
user_productivity_data = db.select('guild_user_productivity',f'user_id = {user.id} AND guild_id = {guild.id}')
|
# user_productivity_data = db.select('guild_user_productivity',f'user_id = {user.id} AND guild_id = {guild.id}')
|
||||||
if user_productivity_data:
|
# if user_productivity_data:
|
||||||
if user_productivity_data['is_enabled']:
|
# if user_productivity_data['is_enabled']:
|
||||||
user = guild.get_member(user.id)
|
# user = guild.get_member(user.id)
|
||||||
if user:
|
# if user:
|
||||||
birthday = user_productivity_data['birthday']
|
# birthday = user_productivity_data['birthday']
|
||||||
today = datetime.today().strftime('%d/%m')
|
# today = datetime.today().strftime('%d/%m')
|
||||||
if birthday == today:
|
# if birthday == today:
|
||||||
channel = guild.get_channel(user_productivity_data['channel_id'])
|
# channel = guild.get_channel(user_productivity_data['channel_id'])
|
||||||
if channel:
|
# if channel:
|
||||||
message = user_productivity_data['birthday_message']
|
# message = user_productivity_data['birthday_message']
|
||||||
if message:
|
# if message:
|
||||||
message = message.replace('{user}',user.mention)
|
# message = message.replace('{user}',user.mention)
|
||||||
await channel.send(message)
|
# await channel.send(message)
|
||||||
else:
|
# else:
|
||||||
LOGGER.debug(f'Channel {user_productivity_data["channel_id"]} not found.')
|
# LOGGER.debug(f'Channel {user_productivity_data["channel_id"]} not found.')
|
||||||
else:
|
# else:
|
||||||
LOGGER.debug(f'No birthday today for user {user.name} ({user.id}).')
|
# LOGGER.debug(f'No birthday today for user {user.name} ({user.id}).')
|
||||||
else:
|
# else:
|
||||||
LOGGER.debug(f'User {user.name} ({user.id}) not found.')
|
# LOGGER.debug(f'User {user.name} ({user.id}) not found.')
|
||||||
else:
|
# else:
|
||||||
LOGGER.debug(f'User {user.name} ({user.id}) has birthday announcements disabled.')
|
# LOGGER.debug(f'User {user.name} ({user.id}) has birthday announcements disabled.')
|
||||||
else:
|
# else:
|
||||||
LOGGER.debug(f'No birthday data found for user {user.name} ({user.id}).')
|
# LOGGER.debug(f'No birthday data found for user {user.name} ({user.id}).')
|
||||||
else:
|
# else:
|
||||||
LOGGER.debug(f'No productivity settings found for guild {guild.name} ({guild.id}).')
|
# LOGGER.debug(f'No productivity settings found for guild {guild.name} ({guild.id}).')
|
||||||
LOGGER.debug('birthday_anouncements_task ended.')
|
# LOGGER.debug('birthday_anouncements_task ended.')
|
||||||
|
|
||||||
@bot.slash_command(name='help',description='Displays the help message.')
|
# @bot.slash_command(name='help',description='Displays the help message.')
|
||||||
async def help(ctx:discord.ApplicationContext):
|
# async def help(ctx:discord.ApplicationContext):
|
||||||
"""Displays this message."""
|
# """Displays this message."""
|
||||||
command_name = 'help'
|
# command_name = 'help'
|
||||||
LOGGER.debug(f'{ctx.author.name} used /{command_name}.')
|
# LOGGER.debug(f'{ctx.author.name} used /{command_name}.')
|
||||||
embed = discord.Embed(title='Help',description='List of commands and their descriptions.',color=discord.Color.from_rgb(171,0,219))
|
# embed = discord.Embed(title='Help',description='List of commands and their descriptions.',color=discord.Color.from_rgb(171,0,219))
|
||||||
embed.set_author(name=bot.user.name,icon_url=bot.user.avatar.url)
|
# embed.set_author(name=bot.user.name,icon_url=bot.user.avatar.url)
|
||||||
for command in bot.commands:
|
# for command in bot.commands:
|
||||||
embed.add_field(name=command.name,value=command.description,inline=False)
|
# embed.add_field(name=command.name,value=command.description,inline=False)
|
||||||
await ctx.send_response(embed=embed,ephemeral=True)
|
# await ctx.send_response(embed=embed,ephemeral=True)
|
||||||
|
|
||||||
@bot.slash_command(name='reload',description='Reloads the bot.')
|
# @bot.slash_command(name='reload',description='Reloads the bot.')
|
||||||
@option(name='feature',description='The feature to reload.',required=True,choices=['birthday','productivity'])
|
# @option(name='feature',description='The feature to reload.',required=True,choices=['birthday','productivity'])
|
||||||
@commands.is_owner()
|
# @commands.is_owner()
|
||||||
async def reload(ctx:discord.ApplicationContext, feature:str):
|
# async def reload(ctx:discord.ApplicationContext, feature:str):
|
||||||
"""Reloads the bot."""
|
# """Reloads the bot."""
|
||||||
command_name = 'reload'
|
# command_name = 'reload'
|
||||||
guild = ctx.guild
|
# guild = ctx.guild
|
||||||
channel = ctx.channel
|
# channel = ctx.channel
|
||||||
LOGGER.debug(f'{ctx.author.name} used /{command_name} {feature}.')
|
# LOGGER.debug(f'{ctx.author.name} used /{command_name} {feature}.')
|
||||||
try:
|
# try:
|
||||||
reload_feature(feature)
|
# reload_feature(feature)
|
||||||
await ctx.send_response(f'{feature} reloaded!',ephemeral=True)
|
# await ctx.send_response(f'{feature} reloaded!',ephemeral=True)
|
||||||
except Exception as e:
|
# except Exception as e:
|
||||||
LOGGER.error(f'Error reloading feature {feature}: {e}')
|
# LOGGER.error(f'Error reloading feature {feature}: {e}')
|
||||||
await ctx.send_response(f'Error reloading feature {feature}: {e}',ephemeral=True)
|
# await ctx.send_response(f'Error reloading feature {feature}: {e}',ephemeral=True)
|
||||||
|
|
||||||
@bot.event
|
# @bot.event
|
||||||
async def on_member_join(member:discord.Member):
|
# async def on_member_join(member:discord.Member):
|
||||||
if not member.bot:
|
# if not member.bot:
|
||||||
user_id = member.id
|
# user_id = member.id
|
||||||
user_name = member.name
|
# user_name = member.name
|
||||||
user_mention = member.mention
|
# user_mention = member.mention
|
||||||
db_user = db.select('global_user',f'WHERE user_id = {user_id}')
|
# db_user = db.select('global_user',f'WHERE user_id = {user_id}')
|
||||||
if not db_user:
|
# if not db_user:
|
||||||
db.insert('global_user',user_id=user_id,user_name=user_name,user_mention=user_mention)
|
# db.insert('global_user',user_id=user_id,user_name=user_name,user_mention=user_mention)
|
||||||
|
|
||||||
@bot.event
|
# @bot.event
|
||||||
async def on_raw_member_remove(payload:discord.RawMemberRemoveEvent):
|
# async def on_raw_member_remove(payload:discord.RawMemberRemoveEvent):
|
||||||
user = payload.user
|
# user = payload.user
|
||||||
if not user.bot:
|
# if not user.bot:
|
||||||
user_id = user.id
|
# user_id = user.id
|
||||||
guild_id = payload.guild_id
|
# guild_id = payload.guild_id
|
||||||
db.delete('guild_user_birthday',f'user_id = {user_id} AND guild_id = {guild_id}')
|
# db.delete('guild_user_birthday',f'user_id = {user_id} AND guild_id = {guild_id}')
|
||||||
db.delete('guild_user_productivity',f'user_id = {user_id} AND guild_id = {guild_id}')
|
# db.delete('guild_user_productivity',f'user_id = {user_id} AND guild_id = {guild_id}')
|
||||||
|
|
||||||
@bot.event
|
# @bot.event
|
||||||
async def on_guild_join(guild:discord.Guild):
|
# async def on_guild_join(guild:discord.Guild):
|
||||||
guild_id = guild.id
|
# guild_id = guild.id
|
||||||
guild_name = guild.name
|
# guild_name = guild.name
|
||||||
LOGGER.info(f'Bot joined guild {guild_name} ({guild_id}).')
|
# LOGGER.info(f'Bot joined guild {guild_name} ({guild_id}).')
|
||||||
db.insert('guild',guild_id=guild_id)
|
# db.insert('guild',guild_id=guild_id)
|
||||||
db.insert('birthday_settings',guild_id=guild_id,is_enabled=False,channel_id=random.choice(guild.text_channels).id)
|
# db.insert('birthday_settings',guild_id=guild_id,is_enabled=False,channel_id=random.choice(guild.text_channels).id)
|
||||||
db.insert('productivity_settings',guild_id=guild_id,is_enabled=False)
|
# db.insert('productivity_settings',guild_id=guild_id,is_enabled=False)
|
||||||
|
|
||||||
@bot.event
|
# @bot.event
|
||||||
async def on_guild_remove(guild:discord.Guild):
|
# async def on_guild_remove(guild:discord.Guild):
|
||||||
guild_id = guild.id
|
# guild_id = guild.id
|
||||||
guild_name = guild.name
|
# guild_name = guild.name
|
||||||
LOGGER.info(f'Bot left guild {guild_name} ({guild_id}).')
|
# LOGGER.info(f'Bot left guild {guild_name} ({guild_id}).')
|
||||||
db.delete('birthday_settings',f'guild_id = {guild_id}')
|
# db.delete('birthday_settings',f'guild_id = {guild_id}')
|
||||||
db.delete('productivity_settings',f'guild_id = {guild_id}')
|
# db.delete('productivity_settings',f'guild_id = {guild_id}')
|
||||||
db.delete('guild',f'guild_id = {guild_id}')
|
# db.delete('guild',f'guild_id = {guild_id}')
|
||||||
|
|
||||||
@bot.event
|
@bot.event
|
||||||
async def on_ready():
|
async def on_ready():
|
||||||
LOGGER.info(f'{bot.user.name} has connected to Discord!')
|
if bot.user:
|
||||||
LOGGER.debug(f'Guilds: {bot.guilds}')
|
LOGGER.info(f'{bot.user.name} has connected to Discord!')
|
||||||
if EXEC_ARGS.reload and EXEC_ARGS.guild_id and EXEC_ARGS.channel_id:
|
LOGGER.debug(f'Guilds: {','.join([guild.name for guild in bot.guilds])}')
|
||||||
guild = bot.get_guild(EXEC_ARGS.guild_id)
|
|
||||||
channel = guild.get_channel_or_thread(EXEC_ARGS.channel_id)
|
|
||||||
await channel.send(f'{bot.user.name} Bot reloaded!',silent=True)
|
|
||||||
birthday_anouncements_task.start()
|
|
||||||
for guild in bot.guilds:
|
|
||||||
for user in guild.members:
|
|
||||||
user_id = user.id
|
|
||||||
db_user = db.select('global_user',f'user_id = {user_id}')
|
|
||||||
if not db_user:
|
|
||||||
db.insert('global_user',user_id=user_id,user_name=user.name,user_mention=user.mention)
|
|
||||||
|
|
||||||
productivity_settings = db.select('productivity_settings',f'guild_id = {guild.id}')
|
|
||||||
if productivity_settings:
|
|
||||||
if productivity_settings['is_enabled']:
|
|
||||||
for user in guild.members:
|
|
||||||
user_productivity_data = db.select('guild_user_productivity',f'user_id = {user.id} AND guild_id = {guild.id}')
|
|
||||||
if user_productivity_data:
|
|
||||||
if user_productivity_data['is_enabled']:
|
|
||||||
next_reminder = user_productivity_data['next_reminder']
|
|
||||||
if next_reminder > datetime.now().timestamp():
|
|
||||||
cooldown = next_reminder - datetime.now().timestamp()
|
|
||||||
channel = guild.get_channel(user_productivity_data['channel_id'])
|
|
||||||
reminder_message = user_productivity_data['reminder_message']
|
|
||||||
PRODUCTIVITY_TASKS[str(user.id)] = create_task(send_reminder(cooldown,user,channel,reminder_message))
|
|
||||||
else:
|
|
||||||
user_productivity_data['next_reminder'] = datetime.now().timestamp() + user_productivity_data['cooldown']
|
|
||||||
db.update('guild_user_productivity',f'user_id = {user.id} AND guild_id = {guild.id}',next_reminder=user_productivity_data['next_reminder'])
|
|
||||||
channel = guild.get_channel(user_productivity_data['channel_id'])
|
|
||||||
reminder_message = user_productivity_data['reminder_message']
|
|
||||||
PRODUCTIVITY_TASKS[str(user.id)] = create_task(send_reminder(user_productivity_data['cooldown'],user,channel,reminder_message))
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'No productivity settings found for guild {guild.name} ({guild.id}).')
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
db.check_conn()
|
load_dotenv()
|
||||||
result = db.select('token','token_name = \'discord\'','token_value')
|
TOKEN = os.getenv("TOKEN")
|
||||||
if result:
|
if TOKEN:
|
||||||
TOKEN = result['token_value']
|
|
||||||
bot.run(TOKEN)
|
bot.run(TOKEN)
|
||||||
else:
|
else:
|
||||||
LOGGER.error('No token found.')
|
LOGGER.error('No token found.')
|
||||||
|
|||||||
119
models/cs_models.py
Normal file
119
models/cs_models.py
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
class Event:
|
||||||
|
def __init__(self, event_id:int, name:str, logo_url:str = None) -> None:
|
||||||
|
self.__event_id = event_id
|
||||||
|
self.__name = name
|
||||||
|
self.__logo_url = logo_url
|
||||||
|
|
||||||
|
@property
|
||||||
|
def event_id(self):
|
||||||
|
return self.__event_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self.__name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def logo_url(self):
|
||||||
|
return self.__logo_url
|
||||||
|
|
||||||
|
def to_dict(self) -> dict:
|
||||||
|
return {
|
||||||
|
'event_id': self.event_id,
|
||||||
|
'name': self.name,
|
||||||
|
'logo_url': self.logo_url
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, data: dict) -> 'Event':
|
||||||
|
return cls(data['event_id'], data['name'], data.get('logo_url'))
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"<Event event_id={self.event_id} name='{self.name}'>"
|
||||||
|
|
||||||
|
|
||||||
|
class Team:
|
||||||
|
def __init__(self, name:str, logo_url:str) -> None:
|
||||||
|
self.__name = name
|
||||||
|
self.__logo_url = logo_url
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self.__name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def logo_url(self):
|
||||||
|
return self.__logo_url
|
||||||
|
|
||||||
|
def to_dict(self) -> dict:
|
||||||
|
return {
|
||||||
|
'name': self.name,
|
||||||
|
'logo_url': self.logo_url
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, data: dict) -> 'Team':
|
||||||
|
return cls(data['name'], data['logo_url'])
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"<Team logo_url='{self.logo_url}' name='{self.name}'>"
|
||||||
|
|
||||||
|
class Match:
|
||||||
|
def __init__(self, url:str, format:str, event:Event, teams:list[Team], date=None):
|
||||||
|
self.__date = date
|
||||||
|
self.__url = url
|
||||||
|
self.__format = format
|
||||||
|
self.__event = event
|
||||||
|
self.__teams = tuple(teams)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def date(self):
|
||||||
|
return self.__date
|
||||||
|
|
||||||
|
@property
|
||||||
|
def url(self):
|
||||||
|
return self.__url
|
||||||
|
|
||||||
|
@property
|
||||||
|
def format(self):
|
||||||
|
return self.__format
|
||||||
|
|
||||||
|
@property
|
||||||
|
def event(self):
|
||||||
|
return self.__event
|
||||||
|
|
||||||
|
@property
|
||||||
|
def teams(self):
|
||||||
|
return self.__teams
|
||||||
|
|
||||||
|
@property
|
||||||
|
def date_iso(self):
|
||||||
|
return self.__date.isoformat()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def teams_names(self):
|
||||||
|
return (self.__teams[0].name, self.__teams[1].name)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def teams_logos(self):
|
||||||
|
return (self.__teams[0].logo_url, self.__teams[1].logo_url)
|
||||||
|
|
||||||
|
def to_dict(self) -> dict:
|
||||||
|
return {
|
||||||
|
'url': self.url,
|
||||||
|
'format': self.format,
|
||||||
|
'event': self.event.to_dict(),
|
||||||
|
'teams': [team.to_dict() for team in self.teams],
|
||||||
|
'date': self.date.isoformat() if self.date else None
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, data: dict) -> 'Match':
|
||||||
|
event = Event.from_dict(data['event'])
|
||||||
|
teams = [Team.from_dict(team_data) for team_data in data['teams']]
|
||||||
|
date = datetime.datetime.fromisoformat(data['date']) if data['date'] else None
|
||||||
|
return cls(data['url'], data['format'], event, teams, date)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"<Match date='{self.date}' url='{self.url}' format='{self.url}' event={self.event} teams='{','.join(self.teams_names)}'>"
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
import discord, re
|
|
||||||
from discord import option
|
|
||||||
from discord.ext import commands
|
|
||||||
from datetime import datetime
|
|
||||||
from ..setup.logger import LOGGER
|
|
||||||
from ..setup import db
|
|
||||||
|
|
||||||
class BirthdayCog(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
@commands.slash_command(description='Sets birthday date. Must be in DAY/MONTH format.')
|
|
||||||
@option(name='date',description='Birthday date.',required=True)
|
|
||||||
@option(name='announcements',description='Enable or disable birthday announcements.',required=True,type=bool)
|
|
||||||
@option(name='message',description='The message to send when it is the user\'s birthday.',required=False)
|
|
||||||
@option(name='for_user',description='The user to set the birthday date for.',required=False,type=discord.Member)
|
|
||||||
async def birthday_set(self,ctx:discord.ApplicationContext, date:str,announcements:bool,message:str,for_user:discord.Member):
|
|
||||||
"""Sets birthday date. Must be in DAY/MONTH format."""
|
|
||||||
command_name = 'birthday_set'
|
|
||||||
guild_id = ctx.guild.id
|
|
||||||
author = ctx.author
|
|
||||||
birthday_settings = db.select('birthday_settings',f'guild_id = {guild_id}')
|
|
||||||
if birthday_settings:
|
|
||||||
if birthday_settings['is_enabled']:
|
|
||||||
if for_user:
|
|
||||||
if author.guild_permissions.administrator:
|
|
||||||
if re.match(r'^\d{1,2}\/\d{1,2}$', date):
|
|
||||||
user_data = db.select('guild_user_birthday',f'guild_id = {guild_id} AND user_id = {for_user.id}')
|
|
||||||
if user_data:
|
|
||||||
# Update user data
|
|
||||||
if message:
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {date} {announcements} {message} for {for_user.name}.')
|
|
||||||
db.update('guild_user_birthday',f'guild_id = {guild_id} AND user_id = {for_user.id}',birthday=date,is_enabled=announcements,birthday_message=message)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {date} {announcements} for {for_user.name}.')
|
|
||||||
db.update('guild_user_birthday',f'guild_id = {guild_id} AND user_id = {for_user.id}',birthday=date,is_enabled=announcements)
|
|
||||||
await ctx.send_response(f'{for_user.name}\'s birthday has been set to {date}.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
# Create user data
|
|
||||||
if message:
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {date} {announcements} {message} for {for_user.name}.')
|
|
||||||
db.insert('guild_user_birthday',guild_id=guild_id,user_id=for_user.id,birthday=date,is_enabled=announcements,birthday_message=message)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {date} {announcements} for {for_user.name}.')
|
|
||||||
db.insert('guild_user_birthday',guild_id=guild_id,user_id=for_user.id,birthday=date,is_enabled=announcements)
|
|
||||||
await ctx.send_response(f'{for_user.name}\'s birthday has been set to {date}.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} tried to use /{command_name} {date} {announcements} {message} for {for_user.name} but the date format is invalid.')
|
|
||||||
await ctx.send_response('The date format must be DAY/MONTH.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} tried to use /{command_name} {date} {announcements} {message} for {for_user.name} but is not an administrator.')
|
|
||||||
await ctx.send_response('You must be an administrator to run the command with "for_user".',ephemeral=True)
|
|
||||||
else:
|
|
||||||
if re.match(r'^\d{1,2}\/\d{1,2}$', date):
|
|
||||||
user_data = db.select('guild_user_birthday',f'guild_id = {guild_id} AND user_id = {author.id}')
|
|
||||||
if user_data:
|
|
||||||
# Update user data
|
|
||||||
if message:
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {date} {announcements} {message}.')
|
|
||||||
db.update('guild_user_birthday',f'guild_id = {guild_id} AND user_id = {author.id}',birthday=date,is_enabled=announcements,birthday_message=message)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {date} {announcements}.')
|
|
||||||
db.update('guild_user_birthday',f'guild_id = {guild_id} AND user_id = {author.id}',birthday=date,is_enabled=announcements)
|
|
||||||
await ctx.send_response(f'Your birthday has been set to {date}.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
# Create user data
|
|
||||||
if message:
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {date} {announcements} {message}.')
|
|
||||||
db.insert('guild_user_birthday',guild_id=guild_id,user_id=author.id,birthday=date,is_enabled=announcements,birthday_message=message)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {date} {announcements}.')
|
|
||||||
db.insert('guild_user_birthday',guild_id=guild_id,user_id=author.id,birthday=date,is_enabled=announcements)
|
|
||||||
await ctx.send_response(f'Your birthday has been set to {date}.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} tried to use /{command_name} {date} {announcements} {message} but the date format is invalid.')
|
|
||||||
await ctx.send_response('The date format must be DAY/MONTH.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} tried to use /{command_name} {date} {announcements} {message} but the birthday feature is not enabled.')
|
|
||||||
await ctx.send_response('The birthday feature is not enabled.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} tried to use /{command_name} {date} {announcements} {message} but the birthday feature is not enabled.')
|
|
||||||
await ctx.send_response('The birthday feature is not enabled.',ephemeral=True)
|
|
||||||
|
|
||||||
@commands.slash_command(description='Configurate birthday announcements.')
|
|
||||||
@option(name='channel',description='The channel to send birthday announcements to.',required=True,type=discord.TextChannel)
|
|
||||||
@option(name='enable',description='Enable or disable birthday announcements.',required=True,type=bool)
|
|
||||||
async def birthday_config(self,ctx:discord.ApplicationContext, channel:discord.TextChannel,enable:bool):
|
|
||||||
"""Configurate birthday announcements."""
|
|
||||||
command_name = 'birthday_config'
|
|
||||||
guild_id = ctx.guild.id
|
|
||||||
author = ctx.author
|
|
||||||
birthday_settings = db.select('birthday_settings',f'guild_id = {guild_id}')
|
|
||||||
if birthday_settings:
|
|
||||||
# Update guild birthday settings
|
|
||||||
if birthday_settings['is_enabled']:
|
|
||||||
if author.guild_permissions.administrator:
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {channel.name} {enable}.')
|
|
||||||
db.update('birthday_settings',f'guild_id = {guild_id}',channel_id=channel.id,is_enabled=enable)
|
|
||||||
await ctx.send_response(f'Birthday announcements have been {"enabled" if enable else "disabled"} in {channel.mention}.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} tried to use /{command_name} {channel.name} {enable} but is not an administrator.')
|
|
||||||
await ctx.send_response('You must be an administrator to run this command.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} tried to use /{command_name} {channel.name} {enable} but the birthday feature is not enabled.')
|
|
||||||
await ctx.send_response('The birthday feature is not enabled.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
# Create guild birthday settings
|
|
||||||
if author.guild_permissions.administrator:
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {channel.name} {enable}.')
|
|
||||||
db.insert('birthday_settings',guild_id=guild_id,channel_id=channel.id,is_enabled=enable)
|
|
||||||
await ctx.send_response(f'Birthday announcements have been {"enabled" if enable else "disabled"} in {channel.mention}.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} tried to use /{command_name} {channel.name} {enable} but is not an administrator.')
|
|
||||||
await ctx.send_response('You must be an administrator to run this command.',ephemeral=True)
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
import discord
|
|
||||||
from datetime import datetime
|
|
||||||
from discord.ext import commands, tasks
|
|
||||||
from discord import option
|
|
||||||
from typing import Union, Optional
|
|
||||||
from asyncio import sleep, create_task
|
|
||||||
from ..setup.logger import LOGGER
|
|
||||||
from ..setup import db
|
|
||||||
|
|
||||||
TASKS = {}
|
|
||||||
|
|
||||||
async def send_reminder(cooldown:int,author:discord.Member,channel:discord.TextChannel,reminder_message:str):
|
|
||||||
while True:
|
|
||||||
await sleep(cooldown)
|
|
||||||
LOGGER.debug(f'Sending productivity reminder to {author.name} in {channel.name} of {channel.guild.name}.')
|
|
||||||
message = reminder_message.replace('{user}',author.mention)
|
|
||||||
await channel.send(message)
|
|
||||||
|
|
||||||
class ProductivityCog(commands.Cog):
|
|
||||||
|
|
||||||
def __init__(self,bot:discord.Bot) -> None:
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
@commands.slash_command(description='Configurate productivity reminder.')
|
|
||||||
@option(name='channel',description='The channel to send productivity reminders in.',required=True)
|
|
||||||
@option(name='enable',description='Enable or disable productivity reminders.',required=True)
|
|
||||||
@option(name='days',description='Number of days to wait before sending a reminder if the user has not been active in the channel.',required=True,type=int)
|
|
||||||
@option(name='custom_message',description='Custom message to send with the reminder.',required=False,type=str)
|
|
||||||
@option(name='for_user',description='The user to configurate productivity reminders for.',required=False,type=discord.Member)
|
|
||||||
async def productivity_set(self,ctx:discord.ApplicationContext, channel:Union[discord.TextChannel,discord.Thread], enable:bool, days:int, custom_message=None, for_user:discord.Member=None):
|
|
||||||
"""Configurate productivity reminder."""
|
|
||||||
command_name = 'productivity_set'
|
|
||||||
guild_id = ctx.guild.id
|
|
||||||
author = ctx.author
|
|
||||||
productivity_settings = db.select('productivity_settings',f'guild_id = {guild_id}')
|
|
||||||
if productivity_settings:
|
|
||||||
if productivity_settings['is_enabled']:
|
|
||||||
if for_user:
|
|
||||||
if author.guild_permissions.administrator:
|
|
||||||
user_data = db.select('guild_user_productivity',f'guild_id = {guild_id} AND user_id = {for_user.id}')
|
|
||||||
cooldown = days*60*60*24
|
|
||||||
next_reminder = int(datetime.now().timestamp() + cooldown)
|
|
||||||
if user_data:
|
|
||||||
# Update user data
|
|
||||||
if custom_message:
|
|
||||||
db.update('guild_user_productivity',f'guild_id = {guild_id} AND user_id = {for_user.id}',channel_id=channel.id,cooldown=cooldown,next_reminder=next_reminder,reminder_message=custom_message,is_enabled=enable)
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {channel.mention} {enable} {days} {custom_message} for {for_user.name}.')
|
|
||||||
await ctx.send_response(f'Productivity reminders for {for_user.name} have been set to {channel.mention}.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
db.update('guild_user_productivity',f'guild_id = {guild_id} AND user_id = {for_user.id}',channel_id=channel.id,cooldown=cooldown,next_reminder=next_reminder,is_enabled=enable)
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {channel.mention} {enable} {days} for {for_user.name}.')
|
|
||||||
await ctx.send_response(f'Productivity reminders for {for_user.name} have been set to {channel.mention}.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
# Create user data
|
|
||||||
if custom_message:
|
|
||||||
db.insert('guild_user_productivity',guild_id=guild_id,user_id=for_user.id,channel_id=channel.id,cooldown=cooldown,next_reminder=next_reminder,reminder_message=custom_message,is_enabled=enable)
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {channel.mention} {enable} {days} {custom_message} for {for_user.name}.')
|
|
||||||
await ctx.send_response(f'Productivity reminders for {for_user.name} have been set to {channel.mention}.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
db.insert('guild_user_productivity',guild_id=guild_id,user_id=for_user.id,channel_id=channel.id,cooldown=cooldown,next_reminder=next_reminder,is_enabled=enable)
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {channel.mention} {enable} {days} for {for_user.name}.')
|
|
||||||
await ctx.send_response(f'Productivity reminders for {for_user.name} have been set to {channel.mention}.',ephemeral=True)
|
|
||||||
user_data = db.select('guild_user_productivity',f'guild_id = {guild_id} AND user_id = {for_user.id}')
|
|
||||||
if str(for_user.id) in TASKS.keys():
|
|
||||||
TASKS[str(for_user.id)].cancel()
|
|
||||||
TASKS[str(for_user.id)] = create_task(send_reminder(cooldown,for_user,channel,user_data['reminder_message']))
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} tried to use /{command_name} {channel.mention} {enable} {days} {custom_message} for {for_user.name} but is not an administrator.')
|
|
||||||
await ctx.send_response('You must be an administrator to run the command with "for_user".',ephemeral=True)
|
|
||||||
else:
|
|
||||||
user_data = db.select('guild_user_productivity',f'guild_id = {guild_id} AND user_id = {author.id}')
|
|
||||||
cooldown = days*60*60*24
|
|
||||||
next_reminder = int(datetime.now().timestamp() + cooldown)
|
|
||||||
if user_data:
|
|
||||||
# Update user data
|
|
||||||
if custom_message:
|
|
||||||
db.update('guild_user_productivity',f'guild_id = {guild_id} AND user_id = {author.id}',channel_id=channel.id,cooldown=cooldown,next_reminder=next_reminder,reminder_message=custom_message,is_enabled=enable)
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {channel.mention} {enable} {days} {custom_message}.')
|
|
||||||
await ctx.send_response(f'Productivity reminders for {author.name} have been set to {channel.mention}.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
db.update('guild_user_productivity',f'guild_id = {guild_id} AND user_id = {author.id}',channel_id=channel.id,cooldown=cooldown,next_reminder=next_reminder,is_enabled=enable)
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {channel.mention} {enable} {days}.')
|
|
||||||
await ctx.send_response(f'Productivity reminders for {author.name} have been set to {channel.mention}.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
# Create user data
|
|
||||||
if custom_message:
|
|
||||||
db.insert('guild_user_productivity',guild_id=guild_id,user_id=author.id,channel_id=channel.id,cooldown=cooldown,next_reminder=next_reminder,reminder_message=custom_message,is_enabled=enable)
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {channel.mention} {enable} {days} {custom_message}.')
|
|
||||||
await ctx.send_response(f'Productivity reminders for {author.name} have been set to {channel.mention}.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
db.insert('guild_user_productivity',guild_id=guild_id,user_id=author.id,channel_id=channel.id,cooldown=cooldown,next_reminder=next_reminder,is_enabled=enable)
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {channel.mention} {enable} {days}.')
|
|
||||||
await ctx.send_response(f'Productivity reminders for {author.name} have been set to {channel.mention}.',ephemeral=True)
|
|
||||||
user_data = db.select('guild_user_productivity',f'guild_id = {guild_id} AND user_id = {author.id}')
|
|
||||||
if str(author.id) in TASKS.keys():
|
|
||||||
TASKS[str(author.id)].cancel()
|
|
||||||
TASKS[str(author.id)] = create_task(send_reminder(cooldown,author,channel,user_data['reminder_message']))
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} tried to use /{command_name} {channel.mention} {enable} {days} {custom_message} but the productivity feature is not enabled.')
|
|
||||||
await ctx.send_response('The productivity feature is not enabled.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} tried to use /{command_name} {channel.mention} {enable} {days} {custom_message} but no productivity settings were found.')
|
|
||||||
await ctx.send_response('No productivity settings were found.',ephemeral=True)
|
|
||||||
|
|
||||||
@commands.slash_command(description='Enable or disable productivity reminders on the server.')
|
|
||||||
@option(name='enable',description='Enable or disable productivity reminders.',required=True)
|
|
||||||
async def productivity_config(self,ctx:discord.ApplicationContext, enable:bool):
|
|
||||||
"""Enable or disable productivity reminders on the server."""
|
|
||||||
command_name = 'productivity_config'
|
|
||||||
guild_id = ctx.guild.id
|
|
||||||
author = ctx.author
|
|
||||||
productivity_settings = db.select('productivity_settings',f'guild_id = {guild_id}')
|
|
||||||
if productivity_settings:
|
|
||||||
# Update guild productivity settings
|
|
||||||
if author.guild_permissions.administrator:
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {enable}.')
|
|
||||||
db.update('productivity_settings',f'guild_id = {guild_id}',is_enabled=enable)
|
|
||||||
await ctx.send_response(f'Productivity reminders have been {"enabled" if enable else "disabled"}.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} tried to use /{command_name} {enable} but is not an administrator.')
|
|
||||||
await ctx.send_response('You must be an administrator to run this command.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
# Create guild productivity settings
|
|
||||||
if author.guild_permissions.administrator:
|
|
||||||
LOGGER.debug(f'{author.name} used /{command_name} {enable}.')
|
|
||||||
db.insert('productivity_settings',guild_id=guild_id,is_enabled=enable)
|
|
||||||
await ctx.send_response(f'Productivity reminders have been {"enabled" if enable else "disabled"}.',ephemeral=True)
|
|
||||||
else:
|
|
||||||
LOGGER.debug(f'{author.name} tried to use /{command_name} {enable} but is not an administrator.')
|
|
||||||
await ctx.send_response('You must be an administrator to run this command.',ephemeral=True)
|
|
||||||
|
|
||||||
@commands.Cog.listener()
|
|
||||||
async def on_message(self,message:discord.Message):
|
|
||||||
author = message.author
|
|
||||||
if author.id != self.bot.user.id: # Ignore messages from the bot
|
|
||||||
guild_id = message.guild.id
|
|
||||||
productivity_settings = db.select('productivity_settings',f'guild_id = {guild_id}')
|
|
||||||
if productivity_settings:
|
|
||||||
if productivity_settings['is_enabled']:
|
|
||||||
user_productivity_data = db.select('guild_user_productivity',f'user_id = {author.id} AND guild_id = {guild_id}')
|
|
||||||
if user_productivity_data:
|
|
||||||
if user_productivity_data['is_enabled']:
|
|
||||||
next_reminder = int(datetime.now().timestamp() + user_productivity_data['cooldown'])
|
|
||||||
db.update('guild_user_productivity',f'user_id = {author.id} AND guild_id = {guild_id}',next_reminder=next_reminder)
|
|
||||||
if str(author.id) in TASKS.keys():
|
|
||||||
TASKS[str(author.id)].cancel()
|
|
||||||
TASKS[str(author.id)] = create_task(send_reminder(user_productivity_data['cooldown'],author,message.channel,user_productivity_data['reminder_message']))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,304 +0,0 @@
|
|||||||
import os, psycopg2
|
|
||||||
from dotenv import load_dotenv
|
|
||||||
from typing import Optional, Callable, Any, Union
|
|
||||||
from .logger import LOGGER
|
|
||||||
|
|
||||||
load_dotenv()
|
|
||||||
DB_NAME = os.getenv('DB_NAME')
|
|
||||||
DB_USER = os.getenv('DB_USER')
|
|
||||||
DB_PASSWORD = os.getenv('DB_PASSWORD')
|
|
||||||
DB_HOST = os.getenv('DB_HOST')
|
|
||||||
|
|
||||||
def check_conn():
|
|
||||||
"""Tests the database connection."""
|
|
||||||
connection = psycopg2.connect(
|
|
||||||
database=DB_NAME,
|
|
||||||
user=DB_USER,
|
|
||||||
password=DB_PASSWORD,
|
|
||||||
host=DB_HOST,
|
|
||||||
port="5432"
|
|
||||||
)
|
|
||||||
if connection.status:
|
|
||||||
LOGGER.debug('Established connection to database.')
|
|
||||||
LOGGER.debug(f'Connection status: {connection.status}')
|
|
||||||
else:
|
|
||||||
LOGGER.error('Failed to connect to database.')
|
|
||||||
connection.close()
|
|
||||||
LOGGER.debug('Closed connection to database.')
|
|
||||||
|
|
||||||
def insert(table:str,**kwargs):
|
|
||||||
"""
|
|
||||||
Inserts the given data into the given table.
|
|
||||||
|
|
||||||
Global_User
|
|
||||||
user_id: int
|
|
||||||
user_mention: str
|
|
||||||
user_mention: str
|
|
||||||
|
|
||||||
Guild
|
|
||||||
guild_id: int
|
|
||||||
|
|
||||||
Birthday_Settings
|
|
||||||
guild_id: int
|
|
||||||
is_enabled: bool
|
|
||||||
channel_id: int
|
|
||||||
|
|
||||||
Productivity_Settings
|
|
||||||
guild_id: int
|
|
||||||
is_enabled: bool
|
|
||||||
|
|
||||||
Guild_User_Birthday
|
|
||||||
user_id: int
|
|
||||||
guild_id: int
|
|
||||||
birthday: int
|
|
||||||
birthday_message: str | None
|
|
||||||
is_enabled: bool
|
|
||||||
|
|
||||||
Guild_User_Productivity
|
|
||||||
user_id: int
|
|
||||||
guild_id: int
|
|
||||||
is_enabled: bool
|
|
||||||
channel_id: int
|
|
||||||
cooldown: int
|
|
||||||
next_reminder: int
|
|
||||||
reminder_message: str | None
|
|
||||||
"""
|
|
||||||
connection = psycopg2.connect(
|
|
||||||
database=DB_NAME,
|
|
||||||
user=DB_USER,
|
|
||||||
password=DB_PASSWORD,
|
|
||||||
host=DB_HOST,
|
|
||||||
port="5432",
|
|
||||||
)
|
|
||||||
cursor = connection.cursor()
|
|
||||||
|
|
||||||
query = f"INSERT INTO {table} ("
|
|
||||||
params = []
|
|
||||||
for key,value in kwargs.items():
|
|
||||||
query += f"{key},"
|
|
||||||
params.append(value)
|
|
||||||
query = query.rstrip(",") # Remove trailing comma
|
|
||||||
query += ") VALUES ("
|
|
||||||
for _ in range(len(params)):
|
|
||||||
query += "%s,"
|
|
||||||
query = query.rstrip(",") # Remove trailing comma
|
|
||||||
query += ")"
|
|
||||||
|
|
||||||
query = cursor.mogrify(query, params)
|
|
||||||
cursor.execute(query)
|
|
||||||
connection.commit()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
LOGGER.debug(f'Inserted data into {table}.')
|
|
||||||
|
|
||||||
def update(table:str,where:str,**kwargs):
|
|
||||||
"""
|
|
||||||
Updates the given data in the given table.
|
|
||||||
|
|
||||||
Global_User
|
|
||||||
user_id: int
|
|
||||||
user_mention: str
|
|
||||||
user_mention: str
|
|
||||||
|
|
||||||
Guild
|
|
||||||
guild_id: int
|
|
||||||
|
|
||||||
Birthday_Settings
|
|
||||||
guild_id: int
|
|
||||||
is_enabled: bool
|
|
||||||
channel_id: int
|
|
||||||
|
|
||||||
Productivity_Settings
|
|
||||||
guild_id: int
|
|
||||||
is_enabled: bool
|
|
||||||
|
|
||||||
Guild_User_Birthday
|
|
||||||
user_id: int
|
|
||||||
guild_id: int
|
|
||||||
birthday: int
|
|
||||||
birthday_message: str | None
|
|
||||||
is_enabled: bool
|
|
||||||
|
|
||||||
Guild_User_Productivity
|
|
||||||
user_id: int
|
|
||||||
guild_id: int
|
|
||||||
is_enabled: bool
|
|
||||||
channel_id: int
|
|
||||||
cooldown: int
|
|
||||||
next_reminder: int
|
|
||||||
reminder_message: str | None
|
|
||||||
"""
|
|
||||||
connection = psycopg2.connect(
|
|
||||||
database=DB_NAME,
|
|
||||||
user=DB_USER,
|
|
||||||
password=DB_PASSWORD,
|
|
||||||
host=DB_HOST,
|
|
||||||
port="5432",
|
|
||||||
)
|
|
||||||
cursor = connection.cursor()
|
|
||||||
|
|
||||||
query = f"UPDATE {table} SET "
|
|
||||||
params = []
|
|
||||||
for key,value in kwargs.items():
|
|
||||||
query += f"{key} = %s,"
|
|
||||||
params.append(value)
|
|
||||||
query = query.rstrip(",") # Remove trailing comma
|
|
||||||
query += f" WHERE {where}"
|
|
||||||
|
|
||||||
query = cursor.mogrify(query, params)
|
|
||||||
cursor.execute(query)
|
|
||||||
connection.commit()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
LOGGER.debug(f'Updated data in {table}.')
|
|
||||||
|
|
||||||
def delete(table:str,where:str):
|
|
||||||
"""
|
|
||||||
Deletes the given data from the given table.
|
|
||||||
|
|
||||||
Global_User
|
|
||||||
user_id: int
|
|
||||||
user_mention: str
|
|
||||||
user_mention: str
|
|
||||||
|
|
||||||
Guild
|
|
||||||
guild_id: int
|
|
||||||
|
|
||||||
Birthday_Settings
|
|
||||||
guild_id: int
|
|
||||||
is_enabled: bool
|
|
||||||
channel_id: int
|
|
||||||
|
|
||||||
Productivity_Settings
|
|
||||||
guild_id: int
|
|
||||||
is_enabled: bool
|
|
||||||
|
|
||||||
Guild_User_Birthday
|
|
||||||
user_id: int
|
|
||||||
guild_id: int
|
|
||||||
birthday: int
|
|
||||||
birthday_message: str | None
|
|
||||||
is_enabled: bool
|
|
||||||
|
|
||||||
Guild_User_Productivity
|
|
||||||
user_id: int
|
|
||||||
guild_id: int
|
|
||||||
is_enabled: bool
|
|
||||||
channel_id: int
|
|
||||||
cooldown: int
|
|
||||||
next_reminder: int
|
|
||||||
reminder_message: str | None
|
|
||||||
"""
|
|
||||||
connection = psycopg2.connect(
|
|
||||||
database=DB_NAME,
|
|
||||||
user=DB_USER,
|
|
||||||
password=DB_PASSWORD,
|
|
||||||
host=DB_HOST,
|
|
||||||
port="5432",
|
|
||||||
)
|
|
||||||
cursor = connection.cursor()
|
|
||||||
|
|
||||||
query = f"DELETE FROM {table} WHERE {where}"
|
|
||||||
cursor.execute(query)
|
|
||||||
connection.commit()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
LOGGER.debug(f'Deleted data from {table}.')
|
|
||||||
|
|
||||||
def select(table:str,where:str,*columns:str) -> dict[str,Any] | None:
|
|
||||||
"""
|
|
||||||
Selects the given data from the given table, and returns it as a dictionary.
|
|
||||||
|
|
||||||
Global_User
|
|
||||||
user_id: int
|
|
||||||
user_mention: str
|
|
||||||
user_mention: str
|
|
||||||
|
|
||||||
Guild
|
|
||||||
guild_id: int
|
|
||||||
|
|
||||||
Birthday_Settings
|
|
||||||
guild_id: int
|
|
||||||
is_enabled: bool
|
|
||||||
channel_id: int
|
|
||||||
|
|
||||||
Productivity_Settings
|
|
||||||
guild_id: int
|
|
||||||
is_enabled: bool
|
|
||||||
|
|
||||||
Guild_User_Birthday
|
|
||||||
user_id: int
|
|
||||||
guild_id: int
|
|
||||||
birthday: int
|
|
||||||
birthday_message: str | None
|
|
||||||
is_enabled: bool
|
|
||||||
|
|
||||||
Guild_User_Productivity
|
|
||||||
user_id: int
|
|
||||||
guild_id: int
|
|
||||||
is_enabled: bool
|
|
||||||
channel_id: int
|
|
||||||
cooldown: int
|
|
||||||
next_reminder: int
|
|
||||||
reminder_message: str | None
|
|
||||||
"""
|
|
||||||
connection = psycopg2.connect(
|
|
||||||
database=DB_NAME,
|
|
||||||
user=DB_USER,
|
|
||||||
password=DB_PASSWORD,
|
|
||||||
host=DB_HOST,
|
|
||||||
port="5432"
|
|
||||||
)
|
|
||||||
connection.readonly = True
|
|
||||||
cursor = connection.cursor()
|
|
||||||
|
|
||||||
query = f"SELECT "
|
|
||||||
if columns:
|
|
||||||
for column in columns:
|
|
||||||
query += f"{column},"
|
|
||||||
query = query.rstrip(",")
|
|
||||||
else:
|
|
||||||
query += "*"
|
|
||||||
query += f" FROM {table} WHERE {where}"
|
|
||||||
cursor.execute(query)
|
|
||||||
record = cursor.fetchone()
|
|
||||||
result = None
|
|
||||||
if record is None:
|
|
||||||
LOGGER.debug(f'No data found in {table} for {where}.')
|
|
||||||
else:
|
|
||||||
result = {}
|
|
||||||
if len(columns) > 0:
|
|
||||||
for i in range(len(columns)):
|
|
||||||
result[columns[i]] = record[i]
|
|
||||||
else:
|
|
||||||
if table.lower() == 'global_user':
|
|
||||||
result['user_id'] = record[0]
|
|
||||||
result['user_name'] = record[1]
|
|
||||||
result['user_mention'] = record[2]
|
|
||||||
elif table.lower() == 'guild':
|
|
||||||
result['guild_id'] = record[0]
|
|
||||||
elif table.lower() == 'birthday_settings':
|
|
||||||
result['guild_id'] = record[0]
|
|
||||||
result['is_enabled'] = record[1]
|
|
||||||
result['channel_id'] = record[2]
|
|
||||||
elif table.lower() == 'productivity_settings':
|
|
||||||
result['guild_id'] = record[0]
|
|
||||||
result['is_enabled'] = record[1]
|
|
||||||
elif table.lower() == 'guild_user_birthday':
|
|
||||||
result['user_id'] = record[0]
|
|
||||||
result['guild_id'] = record[1]
|
|
||||||
result['birthday'] = record[2]
|
|
||||||
result['is_enabled'] = record[3]
|
|
||||||
elif table.lower() == 'guild_user_productivity':
|
|
||||||
result['user_id'] = record[0]
|
|
||||||
result['guild_id'] = record[1]
|
|
||||||
result['is_enabled'] = record[2]
|
|
||||||
result['channel_id'] = record[3]
|
|
||||||
result['cooldown'] = record[4]
|
|
||||||
result['next_reminder'] = record[5]
|
|
||||||
result['reminder_message'] = record[6]
|
|
||||||
else:
|
|
||||||
LOGGER.error(f'Unknown table {table}.')
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return result
|
|
||||||
@@ -1,3 +1,31 @@
|
|||||||
python-dotenv
|
aiohappyeyeballs==2.6.2
|
||||||
py-cord
|
aiohttp==3.14.1
|
||||||
psycopg2-binary
|
aiosignal==1.4.0
|
||||||
|
asarPy==1.0.1
|
||||||
|
attrs==26.1.0
|
||||||
|
beautifulsoup4==4.15.0
|
||||||
|
certifi==2026.5.20
|
||||||
|
charset-normalizer==3.4.7
|
||||||
|
frozenlist==1.8.0
|
||||||
|
h11==0.16.0
|
||||||
|
idna==3.18
|
||||||
|
lxml==6.1.1
|
||||||
|
multidict==6.7.1
|
||||||
|
outcome==1.3.0.post0
|
||||||
|
propcache==0.5.2
|
||||||
|
psycopg2-binary==2.9.12
|
||||||
|
py-cord==2.8.0
|
||||||
|
PySocks==1.7.1
|
||||||
|
python-dotenv==1.2.2
|
||||||
|
requests==2.34.2
|
||||||
|
selenium==4.45.0
|
||||||
|
sniffio==1.3.1
|
||||||
|
sortedcontainers==2.4.0
|
||||||
|
soupsieve==2.8.4
|
||||||
|
trio==0.33.0
|
||||||
|
trio-websocket==0.12.2
|
||||||
|
typing_extensions==4.15.0
|
||||||
|
urllib3==2.7.0
|
||||||
|
websocket-client==1.9.0
|
||||||
|
wsproto==1.3.2
|
||||||
|
yarl==1.24.2
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import discord
|
import discord
|
||||||
from ..cogs.birthday import BirthdayCog
|
from discord.ext import bridge
|
||||||
from ..cogs.productivity import ProductivityCog
|
# from cogs.birthday import BirthdayCog
|
||||||
from .logger import LOGGER
|
# from cogs.productivity import ProductivityCog
|
||||||
|
from cogs.cs import CSCog
|
||||||
|
from cogs.insult import InsultsCog
|
||||||
|
from setup.logger import LOGGER
|
||||||
|
|
||||||
bot_intents = discord.Intents.default()
|
bot_intents = discord.Intents.default()
|
||||||
bot_intents.message_content = True
|
bot_intents.message_content = True
|
||||||
@@ -10,9 +13,9 @@ bot_intents.presences = True
|
|||||||
bot_intents.guilds = True
|
bot_intents.guilds = True
|
||||||
bot_intents.reactions = True
|
bot_intents.reactions = True
|
||||||
|
|
||||||
bot = discord.Bot(command_prefix='$', intents=bot_intents)
|
bot = bridge.Bot(command_prefix='$', intents=bot_intents)
|
||||||
|
|
||||||
COGS = [BirthdayCog, ProductivityCog]
|
COGS = [CSCog, InsultsCog]
|
||||||
|
|
||||||
for cog in COGS:
|
for cog in COGS:
|
||||||
bot.add_cog(cog(bot))
|
bot.add_cog(cog(bot))
|
||||||
Reference in New Issue
Block a user