├── Downloads ├── Addons │ └── Download.txt └── Configs │ └── Download.txt ├── Procfile ├── Logs └── logs.txt ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── codeql-analysis.yml ├── KumosLab └── Database │ ├── Local │ ├── clans.sqlite │ ├── roles.sqlite │ ├── Info.txt │ ├── userbase.sqlite │ └── serverbase.sqlite │ ├── conversion.py │ ├── insert.py │ ├── Create │ ├── RankCard │ │ ├── vacefron_gen.py │ │ ├── text.py │ │ └── custom.py │ ├── ClanCard │ │ └── clan_card.py │ └── Leaderboard │ │ ├── Local │ │ └── leaderboard.py │ │ └── MongoDB │ │ └── leaderboard.py │ ├── check.py │ ├── remove.py │ ├── add.py │ ├── set.py │ └── get.py ├── Addons └── Addons.txt ├── requirements.txt ├── .env ├── Commands ├── leaderboard.py ├── blur.py ├── setborder.py ├── background.py ├── rank.py ├── mainchannel.py ├── xpcolour.py ├── talkchannels.py ├── role.py └── help.py ├── System ├── autoupdater.py ├── addonmanager.py ├── user_check.py └── levelsystem.py ├── README.md ├── main.py ├── Configs └── config.yml └── LICENSE /Downloads/Addons/Download.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: python main.py -------------------------------------------------------------------------------- /Downloads/Configs/Download.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Logs/logs.txt: -------------------------------------------------------------------------------- 1 | Logging will begin when the bot starts! -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: ['https://www.paypal.com/donate?hosted_button_id=TQ4KJSBK9GLJU'] 2 | -------------------------------------------------------------------------------- /KumosLab/Database/Local/clans.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/222ryan/Discord-Levels-Bot/HEAD/KumosLab/Database/Local/clans.sqlite -------------------------------------------------------------------------------- /KumosLab/Database/Local/roles.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/222ryan/Discord-Levels-Bot/HEAD/KumosLab/Database/Local/roles.sqlite -------------------------------------------------------------------------------- /KumosLab/Database/Local/Info.txt: -------------------------------------------------------------------------------- 1 | When starting the bot and using the 'Local' database type, your databases will be automatically created here. -------------------------------------------------------------------------------- /KumosLab/Database/Local/userbase.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/222ryan/Discord-Levels-Bot/HEAD/KumosLab/Database/Local/userbase.sqlite -------------------------------------------------------------------------------- /KumosLab/Database/Local/serverbase.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/222ryan/Discord-Levels-Bot/HEAD/KumosLab/Database/Local/serverbase.sqlite -------------------------------------------------------------------------------- /Addons/Addons.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | You can view the list of available addons via the command: !addon 4 | You can install an addon via the command: !addon 5 | You can view the installed addons via the command: !addons -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | discord~=1.0.1 2 | ruamel.yaml 3 | pymongo~=3.11.3 4 | dnspython 5 | vacefron.py 6 | psutil~=5.8.0 7 | python-dotenv~=0.17.0 8 | pyfiglet 9 | easy-pil 10 | numpy 11 | discord-ext-ipc 12 | Quart 13 | quart_discord -------------------------------------------------------------------------------- /KumosLab/Database/conversion.py: -------------------------------------------------------------------------------- 1 | def translate(num): 2 | num = float('{:.3g}'.format(num)) 3 | magnitude = 0 4 | while abs(num) >= 1000: 5 | magnitude += 1 6 | num /= 1000.0 7 | return '{}{}'.format('{:f}'.format(num).rstrip('0').rstrip('.'), ['', 'K', 'M', 'B', 'T'][magnitude]) 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behaviour: 15 | 16 | **Expected behaviour** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Screenshots** 20 | If applicable, add screenshots to help explain your problem. 21 | 22 | **Desktop (please complete the following information):** 23 | - OS: [e.g. WINDOWS] 24 | - Version [1.4] 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | # Your Discord Bots Token -- Do not put in quotations and make sure you do not share this with anyone! 2 | DISCORD_TOKEN= 3 | 4 | 5 | # To use MongoDB, set it as the Database_Type in the config.yml file. 6 | 7 | # This is the MongoDB Link you get after connecting your databse to python. Make sure you replace your password and the databse name! 8 | MONGODB_URI= 9 | 10 | # These are the two entries for when you made a collection. For example, when i created mine, i used discord and levelling, so for collection, mine would be "discord" 11 | # and for database_name, mine would be "levelling" Note: This is based on what you entered! If you need help with this, join the support server. 12 | COLLECTION= 13 | DATABASE_NAME= 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE]" 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /Commands/leaderboard.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | from ruamel.yaml import YAML 4 | 5 | import KumosLab.Database.get 6 | import KumosLab.Database.Create.Leaderboard.Local.leaderboard 7 | import KumosLab.Database.Create.Leaderboard.MongoDB.leaderboard 8 | 9 | 10 | 11 | yaml = YAML() 12 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 13 | config = yaml.load(file) 14 | 15 | 16 | # leaderboard Class 17 | class leaderboard(commands.Cog): 18 | def __init__(self, client): 19 | self.client = client 20 | 21 | # Leaderboard Command 22 | @commands.command(aliases=config['leaderboard_alias']) 23 | async def leaderboard(self, ctx, leader_type=None): 24 | if leader_type == None: 25 | leader_type = "local" 26 | else: 27 | leader_type = leader_type 28 | if config['Database_Type'].lower() == "local": 29 | await KumosLab.Database.Create.Leaderboard.Local.leaderboard.leaderboard(self=self, ctx=ctx, guild=ctx.guild, leader_type=leader_type) 30 | elif config['Database_Type'].lower() == "mongodb": 31 | await KumosLab.Database.Create.Leaderboard.MongoDB.leaderboard.leaderboard(self=self, ctx=ctx, guild=ctx.guild, leader_type=leader_type) 32 | 33 | 34 | 35 | # Sets-up the cog for leaderboard 36 | def setup(client): 37 | client.add_cog(leaderboard(client)) -------------------------------------------------------------------------------- /Commands/blur.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | from ruamel.yaml import YAML 4 | import random 5 | 6 | import KumosLab.Database.get 7 | import KumosLab.Database.set 8 | 9 | yaml = YAML() 10 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 11 | config = yaml.load(file) 12 | 13 | 14 | # Blur Class 15 | class blur(commands.Cog): 16 | def __init__(self, client): 17 | self.client = client 18 | 19 | # Rank Command 20 | @commands.command() 21 | async def setblur(self, ctx, value: int = None): 22 | if value is None or value < 0 or value > 10: 23 | embed = discord.Embed(description="🔴 **Error**: `Please enter a value less than or equal to 10.`") 24 | await ctx.reply(embed=embed) 25 | return 26 | try: 27 | if config['rank_generator'].lower() == "custom": 28 | member = ctx.author 29 | await KumosLab.Database.set.blur(user=member, guild=ctx.guild, amount=value) 30 | embed = discord.Embed(description=f"🟢 **SUCCESS**: `New Blur Value is: {value}`") 31 | await ctx.reply(embed=embed) 32 | else: 33 | return 34 | 35 | 36 | except Exception as e: 37 | print(f"[Blur Command] {e}") 38 | 39 | 40 | 41 | # Sets-up the cog for blur 42 | def setup(client): 43 | client.add_cog(blur(client)) -------------------------------------------------------------------------------- /KumosLab/Database/insert.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sqlite3 3 | 4 | import discord 5 | from pymongo import MongoClient 6 | from ruamel import yaml 7 | 8 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 9 | config = yaml.load(file) 10 | 11 | if config['Database_Type'].lower() == 'mongodb': 12 | MONGODB_URI = os.environ['MONGODB_URI'] 13 | COLLECTION = os.getenv("COLLECTION") 14 | DB_NAME = os.getenv("DATABASE_NAME") 15 | cluster = MongoClient(MONGODB_URI) 16 | levelling = cluster[COLLECTION][DB_NAME] 17 | 18 | async def userField(member: discord.Member, guild: discord.Guild): 19 | db_type = config["Database_Type"] 20 | if db_type.lower() == "mongodb": 21 | levelling.insert_one( 22 | {"guild_id": guild.id, "user_id": member.id, "name": str(member), "level": 1, "xp": 0, 23 | "background": config['Default_Background'], "xp_colour": config['Default_XP_Colour'], "blur": 0, 24 | "border": config['Default_Border']}) 25 | elif db_type.lower() == "local": 26 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 27 | cursor = db.cursor() 28 | sql = "INSERT INTO levelling (guild_id, user_id, name, level, xp, background, xp_colour, blur, border) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" 29 | val = ( 30 | member.guild.id, member.id, str(member), 1, 0, config['Default_Background'], config['Default_XP_Colour'], 0, 31 | config['Default_Border']) 32 | cursor.execute(sql, val) 33 | db.commit() 34 | cursor.close() -------------------------------------------------------------------------------- /Commands/setborder.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | from easy_pil import load_image 4 | from ruamel.yaml import YAML 5 | import random 6 | 7 | import KumosLab.Database.get 8 | import KumosLab.Database.set 9 | 10 | yaml = YAML() 11 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 12 | config = yaml.load(file) 13 | 14 | 15 | class border(commands.Cog): 16 | def __init__(self, client): 17 | self.client = client 18 | 19 | @commands.command() 20 | async def setborder(self, ctx, url: str = None): 21 | if url is None: 22 | embed = discord.Embed( 23 | description=f"🔴 **ERROR**: `Incorrect Usage! - {config['Prefix']}setborder `") 24 | await ctx.send(embed=embed) 25 | return 26 | try: 27 | await ctx.message.delete() 28 | 29 | # This tries to load the image from the url -- if incorrect it will throw an error resulting in the exception below 30 | load_image(str(url)) 31 | 32 | await KumosLab.Database.set.border(user=ctx.author, guild=ctx.guild, link=url) 33 | embed = discord.Embed(description=f"🟢 **SUCCESS**: `Border Changed To`: [Link]({url})") 34 | embed.set_thumbnail(url=url) 35 | await ctx.send(embed=embed) 36 | 37 | except Exception as e: 38 | embed = discord.Embed( 39 | description=f"🔴 **ERROR**: `Invalid Link! - {config['Prefix']}setborder `") 40 | await ctx.send(embed=embed) 41 | return 42 | 43 | 44 | def setup(client): 45 | client.add_cog(border(client)) 46 | -------------------------------------------------------------------------------- /System/autoupdater.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import os 3 | import sys 4 | 5 | import discord 6 | from discord.ext import commands, tasks 7 | from ruamel import yaml 8 | 9 | import KumosLab.Database.get 10 | 11 | 12 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 13 | config = yaml.load(file) 14 | 15 | 16 | bot_version = "2.0.4" 17 | 18 | class autoupdater(commands.Cog): 19 | def __init__(self, client): 20 | self.client = client 21 | 22 | @commands.Cog.listener() 23 | async def on_ready(self): 24 | if config['update_notify'] is True: 25 | update.start(self) 26 | 27 | def setup(client): 28 | client.add_cog(autoupdater(client)) 29 | 30 | @tasks.loop(hours=24) 31 | async def update(self = None): 32 | current_version = bot_version 33 | latest_version = await KumosLab.Database.get.latestVersion() 34 | if current_version != latest_version: 35 | bot_owner = self.client.get_user(int(config["Bot_Owner"])) 36 | embed = discord.Embed(title="📬 MODERN LEVELS - NEW UPDATE!", description="[A new update has been released for Modern Levels.](https://github.com/KumosLab/Discord-Levels-Bot)") 37 | embed.set_image(url="https://opengraph.githubassets.com/02c65877ccd391bd9b7f3b0e09154e1b9bdb321c2165d34026fc210fa1512f04/KumosLab/Discord-Levels-Bot") 38 | embed.add_field(name="Version", value=f"**~~{current_version}~~** `->` **{latest_version}**") 39 | embed.set_footer(text="React below to accept or decline the auto-update. Update will timeout after 1 hour.") 40 | await bot_owner.send(embed=embed) 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Commands/background.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | from easy_pil import load_image 4 | from ruamel.yaml import YAML 5 | 6 | import KumosLab.Database.get 7 | import KumosLab.Database.set 8 | 9 | import vacefron 10 | 11 | 12 | 13 | yaml = YAML() 14 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 15 | config = yaml.load(file) 16 | 17 | 18 | # Background Class 19 | class background(commands.Cog): 20 | def __init__(self, client): 21 | self.client = client 22 | 23 | # Background Command 24 | @commands.command() 25 | async def background(self, ctx, url: str = None): 26 | if url is None: 27 | embed = discord.Embed(description=f"🔴 **ERROR**: `Incorrect Usage - {config['Prefix']}background `") 28 | await ctx.send(embed=embed) 29 | return 30 | try: 31 | await ctx.message.delete() 32 | 33 | # This tries to load the image from the url -- if incorrect it will throw an error resulting in the exception below 34 | load_image(str(url)) 35 | 36 | await KumosLab.Database.set.background(user=ctx.author, guild=ctx.guild, link=url) 37 | embed = discord.Embed(description=f"🟢 **SUCCESS**: `Background Changed To`: [Link]({url})") 38 | embed.set_thumbnail(url=url) 39 | await ctx.send(embed=embed) 40 | 41 | except Exception as e: 42 | embed = discord.Embed(description=f"🔴 **ERROR**: `Invalid Background Link`") 43 | await ctx.send(embed=embed) 44 | return 45 | 46 | 47 | # Sets-up the cog for background 48 | def setup(client): 49 | client.add_cog(background(client)) -------------------------------------------------------------------------------- /Commands/rank.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | from ruamel.yaml import YAML 4 | 5 | import KumosLab.Database.get 6 | import KumosLab.Database.Create.RankCard.custom 7 | import KumosLab.Database.Create.RankCard.vacefron_gen 8 | import KumosLab.Database.Create.RankCard.text 9 | 10 | import vacefron 11 | 12 | 13 | 14 | yaml = YAML() 15 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 16 | config = yaml.load(file) 17 | 18 | 19 | # Rank Class 20 | class rank(commands.Cog): 21 | def __init__(self, client): 22 | self.client = client 23 | 24 | # Rank Command 25 | @commands.command(aliases=config['rank_alias']) 26 | async def rank(self, ctx, member: discord.Member = None): 27 | if member is None: 28 | member = ctx.author 29 | try: 30 | if config['rank_generator'].lower() == 'custom': 31 | rank = await KumosLab.Database.Create.RankCard.custom.generate(user=member, guild=ctx.guild) 32 | embed = discord.Embed() 33 | embed.set_image(url="attachment://rank_card.png") 34 | await ctx.reply(file=rank, embed=embed) 35 | elif config['rank_generator'].lower() == 'vacefron': 36 | rank = await KumosLab.Database.Create.RankCard.vacefron_gen.generate(user=member, guild=ctx.guild) 37 | embed = discord.Embed() 38 | embed.set_image(url="attachment://rank_card.png") 39 | await ctx.reply(file=rank, embed=embed) 40 | elif config['rank_generator'].lower() == 'text': 41 | rank = await KumosLab.Database.Create.RankCard.text.generate(user=member, guild=ctx.guild) 42 | await ctx.reply(embed=rank) 43 | 44 | 45 | 46 | except Exception as e: 47 | print(f"[Rank Command] {e}") 48 | embed = discord.Embed(description=":x: **Error**: `User not Found`") 49 | await ctx.send(embed=embed) 50 | raise e 51 | 52 | 53 | 54 | # Sets-up the cog for rank 55 | def setup(client): 56 | client.add_cog(rank(client)) -------------------------------------------------------------------------------- /KumosLab/Database/Create/RankCard/vacefron_gen.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord import File 3 | from easy_pil import Editor, load_image_async, Font, load_image 4 | from ruamel.yaml import YAML 5 | import Commands.rank 6 | 7 | import vacefron 8 | 9 | import KumosLab.Database.get 10 | 11 | vac_api = vacefron.Client() 12 | 13 | yaml = YAML() 14 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 15 | config = yaml.load(file) 16 | 17 | 18 | 19 | async def generate(user: discord.Member = None, guild: discord.Guild = None): 20 | if guild is None: 21 | print("[Vacefron] Guild is None") 22 | return 23 | if user is None: 24 | print("[Vacefron] User is None") 25 | return 26 | try: 27 | 28 | user_ranking = await KumosLab.Database.get.rankings(user=user, guild=guild) 29 | lvl = await KumosLab.Database.get.level(user=user, guild=guild) 30 | xp = await KumosLab.Database.get.xp(user=user, guild=guild) 31 | xp_colour = await KumosLab.Database.get.colour(user=user, guild=guild) 32 | background = await KumosLab.Database.get.background(user=user, guild=guild) 33 | 34 | lvl = 0 35 | rank = 0 36 | while True: 37 | if xp < ((config['xp_per_level'] / 2 * (lvl ** 2)) + (config['xp_per_level'] / 2 * lvl)): 38 | break 39 | lvl += 1 40 | xp -= ((config['xp_per_level'] / 2 * (lvl - 1) ** 2) + (config['xp_per_level'] / 2 * (lvl - 1))) 41 | 42 | gen_card = await vac_api.rank_card( 43 | username=str(user), 44 | avatar=user.avatar_url, 45 | level=int(lvl), 46 | rank=int(user_ranking), 47 | current_xp=int(xp), 48 | next_level_xp=int(config['xp_per_level'] * 2 * ((1 / 2) * lvl)), 49 | previous_level_xp=0, 50 | xp_color=str(xp_colour), 51 | custom_background=str(background), 52 | is_boosting=bool(user.premium_since), 53 | circle_avatar=False 54 | ) 55 | 56 | card = File(fp=await gen_card.read(), filename="rank_card.png") 57 | return card 58 | 59 | 60 | 61 | except Exception as e: 62 | print(f"[Vacefron Rank Card] {e}") 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /KumosLab/Database/Create/RankCard/text.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord import File 3 | from easy_pil import Editor, load_image_async, Font, load_image 4 | from ruamel.yaml import YAML 5 | import Commands.rank 6 | 7 | import vacefron 8 | 9 | import KumosLab.Database.get 10 | 11 | vac_api = vacefron.Client() 12 | 13 | yaml = YAML() 14 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 15 | config = yaml.load(file) 16 | 17 | 18 | 19 | async def generate(user: discord.Member = None, guild: discord.Guild = None): 20 | if guild is None: 21 | print("[Vacefron] Guild is None") 22 | return 23 | if user is None: 24 | print("[Vacefron] User is None") 25 | return 26 | try: 27 | 28 | user_ranking = await KumosLab.Database.get.rankings(user=user, guild=guild) 29 | lvl = await KumosLab.Database.get.level(user=user, guild=guild) 30 | xp = await KumosLab.Database.get.xp(user=user, guild=guild) 31 | 32 | lvl = 0 33 | rank = 0 34 | while True: 35 | if xp < ((config['xp_per_level'] / 2 * (lvl ** 2)) + (config['xp_per_level'] / 2 * lvl)): 36 | break 37 | lvl += 1 38 | xp -= ((config['xp_per_level'] / 2 * (lvl - 1) ** 2) + (config['xp_per_level'] / 2 * (lvl - 1))) 39 | 40 | embed = discord.Embed(title=f"👤 {user}' Rank Card") 41 | embed.set_thumbnail(url=user.avatar_url) 42 | embed.add_field(name="Level:", value=f"{lvl:,}") 43 | embed.add_field(name="Rank:", value=f"{user_ranking:,}") 44 | 45 | dashes = 10 46 | max_level = int(config['xp_per_level'] * 2 * ((1 / 2) * lvl)) 47 | 48 | # create a progress bar 49 | dashConvert = int(max_level / dashes) 50 | currentDashes = int(xp / dashConvert) 51 | remainingDashes = dashes - currentDashes 52 | 53 | progressDisplay = '🟦' * currentDashes 54 | remainingDisplay = '⬛' * remainingDashes 55 | 56 | embed.add_field(name=f"Progress ({xp:,} / {max_level:,})", value=f"{progressDisplay}{remainingDisplay}", inline=False) 57 | 58 | 59 | return embed 60 | 61 | 62 | 63 | except Exception as e: 64 | print(f"[Vacefron Rank Card] {e}") 65 | raise e 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /Commands/mainchannel.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | from ruamel.yaml import YAML 4 | 5 | import KumosLab.Database.get 6 | import KumosLab.Database.set 7 | import KumosLab.Database.add 8 | 9 | import vacefron 10 | 11 | yaml = YAML() 12 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 13 | config = yaml.load(file) 14 | 15 | 16 | 17 | 18 | # MainChannel Class 19 | class mainchannel(commands.Cog): 20 | def __init__(self, client): 21 | self.client = client 22 | 23 | # Rank Command 24 | @commands.command(aliases=['mc']) 25 | async def mainchannel(self, ctx, channel: discord.TextChannel = None): 26 | if channel is None: 27 | if await KumosLab.Database.get.mainChannel(guild=ctx.guild) is None: 28 | embed = discord.Embed(description=f"🔴 **ERROR**: `Incorrect Usage - {config['Prefix']}mc <#channel>`") 29 | await ctx.reply(embed=embed) 30 | return 31 | try: 32 | await KumosLab.Database.set.mainChannel(guild=ctx.guild, channel=channel) 33 | embed = discord.Embed( 34 | description=f"🟢 **SUCCESS**: `📢 Main Channel set to: {await KumosLab.Database.get.mainChannel(guild=ctx.guild)}`") 35 | await ctx.reply(embed=embed) 36 | except Exception as e: 37 | print(f"[MainChannel Command] {e}") 38 | embed = discord.Embed(description=f"🔴 **ERROR**: `Failed to set Main Channel`") 39 | await ctx.reply(embed=embed) 40 | return 41 | 42 | @commands.Cog.listener() 43 | async def on_guild_channel_delete(self, channel): 44 | try: 45 | channels = await KumosLab.Database.get.mainChannel(guild=channel.guild) 46 | if channel.id in channels: 47 | # get random channel in guild 48 | channel = await channel.guild.fetch_channels() 49 | channel = channel[0] 50 | await KumosLab.Database.set.mainChannel(guild=channel.guild, channel=None) 51 | return 52 | except Exception as e: 53 | print(f"[MainChannel Command] {e}") 54 | return 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | # Sets-up the cog for mainchannel 63 | def setup(client): 64 | client.add_cog(mainchannel(client)) 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](https://cdn.discordapp.com/attachments/831180817064656907/958877659629248512/Modern_Levels.png) 2 |

3 | 5 |

Welcome To Modern Levels

6 |

7 | 8 | Modern Levels is the most advanced open-source Discord Levelling Bot 9 | 10 | 16 | 17 | 18 | Running into problems? Want to submit a bug report or suggestion? Join our [Support Server](https://discord.gg/UgvTHmuyNK) 19 | 20 | **Please do not use REPLIT to host the bot!** 21 | 22 | 23 | # The Rank Card 24 | ![](https://media.discordapp.net/attachments/831180817064656907/958884572270067803/Modern_Levels_1.png?width=998&height=285) 25 | The Rank Card can easily have it's Blur Level, Background, Profile Border & Text Colour changed through commands. 26 | 27 | Modern Levels Allows you to switch between 3 Rank Card Generators: 28 | 29 | | Generator | Description | 30 | | ------------- |:-------------:| 31 | | Custom | The Rank Card by Kumo's Lab, supports all customisation options and will never go down. | 32 | | Vacefron | The Rank Card created by Vacefron, supports half the customisation options, regular down time. | 33 | | Text | The Rank Card to keep things simple and fast, currently with no customisations, but the fastest out of the 3. | 34 | 35 | 36 | # Features 37 | ![](https://media.discordapp.net/attachments/831180817064656907/958887123900067910/Modern_Levels_4.png?width=998&height=285) 38 | 49 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | schedule: 21 | - cron: '32 7 * * 5' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | language: [ 'python' ] 32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 33 | # Learn more: 34 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 35 | 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@v2 39 | 40 | # Initializes the CodeQL tools for scanning. 41 | - name: Initialize CodeQL 42 | uses: github/codeql-action/init@v1 43 | with: 44 | languages: ${{ matrix.language }} 45 | # If you wish to specify custom queries, you can do so here or in a config file. 46 | # By default, queries listed here will override any specified in a config file. 47 | # Prefix the list here with "+" to use these queries and those in the config file. 48 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 49 | 50 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 51 | # If this step fails, then you should remove it and run the build manually (see below) 52 | - name: Autobuild 53 | uses: github/codeql-action/autobuild@v1 54 | 55 | # ℹ️ Command-line programs to run using the OS shell. 56 | # 📚 https://git.io/JvXDl 57 | 58 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 59 | # and modify them (or add more) to build your code if your project 60 | # uses a compiled language 61 | 62 | #- run: | 63 | # make bootstrap 64 | # make release 65 | 66 | - name: Perform CodeQL Analysis 67 | uses: github/codeql-action/analyze@v1 68 | -------------------------------------------------------------------------------- /Commands/xpcolour.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | from ruamel.yaml import YAML 4 | import random 5 | 6 | import KumosLab.Database.get 7 | import KumosLab.Database.set 8 | 9 | yaml = YAML() 10 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 11 | config = yaml.load(file) 12 | 13 | 14 | # XP Colour Class 15 | class setcolour(commands.Cog): 16 | def __init__(self, client): 17 | self.client = client 18 | 19 | @commands.command(aliases=['setcolor']) 20 | async def setcolour(self, ctx, hex: str = None): 21 | if hex is None: 22 | embed = discord.Embed( 23 | description=f"🔴 **ERROR**: `Colour Change Failed! - {config['Prefix']}setcolour <#hexcode|random>`") 24 | await ctx.send(embed=embed) 25 | return 26 | try: 27 | member = ctx.author 28 | if hex.lower() == "random": 29 | random_number = random.randint(0, 16777215) 30 | hex_number = format(random_number, 'x') 31 | hex_number = '#' + hex_number 32 | await KumosLab.Database.set.colour(user=member,guild=member.guild, hex=hex_number) 33 | embed = discord.Embed(description=f"🟢 **SUCCESS**: `Colour Changed to {hex_number}`", color=int(str(hex_number).replace("#", "0x"), 16)) 34 | await ctx.reply(embed=embed) 35 | else: 36 | # check if hex includes # 37 | if hex.startswith("#"): 38 | if len(hex) > 7 or len(hex) < 7: 39 | embed = discord.Embed( 40 | description=f"🔴 **ERROR**: `Colour Change Failed! - Invalid Hex Code`") 41 | await ctx.reply(embed=embed) 42 | else: 43 | await KumosLab.Database.set.colour(user=member,guild=member.guild, hex=hex) 44 | embed = discord.Embed(description=f"🟢 **SUCCESS**: `Colour Changed to {hex}`", color=int(str(hex).replace("#", "0x"), 16)) 45 | await ctx.reply(embed=embed) 46 | # add # to hex 47 | else: 48 | new_hex = "#" + hex 49 | if len(hex) > 7 or len(new_hex) < 7: 50 | embed = discord.Embed( 51 | description=f"🔴 **ERROR**: `Colour Change Failed! - Invalid Hex Code`") 52 | await ctx.reply(embed=embed) 53 | else: 54 | await KumosLab.Database.set.colour(user=member,guild=member.guild, hex=new_hex) 55 | embed = discord.Embed(description=f"🟢 **SUCCESS**: `Colour Changed to {new_hex}`", color=int(str(new_hex).replace("#", "0x"), 16)) 56 | await ctx.reply(embed=embed) 57 | 58 | 59 | except Exception as e: 60 | print(f"[XP-Colour Command] {e}") 61 | 62 | def setup(client): 63 | client.add_cog(setcolour(client)) -------------------------------------------------------------------------------- /KumosLab/Database/Create/ClanCard/clan_card.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord import File 3 | from easy_pil import Editor, load_image_async, Font, load_image 4 | from ruamel.yaml import YAML 5 | import Commands.rank 6 | 7 | 8 | import KumosLab.Database.get 9 | 10 | 11 | yaml = YAML() 12 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 13 | config = yaml.load(file) 14 | with open("Configs/clan_addon.yml", "r", encoding="utf-8") as file: 15 | clan_config = yaml.load(file) 16 | 17 | def translate(num): 18 | num = float('{:.3g}'.format(num)) 19 | magnitude = 0 20 | while abs(num) >= 1000: 21 | magnitude += 1 22 | num /= 1000.0 23 | return '{}{}'.format('{:f}'.format(num).rstrip('0').rstrip('.'), ['', 'K', 'M', 'B', 'T'][magnitude]) 24 | 25 | async def generate(user: discord.Member = None, guild: discord.Guild = None, clan_Name: str = None): 26 | if guild is None: 27 | print("[Custom] Guild is None") 28 | return 29 | if user is None: 30 | print("[Custom] User is None") 31 | return 32 | if clan_Name is None: 33 | print("[Custom] Clan_Name is None") 34 | return 35 | try: 36 | xp = await KumosLab.Database.get.clanXP(clan_Name=clan_Name, guild=guild) 37 | level = 1 38 | 39 | rank_colour = await KumosLab.Database.get.clanColour(clan_Name=clan_Name, guild=guild) 40 | clan_owner = await KumosLab.Database.get.clanOwner(clan_Name=clan_Name, guild=guild) 41 | 42 | blur = 0 43 | 44 | while True: 45 | if xp < ((config['xp_per_level'] / 2 * (level ** 2)) + (config['xp_per_level'] / 2 * level)): 46 | break 47 | level += 1 48 | xp -= ((config['xp_per_level'] / 2 * (level - 1) ** 2) + (config['xp_per_level'] / 2 * (level - 1))) 49 | 50 | next_level_xp = int(config['xp_per_level'] * 2 * ((1 / 2) * level)) 51 | 52 | percentage = int((xp / next_level_xp) * 100) 53 | 54 | clan_logo = await KumosLab.Database.get.clanLogo(clan_Name=clan_Name, guild=guild) 55 | clan_background = clan_config['clan_card_background'] 56 | 57 | background_image = load_image(str(clan_background)) 58 | background = Editor(background_image).resize((1280, 720)).blur(amount=int(blur)) 59 | 60 | profile_border = load_image(clan_config['clan_icon_border']) 61 | profile_border = Editor(profile_border).resize((250, 260)) 62 | 63 | profile_image = load_image(clan_logo) 64 | profile = Editor(profile_image).resize((240, 250)) 65 | 66 | 67 | font_25 = Font.poppins(size=35, variant="bold") 68 | font_60_bold = Font.poppins(size=60, variant="bold") 69 | font_40_bold = Font.poppins(size=50, variant="bold") 70 | 71 | background.paste(profile_border, (30, 40)) 72 | background.paste(profile, (35, 45)) 73 | 74 | background.text((300, 40), f"{clan_owner}", font=font_60_bold, color=rank_colour) 75 | 76 | background.text((270, 150), f"Level: {level:,}", font=font_25, color="white") 77 | 78 | background.rectangle((260, 190), width=600, height=40, radius=20) 79 | if percentage > 5: 80 | background.bar( 81 | (260, 190), 82 | max_width=600, 83 | height=40, 84 | percentage=percentage, 85 | fill=rank_colour, 86 | radius=20, 87 | ) 88 | 89 | background.text( 90 | (845, 145), f"{translate(xp)} / {translate(next_level_xp)}", font=font_25, color="white", align="right" 91 | ) 92 | 93 | card = File(fp=background.image_bytes, filename="rank_card.png") 94 | return card 95 | 96 | except Exception as e: 97 | print(f"[Custom Rank Card] {e}") 98 | raise e 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /Commands/talkchannels.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | from ruamel.yaml import YAML 4 | 5 | import KumosLab.Database.get 6 | import KumosLab.Database.set 7 | import KumosLab.Database.add 8 | 9 | import vacefron 10 | 11 | yaml = YAML() 12 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 13 | config = yaml.load(file) 14 | 15 | 16 | class talkchannel(commands.Cog): 17 | def __init__(self, client): 18 | self.client = client 19 | 20 | @commands.command(aliases=['tc']) 21 | async def talkchannel(self, ctx, case = None, channel: discord.TextChannel = None): 22 | if channel is None: 23 | embed = discord.Embed(description=f"🔴 **ERROR**: `Incorrect Usage - {config['Prefix']}tc <#channel>`") 24 | await ctx.reply(embed=embed) 25 | return 26 | if case is None: 27 | embed = discord.Embed(description=f"🔴 **ERROR**: `Incorrect Usage - {config['Prefix']}tc <#channel>`") 28 | await ctx.reply(embed=embed) 29 | return 30 | try: 31 | if case.lower() == "add": 32 | await KumosLab.Database.add.talkchannel(guild=ctx.guild, channel=channel) 33 | embed = discord.Embed( 34 | description=f"🟢 **SUCCESS**: `💭 Added Talk Channel: {channel}`") 35 | await ctx.reply(embed=embed) 36 | return 37 | elif case.lower() == "remove": 38 | await KumosLab.Database.remove.talkchannel(guild=ctx.guild, channel=channel) 39 | embed = discord.Embed( 40 | description=f"🟢 **SUCCESS**: `💭 Removed Talk Channel: {channel}`") 41 | await ctx.reply(embed=embed) 42 | return 43 | except Exception as e: 44 | print(f"[TalkChannel Command] {e}") 45 | embed = discord.Embed(description=f"🔴 **ERROR**: `Failed to add Talk Channel`") 46 | await ctx.reply(embed=embed) 47 | return 48 | 49 | @commands.command(aliases=['tcs']) 50 | async def talkchannels(self, ctx): 51 | try: 52 | channels = await KumosLab.Database.get.talkchannels(guild=ctx.guild) 53 | if channels is None or len(channels) == 0: 54 | embed = discord.Embed(description=f"💭: `You can gain XP anywhere!`") 55 | await ctx.reply(embed=embed) 56 | return 57 | else: 58 | channel_Array = [] 59 | for channel in channels: 60 | channel_Array.append(channel) 61 | if channel_Array[0] is None: 62 | embed = discord.Embed(description=f"💭: `You can gain XP anywhere!`") 63 | await ctx.reply(embed=embed) 64 | return 65 | # convert channel id to channel object 66 | channel_List = [] 67 | for x in channel_Array: 68 | channel = self.client.get_channel(int(x)) 69 | channel_List.append(channel.name) 70 | embed = discord.Embed(description=f"💭: `You can gain XP in:`") 71 | embed.add_field(name="Talk Channels", value=f"`{channel_List}`".replace("[", "").replace("]", "").replace("'", "").replace(" ", "")) 72 | await ctx.reply(embed=embed) 73 | return 74 | except Exception as e: 75 | print(f"[TalkChannels Command] {e}") 76 | embed = discord.Embed(description=f"🔴 **ERROR**: `Failed to get Talk Channels`") 77 | await ctx.reply(embed=embed) 78 | return 79 | 80 | @commands.Cog.listener() 81 | async def on_guild_channel_delete(self, channel): 82 | try: 83 | channels = await KumosLab.Database.get.talkchannels(guild=channel.guild) 84 | if channel.id in channels: 85 | await KumosLab.Database.remove.talkchannel(guild=channel.guild, channel=channel) 86 | return 87 | except Exception as e: 88 | print(f"[TalkChannels Command] {e}") 89 | return 90 | 91 | 92 | 93 | def setup(client): 94 | client.add_cog(talkchannel(client)) 95 | -------------------------------------------------------------------------------- /KumosLab/Database/Create/RankCard/custom.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord import File 3 | from easy_pil import Editor, load_image_async, Font, load_image 4 | from ruamel.yaml import YAML 5 | import Commands.rank 6 | 7 | 8 | import KumosLab.Database.get 9 | 10 | 11 | yaml = YAML() 12 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 13 | config = yaml.load(file) 14 | 15 | def translate(num): 16 | num = float('{:.3g}'.format(num)) 17 | magnitude = 0 18 | while abs(num) >= 1000: 19 | magnitude += 1 20 | num /= 1000.0 21 | return '{}{}'.format('{:f}'.format(num).rstrip('0').rstrip('.'), ['', 'K', 'M', 'B', 'T'][magnitude]) 22 | 23 | async def generate(user: discord.Member = None, guild: discord.Guild = None): 24 | if guild is None: 25 | print("[Custom] Guild is None") 26 | return 27 | if user is None: 28 | print("[Custom] User is None") 29 | return 30 | try: 31 | xp = await KumosLab.Database.get.xp(user=user, guild=guild) 32 | level = 1 33 | 34 | rank_colour = await KumosLab.Database.get.colour(user=user, guild=guild) 35 | 36 | blur = await KumosLab.Database.get.blur(user=user, guild=guild) 37 | 38 | while True: 39 | if xp < ((config['xp_per_level'] / 2 * (level ** 2)) + (config['xp_per_level'] / 2 * level)): 40 | break 41 | level += 1 42 | xp -= ((config['xp_per_level'] / 2 * (level - 1) ** 2) + (config['xp_per_level'] / 2 * (level - 1))) 43 | 44 | next_level_xp = int(config['xp_per_level'] * 2 * ((1 / 2) * level)) 45 | 46 | percentage = int((xp / next_level_xp) * 100) 47 | 48 | user_background = await KumosLab.Database.get.background(user=user, guild=guild) 49 | user_border = await KumosLab.Database.get.border(user=user, guild=guild) 50 | 51 | background_image = load_image(str(user_background)) 52 | background = Editor(background_image).resize((1050, 300)).blur(amount=int(blur)) 53 | 54 | user_ranking = await KumosLab.Database.get.rankings(user=user, guild=guild) 55 | 56 | profile_image = load_image(user.avatar_url) 57 | profile = Editor(profile_image).resize((200, 210)) 58 | border_image = load_image(user_border) 59 | border = Editor(border_image).resize((210, 220)) 60 | 61 | 62 | font_25 = Font.poppins(size=35, variant="bold") 63 | font_60_bold = Font.poppins(size=60, variant="bold") 64 | font_40_bold = Font.poppins(size=50, variant="bold") 65 | 66 | background.paste(border, (30, 40)) 67 | background.paste(profile, (35, 45)) 68 | 69 | if config['name_colour'] is True: 70 | background.text((260, 40), f"{user}", font=font_60_bold, color=rank_colour) 71 | background.text( 72 | (870, 190), f"#{translate(user_ranking)}", font=font_40_bold, 73 | color=rank_colour 74 | ) 75 | else: 76 | background.text((250, 40), f"{user}", 77 | font=font_60_bold, color="white") 78 | background.text( 79 | (870, 190), f"#{await KumosLab.Database.get.rankings(user=user, guild=user.guild):,}", font=font_40_bold, 80 | color="white" 81 | ) 82 | background.text((270, 150), f"Level: {level:,}", font=font_25, color="white") 83 | 84 | background.rectangle((260, 190), width=600, height=40, radius=20) 85 | if percentage > 5: 86 | background.bar( 87 | (260, 190), 88 | max_width=600, 89 | height=40, 90 | percentage=percentage, 91 | fill=rank_colour, 92 | radius=20, 93 | ) 94 | 95 | background.text( 96 | (845, 145), f"{translate(xp)} / {translate(next_level_xp)}", font=font_25, color="white", align="right" 97 | ) 98 | 99 | card = File(fp=background.image_bytes, filename="rank_card.png") 100 | return card 101 | 102 | except Exception as e: 103 | print(f"[Custom Rank Card] {e}") 104 | raise e 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /System/addonmanager.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import os 3 | from os import listdir 4 | import sys 5 | 6 | import discord 7 | from discord.ext import commands, tasks 8 | from ruamel import yaml 9 | 10 | import KumosLab.Database.get 11 | 12 | 13 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 14 | config = yaml.load(file) 15 | 16 | 17 | class addonmanager(commands.Cog): 18 | def __init__(self, client): 19 | self.client = client 20 | 21 | @commands.command() 22 | async def addons(self, ctx): 23 | addons = [] 24 | for file in listdir("Addons"): 25 | if file.endswith(".py"): 26 | addons.append(file.replace(".py", "")) 27 | 28 | if len(addons) == 0: 29 | embed = discord.Embed(title="Installed Addons", description="```No addons installed!```") 30 | await ctx.reply(embed=embed) 31 | else: 32 | embed = discord.Embed(title="Installed Addons", description=f"```{addons}```".replace("[", "").replace("]", "").replace("'", "")) 33 | await ctx.reply(embed=embed) 34 | 35 | 36 | @commands.command() 37 | async def addon(self, ctx, addon: str = None): 38 | if ctx.author.id == int(config['Bot_Owner']): 39 | if addon is None: 40 | embed = discord.Embed(title="📬 ADDON MANAGER") 41 | embed.add_field(name="📢 Vocal", value=f"`{config['Prefix']}addon vocal`", inline=False) 42 | embed.add_field(name="➕ Extras", value=f"`{config['Prefix']}addon extras`", inline=False) 43 | embed.add_field(name="👤 Status", value=f"`{config['Prefix']}addon status`", inline=False) 44 | await ctx.reply(embed=embed) 45 | else: 46 | if addon.title() not in ["Vocal", "Clan", "Extras", "Status", "Prestige"]: 47 | await ctx.reply("❌ **Addon not found**") 48 | else: 49 | link = "https://github.com/KumosLab/Discord-Levels-Bot.git" 50 | branch = addon.title() 51 | 52 | # git init into Downloads 53 | os.system(f"git init Downloads") 54 | os.system(f"cd Downloads && git remote add origin {link}") 55 | os.system(f"cd Downloads && git pull origin {branch}") 56 | os.system(f"cd Downloads && git checkout {branch}") 57 | os.system(f"cd Downloads && git pull") 58 | 59 | 60 | 61 | 62 | # get absolute path of Downloads 63 | path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "Downloads/Addons")) 64 | path2 = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "Downloads/Configs")) 65 | # get absolute path of addon folder 66 | addon_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "Addons")) 67 | # get absolute path of configs folder 68 | config_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "Configs")) 69 | 70 | # for files in path 1 move to addon_path 71 | for file in listdir(path): 72 | os.replace(os.path.join(path, file), os.path.join(addon_path, file)) 73 | 74 | # for files in path 2 move to config_path 75 | for file in listdir(path2): 76 | os.replace(os.path.join(path2, file), os.path.join(config_path, file)) 77 | 78 | await ctx.reply("`🟢` | Addon installed, starting addon...") 79 | for fn in listdir("Addons"): 80 | if fn.endswith(".py"): 81 | try: 82 | self.client.load_extension(f"Addons.{addon.title()}") 83 | await ctx.reply("`🟢` | Addon started") 84 | break 85 | except Exception as e: 86 | self.client.reload_extension(f"Addons.{addon.title()}") 87 | await ctx.reply("`🟢` | Addon started") 88 | break 89 | 90 | 91 | else: 92 | return 93 | 94 | 95 | 96 | 97 | 98 | def setup(client): 99 | client.add_cog(addonmanager(client)) 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /System/user_check.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import functools 3 | import os 4 | import sqlite3 5 | import typing 6 | 7 | from discord.ext import commands 8 | from dotenv import load_dotenv 9 | from pymongo import MongoClient 10 | from ruamel.yaml import YAML 11 | 12 | yaml = YAML() 13 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 14 | config = yaml.load(file) 15 | 16 | # Loads the .env file and gets the required information 17 | load_dotenv() 18 | 19 | if config['Database_Type'].lower() == 'mongodb': 20 | MONGODB_URI = os.environ['MONGODB_URI'] 21 | COLLECTION = os.getenv("COLLECTION") 22 | DB_NAME = os.getenv("DATABASE_NAME") 23 | cluster = MongoClient(MONGODB_URI) 24 | levelling = cluster[COLLECTION][DB_NAME] 25 | 26 | 27 | 28 | class user_check(commands.Cog): 29 | def __init__(self, client): 30 | self.client = client 31 | 32 | async def check(self): 33 | # get database type from config file 34 | print(f"[User-Check] Checking for users & guilds...") 35 | db_type = config["Database_Type"] 36 | if db_type.lower() == "mongodb": 37 | for member in self.client.get_all_members(): 38 | if not member.bot: 39 | if not levelling.find_one({"user_id": member.id, "guild_id": member.guild.id}): 40 | levelling.insert_one( 41 | {"guild_id": member.guild.id, "user_id": member.id, "name": str(member), "level": 1, 42 | "xp": 0, 43 | "background": config['Default_Background'], "xp_colour": config['Default_XP_Colour'], 44 | "blur": 0, "border": config['Default_Border']}) 45 | print(f"[User-Check] Added {member.name} to MongoDB Database.") 46 | else: 47 | continue 48 | for guild in self.client.guilds: 49 | if not levelling.find_one({"guild": guild.id}): 50 | levelling.insert_one({"guild": guild.id, "main_channel": None, "admin_role": None, "roles": [], 51 | "role_levels": [], 'talkchannels': []}) 52 | print(f"[User-Check] Added {guild.name} to MongoDB Database.") 53 | else: 54 | continue 55 | elif db_type.lower() == "local": 56 | for guild in self.client.guilds: 57 | db = sqlite3.connect("KumosLab/Database/Local/serverbase.sqlite") 58 | cursor = db.cursor() 59 | cursor.execute("SELECT * FROM levelling where guild_id = ?", (guild.id,)) 60 | if cursor.fetchone() is None: 61 | sql = "INSERT INTO levelling (guild_id, admin_role, main_channel, talkchannels) VALUES (?, ?, ?, ?) " 62 | cursor.execute(sql, (guild.id, None, None, None)) 63 | print(f"[User-Check] Added {guild.name} to SQLite Database.") 64 | db.commit() 65 | cursor.close() 66 | for member in guild.members: 67 | # check if member is a bot 68 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 69 | cursor = db.cursor() 70 | if not member.bot: 71 | cursor.execute("SELECT * FROM levelling WHERE user_id = ? AND guild_id = ?", 72 | (member.id, guild.id)) 73 | result = cursor.fetchone() 74 | if result is None: 75 | sql = "INSERT INTO levelling (guild_id, user_id, name, level, xp, background, xp_colour, blur, border) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" 76 | val = (guild.id, member.id, str(member), 1, 0, config['Default_Background'], 77 | config['Default_XP_Colour'], 0, config['Default_Border']) 78 | cursor.execute(sql, val) 79 | print(f"[User-Check] Added {member.name} to SQLite Database.") 80 | db.commit() 81 | else: 82 | continue 83 | 84 | 85 | 86 | @commands.Cog.listener() 87 | async def on_ready(self): 88 | await self.client.wait_until_ready() 89 | if config['loader_type'].lower() == 'startup': 90 | await user_check.check(self) 91 | 92 | 93 | 94 | def setup(client): 95 | client.add_cog(user_check(client)) 96 | -------------------------------------------------------------------------------- /KumosLab/Database/check.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sqlite3 3 | 4 | import discord 5 | from pymongo import MongoClient 6 | from ruamel import yaml\ 7 | 8 | import numpy as np 9 | from discord import File 10 | 11 | from easy_pil import Editor, load_image_async, Font, load_image 12 | import KumosLab.Database.add 13 | import KumosLab.Database.get 14 | import KumosLab.Database.set 15 | import KumosLab.Database.remove 16 | 17 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 18 | config = yaml.load(file) 19 | 20 | def translate(num): 21 | num = float('{:.3g}'.format(num)) 22 | magnitude = 0 23 | while abs(num) >= 1000: 24 | magnitude += 1 25 | num /= 1000.0 26 | return '{}{}'.format('{:f}'.format(num).rstrip('0').rstrip('.'), ['', 'K', 'M', 'B', 'T'][magnitude]) 27 | 28 | async def levelUp(user: discord.Member = None, guild: discord.Guild = None): 29 | if user is None: 30 | print("Error in 'KumosLab/Database/check.py' - User is None for 'levelUp'") 31 | return 32 | if guild is None: 33 | print("Error in 'KumosLab/Database/check.py' - Guild is None for 'levelUp'") 34 | return 35 | 36 | try: 37 | user_xp = await KumosLab.Database.get.xp(user=user, guild=guild) 38 | lvl = 0 39 | 40 | while True: 41 | if user_xp < ((config['xp_per_level'] / 2 * (lvl ** 2)) + (config['xp_per_level'] / 2 * lvl)): 42 | break 43 | lvl += 1 44 | user_xp -= ((config['xp_per_level'] / 2 * ((lvl - 1) ** 2)) + (config['xp_per_level'] / 2 * (lvl - 1))) 45 | if await KumosLab.Database.get.level(user=user, guild=guild) != lvl: 46 | await KumosLab.Database.set.level(user=user, guild=guild, amount=lvl) 47 | 48 | background_image = load_image(config['level_up_background']) 49 | background = Editor(background_image).resize((900, 270)).blur(amount=config['level_up_blur']) 50 | profile_image = load_image(str(user.avatar_url)) 51 | profile = Editor(profile_image).resize((200, 200)).circle_image() 52 | 53 | poppins_big = Font.poppins(variant="bold", size=50) 54 | poppins_mediam = Font.poppins(variant="bold", size=40) 55 | poppins_regular = Font.poppins(variant="regular", size=30) 56 | 57 | card_left_shape = [(0, 0), (0, 270), (330, 270), (260, 0)] 58 | 59 | background.polygon(card_left_shape, "#2C2F33") 60 | border_image = load_image(await KumosLab.Database.get.border(user=user, guild=guild)) 61 | border = Editor(border_image).resize((210, 210)).circle_image() 62 | background.paste(border, (40, 30)) 63 | background.paste(profile, (45, 35)) 64 | 65 | background.text((600, 30), "LEVEL UP!", font=poppins_big, color="white", align="center") 66 | background.text( 67 | (600, 80), str(user), font=poppins_regular, color="white", align="center" 68 | ) 69 | background.text( 70 | (600, 130), f"LEVEL {lvl:,}", font=poppins_mediam, color="white", align="center" 71 | ) 72 | background.text( 73 | (600, 170), f"{translate(user_xp)}/{translate(int(config['xp_per_level'] * 2 * ((1 / 2) * lvl)))} XP", 74 | font=poppins_regular, color="white", align="center" 75 | ) 76 | 77 | embed = discord.Embed() 78 | 79 | member = user 80 | if await KumosLab.Database.get.mainChannel(guild=guild) is None: 81 | channel = guild.system_channel 82 | else: 83 | channel = discord.utils.get(member.guild.channels, 84 | name=await KumosLab.Database.get.mainChannel(guild=member.guild)) 85 | if channel is None: 86 | return 87 | if config['level_up_ping'] is True: 88 | await channel.send(f"{user.mention},") 89 | 90 | level_roles = np.asarray(await KumosLab.Database.get.roles(guild=guild)) 91 | level_roles_num = np.asarray(await KumosLab.Database.get.roleLevel(guild=guild)) 92 | 93 | for i in range(len(level_roles)): 94 | if lvl == int(level_roles_num[i]): 95 | await user.add_roles( 96 | discord.utils.get(user.guild.roles, name=level_roles[i])) 97 | background.text( 98 | (620, 225), 99 | f"ROLE UNLOCKED - {level_roles[i]}".replace("[", "").replace("]", "").replace("'", ''), 100 | font=poppins_regular, 101 | color="white", 102 | align="center", 103 | ) 104 | 105 | # remove the previous role 106 | if i > 0: 107 | await user.remove_roles( 108 | discord.utils.get(user.guild.roles, name=level_roles[i - 1])) 109 | else: 110 | continue 111 | 112 | card = File(fp=background.image_bytes, filename="level_card.png") 113 | embed.set_image(url="attachment://level_card.png") 114 | await channel.send(file=card, embed=embed) 115 | except Exception as e: 116 | print(f"Error in 'KumosLab/Database/check.py' - {e}") -------------------------------------------------------------------------------- /Commands/role.py: -------------------------------------------------------------------------------- 1 | import discord 2 | import numpy as np 3 | from discord.ext import commands 4 | from ruamel.yaml import YAML 5 | 6 | import KumosLab.Database.get 7 | import KumosLab.Database.set 8 | import KumosLab.Database.add 9 | import KumosLab.Database.remove 10 | 11 | from discord.ext.commands import RoleNotFound 12 | 13 | import vacefron 14 | 15 | yaml = YAML() 16 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 17 | config = yaml.load(file) 18 | 19 | 20 | 21 | # Roles Class 22 | class role(commands.Cog): 23 | def __init__(self, client): 24 | self.client = client 25 | 26 | # Role Command 27 | @commands.command() 28 | async def role(self, ctx, state: str = None, role_name: discord.Role = None, role_level: int = None): 29 | if state is None: 30 | embed = discord.Embed(description=f"🔴 **ERROR**: `You must define add or remove! - {config['Prefix']}role `") 31 | await ctx.reply(embed=embed) 32 | return 33 | if role is None: 34 | embed = discord.Embed(description=f"🔴 **ERROR**: `You must define a role! - {config['Prefix']}role `") 35 | await ctx.send(embed=embed) 36 | return 37 | if role_level is None: 38 | embed = discord.Embed(description=f"🔴 **ERROR**: `You must define a role level! - {config['Prefix']}role `") 39 | await ctx.send(embed=embed) 40 | return 41 | try: 42 | if state.lower() == "add": 43 | exists = await KumosLab.Database.add.role(guild=ctx.guild, role_name=role_name, role_level=int(role_level)) 44 | if exists == "error": 45 | embed = discord.Embed(description=f"🔴 **ERROR**: `Role already exists! - {config['Prefix']}role `") 46 | await ctx.reply(embed=embed) 47 | return 48 | else: 49 | embed = discord.Embed(description=f"🟢 **SUCCESS**: `Added {role_name} to unlock at Level {role_level}`") 50 | await ctx.reply(embed=embed) 51 | elif state.lower() == "remove": 52 | await KumosLab.Database.remove.role(guild=ctx.guild, role_name=role_name, role_level=int(role_level)) 53 | embed = discord.Embed( 54 | description=f"🟢 **SUCCESS**: `Removed {role_name} from the Database!`") 55 | await ctx.reply(embed=embed) 56 | 57 | except RoleNotFound as e: 58 | embed = discord.Embed(description=f"🔴 **ERROR**: `Role not found! - {config['Prefix']}role `") 59 | await ctx.send(embed=embed) 60 | return 61 | 62 | # Role List Command 63 | @commands.command() 64 | async def roles(self, ctx): 65 | embed = discord.Embed(title="🔓 // LEVEL ROLES", description=f"**Level Roles for** `{ctx.guild.name}`") 66 | role_array = np.asarray(await KumosLab.Database.get.roles(guild=ctx.guild)) 67 | role_level_array = np.asarray(await KumosLab.Database.get.roleLevel(guild=ctx.guild)) 68 | if role_array is None or role_level_array is None: 69 | embed.add_field(name="Roles:", value="`There are no roles to unlock!`") 70 | embed.add_field(name="Level:", value="`No level required!`") 71 | return 72 | else: 73 | embed.add_field(name="Roles:", value=f"`{str(role_array).replace('[', '').replace(']', '')}`") 74 | embed.add_field(name="Level:", value=f"`{str(role_level_array).replace('[', '').replace(']', '')}`", inline=False) 75 | await ctx.send(embed=embed) 76 | 77 | @commands.command() 78 | async def creator(self, ctx, amount: int = None, prefix: str = None): 79 | if amount is None: 80 | embed = discord.Embed(description=f"🔴 **ERROR**: `You must define a amount! - {config['Prefix']}creator `") 81 | await ctx.reply(embed=embed) 82 | return 83 | if prefix is None: 84 | embed = discord.Embed(description=f"🔴 **ERROR**: `You must define a role-prefix! - {config['Prefix']}creator `") 85 | await ctx.reply(embed=embed) 86 | return 87 | if amount > 50 or amount < 1: 88 | embed = discord.Embed(description=f"🔴 **ERROR**: `You can only create 50 roles at a time! - {config['Prefix']}creator `") 89 | await ctx.reply(embed=embed) 90 | return 91 | if len(prefix) > 10 or len(prefix) < 1: 92 | embed = discord.Embed(description=f"🔴 **ERROR**: `You can only create a prefix with 10 characters! - {config['Prefix']}creator `") 93 | await ctx.reply(embed=embed) 94 | return 95 | # loop amount of times 96 | message = await ctx.send(f"🔓 **CREATING ROLES**: `Creating {amount} roles with prefix {prefix}. Please wait, this may take some time...`") 97 | for i in range(amount): 98 | # create role 99 | role = await ctx.guild.create_role(name=f"{prefix} {i + 1}") 100 | # add role to database 101 | await KumosLab.Database.add.role(guild=ctx.guild, role_name=role, role_level=i + 1) 102 | 103 | await message.edit(content=f"🔓 **CREATING ROLES**: `Created {amount} roles with prefix {prefix}.`") 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | # Sets-up the cog for roles 116 | def setup(client): 117 | client.add_cog(role(client)) 118 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # Imports 2 | import sqlite3 3 | from os import listdir 4 | 5 | import ruamel.yaml.error 6 | from discord.ext import commands, ipc 7 | from discord.ext.commands import CommandNotFound, RoleNotFound, MemberNotFound 8 | import discord 9 | from ruamel.yaml import YAML 10 | import logging 11 | import os 12 | from dotenv import load_dotenv 13 | import warnings 14 | import pyfiglet 15 | 16 | 17 | load_dotenv() 18 | 19 | class client(commands.Bot): 20 | def __init__(self, *args, **kwargs): 21 | super().__init__(*args, **kwargs) 22 | 23 | self.ipc = ipc.Server(self, secret_key="ModernLevels") 24 | 25 | async def on_ipc_error(self, endpoint, error): 26 | print(f"IPC Error: {endpoint} raised {error}") 27 | 28 | 29 | # Opens the config and reads it, no need for changes unless you'd like to change the library (no need to do so unless having issues with ruamel) 30 | yaml = YAML() 31 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 32 | config = yaml.load(file) 33 | 34 | warnings.simplefilter('ignore', ruamel.yaml.error.UnsafeLoaderWarning) 35 | 36 | # Command Prefix + Removes the default discord.py help command 37 | Client = client(command_prefix=commands.when_mentioned_or(config['Prefix']), intents=discord.Intents.all(), case_insensitive=True) 38 | Client.remove_command('help') 39 | 40 | # sends discord logging files which could potentially be useful for catching errors. 41 | os.close(os.open("Logs/logs.txt", os.O_CREAT)) 42 | os.truncate("Logs/logs.txt", 1) 43 | FORMAT = '[%(asctime)s]:[%(levelname)s]: %(message)s' 44 | logging.basicConfig(filename='Logs/logs.txt', level=logging.DEBUG, format=FORMAT) 45 | logging.debug('Begin Logging') 46 | logging.info('Getting ready to login to Discord...') 47 | 48 | 49 | @Client.event # On Bot Startup, Will send some details about the bot and sets it's activity and status. Feel free to remove the print messages, but keep everything else. 50 | async def on_ready(): 51 | if config['Database_Type'].lower() == 'local': 52 | print("Connecting to KumosLab/Database/Local/userbase.sqlite") 53 | db = sqlite3.connect('KumosLab/Database/Local/userbase.sqlite') 54 | cursor = db.cursor() 55 | cursor.execute("""CREATE TABLE IF NOT EXISTS levelling( 56 | user_id INTEGER, 57 | name TEXT, 58 | guild_id TEXT, 59 | level INTEGER, 60 | xp INTEGER, 61 | background TEXT, 62 | xp_colour TEXT, 63 | blur INTEGER, 64 | border TEXT 65 | )""") 66 | cursor.close() 67 | print("Connecting to KumosLab/Database/Local/serverbase.sqlite") 68 | db = sqlite3.connect('KumosLab/Database/Local/serverbase.sqlite') 69 | cursor = db.cursor() 70 | cursor.execute("""CREATE TABLE IF NOT EXISTS levelling( 71 | guild_id TEXT, 72 | admin_role TEXT, 73 | main_channel TEXT, 74 | talkchannels TEXT)""") 75 | cursor.close() 76 | print("Connecting to KumosLab/Database/Local/roles.sqlite") 77 | db = sqlite3.connect('KumosLab/Database/Local/roles.sqlite') 78 | cursor = db.cursor() 79 | cursor.execute("""CREATE TABLE IF NOT EXISTS levelling( 80 | guild_id TEXT, 81 | role TEXT, 82 | role_levels INTEGER 83 | )""") 84 | cursor.close() 85 | 86 | ascii_banner = pyfiglet.figlet_format("MODERN LEVELS") 87 | print(ascii_banner) 88 | 89 | print("Thank you for downloading Modern Levels 2.0 <3 \nIf you run into any issues, want to suggest a feature or " 90 | "want " 91 | "a place to hang out, join the Discord! discord.gg/UgvTHmuyNK\n") 92 | print('Logged In As:') 93 | print(f"Username: {Client.user.name}\nID: {Client.user.id}") 94 | print(f'Database Type: {str(config["Database_Type"]).title()}') 95 | 96 | @Client.event 97 | async def on_command_error(ctx, error): 98 | if isinstance(error, CommandNotFound): 99 | return 100 | if isinstance(error, RoleNotFound): 101 | embed = discord.Embed( 102 | description=f"🔴 **ERROR**: `Role not found! - {config['Prefix']}role `") 103 | await ctx.send(embed=embed) 104 | return 105 | if isinstance(error, MemberNotFound): 106 | embed = discord.Embed( 107 | description=f"🔴 **ERROR**: `Member not found!`") 108 | await ctx.send(embed=embed) 109 | return 110 | raise error 111 | 112 | logging.info("------------- Loading -------------") 113 | for fn in listdir("Commands"): 114 | if fn.endswith(".py"): 115 | logging.info(f"Loading: {fn}") 116 | Client.load_extension(f"Commands.{fn[:-3]}") 117 | logging.info(f"Loaded {fn}") 118 | 119 | for fn in listdir("Addons"): 120 | if fn.endswith(".py"): 121 | logging.info(f"Loading: {fn} Addon") 122 | Client.load_extension(f"Addons.{fn[:-3]}") 123 | logging.info(f"Loaded {fn} Addon") 124 | 125 | for fn in listdir("System"): 126 | if fn.endswith(".py"): 127 | logging.info(f"Loading: {fn} System") 128 | Client.load_extension(f"System.{fn[:-3]}") 129 | logging.info(f"Loaded {fn} System") 130 | logging.info("------------- Finished Loading -------------") 131 | 132 | # Uses the bot token to login, so don't remove this. 133 | token = os.getenv("DISCORD_TOKEN") 134 | Client.ipc.start() 135 | Client.run(token) 136 | 137 | 138 | # End Of Main -------------------------------------------------------------------------------- /Configs/config.yml: -------------------------------------------------------------------------------- 1 | # ====================================================================================== 2 | # WELCOME TO THE CONFIG 3 | # FOR 4 | # MODERN LEVELS 2.0 5 | # ====================================================================================== 6 | 7 | # NOTE: BOT_TOKEN DETAILS ARE STORED IN THE .env FILE! 8 | # The prefix for the bots commands 9 | Prefix: "!" 10 | 11 | # Determines the database type to use. Note: MongoDB requires the details to be stored inside the .env file! **Note: Local is recommended** 12 | # MongoDB / Local 13 | Database_Type: "mongodb" 14 | 15 | # Member ID of the bot owner (In most cases, whoever is reading this sentence right now AKA you.) **YOU WILL RECEIVE ERRORS IF THIS IS NOT FILLED** 16 | Bot_Owner: "512760269764820993" 17 | 18 | # How the bot adds users to the database when the bot starts 19 | # startup - Adds all missing users to the database when the bot starts (Recommended for those with smaller member amounts - Not great performance for large servers) 20 | # message - Adds users to the database once they send a message (Recommended for those with any member amounts - Better performance for large servers) 21 | loader_type: "message" 22 | 23 | # The default background for each user when they get added to the database || Please do not leave this as nothing!! If you get errors, it means the url is invalid. 24 | # I recommend using imgur to get the link for your background. 25 | Default_Background: "https://coolbackgrounds.io/images/backgrounds/black/pure-black-background-f82588d3.jpg" 26 | 27 | # Default XP Colour for each user when they get added to the database 28 | Default_XP_Colour: "#ffffff" 29 | 30 | # The default border for the users profile picture on the rank card **ONLY IF THE RANK GENERATOR IS CUSTOM!!** 31 | Default_Border: "https://coolbackgrounds.io/images/backgrounds/black/pure-black-background-f82588d3.jpg" 32 | 33 | # Enables / Disables the help command (true = enabled, false = disabled) 34 | help_command: True 35 | 36 | # Notifies the bot owner when a new version is released (Bot_Owner must be filled) 37 | update_notify: True 38 | 39 | # If XP Chance is enabled or disabled (true = enabled, false = disabled) 40 | XP_Chance: True 41 | 42 | # Chance to earn XP when a user sends a message (Chance Rate, 1 to x) - If number = x, user gains xp 43 | XP_Chance_Rate: 2 44 | 45 | 46 | # ====================================================================================== 47 | # XP 48 | # ====================================================================================== 49 | 50 | # XP Type 'words' = User xp increases by how many words were said, 51 | # 'ranrange' = User xp increases by a random number between the min and max 52 | # 'normal' = User xp increases by set value 53 | xp_type: 'ranrange' 54 | 55 | # The amount of xp a user gets when they send a message -- This is only used if the xp_type is set to 'normal' 56 | xp_normal_amount: 10 57 | 58 | # The minimum amount of xp a user can gain -- This is only used if the xp_type is set to 'ranrange' 59 | xp_ranrange_min: 5 60 | 61 | # The maximum amount of xp a user can gain -- This is only used if the xp_type is set to 'ranrange' 62 | xp_ranrange_max: 50 63 | 64 | # How much XP is required per level (e.g - xp_per_level: 10 = Level 1 would require 10 xp to level up. Level 2 would require 20 xp to level up) 65 | xp_per_level: 100 66 | 67 | 68 | # ====================================================================================== 69 | # LEADERBOARD 70 | # ====================================================================================== 71 | 72 | # Set aliases for the leaderboard command 73 | leaderboard_alias: ['lb', 'leader', 'rankings'] 74 | 75 | 76 | # ====================================================================================== 77 | # RANK 78 | # ====================================================================================== 79 | # Sets aliases for the rank command **DO NOT ADD 'RANK' AS AN ALIAS, RANK IS THE MAIN NAME FOR THE COMMAND!** 80 | rank_alias: ['r', 'level', 'l', 'stats', 'xp', 'progress'] 81 | 82 | # Sends a ping to the user that levelled up 83 | level_up_ping: True 84 | 85 | # The background image for the level up card 86 | level_up_background: "https://wallpaperaccess.com/full/4956346.jpg" 87 | 88 | # The amount of blur on the background image for the level up card 89 | level_up_blur: 10 90 | 91 | # RankCard Generator (Vacefron, Custom, Text) 92 | # 'Vacefron' - Uses the Vacefron rank card generator (The API may go down occasionally, or you can be rate limited) 1050 x 300 93 | # 'Custom' - Uses the custom rank card generator (Will never go down / be rate limited) - 1050 x 240 - Can be most resource intensive at times 94 | # 'Text' - Uses the text rank card generator (Will never go down / be rate limited) - Most resource light 95 | rank_generator: 'custom' 96 | 97 | # If the rank generator is set to custom, the name of the user on the rank card is the colour of the users xp colour **ONLY IF RANK GENERATOR IS CUSTOM!!** 98 | name_colour: True 99 | 100 | 101 | # ====================================================================================== 102 | # EMBED 103 | # ====================================================================================== 104 | 105 | 106 | # Note Below these have not been fully implemented, in 2.0.1, they will be! 107 | 108 | # Rank Embed Colour | Must Be Hex Notation 109 | rank_embed_colour: 0x4863A0 110 | 111 | # Leaderboard Embed Colour | Must Be Hex Notation (Replace # with 0x) 112 | leaderboard_embed_colour: 0xffffff 113 | 114 | # Embed Colour | Must Be Hex Notation 115 | embed_colour: 0xffffff 116 | 117 | # Error Embed Colour | Must Be Hex Notation 118 | error_embed_colour: 0x4863A0 119 | 120 | # Success Embed Colour | Must Be Hex Notation 121 | success_embed_colour: 0x4863A0 122 | 123 | 124 | # ====================================================================================== 125 | # THE END 126 | # ====================================================================================== 127 | -------------------------------------------------------------------------------- /KumosLab/Database/remove.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sqlite3 3 | 4 | import discord 5 | from pymongo import MongoClient 6 | from ruamel import yaml 7 | 8 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 9 | config = yaml.load(file) 10 | 11 | 12 | if config['Database_Type'].lower() == 'mongodb': 13 | MONGODB_URI = os.environ['MONGODB_URI'] 14 | COLLECTION = os.getenv("COLLECTION") 15 | DB_NAME = os.getenv("DATABASE_NAME") 16 | cluster = MongoClient(MONGODB_URI) 17 | levelling = cluster[COLLECTION][DB_NAME] 18 | 19 | async def xp(user: discord.Member = None, guild: discord.Guild = None, amount=None): 20 | if user is None: 21 | print("Error in 'KumosLab/Database/remove.py' - User is None for 'xp'") 22 | return 23 | if guild is None: 24 | print("Error in 'KumosLab/Database/remove.py' - Guild is None for 'xp'") 25 | return 26 | if amount is None: 27 | print("Error in 'KumosLab/Database/remove.py' - Amount is None for 'xp'") 28 | return 29 | try: 30 | if config['Database_Type'].lower() == "mongodb": 31 | user_search = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 32 | if user_search is None: 33 | print("User Not Found!") 34 | return 35 | # add xp 36 | levelling.update_one({'user_id': user.id, 'guild_id': guild.id}, {'$inc': {'xp': - amount}}) 37 | return 38 | elif config['Database_Type'].lower() == "local": 39 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 40 | cursor = db.cursor() 41 | cursor.execute("SELECT xp FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 42 | result = cursor.fetchone() 43 | if result is None: 44 | print("User Not Found!") 45 | return 46 | # add xp 47 | cursor.execute("UPDATE levelling SET xp = xp - ? WHERE user_id = ? AND guild_id = ?", (amount, user.id, guild.id)) 48 | db.commit() 49 | cursor.close() 50 | return 51 | except Exception as e: 52 | print("Error in 'KumosLab/Database/remove.py' - " + str(e)) 53 | return 54 | 55 | async def level(user: discord.Member = None, guild: discord.Guild = None, amount=None): 56 | if user is None: 57 | print("Error in 'KumosLab/Database/remove.py' - User is None for 'level'") 58 | return 59 | if guild is None: 60 | print("Error in 'KumosLab/Database/remove.py' - Guild is None for 'level'") 61 | return 62 | if amount is None: 63 | print("Error in 'KumosLab/Database/remove.py' - Amount is None for 'level'") 64 | return 65 | try: 66 | if config['Database_Type'].lower() == "mongodb": 67 | member = levelling.find_one({'user_id': user.id, 'guild': guild.id}) 68 | if member is None: 69 | print("User Not Found!") 70 | return 71 | # add level 72 | levelling.update_one({'user_id': user.id, 'guild_id': guild.id}, {'$inc': {'level': - amount}}) 73 | return 74 | elif config['Database_Type'].lower() == "local": 75 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 76 | cursor = db.cursor() 77 | cursor.execute("SELECT level FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 78 | result = cursor.fetchone() 79 | if result is None: 80 | print("User Not Found!") 81 | return 82 | # add level 83 | cursor.execute("UPDATE levelling SET level = level - ? WHERE user_id = ? AND guild_id = ?", (amount, user.id, guild.id)) 84 | db.commit() 85 | cursor.close() 86 | return 87 | except Exception as e: 88 | print("Error in 'KumosLab/Database/remove.py' - " + str(e)) 89 | return 90 | 91 | async def role(guild: discord.Guild = None, role_name: discord.Role = None, role_level: int = None): 92 | if guild is None: 93 | print("Error in 'KumosLab/Database/remove.py' - Guild is None for 'role'") 94 | return 95 | if role is None: 96 | print("Error in 'KumosLab/Database/remove.py' - Role is None for 'role'") 97 | return 98 | if role_level is None: 99 | print("Error in 'KumosLab/Database/remove.py' - Role_Level is None for 'role'") 100 | return 101 | try: 102 | if config['Database_Type'].lower() == "mongodb": 103 | # add role 104 | levelling.update_one({'guild': guild.id}, {'$pull': {'roles': role_name.name, 'role_levels': int(role_level)}}) 105 | return 106 | elif config['Database_Type'].lower() == "local": 107 | db = sqlite3.connect("KumosLab/Database/Local/roles.sqlite") 108 | cursor = db.cursor() 109 | # delete guild, role and level 110 | cursor.execute("DELETE FROM levelling WHERE guild_id = ? AND role = ? AND role_levels = ?", (guild.id, role_name.name, role_level)) 111 | db.commit() 112 | cursor.close() 113 | return 114 | except Exception as e: 115 | print("Error in 'KumosLab/Database/remove.py' - " + str(e)) 116 | return 117 | 118 | async def talkchannel(guild: discord.Guild = None, channel: discord.TextChannel = None): 119 | if guild is None: 120 | print("Error in 'KumosLab/Database/add.py' - Guild is None for 'talkchannel'") 121 | return 122 | if channel is None: 123 | print("Error in 'KumosLab/Database/add.py' - channel is None for 'talkchannel'") 124 | return 125 | try: 126 | if config['Database_Type'].lower() == "mongodb": 127 | # find if role is already in database 128 | talk_db = levelling.find_one({'guild': guild.id, 'talkchannels': channel.id}) 129 | if talk_db is None: 130 | return "error" 131 | levelling.update_one({'guild': guild.id}, {'$pull': {'talkchannels': channel.id}}) 132 | return 133 | elif config['Database_Type'].lower() == "local": 134 | db = sqlite3.connect("KumosLab/Database/Local/serverbase.sqlite") 135 | cursor = db.cursor() 136 | # set talkchannels to none 137 | cursor.execute("UPDATE levelling SET talkchannels = ? WHERE guild_id = ?", (None, guild.id)) 138 | db.commit() 139 | cursor.close() 140 | return 141 | except Exception as e: 142 | print("Error in 'KumosLab/Database/remove.py' - " + str(e)) 143 | return 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /Commands/help.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | import discord 4 | from discord.ext import commands 5 | from ruamel.yaml import YAML 6 | import KumosLab.Database.get 7 | import KumosLab.Database.set 8 | 9 | import os 10 | 11 | yaml = YAML() 12 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 13 | config = yaml.load(file) 14 | 15 | # Help Class 16 | class helpcommand(commands.Cog): 17 | def __init__(self, client): 18 | self.client = client 19 | 20 | @commands.command() 21 | async def help(self, ctx, value: str = None): 22 | try: 23 | prefix = config["Prefix"] 24 | if config['help_command'] is True: 25 | if value is None: 26 | embed = discord.Embed( 27 | title=f"{self.client.user.name}'s Command List") 28 | embed.set_thumbnail(url=self.client.user.avatar_url) 29 | embed.add_field(name="📷 Profile", value=f"`Profile Customisation`") 30 | embed.add_field(name="😃 Fun", value=f"`Fun Commands`") 31 | if ctx.author.guild_permissions.administrator: 32 | embed.add_field(name="🔧 Admin", value=f"`Admin Commands`") 33 | if ctx.author.id == int(config["Bot_Owner"]): 34 | embed.add_field(name="💼 Owner", value=f"`Owner Commands`") 35 | if os.path.isfile("Addons/Extras.py"): 36 | embed.add_field(name="🔗 Extras", value=f"`Extra Commands`") 37 | 38 | msg = await ctx.reply(embed=embed) 39 | await msg.add_reaction("📷") 40 | await msg.add_reaction("😃") 41 | if ctx.author.id == int(config["Bot_Owner"]): 42 | await msg.add_reaction("💼") 43 | if ctx.author.guild_permissions.administrator: 44 | await msg.add_reaction("🔧") 45 | if os.path.isfile("Addons/Extras.py"): 46 | await msg.add_reaction("🔗") 47 | 48 | def check(reaction, user): 49 | return user == ctx.author and reaction.message.id == msg.id 50 | 51 | try: 52 | reaction, user = await self.client.wait_for('reaction_add', timeout=60.0, check=check) 53 | if reaction.emoji == "📷": 54 | # remove all reactions 55 | await msg.clear_reactions() 56 | embed = discord.Embed(title="📷 Profile Commands", description="```background, setblur, setcolour, setborder```") 57 | embed.add_field(name="Examples:", value=f"```🖼️ {prefix}background - Changes your Rank Card background\n" 58 | f"⚪ {prefix}setcolour <#hex|random> - Sets your XP Bar to the chosen HEX code\n" 59 | f"👁️ {prefix}setblur - Blurs your Rank Cards background\n" 60 | f"🖼️ {prefix}setborder - Changes your Rank Cards profile picture border```") 61 | await msg.edit(embed=embed) 62 | elif reaction.emoji == "🔧": 63 | # remove all reactions 64 | await msg.clear_reactions() 65 | embed = discord.Embed(title="🔧 Admin Commands", description="```role, mainchannel, talkchannel, creator```") 66 | embed.add_field(name="Examples:", value=f"```🔨 {prefix}role <@role> - Adds or removes a role from being unlocked at a certain level\n" 67 | f"📢 {prefix}mainchannel <@channel> - Sets the main channel for level up and other sorts\n" 68 | f"🗣️ {prefix}talkchannel <@channel> - Adds or removes a channel that allows xp gain\n" 69 | f"🔧 {prefix}creator - Auto-create roles for the amount and adds to database```") 70 | await msg.edit(embed=embed) 71 | 72 | elif reaction.emoji == "💼": 73 | # remove all reactions 74 | await msg.clear_reactions() 75 | embed = discord.Embed(title="💼 Owner Commands", description="```addon, addons```") 76 | embed.add_field(name="Examples:", value=f"```🔨 {prefix}addon - Installs an addon\n" 77 | f"🔨 {prefix}addons - Lists all installed addons```") 78 | await msg.edit(embed=embed) 79 | elif reaction.emoji == "😃": 80 | # remove all reactions 81 | await msg.clear_reactions() 82 | embed = discord.Embed(title="😃 Fun Commands", description="```rank, leaderboard, roles, talkchannels```") 83 | embed.add_field(name="Examples:", value=f"```🏆 {prefix}rank <@user> - Displays the users Rank Card\n" 84 | f"📊 {prefix}leaderboard - Displays the rankings of all users in the guild or global\n" 85 | f"🔒 {prefix}roles - Displays all the roles you can unlock for levelling up\n" 86 | f"🗣️ {prefix}talkchannels - Displays all the channels that allow xp gain```") 87 | await msg.edit(embed=embed) 88 | elif reaction.emoji == "🔗": 89 | # remove all reactions 90 | await msg.clear_reactions() 91 | embed = discord.Embed(title="🔗 Extras", description="```addxp, removexp```") 92 | embed.add_field(name="Examples:", value=f"```🔧 {prefix}addxp <@user> - Adds XP to a user\n" 93 | f"🔧 {prefix}removexp <@user> - Removes XP from a user```") 94 | await msg.edit(embed=embed) 95 | 96 | 97 | 98 | 99 | except asyncio.TimeoutError: 100 | await msg.delete() 101 | 102 | 103 | except Exception as e: 104 | print(f"[Help Command] {e}") 105 | 106 | 107 | 108 | # Sets-up the cog for help 109 | def setup(client): 110 | client.add_cog(helpcommand(client)) -------------------------------------------------------------------------------- /KumosLab/Database/Create/Leaderboard/Local/leaderboard.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import sqlite3 3 | 4 | import discord 5 | from discord.ext import commands 6 | from ruamel.yaml import YAML 7 | import KumosLab.Database.conversion as conversion 8 | 9 | 10 | yaml = YAML() 11 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 12 | config = yaml.load(file) 13 | 14 | async def leaderboard(self=None, ctx=None, guild=None, leader_type=None): 15 | if self is None: 16 | print("[Leaderboard-Local] Self is None") 17 | return 18 | if ctx is None: 19 | print("[Leaderboard-Local] Context is None") 20 | return 21 | if guild is None: 22 | print("[Leaderboard-Local] Guild is None") 23 | return 24 | if leader_type is None: 25 | print("[Leaderboard-Local] Type is None") 26 | return 27 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 28 | cursor = db.cursor() 29 | # sort by xp desc 30 | if leader_type.lower() == "local": 31 | cursor.execute( 32 | "SELECT * FROM levelling WHERE guild_id = ? ORDER BY xp DESC", (guild.id,)) 33 | result = cursor.fetchall() 34 | embed = discord.Embed(title=f":trophy: {guild}'s Leaderboard", colour=config['leaderboard_embed_colour']) 35 | else: 36 | cursor.execute("SELECT * FROM levelling ORDER BY xp DESC") 37 | result = cursor.fetchall() 38 | embed = discord.Embed(title=f"🌎 Global Leaderboard", colour=config['leaderboard_embed_colour']) 39 | if result is None: 40 | return "Server Not Found!" 41 | 42 | users = [] 43 | level = [] 44 | xp = [] 45 | guild = [] 46 | 47 | for x in result: 48 | users.append(x[1]) 49 | level.append(x[3]) 50 | xp.append(x[4]) 51 | guild_obj = self.client.get_guild(x[2]) 52 | guild.append(guild_obj.name) 53 | 54 | pagination = list(zip(users, level, xp, guild)) 55 | pages = [pagination[i:i + 10] for i in range(0, len(pagination), 10)] 56 | page = 0 57 | num = 0 58 | user_list = [] 59 | level_list = [] 60 | xp_list = [] 61 | guild_list = [] 62 | for i in pages: 63 | embed.clear_fields() 64 | for users, levels, xp, guild in i: 65 | num += 1 66 | if leader_type.lower() == "local": 67 | embed.add_field(name=f"#{num}: {users}", value=f"```Level: {levels:,} - {conversion.translate(xp)} XP```", inline=True) 68 | else: 69 | embed.add_field(name=f"#{num}: {users} - {guild}", value=f"```Level: {levels:,} - {conversion.translate(xp)} XP```", inline=True) 70 | embed.set_footer(text=f"Page {page + 1}/{len(pages)}") 71 | message = await ctx.send(embed=embed) 72 | page += 1 73 | await message.add_reaction("⬅") 74 | await message.add_reaction("➡") 75 | await message.add_reaction("❌") 76 | 77 | while True: 78 | def check(reaction, user): 79 | return user == ctx.author and str(reaction.emoji) in ["⬅", "➡", "❌"] and reaction.message.id == message.id 80 | 81 | try: 82 | reaction, user = await ctx.bot.wait_for("reaction_add", timeout=60.0, check=check) 83 | 84 | if str(reaction.emoji) == "⬅": 85 | if page == 1: 86 | pass 87 | else: 88 | page -= 1 89 | embed.clear_fields() 90 | for users, levels, xp, guild in pages[page - 1]: 91 | num -= 1 92 | user_list.append(users) 93 | level_list.append(levels) 94 | xp_list.append(xp) 95 | guild_list.append(guild) 96 | for x in range(0, len(user_list)): 97 | if leader_type.lower() == "local": 98 | embed.add_field(name=f"#{x + 1 + num - len(user_list)}: {user_list[x]}", 99 | value=f"```Level {level_list[x]:,} - {conversion.translate(xp_list[x])} XP```", inline=True) 100 | else: 101 | embed.add_field( 102 | name=f"#{x + 1 + num - len(user_list)}: {user_list[x]} - {guild_list[x]}", 103 | value=f"```Level {level_list[x]:,} - {conversion.translate(xp_list[x])} XP```", 104 | inline=True) 105 | user_list.clear() 106 | level_list.clear() 107 | xp_list.clear() 108 | guild_list.clear() 109 | embed.set_footer(text=f"Page {page}/{len(pages)}") 110 | await message.edit(embed=embed) 111 | await message.remove_reaction("⬅", user) 112 | await message.remove_reaction("➡", user) 113 | await message.remove_reaction("❌", user) 114 | elif str(reaction.emoji) == "➡": 115 | if page == 1: 116 | pass 117 | else: 118 | page += 1 119 | embed.clear_fields() 120 | for users, levels, xp, guild in pages[page - 1]: 121 | num += 1 122 | user_list.append(users) 123 | level_list.append(levels) 124 | xp_list.append(xp) 125 | guild_list.append(guild) 126 | for x in range(0, len(user_list)): 127 | if leader_type.lower() == "local": 128 | embed.add_field(name=f"#{x + 1 + num - len(user_list)}: {user_list[x]}", 129 | value=f"```Level {level_list[x]:,} - {conversion.translate(xp_list[x])} XP```", 130 | inline=True) 131 | else: 132 | embed.add_field( 133 | name=f"#{x + 1 + num - len(user_list)}: {user_list[x]} - {guild_list[x]}", 134 | value=f"```Level {level_list[x]:,} - {conversion.translate(xp_list[x])} XP```", 135 | inline=True) 136 | user_list.clear() 137 | level_list.clear() 138 | xp_list.clear() 139 | guild_list.clear() 140 | embed.set_footer(text=f"Page {page}/{len(pages)}") 141 | await message.edit(embed=embed) 142 | await message.remove_reaction("⬅", user) 143 | await message.remove_reaction("➡", user) 144 | await message.remove_reaction("❌", user) 145 | elif str(reaction.emoji) == "❌": 146 | await message.delete() 147 | return 148 | except asyncio.TimeoutError: 149 | await message.delete() 150 | return 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /KumosLab/Database/Create/Leaderboard/MongoDB/leaderboard.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import os 3 | import sqlite3 4 | 5 | import discord 6 | from discord.ext import commands 7 | from pymongo import MongoClient 8 | from ruamel.yaml import YAML 9 | import KumosLab.Database.conversion as conversion 10 | 11 | 12 | 13 | yaml = YAML() 14 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 15 | config = yaml.load(file) 16 | 17 | if config['Database_Type'].lower() == 'mongodb': 18 | MONGODB_URI = os.environ['MONGODB_URI'] 19 | COLLECTION = os.getenv("COLLECTION") 20 | DB_NAME = os.getenv("DATABASE_NAME") 21 | cluster = MongoClient(MONGODB_URI) 22 | levelling = cluster[COLLECTION][DB_NAME] 23 | 24 | async def leaderboard(self=None, ctx=None, guild=None, leader_type=None): 25 | if self is None: 26 | print("[Leaderboard-MongoDB] Self is None") 27 | return 28 | if ctx is None: 29 | print("[Leaderboard-MongoDB] Context is None") 30 | return 31 | if guild is None: 32 | print("[Leaderboard-MongoDB] Guild is None") 33 | return 34 | if leader_type is None: 35 | print("[Leaderboard-MongoDB] Leaderboard Type is None") 36 | return 37 | 38 | if leader_type.lower() == 'local': 39 | result = levelling.find({"guild_id": ctx.guild.id, "xp": {"$exists": True}}).sort( 40 | "xp", -1) 41 | embed = discord.Embed(title=f":trophy: {guild}'s Leaderboard", colour=config['leaderboard_embed_colour']) 42 | else: 43 | result = levelling.find({"xp": {"$exists": True}}).sort( 44 | "xp", -1) 45 | embed = discord.Embed(title=f"🌎 Global Leaderboard", colour=config['leaderboard_embed_colour']) 46 | 47 | if result is None: 48 | print("Server Not Found!") 49 | 50 | users = [] 51 | level = [] 52 | xp = [] 53 | guild = [] 54 | 55 | for x in result: 56 | users.append(x["name"]) 57 | level.append(x["level"]) 58 | xp.append(x["xp"]) 59 | # get guild object and append the name to the list 60 | guild.append(self.client.get_guild(x["guild_id"])) 61 | 62 | pagination = list(zip(users, level, xp, guild)) 63 | pages = [pagination[i:i + 10] for i in range(0, len(pagination), 10)] 64 | page = 0 65 | num = 0 66 | user_list = [] 67 | level_list = [] 68 | xp_list = [] 69 | guild_list = [] 70 | for i in pages: 71 | embed.clear_fields() 72 | for users, levels, xp, guild in i: 73 | num += 1 74 | if leader_type.lower() == 'local': 75 | embed.add_field(name=f"#{num}: {users}", value=f"```Level: {levels:,} - {conversion.translate(xp)} XP```", inline=True) 76 | else: 77 | embed.add_field(name=f"#{num}: {users} - {guild}", value=f"```Level: {levels:,} - {conversion.translate(xp)} XP```", inline=True) 78 | embed.set_footer(text=f"Page {page + 1}/{len(pages)}") 79 | message = await ctx.send(embed=embed) 80 | page += 1 81 | await message.add_reaction("⬅") 82 | await message.add_reaction("➡") 83 | await message.add_reaction("❌") 84 | 85 | while True: 86 | def check(reaction, user): 87 | return user == ctx.author and str(reaction.emoji) in ["⬅", "➡", "❌"] and reaction.message.id == message.id 88 | 89 | try: 90 | reaction, user = await ctx.bot.wait_for("reaction_add", timeout=60.0, check=check) 91 | 92 | if str(reaction.emoji) == "⬅": 93 | if page == 1: 94 | pass 95 | else: 96 | page -= 1 97 | embed.clear_fields() 98 | for users, levels, xp, guild in pages[page - 1]: 99 | num -= 1 100 | user_list.append(users) 101 | level_list.append(levels) 102 | xp_list.append(xp) 103 | guild_list.append(guild) 104 | for x in range(0, len(user_list)): 105 | if leader_type.lower() == 'local': 106 | embed.add_field(name=f"#{x + 1 + num - len(user_list)}: {user_list[x]}", 107 | value=f"```Level: {level_list[x]:,} - {conversion.translate(xp_list[x])} XP```", inline=True) 108 | else: 109 | embed.add_field(name=f"#{x + 1 + num - len(user_list)}: {user_list[x]} - {guild_list[x]}", 110 | value=f"```Level: {level_list[x]:,} - {conversion.translate(xp_list[x])} XP```", 111 | inline=True) 112 | user_list.clear() 113 | level_list.clear() 114 | xp_list.clear() 115 | guild_list.clear() 116 | embed.set_footer(text=f"Page {page}/{len(pages)}") 117 | await message.edit(embed=embed) 118 | await message.remove_reaction("⬅", user) 119 | await message.remove_reaction("➡", user) 120 | await message.remove_reaction("❌", user) 121 | elif str(reaction.emoji) == "➡": 122 | if page == len(pages): 123 | pass 124 | else: 125 | page += 1 126 | embed.clear_fields() 127 | for users, levels, xp, guild in pages[page - 1]: 128 | num += 1 129 | user_list.append(users) 130 | level_list.append(levels) 131 | xp_list.append(xp) 132 | guild_list.append(guild) 133 | for x in range(0, len(user_list)): 134 | if leader_type.lower() == 'local': 135 | embed.add_field(name=f"#{x + 1 + num - len(user_list)}: {user_list[x]}", 136 | value=f"```Level: {level_list[x]:,} - {conversion.translate(xp_list[x])} XP```", 137 | inline=True) 138 | else: 139 | embed.add_field( 140 | name=f"#{x + 1 + num - len(user_list)}: {user_list[x]} - {guild_list[x]}", 141 | value=f"```Level: {level_list[x]:,} - {conversion.translate(xp_list[x])} XP```", 142 | inline=True) 143 | user_list.clear() 144 | level_list.clear() 145 | xp_list.clear() 146 | guild_list.clear() 147 | embed.set_footer(text=f"Page {page}/{len(pages)}") 148 | await message.edit(embed=embed) 149 | await message.remove_reaction("⬅", user) 150 | await message.remove_reaction("➡", user) 151 | await message.remove_reaction("❌", user) 152 | elif str(reaction.emoji) == "❌": 153 | await message.delete() 154 | return 155 | except asyncio.TimeoutError: 156 | await message.delete() 157 | return 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /System/levelsystem.py: -------------------------------------------------------------------------------- 1 | # Imports 2 | import random 3 | 4 | from discord.ext import commands 5 | from pymongo import MongoClient 6 | from ruamel.yaml import YAML 7 | import os 8 | from dotenv import load_dotenv 9 | import sqlite3 10 | 11 | import KumosLab.Database.get 12 | import KumosLab.Database.set 13 | import KumosLab.Database.add 14 | import KumosLab.Database.check 15 | import KumosLab.Database.insert 16 | 17 | yaml = YAML() 18 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 19 | config = yaml.load(file) 20 | 21 | # Loads the .env file and gets the required information 22 | load_dotenv() 23 | if config['Database_Type'].lower() == 'mongodb': 24 | MONGODB_URI = os.environ['MONGODB_URI'] 25 | COLLECTION = os.getenv("COLLECTION") 26 | DB_NAME = os.getenv("DATABASE_NAME") 27 | cluster = MongoClient(MONGODB_URI) 28 | levelling = cluster[COLLECTION][DB_NAME] 29 | 30 | 31 | class levelsys(commands.Cog): 32 | def __init__(self, client): 33 | self.client = client 34 | 35 | @commands.Cog.listener() 36 | async def on_message(self, ctx): 37 | if not ctx.author.bot: 38 | if ctx.content.startswith(config["Prefix"]): 39 | return 40 | 41 | if config['loader_type'].lower() == 'message': 42 | user_check = await KumosLab.Database.get.xp(user=ctx.author, guild=ctx.guild) 43 | if user_check == "User Not Found!": 44 | await KumosLab.Database.insert.userField(member=ctx.author, guild=ctx.guild) 45 | 46 | if config['XP_Chance'] is True: 47 | chance_rate = config['XP_Chance_Rate'] 48 | random_num = random.randint(1, chance_rate) 49 | if random_num != chance_rate: 50 | return 51 | 52 | channels = await KumosLab.Database.get.talkchannels(guild=ctx.guild) 53 | channel_Array = [] 54 | channel_List = [] 55 | for channel in channels: 56 | channel_Array.append(channel) 57 | if len(channel_Array) < 1 or channel_Array[0] is None: 58 | pass 59 | else: 60 | for x in channel_Array: 61 | channel = self.client.get_channel(int(x)) 62 | channel_List.append(channel.name) 63 | 64 | if str(channel_List) == "[]": 65 | pass 66 | elif channel_List is not None: 67 | if ctx.channel.name in channel_List: 68 | pass 69 | else: 70 | return 71 | 72 | xp_type = config['xp_type'] 73 | if xp_type.lower() == "normal": 74 | to_add = config['xp_normal_amount'] 75 | await KumosLab.Database.add.xp(user=ctx.author, guild=ctx.guild, amount=to_add) 76 | elif xp_type.lower() == "words": 77 | # get the length of the message 78 | res = len(ctx.content.split()) 79 | message_length = int(res) 80 | await KumosLab.Database.add.xp(user=ctx.author, guild=ctx.guild, amount=message_length) 81 | elif xp_type.lower() == "ranrange": 82 | # get ranges from config 83 | min = config['xp_ranrange_min'] 84 | max = config['xp_ranrange_max'] 85 | num = random.randint(min, max) 86 | await KumosLab.Database.add.xp(user=ctx.author, guild=ctx.guild, amount=num) 87 | 88 | await KumosLab.Database.check.levelUp(user=ctx.author, guild=ctx.guild) 89 | 90 | # on guild join 91 | @commands.Cog.listener() 92 | async def on_guild_join(self, guild): 93 | # get database type from config file 94 | db_type = config["Database_Type"] 95 | if db_type.lower() == "mongodb": 96 | levelling.insert_one({"guild": guild.id, "main_channel": None, "admin_role": None, "roles": [], 97 | "role_levels": [], 'talkchannels': []}) 98 | for member in guild.members: 99 | # check if member is a bot 100 | if not member.bot: 101 | levelling.insert_one( 102 | {"guild_id": guild.id, "user_id": member.id, "name": str(member), "level": 1, "xp": 0, 103 | "background": config['Default_Background'], "xp_colour": config['Default_XP_Colour'], 104 | "blur": 0, "border": config['Default_Border']}) 105 | elif db_type.lower() == "local": 106 | db = sqlite3.connect("KumosLab/Database/Local/serverbase.sqlite") 107 | cursor = db.cursor() 108 | sql = "INSERT INTO levelling (guild_id, admin_role, main_channel, talkchannels) VALUES (?, ?, ?, ?)" 109 | val = (guild.id, None, None, None) 110 | cursor.execute(sql, val) 111 | db.commit() 112 | for member in guild.members: 113 | # check if member is a bot 114 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 115 | cursor = db.cursor() 116 | if not member.bot: 117 | sql = "INSERT INTO levelling (guild_id, user_id, name, level, xp, background, xp_colour, blur, border) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" 118 | val = ( 119 | guild.id, member.id, str(member), 1, 0, config['Default_Background'], config['Default_XP_Colour'], 120 | 0, config['Default_Border']) 121 | cursor.execute(sql, val) 122 | db.commit() 123 | else: 124 | continue 125 | cursor.close() 126 | 127 | # on guild leave 128 | @commands.Cog.listener() 129 | async def on_guild_remove(self, guild): 130 | # get database type from config file 131 | db_type = config["Database_Type"] 132 | if db_type.lower() == "mongodb": 133 | levelling.delete_one({"guild": guild.id}) 134 | for member in guild.members: 135 | levelling.delete_one({"guild_id": guild.id, "user_id": member.id}) 136 | elif db_type.lower() == "local": 137 | db = sqlite3.connect("KumosLab/Database/Local/serverbase.sqlite") 138 | cursor = db.cursor() 139 | sql = "DELETE FROM levelling WHERE guild_id = ?" 140 | val = (guild.id,) 141 | cursor.execute(sql, val) 142 | db.commit() 143 | cursor.close() 144 | for member in guild.members: 145 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 146 | cursor = db.cursor() 147 | sql = "DELETE FROM levelling WHERE guild_id = ? AND user_id = ?" 148 | val = (guild.id, member.id) 149 | cursor.execute(sql, val) 150 | db.commit() 151 | cursor.close() 152 | 153 | # on member join 154 | @commands.Cog.listener() 155 | async def on_member_join(self, member): 156 | await KumosLab.Database.insert.userField(member=member, guild=member.guild) 157 | 158 | # on member leave 159 | @commands.Cog.listener() 160 | async def on_member_remove(self, member): 161 | # get database type from config file 162 | db_type = config["Database_Type"] 163 | if db_type.lower() == "mongodb": 164 | levelling.delete_one({"guild_id": member.guild.id, "user_id": member.id}) 165 | elif db_type.lower() == "local": 166 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 167 | cursor = db.cursor() 168 | sql = "DELETE FROM levelling WHERE guild_id = ? AND user_id = ?" 169 | val = (member.guild.id, member.id) 170 | cursor.execute(sql, val) 171 | db.commit() 172 | cursor.close() 173 | 174 | 175 | def setup(client): 176 | client.add_cog(levelsys(client)) 177 | 178 | # End Of Level System 179 | -------------------------------------------------------------------------------- /KumosLab/Database/add.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sqlite3 3 | 4 | import discord 5 | from pymongo import MongoClient 6 | from ruamel import yaml 7 | 8 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 9 | config = yaml.load(file) 10 | 11 | 12 | # check if clan.py in addon folder 13 | if os.path.isfile("Addons/clan.py"): 14 | with open("Configs/clan_addon.yml", "r", encoding="utf-8") as file: 15 | clan_config = yaml.load(file) 16 | 17 | 18 | if config['Database_Type'].lower() == 'mongodb': 19 | MONGODB_URI = os.environ['MONGODB_URI'] 20 | COLLECTION = os.getenv("COLLECTION") 21 | DB_NAME = os.getenv("DATABASE_NAME") 22 | cluster = MongoClient(MONGODB_URI) 23 | levelling = cluster[COLLECTION][DB_NAME] 24 | 25 | async def xp(user: discord.Member = None, guild: discord.Guild = None, amount=None): 26 | if user is None: 27 | print("Error in 'KumosLab/Database/add.py' - User is None for 'xp'") 28 | return 29 | if guild is None: 30 | print("Error in 'KumosLab/Database/add.py' - Guild is None for 'xp'") 31 | return 32 | if amount is None: 33 | print("Error in 'KumosLab/Database/add.py' - Amount is None for 'xp'") 34 | return 35 | try: 36 | if config['Database_Type'].lower() == "mongodb": 37 | user_find = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 38 | if user_find is None: 39 | print("User Not Found!") 40 | return 41 | # add xp 42 | levelling.update_one({'user_id': user.id, 'guild_id': guild.id}, {'$inc': {'xp': + amount}}) 43 | return 44 | elif config['Database_Type'].lower() == "local": 45 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 46 | cursor = db.cursor() 47 | cursor.execute("SELECT xp FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 48 | result = cursor.fetchone() 49 | if result is None: 50 | print("User Not Found!") 51 | return 52 | # add xp 53 | cursor.execute("UPDATE levelling SET xp = xp + ? WHERE user_id = ? AND guild_id = ?", (amount, user.id, guild.id)) 54 | db.commit() 55 | cursor.close() 56 | return 57 | except Exception as e: 58 | print("Error in 'KumosLab/Database/add.py' - " + str(e)) 59 | return 60 | 61 | async def level(user: discord.Member = None, guild: discord.Guild = None, amount=None): 62 | if user is None: 63 | print("Error in 'KumosLab/Database/add.py' - User is None for 'level'") 64 | return 65 | if guild is None: 66 | print("Error in 'KumosLab/Database/add.py' - Guild is None for 'level'") 67 | return 68 | if amount is None: 69 | print("Error in 'KumosLab/Database/add.py' - Amount is None for 'level'") 70 | return 71 | try: 72 | if config['Database_Type'].lower() == "mongodb": 73 | member = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 74 | if member is None: 75 | print("User Not Found!") 76 | return 77 | # add level 78 | levelling.update_one({'user_id': user.id, 'guild_id': guild.id}, {'$inc': {'level': + amount}}) 79 | return 80 | elif config['Database_Type'].lower() == "local": 81 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 82 | cursor = db.cursor() 83 | cursor.execute("SELECT level FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 84 | result = cursor.fetchone() 85 | if result is None: 86 | print("User Not Found!") 87 | return 88 | # add level 89 | cursor.execute("UPDATE levelling SET level = level + ? WHERE user_id = ? AND guild_id = ?", (amount, user.id, guild.id)) 90 | db.commit() 91 | cursor.close() 92 | return 93 | except Exception as e: 94 | print("Error in 'KumosLab/Database/add.py' - " + str(e)) 95 | return 96 | 97 | async def role(guild: discord.Guild = None, role_name: discord.Role = None, role_level: int = None): 98 | if guild is None: 99 | print("Error in 'KumosLab/Database/add.py' - Guild is None for 'role'") 100 | return 101 | if role is None: 102 | print("Error in 'KumosLab/Database/add.py' - Role is None for 'role'") 103 | return 104 | if role_level is None: 105 | print("Error in 'KumosLab/Database/add.py' - Role_Level is None for 'role'") 106 | return 107 | try: 108 | if config['Database_Type'].lower() == "mongodb": 109 | # find if role is already in database 110 | role_db = levelling.find_one({'guild': guild.id, 'role_name': role_name.name}) 111 | if role_db is not None: 112 | return "error" 113 | # add role 114 | levelling.update_one({'guild': guild.id}, {'$push': {'roles': role_name.name, 'role_levels': int(role_level)}}) 115 | return 116 | elif config['Database_Type'].lower() == "local": 117 | db = sqlite3.connect("KumosLab/Database/Local/roles.sqlite") 118 | cursor = db.cursor() 119 | # find if role is already in database 120 | cursor.execute("SELECT * FROM levelling WHERE guild_id = ? AND role = ?", (guild.id, role_name.name)) 121 | result = cursor.fetchone() 122 | if result is not None: 123 | return "error" 124 | # insert guild, role and level 125 | cursor.execute("INSERT INTO levelling (guild_id, role, role_levels) VALUES (?, ?, ?)", (guild.id, role_name.name, role_level)) 126 | db.commit() 127 | cursor.close() 128 | return 129 | except Exception as e: 130 | print("Error in 'KumosLab/Database/add.py' - " + str(e)) 131 | return 132 | 133 | async def talkchannel(guild: discord.Guild = None, channel: discord.TextChannel = None): 134 | if guild is None: 135 | print("Error in 'KumosLab/Database/add.py' - Guild is None for 'talkchannel'") 136 | return 137 | if channel is None: 138 | print("Error in 'KumosLab/Database/add.py' - Talk_Channel is None for 'talkchannel'") 139 | return 140 | try: 141 | if config['Database_Type'].lower() == "mongodb": 142 | talk_db = levelling.find_one({'guild': guild.id, 'talkchannels': channel.id}) 143 | if talk_db is not None: 144 | return "error" 145 | levelling.update_one({'guild': guild.id}, {'$push': {'talkchannels': channel.id}}) 146 | return 147 | elif config['Database_Type'].lower() == "local": 148 | db = sqlite3.connect("KumosLab/Database/Local/serverbase.sqlite") 149 | cursor = db.cursor() 150 | cursor.execute("SELECT * FROM levelling WHERE guild_id = ? AND talkchannels = ?", (guild.id, channel.id)) 151 | result = cursor.fetchone() 152 | if result is not None: 153 | return "error" 154 | # update talkchannels to add channel to list 155 | cursor.execute("UPDATE levelling SET talkchannels = ? WHERE guild_id = ?", (channel.id, guild.id)) 156 | db.commit() 157 | cursor.close() 158 | return 159 | except Exception as e: 160 | print("Error in 'KumosLab/Database/add.py' - " + str(e)) 161 | return 162 | 163 | async def clan(guild: discord.Guild = None, clan_name: str = None, owner: discord.Member = None): 164 | if guild is None: 165 | print("Error in 'KumosLab/Database/add.py' - Guild is None for 'clan'") 166 | return 167 | if clan_name is None: 168 | print("Error in 'KumosLab/Database/add.py' - Clan Name is None for 'clan'") 169 | return 170 | if owner is None: 171 | print("Error in 'KumosLab/Database/add.py' - Owner is None for 'clan'") 172 | return 173 | try: 174 | if config['Database_Type'].lower() == "mongodb": 175 | role_db = levelling.find_one({'clans_guild': guild.id, 'clan_name': clan_name}) 176 | if role_db is not None: 177 | return "error" 178 | levelling.insert_one({'clans_guild': guild.id, 'clan_name': clan_name, 'owner': owner.id, 'members': [owner.id], 'level': 1, 'xp': 0, 'logo': clan_config['default_logo'], 'colour': clan_config['default_colour']}) 179 | return 180 | elif config['Database_Type'].lower() == "local": 181 | db = sqlite3.connect("KumosLab/Database/Local/clans.sqlite") 182 | cursor = db.cursor() 183 | cursor.execute("SELECT * FROM levelling WHERE clans_guild = ? AND clan_name = ?", (guild.id, clan_name)) 184 | result = cursor.fetchone() 185 | if result is not None: 186 | return "error" 187 | cursor.execute("INSERT INTO levelling (clans_guild, clan_name, owner, members, level, xp, logo, colour) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", (guild.id, clan_name, str(owner.id), owner.id, 1, 0, clan_config['default_logo'], clan_config['default_colour'])) 188 | db.commit() 189 | cursor.close() 190 | return 191 | except Exception as e: 192 | print("Error in 'KumosLab/Database/add.py' - " + str(e)) 193 | return 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /KumosLab/Database/set.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sqlite3 3 | 4 | import discord 5 | from pymongo import MongoClient 6 | from ruamel import yaml 7 | 8 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 9 | config = yaml.load(file) 10 | 11 | 12 | if config['Database_Type'].lower() == 'mongodb': 13 | MONGODB_URI = os.environ['MONGODB_URI'] 14 | COLLECTION = os.getenv("COLLECTION") 15 | DB_NAME = os.getenv("DATABASE_NAME") 16 | cluster = MongoClient(MONGODB_URI) 17 | levelling = cluster[COLLECTION][DB_NAME] 18 | 19 | async def xp(user: discord.Member = None, guild: discord.Guild = None, amount=None): 20 | if user is None: 21 | print("Error in 'KumosLab/Database/set.py' - User is None for 'xp'") 22 | return 23 | if guild is None: 24 | print("Error in 'KumosLab/Database/set.py' - Guild is None for 'xp'") 25 | return 26 | if amount is None: 27 | print("Error in 'KumosLab/Database/set.py' - Amount is None for 'xp'") 28 | return 29 | try: 30 | if config['Database_Type'].lower() == "mongodb": 31 | member = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 32 | if member is None: 33 | print("User Not Found!") 34 | return 35 | # add xp 36 | levelling.update_one({'user_id': user.id, 'guild_id': guild.id}, {'$set': {'xp': amount}}) 37 | return 38 | elif config['Database_Type'].lower() == "local": 39 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 40 | cursor = db.cursor() 41 | cursor.execute("SELECT xp FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 42 | result = cursor.fetchone() 43 | if result is None: 44 | print("User Not Found!") 45 | return 46 | # add xp 47 | cursor.execute("UPDATE levelling SET xp = ? WHERE user_id = ? AND guild_id = ?", (amount, user.id, guild.id)) 48 | db.commit() 49 | cursor.close() 50 | return 51 | except Exception as e: 52 | print("Error in 'KumosLab/Database/add.py' - " + str(e)) 53 | return 54 | 55 | async def level(user: discord.Member = None, guild: discord.Guild = None, amount=None): 56 | if user is None: 57 | print("Error in 'KumosLab/Database/set.py' - User is None for 'level'") 58 | return 59 | if guild is None: 60 | print("Error in 'KumosLab/Database/set.py' - Guild is None for 'level'") 61 | return 62 | if amount is None: 63 | print("Error in 'KumosLab/Database/set.py' - Amount is None for 'level'") 64 | return 65 | try: 66 | if config['Database_Type'].lower() == "mongodb": 67 | member = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 68 | if member is None: 69 | print("User Not Found!") 70 | return 71 | # add level 72 | levelling.update_one({'user_id': user.id, 'guild_id': guild.id}, {'$set': {'level': amount}}) 73 | return 74 | elif config['Database_Type'].lower() == "local": 75 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 76 | cursor = db.cursor() 77 | cursor.execute("SELECT level FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 78 | result = cursor.fetchone() 79 | if result is None: 80 | print("User Not Found!") 81 | return 82 | # add level 83 | cursor.execute("UPDATE levelling SET level = ? WHERE user_id = ? AND guild_id = ?", (amount, user.id, guild.id)) 84 | db.commit() 85 | cursor.close() 86 | return 87 | except Exception as e: 88 | print("Error in 'KumosLab/Database/set.py' - " + str(e)) 89 | return 90 | 91 | async def background(user: discord.Member = None, guild: discord.Guild = None, link=None): 92 | if user is None: 93 | print("Error in 'KumosLab/Database/set.py' - User is None for 'background'") 94 | return 95 | if guild is None: 96 | print("Error in 'KumosLab/Database/set.py' - Guild is None for 'background'") 97 | return 98 | if link is None: 99 | print("Error in 'KumosLab/Database/set.py' - Link is None for 'background'") 100 | return 101 | try: 102 | if config['Database_Type'].lower() == "mongodb": 103 | member = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 104 | if member is None: 105 | print("User Not Found!") 106 | return 107 | # add background 108 | levelling.update_one({'user_id': user.id, 'guild_id': guild.id}, {'$set': {'background': link}}) 109 | return 110 | elif config['Database_Type'].lower() == "local": 111 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 112 | cursor = db.cursor() 113 | cursor.execute("SELECT background FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 114 | result = cursor.fetchone() 115 | if result is None: 116 | print("User Not Found!") 117 | return 118 | # add level 119 | cursor.execute("UPDATE levelling SET background = ? WHERE user_id = ? AND guild_id = ?", (link, user.id, guild.id)) 120 | db.commit() 121 | cursor.close() 122 | return 123 | except Exception as e: 124 | print("Error in 'KumosLab/Database/set.py' - " + str(e)) 125 | return 126 | 127 | async def border(user: discord.Member = None, guild: discord.Guild = None, link=None): 128 | if user is None: 129 | print("Error in 'KumosLab/Database/set.py' - User is None for 'border'") 130 | return 131 | if guild is None: 132 | print("Error in 'KumosLab/Database/set.py' - Guild is None for 'border'") 133 | return 134 | if link is None: 135 | print("Error in 'KumosLab/Database/set.py' - Link is None for 'border'") 136 | return 137 | try: 138 | if config['Database_Type'].lower() == "mongodb": 139 | member = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 140 | if member is None: 141 | print("User Not Found!") 142 | return 143 | # add border 144 | levelling.update_one({'user_id': user.id, 'guild_id': guild.id}, {'$set': {'border': link}}) 145 | return 146 | elif config['Database_Type'].lower() == "local": 147 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 148 | cursor = db.cursor() 149 | cursor.execute("SELECT border FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 150 | result = cursor.fetchone() 151 | if result is None: 152 | print("User Not Found!") 153 | return 154 | # add level 155 | cursor.execute("UPDATE levelling SET border = ? WHERE user_id = ? AND guild_id = ?", (link, user.id, guild.id)) 156 | db.commit() 157 | cursor.close() 158 | return 159 | except Exception as e: 160 | print("Error in 'KumosLab/Database/set.py' - " + str(e)) 161 | return 162 | 163 | async def colour(user: discord.Member = None, guild: discord.Guild = None, hex=None): 164 | if user is None: 165 | print("Error in 'KumosLab/Database/set.py' - User is None for 'colour'") 166 | return 167 | if guild is None: 168 | print("Error in 'KumosLab/Database/set.py' - Guild is None for 'colour'") 169 | return 170 | if hex is None: 171 | print("Error in 'KumosLab/Database/set.py' - Hex is None for 'colour'") 172 | return 173 | try: 174 | if config['Database_Type'].lower() == "mongodb": 175 | member = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 176 | if member is None: 177 | print("User Not Found!") 178 | return 179 | # add background 180 | levelling.update_one({'user_id': user.id, 'guild_id': guild.id}, {'$set': {'xp_colour': hex}}) 181 | return 182 | elif config['Database_Type'].lower() == "local": 183 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 184 | cursor = db.cursor() 185 | cursor.execute("SELECT xp_colour FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 186 | result = cursor.fetchone() 187 | if result is None: 188 | print("User Not Found!") 189 | return 190 | # add level 191 | cursor.execute("UPDATE levelling SET xp_colour = ? WHERE user_id = ? AND guild_id = ?", (hex, user.id, guild.id)) 192 | db.commit() 193 | cursor.close() 194 | return 195 | except Exception as e: 196 | print("Error in 'KumosLab/Database/set.py' - " + str(e)) 197 | return 198 | 199 | async def blur(user: discord.Member = None, guild: discord.Guild = None, amount=None): 200 | if user is None: 201 | print("Error in 'KumosLab/Database/set.py' - User is None for 'blur'") 202 | return 203 | if guild is None: 204 | print("Error in 'KumosLab/Database/set.py' - Guild is None for 'blur'") 205 | return 206 | if amount is None: 207 | print("Error in 'KumosLab/Database/set.py' - Amount is None for 'blur'") 208 | return 209 | try: 210 | if config['Database_Type'].lower() == "mongodb": 211 | member = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 212 | if member is None: 213 | print("User Not Found!") 214 | return 215 | # add background 216 | levelling.update_one({'user_id': user.id, 'guild_id': guild.id}, {'$set': {'blur': amount}}) 217 | return 218 | elif config['Database_Type'].lower() == "local": 219 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 220 | cursor = db.cursor() 221 | cursor.execute("SELECT blur FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 222 | result = cursor.fetchone() 223 | if result is None: 224 | print("User Not Found!") 225 | return 226 | # add level 227 | cursor.execute("UPDATE levelling SET blur = ? WHERE user_id = ? AND guild_id = ?", (amount, user.id, guild.id)) 228 | db.commit() 229 | cursor.close() 230 | return 231 | except Exception as e: 232 | print("Error in 'KumosLab/Database/set.py' - " + str(e)) 233 | return 234 | 235 | async def mainChannel(guild: discord.Guild = None, channel: discord.TextChannel = None): 236 | if guild is None: 237 | print("Error in 'KumosLab/Database/set.py' - Guild is None for 'mainChannel'") 238 | return 239 | if channel is None: 240 | print("Error in 'KumosLab/Database/set.py' - Channel is None for 'mainChannel'") 241 | return 242 | try: 243 | if config['Database_Type'].lower() == "mongodb": 244 | levelling.update_one({'guild': guild.id}, {'$set': {'main_channel': channel.name}}) 245 | return 246 | elif config['Database_Type'].lower() == "local": 247 | db = sqlite3.connect("KumosLab/Database/Local/serverbase.sqlite") 248 | cursor = db.cursor() 249 | cursor.execute("UPDATE levelling SET main_channel = ? WHERE guild_id = ?", (channel.name, guild.id)) 250 | db.commit() 251 | cursor.close() 252 | return 253 | except Exception as e: 254 | print("Error in 'KumosLab/Database/set.py' - " + str(e)) 255 | return 256 | 257 | 258 | 259 | 260 | 261 | -------------------------------------------------------------------------------- /KumosLab/Database/get.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sqlite3 3 | import urllib.request 4 | import json 5 | 6 | import discord 7 | from pymongo import MongoClient 8 | from ruamel import yaml 9 | 10 | with open("Configs/config.yml", "r", encoding="utf-8") as file: 11 | config = yaml.load(file) 12 | 13 | 14 | if config['Database_Type'].lower() == 'mongodb': 15 | MONGODB_URI = os.environ['MONGODB_URI'] 16 | COLLECTION = os.getenv("COLLECTION") 17 | DB_NAME = os.getenv("DATABASE_NAME") 18 | cluster = MongoClient(MONGODB_URI) 19 | levelling = cluster[COLLECTION][DB_NAME] 20 | 21 | async def xp(user: discord.Member = None, guild: discord.Guild = None): 22 | if user is None: 23 | print("Error in 'KumosLab/Database/get.py' - User is None for 'xp'") 24 | return 25 | if guild is None: 26 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'xp'") 27 | return 28 | try: 29 | if config['Database_Type'].lower() == "mongodb": 30 | member = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 31 | if user is None: 32 | return "User Not Found!" 33 | return member['xp'] 34 | elif config['Database_Type'].lower() == "local": 35 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 36 | cursor = db.cursor() 37 | cursor.execute("SELECT xp FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 38 | result = cursor.fetchone() 39 | if result is None: 40 | return "User Not Found!" 41 | cursor.close() 42 | return result[0] 43 | 44 | except Exception as e: 45 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 46 | return 47 | 48 | async def background(user: discord.Member = None, guild: discord.Guild = None): 49 | if user is None: 50 | print("Error in 'KumosLab/Database/get.py' - User is None for 'background'") 51 | return 52 | if guild is None: 53 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'background'") 54 | return 55 | try: 56 | if config['Database_Type'].lower() == "mongodb": 57 | member = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 58 | if member is None: 59 | print("User Not Found!") 60 | return 61 | return member['background'] 62 | elif config['Database_Type'].lower() == "local": 63 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 64 | cursor = db.cursor() 65 | cursor.execute("SELECT background FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 66 | result = cursor.fetchone() 67 | if result is None: 68 | print("User Not Found!") 69 | return 70 | cursor.close() 71 | return result[0] 72 | except Exception as e: 73 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 74 | return 75 | 76 | async def border(user: discord.Member = None, guild: discord.Guild = None): 77 | if user is None: 78 | print("Error in 'KumosLab/Database/get.py' - User is None for 'border'") 79 | return 80 | if guild is None: 81 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'border'") 82 | return 83 | try: 84 | if config['Database_Type'].lower() == "mongodb": 85 | member = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 86 | if member is None: 87 | print("User Not Found!") 88 | return 89 | return member['border'] 90 | elif config['Database_Type'].lower() == "local": 91 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 92 | cursor = db.cursor() 93 | cursor.execute("SELECT border FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 94 | result = cursor.fetchone() 95 | if result is None: 96 | print("User Not Found!") 97 | return 98 | cursor.close() 99 | return result[0] 100 | except Exception as e: 101 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 102 | return 103 | 104 | async def colour(user: discord.Member = None, guild: discord.Guild = None): 105 | if user is None: 106 | print("Error in 'KumosLab/Database/get.py' - User is None for 'background'") 107 | return 108 | if guild is None: 109 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'background'") 110 | return 111 | try: 112 | if config['Database_Type'].lower() == "mongodb": 113 | member = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 114 | if member is None: 115 | print("User Not Found!") 116 | return 117 | return member['xp_colour'] 118 | elif config['Database_Type'].lower() == "local": 119 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 120 | cursor = db.cursor() 121 | cursor.execute("SELECT xp_colour FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 122 | result = cursor.fetchone() 123 | if result is None: 124 | print("User Not Found!") 125 | return 126 | cursor.close() 127 | return result[0] 128 | except Exception as e: 129 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 130 | return 131 | 132 | async def blur(user: discord.Member = None, guild: discord.Guild = None): 133 | if user is None: 134 | print("Error in 'KumosLab/Database/get.py' - User is None for 'blur'") 135 | return 136 | if guild is None: 137 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'blur'") 138 | return 139 | try: 140 | if config['Database_Type'].lower() == "mongodb": 141 | member = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 142 | if member is None: 143 | print("User Not Found!") 144 | return 145 | return member['blur'] 146 | elif config['Database_Type'].lower() == "local": 147 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 148 | cursor = db.cursor() 149 | cursor.execute("SELECT blur FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 150 | result = cursor.fetchone() 151 | if result is None: 152 | print("User Not Found!") 153 | return 154 | cursor.close() 155 | return result[0] 156 | except Exception as e: 157 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 158 | return 159 | 160 | 161 | async def level(user: discord.Member = None, guild: discord.Guild = None): 162 | if user is None: 163 | print("Error in 'KumosLab/Database/get.py' - User is None for 'level'") 164 | return 165 | if guild is None: 166 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'level'") 167 | return 168 | try: 169 | if config['Database_Type'].lower() == "mongodb": 170 | member = levelling.find_one({'user_id': user.id, 'guild_id': guild.id}) 171 | if member is None: 172 | print("User Not Found!") 173 | return 174 | return member['level'] 175 | elif config['Database_Type'].lower() == "local": 176 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 177 | cursor = db.cursor() 178 | cursor.execute("SELECT level FROM levelling WHERE user_id = ? AND guild_id = ?", (user.id, guild.id)) 179 | result = cursor.fetchone() 180 | if result is None: 181 | print("User Not Found!") 182 | return 183 | cursor.close() 184 | return result[0] 185 | except Exception as e: 186 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 187 | return 188 | 189 | async def rankings(user: discord.Member = None, guild: discord.Guild = None): 190 | if guild is None: 191 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'rankings'") 192 | return 193 | try: 194 | if config['Database_Type'].lower() == "mongodb": 195 | stats = levelling.find_one({"guild_id": guild.id, "user_id": user.id}) 196 | rankings = levelling.find({"guild_id": guild.id}).sort("xp", -1) 197 | rank = 0 198 | for x in rankings: 199 | rank += 1 200 | if stats["user_id"] == x["user_id"]: 201 | break 202 | return rank 203 | elif config['Database_Type'].lower() == "local": 204 | db = sqlite3.connect("KumosLab/Database/Local/userbase.sqlite") 205 | cursor = db.cursor() 206 | rankings = cursor.execute("SELECT * FROM levelling WHERE guild_id = ? ORDER BY xp DESC", (guild.id,)) 207 | rank = 0 208 | for x in rankings: 209 | rank += 1 210 | if user.id == x[0]: 211 | break 212 | cursor.close() 213 | return rank 214 | except Exception as e: 215 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 216 | return 217 | 218 | async def mainChannel(guild: discord.Guild = None): 219 | if guild is None: 220 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'mainChannel'") 221 | return 222 | try: 223 | if config['Database_Type'].lower() == "mongodb": 224 | server = levelling.find_one({"guild": guild.id}) 225 | if server is None: 226 | print("Server Not Found!") 227 | return 228 | return server["main_channel"] 229 | elif config['Database_Type'].lower() == "local": 230 | db = sqlite3.connect("KumosLab/Database/Local/serverbase.sqlite") 231 | cursor = db.cursor() 232 | cursor.execute("SELECT main_channel FROM levelling WHERE guild_id = ?", (guild.id,)) 233 | result = cursor.fetchone() 234 | if result is None: 235 | print("Server Not Found!") 236 | return 237 | cursor.close() 238 | return result[0] 239 | except Exception as e: 240 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 241 | return 242 | 243 | async def roles(guild: discord.Guild = None): 244 | if guild is None: 245 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'roles'") 246 | return 247 | try: 248 | if config['Database_Type'].lower() == "mongodb": 249 | server = levelling.find_one({"guild": guild.id}) 250 | if server is None: 251 | print("Server Not Found!") 252 | return 253 | return server["roles"] 254 | elif config['Database_Type'].lower() == "local": 255 | db = sqlite3.connect("KumosLab/Database/Local/roles.sqlite") 256 | cursor = db.cursor() 257 | # get all roles 258 | cursor.execute("SELECT role FROM levelling WHERE guild_id = ?", (guild.id,)) 259 | result = cursor.fetchall() 260 | if result is None: 261 | print("Server Not Found!") 262 | return 263 | cursor.close() 264 | return result 265 | except Exception as e: 266 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 267 | return 268 | 269 | async def roleLevel(guild: discord.Guild = None): 270 | if guild is None: 271 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'roleLevel'") 272 | return 273 | try: 274 | if config['Database_Type'].lower() == "mongodb": 275 | server = levelling.find_one({"guild": guild.id}) 276 | if server is None: 277 | print("Server Not Found!") 278 | return 279 | return server["role_levels"] 280 | elif config['Database_Type'].lower() == "local": 281 | db = sqlite3.connect("KumosLab/Database/Local/roles.sqlite") 282 | cursor = db.cursor() 283 | cursor.execute("SELECT role_levels FROM levelling WHERE guild_id = ?", (guild.id,)) 284 | result = cursor.fetchall() 285 | if result is None: 286 | print("Server Not Found!") 287 | return 288 | cursor.close() 289 | # convert to an int array 290 | return [int(x[0]) for x in result] 291 | 292 | except Exception as e: 293 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 294 | return 295 | 296 | async def talkchannels(guild: discord.Guild = None): 297 | if guild is None: 298 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'talkchannels'") 299 | return 300 | try: 301 | if config['Database_Type'].lower() == "mongodb": 302 | server = levelling.find_one({"guild": guild.id}) 303 | if server is None: 304 | print("Server Not Found!") 305 | return 306 | return server["talkchannels"] 307 | elif config['Database_Type'].lower() == "local": 308 | db = sqlite3.connect("KumosLab/Database/Local/serverbase.sqlite") 309 | cursor = db.cursor() 310 | cursor.execute("SELECT talkchannels FROM levelling WHERE guild_id = ?", (guild.id,)) 311 | result = cursor.fetchall() 312 | if result is None: 313 | print("Server Not Found!") 314 | return 315 | cursor.close() 316 | # convert to an int array 317 | return [x[0] for x in result] 318 | 319 | except Exception as e: 320 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 321 | return 322 | 323 | async def clan(guild: discord.Guild = None, clan_Name: str = None): 324 | if guild is None: 325 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'clan'") 326 | return 327 | if clan_Name is None: 328 | print("Error in 'KumosLab/Database/get.py' - Clan Name is None for 'clan'") 329 | return 330 | try: 331 | if config['Database_Type'].lower() == "mongodb": 332 | server = levelling.find_one({"clans_guild": guild.id, "clan_name": clan_Name}) 333 | if server is None: 334 | return "error" 335 | return server["clan_name"] 336 | elif config['Database_Type'].lower() == "local": 337 | db = sqlite3.connect("KumosLab/Database/Local/clans.sqlite") 338 | cursor = db.cursor() 339 | cursor.execute("SELECT clan_Name FROM levelling WHERE clans_guild = ? AND clan_name = ?", (guild.id, clan_Name)) 340 | result = cursor.fetchone() 341 | if result is None: 342 | return "error" 343 | cursor.close() 344 | return result[0] 345 | 346 | except Exception as e: 347 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 348 | return 349 | 350 | async def clanXP(guild: discord.Guild = None, clan_Name: str = None): 351 | if guild is None: 352 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'clanXP'") 353 | return 354 | if clan_Name is None: 355 | print("Error in 'KumosLab/Database/get.py' - Clan Name is None for 'clanXP'") 356 | return 357 | try: 358 | if config['Database_Type'].lower() == "mongodb": 359 | server = levelling.find_one({"clans_guild": guild.id, "clan_name": clan_Name}) 360 | if server is None: 361 | return "error" 362 | return server["xp"] 363 | elif config['Database_Type'].lower() == "local": 364 | db = sqlite3.connect("KumosLab/Database/Local/clans.sqlite") 365 | cursor = db.cursor() 366 | cursor.execute("SELECT xp FROM levelling WHERE clans_guild = ? AND clan_name = ?", (guild.id, clan_Name)) 367 | result = cursor.fetchone() 368 | if result is None: 369 | return "error" 370 | cursor.close() 371 | return result[0] 372 | 373 | except Exception as e: 374 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 375 | return 376 | 377 | async def clanOwner(guild: discord.Guild = None, clan_Name: str = None): 378 | if guild is None: 379 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'clanXP'") 380 | return 381 | if clan_Name is None: 382 | print("Error in 'KumosLab/Database/get.py' - Clan Name is None for 'clanXP'") 383 | return 384 | try: 385 | if config['Database_Type'].lower() == "mongodb": 386 | server = levelling.find_one({"clans_guild": guild.id, "clan_name": clan_Name}) 387 | if server is None: 388 | return "error" 389 | return server["owner"] 390 | elif config['Database_Type'].lower() == "local": 391 | db = sqlite3.connect("KumosLab/Database/Local/clans.sqlite") 392 | cursor = db.cursor() 393 | cursor.execute("SELECT owner FROM levelling WHERE clans_guild = ? AND clan_name = ?", (guild.id, clan_Name)) 394 | result = cursor.fetchone() 395 | if result is None: 396 | return "error" 397 | cursor.close() 398 | client = discord.Client() 399 | return client.get_user(result[0]) 400 | 401 | except Exception as e: 402 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 403 | return 404 | 405 | async def clanLevel(guild: discord.Guild = None, clan_Name: str = None): 406 | if guild is None: 407 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'clanXP'") 408 | return 409 | if clan_Name is None: 410 | print("Error in 'KumosLab/Database/get.py' - Clan Name is None for 'clanXP'") 411 | return 412 | try: 413 | if config['Database_Type'].lower() == "mongodb": 414 | server = levelling.find_one({"clans_guild": guild.id, "clan_name": clan_Name}) 415 | if server is None: 416 | return "error" 417 | return server["level"] 418 | elif config['Database_Type'].lower() == "local": 419 | db = sqlite3.connect("KumosLab/Database/Local/clans.sqlite") 420 | cursor = db.cursor() 421 | cursor.execute("SELECT level FROM levelling WHERE clans_guild = ? AND clan_name = ?", (guild.id, clan_Name)) 422 | result = cursor.fetchone() 423 | if result is None: 424 | return "error" 425 | cursor.close() 426 | return result[0] 427 | 428 | except Exception as e: 429 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 430 | return 431 | 432 | async def clanLogo(guild: discord.Guild = None, clan_Name: str = None): 433 | if guild is None: 434 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'clanXP'") 435 | return 436 | if clan_Name is None: 437 | print("Error in 'KumosLab/Database/get.py' - Clan Name is None for 'clanXP'") 438 | return 439 | try: 440 | if config['Database_Type'].lower() == "mongodb": 441 | server = levelling.find_one({"clans_guild": guild.id, "clan_name": clan_Name}) 442 | if server is None: 443 | return "error" 444 | return server["logo"] 445 | elif config['Database_Type'].lower() == "local": 446 | db = sqlite3.connect("KumosLab/Database/Local/clans.sqlite") 447 | cursor = db.cursor() 448 | cursor.execute("SELECT logo FROM levelling WHERE clans_guild = ? AND clan_name = ?", (guild.id, clan_Name)) 449 | result = cursor.fetchone() 450 | if result is None: 451 | return "error" 452 | cursor.close() 453 | return result[0] 454 | 455 | except Exception as e: 456 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 457 | return 458 | 459 | async def clanColour(guild: discord.Guild = None, clan_Name: str = None): 460 | if guild is None: 461 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'clanXP'") 462 | return 463 | if clan_Name is None: 464 | print("Error in 'KumosLab/Database/get.py' - Clan Name is None for 'clanXP'") 465 | return 466 | try: 467 | if config['Database_Type'].lower() == "mongodb": 468 | server = levelling.find_one({"clans_guild": guild.id, "clan_name": clan_Name}) 469 | if server is None: 470 | return "error" 471 | return server["colour"] 472 | elif config['Database_Type'].lower() == "local": 473 | db = sqlite3.connect("KumosLab/Database/Local/clans.sqlite") 474 | cursor = db.cursor() 475 | cursor.execute("SELECT colour FROM levelling WHERE clans_guild = ? AND clan_name = ?", (guild.id, clan_Name)) 476 | result = cursor.fetchone() 477 | if result is None: 478 | return "error" 479 | cursor.close() 480 | return result[0] 481 | 482 | except Exception as e: 483 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 484 | return 485 | 486 | async def clanMembers(guild: discord.Guild = None, clan_Name: str = None): 487 | if guild is None: 488 | print("Error in 'KumosLab/Database/get.py' - Guild is None for 'clanXP'") 489 | return 490 | if clan_Name is None: 491 | print("Error in 'KumosLab/Database/get.py' - Clan Name is None for 'clanXP'") 492 | return 493 | try: 494 | if config['Database_Type'].lower() == "mongodb": 495 | server = levelling.find_one({"clans_guild": guild.id, "clan_name": clan_Name}) 496 | if server is None: 497 | return "error" 498 | return server["members"] 499 | elif config['Database_Type'].lower() == "local": 500 | db = sqlite3.connect("KumosLab/Database/Local/clans.sqlite") 501 | cursor = db.cursor() 502 | cursor.execute("SELECT members FROM levelling WHERE clans_guild = ? AND clan_name = ?", (guild.id, clan_Name)) 503 | result = cursor.fetchone() 504 | if result is None: 505 | return "error" 506 | cursor.close() 507 | return result[0] 508 | 509 | except Exception as e: 510 | print("Error in 'KumosLab/Database/get.py' - " + str(e)) 511 | return 512 | 513 | async def latestVersion(): 514 | with urllib.request.urlopen("https://api.github.com/repos/KumosLab/Discord-Levels-Bot/releases/latest") as url: 515 | data = json.loads(url.read().decode()) 516 | return data["tag_name"] 517 | 518 | 519 | 520 | 521 | 522 | --------------------------------------------------------------------------------