This commit is contained in:
Romain J 2020-04-01 16:38:34 +02:00
commit 7eac932a4e
20 changed files with 264 additions and 207 deletions

91
bot.py
View file

@ -1,5 +1,6 @@
import contextlib import contextlib
import datetime import datetime
import json
import logging import logging
import sys import sys
from collections import deque, Counter from collections import deque, Counter
@ -8,12 +9,15 @@ from typing import List
import aiohttp import aiohttp
import discord import discord
import git import git
import sqlalchemy
from discord.ext import commands from discord.ext import commands
from utils import Config from utils.functions import Config
from utils import Database from utils.functions import Texts
from utils import Texts from utils.functions import Version
from utils import Version from utils.functions import ContextPlus
from utils.models import metadata, database
description = """ description = """
Je suis TuxBot, le bot qui vit de l'OpenSource ! ;) Je suis TuxBot, le bot qui vit de l'OpenSource ! ;)
@ -26,6 +30,7 @@ log = logging.getLogger(__name__)
l_extensions: List[str] = [ l_extensions: List[str] = [
'cogs.Admin', 'cogs.Admin',
'cogs.API',
'cogs.Help', 'cogs.Help',
'cogs.Logs', 'cogs.Logs',
# 'cogs.Monitoring', # 'cogs.Monitoring',
@ -37,6 +42,7 @@ l_extensions: List[str] = [
async def _prefix_callable(bot, message: discord.message) -> list: async def _prefix_callable(bot, message: discord.message) -> list:
<<<<<<< HEAD
extras = [bot.cluster.get('Name') + '.'] extras = [bot.cluster.get('Name') + '.']
if message.guild is not None: if message.guild is not None:
if str(message.guild.id) in bot.prefixes: if str(message.guild.id) in bot.prefixes:
@ -45,13 +51,25 @@ async def _prefix_callable(bot, message: discord.message) -> list:
bot.config.get("misc", "Separator") bot.config.get("misc", "Separator")
) )
) )
=======
try:
with open(f'./configs/guilds/{message.guild.id}.json', 'r') as f:
data = json.load(f)
custom_prefix = data['prefixes']
except FileNotFoundError:
custom_prefix = ['']
extras = [bot.cluster.get('Name') + '.']
extras.extend(custom_prefix)
>>>>>>> cce7bb409303e9ad27ef4e5617d0bc9068810f13
return commands.when_mentioned_or(*extras)(bot, message) return commands.when_mentioned_or(*extras)(bot, message)
class TuxBot(commands.AutoShardedBot): class TuxBot(commands.AutoShardedBot):
def __init__(self, database): def __init__(self, ):
super().__init__(command_prefix=_prefix_callable, pm_help=None, super().__init__(command_prefix=_prefix_callable, pm_help=None,
help_command=None, description=description, help_command=None, description=description,
help_attrs=dict(hidden=True), help_attrs=dict(hidden=True),
@ -62,20 +80,22 @@ class TuxBot(commands.AutoShardedBot):
self.socket_stats = Counter() self.socket_stats = Counter()
self.command_stats = Counter() self.command_stats = Counter()
self.uptime: datetime = datetime.datetime.utcnow()
self._prev_events = deque(maxlen=10)
self.session = aiohttp.ClientSession(loop=self.loop)
self.database = database
self.config = Config('./configs/config.cfg') self.config = Config('./configs/config.cfg')
self.prefixes = Config('./configs/prefixes.cfg')
self.blacklist = Config('./configs/blacklist.cfg') self.blacklist = Config('./configs/blacklist.cfg')
self.fallbacks = Config('./configs/fallbacks.cfg') self.fallbacks = Config('./configs/fallbacks.cfg')
self.cluster = self.fallbacks.find('True', key='This', first=True) self.cluster = self.fallbacks.find('True', key='This', first=True)
self.uptime: datetime = datetime.datetime.utcnow()
self._prev_events = deque(maxlen=10)
self.session = aiohttp.ClientSession(loop=self.loop)
self.database, self.metadata = database, metadata
self.engine = sqlalchemy.create_engine(str(self.database.url))
self.metadata.create_all(self.engine)
self.version = Version(*version, pre_release='rc2', build=build) self.version = Version(*version, pre_release='rc2', build=build)
self.owner: discord.User = discord.User self.owners_id = [int(owner_id) for owner_id in self.config.get('permissions', 'Owners').split(', ')]
self.owners: List[discord.User] = [] self.owner_id = int(self.owners_id[0])
for extension in l_extensions: for extension in l_extensions:
try: try:
@ -91,9 +111,19 @@ class TuxBot(commands.AutoShardedBot):
log.error(Texts().get("Failed to load extension : ") log.error(Texts().get("Failed to load extension : ")
+ extension, exc_info=e) + extension, exc_info=e)
@property
def owner(self):
return self.get_user(self.owner_id)
@property
def owners(self):
return [self.get_user(owner_id) for owner_id in self.owners_id]
async def is_owner(self, user: discord.User) -> bool: async def is_owner(self, user: discord.User) -> bool:
return str(user.id) in self.config.get("permissions", "Owners").split( return user in self.owners
', ')
async def get_context(self, message, *, cls=None):
return await super().get_context(message, cls=cls or ContextPlus)
async def on_socket_response(self, msg): async def on_socket_response(self, msg):
self._prev_events.append(msg) self._prev_events.append(msg)
@ -110,9 +140,11 @@ class TuxBot(commands.AutoShardedBot):
"Sorry. This command is disabled and cannot be used." "Sorry. This command is disabled and cannot be used."
) )
) )
elif isinstance(error, commands.CommandOnCooldown):
await ctx.send(str(error))
async def process_commands(self, message: discord.message): async def process_commands(self, message: discord.message):
ctx = await self.get_context(message) ctx: commands.Context = await self.get_context(message)
if ctx.command is None: if ctx.command is None:
return return
@ -151,13 +183,6 @@ class TuxBot(commands.AutoShardedBot):
print('-' * 60) print('-' * 60)
await self.change_presence(**presence) await self.change_presence(**presence)
self.owner = await self.fetch_user(
int(self.config.get('permissions', 'Owners').split(', ')[0])
)
for owner in self.config.get('permissions', 'Owners').split(', '):
self.owners.append(
await self.fetch_user(int(owner))
)
@staticmethod @staticmethod
async def on_resumed(): async def on_resumed():
@ -189,13 +214,13 @@ class TuxBot(commands.AutoShardedBot):
@contextlib.contextmanager @contextlib.contextmanager
def setup_logging(): def setup_logging():
logging.getLogger('discord').setLevel(logging.INFO)
logging.getLogger('discord.http').setLevel(logging.WARNING)
log = logging.getLogger()
log.setLevel(logging.INFO)
try: try:
logging.getLogger('discord').setLevel(logging.INFO)
logging.getLogger('discord.http').setLevel(logging.WARNING)
log = logging.getLogger()
log.setLevel(logging.INFO)
handler = logging.FileHandler(filename='logs/tuxbot.log', handler = logging.FileHandler(filename='logs/tuxbot.log',
encoding='utf-8', mode='w') encoding='utf-8', mode='w')
fmt = logging.Formatter('[{levelname:<7}] [{asctime}]' fmt = logging.Formatter('[{levelname:<7}] [{asctime}]'
@ -214,14 +239,12 @@ def setup_logging():
if __name__ == "__main__": if __name__ == "__main__":
log = logging.getLogger()
print(Texts().get('Starting...')) print(Texts().get('Starting...'))
bot = TuxBot(Database(Config("./configs/config.cfg"))) app = TuxBot()
try: try:
with setup_logging(): with setup_logging():
bot.run() app.run()
except KeyboardInterrupt: except KeyboardInterrupt:
bot.close() app.close()

56
cogs/API.py Normal file
View file

@ -0,0 +1,56 @@
import logging
import discord
from aiohttp import web
from discord.ext import commands
from bot import TuxBot
log = logging.getLogger(__name__)
class API(commands.Cog):
def __init__(self, bot: TuxBot):
self.bot = bot
self.site = web.TCPSite
app = web.Application()
app.add_routes([web.get('/users/{user_id}', self.users)])
self.runner = web.AppRunner(app)
self.bot.loop.create_task(self.start_HTTPMonitoring_server())
async def start_HTTPMonitoring_server(self):
host = self.bot.config.get('API', 'Host')
port = self.bot.config.get('API', 'Port')
print(f"Starting API server on {host}:{port}")
await self.runner.setup()
self.site = web.TCPSite(self.runner, host, port)
await self.site.start()
async def users(self, request):
try:
user = await self.bot.fetch_user(request.match_info['user_id'])
except discord.NotFound:
return web.Response(status=404)
json = {
'id': user.id,
'username': user.name,
'discriminator': user.discriminator,
'avatar': user.avatar,
'default_avatar': user.default_avatar.value,
'bot': user.bot,
'system': user.system,
}
return web.json_response(
json
)
def setup(bot: TuxBot):
bot.add_cog(API(bot))

View file

@ -9,8 +9,8 @@ from discord.ext import commands
from bot import TuxBot from bot import TuxBot
from utils import Texts from utils import Texts
from utils import WarnModel, LangModel from utils.models import WarnModel
from utils import commandExtra, groupExtra from utils import command_extra, group_extra
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -65,7 +65,7 @@ class Admin(commands.Cog):
########################################################################### ###########################################################################
@groupExtra(name='say', invoke_without_command=True, category='text') @group_extra(name='say', invoke_without_command=True, category='text')
async def _say(self, ctx: commands.Context, *, content: str): async def _say(self, ctx: commands.Context, *, content: str):
if ctx.invoked_subcommand is None: if ctx.invoked_subcommand is None:
try: try:
@ -105,7 +105,7 @@ class Admin(commands.Cog):
########################################################################### ###########################################################################
@commandExtra(name='ban', category='administration') @command_extra(name='ban', category='administration')
async def _ban(self, ctx: commands.Context, user: discord.Member, *, async def _ban(self, ctx: commands.Context, user: discord.Member, *,
reason=""): reason=""):
try: try:
@ -132,7 +132,7 @@ class Admin(commands.Cog):
########################################################################### ###########################################################################
@commandExtra(name='kick', category='administration') @command_extra(name='kick', category='administration')
async def _kick(self, ctx: commands.Context, user: discord.Member, *, async def _kick(self, ctx: commands.Context, user: discord.Member, *,
reason=""): reason=""):
try: try:
@ -159,7 +159,7 @@ class Admin(commands.Cog):
########################################################################### ###########################################################################
@commandExtra(name='clear', category='text') @command_extra(name='clear', category='text')
async def _clear(self, ctx: commands.Context, count: int): async def _clear(self, ctx: commands.Context, count: int):
try: try:
await ctx.message.delete() await ctx.message.delete()
@ -169,7 +169,7 @@ class Admin(commands.Cog):
########################################################################### ###########################################################################
@groupExtra(name='react', category='text') @group_extra(name='react', category='text')
async def _react(self, ctx: commands.Context): async def _react(self, ctx: commands.Context):
if ctx.invoked_subcommand is None: if ctx.invoked_subcommand is None:
await ctx.send_help('react') await ctx.send_help('react')
@ -203,7 +203,7 @@ class Admin(commands.Cog):
########################################################################### ###########################################################################
@groupExtra(name='delete', invoke_without_command=True, category='text') @group_extra(name='delete', invoke_without_command=True, category='text')
async def _delete(self, ctx: commands.Context, message_id: int): async def _delete(self, ctx: commands.Context, message_id: int):
try: try:
await ctx.message.delete() await ctx.message.delete()
@ -229,12 +229,14 @@ class Admin(commands.Cog):
try: try:
message: discord.Message = await channel.fetch_message( message: discord.Message = await channel.fetch_message(
message_id) message_id
)
await message.delete() await message.delete()
except (discord.errors.NotFound, discord.errors.Forbidden): except (discord.errors.NotFound, discord.errors.Forbidden):
await ctx.send( await ctx.send(
Texts('utils', ctx).get("Unable to find the message"), Texts('utils', ctx).get("Unable to find the message"),
delete_after=5) delete_after=5
)
########################################################################### ###########################################################################
@ -242,24 +244,18 @@ class Admin(commands.Cog):
member: discord.Member = False): member: discord.Member = False):
await ctx.trigger_typing() await ctx.trigger_typing()
week_ago = datetime.datetime.now() - datetime.timedelta(weeks=6)
if member: if member:
warns = self.bot.database.session \ warns = WarnModel.objects.filter(
.query(WarnModel) \ server_id=str(ctx.guild.id),
.filter(WarnModel.user_id == member.id, user_id=member.id
WarnModel.created_at > week_ago, )
WarnModel.server_id == ctx.guild.id) \
.order_by(WarnModel.created_at.desc())
else: else:
warns = self.bot.database.session \ warns = WarnModel.objects.filter(
.query(WarnModel) \ server_id=str(ctx.guild.id)
.filter(WarnModel.created_at > week_ago, )
WarnModel.server_id == ctx.guild.id) \
.order_by(WarnModel.created_at.desc())
warns_list = '' warns_list = ''
for warn in warns: for warn in await warns.all():
row_id = warn.id row_id = warn.id
user_id = warn.user_id user_id = warn.user_id
user = await self.bot.fetch_user(user_id) user = await self.bot.fetch_user(user_id)
@ -283,7 +279,7 @@ class Admin(commands.Cog):
self.bot.database.session.add(warn) self.bot.database.session.add(warn)
self.bot.database.session.commit() self.bot.database.session.commit()
@groupExtra(name='warn', aliases=['warns'], category='administration') @group_extra(name='warn', aliases=['warns'], category='administration')
async def _warn(self, ctx: commands.Context): async def _warn(self, ctx: commands.Context):
await ctx.trigger_typing() await ctx.trigger_typing()
if ctx.invoked_subcommand is None: if ctx.invoked_subcommand is None:
@ -411,7 +407,7 @@ class Admin(commands.Cog):
########################################################################### ###########################################################################
@commandExtra(name='language', aliases=['lang', 'langue', 'langage'], category='server') @command_extra(name='language', aliases=['lang', 'langue', 'langage'], category='server')
async def _language(self, ctx: commands.Context, locale: str): async def _language(self, ctx: commands.Context, locale: str):
available = self.bot.database.session \ available = self.bot.database.session \
.query(LangModel.value) \ .query(LangModel.value) \
@ -442,7 +438,7 @@ class Admin(commands.Cog):
########################################################################### ###########################################################################
@groupExtra(name='prefix', aliases=['prefixes'], category='server') @group_extra(name='prefix', aliases=['prefixes'], category='server')
async def _prefix(self, ctx: commands.Context): async def _prefix(self, ctx: commands.Context):
if ctx.invoked_subcommand is None: if ctx.invoked_subcommand is None:
await ctx.send_help('prefix') await ctx.send_help('prefix')

View file

@ -20,7 +20,7 @@ from discord.ext import commands, tasks
from bot import TuxBot from bot import TuxBot
from utils import Texts from utils import Texts
from utils import commandExtra from utils import command_extra
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -243,7 +243,7 @@ class Logs(commands.Cog):
msg = f'{emoji} `[{dt:%Y-%m-%d %H:%M:%S}] {record.message}`' msg = f'{emoji} `[{dt:%Y-%m-%d %H:%M:%S}] {record.message}`'
await self.webhook.send(msg) await self.webhook.send(msg)
@commandExtra(name='commandstats', hidden=True, category='misc') @command_extra(name='commandstats', hidden=True, category='misc')
@commands.is_owner() @commands.is_owner()
async def _commandstats(self, ctx, limit=20): async def _commandstats(self, ctx, limit=20):
counter = self.bot.command_stats counter = self.bot.command_stats
@ -258,7 +258,7 @@ class Logs(commands.Cog):
await ctx.send(f'```\n{output}\n```') await ctx.send(f'```\n{output}\n```')
@commandExtra(name='socketstats', hidden=True, category='misc') @command_extra(name='socketstats', hidden=True, category='misc')
@commands.is_owner() @commands.is_owner()
async def _socketstats(self, ctx): async def _socketstats(self, ctx):
delta = datetime.datetime.utcnow() - self.bot.uptime delta = datetime.datetime.utcnow() - self.bot.uptime
@ -268,7 +268,7 @@ class Logs(commands.Cog):
await ctx.send( await ctx.send(
f'{total} socket events observed ({cpm:.2f}/minute):\n{self.bot.socket_stats}') f'{total} socket events observed ({cpm:.2f}/minute):\n{self.bot.socket_stats}')
@commandExtra(name='uptime', category='misc') @command_extra(name='uptime', category='misc')
async def _uptime(self, ctx): async def _uptime(self, ctx):
uptime = humanize.naturaltime( uptime = humanize.naturaltime(
datetime.datetime.utcnow() - self.bot.uptime) datetime.datetime.utcnow() - self.bot.uptime)

View file

@ -10,7 +10,7 @@ from bot import TuxBot
from utils import PollModel, ResponsesModel from utils import PollModel, ResponsesModel
from utils import Texts from utils import Texts
from utils.functions import emotes as utils_emotes from utils.functions import emotes as utils_emotes
from utils import groupExtra from utils import group_extra
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -205,7 +205,7 @@ class Poll(commands.Cog):
poll.content = json.dumps(content) poll.content = json.dumps(content)
self.bot.database.session.commit() self.bot.database.session.commit()
@groupExtra(name='poll', aliases=['sondage'], category='poll') @group_extra(name='poll', aliases=['sondage'], category='poll')
async def _poll(self, ctx: commands.Context): async def _poll(self, ctx: commands.Context):
if ctx.invoked_subcommand is None: if ctx.invoked_subcommand is None:
await ctx.send_help('poll') await ctx.send_help('poll')

View file

@ -23,7 +23,7 @@ from tcp_latency import measure_latency
from bot import TuxBot from bot import TuxBot
from utils import Texts from utils import Texts
from utils import commandExtra, groupExtra from utils import command_extra, group_extra
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -86,7 +86,7 @@ class Useful(commands.Cog):
########################################################################### ###########################################################################
@commandExtra(name='iplocalise', category='network') @command_extra(name='iplocalise', category='network')
async def _iplocalise(self, ctx: commands.Context, addr, ip_type=''): async def _iplocalise(self, ctx: commands.Context, addr, ip_type=''):
addr = re.sub(r'http(s?)://', '', addr) addr = re.sub(r'http(s?)://', '', addr)
addr = addr[:-1] if addr.endswith('/') else addr addr = addr[:-1] if addr.endswith('/') else addr
@ -150,14 +150,7 @@ class Useful(commands.Cog):
########################################################################### ###########################################################################
@commands.Cog.listener() @command_extra(name='getheaders', category='network')
async def on_command_error(self, ctx, error):
if isinstance(error, commands.CommandOnCooldown):
await ctx.send(error)
###########################################################################
@commandExtra(name='getheaders', category='network')
async def _getheaders(self, ctx: commands.Context, addr: str): async def _getheaders(self, ctx: commands.Context, addr: str):
if (addr.startswith('http') or addr.startswith('ftp')) is not True: if (addr.startswith('http') or addr.startswith('ftp')) is not True:
addr = f"http://{addr}" addr = f"http://{addr}"
@ -187,7 +180,7 @@ class Useful(commands.Cog):
########################################################################### ###########################################################################
@commandExtra(name='git', aliases=['sources', 'source', 'github'], category='misc') @command_extra(name='git', aliases=['sources', 'source', 'github'], category='misc')
async def _git(self, ctx): async def _git(self, ctx):
e = discord.Embed( e = discord.Embed(
title=Texts('useful', ctx).get('git repo'), title=Texts('useful', ctx).get('git repo'),
@ -202,7 +195,7 @@ class Useful(commands.Cog):
########################################################################### ###########################################################################
@commandExtra(name='quote', category='misc') @command_extra(name='quote', category='misc')
async def _quote(self, ctx, message_id: discord.Message): async def _quote(self, ctx, message_id: discord.Message):
e = discord.Embed( e = discord.Embed(
colour=message_id.author.colour, colour=message_id.author.colour,
@ -224,7 +217,7 @@ class Useful(commands.Cog):
########################################################################### ###########################################################################
@commandExtra(name='ping', category='network') @command_extra(name='ping', category='network')
async def _ping(self, ctx: commands.Context): async def _ping(self, ctx: commands.Context):
start = time.perf_counter() start = time.perf_counter()
await ctx.trigger_typing() await ctx.trigger_typing()
@ -242,7 +235,7 @@ class Useful(commands.Cog):
########################################################################### ###########################################################################
@commandExtra(name='info', aliases=['about'], category='misc') @command_extra(name='info', aliases=['about'], category='misc')
async def _info(self, ctx: commands.Context): async def _info(self, ctx: commands.Context):
proc = psutil.Process() proc = psutil.Process()
total, python = self.fetch_info() total, python = self.fetch_info()
@ -325,7 +318,7 @@ class Useful(commands.Cog):
########################################################################### ###########################################################################
@commandExtra(name='credits', aliases=['contributors', 'authors'], category='misc') @command_extra(name='credits', aliases=['contributors', 'authors'], category='misc')
async def _credits(self, ctx: commands.Context): async def _credits(self, ctx: commands.Context):
e = discord.Embed( e = discord.Embed(
title=Texts('useful', ctx).get('Contributors'), title=Texts('useful', ctx).get('Contributors'),
@ -349,7 +342,7 @@ class Useful(commands.Cog):
await ctx.send(embed=e) await ctx.send(embed=e)
########################################################################### ###########################################################################
@groupExtra(name='cb', aliases=['cc'], category='misc') @group_extra(name='cb', aliases=['cc'], category='misc')
@commands.cooldown(1, 5, type=commands.BucketType.user) @commands.cooldown(1, 5, type=commands.BucketType.user)
async def _cb(self, ctx: commands.Context): async def _cb(self, ctx: commands.Context):
if ctx.invoked_subcommand is None: if ctx.invoked_subcommand is None:

View file

@ -5,7 +5,7 @@ from discord.ext import commands
from bot import TuxBot from bot import TuxBot
from utils import AliasesModel from utils import AliasesModel
from utils import Texts from utils import Texts
from utils import groupExtra from utils import group_extra
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -19,7 +19,7 @@ class User(commands.Cog):
########################################################################### ###########################################################################
@groupExtra(name='alias', aliases=['aliases'], category='alias') @group_extra(name='alias', aliases=['aliases'], category='alias')
async def _alias(self, ctx: commands.Context): async def _alias(self, ctx: commands.Context):
if ctx.invoked_subcommand is None: if ctx.invoked_subcommand is None:
await ctx.send_help('alias') await ctx.send_help('alias')

View file

@ -18,3 +18,7 @@ Token =
[misc] [misc]
Separator = Separator =
[API]
Host =
Port =

View file

@ -1,7 +1,5 @@
from utils import Config import sqlalchemy
from utils.models import Base from utils.models import database, metadata
from utils import Database
from utils.models.lang import LangModel
import argparse import argparse
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
@ -9,20 +7,13 @@ parser.add_argument("-m", "--migrate", action="store_true")
parser.add_argument("-s", "--seed", action="store_true") parser.add_argument("-s", "--seed", action="store_true")
args = parser.parse_args() args = parser.parse_args()
database = Database(Config("./configs/config.cfg"))
if args.migrate: if args.migrate:
print("Migrate...") print("Migrate...")
Base.metadata.create_all(database.engine) engine = sqlalchemy.create_engine(str(database.url))
metadata.create_all(engine)
print("Done!") print("Done!")
if args.seed: if args.seed:
print('Seeding...') print('Seeding...')
default = LangModel(key="default", value="fr") # todo: add seeding
available = LangModel(key="available", value="fr,en")
database.session.add(default)
database.session.add(available)
database.session.commit()
print("Done!") print("Done!")

View file

@ -3,7 +3,8 @@ humanize
git+https://github.com/Rapptz/discord.py@master git+https://github.com/Rapptz/discord.py@master
jishaku jishaku
gitpython gitpython
sqlalchemy orm
asyncpg
psycopg2 psycopg2
configparser configparser
psutil psutil

View file

@ -1,5 +1,3 @@
from .models import *
from utils.functions.config import * from utils.functions.config import *
from utils.functions.lang import * from utils.functions.lang import *
from utils.functions.version import * from utils.functions.version import *

View file

@ -0,0 +1,6 @@
from .config import Config
from .database import Database
from .extra import *
from .lang import Texts
from .paginator import *
from .version import Version

View file

@ -1,7 +1,7 @@
from .config import Config from .config import Config
from sqlalchemy import create_engine import sqlalchemy
from sqlalchemy.orm import sessionmaker, session import databases
class Database: class Database:
@ -10,8 +10,7 @@ class Database:
postgresql = 'postgresql://{}:{}@{}/{}'.format( postgresql = 'postgresql://{}:{}@{}/{}'.format(
conf_postgresql.get("Username"), conf_postgresql.get("Password"), conf_postgresql.get("Username"), conf_postgresql.get("Password"),
conf_postgresql.get("Host"), conf_postgresql.get("DBName")) conf_postgresql.get("Host"), conf_postgresql.get("DBName"))
self.engine = create_engine(postgresql, echo=False)
Session = sessionmaker() self.database = databases.Database(postgresql)
Session.configure(bind=self.engine) self.metadata = sqlalchemy.MetaData()
self.session: session = Session() self.engine = sqlalchemy.create_engine(str(self.database.url))

View file

@ -1,20 +1,32 @@
from discord.ext import commands from discord.ext import commands
from utils.functions import Config
class commandsPlus(commands.Command): class CommandsPlus(commands.Command):
def __init__(self, func, **kwargs): def __init__(self, func, **kwargs):
super().__init__(func, **kwargs) super().__init__(func, **kwargs)
self.category = kwargs.get("category", 'other') self.category = kwargs.get("category", 'other')
def commandExtra(*args, **kwargs):
return commands.command(*args, **kwargs, cls=commandsPlus)
class GroupPlus(commands.Group): class GroupPlus(commands.Group):
def __init__(self, func, **kwargs): def __init__(self, func, **kwargs):
super().__init__(func, **kwargs) super().__init__(func, **kwargs)
self.category = kwargs.get("category", 'other') self.category = kwargs.get("category", 'other')
def groupExtra(*args, **kwargs):
class ContextPlus(commands.Context):
async def send(self, content=None, **kwargs):
config = Config('./configs/config.cfg')
content = content.replace(config.get("bot", "Token"), 'Whoops! leaked token')
content = content.replace(config.get("webhook", "Token"), 'Whoops! leaked token')
return await super().send(content, **kwargs)
def command_extra(*args, **kwargs):
return commands.command(*args, **kwargs, cls=CommandsPlus)
def group_extra(*args, **kwargs):
return commands.group(*args, **kwargs, cls=GroupPlus) return commands.group(*args, **kwargs, cls=GroupPlus)

View file

@ -1,8 +1,6 @@
import gettext import gettext
from .config import Config import json
from .database import Database
from utils.models.lang import LangModel
from discord.ext import commands from discord.ext import commands
@ -21,18 +19,16 @@ class Texts:
self.locale = lang self.locale = lang
@staticmethod @staticmethod
def get_locale(ctx): def get_locale(ctx: commands.Context):
database = Database(Config("./configs/config.cfg")) lang = 'fr'
if ctx is not None: if ctx is not None:
current = database.session\ try:
.query(LangModel.value)\ with open(f'./configs/guilds/{ctx.guild.id}.json', 'r') as f:
.filter(LangModel.key == str(ctx.guild.id)) data = json.load(f)
if current.count() > 0:
return current.one()[0]
default = database.session\ lang = data['lang']
.query(LangModel.value)\
.filter(LangModel.key == 'default')\ except FileNotFoundError:
.one()[0] pass
return default
return lang

View file

@ -1,7 +1,18 @@
from sqlalchemy.ext.declarative import declarative_base import databases
Base = declarative_base() import sqlalchemy
from utils.functions import Config
conf_postgresql = Config('./configs/config.cfg')["postgresql"]
postgresql = 'postgresql://{}:{}@{}/{}'.format(
conf_postgresql.get("Username"), conf_postgresql.get("Password"),
conf_postgresql.get("Host"), conf_postgresql.get("DBName"))
database = databases.Database(postgresql)
metadata = sqlalchemy.MetaData()
engine = sqlalchemy.create_engine(str(database.url))
metadata.create_all(engine)
from .lang import LangModel
from .warn import WarnModel from .warn import WarnModel
from .poll import PollModel, ResponsesModel from .poll import PollModel, ResponsesModel
from .alias import AliasesModel from .alias import AliasesModel

View file

@ -1,28 +1,14 @@
from sqlalchemy import Column, String, BigInteger, Integer import orm
from . import database, metadata
from . import Base
class AliasesModel(Base): class AliasesModel(orm.Model):
__tablename__ = 'aliases' __tablename__ = 'aliases'
__database__ = database
__metadata__ = metadata
id = Column(Integer, primary_key=True) id = orm.Integer(primary_key=True)
user_id = Column(BigInteger) user_id = orm.String(max_length=18)
alias = Column(String) alias = orm.String(max_length=255)
command = Column(String) command = orm.String(max_length=255)
guild = Column(String) guild = orm.String(max_length=255)
def __repr__(self):
return "<AliasesModel(" \
"id='%s', " \
"user_id='%s', " \
"alias='%s', " \
"command='%s', " \
"guild='%s', " \
")>" % (
self.id,
self.user_id,
self.alias,
self.command,
self.guild
)

View file

@ -1,12 +0,0 @@
from . import Base
from sqlalchemy import Column, String
class LangModel(Base):
__tablename__ = 'langs'
key = Column(String, primary_key=True)
value = Column(String)
def __repr__(self):
return "<LangModel(key='%s', locale='%s')>" % (self.key, self.value)

View file

@ -1,27 +1,29 @@
from . import Base import orm
from sqlalchemy import Column, Integer, BigInteger, JSON, ForeignKey, Boolean from . import database, metadata
from sqlalchemy.orm import relationship
class PollModel(Base): class ResponsesModel(orm.Model):
__tablename__ = 'polls'
id = Column(Integer, primary_key=True, autoincrement=True)
channel_id = Column(BigInteger)
message_id = Column(BigInteger)
content = Column(JSON)
is_anonymous = Column(Boolean)
available_choices = Column(Integer)
choice = relationship("ResponsesModel")
class ResponsesModel(Base):
__tablename__ = 'responses' __tablename__ = 'responses'
__database__ = database
__metadata__ = metadata
id = Column(Integer, primary_key=True, autoincrement=True) id = orm.Integer(primary_key=True)
user = Column(BigInteger) user = orm.String(max_length=18)
poll_id = Column(Integer, ForeignKey('polls.id')) choice = orm.Integer()
choice = Column(Integer)
class PollModel(orm.Model):
__tablename__ = 'polls'
__database__ = database
__metadata__ = metadata
id = orm.Integer(primary_key=True)
channel_id = orm.String(max_length=18)
message_id = orm.String(max_length=18)
content = orm.JSON()
is_anonymous = orm.Boolean()
available_choices = orm.Integer()
choice = orm.ForeignKey(ResponsesModel)

View file

@ -1,19 +1,14 @@
import datetime import orm
from . import database, metadata
from . import Base
from sqlalchemy import Column, Integer, String, BIGINT, TIMESTAMP
class WarnModel(Base): class WarnModel(orm.Model):
__tablename__ = 'warns' __tablename__ = 'warns'
__database__ = database
__metadata__ = metadata
id = Column(Integer, primary_key=True) id = orm.Integer(primary_key=True)
server_id = Column(BIGINT) server_id = orm.String(max_length=18)
user_id = Column(BIGINT) user_id = orm.String(max_length=18)
reason = Column(String) reason = orm.String(max_length=255)
created_at = Column(TIMESTAMP, default=datetime.datetime.now()) created_at = orm.DateTime()
def __repr__(self):
return "<WarnModel(server_id='%s', user_id='%s', reason='%s', " \
"created_at='%s')>" \
% (self.server_id, self.user_id, self.reason, self.created_at)