feat: Add gift approval
All checks were successful
Build Docker / Build Image (push) Successful in 20s

This commit is contained in:
Nathan Woodburn 2023-11-09 11:27:25 +11:00
parent b9fe89801e
commit b8610e743a
Signed by: nathanwoodburn
GPG Key ID: 203B000478AD0EF1
3 changed files with 99 additions and 19 deletions

95
bot.py
View File

@ -10,11 +10,15 @@ import dns.exception
import dns.message import dns.message
import shaker import shaker
import re import re
import datetime
load_dotenv() load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN') TOKEN = os.getenv('DISCORD_TOKEN')
ADMINID = 0 ADMINID = 0
LOCAL = False
if os.getenv('LOCAL') == "True":
LOCAL = True
intents = discord.Intents.default() intents = discord.Intents.default()
intents.members = True intents.members = True
@ -22,6 +26,15 @@ intents.guilds = True
client = discord.Client(intents=intents) client = discord.Client(intents=intents)
tree = app_commands.CommandTree(client) tree = app_commands.CommandTree(client)
faucet_messages = []
faucet_roles = '/data/faucet.json'
verified_roles = '/data/roles.json'
if LOCAL:
faucet_roles = 'faucet.json'
verified_roles = 'roles.json'
# Commands # Commands
@tree.command(name="faucet", description="Get a free domain") @tree.command(name="faucet", description="Get a free domain")
async def faucet(ctx, email:str): async def faucet(ctx, email:str):
@ -32,29 +45,37 @@ async def faucet(ctx, email:str):
roles = {} roles = {}
if os.path.exists('/data/faucet.json'): if os.path.exists(faucet_roles):
with open('/data/faucet.json', 'r') as f: with open(faucet_roles, 'r') as f:
roles = json.load(f) roles = json.load(f)
if str(ctx.guild.id) in roles: if str(ctx.guild.id) in roles:
if roles[str(ctx.guild.id)] in [role.id for role in ctx.user.roles]: if roles[str(ctx.guild.id)] in [role.id for role in ctx.user.roles]:
await ctx.response.send_message("I'll send you a DM when your domain has been sent",ephemeral=True) await ctx.response.send_message("The faucet will gift you a domain when someone approves your request")
await send_domain(ctx.user, email) message = await ctx.channel.send("Approve this gift by reacting to this message with a 👍")
faucet_messages.append({
"id": message.id,
"email": email,
"user": ctx.user.id,
"time": datetime.datetime.now()
})
print(faucet_messages)
await message.add_reaction("👍")
return return
await ctx.response.send_message("You can't claim from the faucet",ephemeral=True) await ctx.response.send_message("You can't claim from the faucet",ephemeral=True)
@tree.command(name="faucet-role", description="Change the role that can use the faucet") @tree.command(name="setfaucetrole", description="Change the role that can use the faucet")
async def faucetrole(ctx,role:discord.Role): async def faucetrole(ctx,role:discord.Role):
if ctx.user.id != ADMINID: if ctx.user.id != ADMINID:
await ctx.response.send_message("You don't have permission to do that",ephemeral=True) await ctx.response.send_message("You don't have permission to do that",ephemeral=True)
return return
await ctx.response.send_message("Faucet role set to " + role.name + " for server " + ctx.guild.name,ephemeral=True) await ctx.response.send_message("Faucet role set to " + role.name + " for server " + ctx.guild.name,ephemeral=True)
roles = {} roles = {}
if os.path.exists('/data/faucet.json'): if os.path.exists(faucet_roles):
with open('/data/faucet.json', 'r') as f: with open(faucet_roles, 'r') as f:
roles = json.load(f) roles = json.load(f)
roles[str(ctx.guild.id)] = role.id roles[str(ctx.guild.id)] = role.id
with open('/data/faucet.json', 'w') as f: with open(faucet_roles, 'w') as f:
json.dump(roles, f) json.dump(roles, f)
@tree.command(name="setverifiedrole", description="Set the role that verified users get") @tree.command(name="setverifiedrole", description="Set the role that verified users get")
@ -72,15 +93,15 @@ async def setverifiedrole(ctx,role:discord.Role):
await ctx.response.send_message("I don't have permission to do that",ephemeral=True) await ctx.response.send_message("I don't have permission to do that",ephemeral=True)
return return
if not os.path.exists('/data/roles.json'): if not os.path.exists(verified_roles):
with open('/data/roles.json', 'w') as f: with open(verified_roles, 'w') as f:
json.dump({}, f) json.dump({}, f)
with open('/data/roles.json', 'r') as f: with open(verified_roles, 'r') as f:
roles = json.load(f) roles = json.load(f)
roles[str(ctx.guild.id)] = role.id roles[str(ctx.guild.id)] = role.id
with open('/data/roles.json', 'w') as f: with open(verified_roles, 'w') as f:
json.dump(roles, f) json.dump(roles, f)
await ctx.response.send_message("Verified role set to " + role.name + " for server " + ctx.guild.name,ephemeral=True) await ctx.response.send_message("Verified role set to " + role.name + " for server " + ctx.guild.name,ephemeral=True)
@ -155,5 +176,55 @@ async def on_message(message):
if not message.guild: if not message.guild:
await message.channel.send('Invite this bot into your server by using this link:\nhttps://discord.com/api/oauth2/authorize?client_id=1073940877984153692&permissions=402653184&scope=bot') await message.channel.send('Invite this bot into your server by using this link:\nhttps://discord.com/api/oauth2/authorize?client_id=1073940877984153692&permissions=402653184&scope=bot')
# On reaction
@client.event
async def on_reaction_add(reaction, user):
if user == client.user:
return
if not reaction.message.guild:
return
if user.bot:
return
if reaction.message.author != client.user:
return
if reaction.emoji != "👍":
return
print(reaction.message.id)
# If it is within 15 minutes
for faucet_message in faucet_messages:
if faucet_message["id"] == reaction.message.id:
if faucet_message["user"] == user.id and user.id != ADMINID:
await reaction.message.channel.send("You can't approve your own gift")
return
# Verify the approver has the shaker role
if not os.path.exists(verified_roles):
with open(verified_roles, 'w') as f:
json.dump({}, f)
with open(verified_roles, 'r') as f:
roles = json.load(f)
if str(reaction.message.guild.id) in roles:
if roles[str(reaction.message.guild.id)] not in [role.id for role in user.roles]:
await reaction.message.channel.send("You don't have permission to approve this gift")
return
else:
message = "You don't have permission to approve this gift\n"
message += "Run /verify to be eligable to approve gifts"
await reaction.message.channel.send(message)
return
if (datetime.datetime.now() - faucet_message["time"]).total_seconds() > 900:
await reaction.message.channel.send("This gift has expired")
return
resault = await send_domain(faucet_message["user"], faucet_message["email"])
receiver = await client.fetch_user(faucet_message["user"])
await receiver.send(resault)
faucet_messages.remove(faucet_message)
return
client.run(TOKEN) client.run(TOKEN)

View File

@ -11,14 +11,14 @@ async def send_domain(user, email):
emailinfo = validate_email(email, check_deliverability=False) emailinfo = validate_email(email, check_deliverability=False)
email = emailinfo.normalized email = emailinfo.normalized
except EmailNotValidError as e: except EmailNotValidError as e:
await user.send("Your email is invalid") return "Your email is invalid"
return
response = requests.post("https://faucet.woodburn.au/api?email=" + email+"&name="+user.id + "&key=" + os.getenv('FAUCET_KEY')) response = requests.post("https://faucet.woodburn.au/api?email=" + email+"&name="+str(user) + "&key=" + os.getenv('FAUCET_KEY'))
print(response)
print(response.text)
response = response.json() response = response.json()
if response['success']: if response['success']:
await user.send("Congratulations! We've sent you a domain to your email") return "Congratulations! We've sent you a domain to your email"
else: else:
await user.send("Sorry, something went wrong. Please try again later") return "Sorry, something went wrong. Please try again later\n" + response['error']
await user.send(response['error'])

View File

@ -13,6 +13,15 @@ serverIP = os.getenv('DNS_SERVER')
resolver.nameservers = [serverIP] resolver.nameservers = [serverIP]
resolver.port = int(os.getenv('DNS_PORT')) resolver.port = int(os.getenv('DNS_PORT'))
LOCAL = False
if os.getenv('LOCAL') == "True":
LOCAL = True
verified_roles = '/data/roles.json'
if LOCAL:
verified_roles = 'roles.json'
def check_name(user_id: int, name: str) -> bool: def check_name(user_id: int, name: str) -> bool:
try: try:
@ -28,7 +37,7 @@ def check_name(user_id: int, name: str) -> bool:
return False return False
async def handle_role(member: discord.Member, shouldHaveRole: bool): async def handle_role(member: discord.Member, shouldHaveRole: bool):
with open('/data/roles.json', 'r') as f: with open(verified_roles, 'r') as f:
roles = json.load(f) roles = json.load(f)
key = str(member.guild.id) key = str(member.guild.id)