diff --git a/README.md b/README.md index 23e5de1..af4469d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # Welcome to Mecha -Mecha is an innovative bot powered by the [Voltage](https://github.com/EnokiUN/Voltage) framework, designed to enhance your server experience with a variety of interactive features. - ## Key Features - **Advanced Leveling System**: Foster community engagement through a sophisticated global leveling system that rewards user participation and interaction within the server. diff --git a/cogs/economy.py b/cogs/economy.py index 2e322b1..25b8483 100644 --- a/cogs/economy.py +++ b/cogs/economy.py @@ -1,11 +1,12 @@ -import voltage, json, random, pymongo, time, datetime, asyncio, motor -import motor.motor_asyncio -from functools import wraps -from voltage.ext import commands -from pymongo.mongo_client import MongoClient -from pymongo.server_api import ServerApi +import asyncio +import pymongo +import random +import revolt +import time +from revolt.ext import commands + +from main import MyClient -sep = "\n" def strfdelta(tdelta, fmt): d = {"days": tdelta.days} @@ -13,32 +14,7 @@ def strfdelta(tdelta, fmt): d["minutes"], d["seconds"] = divmod(rem, 60) return fmt.format(**d) -def limiter(cooldown: int, *, on_ratelimited = None, key = None): - cooldowns = {} - getter = key or (lambda ctx, *_1, **_2: ctx.author.id) - def wrapper(callback): - @wraps(callback) - async def wrapped(ctx, *args, **kwargs): - k = getter(ctx, *args, **kwargs) - v = (time.time() - cooldowns.get(k, 0)) - if v < cooldown and 0 > v: - if on_ratelimited: - return await on_ratelimited(ctx, -v, *args, **kwargs) - return - cooldowns[k] = time.time() + cooldown - return await callback(ctx, *args, **kwargs) - return wrapped - return wrapper - -with open("json/config.json", "r") as f: - config = json.load(f) - -DBclient = motor.motor_asyncio.AsyncIOMotorClient(config['MONGOURI']) - -db = DBclient["beta"] -userdb = db["users"] -serverdb = db["servers"] - +unusable_items = ["resume"] # Add more items if needed joblist = [ "Professional Couch Potato", "Chief Meme Officer", @@ -57,6 +33,7 @@ async def wrapped(ctx, *args, **kwargs): ] short_forms = [job[:3].lower() for job in joblist] + def match_job_to_short_form(job_name, short_forms, joblist): """ Return the full job name that corresponds to the given short form. @@ -72,80 +49,16 @@ def match_job_to_short_form(job_name, short_forms, joblist): except ValueError: return "Job not found." -async def add_user(user: voltage.User, isbot:bool=False): # long ass fucking function to add users to the database if they dont exist yet. but it works.. - if (await userdb.find_one({"userid": user.id})): - return "User already exists." - try: - await userdb.insert_one({ - "_id": userdb.count_documents({}) + 1, - "username": user.name, - "userid": user.id, - "levels": { - "xp": 0, - "level": 0, - "totalxp": 0, - "lastmessage": time.time() - }, - "prefixes": ["m!"], - "economy": { - "wallet": 0, - "bank": 0, - "total": 0, - "daily": time.time(), - "monthly": time.time(), - "data": { - "inventory": { - "Bank Loan": 1 - }, - "job": "unemployed" - }, - "buffs": { - "beginner_luck": 100 - }, - "debuffs": {}, - "achievements": { - "early_user": True, - "beta_tester": True - } - }, - "notifications": { - "inbox": { - "1":{ - "message": f"Welcome to Mecha, {user.name}!{sep}To get started, type `m!help` in this server to get started!", - "date": time.time(), - "title": "Welcome To Mecha!", - "type": "bot", - "read": False - } - } - }, - "status": { - "developer": False, - "admin": False, - "moderator": False, - "friend": False, - "premium": False, - "bug": False, - "beta": False, - "familyfriendly": False, - "isBot": isbot, - "banned": False, - "afk": {} - } - }) - return "Added" - except Exception as e: - return f"Sorry, An Error Occured!{sep}{sep}```{sep}{e}{sep}```" - -async def parse_amount(ctx, amount, bank=False): - user = (await userdb.find_one({"userid": ctx.author.id})) +# TODO: Turn this into a proper converter +async def parse_amount(ctx: commands.Context, amount: int, bank: bool = False): + user = await ctx.client.db_client.get_user(ctx.author) if bank: econ = user["economy"]["bank"] try: if "%" in amount: - if float(amount.replace("%", "")) > 100 and float(amount.replace("%", "")) <= 0: - embed = voltage.SendableEmbed( + if 100 < float(amount.replace("%", "")) <= 0: + embed = revolt.SendableEmbed( description="You can only withdraw up to 100%!", color="#FF0000", title="Error" @@ -163,7 +76,7 @@ async def parse_amount(ctx, amount, bank=False): return int(amount.replace(" ", "")) except ValueError: print(f"Error parsing amount: {amount}") - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( description="Invalid amount!", color="#FF0000", title="Error" @@ -171,7 +84,6 @@ async def parse_amount(ctx, amount, bank=False): await ctx.reply(embed=embed) return None - user = await userdb.find_one({"userid": ctx.author.id}) try: suffixes = { 'k': 1000, @@ -185,8 +97,8 @@ async def parse_amount(ctx, amount, bank=False): 'th': 100000 } if "%" in amount: - if float(amount.replace("%", "")) > 100 and float(amount.replace("%", "")) <= 0: - embed = voltage.SendableEmbed( + if 100 < float(amount.replace("%", "")) <= 0: + embed = revolt.SendableEmbed( description="You can only withdraw up to 100%!", color="#FF0000", title="Error" @@ -204,7 +116,7 @@ async def parse_amount(ctx, amount, bank=False): amount = int(amount) return amount except ValueError: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( description="Amount must be an integer or use k, m, h, or th suffixes for thousand, million, hundred, or hundred thousand respectively!", color="#FF0000", title="Error" @@ -213,33 +125,36 @@ async def parse_amount(ctx, amount, bank=False): return None -async def buy_item(ctx, item:str, price:int, amount:int): # this sucks but it works - if (await userdb.find_one({"userid": ctx.author.id})): +async def buy_item(ctx, item: str, price: int, amount: int): # this sucks but it works + user_data = await ctx.client.db_client.get_user(ctx.author) + userdb = ctx.client.db_client.userdb + if user_data: if amount < 1: return await ctx.reply("Amount must be greater than 0!") - userdata = (await userdb.find_one({"userid": ctx.author.id})) - if userdata['economy']['wallet'] < price: + if user_data['economy']['wallet'] < price: return await ctx.reply("You don't have enough money to purchase this!") - if item in userdata['economy']['data']['inventory']: + if item in user_data['economy']['data']['inventory']: await userdb.bulk_write([ pymongo.UpdateOne({"userid": ctx.author.id}, {"$inc": {"economy.wallet": -price}}), pymongo.UpdateOne({"userid": ctx.author.id}, {"$inc": {f"economy.data.inventory.{item.lower()}": amount}}) ]) else: - await userdb.bulk_write([ + await user_data.bulk_write([ pymongo.UpdateOne({"userid": ctx.author.id}, {"$inc": {f"economy.data.inventory.{item.lower()}": amount}}), pymongo.UpdateOne({"userid": ctx.author.id}, {"$inc": {"economy.wallet": -price}}) ]) return await ctx.reply(f"You bought **{item.capitalize()}** for **{price}** coins!") -async def apply_job(ctx, job:str): - if (await userdb.find_one({"userid": ctx.author.id})): - userdata = (await userdb.find_one({"userid": ctx.author.id})) - if "resume" in userdata['economy']['data']['inventory']: + +async def apply_job(ctx, job: str): + user_data = await ctx.client.db_client.get_user(ctx.author) + userdb = ctx.client.db_client.userdb + if user_data: + if "resume" in user_data['economy']['data']['inventory']: jobname = match_job_to_short_form(job.lower(), short_forms, joblist) if random.randint(1, 100) < 75: await userdb.update_one({"userid": ctx.author.id}, {"$set": {"economy.data.job": jobname}}) - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title="Application Accepted", description=f"You were accepted for **{jobname.capitalize()}**!", colour="#198754" @@ -250,9 +165,9 @@ async def apply_job(ctx, job:str): pymongo.UpdateOne({"userid": ctx.author.id}, {"$set": {"economy.data.job": "unemployed"}}), pymongo.UpdateOne({"userid": ctx.author.id}, {"$inc": {"economy.wallet": 250}}) ]) - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title="Application Rejected", - description=f"### :01HQ9JZ0Q1FMAKF6Y4Z2TZ58ZG:{sep}You were rejected for **{jobname.capitalize()}**{sep}You have received `250` coins as compensation!{sep}You are now unemployed..", + description=f"### :01HQ9JZ0Q1FMAKF6Y4Z2TZ58ZG:\nYou were rejected for **{jobname.capitalize()}**\nYou have received `250` coins as compensation!\nYou are now unemployed..", colour="#FF033E" ) return await ctx.reply(embed=embed) @@ -261,31 +176,34 @@ async def apply_job(ctx, job:str): else: return await ctx.reply("You don't have an account registered with me!") -def setup(client) -> commands.Cog: - eco = commands.Cog("Economy", "Wanna get rich! TOO BAD.") +async def create_account(ctx): + await ctx.send("You dont have a bank account registered in our database! I can register you now, is that okay? *(Yes/No)*") + try: + message = await client.wait_for("message", check=lambda message: message.author.id == ctx.author.id, timeout=15) + except asyncio.TimeoutError: + return await ctx.send(f"{ctx.author.mention} | Timed out! Please try again!") + if any(x in message.content.lower() for x in ["yes", "y", "yea", "yeah", "yup"]): + return await ctx.send(await ctx.client.db_client.add_user(ctx.author)) + else: + return await ctx.send("Oh... Nevermind then!") + - async def create_account(ctx): - await ctx.send("You dont have a bank account registered in our database! I can resgister you now, is that okay? *(Yes/No)*") - try: - message = await client.wait_for("message", check=lambda message: message.author.id != client.user.id, timeout=15) - except asyncio.TimeoutError: - return await ctx.send(f"{ctx.author.mention} | Timed out! Please try again!") - if any(x in message.content.lower() for x in ["yes", "y", "yea", "yeah", "yup"]): - return await ctx.send(await add_user(ctx.author)) - else: - return await ctx.send("Oh... Nevermind then!") +class Economy(commands.Cog): + def __init__(self, client: MyClient): + self.client: MyClient = client - @eco.command(description="View your balance.", aliases=["bal", 'b', 'money', 'mybal'], name="balance") - @limiter(5, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def bal(ctx, user:voltage.User=None): - if not user: - user = ctx.author - if (await userdb.find_one({"userid": user.id})): - items = 0 - userdata = (await userdb.find_one({"userid": user.id})) + @commands.command(aliases=["bal", 'b', 'money', 'mybal'], name="balance") + @commands.cooldown(1, 5, bucket=commands.BucketType.user) + async def bal(self, ctx, user: revolt.User = None): + """View your balance.""" + + user = user or ctx.author + user_data = await ctx.client.db_client.get_user(user) + if user_data: + items = [] try: - items = userdata['economy']['data']["inventory"] + items = user_data['economy']['data']["inventory"] itemlist = {} itemstuff = [] for item in items: @@ -297,25 +215,32 @@ async def bal(ctx, user:voltage.User=None): itemstuff.append(f"**{item}:** *x{itemlist[item]['amount']}*") except: items = [] + if len(items) == 0: items = ["You have no items :boohoo:"] - embed = voltage.SendableEmbed(title=f"{user.name}'s balance", icon_url=user.display_avatar.url, description=f"**Wallet Balance:**{sep}> \${round(userdata['economy']['wallet'], 2):,}{sep}{sep}**Bank Balance:**{sep}> \${round(userdata['economy']['bank'], 2):,}{sep}**Inventory:**{sep}> {f'{sep}> '.join(itemstuff)}", colour="#516BF2") + + embed = revolt.SendableEmbed( + title=f"{user.name}'s balance", icon_url=user.display_avatar.url if user.display_avatar else None, + description=f"**Wallet Balance:**\n> \\${round(user_data['economy']['wallet'], 2):,}\n\n**Bank Balance:**\n> \\${round(user_data['economy']['bank'], 2):,}\n**Inventory:**\n> {f'\n> '.join(itemstuff)}", + colour="#516BF2" + ) await ctx.send(embed=embed) else: await ctx.send( "You dont have a bank account registered in our database! Would you like me to create one?" ) - message = await client.wait_for("message", check=lambda message: message.author.id != client.user.id, timeout=15) + message = await client.wait_for( + "message", check=lambda message: message.author.id != client.user.id, timeout=15 + ) if any(x in message.content.lower() for x in ["yes", "y", "yea", "yeah", "yup"]): return await ctx.send(await add_user(ctx.author)) else: return await ctx.send("Oh... Nevermind then!") - @eco.command( - description="25% chance to get **nothing** and 75% to get up to 250 coins!" - ) - @limiter(15, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def beg(ctx): + @commands.command() + @commands.cooldown(1, 15, bucket=commands.BucketType.user) + async def beg(self, ctx): + """25% chance to get **nothing** and 75% to get up to 250 coins!""" amount = random.randint(1, 250) people = [ "Lea From Revolt", @@ -440,31 +365,33 @@ async def beg(ctx): "Imagine begging in 2024, gofundme is where it is at", ] percentage = random.randint(1, 100) - if not (await userdb.find_one({"userid": ctx.author.id})): - await create_account(ctx) - elif random.randint(1,200) == 1 or ctx.author.display_name.lower() == "mechahater": - embed = voltage.SendableEmbed( + user_data = await self.client.db_client.get_user(ctx.author) + if not user_data: + return await create_account(ctx) + + if random.randint(1, 200) == 1 or ctx.author.display_name.lower() == "mechahater": + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, description=f"YOU JUST GOT ROBBED! OH NO! THEY TOOK EVERYTHING IN YOUR WALLET WHADAFRICK!", - colour = "#FF0000" + colour="#FF0000" ) - await userdb.update_one( + await self.client.db_client.userdb.update_one( {"userid": ctx.author.id}, {"$set": {"economy.wallet": 0}}, ) return await ctx.reply(embed=embed) elif percentage > 25: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, description=f"{random.choice(people)} gave you `{round(amount, 2):,}` coins! Now get a job you bum.", color="#00FF00", ) - await userdb.update_one({"userid": ctx.author.id}, {"$inc": {"economy.wallet": amount}}) + await self.client.db_client.userdb.update_one({"userid": ctx.author.id}, {"$inc": {"economy.wallet": amount}}) return await ctx.send(embed=embed) else: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, description=f'"{random.choice(badline)}" -{random.choice(people)}', @@ -472,25 +399,27 @@ async def beg(ctx): ) return await ctx.send(embed=embed) - @eco.command(description="Go to work u bum **requires Resume**") - @limiter(60, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def work(ctx): + @commands.command() + @commands.cooldown(1, 60, bucket=commands.BucketType.user) + async def work(self, ctx): + """Go to work u bum **requires Resume**""" + amount = random.randint(500, 1000) - if not (await userdb.find_one({"userid": ctx.author.id})): - await create_account(ctx) - else: - userdata = (await userdb.find_one({"userid": ctx.author.id})) - if userdata['economy']['data']['job'] == "unemployed": + user_data = await self.client.db_client.get_user(ctx.author) + if not user_data: + return await create_account(ctx) + + if user_data['economy']['data']['job'] == "unemployed": return await ctx.send("You're unemployed, get a job u bum!") - elif "resume" in userdata['economy']['data']["inventory"]: - embed = voltage.SendableEmbed( + elif "resume" in user_data['economy']['data']["inventory"]: + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, description=f"You worked as a {userdata['economy']['data']['job']} and made `{amount}`!", color="#00FF00", ) await ctx.send(embed=embed) - await userdb.update_one( + await self.client.db_client.userdb.update_one( {"userid": ctx.author.id}, {"$inc": {"economy.wallet": amount}} ) else: @@ -498,31 +427,34 @@ async def work(ctx): "You need a `resume` to work, your not workin' here bub." ) - @eco.command(name="richest",aliases=["richlist", "richrank"], description="Check out the richest users in all of Mecha!") - @limiter(5, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def richest(ctx): + @commands.command(name="richest", aliases=["richlist", "richrank"]) + @commands.cooldown(1, 5, bucket=commands.BucketType.user) + async def richest(self, ctx): + """Check out the richest users in all of Mecha!""" lb = [] count = 0 - d = userdb.find().sort([("economy.total", pymongo.DESCENDING)]).limit(10) + d = self.client.db_client.userdb.find().sort([("economy.total", pymongo.DESCENDING)]).limit(10) for doc in (await d.to_list(length=10)): total = doc['economy']['wallet'] + doc['economy']['bank'] count += 1 if count <= 3: emoji = ["0", "🥇", "🥈", "🥉"] if len(doc['username']) <= 10: - lb.append(f"{'#' * count} **{emoji[count]}** {doc['username']}{sep}#### **\${round(total):,}**") + lb.append(f"{'#' * count} **{emoji[count]}** {doc['username']}\n#### **\\${round(total):,}**") elif len(doc['username']) > 10 and count == 1: - lb.append(f"{'###' * count} **{emoji[count]}** {doc['username']}{sep}#### **\${round(total):,}**") + lb.append(f"{'###' * count} **{emoji[count]}** {doc['username']}\n#### **\\${round(total):,}**") elif count == 3 and len(doc['username']) < 20: - lb.append(f"{'#' * count} **{emoji[count]}** {doc['username']}{sep}#### **\${round(total):,}**") + lb.append(f"{'#' * count} **{emoji[count]}** {doc['username']}\n#### **\\${round(total):,}**") else: - lb.append(f"{'#' * count + '#'} **{emoji[count]}** {doc['username']}{sep}#### **\${round(total):,}**") + lb.append( + f"{'#' * count + '#'} **{emoji[count]}** {doc['username']}\n#### **\\${round(total):,}**" + ) elif count == 4: lb.append(f"**#4** -> {doc['username']}: {round(total):,}") else: lb.append(f"**#{count}** -> {doc['username']}: {round(total):,}") - embed = voltage.SendableEmbed( - title = "View the Leaderboard (UPDATES EVERY 2 MINUTES!)", + embed = revolt.SendableEmbed( + title="View the Leaderboard (UPDATES EVERY 2 MINUTES!)", description='\n'.join(lb), color="#516BF2" ) @@ -530,15 +462,15 @@ async def richest(ctx): embed=embed ) - @eco.command(description="Move money into your bank account!", name="deposit", aliases=['dep', 'tobank', 'dp', 'd']) - @limiter(10, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def deposit(ctx, *, amount: str): - if (await userdb.find_one({"userid": ctx.author.id})): - amt = (await parse_amount(ctx, amount, False)) + @commands.command(name="deposit", aliases=['dep', 'tobank', 'dp', 'd']) + @commands.cooldown(1, 10, bucket=commands.BucketType.user) + async def deposit(self, ctx, *, amount: str): + """Move money into your bank account!""" + user_data = await self.client.db_client.get_user(ctx.author) + if user_data: + amt = await parse_amount(ctx, amount, False) if amt is None: - print(amt) - print(amount) - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, description="Please enter a valid amount!", @@ -547,33 +479,35 @@ async def deposit(ctx, *, amount: str): await ctx.reply(embed=embed) return elif amt < 0: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, description="Please enter a valid amount!", color="#FF0000", ) return await ctx.reply(embed=embed) - userdata = (await userdb.find_one({"userid": ctx.author.id}))["economy"]["wallet"] - if userdata > 0: - if amt > userdata: + user_data = user_data["economy"]["wallet"] + if user_data > 0: + if amt > user_data: await ctx.reply("You're trying to deposit more than you have in your wallet!") return - await userdb.bulk_write([ - pymongo.UpdateOne( - {"userid": ctx.author.id}, - {"$inc": {"economy.wallet": -amt, "economy.bank": amt}} - ) - ]) - embed = voltage.SendableEmbed( + await self.client.db_client.userdb.bulk_write( + [ + pymongo.UpdateOne( + {"userid": ctx.author.id}, + {"$inc": {"economy.wallet": -amt, "economy.bank": amt}} + ) + ] + ) + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"You deposited `${amt:,}` into your bank account! {sep}You have `${(await userdb.find_one({'userid': ctx.author.id}))['economy']['bank']:,}` in your bank account!", + description=f"You deposited `${amt:,}` into your bank account! \nYou have `${(await self.client.db_client.userdb.find_one({'userid': ctx.author.id}))['economy']['bank']:,}` in your bank account!", color="#00FF00", ) await ctx.reply(embed=embed) else: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, description="Please enter a valid amount!", @@ -582,98 +516,109 @@ async def deposit(ctx, *, amount: str): await ctx.reply(embed=embed) else: await create_account(ctx) - + # GAMBA GAMBA GAMBA - - @eco.command(name="coinflip", aliases=['cf', 'coin', 'flip'], description="Flip a coin!") - @limiter(7, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def coinflip(ctx, bet:int=None, choice:str=None, user:voltage.User=None): - if not bet or bet < 0: + + @commands.command(name="coinflip", aliases=['cf', 'coin', 'flip']) + @commands.cooldown(1, 7, bucket=commands.BucketType.user) + async def coinflip(self, ctx: commands.Context, bet: int, choice: str, user: revolt.Member = None): + """Flip a coin!""" + if bet < 0: return await ctx.reply("Please enter a valid bet!") else: bet = int(bet) - if not choice: - return await ctx.reply("Please enter heads or tails!") - elif choice.lower() not in ['heads', 'tails']: + + if choice.lower() not in ['heads', 'tails']: return await ctx.reply("Please enter heads or tails!") - elif bet > (await userdb.find_one({"userid": ctx.author.id}))["economy"]["wallet"]: - embed = voltage.SendableEmbed( + + user_data = await self.client.db_client.get_user(ctx.author) + if not user_data: + return await create_account(ctx) + + if bet > user_data["economy"]["wallet"]: + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"You don't have that much money in your wallet!{sep}*(lol poor fella)*", + description=f"You don't have that much money in your wallet!\n*(lol poor fella)*", colour="#FF0000" ) return await ctx.reply(embed=embed) - elif (await userdb.find_one({"userid": ctx.author.id})): - if not user: - embed = voltage.SendableEmbed( - title=ctx.author.display_name, - icon_url=ctx.author.display_avatar.url, - description=f"Flipping a coin for **\${bet:,}**... {sep}You now have `${(await userdb.find_one({'userid': ctx.author.id}))['economy']['wallet']-bet:,}` in your wallet!", - colour="#00FF00", - media = "https://media.tenor.com/images/60b3d58b8161ad9b03675abf301e8fb4/tenor.gif" - ) - msg = await ctx.reply(embed=embed) - await userdb.bulk_write([ + + if not user: + embed = revolt.SendableEmbed( + title=ctx.author.display_name, + icon_url=ctx.author.display_avatar.url, + description=f"Flipping a coin for **\\${bet:,}**... \nYou now have `${user_data['economy']['wallet'] - bet:,}` in your wallet!", + colour="#00FF00", + # media="https://media.tenor.com/images/60b3d58b8161ad9b03675abf301e8fb4/tenor.gif" # setting the media in an embed is tricky - andreaw + ) + msg = await ctx.reply(embed=embed) + await self.client.db_client.userdb.bulk_write( + [ pymongo.UpdateOne( {"userid": ctx.author.id}, {"$inc": {"economy.wallet": -bet}} ) - ]) - await asyncio.sleep(3) - if random.choice(['heads', 'tails']) == choice.lower(): - await userdb.bulk_write([ + ] + ) + await asyncio.sleep(3) + if random.choice(['heads', 'tails']) == choice.lower(): + await self.client.db_client.userdb.bulk_write( + [ pymongo.UpdateOne( {"userid": ctx.author.id}, - {"$inc": {"economy.wallet": bet*2}} + {"$inc": {"economy.wallet": bet * 2}} ) - ]) - embed = voltage.SendableEmbed( - title=ctx.author.display_name, - icon_url=ctx.author.display_avatar.url, - description=f"You won **\${bet:,}**! {sep}You now have `${(await userdb.find_one({'userid': ctx.author.id}))['economy']['wallet']:,}` in your wallet!", - colour="#00FF00" - ) - return await msg.edit(embed=embed) - else: - embed = voltage.SendableEmbed( - title=ctx.author.display_name, - icon_url=ctx.author.display_avatar.url, - description=f"You lost **\${bet:,}**! {sep}You now have `${(await userdb.find_one({'userid': ctx.author.id}))['economy']['wallet']:,}` in your wallet!", - colour="#FF0000" - ) - return await msg.edit(embed=embed) - else: - embed = voltage.SendableEmbed( + ] + ) + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"{ctx.author.display_name}, challenges {user.display_name} to a coinflip for **\${bet:,}*! {sep}Do you confirm? (15 seconds)", + description=f"You won **\\${bet:,}**! \nYou now have `${user_data['economy']['wallet']+bet:,}` in your wallet!", colour="#00FF00" ) - await ctx.send(embed=embed, content=user.mention) - try: - def check(msg): - return msg.author.id == user.id - msg = await client.wait_for("message", check=check, timeout=15) - if msg.content.lower() in ["yes", "y", "yea", "yeah", "yup"]: - if (await userdb.find_one({"userid": user.id})): - udata = (await userdb.find_one({"userid": user.id})) - if bet > udata["economy"]["wallet"]: - embed = voltage.SendableEmbed( - title=ctx.author.display_name, - icon_url=ctx.author.display_avatar.url, - description=f"{user.display_name} doesn't have that much money in their wallet!{sep}*(lol poor fella)*", - colour="#FF0000" - ) - return await ctx.reply(embed=embed) - embed = voltage.SendableEmbed( + return await msg.edit(embed=embed) + else: + embed = revolt.SendableEmbed( + title=ctx.author.display_name, + icon_url=ctx.author.display_avatar.url, + description=f"You lost **\\${bet:,}**! \nYou now have `${user_data['economy']['wallet']-bet:,}` in your wallet!", + colour="#FF0000" + ) + return await msg.edit(embed=embed) + else: + embed = revolt.SendableEmbed( + title=ctx.author.display_name, + icon_url=ctx.author.display_avatar.url, + description=f"{ctx.author.display_name}, challenges {user.display_name} to a coinflip for **\\${bet:,}*! \nDo you confirm? (15 seconds)", + colour="#00FF00" + ) + await ctx.send(embed=embed, content=user.mention) + try: + def check(msg): + return msg.author.id == user.id + + msg = await client.wait_for("message", check=check, timeout=15) + if msg.content.lower() in ["yes", "y", "yea", "yeah", "yup"]: + if (await self.client.db_client.userdb.find_one({"userid": user.id})): + udata = (await self.client.db_client.userdb.find_one({"userid": user.id})) + if bet > udata["economy"]["wallet"]: + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"Flipping a coin for **\${bet:,}**... {sep}You now have `${(await userdb.find_one({'userid': user.id}))['economy']['wallet']-bet:,}` in your wallet!", - media = "https://media.tenor.com/images/60b3d58b8161ad9b03675abf301e8fb4/tenor.gif", - colour="#00FF00" + description=f"{user.display_name} doesn't have that much money in their wallet!\n*(lol poor fella)*", + colour="#FF0000" ) - await userdb.bulk_write([ + return await ctx.reply(embed=embed) + embed = revolt.SendableEmbed( + title=ctx.author.display_name, + icon_url=ctx.author.display_avatar.url, + description=f"Flipping a coin for **\\${bet:,}**... \nYou now have `${(await self.client.db_client.userdb.find_one({'userid': user.id}))['economy']['wallet'] - bet:,}` in your wallet!", + # media="https://media.tenor.com/images/60b3d58b8161ad9b03675abf301e8fb4/tenor.gif", + colour="#00FF00" + ) + await self.client.db_client.userdb.bulk_write( + [ pymongo.UpdateOne( {"userid": user.id}, {"$inc": {"economy.wallet": -bet}} @@ -682,210 +627,224 @@ def check(msg): {"userid": ctx.author.id}, {"$inc": {"economy.wallet": -bet}} ) - ]) - await ctx.reply(embed=embed, content=user.mention) - if random.choice(['heads', 'tails']) == choice.lower(): - await userdb.bulk_write([ + ] + ) + await ctx.reply(embed=embed, content=user.mention) + if random.choice(['heads', 'tails']) == choice.lower(): + await self.client.db_client.userdb.bulk_write( + [ pymongo.UpdateOne( {"userid": ctx.author.id}, - {"$inc": {"economy.wallet": bet*2}} + {"$inc": {"economy.wallet": bet * 2}} ) - ]) - embed = voltage.SendableEmbed( - title=ctx.author.display_name, - icon_url=ctx.author.display_avatar.url, - description=f"{ctx.author.mention} won **\${bet:,}**! {sep}You now have `${(await userdb.find_one({'userid': ctx.author.id}))['economy']['wallet']:,}` in your wallet!", - colour="#00FF00" - ) - return await ctx.reply(embed=embed) - else: - await userdb.bulk_write([ + ] + ) + embed = revolt.SendableEmbed( + title=ctx.author.display_name, + icon_url=ctx.author.display_avatar.url, + description=f"{ctx.author.mention} won **\\${bet:,}**! \nYou now have `${(await self.client.db_client.userdb.find_one({'userid': ctx.author.id}))['economy']['wallet']:,}` in your wallet!", + colour="#00FF00" + ) + return await ctx.reply(embed=embed) + else: + await self.client.db_client.userdb.bulk_write( + [ pymongo.UpdateOne( {"userid": user.id}, - {"$inc": {"economy.wallet": bet*2}} + {"$inc": {"economy.wallet": bet * 2}} ) - ]) - embed = voltage.SendableEmbed( - title=ctx.author.display_name, - icon_url=ctx.author.display_avatar.url, - description=f"{user.mention} won **\${bet:,}**! {sep}They now have `${(await userdb.find_one({'userid': ctx.author.id}))['economy']['wallet']:,}` in their wallet!", - colour="#00FF00" - ) - return await msg.reply(embed=embed) - else: - embed = voltage.SendableEmbed( + ] + ) + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"{user.display_name} doesn't exist! {sep}You now have `${(await userdb.find_one({'userid': ctx.author.id}))['economy']['wallet']:,}` in your wallet!", - colour="#FF0000" + description=f"{user.mention} won **\\${bet:,}**! \nThey now have `${(await self.client.db_client.userdb.find_one({'userid': ctx.author.id}))['economy']['wallet']:,}` in their wallet!", + colour="#00FF00" ) - await ctx.reply(embed=embed) - elif msg.content.lower() in ["no", "n", "nah", "nope"]: - embed = voltage.SendableEmbed( + return await msg.reply(embed=embed) + else: + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"Looks like {user.display_name} doesn't want to play with you. {sep}You now have `${(await userdb.find_one({'userid': ctx.author.id}))['economy']['wallet']:,}` in your wallet!", + description=f"{user.display_name} doesn't exist! \nYou now have `${(await self.client.db_client.userdb.find_one({'userid': ctx.author.id}))['economy']['wallet']:,}` in your wallet!", colour="#FF0000" ) - return await ctx.reply(embed=embed) - else: - await ctx.send(msg.content) - except asyncio.TimeoutError: - embed = voltage.SendableEmbed( + await ctx.reply(embed=embed) + elif msg.content.lower() in ["no", "n", "nah", "nope"]: + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"{user.display_name} didn't respond in time! {sep}You now have `${(await userdb.find_one({'userid': ctx.author.id}))['economy']['wallet']:,}` in your wallet!", + description=f"Looks like {user.display_name} doesn't want to play with you. \nYou now have `${(await self.client.db_client.userdb.find_one({'userid': ctx.author.id}))['economy']['wallet']:,}` in your wallet!", colour="#FF0000" ) return await ctx.reply(embed=embed) - - @eco.command(name="blackjack", aliases=["bj"], description="Play a game of blackjack!") - @limiter(7, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def blackjack(ctx, *, bet:str): + else: + await ctx.send(msg.content) + except asyncio.TimeoutError: + embed = revolt.SendableEmbed( + title=ctx.author.display_name, + icon_url=ctx.author.display_avatar.url, + description=f"{user.display_name} didn't respond in time! \nYou now have `${(await self.client.db_client.userdb.find_one({'userid': ctx.author.id}))['economy']['wallet']:,}` in your wallet!", + colour="#FF0000" + ) + return await ctx.reply(embed=embed) + + @commands.command(name="blackjack", aliases=["bj"]) + @commands.cooldown(1, 7, bucket=commands.BucketType.user) + async def blackjack(self, ctx, *, bet: str): + """Play a game of blackjack!""" bet = await parse_amount(ctx, bet) if bet is None or bet <= 0: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"Please specify a valid bet!{sep}**Usage:** `{ctx.prefix}bj `", + description=f"Please specify a valid bet!\n**Usage:** `{ctx.prefix}bj `", colour="#FF0000" ) return await ctx.reply(embed=embed) - elif bet > (await userdb.find_one({"userid": ctx.author.id}))["economy"]["wallet"]: - embed = voltage.SendableEmbed( + + user_data = await self.client.db_client.userdb.find_one({"userid": ctx.author.id}) + if not user_data: + return await create_account(ctx) + elif bet > user_data["economy"]["wallet"]: + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"You don't have that much money in your wallet!{sep}*(lol poor fella)*", + description=f"You don't have that much money in your wallet!\n*(lol poor fella)*", colour="#FF0000" ) return await ctx.reply(embed=embed) - elif (await userdb.find_one({"userid": ctx.author.id})): - await userdb.update_one({"userid": ctx.author.id}, {"$inc": {"economy.wallet": -bet}}) - deck = [ - 'SA', 'S2', 'S3', 'S4', 'S5', 'S6', 'S7', 'S8', 'S9', 'S10', 'SJ', 'SQ', 'SK', - 'HA', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'H8', 'H9', 'H10', 'HJ', 'HQ', 'HK', - 'CA', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'C10', 'CJ', 'CQ', 'CK', - 'DA', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'D10', 'DJ', 'DQ', 'DK' - ] - random.shuffle(deck) - - def calculate_hand(hand): - value = 0 - ace_count = 0 - for card in hand: - if card[1:] in ['J', 'Q', 'K']: - value += 10 - elif card[1:] == 'A': - ace_count += 1 - value += 11 - else: - value += int(card[1:]) - while value > 21 and ace_count: - value -= 10 - ace_count -= 1 - return value - player_hand = [deck.pop(), deck.pop()] - dealer_hand = [deck.pop(), deck.pop()] + await self.client.db_client.userdb.update_one({"userid": ctx.author.id}, {"$inc": {"economy.wallet": -bet}}) + deck = [ + 'SA', 'S2', 'S3', 'S4', 'S5', 'S6', 'S7', 'S8', 'S9', 'S10', 'SJ', 'SQ', 'SK', + 'HA', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'H8', 'H9', 'H10', 'HJ', 'HQ', 'HK', + 'CA', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'C10', 'CJ', 'CQ', 'CK', + 'DA', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'D10', 'DJ', 'DQ', 'DK' + ] + random.shuffle(deck) - player_value = calculate_hand(player_hand) - dealer_value = calculate_hand(dealer_hand) + def calculate_hand(hand): + value = 0 + ace_count = 0 + for card in hand: + if card[1:] in ['J', 'Q', 'K']: + value += 10 + elif card[1:] == 'A': + ace_count += 1 + value += 11 + else: + value += int(card[1:]) + while value > 21 and ace_count: + value -= 10 + ace_count -= 1 + return value - # Initial hand display - embed = voltage.SendableEmbed( - title=f"{ctx.author.display_name}'s blackjack game", - description=f"Dealer's hand: {str(dealer_hand[0])} and ?{sep}Your hand: {' '.join(player_hand)} (Total: {player_value}){sep}`hit` or `stand`?", - colour="#44ff44" - ) - await ctx.reply(embed=embed) + player_hand = [deck.pop(), deck.pop()] + dealer_hand = [deck.pop(), deck.pop()] - # Player's turn - while True: - if player_value == 21: - embed = voltage.SendableEmbed( - title=f"{ctx.author.display_name}'s blackjack game", - description=f"Blackjack! You win!", - colour="#198754" - ) - await ctx.reply(embed=embed) - await userdb.update_one({"userid": ctx.author.id}, {"$inc": {"economy.wallet": round(bet*2.5)}}) - return - elif player_value > 21: - embed = voltage.SendableEmbed( - title=f"{ctx.author.display_name}'s blackjack game", - description=f"You busted with a total of {player_value}. Dealer wins.", - colour="#dc3545" - ) - await ctx.reply(embed=embed) - return - action = await client.wait_for('message', check=lambda m: m.author == ctx.author and m.content.lower() in ['hit', 'stand', 'h', 's'], timeout=30) - if any(x in action.content.lower() for x in ['hit', 'h', 'draw']): - player_hand.append(deck.pop()) - player_value = calculate_hand(player_hand) - embed=voltage.SendableEmbed( - title=f"{ctx.author.display_name}'s blackjack game", - description=f"You drew a card: {str(player_hand[-1])}{sep}Your hand: {' '.join(player_hand)} (Total: {player_value}){sep}`hit` or `stand`?", - colour="#0d6efd" - ) - await ctx.reply(embed=embed) - else: - break + player_value = calculate_hand(player_hand) + dealer_value = calculate_hand(dealer_hand) - # Dealer's turn - embed = voltage.SendableEmbed( - title=f"{ctx.author.display_name}'s blackjack game", - description=f"It's the Dealer's turn.{sep}Dealer's hand: {' '.join(dealer_hand)} (Total: {dealer_value})", - colour="#ffc107" - ) - await ctx.send(embed=embed) - while dealer_value < 17: - dealer_hand.append(deck.pop()) - dealer_value = calculate_hand(dealer_hand) - text = [] - text.append(f"Dealer drew a card: {dealer_hand[-1]}{sep}Dealer's hand: {' '.join(dealer_hand)} (Total: {dealer_value})") - embed = voltage.SendableEmbed( - title=f"{ctx.author.display_name}'s blackjack game", - description='\n'.join(text), - colour="#ffc107" - ) - await ctx.reply(embed=embed) + # Initial hand display + embed = revolt.SendableEmbed( + title=f"{ctx.author.display_name}'s blackjack game", + description=f"Dealer's hand: {str(dealer_hand[0])} and ?\nYour hand: {' '.join(player_hand)} (Total: {player_value})\n`hit` or `stand`?", + colour="#44ff44" + ) + await ctx.reply(embed=embed) - # Determine winner - if dealer_value > 21 or player_value > dealer_value: - embed = voltage.SendableEmbed( + # Player's turn + while True: + if player_value == 21: + embed = revolt.SendableEmbed( title=f"{ctx.author.display_name}'s blackjack game", - description=f"You won `${bet*2}`!{sep}Dealer busted with a total of {dealer_value}.{sep}Your hand: {' '.join(player_hand)} (Total: {player_value})", + description=f"Blackjack! You win!", colour="#198754" ) await ctx.reply(embed=embed) - await userdb.update_one({"userid": ctx.author.id}, {"$inc": {"economy.wallet": bet*2}}) - elif dealer_value == player_value: - embed = voltage.SendableEmbed( + await self.client.db_client.userdb.update_one({"userid": ctx.author.id}, {"$inc": {"economy.wallet": round(bet * 2.5)}}) + return + elif player_value > 21: + embed = revolt.SendableEmbed( title=f"{ctx.author.display_name}'s blackjack game", - description=f"It's a tie!", - colour="#ffc107" + description=f"You busted with a total of {player_value}. Dealer wins.", + colour="#dc3545" ) await ctx.reply(embed=embed) - await userdb.update_one({"userid": ctx.author.id}, {"$inc": {"economy.wallet": bet}}) - else: - embed = voltage.SendableEmbed( + return + action = await client.wait_for( + 'message', check=lambda m: m.author == ctx.author and m.content.lower() in ['hit', 'stand', 'h', + 's'], timeout=30 + ) + if any(x in action.content.lower() for x in ['hit', 'h', 'draw']): + player_hand.append(deck.pop()) + player_value = calculate_hand(player_hand) + embed = revolt.SendableEmbed( title=f"{ctx.author.display_name}'s blackjack game", - description=f"Dealer wins with a total of {dealer_value}.{sep}Your hand: {' '.join(player_hand)} (Total: {player_value})", - colour="#dc3545" + description=f"You drew a card: {str(player_hand[-1])}\nYour hand: {' '.join(player_hand)} (Total: {player_value})\n`hit` or `stand`?", + colour="#0d6efd" ) await ctx.reply(embed=embed) + else: + break + + # Dealer's turn + embed = revolt.SendableEmbed( + title=f"{ctx.author.display_name}'s blackjack game", + description=f"It's the Dealer's turn.\nDealer's hand: {' '.join(dealer_hand)} (Total: {dealer_value})", + colour="#ffc107" + ) + await ctx.send(embed=embed) + while dealer_value < 17: + dealer_hand.append(deck.pop()) + dealer_value = calculate_hand(dealer_hand) + text = [] + text.append( + f"Dealer drew a card: {dealer_hand[-1]}\nDealer's hand: {' '.join(dealer_hand)} (Total: {dealer_value})" + ) + embed = revolt.SendableEmbed( + title=f"{ctx.author.display_name}'s blackjack game", + description='\n'.join(text), + colour="#ffc107" + ) + await ctx.reply(embed=embed) + + # Determine winner + if dealer_value > 21 or player_value > dealer_value: + embed = revolt.SendableEmbed( + title=f"{ctx.author.display_name}'s blackjack game", + description=f"You won `${bet * 2}`!\nDealer busted with a total of {dealer_value}.\nYour hand: {' '.join(player_hand)} (Total: {player_value})", + colour="#198754" + ) + await ctx.reply(embed=embed) + await self.client.db_client.userdb.update_one({"userid": ctx.author.id}, {"$inc": {"economy.wallet": bet * 2}}) + elif dealer_value == player_value: + embed = revolt.SendableEmbed( + title=f"{ctx.author.display_name}'s blackjack game", + description=f"It's a tie!", + colour="#ffc107" + ) + await ctx.reply(embed=embed) + await self.client.db_client.userdb.update_one({"userid": ctx.author.id}, {"$inc": {"economy.wallet": bet}}) else: - await add_user(ctx.author) - await ctx.send("Please try again!") - - @eco.command(description="Pay another user from your wallet!", name="pay", aliases=['transfer', 'sendmoney']) - @limiter(10, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def pay(ctx, member:voltage.User, amount:str): - parsed_amount = await parse_amount(ctx, amount) + embed = revolt.SendableEmbed( + title=f"{ctx.author.display_name}'s blackjack game", + description=f"Dealer wins with a total of {dealer_value}.\nYour hand: {' '.join(player_hand)} (Total: {player_value})", + colour="#dc3545" + ) + await ctx.reply(embed=embed) + + @commands.command(name="pay", aliases=['transfer', 'sendmoney']) + @commands.cooldown(1, 10, bucket=commands.BucketType.user) + async def pay(self, ctx, member: revolt.Member, amount: str): + """Pay another user from your wallet!""" + parsed_amount = round(await parse_amount(ctx, amount), 2) if parsed_amount is None: return await ctx.reply("Please enter a valid amount!") + if parsed_amount <= 0: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title="Error!", description="Please enter a positive amount to pay.", colour="#dc3545" @@ -893,71 +852,79 @@ async def pay(ctx, member:voltage.User, amount:str): await ctx.reply(embed=embed) return if ctx.author.id == member.id: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title="Error!", description="You cannot pay yourself!", colour="#dc3545" ) await ctx.reply(embed=embed) return - sender_data = await userdb.find_one({"userid": ctx.author.id}) - if sender_data and sender_data["economy"]["wallet"] >= amount: - recipient_data = (await userdb.find_one({"userid": member.id})) + sender_data = await self.client.db_client.get_user(ctx.author) + if sender_data and sender_data["economy"]["wallet"] >= parsed_amount: + recipient_data = await self.client.db_client.get_user(member) if recipient_data: - await userdb.bulk_write([ - pymongo.UpdateOne({"userid": ctx.author.id}, {"$inc": {"economy.wallet": -amount}}), - pymongo.UpdateOne({"userid": member.id}, {"$inc": {"economy.wallet": -amount}}), - pymongo.UpdateOne({"userid": member.id}, {"$append": {"notifications.inbox": { - "title": f"Payment from {ctx.author.display_name}", - "message": f"{ctx.author.display_name} paid you {round(amount, 2):,} coins!", - "date": time.time(), - "read": False, - "type": "member" - }}}), - ]) - embed = voltage.SendableEmbed( + await self.client.db_client.userdb.bulk_write( + [ + pymongo.UpdateOne({"userid": ctx.author.id}, {"$inc": {"economy.wallet": -parsed_amount}}), + pymongo.UpdateOne({"userid": member.id}, {"$inc": {"economy.wallet": -parsed_amount}}), + pymongo.UpdateOne( + {"userid": member.id}, {"$append": {"notifications.inbox": { + "title": f"Payment from {ctx.author.display_name}", + "message": f"{ctx.author.display_name} paid you {parsed_amount:,} coins!", + "date": time.time(), + "read": False, + "type": "member" + }}} + ), + ] + ) + embed = revolt.SendableEmbed( title="Success!", - description=f"You have successfully paid {round(amount, 2):,} to {member.display_name}.", + description=f"You have successfully paid {parsed_amount:,} to {member.display_name}.", colour="#198754" ) await ctx.reply(embed=embed) else: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title="Error!", description="The recipient does not have an account. Please ask them to create one using `m!add`.", colour="#dc3545" ) await ctx.relpy(embed=embed) else: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title="Error!", description="You do not have enough funds in your wallet to make this payment.", colour="#dc3545" ) await ctx.reply(embed=embed) - - @eco.command(description="Move money back into your wallet!", name="withdraw", aliases=['with', 'towallet', 'wd', 'w']) - @limiter(10, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def withdraw(ctx, *, amount): - if (await userdb.find_one({"userid": ctx.author.id})): + + @commands.command(name="withdraw", aliases=['with', 'towallet', 'wd', 'w']) + @commands.cooldown(1, 10, bucket=commands.BucketType.user) + async def withdraw(self, ctx, *, amount): + """Move money back into your wallet!""" + user_data = await self.client.db_client.get_user(ctx.author) + if user_data: userdata = await parse_amount(ctx, amount, True) - if userdata >= 0: - await userdb.bulk_write([ - pymongo.UpdateOne( - {"userid": ctx.author.id}, - {"$inc": {"economy.wallet": userdata, "economy.bank": -userdata}} - ) - ]) + if 0 <= userdata <= user_data['economy']['bank']: + await self.client.db_client.userdb.bulk_write( + [ + pymongo.UpdateOne( + {"userid": ctx.author.id}, + {"$inc": {"economy.wallet": userdata, "economy.bank": -userdata}} + ) + ] + ) amt = userdata - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"You withdrew `${round(amt, 2):,}` from your bank account! {sep}You have `${round((await userdb.find_one({'userid': ctx.author.id}))['economy']['bank'], 2):,}` in your bank account!", + description=f"You withdrew `${round(amt, 2):,}` from your bank account! \nYou have `${round((await self.client.db_client.userdb.find_one({'userid': ctx.author.id}))['economy']['bank'], 2):,}` in your bank account!", color="#00FF00", ) await ctx.reply(embed=embed) else: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, description="Please enter a valid amount!", @@ -967,60 +934,68 @@ async def withdraw(ctx, *, amount): else: await create_account(ctx) - @eco.command(name="monthly", description="Claim your monthly reward! (50,000 - 150,000 coins!)") - async def monthly(ctx): - if (await userdb.find_one({"userid": ctx.author.id})): - if time.time() < (await userdb.find_one({"userid": ctx.author.id}))["economy"]["monthly"]: - elapsed_time = int((await userdb.find_one({"userid": ctx.author.id}))['economy']['monthly'] - time.time()) + @commands.command(name="monthly") + async def monthly(self, ctx): + """Claim your monthly reward! (50,000 - 150,000 coins!)""" + user_data = await self.client.db_client.get_user(ctx.author) + if user_data: + if time.time() < user_data["economy"]["monthly"]: + elapsed_time = int( + user_data['economy']['monthly'] - time.time() + ) days, remainder = divmod(elapsed_time, 86400) hours, remainder = divmod(remainder, 3600) minutes, seconds = divmod(remainder, 60) - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"Please wait `{str(days)+'d ' if days > 0 else ''}{str(hours) + 'h ' if hours > 0 else ''}{str(minutes) + 'm ' if minutes > 0 else ''}{str(seconds) + 's' if seconds > 0 else ''}` before claiming your monthly reward!", + description=f"Please wait `{str(days) + 'd ' if days > 0 else ''}{str(hours) + 'h ' if hours > 0 else ''}{str(minutes) + 'm ' if minutes > 0 else ''}{str(seconds) + 's' if seconds > 0 else ''}` before claiming your monthly reward!", color="#dc3545" ) return await ctx.reply(embed=embed) else: amount = random.randint(50000, 150000) - await userdb.bulk_write([ - pymongo.UpdateOne( - {"userid": ctx.author.id}, - {"$set": {"economy.monthly": time.time() + 2592000}} - ), - pymongo.UpdateOne( - {"userid": ctx.author.id}, - {"$inc": {"economy.wallet": amount}} - ) - ]) - embed = voltage.SendableEmbed( + await self.client.db_client.userdb.bulk_write( + [ + pymongo.UpdateOne( + {"userid": ctx.author.id}, + {"$set": {"economy.monthly": time.time() + 2592000}} + ), + pymongo.UpdateOne( + {"userid": ctx.author.id}, + {"$inc": {"economy.wallet": amount}} + ) + ] + ) + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"You have claimed your monthly reward! {sep}You have received `${amount:,}`!", + description=f"You have claimed your monthly reward! \nYou have received `${amount:,}`!", color="#00FF00" ) return await ctx.reply(embed=embed) else: await create_account(ctx) - @eco.command(name="daily", aliases=["dailies", 'dr', 'claimdaily'], description="Claim your daily reward! (5,000 - 15,000 coins!)") - async def daily(ctx): - if (await userdb.find_one({"userid": ctx.author.id})): - if time.time() < (await userdb.find_one({"userid": ctx.author.id}))["economy"]["daily"]: - elapsed_time = int((await userdb.find_one({"userid": ctx.author.id}))['economy']['daily'] - time.time()) + @commands.command(name="daily", aliases=["dailies", 'dr', 'claimdaily']) + async def daily(self, ctx): + """Claim your daily reward! (5,000 - 15,000 coins!)""" + user_data = await self.client.db_client.get_user(ctx.author) + if user_data: + if time.time() < user_data["economy"]["daily"]: + elapsed_time = int(user_data['economy']['daily'] - time.time()) days, remainder = divmod(elapsed_time, 86400) hours, remainder = divmod(remainder, 3600) minutes, seconds = divmod(remainder, 60) - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"You already claimed your daily reward today!{sep}Come back in `{str(days)+'d ' if days > 0 else ''}{str(hours) + 'h ' if hours > 0 else ''}{str(minutes) + 'm ' if minutes > 0 else ''}{str(seconds) + 's' if seconds > 0 else ''}`!", + description=f"You already claimed your daily reward today!\nCome back in `{str(days) + 'd ' if days > 0 else ''}{str(hours) + 'h ' if hours > 0 else ''}{str(minutes) + 'm ' if minutes > 0 else ''}{str(seconds) + 's' if seconds > 0 else ''}`!", color="#dc3545" ) return await ctx.reply(embed=embed) amount = random.randint(5000, 15000) - await userdb.bulk_write( + await self.client.db_client.userdb.bulk_write( [ pymongo.UpdateOne( {"userid": ctx.author.id}, @@ -1032,7 +1007,7 @@ async def daily(ctx): ) ] ) - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, description=f"You claimed your daily reward of `${amount:,}`!", @@ -1041,162 +1016,151 @@ async def daily(ctx): return await ctx.reply(embed=embed) else: await create_account(ctx) - - @eco.command( - aliases=["apply", "getjob", "gj", "workas", "howjob"] - ) - @limiter(5, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def job(ctx, job=None): + + @commands.command(aliases=["apply", "getjob", "gj", "workas", "howjob"]) + @commands.cooldown(1, 5, bucket=commands.BucketType.user) + async def job(self, ctx, job=None): if job is None: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"## **Available Jobs:**{sep}{f'{sep}> '.join(joblist)}", + description=f"## **Available Jobs:**\n{f'\n> '.join(joblist)}", ) return await ctx.send(embed=embed) elif any(x in job.lower() for x in short_forms): await apply_job(ctx, job) - - @eco.command(aliases=["sh", "buy"], description="Buy items from the shop!", name="shop") - @limiter(5, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please try again in `{strfdelta(datetime.timedelta(seconds=delay), '{seconds}s')}`!")) - async def shop(ctx, item:str=None, amount:int=1): + @commands.command(aliases=["sh", "buy"], name="shop") + @commands.cooldown(1, 5, bucket=commands.BucketType.user) + async def shop(self, ctx, item: str = None, amount: int = 1): + """Buy items from the shop!""" if not item: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, description=""" **Available items for sale:** - -Playboy Magazine - `1000` + Resume - `250` +Playboy Magazine - `1000` Golden Egg - `5000` - """, ) - return await ctx.send(content="[]()", embed=embed) + return await ctx.send(embed=embed) else: - if (await userdb.find_one({"userid": ctx.author.id})): - if any(x in item.lower() for x in [ - "r", - "resume", - "application", - "jobform", - "resum", - "res", - "form", - "resueme", - ]): + user_data = await self.client.db_client.get_user(ctx.author) + if user_data: + if any( + x in item.lower() for x in [ + "r", + "resume", + "application", + "jobform", + "resum", + "res", + "form", + "resueme", + ] + ): await buy_item(ctx, "Resume", 250, amount) - elif any(x in item.lower() for x in [ - "gedd", - "gegg", - "goldenegg", - "goldegg", - "gold", - "egggold", - "egg", - "ge", - ]): + elif any( + x in item.lower() for x in [ + "gedd", + "gegg", + "goldenegg", + "goldegg", + "gold", + "egggold", + "egg", + "ge", + ] + ): await buy_item(ctx, "Golden Egg", 5000, amount) - elif any(x in item.lower() for x in [ - "pb", - "playboi", - "playboy", - "magazine", - "magasine", - "playb", - "pboy", - ]): + elif any( + x in item.lower() for x in [ + "pb", + "playboi", + "playboy", + "magazine", + "magasine", + "playb", + "pboy", + ] + ): await buy_item(ctx, "Playboy", 1000, amount) else: await create_account(ctx) - async def slots_game(ctx, amount: int): - if (await userdb.find_one({"userid": ctx.author.id})): - user = await userdb.find_one({"userid": ctx.author.id}) - await userdb.update_one({"userid": ctx.author.id}, {"$inc": {"economy.wallet": -amount}}) - if user["economy"]["wallet"] < amount: - embed = voltage.SendableEmbed( - title=ctx.author.display_name, - icon_url=ctx.author.display_avatar.url, - description=f"You don't have enough money to bet {amount:,}!", - colour="#FF0000" - ) - return await ctx.reply(embed=embed) - elif amount < 100: - embed = voltage.SendableEmbed( - title=ctx.author.display_name, - icon_url=ctx.author.display_avatar.url, - description="You can't bet less than 100 coins!", - colour="#FF0000" - ) - return await ctx.reply(embed=embed) + async def slots_game(self, ctx, amount: int): + await self.client.db_client.userdb.update_one({"userid": ctx.author.id}, {"$inc": {"economy.wallet": -amount}}) - emojis = { # The emojis and their values - "🗑️": 0, # Trash Can - "🍎": 1, # Apple - "🍊": 4, # Orange - "🍇": 8, # Grapes - "🍓": 2, # Strawberry - "🍒": 5, # Cherry - "🍉": 7, # Watermelon - "🍌": 10, # Banana - "🥝": 12, # Kiwi - "🍋": 15, # Lemon - "🍈": 18, # Plum - "🍅": 20, # Tomato - "7️⃣": 50, # 7 - } - - a = random.choice(list(emojis.keys())) - b = random.choice(list(emojis.keys())) - c = random.choice(list(emojis.keys())) - - embed = voltage.SendableEmbed( + if amount < 100: + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"You bet {amount:,}...{sep}{sep} | **{a}** | **{b}** | **{c}** |", - colour="#FFD700" + description="You can't bet less than 100 coins!", + colour="#FF0000" ) - msg = await ctx.reply(embed=embed) - prize = 0 - if a == b == c == "7️⃣": - prize = 25_000_000 - else: - if a == b: - prize = emojis.get(a, 0) * 2 * amount - elif a == c: - prize = emojis.get(a, 0) * amount - elif b == c: - prize = emojis.get(b, 0) * amount - if prize == 0: - embed = voltage.SendableEmbed( - title=ctx.author.display_name, - icon_url=ctx.author.display_avatar.url, - description=f"You lost! {sep}{sep} | **{a}** | **{b}** | **{c}** |", - colour="#FF0000" - ) - return await msg.edit(embed=embed) - embed = voltage.SendableEmbed( + return await ctx.reply(embed=embed) + + emojis = { # The emojis and their values + "🗑️": 0, # Trash Can + "🍎": 1, # Apple + "🍊": 4, # Orange + "🍇": 8, # Grapes + "🍓": 2, # Strawberry + "🍒": 5, # Cherry + "🍉": 7, # Watermelon + "🍌": 10, # Banana + "🥝": 12, # Kiwi + "🍋": 15, # Lemon + "🍈": 18, # Plum + "🍅": 20, # Tomato + "7️⃣": 50, # 7 + } + + a = random.choice(list(emojis.keys())) + b = random.choice(list(emojis.keys())) + c = random.choice(list(emojis.keys())) + + embed = revolt.SendableEmbed( + title=ctx.author.display_name, + icon_url=ctx.author.display_avatar.url, + description=f"You bet {amount:,}...\n\n | **{a}** | **{b}** | **{c}** |", + colour="#FFD700" + ) + msg = await ctx.reply(embed=embed) + prize = 0 + if a == b == c == "7️⃣": + prize = 25_000_000 + else: + if a == b: + prize = emojis.get(a, 0) * 2 * amount + elif a == c: + prize = emojis.get(a, 0) * amount + elif b == c: + prize = emojis.get(b, 0) * amount + if prize == 0: + embed = revolt.SendableEmbed( title=ctx.author.display_name, icon_url=ctx.author.display_avatar.url, - description=f"**x{round(prize / amount)}!**{sep}You won `{prize:,}`!{sep}{sep} | **{a}** | **{b}** | **{c}** |", - colour="#198754" + description=f"You lost! \n\n | **{a}** | **{b}** | **{c}** |", + colour="#FF0000" ) - await msg.edit(embed=embed) - await userdb.update_one({"userid": ctx.author.id}, {"$inc": {"economy.wallet": prize}}) - else: - await create_account(ctx) - + return await msg.edit(embed=embed) + embed = revolt.SendableEmbed( + title=ctx.author.display_name, + icon_url=ctx.author.display_avatar.url, + description=f"**x{round(prize / amount)}!**\nYou won `{prize:,}`!\n\n | **{a}** | **{b}** | **{c}** |", + colour="#198754" + ) + await msg.edit(embed=embed) + await self.client.db_client.userdb.update_one({"userid": ctx.author.id}, {"$inc": {"economy.wallet": prize}}) - @eco.command( - name="slots", - aliases=["bet", "slts"], - description="Bet on the slots machine!", - ) - @limiter(30, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please try again in `{strfdelta(datetime.timedelta(seconds=delay), '{seconds}s')}`!")) - async def slots(ctx, amount: str): + @commands.command(name="slots", aliases=["bet", "slts"]) + @commands.cooldown(1, 30, bucket=commands.BucketType.user) + async def slots(self, ctx, amount: str): + """Bet on the slots machine!""" parsed_amount = await parse_amount(ctx, amount) if parsed_amount is None: @@ -1209,31 +1173,28 @@ async def slots(ctx, amount: str): "You can't bet more than 100,000,000 coins!" ) - if parsed_amount > (await userdb.find_one({"userid": ctx.author.id}))["economy"]["wallet"]: + user_data = await self.client.db_client.userdb.find_one({"userid": ctx.author.id}) + if not user_data: + return await create_account(ctx) + if parsed_amount > user_data["economy"]["wallet"]: return await ctx.reply( f"You don't have enough money to bet {parsed_amount:,}!" ) - await slots_game(ctx, parsed_amount) - - if (await userdb.find_one({"userid": ctx.author.id})) is None: - await create_account(ctx) - + await self.slots_game(ctx, parsed_amount) - unusable_items = ["resume"] # Add more items if needed - - async def useitem(ctx, item:str, amount:str="1"): + async def useitem(self, ctx, item: str, amount: str = "1"): am = int(await parse_amount(ctx, amount)) if am < 1: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title="Error", description="Invalid amount specified. Please specify an amount like `100` or `1k` or `1m`", color="#FF0000" ) return await ctx.reply(embed=embed) - user = await userdb.find_one({"userid": ctx.author.id}) + user = await self.client.db_client.userdb.find_one({"userid": ctx.author.id}) if user is None: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title="Error", description="You dont have a bank account registered in our database! Would you like me to create one?", color="#FF0000", @@ -1241,31 +1202,31 @@ async def useitem(ctx, item:str, amount:str="1"): return await ctx.send(embed=embed) items = user["economy"]["data"]["inventory"] if item not in items: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title="Error", description=f"You don't have {item}!", color="#FF0000", ) return await ctx.send(embed=embed) elif items[item] < 1: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title="Error", description=f"You don't have enough {item}!", color="#FF0000", ) return await ctx.send(embed=embed) elif item in unusable_items: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title="Error", description=f"You can't use {item}!", color="#FF0000", ) return await ctx.send(embed=embed) - + # check what the item is if item == "playboy": if user["economy"]["data"]["inventory"]["playboy"] < 1: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title="Error", description=f"You don't have any {item}!", color="#FF0000", @@ -1275,43 +1236,53 @@ async def useitem(ctx, item:str, amount:str="1"): amt = (random.randint(1, 50) * user["levels"]["level"]) * round(am) else: amt = (random.randint(500, 1000) * user["levels"]["level"]) * round(am) - - await userdb.bulk_write([ - pymongo.UpdateOne({"userid": ctx.author.id}, {"$inc": {"economy.data.inventory.playboy": -int(am)}}), - pymongo.UpdateOne({"userid": ctx.author.id}, {"$inc": {"economy.wallet": round(amt)}}), - ]) - embed = voltage.SendableEmbed( + + await self.client.db_client.userdb.bulk_write( + [ + pymongo.UpdateOne( + {"userid": ctx.author.id}, {"$inc": {"economy.data.inventory.playboy": -int(am)}} + ), + pymongo.UpdateOne({"userid": ctx.author.id}, {"$inc": {"economy.wallet": round(amt)}}), + ] + ) + embed = revolt.SendableEmbed( title="Success", - description=f"You used `x{round(am)}` **{item}**!{sep}You got ${round(amt):,} coins!", + description=f"You used `x{round(am)}` **{item}**!\nYou got ${round(amt):,} coins!", color="#00FF00", ) return await ctx.send(embed=embed) elif item == "bank_loan" or item == "Bank Loan": for i in user["economy"]["data"]["inventory"]: - if any(x in i for x in ["bank_loan", "Bank Loan"]) > 0: # Check if the item is in the inventory + if any(x in i for x in ["bank_loan", "Bank Loan"]) > 0: # Check if the item is in the inventory amt = (random.randint(10000, 50000) * user["levels"]["level"]) * round(am) - await userdb.bulk_write([ - pymongo.UpdateOne({"userid": ctx.author.id}, {"$inc": {"economy.data.inventory.Bank Loan": -int(am)}}), - pymongo.UpdateOne({"userid": ctx.author.id}, {"$inc": {"economy.wallet": amt}}), - ]) - embed = voltage.SendableEmbed( + await self.client.db_client.userdb.bulk_write( + [ + pymongo.UpdateOne( + {"userid": ctx.author.id}, {"$inc": {"economy.data.inventory.Bank Loan": -int(am)}} + ), + pymongo.UpdateOne({"userid": ctx.author.id}, {"$inc": {"economy.wallet": amt}}), + ] + ) + embed = revolt.SendableEmbed( title="Success", - description=f"You used `x{round(am)}` **{item}**!{sep}You got ${amt:,} coins!", + description=f"You used `x{round(am)}` **{item}**!\nYou got ${amt:,} coins!", color="#00FF00", ) return await ctx.send(embed=embed) else: - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title="Error", description=f"You don't have any {item}!", color="#FF0000", ) return await ctx.reply(embed=embed) - - - @eco.command(name="use", description="Use an item.", aliases=["eat", "drink", "useitem"]) - async def use(ctx, item, amount="1"): - await useitem(ctx, item, amount) + @commands.command(name="use", aliases=["eat", "drink", "useitem"]) + async def use(self, ctx, item, amount="1"): + """Use an item.""" + await self.useitem(ctx, item, amount) + + +async def setup(client): + await client.add_cog(Economy(client)) - return eco \ No newline at end of file diff --git a/cogs/fun.py b/cogs/fun.py index 3c987be..d451385 100644 --- a/cogs/fun.py +++ b/cogs/fun.py @@ -1,113 +1,118 @@ -import voltage, pymongo, os, random, aiohttp, requests, json -from voltage.ext import commands -from bardapi import BardAsync -import google.generativeai as genai +import json +import random +import google.generativeai as genai +import revolt +from revolt.ext import commands with open("json/config.json", "r") as f: - config = json.load(f) + config = json.load(f) genai.configure(api_key=config["GOOGLEAPIKEY"]) - model = genai.GenerativeModel('gemini-pro') -bard = BardAsync(token=config['BARDTOKEN']) - -def setup(client) -> commands.Cog: - fun = commands.Cog( - "Fun", - "More command testing, use these if you want *basic* fun commands." - ) - - @fun.command( - description="Are you gay or no?", - aliases=["howgay", "gay", "amigay", "gaypercent", "gayamount", "GayRate"], - name="gayrate" - ) - async def gayrate(ctx, member: voltage.Member = None): - if member is None: - member = ctx.author - rate = random.randint(1, 100) - embed = voltage.SendableEmbed( - title=f"{ctx.author.name}", - icon_url=ctx.author.avatar.url, - description=f"🏳️‍🌈 | {member.display_name} is `{str(rate)}%` gay!", - color="#516BF2", - ) - await ctx.reply(embed=embed) - - @fun.command(name="8ball", description="Seek your fortune!") - async def _8ball(ctx, *, question): - responses = [ - "I belive not", - "I dont think so", - "No", - "Maybe", - "Ask again later", - "Yes", - "Affirmative", - "I Belive So", - "Its possible", - ] - embed = voltage.SendableEmbed( - title=f"{ctx.author.name}", - icon_url=ctx.author.avatar.url, - description=f"""My response to `{str(question)}`...\n `{random.choice(responses)}`!""", - color="#516BF2", - ) - await ctx.reply(embed=embed) - - def split_text(text, max_chars): - """ - Splits a large text into groups by newlines if they're over a character limit, - without cutting out words while keeping its format. - - Args: - text (str): The input text. - max_chars (int): The maximum number of characters per group. - - Returns: - list: A list of strings, each representing a group of text. - """ - lines = text.split("\n") - result = [] - current_group = "" - - for line in lines: - if len(current_group) + len(line) <= max_chars: - current_group += line + "\n" - else: + + +class Fun(commands.Cog): + description = "More command testing, use these if you want *basic* fun commands." + + def __init__(self, client): + self.client = client + + @staticmethod + def split_text(text, max_chars): + """ + Splits a large text into groups by newlines if they're over a character limit, + without cutting out words while keeping its format. + + Args: + text (str): The input text. + max_chars (int): The maximum number of characters per group. + + Returns: + list: A list of strings, each representing a group of text. + """ + lines = text.split("\n") + result = [] + current_group = "" + + for line in lines: + if len(current_group) + len(line) <= max_chars: + current_group += line + "\n" + else: + result.append(current_group.strip()) + current_group = line + "\n" + + if current_group: result.append(current_group.strip()) - current_group = line + "\n" - - if current_group: - result.append(current_group.strip()) - - return result - - @fun.command( - name="ai", - aliases=['talkai'], - description="Talk to an AI" - ) - async def ai(ctx, *, question): - embed = voltage.SendableEmbed( - title=f"{ctx.author.name}", - icon_url=ctx.author.avatar.url, - description=f"Your question: `{question}`\n\nGenerating Response..", - colour="#516BF2" - ) - await ctx.reply(embed=embed) - chat = model.start_chat() - response = chat.send_message(question) - groups = split_text(response.text, 800) + return result - for i, group in enumerate(groups): - embed = voltage.SendableEmbed( - description=group, - colour="#516BF2" - ) - await ctx.send(embed=embed) + @commands.command( + aliases=["howgay", "gay", "amigay", "gaypercent", "gayamount", "GayRate"], + name="gayrate" + ) + async def gayrate(self, ctx: commands.Context, member: revolt.Member = None): + """Are you gay or no?""" + if member is None: + member = ctx.author + + rate = random.randint(1, 100) + embed = revolt.SendableEmbed( + title=f"{ctx.author.name}", + icon_url=ctx.author.avatar.url if ctx.author.avatar else None, + description=f"🏳️‍🌈 | {member.display_name} is `{str(rate)}%` gay!", + color="#516BF2", + ) + await ctx.reply(embed=embed) + + @commands.command(name="8ball") + async def _8ball(self, ctx, *, question): + """Seek your fortune!""" + responses = [ + "I believe not", + "I dont think so", + "No", + "Maybe", + "Ask again later", + "Yes", + "Affirmative", + "I Believe So", + "Its possible", + ] + embed = revolt.SendableEmbed( + title=ctx.author.name, + icon_url=ctx.author.avatar.url if ctx.author.avatar else None, + description=f"My response to `{str(question)}`...\n `{random.choice(responses)}`!", + color="#516BF2", + ) + await ctx.reply(embed=embed) + + @commands.command( + name="ai", + aliases=['talkai'], + ) + async def ai(self, ctx, *, question): + """"Talk to an AI""" + embed = revolt.SendableEmbed( + title=f"{ctx.author.name}", + icon_url=ctx.author.avatar.url, + description=f"Your question: `{question}`\n\nGenerating Response..", + colour="#516BF2" + ) + await ctx.reply(embed=embed) + chat = model.start_chat() + response = chat.send_message(question) + + groups = self.split_text(response.text, 800) + + for group in groups: + embed = revolt.SendableEmbed( + description=group, + colour="#516BF2" + ) + await ctx.send(embed=embed) + + +async def setup(client): + await client.add_cog(Fun(client)) - - return fun \ No newline at end of file diff --git a/cogs/giveaway.py b/cogs/giveaway.py index f076fba..f79e210 100644 --- a/cogs/giveaway.py +++ b/cogs/giveaway.py @@ -1,15 +1,15 @@ -import voltage, pymongo, os -from voltage.ext import commands +from revolt.ext import commands -def setup(client) -> commands.Cog: - giveaway = commands.Cog( - "Giveaway", - "More command testing, use these if you want *basic* fun commands." - ) - @giveaway.command() - async def giveawaystuffs(ctx): +class Giveaway(commands.Cog): + def __init__(self, client): + self.client = client + + @commands.command(hidden=True) + async def giveawaystuffs(self, ctx): """Adds you to the giveaway""" await ctx.reply("nuh uh :)") - return giveaway \ No newline at end of file + +async def setup(client): + await client.add_cog(Giveaway(client)) diff --git a/cogs/help.py b/cogs/help.py new file mode 100644 index 0000000..285f73a --- /dev/null +++ b/cogs/help.py @@ -0,0 +1,150 @@ +import revolt +from revolt.ext import commands + +from utilities.revolt_utilities import Paginator + +from revolt import SendableEmbed +MAIN = "#dd2e44" + + +class HelpCommand(commands.HelpCommand): + def get_usage(self, command: commands.Command) -> str: + if command.usage: + return command.usage + + parents: list[str] = [] + + if command.parent: + parent = command.parent + + while parent: + parents.append(parent.name) + parent = parent.parent + + parameters: list[str] = [] + names = [command.name] + names.extend(command.aliases) + + for parameter in command.parameters[2:]: + if parameter.kind == parameter.POSITIONAL_OR_KEYWORD: + if parameter.default is not parameter.empty: + parameters.append(f"[{parameter.name}={parameter.default}]") + else: + parameters.append(f"<{parameter.name}>") + elif parameter.kind == parameter.KEYWORD_ONLY: + if parameter.default is not parameter.empty: + parameters.append(f"[{parameter.name}={parameter.default}]") + else: + parameters.append(f"<{parameter.name}...>") + elif parameter.kind == parameter.VAR_POSITIONAL: + parameters.append(f"[{parameter.name}...]") + + names = f"[{'|'.join(names)}]" if len(names) > 1 else names[0] + return f"{' '.join(parents[::-1])} {names} {' '.join(parameters)}" + + async def create_global_help(self, context: commands.Context, commands_: dict[commands.Cog | None, list[commands.Command]]) -> Paginator: + embed = SendableEmbed(title="Help!", description=f"""- Hello, welcome to the help page! This is the global help page. +- If you want more information use `{context.prefix}help ` + +Here's how you can read a command's signature: + +#### +if the argument is surrounded by `<>` it means that it's a required argument. +#### [argument] +if the argument is surrounded by `[]` it means that it's a optional argument. +#### argument... +if the argument is followed by `...` it means that it's a greedy argument.""", colour=MAIN) + embeds = [embed] + + for cog, cmds in commands_.items(): + if not cmds: + continue + + embed = SendableEmbed(title=f"Help for {cog.qualified_name if cog else 'Global'}", description=f"### {cog.qualified_name if cog else 'Global'}\n\n", colour=MAIN) + + for command in cmds: + embed.description += f"- `{context.prefix}{self.get_usage(command)}` - {command.short_description}\n" + + if isinstance(command, commands.Group): + for subcommand in command.commands: + embed.description += f" - `{context.prefix}{self.get_usage(subcommand)}` - {subcommand.short_description}\n" + + embed.description += "***\n" + + embed.description = embed.description.strip() + embeds.append(embed) + + paginator = Paginator(timeout=60, client=context.client, pages=embeds) + paginator.add_button("first", emoji="⏪") + paginator.add_button("previous", emoji="◀️") + paginator.add_button("delete", emoji="🗑️") + paginator.add_button("next", emoji="▶️") + paginator.add_button("last", emoji="⏩") + return paginator + + async def create_cog_help(self, context: commands.Context, cog: commands.Cog) -> SendableEmbed | Paginator: + cmds = await self.filter_commands(context, cog.commands) + if not cmds: + return "No commands found in the category" + + embed = SendableEmbed(title=f"Help for {cog.qualified_name}", description=f"### {cog.qualified_name}\n\n", colour=MAIN) + + for command in cmds: + embed.description += f"- `{context.prefix}{self.get_usage(command)}` - {command.short_description}\n" + + if isinstance(command, commands.Group): + for subcommand in command.commands: + embed.description += f" - `{context.prefix}{self.get_usage(subcommand)}` - {subcommand.short_description}\n" + + embed.description += "***\n" + + embed.description = embed.description.strip() + return embed + + async def create_command_help(self, context: commands.Context, command: commands.Command | commands.Group) -> SendableEmbed: + embed = SendableEmbed(title=f"Help for {command.name}", description=f"### {command.name}\n\n`{context.prefix}{self.get_usage(command)}`\n{chr(10).join('> '+l for l in command.description.split(chr(10)))}\n", colour=MAIN) + + if command.aliases: + embed.description += f"**Aliases:** {', '.join(command.aliases)}\n" + + if command.parent: + embed.description += f"**Parent command:** {command.parent.name}\n" + + if command.cog: + embed.description += f"**Category:** {command.cog.qualified_name}\n" + + if isinstance(command, commands.Group): + embed.description += f"**Children commands:** {', '.join('`'+c.name+'`' for c in command.commands)}\n" + + embed.description = embed.description.strip() + return embed + + create_group_help = create_command_help + + async def send_help_command(self, context: commands.Context, message_payload: Paginator | dict[str, SendableEmbed | str]): + if isinstance(message_payload, Paginator): + await message_payload.start_paginator(context, check=lambda _, u, __: u.id == context.author.id) + else: + return await context.send(**message_payload) + + async def handle_no_command_found(self, context: commands.Context, name: str) -> str: + return f"No help found for `{name}`." + + +class Help(commands.Cog): + def __init__(self, client): + self.client = client + self._default_help = None + + async def cog_load(self): + self._default_help = self.client.help_command + self.client.help_command = HelpCommand() + cmd: commands.Command = self.client.get_command('help') + cmd.description = "Shows help for a command, category or the entire bot" + + async def cog_unload(self): + self.client.help_command = self._default_help + + +async def setup(client): # Your help command in help.py doesn't work through the migration, so I just pasted mine + await client.add_cog(Help(client)) diff --git a/cogs/moderation.py b/cogs/moderation.py index 825eb67..045acb3 100644 --- a/cogs/moderation.py +++ b/cogs/moderation.py @@ -1,157 +1,121 @@ -import voltage, asyncio, requests, aiohttp -import time, json -from functools import wraps +import asyncio import datetime -from datetime import timedelta -from voltage.ext import commands +import json +import time + +import revolt +from revolt.ext import commands + +from main import MyClient with open("json/config.json", "r") as f: config = json.load(f) -def limiter(cooldown: int, *, on_ratelimited = None, key = None): - cooldowns = {} - getter = key or (lambda ctx, *_1, **_2: ctx.author.id) - def wrapper(callback): - @wraps(callback) - async def wrapped(ctx, *args, **kwargs): - k = getter(ctx, *args, **kwargs) - v = (time.time() - cooldowns.get(k, 0)) - if v < cooldown and 0 > v: - if on_ratelimited: - return await on_ratelimited(ctx, -v, *args, **kwargs) - return - cooldowns[k] = time.time() + cooldown - return await callback(ctx, *args, **kwargs) - return wrapped - return wrapper -def setup(client) -> commands.Cog: +class Moderation(commands.Cog): + description = "Some commands for moderation, in, out, and all around." + + def __init__(self, client: MyClient): + self.client: MyClient = client - mod = commands.Cog( - "Moderation", - "Some commands for moderation, in, out, and all around." - ) + @commands.command(name="nickname", aliases=['sn', 'username', 'setname']) + @commands.has_permissions(manage_nicknames=True) + @commands.cooldown(1, 20, bucket=commands.BucketType.member) + async def nickname(self, ctx, member: revolt.Member, *, nick: str): + """Sets the nickname of a user!""" + await member.edit(nick=nick) + embed = revolt.SendableEmbed( + title="Nickname", + description=f"Changed {member.display_name}'s nickname to `{nick}`!", + colour="#00FF00", + icon_url=member.display_avatar.url if member.display_avatar else None + ) + await ctx.send(embed=embed) - @mod.command(description="Sets the nickname of a user!", name="nickname", aliases=['sn', 'username', 'setname']) - @limiter(20, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def nickname(ctx, member: voltage.User, *, nick:str): - if ctx.author.permissions.manage_nicknames or ctx.author.id == ctx.server.owner.id: - try: - async with aiohttp.ClientSession() as s: - await s.patch( - url=f"https://api.revolt.chat/servers/{ctx.server.id}/members/{member.id}", - headers={"x-bot-token": config['TOKEN']}, - json={"nickname": nick}, - timeout=10 - ) - await s.close() - except aiohttp.ClientTimeout: - return - embed = voltage.SendableEmbed( - title="Nickname", - description=f"Changed {member.display_name}'s nickname to `{nick}`!", - colour="#00FF00", - icon_url=member.display_avatar.url + @commands.command(name="purge", aliases=["clear", "c", "prune"]) + @commands.has_permissions(manage_messages=True) + @commands.cooldown(1, 20, bucket=commands.BucketType.member) + async def purge(self, ctx: commands.Context, amount: int = 10): + """BEGONE MESSAGES!""" + if 0 < amount < 101: + if amount == 1: + amount += 1 + + starttime = time.time() + messages = await ctx.channel.history(limit=amount) + await ctx.channel.delete_messages(messages) + embed = revolt.SendableEmbed( + description=f"# Purged!\nPurged {amount} messages in {round(time.time() - starttime, 2)}s!", + color="#00FF00", ) - await ctx.send(embed=embed) + msg = await ctx.send(content=ctx.author.mention, embed=embed) + await asyncio.sleep(3) + await msg.delete() else: - await ctx.reply("You don't have permission to do that!") - - - - @mod.command(description="BEGONE MESSAGES!", name="purge", aliases=["clear", "c", "prune"]) - @limiter(20, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def purge(ctx, amount:int=10): - if ctx.author.permissions.manage_messages or ctx.author.id == ctx.server.owner.id and ctx.me.permissions.manage_messages: - if amount > 0 and amount < 101: - if amount == 1: - amount += 1 - starttime = time.time() - messages = await ctx.channel.history(limit=amount) - ids = [m.id for m in messages] - await ctx.send("Purging...", delete_after=2) - async with aiohttp.ClientSession() as session: - await session.delete( - url=f"https://api.revolt.chat/channels/{ctx.channel.id}/messages/bulk", - headers={"x-bot-token": config['TOKEN']}, - json={"ids": ids} - ) - await session.close() - embed = voltage.SendableEmbed( - description=f"# Purged!\nPurged {amount} messages in {round(time.time() - starttime, 2)}s!", - color="#00FF00", - ) - await ctx.send(content=ctx.author.mention, embed=embed, delete_after=3) - else: - embed = voltage.SendableEmbed( - description="Please provide a purge amount between 1 and 100!", - ) - await ctx.reply(embed=embed, delete_after=3) - elif not ctx.author.permissions.manage_messages: - embed = voltage.SendableEmbed( - description="You `or me` doesn't have the required permission(s) to use this command!", - color="#FF0000", + embed = revolt.SendableEmbed( + description="Please provide a purge amount between 1 and 100!", ) - await ctx.reply(embed=embed) + await ctx.reply(embed=embed, delete_after=3) - @mod.command(description="Ban a user from your server!") - @limiter(20, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def ban(ctx, member: voltage.Member): - if ctx.author.permissions.ban_members: - return await ctx.send(f"Attempting to ban {member.name}!") + @commands.command() + @commands.has_permissions(ban_members=True) + @commands.cooldown(1, 20, bucket=commands.BucketType.member) + async def ban(self, ctx, member: revolt.Member): # command seems incomplete + """Ban a user from your server!""" + if ctx.author.roles[0] > member.roles[0]: + return await ctx.send( + "That user is above your top role! I cannot ban them!" + ) elif member.id == ctx.author.id: return await ctx.send("You can't ban yourself!") - else: - return await ctx.send("You dont have the required permission!") - - @mod.command(description="Kick a user from your server!") - @limiter(20, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def kick(ctx, member: voltage.Member): - if commands.has_perms(kick_members=True) and commands.bot_has_perms(kick_members=True): - return await ctx.send( - "You don't have the required permission `kick_members` that is required for this command!" + elif member.id == "01FZB4GBHDVYY6KT8JH4RBX4KR": + return await ctx.send("You want to ban me?! How dare you :boohoo:") + try: + await member.ban() + embed = revolt.SendableEmbed( + title="Done!", description=f"Just Banned {member.name}!", colour="#516BF2" ) - elif ctx.author.roles[0] > member.roles[0]: + await ctx.send(content=ctx.author.mention, embed=embed) + except Exception as e: + await ctx.send(f"I was unable to kick {member.display_name}!\n```\n{e}\n```") + + @commands.command() + @commands.has_permissions(kick_members=True) + @commands.cooldown(1, 20, bucket=commands.BucketType.member) + async def kick(self, ctx, member: revolt.Member): + """Kick a user from your server!""" + if ctx.author.roles[0] > member.roles[0]: return await ctx.send( "That user is above your top role! I cannot kick them!" ) - elif member.roles[0] < client.roles[0]: - return await ctx.send( - "I couldnt kick the member because I do not have a high enough role to do this!" - ) - elif ctx.author.permissions.ban_members: - return await ctx.send(f"Attempting to kick {member.name}!") elif member.id == ctx.author.id: return await ctx.send("You can't kick yourself!") elif member.id == "01FZB4GBHDVYY6KT8JH4RBX4KR": return await ctx.send("You want to kick me?! How dare you :boohoo:") - elif member.permissions.ban_members: - return await ctx.send( - "This user is an administrator! I cannot kick them! Please remove their administrative permissions before continuing." - ) try: await member.kick() - embed = voltage.SendableEmbed( + embed = revolt.SendableEmbed( title="Done!", description=f"Just Kicked {member.name}!", colour="#516BF2" ) await ctx.send(content=ctx.author.mention, embed=embed) except Exception as e: await ctx.send(f"I was unable to kick {member.display_name}!\n```\n{e}\n```") - @mod.command(description="Go to the corner! >_<", name="timeout", aliases=["time", "to", "corner", "gotocorner"]) - async def timeout(ctx, member: voltage.Member, duration: int): - if ctx.author.permissions.timeout_members and ctx.me.permissions.timeout_members: - try: - await member.timeout(duration) - embed = voltage.SendableEmbed( - title="Done!", - description=f"Timed out {member.display_name} for {duration:.0f} seconds!", - colour="#516BF2" - ) - return await ctx.reply(embed=embed) - except: - return await ctx.reply("I was unable to timeout that user!") - else: - return await ctx.reply("You don't have the required permission `Timeout Members` that is required for this command!") - - return mod \ No newline at end of file + @commands.command(name="timeout", aliases=["time", "to", "corner", "gotocorner"]) + @commands.has_permissions(timeout_members=True) + async def timeout(self, ctx, member: revolt.Member, duration: int): + """Go to the corner! >_<""" + try: + await member.timeout(datetime.timedelta(seconds=duration)) + embed = revolt.SendableEmbed( + title="Done!", + description=f"Timed out {member.display_name} for {duration:.0f} seconds!", + colour="#516BF2" + ) + return await ctx.reply(embed=embed) + except: + return await ctx.reply("I was unable to timeout that user!") + + +async def setup(client): + await client.add_cog(Moderation(client)) diff --git a/cogs/owner.py b/cogs/owner.py index 3211c2d..3c17b57 100644 --- a/cogs/owner.py +++ b/cogs/owner.py @@ -1,374 +1,362 @@ -import voltage, asyncio, random, time, psutil, pymongo, json, datetime, io, contextlib, requests, string, os, sys, pilcord, motor -from bson.son import SON -from voltage.ext import commands -from pymongo.mongo_client import MongoClient -from pymongo.server_api import ServerApi +import asyncio +import datetime +import json +import os +import traceback -with open("json/config.json", "r") as f: - config = json.load(f) +import psutil +import pymongo +import sys +import time +import revolt -DBclient = motor.motor_asyncio.AsyncIOMotorClient(config['MONGOURI']) - -db = DBclient["beta"] -userdb = db["users"] -serverdb = db["servers"] - -def setup(client) -> commands.Cog: - owner = commands.Cog( - "Owner", - "Some commands for testing." - ) - - @owner.command() - async def statz(ctx): - """Different from normal stats, the normal one shows the stats of the bot, this one shows complex stats. Like CPU usage and whatnot.""" - if ctx.author.id == "01FZB2QAPRVT8PVMF11480GRCD": - with open("json/data.json", "r") as f: - uptime = json.load(f)['uptime'] - embed = voltage.SendableEmbed( - title=f"{client.user.name}'s Stats", - description=f""" - ## Computer Based Stats - > CPU Usage: `{psutil.cpu_percent()}%` - > RAM Usage: `{psutil.virtual_memory().percent}%` - > Disk Usage: `{psutil.disk_usage('/').percent}%` - - ## Bot Stats - > Servers: `{len(client.servers)}` - > Users: `{len(client.users)}` - > Uptime: `{str(datetime.timedelta(seconds=int(round(time.time() - uptime))))}s` - """, - colour="#44ff44" - ) # fix the uptime formatting at some point i swear to god - await ctx.send(embed=embed) - else: - await ctx.reply("Not owner, cant use this.") - - @owner.command() - async def oping(ctx): - """Different from normal ping command, this one checks response time and rate limits.""" - if ctx.author.id == "01FZB2QAPRVT8PVMF11480GRCD": - start = time.time() - embed=voltage.SendableEmbed( - title="Pinging..", - description=f"Ping!", - color="#44ff44" - ) - msg = await ctx.reply(content="[]()", embed=embed) - for i in range(1,10): - embed1 = voltage.SendableEmbed( - title="Running PING sequence!", - description=f"Ping! `{i}/10`", - colour="#44ff44" - ) - await msg.edit(embed=embed1) - end = time.time() - total = end - start - await msg.edit( - embed=voltage.SendableEmbed( - title="Pong!", - description=f"Pong! in {round(total, 2)}s", # usually this should be 3s - 4s, if its above, you're fucked. - colour="#44ff44" - ) - ) - else: - await ctx.reply("Not owner, cant use this.") - - @owner.command(name="eval", description="Run commands in multiple languages!") - async def eval_fn(ctx, *, code): - if ctx.author.id in [ - "01FZB2QAPRVT8PVMF11480GRCD", - "01FZBQCQPT53YTAD86T28WV69X", - ]: - languagespecifiers = [ - "python", - "py", - "javascript", - "js", - "html", - "css", - "php", - "md", - "markdown", - "go", - "golang", - "c", - "c++", - "cpp", - "c#", - "cs", - "csharp", - "java", - "ruby", - "rb", - "coffee-script", - "coffeescript", - "coffee", - "bash", - "shell", - "sh", - "json", - "http", - "pascal", - "perl", - "rust", - "sql", - "swift", - "vim", - "xml", - "yaml", - ] - loops = 0 - while code.startswith("`"): - code = "".join(list(code)[1:]) - loops += 1 - if loops == 3: - loops = 0 - break - for languagespecifier in languagespecifiers: - if code.startswith(languagespecifier): - code = code.lstrip(languagespecifier) - while code.endswith("`"): - code = "".join(list(code)[0:-1]) - loops += 1 - if loops == 3: - break - code = "\n".join(f" {i}" for i in code.splitlines()) - code = f"async def eval_expr():\n{code}" - - async def send(text): - await ctx.send(text) - - env = { - "bot": client, - "client": client, - "ctx": ctx, - "print": send, - "_author": ctx.author, - "_message": ctx.message, - "_channel": ctx.channel, - "_guild": ctx.server, - "_me": ctx.me, - } - env.update(globals()) - try: - exec(code, env) - eval_expr = env["eval_expr"] - result = await eval_expr() - if result: - embed = voltage.SendableEmbed( - title="Code Ran with no errors!", - description=result, - colour="#00FF00", - ) - await ctx.send(content=ctx.author.mention, embed=embed) - except Exception as e: - embed = voltage.SendableEmbed( - title="Error occured!", - description=f"```{languagespecifier}\n{e}\n```", - colour="#0000FF", - ) - await ctx.send(content=ctx.author.mention, embed=embed) - else: - embed = voltage.SendableEmbed( - title="Whoops!", - description="You aren't an owner of this bot!", - colour="#FFFF00", - ) - return await ctx.send(content=ctx.author.mention, embed=embed) - - - @owner.command( - name="kwargstest", - description="working with kwargs sucks, kids.", - aliases=['kt', 'okt', 't'] - ) - async def kwargstest(ctx, *time, **message): - if ctx.author.id == "01FZB2QAPRVT8PVMF11480GRCD": - await ctx.send(f"{str(time)}\n{str(message)}") - else: - await ctx.reply("Not owner, cant use this.") +from revolt.ext import commands +from main import MyClient - @owner.command() - async def reac(ctx): - def check(reaction, user): - return user == ctx.author and str(reaction.emoji) == '👍' +with open("json/config.json", "r") as f: + config = json.load(f) - try: - reaction, user = await client.wait_for('reaction_add', timeout=60.0, check=check) - except asyncio.TimeoutError: - await ctx.send('👎') - else: - await ctx.send('👍') - @owner.command() - async def aggregate(ctx): - await ctx.send("done") - - def restart_bot(): +def restart_bot(): os.execv(sys.executable, ['python'] + sys.argv) - @owner.command(name= 'restart') - async def restart(ctx): - if ctx.author.id == "01FZB2QAPRVT8PVMF11480GRCD": - await ctx.send("Restarting bot...") - restart_bot() - else: - await ctx.reply("Not owner, cant use this.") - @owner.command() - async def servers(ctx): - if ctx.author.id == "01FZB2QAPRVT8PVMF11480GRCD": - for server in client.servers: - print(f"[{server.id}] {server.name} - {len(server.members)}") - else: - await ctx.reply("Not owner, cant use this.") - - - @owner.command() - async def apu(ctx, user:voltage.User, *, prefix:str): - if ctx.author.id == "01FZB2QAPRVT8PVMF11480GRCD": - await userdb.update_one({ - "userid": user.id - }, { - "$push": { - "prefixes": prefix - } - }) - await ctx.send(f"Added {prefix}, to {user.display_name}'s prefix list!") - else: - await ctx.reply("Not owner, cant use this.") - - @owner.command() - async def dpu(ctx, user:voltage.User, *, prefix:str): - if ctx.author.id == "01FZB2QAPRVT8PVMF11480GRCD": - await userdb.update_one({ - "userid": user.id - }, { - "$pull": { - "prefixes": prefix - } - }) - await ctx.send(f"Removed {prefix}, from {user.display_name}'s prefix list!") - else: - await ctx.reply("Not owner, cant use this.") - - def get_badge(badge): +def get_badge(badge): if badge == 1: - return "dev" + return "dev" elif badge == 2: - return "admin" + return "admin" elif badge == 3: - return "mod" + return "mod" elif badge == 4: - return "bug" + return "bug" elif badge == 5: - return "beta" + return "beta" else: - return None - - @owner.command() - async def addbadge(ctx, user:voltage.User, badge:int=None): - if ctx.author.id == "01FZB2QAPRVT8PVMF11480GRCD": - if not badge: - embed = voltage.SendableEmbed( - title="Add Badge", - description="Please specify a badge number!\nFor example: `m!addbadge @user 1`\nBadge List:\n```\n1 - Developer\n2 - Admin\n3 - Moderator\n4 - Bug Hunter\n5 - Beta Tester", - colour="#FF0000" - ) - return await ctx.send(embed=embed) - elif get_badge(badge): - await userdb.update_one( - { - "userid": user.id - }, - { - "$set": { - f"status.{get_badge(badge)}": True - } - } + return None + + +class Owner(commands.Cog): + """Some commands for testing.""" + + def __init__(self, client: MyClient): + self.client: MyClient = client + + @commands.command(name="add", hidden=True) + @commands.is_bot_owner() + async def add(self, ctx, user: revolt.User = None): + """Adds you to the database!""" + + user = user or ctx.author + result = await self.client.db_client.add_user(user) + await ctx.reply(f"Results are in! {result}") + + @commands.command(hidden=True) + async def statz(self, ctx): + """Different from normal stats, the normal one shows the stats of the bot, this one shows complex stats. Like CPU usage and whatnot.""" + with open("json/data.json", "r") as f: + uptime = json.load(f)['uptime'] + + embed = revolt.SendableEmbed( + title=f"{self.client.user.name}'s Stats", + description=f""" +## Computer Based Stats +> CPU Usage: `{psutil.cpu_percent()}%` +> RAM Usage: `{psutil.virtual_memory().percent}%` +> Disk Usage: `{psutil.disk_usage('/').percent}%` + +## Bot Stats +> Servers: `{len(self.client.servers)}` +> Users: `{len(self.client.users)}` +> Uptime: `{str(datetime.timedelta(seconds=int(round(time.time() - uptime))))}s` + """, + colour="#44ff44" + ) # fix the uptime formatting at some point I swear to god + await ctx.send(embed=embed) + + @commands.command(hidden=True) + @commands.is_bot_owner() + async def oping(self, ctx): + """Different from normal ping command, this one checks response time and rate limits.""" + start = time.time() + embed = revolt.SendableEmbed( + title="Pinging..", + description=f"Ping!", + color="#44ff44" ) - await ctx.send(f"Added badge {badge} to {user.display_name}!") - else: - await ctx.reply("Not owner, cant use this.") - - @owner.command() - async def removebadge(ctx, user:voltage.User, badge:int=None): - if ctx.author.id == "01FZB2QAPRVT8PVMF11480GRCD": - if not badge: - embed = voltage.SendableEmbed( - title="Remove Badge", - description="Please specify a badge number!\nFor example: `m!removebadge @user 1`\nBadge List:\n```\n1 - Developer\n2 - Admin\n3 - Moderator\n4 - Bug Hunter\n5 - Beta Tester", + msg = await ctx.reply(content="[]()", embed=embed) + for i in range(1, 10): + embed1 = revolt.SendableEmbed( + title="Running PING sequence!", + description=f"Ping! `{i}/10`", + colour="#44ff44" + ) + await msg.edit(embed=embed1) + end = time.time() + total = end - start + await msg.edit( + embed=revolt.SendableEmbed( + title="Pong!", + description=f"Pong! in {round(total, 2)}s", + # usually this should be 3s - 4s, if its above, you're fucked. + colour="#44ff44" + ) ) - await ctx.send(embed=embed) - elif get_badge(badge): - await userdb.update_one( - { - "userid": user.id - }, - { - "$set": { - f"status.{get_badge(badge)}": False + + @commands.command(name="eval", hidden=True) + # @commands.is_bot_owner() + async def eval_fn(self, ctx, *, code): + """Run commands in multiple languages!""" + languagespecifiers = [ + "python", + "py", + "javascript", + "js", + "html", + "css", + "php", + "md", + "markdown", + "go", + "golang", + "c", + "c++", + "cpp", + "c#", + "cs", + "csharp", + "java", + "ruby", + "rb", + "coffee-script", + "coffeescript", + "coffee", + "bash", + "shell", + "sh", + "json", + "http", + "pascal", + "perl", + "rust", + "sql", + "swift", + "vim", + "xml", + "yaml", + ] + loops = 0 + while code.startswith("`"): + code = "".join(list(code)[1:]) + loops += 1 + if loops == 3: + loops = 0 + break + for languagespecifier in languagespecifiers: + if code.startswith(languagespecifier): + code = code.lstrip(languagespecifier) + while code.endswith("`"): + code = "".join(list(code)[0:-1]) + loops += 1 + if loops == 3: + break + code = "\n".join(f" {i}" for i in code.splitlines()) + code = f"async def eval_expr():\n{code}" + + async def send(text): + await ctx.send(text) + + env = { + "bot": self.client, + "client": self.client, + "ctx": ctx, + "print": send, + "_author": ctx.author, + "_message": ctx.message, + "_channel": ctx.channel, + "_guild": ctx.server, + # "_me": ctx.me, + } + env.update(globals()) + try: + exec(code, env) + eval_expr = env["eval_expr"] + result = await eval_expr() + if result: + embed = revolt.SendableEmbed( + title="Code Ran with no errors!", + description=result, + colour="#00FF00", + ) + await ctx.send(content=ctx.author.mention, embed=embed) + except Exception as e: + embed = revolt.SendableEmbed( + title="Error occured!", + description=f"```{languagespecifier}\n{''.join(traceback.format_exception(type(e), e, e.__traceback__))}\n```", + colour="#0000FF", + ) + await ctx.send(content=ctx.author.mention, embed=embed) + + # @commands.command(name="kwargstest", aliases=['kt', 'okt', 't'], hidden=True) + # async def kwargstest(ctx, *time, **message): + # """working with kwargs sucks, kids.""" + # if ctx.author.id == "01FZB2QAPRVT8PVMF11480GRCD": + # await ctx.send(f"{str(time)}\n{str(message)}") + # else: + # await ctx.reply("Not owner, cant use this.") + + # @commands.command(hidden=True) + # async def reac(self, ctx): + # def check(reaction, user): + # return user == ctx.author and str(reaction.emoji) == '👍' + # + # try: + # reaction, user = await client.wait_for('reaction_add', timeout=60.0, check=check) + # except asyncio.TimeoutError: + # await ctx.send('👎') + # else: + # await ctx.send('👍') + + # @commands.command(hidden=True) + # async def aggregate(self, ctx): + # await ctx.send("done") + + @commands.command(name='restart', hidden=True) + @commands.is_bot_owner() + async def restart(self, ctx): + await ctx.send("Restarting bot...") + restart_bot() + + @commands.command(hidden=True) + @commands.is_bot_owner() + async def servers(self, ctx): + for server in self.client.servers: + print(f"[{server.id}] {server.name} - {len(server.members)}") + + @commands.command(hidden=True) + @commands.is_bot_owner() + async def apu(self, ctx, user: revolt.User, *, prefix: str): + await self.client.db_client.userdb.update_one( + { + "userid": user.id + }, { + "$push": { + "prefixes": prefix + } } - } ) - await ctx.send(f"Removed badge {badge} from {user.display_name}!") - else: - await ctx.reply("Not owner, cant use this.") - - @owner.command() - async def give(ctx, user:voltage.User, amount:int): - if ctx.author.id == "01FZB2QAPRVT8PVMF11480GRCD": - i = 1 - for _ in (await userdb.find_one({"userid": user.id}))["notifications"]["inbox"]: - i += 1 - userdb.bulk_write([ - pymongo.UpdateOne( - { - "userid": user.id - }, - { - "$inc": { - "economy.bank": amount - } - } - ), - pymongo.UpdateOne( - { - "userid": user.id - }, - { - "$set": { - f"notifications.inbox.{str(i)}": { - "message":f"You've recieved {amount:,}!", - "date": time.time(), - "title": "You've been given some coins!", - "type": "admin", - "read": False - } + await ctx.send(f"Added {prefix}, to {user.display_name}'s prefix list!") + + @commands.command(hidden=True) + @commands.is_bot_owner() + async def dpu(self, ctx, user: revolt.User, *, prefix: str): + await self.client.db_client.userdb.update_one( + { + "userid": user.id + }, { + "$pull": { + "prefixes": prefix + } } - } ) - ]) - await ctx.send(f"Gave `{user.display_name}#{user.discriminator}` `${amount:,}` coins!") - else: - await ctx.reply("Not owner, cant use this.") - - @owner.command() - async def betamsg(ctx): - if ctx.author.id == "01FZB2QAPRVT8PVMF11480GRCD": - embed = voltage.SendableEmbed( - title="Beta Message", - description="React with **👍** to enable beta testing!", - colour="#FF0000" - ) - msg = await ctx.send(embed=embed, interactions={"reactions":['👍'], "restrict_reactions": True}) - with open("json/data.json", "r") as f: - data = json.load(f) - data["BETA_ID"] = str(msg.id) - with open("json/data.json", "w") as f: - json.dump(data, f, indent=2) - else: - await ctx.reply("Not owner, cant use this.") - - return owner \ No newline at end of file + await ctx.send(f"Removed {prefix}, from {user.display_name}'s prefix list!") + + @commands.command(hidden=True) + @commands.is_bot_owner() + async def addbadge(self, ctx, user: revolt.User, badge: int = None): + if not badge: + embed = revolt.SendableEmbed( + title="Add Badge", + description="Please specify a badge number!\nFor example: `m!addbadge @user 1`\nBadge List:\n```\n1 - Developer\n2 - Admin\n3 - Moderator\n4 - Bug Hunter\n5 - Beta Tester", + colour="#FF0000" + ) + return await ctx.send(embed=embed) + elif get_badge(badge): + await self.client.db_client.userdb.update_one( + { + "userid": user.id + }, + { + "$set": { + f"status.{get_badge(badge)}": True + } + } + ) + await ctx.send(f"Added badge {badge} to {user.display_name}!") + + @commands.command(hidden=True) + @commands.is_bot_owner() + async def removebadge(self, ctx, user: revolt.User, badge: int = None): + if not badge: + embed = revolt.SendableEmbed( + title="Remove Badge", + description="Please specify a badge number!\nFor example: `m!removebadge @user 1`\nBadge List:\n```\n1 - Developer\n2 - Admin\n3 - Moderator\n4 - Bug Hunter\n5 - Beta Tester", + ) + await ctx.send(embed=embed) + elif get_badge(badge): + await self.client.db_client.userdb.update_one( + { + "userid": user.id + }, + { + "$set": { + f"status.{get_badge(badge)}": False + } + } + ) + await ctx.send(f"Removed badge {badge} from {user.display_name}!") + + @commands.command(hidden=True) + @commands.is_bot_owner() + async def give(self, ctx, user: revolt.User, amount: int): + user_data = await self.client.db_client.get_user(user) + i = len(user_data["notifications"]["inbox"]) + await self.client.db_client.userdb.bulk_write( + [ + pymongo.UpdateOne( + { + "userid": user.id + }, + { + "$inc": { + "economy.bank": amount + } + } + ), + pymongo.UpdateOne( + { + "userid": user.id + }, + { + "$set": { + f"notifications.inbox.{str(i)}": { + "message": f"You've received {amount:,}!", + "date": time.time(), + "title": "You've been given some coins!", + "type": "admin", + "read": False + } + } + } + ) + ] + ) + await ctx.send(f"Gave `{user.display_name}#{user.discriminator}` `${amount:,}` coins!") + + # @commands.command(hidden=True) + # async def betamsg(self, ctx): + # embed = revolt.SendableEmbed( + # title="Beta Message", + # description="React with **👍** to enable beta testing!", + # colour="#FF0000" + # ) + # msg = await ctx.send(embed=embed, interactions={"reactions": ['👍'], "restrict_reactions": True}) + # with open("json/data.json", "r") as f: + # data = json.load(f) + # data["BETA_ID"] = str(msg.id) + # with open("json/data.json", "w") as f: + # json.dump(data, f, indent=2) + + +async def setup(client): + await client.add_cog(Owner(client)) diff --git a/cogs/utility.py b/cogs/utility.py index 961a9b7..5ef52e6 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -1,10 +1,19 @@ -import voltage, motor, os, asyncio, pymongo, json, datetime, time, pendulum, re, requests, pilcord, aiohttp -import motor.motor_asyncio -from mcstatus import JavaServer -from functools import wraps -from voltage.ext import commands +import asyncio +import json +import re +import time -sep = "\n" +import pendulum +import pilcord +import pymongo +import revolt +# from mcstatus import JavaServer +from revolt.ext import commands + +from main import MyClient + +with open("json/config.json", "r") as f: + config = json.load(f) # TODO: Add settings or add customization options for this settings = pilcord.CardSettings( @@ -14,76 +23,101 @@ background="assets/background.jpg" ) + +def parse_time(time: str): # I am not touching this - andreaw + if time: + gtime = 0 + try: + if any(x in time for x in ["d", "h", "m", "s"]): + # mlist = list[time] will use this soon :) just gotta get a release out tbh + mtime = re.sub("d|h|m|s", "", time) + if any(x in time for x in ["s", "sec", "seconds"]): + ntime = int(re.sub("d|h|m|s", "", str(time))) + stime = ntime * 1 + elif any(x in time for x in ["m", "min", "minutes"]): + ntime = int(re.sub("d|h|m|s", "", str(time))) + mintime = ntime * 60 + elif any(x in time for x in ["h", "hrs", "hs", "hours", "hour", "hr"]): + ntime = int(re.sub("d|h|m|s", "", str(time))) + htime = ntime * 3600 + elif any(x in time for x in ["d", "day", "da", "days"]): + ntime = int(re.sub("d|h|m|s", "", str(time))) + dtime = ntime * 86400 + try: + if stime: + gtime = gtime + int(stime) + except: + pass + try: + if mintime: + gtime = gtime + int(mintime) + except: + pass + try: + if htime: + gtime = gtime + int(htime) + except: + pass + try: + if dtime: + gtime = gtime + int(dtime) + except: + pass + if int(gtime) > 7776000: + return 0 + return gtime + else: + return None + except Exception as e: + return e + + # Fixed :) -async def get_badges(badges, user:voltage.User): +async def get_badges(badges, user: revolt.User): """ Outputs a sorted array of badge names """ badgeslist = [] with open("json/data.json", "r") as f: data = json.load(f) - + for badge in badges: if badge.lower() in data: - if (await userdb.find_one({"userid": user.id}))['status'][badge.lower()]: - badgeslist.append(f":{data.get(badge)}:") - + # if (await userdb.find_one({"userid": user.id}))['status'][badge.lower()]: + badgeslist.append(f":{data.get(badge)}:") + # Output the sorted array of badge names return badgeslist -def limiter(cooldown: int, *, on_ratelimited = None, key = None): - cooldowns = {} - getter = key or (lambda ctx, *_1, **_2: ctx.author.id) - def wrapper(callback): - @wraps(callback) - async def wrapped(ctx, *args, **kwargs): - k = getter(ctx, *args, **kwargs) - v = (time.time() - cooldowns.get(k, 0)) - if v < cooldown and 0 > v: - if on_ratelimited: - return await on_ratelimited(ctx, -v, *args, **kwargs) - return - cooldowns[k] = time.time() + cooldown - return await callback(ctx, *args, **kwargs) - return wrapped - return wrapper - -with open("json/config.json", "r") as f: - config = json.load(f) - -DBclient = motor.motor_asyncio.AsyncIOMotorClient(config['MONGOURI']) -db = DBclient["beta"] -userdb = db["users"] -serverdb = db["servers"] +class Utility(commands.Cog): + description = "Utility commands for Mecha, these commands consist of leaderboard commands, leveling commands, and more." -def setup(client) -> commands.Cog: - utility = commands.Cog( - "Utility", - "Utility commands for Mecha, these commands consist of leaderboard commands, leveling commands, and more." - ) + def __init__(self, client: MyClient): + self.client: MyClient = client - @utility.command( + @commands.command( name="profile", - aliases=["ui", "userinfo"], - description = "Get information on any user! Including yourself!" + aliases=["ui", "userinfo"] ) - async def profile(ctx, user: voltage.User = None): - if not user: - user = ctx.author - if (await userdb.find_one({"userid": user.id})): - userdata = (await userdb.find_one({"userid": user.id})) - data = userdata['status'] - badges = await get_badges(data, user) - badgetext = f"{sep}## {''.join(badges)}" - ubio = str(userdata['profile']['bio']), - colour = userdata['profile']['colour'] - elif not (await userdb.find_one({"userid": user.id})): + async def profile(self, ctx, user: revolt.User = None): + """Get information on any user! Including yourself!""" + user = user or ctx.author + + user_data = await self.client.db_client.get_user(user) + print(user_data) + if user_data is not None: + data = user_data['status'] + badges = await get_badges(data, user_data) + badgetext = f"\n## {''.join(badges)}" + ubio = user_data['profile']['bio'], + colour = user_data['profile']['colour'] + else: colour = "#454FBF" badgetext = "" ubio = "No bio set." - userdate = user.created_at - embed = voltage.SendableEmbed( + + embed = revolt.SendableEmbed( title=f"{user.display_name}'s Profile", description=f"""### ### **Username:** `{user.name}#{user.discriminator}`{badgetext} @@ -94,107 +128,70 @@ async def profile(ctx, user: voltage.User = None): ) await ctx.reply(embed=embed) - @utility.command() - @limiter(10, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def stats(ctx): + @commands.command() + @commands.cooldown(1, 10, bucket=commands.BucketType.user) + async def stats(self, ctx): """Get some statistics up in here!""" with open("json/data.json", "r") as f: uptime = json.load(f)['uptime'] + elapsed_time = int(time.time() - uptime) days, remainder = divmod(elapsed_time, 86400) hours, remainder = divmod(remainder, 3600) minutes, seconds = divmod(remainder, 60) - embed = voltage.SendableEmbed( - title=f"{client.user.name}'s Stats", - description=f""" + + embed = revolt.SendableEmbed( + title=f"{self.client.user.name}'s Stats", + description=f""" ## Bot Stats -> Servers: `{len(client.servers)}` -> Users: `{len(client.users)}` +> Servers: `{len(self.client.servers)}` +> Users: `{len(self.client.users)}` > [Uptime](https://stats.uptimerobot.com/2JgmlCVB0O): `{days}d {hours}h {minutes}m {seconds}s` - """, - colour="#44ff44" - ) # fix the uptime formatting at some point i swear to god + """, + colour="#44ff44" + ) # fix the uptime formatting at some point I swear to god await ctx.send(embed=embed) - def parse_time(time:str): - if time: - gtime = 0 - try: - if any(x in time for x in ["d", "h", "m", "s"]): - # mlist = list[time] will use this soon :) just gotta get a release out tbh - mtime = re.sub("d|h|m|s", "", time) - if any(x in time for x in ["s", "sec", "seconds"]): - ntime = int(re.sub("d|h|m|s", "", str(time))) - stime = ntime * 1 - elif any(x in time for x in ["m", "min", "minutes"]): - ntime = int(re.sub("d|h|m|s", "", str(time))) - mintime = ntime * 60 - elif any(x in time for x in ["h", "hrs", "hs", "hours", "hour", "hr"]): - ntime = int(re.sub("d|h|m|s", "", str(time))) - htime = ntime * 3600 - elif any(x in time for x in ["d", "day", "da", "days"]): - ntime = int(re.sub("d|h|m|s", "", str(time))) - dtime = ntime * 86400 - try: - if stime: - gtime = gtime + int(stime) - except: - pass - try: - if mintime: - gtime = gtime + int(mintime) - except: - pass - try: - if htime: - gtime = gtime + int(htime) - except: - pass - try: - if dtime: - gtime = gtime + int(dtime) - except: - pass - if int(gtime) > 7776000: - return 0 - return gtime - else: - return None - except Exception as e: - return e - - @utility.command( - description="Get a users avatar!", - name="avatar", - aliases=["av", "getav", "ua"], - #usage="m!avatar ", - #example="m!avatar @css" - ) - @limiter(3, on_ratelimited=lambda ctx, delay, *_1, **_2: ctx.send(f"You're on cooldown! Please wait `{round(delay, 2)}s`!")) - async def avatar(ctx, member: voltage.Member): - embed = voltage.SendableEmbed( - title=f"{member.display_name}'s avatar!", - media=member.display_avatar.url, - colour="#516BF2", + @commands.command() + async def ping(self, ctx): + """Get the bot's ping!""" + # `{round((time.time() - ctx.message.created_at)*1000,2)}ms` + await ctx.reply(f"Pong!") + + @commands.command(name="avatar", aliases=["av", "getav", "ua"]) + @commands.cooldown(1, 3, bucket=commands.BucketType.user) + async def avatar(self, ctx, member: revolt.Member = None): + """Get a users avatar!""" + + member = member or ctx.author + + if member.display_avatar: + b = await member.display_avatar.read() + f = revolt.File(b) + u = await self.client.upload_file(f, 'attachments') + embed = revolt.SendableEmbed( + title=f"{member.display_name}'s avatar!", + media=u.id, + colour="#516BF2", + ) + await ctx.reply(embed=embed) + else: + return await ctx.reply(f"{member.name} does not have an avatar!") + + @commands.command( + name="reminder", aliases=["remind", "alert", "timer", "schedule", "setreminder", "setalert", "settimer", + "setschedule"] ) - await ctx.reply(content="[]()", embed=embed) - - @utility.command( - description="🕒 | Set a reminder up to a month! (1d, 1h, 1m, 1s) 'm!reminder 10 'm' do the dishes'", - name="reminder", - aliases=["remind", "alert", "timer", "schedule", "setreminder", "setalert", "settimer", "setschedule"], - #usage="m!reminder