-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
352 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"token": "DISCORD-BOT-TOKEN", | ||
"guild-id": "DISCORD-SERVER-ID", | ||
|
||
"stock-command-silent": false, | ||
"remove-capture-from-stock": true, | ||
|
||
"gen-channels": [12345], | ||
"admins": [0], | ||
"roles": [ | ||
{ | ||
"id": 0, | ||
"cooldown": 60, | ||
"gen-access": ["netflix"] | ||
}, | ||
{ | ||
"id": 0, | ||
"cooldown": 30, | ||
"gen-access": ["all"] | ||
} | ||
], | ||
|
||
"messages": { | ||
"noperms": "You do not have permissions to use this command.", | ||
"wrongchannel": ":thinking: ", | ||
"altsent": "Thank you for using AtluzkaGEN", | ||
"footer-msg": "github.com/Atluzka/account-gen-bot" | ||
}, | ||
|
||
"generate-settings": { | ||
"gif-img-url": "https://media.discordapp.net/attachments/807809192537882647/1119647605140488242/C02ECC68-ACE2-4293-8992-BE67B45E6378.gif" | ||
}, | ||
|
||
"colors": { | ||
"error": 16713025, | ||
"success": 1288807, | ||
"stock": 7229605 | ||
}, | ||
|
||
"_comment1": "Size for uploading stock. Default: 2097152 == 2mb", | ||
"maximum-file-size": 2097152 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
import discord, json, sqlite3 | ||
from discord import app_commands | ||
from datetime import timedelta | ||
from typing import List | ||
|
||
from src import database | ||
from src import utils | ||
|
||
# connect to the database | ||
con = sqlite3.connect('accounts.db'); con.row_factory = sqlite3.Row | ||
|
||
# discord bot stuff | ||
bot = discord.Client(intents=discord.Intents.default()) | ||
tree = app_commands.CommandTree(bot) | ||
config = json.load(open('config.json')) | ||
|
||
serviceList = [] | ||
is_everything_ready = False | ||
|
||
async def updateServices(): | ||
global serviceList | ||
serviceList = await database.getServices(con) | ||
return | ||
|
||
user_cooldown = [] | ||
|
||
@bot.event | ||
async def on_ready(): | ||
global is_everything_ready | ||
await tree.sync(guild=discord.Object(id=config["guild-id"])) | ||
|
||
await updateServices() | ||
print("Servicelist:", serviceList) | ||
|
||
is_everything_ready = True | ||
print("Logged in as {0.user}".format(bot)) | ||
|
||
async def service_autcom(interaction: discord.Interaction, current: str) -> List[app_commands.Choice[str]]: | ||
types = serviceList | ||
return [ | ||
app_commands.Choice(name=service, value=service) | ||
for service in types if current.lower() in service.lower() | ||
] | ||
|
||
@tree.command(name = "deleteservice", description = "(admin only)", guild=discord.Object(id=config["guild-id"])) | ||
@app_commands.autocomplete(service=service_autcom) | ||
async def deleteservice(interaction: discord.Interaction, service: str): | ||
|
||
if not interaction.user.id in config['admins']: | ||
return await interaction.response.send_message(str(config['messages']['noperms']), ephemeral=True) | ||
|
||
if not is_everything_ready: | ||
return await interaction.response.send_message("Bot is starting.", ephemeral=True) | ||
|
||
db_res1 = await database.deleteService(con, service, serviceList) | ||
if db_res1: | ||
await updateServices() | ||
|
||
embd=discord.Embed( | ||
title=f"Delete Service", | ||
description=f'{"Successfully deleted service" if db_res1 else "Error. Service doesnt exist."}', | ||
color=int(config['colors']['success']) if db_res1 else int(config['colors']['error']) | ||
) | ||
embd.set_footer(text=config['messages']['footer-msg']) | ||
|
||
return await interaction.response.send_message(embed=embd, ephemeral=True) | ||
|
||
async def gen_cooldown(interaction: discord.Interaction): | ||
if interaction.user.id in config['admins']: | ||
return None | ||
|
||
userRoles = [role.id for role in interaction.user.roles] | ||
minCooldown = float("inf") | ||
|
||
for role in config["roles"]: | ||
if int(role["id"]) in userRoles and float(role["cooldown"]) < minCooldown: | ||
minCooldown = float(role["cooldown"]) | ||
|
||
if not minCooldown == float("inf"): | ||
if interaction.user.id in user_cooldown: | ||
return app_commands.Cooldown(1, str(timedelta(seconds=minCooldown).total_seconds())) | ||
else: | ||
return None | ||
else: | ||
if interaction.user.id in user_cooldown: | ||
return app_commands.Cooldown(1, str(timedelta(seconds=config['roles'][0]["cooldown"]).total_seconds())) | ||
else: | ||
return None | ||
|
||
@tree.command(name = "gen", description = "Generate an account of your choice", guild=discord.Object(id=config["guild-id"])) | ||
@app_commands.autocomplete(service=service_autcom) | ||
@app_commands.checks.dynamic_cooldown(gen_cooldown) | ||
async def gen(interaction: discord.Interaction, service: str): | ||
global user_cooldown | ||
|
||
if not is_everything_ready: | ||
return await interaction.response.send_message("Bot is starting.", ephemeral=True) | ||
|
||
if service not in serviceList: | ||
return await interaction.response.send_message(f'Invalid service.', ephemeral=True) | ||
|
||
if not interaction.user.id in config['admins'] and not interaction.channel_id in config["gen-channels"]: | ||
channel_list = [f"<#{channel}>" for channel in config["gen-channels"]] | ||
return await interaction.response.send_message(str(config['messages']['wrongchannel']) + ', '.join(channel_list), ephemeral=True) | ||
|
||
utl_res = await utils.does_user_meet_requirements(interaction.user.roles, config, service) | ||
if not interaction.user.id in config['admins'] and not utl_res: | ||
return await interaction.response.send_message(str(config['messages']['noperms']), ephemeral=True) | ||
|
||
# Cooldown | ||
if interaction.user.id in user_cooldown: | ||
user_cooldown.remove(interaction.user.id) | ||
embd=discord.Embed(title="Cooldown",description=f':no_entry_sign: This command is on cooldown.',color=config['colors']['error']) | ||
return await interaction.response.send_message(embed=embd, ephemeral=False) | ||
if interaction.user.id not in config['admins']: | ||
user_cooldown.append(interaction.user.id) | ||
|
||
success, account = await database.getAccount(con, service) | ||
if not success: | ||
user_cooldown.remove(interaction.user.id) | ||
return await interaction.response.send_message(f"There is no stock left.", ephemeral=True) | ||
else: | ||
|
||
channel = await interaction.user.create_dm() | ||
embd=discord.Embed( | ||
title=f"Account Generated :label: ", | ||
description=config['messages']['altsent'] + f"\n```{account['combo']}```", | ||
color=config['colors']['success'] | ||
) | ||
embd.set_footer(text=config['messages']['footer-msg'],icon_url=interaction.user.avatar.url) | ||
|
||
embd2=discord.Embed(title=f"`{service}` generated :label: ",description=':incoming_envelope: Check your DMs for the account.',color=config['colors']['success']) | ||
embd2.set_footer(text=config['messages']['footer-msg'],icon_url=interaction.user.avatar.url) | ||
embd2.set_image(url=config["generate-settings"]["gif-img-url"]) | ||
|
||
await channel.send(embed=embd) | ||
return await interaction.response.send_message(embed=embd2, ephemeral=False) | ||
|
||
@gen.error | ||
async def gencmd_error(interaction: discord.Interaction, error): | ||
if isinstance(error, app_commands.CommandOnCooldown): | ||
embd=discord.Embed(title="Cooldown",description=f':no_entry_sign: This command is on cooldown, try again in {(error.retry_after/60):.2f} minutes.',color=config['colors']['error']) | ||
await interaction.response.send_message(embed=embd, ephemeral=False) | ||
|
||
@tree.command(name = "addstock", description = "Add stock to database (admin only)", guild=discord.Object(id=config["guild-id"])) | ||
@app_commands.autocomplete(service=service_autcom) | ||
async def addaccounts(interaction: discord.Interaction, service: str, file: discord.Attachment): | ||
|
||
if not interaction.user.id in config['admins']: | ||
return await interaction.response.send_message(str(config['messages']['noperms']), ephemeral=True) | ||
|
||
if not is_everything_ready: | ||
return await interaction.response.send_message("Bot is starting.", ephemeral=True) | ||
|
||
if service not in serviceList: | ||
return await interaction.response.send_message(f'Invalid service.', ephemeral=True) | ||
|
||
try: | ||
if not str(file.filename).endswith(".txt"): | ||
return await interaction.response.send_message(f'You can only upload files with .txt extension', ephemeral=True) | ||
except: | ||
return await interaction.response.send_message(f'Error when checking file.', ephemeral=True) | ||
|
||
if file.size > config["maximum-file-size"]: | ||
return await interaction.response.send_message(f'Maximum file size: `{config["maximum-file-size"]} bytes`', ephemeral=True) | ||
content = await file.read() | ||
|
||
filtered_stock = [] | ||
dec_cont = content.decode('utf-8') | ||
content = str(dec_cont).split("\n") | ||
for item in content: | ||
if len(item) > 2: | ||
filtered_stock.append(item) | ||
add_cnt,dupe_cnt = await database.addStock(con, service, filtered_stock, config['remove-capture-from-stock']) | ||
return await interaction.response.send_message(f'`{add_cnt}` accounts have been added to the `{service}` database. `{dupe_cnt}` dupes found.', ephemeral=True) | ||
|
||
@tree.command(name = "createservice", description = "(admin only)", guild=discord.Object(id=config["guild-id"])) | ||
async def createservice(interaction: discord.Interaction, servicename: str): | ||
|
||
if not interaction.user.id in config['admins']: | ||
return await interaction.response.send_message(str(config['messages']['noperms']), ephemeral=True) | ||
|
||
if not is_everything_ready: | ||
return await interaction.response.send_message("Bot is starting.", ephemeral=True) | ||
|
||
db_res1 = await database.createService(con, servicename, serviceList) | ||
if db_res1: | ||
await updateServices() | ||
|
||
embd=discord.Embed( | ||
title=f"Create Service", | ||
description=f'{"Successfully created service" if db_res1 else "Error. Service already exists."}', | ||
color=int(config['colors']['success']) if db_res1 else int(config['colors']['error']) | ||
) | ||
embd.set_footer(text=config['messages']['footer-msg']) | ||
|
||
return await interaction.response.send_message(embed=embd, ephemeral=True) | ||
|
||
@tree.command(name = "stock", description = "Get the amount of stock", guild=discord.Object(id=config["guild-id"])) | ||
async def stock(interaction: discord.Interaction): | ||
|
||
if not is_everything_ready: | ||
return await interaction.response.send_message("Bot is starting.", ephemeral=True) | ||
|
||
stock = await database.getStock(con, serviceList) | ||
if len(stock) <= 0: | ||
embd=discord.Embed( | ||
title=f"Stock - 0 services", | ||
description='There are no services to display', | ||
color=config['colors']['stock']) | ||
embd.set_footer(text=config['messages']['footer-msg']) | ||
return await interaction.response.send_message(embed=embd) | ||
|
||
filtered_stock = [] | ||
for stk in stock: | ||
stk = (stk.split(':')) | ||
filtered_stock.append(f"**{stk[0]}**: `{stk[1]}`") | ||
|
||
embd=discord.Embed( | ||
title=f"Stock - {len(filtered_stock)}", | ||
description='\n'.join(filtered_stock), | ||
color=config['colors']['stock'] | ||
) | ||
embd.set_footer(text=config['messages']['footer-msg']) | ||
|
||
return await interaction.response.send_message(embed=embd, ephemeral=config['stock-command-silent']) | ||
|
||
bot.run(config['token']) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
async def getServices(con): | ||
serviceslist = [] | ||
cur = con.cursor(); cur.execute("SELECT name FROM sqlite_master WHERE type='table';") | ||
table_names = cur.fetchall(); cur.close() | ||
for table in table_names: | ||
if str(table[0]).split('_')[0] == 'accounts': | ||
serviceslist.append(str(table[0]).split('_')[1].lower()) | ||
return serviceslist | ||
|
||
async def createService(con, table_name, servicelist): | ||
if table_name.lower() not in servicelist: | ||
cur = con.cursor() | ||
cur.execute(f'CREATE TABLE IF NOT EXISTS accounts_{table_name.lower()}(combo TEXT NOT NULL)') | ||
con.commit() | ||
cur.close() | ||
return True | ||
else: | ||
return False | ||
|
||
async def deleteService(con, table_name, servicelist): | ||
if table_name.lower() in servicelist: | ||
cur = con.cursor() | ||
cur.execute(f"DROP TABLE accounts_{table_name.lower()}") | ||
con.commit() | ||
cur.close() | ||
return True | ||
else: | ||
return False | ||
|
||
async def getAccount(con, service): | ||
cursor = con.cursor() | ||
name = f"accounts_{service}" | ||
cursor.execute(f"SELECT COUNT(*) FROM {name}") | ||
row_count = cursor.fetchone()[0] | ||
if row_count > 0: | ||
cursor.execute(f"SELECT * FROM {name} ORDER BY RANDOM() LIMIT 1") | ||
account = cursor.fetchone() | ||
cursor.execute(f"DELETE FROM {name} WHERE combo = '{account[0]}'") | ||
con.commit() | ||
cursor.close() | ||
return True,account | ||
else: | ||
cursor.close() | ||
return False,None | ||
|
||
async def addStock(con, service, stock, remove_capture): | ||
cursor = con.cursor() | ||
dupe_amount = 0 | ||
already_added = [] | ||
for account in stock: | ||
try: | ||
if not account in already_added: | ||
already_added.append(account) | ||
if "|" in account and remove_capture: | ||
account = account.split('|')[0] | ||
values = (account) | ||
cursor.execute(f"INSERT INTO accounts_{service}(combo) VALUES(?)",(values,)) | ||
else: | ||
dupe_amount += 1 | ||
except Exception as e: | ||
print(e) | ||
con.commit() | ||
cursor.close() | ||
return len(already_added),dupe_amount | ||
|
||
async def getStock(con, serviceList): | ||
stock = [] | ||
cursor = con.cursor() | ||
for service in serviceList: | ||
name = f'accounts_{service}' | ||
cursor.execute(f"SELECT COUNT(*) FROM {name}") | ||
row_count = cursor.fetchone()[0] | ||
txt_cnt = "Out of stock" if row_count <= 0 else row_count | ||
stock.append(f"{service}:{txt_cnt}") | ||
return stock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
async def does_user_meet_requirements(user_roles, config, service_input): | ||
user_roles = [role.id for role in user_roles] | ||
for role in config["roles"]: | ||
if role['id'] in user_roles: | ||
if service_input in role['gen-access'] or "all" in role['gen-access']: | ||
return True | ||
return False |