2023-07-14 19:47:41 +00:00
# db - msg_id, user_id, guild_id
2023-08-01 21:52:03 +00:00
import asyncio
2023-07-14 19:47:41 +00:00
import discord
import os
import json
from dotenv import load_dotenv
from discord . ui import Modal , InputText
2023-07-14 20:57:01 +00:00
from discord . utils import get
2023-08-09 20:54:38 +00:00
from discord . ext import commands
2023-08-08 15:34:51 +00:00
from dbutil import MessageDB
2023-08-10 20:29:21 +00:00
from dbutil import GuildAppDB
2023-07-14 19:47:41 +00:00
load_dotenv ( )
TOKEN = os . getenv ( " TOKEN " )
SERVER_NAME = os . getenv ( " SERVER_NAME " )
2023-07-15 21:32:28 +00:00
CHANNEL_ID = os . getenv ( " CHANNEL_ID " )
2023-07-14 19:47:41 +00:00
bot = discord . Bot ( intents = discord . Intents . all ( ) )
2023-07-15 21:32:28 +00:00
channel_id = int ( CHANNEL_ID )
2023-07-14 19:47:41 +00:00
2023-08-09 20:08:23 +00:00
questions = [
" What is your Minecraft username? " ,
" How did you learn about CraftTopia? (If it was from a friend or a website we would like to know either who or where just to know where credit is due) " ,
" Have you been a part of a minecraft community before, if so, let us know what your experience was with that community. " ,
" How old are you? " ,
" Do you have a good microphone for proximity chat? " ,
" Do you plan on spending at least 2-3 hours a week on the server (our current definition of active) " ,
" What will you be able to do to help us grow and build our community? " ,
" Any other questions or concerns? "
]
2023-07-14 19:47:41 +00:00
max_questions = len ( questions )
@bot.event
async def on_ready ( ) :
bot . add_view ( ApplicationButtonsView ( ) )
2023-07-18 14:02:42 +00:00
bot . add_view ( ApplicationStartButtonView ( ) )
2023-08-09 22:08:45 +00:00
activity = discord . Activity ( name = f " { len ( bot . guilds ) } guilds " , type = discord . ActivityType . listening )
await bot . change_presence ( activity = activity , status = discord . Status . online )
2023-07-14 19:47:41 +00:00
print ( f " Logged in as { bot . user } " )
2023-08-10 20:29:21 +00:00
for i in bot . guilds :
if str ( i . id ) not in GuildAppDB . get_all_guilds ( ) :
GuildAppDB . create_guild ( str ( i . id ) , i . name )
print ( f " entry for { i . id } created " )
2023-07-14 19:47:41 +00:00
2023-08-09 22:08:45 +00:00
@bot.event
async def on_guild_join ( guild ) :
activity = discord . Activity ( name = f " { len ( bot . guilds ) } guilds " , type = discord . ActivityType . listening )
await bot . change_presence ( activity = activity , status = discord . Status . online )
2023-08-10 20:29:21 +00:00
GuildAppDB . create_guild ( str ( guild . id ) , guild . name )
print ( f " Joined guild { guild . name } : { guild . id } " )
2023-08-09 22:08:45 +00:00
@bot.event
async def on_guild_remove ( guild ) :
activity = discord . Activity ( name = f " { len ( bot . guilds ) } guilds " , type = discord . ActivityType . listening )
await bot . change_presence ( activity = activity , status = discord . Status . online )
2023-08-10 20:29:21 +00:00
print ( f " Removed from guild { guild . name } : { guild . id } " )
2023-08-09 22:08:45 +00:00
2023-07-15 21:32:28 +00:00
@bot.slash_command ( description = " Command used to apply " )
2023-07-14 19:47:41 +00:00
async def apply ( ctx ) :
await ctx . response . send_message ( content = " Application started " , ephemeral = True )
user = await ctx . author . create_dm ( )
await user . send ( " Hey! Your application has started. You have 300 seconds to complete it. " )
application = { ' userId ' : ctx . author . id }
2023-08-09 20:08:23 +00:00
for i in range ( 0 , max_questions ) :
embed = discord . Embed ( title = f ' Question [ { i + 1 } / { max_questions } ] ' , description = questions [ i ] )
2023-07-14 19:47:41 +00:00
await user . send ( embed = embed )
response = await bot . wait_for ( ' message ' , check = lambda m : m . author == ctx . author and m . channel == user , timeout = 300 )
application [ f ' question { i } ' ] = response . content
try :
with open ( ' applications.json ' , ' r ' ) as f :
data = json . load ( f )
except ( FileNotFoundError , json . JSONDecodeError ) :
data = [ ]
data . append ( application )
with open ( ' applications.json ' , ' w ' ) as f :
json . dump ( data , f )
channel = bot . get_channel ( channel_id )
embed = discord . Embed ( title = ' Application: ' + ctx . author . display_name )
2023-08-09 20:08:23 +00:00
for i in range ( 0 , max_questions ) :
2023-07-16 08:53:39 +00:00
embed . add_field ( name = f ' { questions [ i ] } ' , value = application [ f ' question { i } ' ] , inline = False )
2023-07-14 19:47:41 +00:00
embed . set_footer ( text = f " Applicant ID: { ctx . author . id } " )
appView = ApplicationButtonsView ( )
msg = await channel . send ( embed = embed , view = appView )
print ( msg . id )
2023-08-08 15:34:51 +00:00
MessageDB . add_application_msg ( msg . id , ctx . author . id , ctx . guild . id )
2023-07-14 19:47:41 +00:00
await user . send ( ' Thank you for applying! ' )
class ApplicationButtonsView ( discord . ui . View ) :
def __init__ ( self ) :
super ( ) . __init__ ( timeout = None )
@discord.ui.button (
label = " Accept " ,
style = discord . ButtonStyle . green ,
custom_id = f " persistent:accept " ,
)
async def accept ( self , button : discord . ui . Button , interaction : discord . Interaction ) :
msg_id = str ( interaction . message . id )
2023-08-08 15:34:51 +00:00
user_id , guild_id = MessageDB . get_application_msg ( msg_id )
2023-08-01 21:54:41 +00:00
2023-07-14 19:47:41 +00:00
modal = ApplicationModal ( title = f " Accepting: { bot . get_user ( user_id ) . display_name } " )
modal . set_action ( " acc " )
modal . add_item ( discord . ui . InputText ( label = f " Reason: " ) )
await interaction . response . send_modal ( modal )
@discord.ui.button (
label = " Decline " ,
style = discord . ButtonStyle . red ,
custom_id = f " persistent:decline " ,
)
async def decline ( self , button : discord . ui . Button , interaction : discord . Interaction ) :
msg_id = str ( interaction . message . id )
2023-08-08 15:34:51 +00:00
user_id , guild_id = MessageDB . get_application_msg ( msg_id )
2023-08-01 21:54:07 +00:00
2023-07-14 19:47:41 +00:00
modal = ApplicationModal ( title = f " Declining: { bot . get_user ( user_id ) . display_name } " )
modal . set_action ( " dec " )
modal . add_item ( discord . ui . InputText ( label = f " Reason: " ) )
await interaction . response . send_modal ( modal )
class ApplicationModal ( discord . ui . Modal ) :
def set_action ( self , action ) :
self . action = action
async def callback ( self , interaction : discord . Interaction ) :
reason = self . children [ 0 ] . value
msg_id = str ( interaction . message . id )
2023-08-08 15:34:51 +00:00
user_id , guild_id = MessageDB . get_application_msg ( msg_id )
2023-07-14 19:47:41 +00:00
if self . action == " acc " :
user = await bot . get_user ( user_id ) . create_dm ( )
await user . send ( f " You have been accepted to the CreatTopia Minecraft server! " )
await user . send ( f " Reason: { reason } " )
await interaction . response . send_message ( content = " Application accepted " , ephemeral = True )
2023-07-14 20:57:01 +00:00
role = get ( interaction . message . guild . roles , name = " CreatTopian " )
await discord . utils . get ( interaction . message . guild . members , id = int ( user_id ) ) . add_roles ( role )
2023-07-15 21:32:28 +00:00
emb = interaction . message . embeds [ 0 ]
emb . colour = discord . Colour . green ( )
2023-07-16 09:10:19 +00:00
embed = discord . Embed ( title = ' Accepted ' )
embed . add_field ( name = f ' Reason: ' , value = reason , inline = False )
embed . colour = discord . Colour . green ( )
await interaction . followup . edit_message ( message_id = interaction . message . id , embeds = [ emb , embed ] )
2023-08-04 13:40:40 +00:00
view = discord . ui . View . from_message ( interaction . message )
view . disable_all_items ( )
await interaction . followup . edit_message ( message_id = interaction . message . id , view = view )
2023-07-14 19:47:41 +00:00
if self . action == " dec " :
user = await bot . get_user ( user_id ) . create_dm ( )
await user . send ( f " You have been declined access to the CreatTopia Minecraft server. " )
await user . send ( f " Reason: { reason } " )
await interaction . response . send_message ( content = " Application declined " , ephemeral = True )
2023-07-15 21:32:28 +00:00
emb = interaction . message . embeds [ 0 ]
emb . colour = discord . Colour . red ( )
2023-07-16 09:10:19 +00:00
embed = discord . Embed ( title = ' Declined ' )
embed . add_field ( name = f ' Reason: ' , value = reason , inline = False )
embed . colour = discord . Colour . red ( )
await interaction . followup . edit_message ( message_id = interaction . message . id , embeds = [ emb , embed ] )
2023-08-04 13:40:40 +00:00
view = discord . ui . View . from_message ( interaction . message )
view . disable_all_items ( )
await interaction . followup . edit_message ( message_id = interaction . message . id , view = view )
2023-07-14 19:47:41 +00:00
2023-08-09 20:54:38 +00:00
@commands.has_permissions ( administrator = True )
2023-07-17 10:26:28 +00:00
@bot.slash_command ( description = " Command used to set up the application prompt " )
async def setup ( ctx ) :
embed = discord . Embed ( title = " **Start your application!** " )
embed . add_field ( name = " Click the button below to start your application " , value = " " , inline = False )
appStartView = ApplicationStartButtonView ( )
await ctx . response . send_message ( " Message set up " , ephemeral = True )
await ctx . channel . send ( embeds = [ embed ] , view = appStartView )
2023-08-09 20:54:38 +00:00
@setup.error
async def on_application_command_error ( ctx , error ) :
if isinstance ( error , commands . MissingPermissions ) :
await ctx . respond ( " You need Administrator permissions to use this command " , ephemeral = True )
else :
raise error
2023-07-17 10:26:28 +00:00
class ApplicationStartButtonView ( discord . ui . View ) :
def __init__ ( self ) :
super ( ) . __init__ ( timeout = None )
@discord.ui.button (
label = " Start application! " ,
style = discord . ButtonStyle . green ,
custom_id = f " persistent:start_application " ,
)
async def start_app ( self , button : discord . ui . Button , interaction : discord . Interaction ) :
user = await interaction . user . create_dm ( )
2023-07-18 14:02:42 +00:00
embedd = discord . Embed ( title = f ' CreaTopia Application ' , description = " Hey! Your application has started. You have 300 seconds to complete it. " )
embedd . add_field ( value = f ' You can cancel the application by answering " cancel " to any of the questions ' , name = " " , inline = False )
2023-08-01 20:35:23 +00:00
try :
await user . send ( embed = embedd )
except discord . Forbidden :
2023-08-01 21:52:03 +00:00
await interaction . response . send_message ( content = " Can ' t start application. Please allow direct messages from server members in your privacy settings. " , ephemeral = True )
2023-08-01 20:35:23 +00:00
return
await interaction . response . send_message ( content = " Application started " , ephemeral = True )
2023-07-17 10:26:28 +00:00
application = { ' userId ' : interaction . user . id }
2023-08-09 20:08:23 +00:00
for i in range ( 0 , max_questions ) :
2023-08-01 20:42:18 +00:00
try :
2023-08-09 20:08:23 +00:00
embed = discord . Embed ( title = f ' Question [ { i + 1 } / { max_questions } ] ' , description = questions [ i ] )
2023-08-01 20:42:18 +00:00
await user . send ( embed = embed )
response = await bot . wait_for ( ' message ' , check = lambda m : m . author == interaction . user and m . channel == user , timeout = 300 )
if response . content . startswith ( " cancel " ) :
await user . send ( " Your application has been cancelled " )
return
else :
application [ f ' question { i } ' ] = response . content
2023-08-01 21:52:03 +00:00
except asyncio . TimeoutError :
await user . send ( content = " As you haven ' t replied in 300 seconds, your application has been cancelled " )
return
2023-07-17 10:26:28 +00:00
try :
with open ( ' applications.json ' , ' r ' ) as f :
data = json . load ( f )
except ( FileNotFoundError , json . JSONDecodeError ) :
data = [ ]
data . append ( application )
with open ( ' applications.json ' , ' w ' ) as f :
json . dump ( data , f )
channel = bot . get_channel ( channel_id )
embed = discord . Embed ( title = ' Application: ' + interaction . user . display_name )
2023-08-09 20:08:23 +00:00
for i in range ( 0 , max_questions ) :
2023-07-17 10:26:28 +00:00
embed . add_field ( name = f ' { questions [ i ] } ' , value = application [ f ' question { i } ' ] , inline = False )
embed . set_footer ( text = f " Applicant ID: { interaction . user . id } " )
appView = ApplicationButtonsView ( )
msg = await channel . send ( embed = embed , view = appView )
print ( msg . id )
2023-08-08 15:34:51 +00:00
MessageDB . add_application_msg ( msg . id , interaction . user . id , interaction . guild . id )
2023-07-17 10:26:28 +00:00
await user . send ( ' Thank you for applying! ' )
2023-07-14 19:47:41 +00:00
bot . run ( TOKEN )