From f98c17421a2f58c2f110a91a5c1888823e8f0238 Mon Sep 17 00:00:00 2001 From: rqi14 Date: Wed, 3 Nov 2021 14:58:52 +0000 Subject: [PATCH 01/14] Add wildcard support for email domains --- bot.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 2fac303..8f1aeee 100644 --- a/bot.py +++ b/bot.py @@ -8,6 +8,7 @@ from sendgrid.helpers.mail import Mail import requests from keep_alive import keep_alive +import fnmatch conn = sqlite3.connect('bot.db') c = conn.cursor() @@ -115,6 +116,12 @@ def mailgun_send(email_address, verification_code): "subject": "Verify your server email", "text": str(verification_code)}) +def domain_wildcard_match(domain_to_verify, domains_allowed): + for da in domains_allowed: + if fnmatch.fnmatch(domain_to_verify, da): + return True + return False + intents = discord.Intents.default() intents.members = True @@ -165,7 +172,7 @@ async def on_message(message): if len(guild_domains) == 0: continue guild_domains = guild_domains.split('|') - if message_content.split("@")[1] in guild_domains: + if domain_wildcard_match(message_content.split("@")[1],guild_domains): verif_list.append(i) if len(verif_list) >= 1: random_code = random.randint(100000, 999999) From 768a7b6599d8125d4d8e65ee96432242c1918614 Mon Sep 17 00:00:00 2001 From: rqi14 Date: Wed, 3 Nov 2021 20:06:38 +0000 Subject: [PATCH 02/14] Add SMTP support Including STARTTLS --- README.md | 6 ++++++ bot.py | 45 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index ebcbd73..9784874 100644 --- a/README.md +++ b/README.md @@ -51,12 +51,18 @@ pip install -r requirements.txt Before running it make sure these environment variables are set. You will need a [Sendgrid](https://sendgrid.com/docs/for-developers/sending-email/api-getting-started/) and [Discord](https://discordpy.readthedocs.io/en/latest/discord.html#discord-intro) account (both are free). Optionally consider making a [Mailgun](https://documentation.mailgun.com/en/latest/quickstart-sending.html#how-to-start-sending-email) account, since this bot uses Mailgun when Sendgrid fails to send an email: +SMTP will be used first, if failed, Sendgrid, if failed again, Mailgun. Set SMTP_USE_STARTTLS to 'true' if using STARTTLS ``` export SENDGRID_API_KEY='YOUR_SENDGRID_API_KEY' export SENDGRID_EMAIL='YOUR_SENDGRID_EMAIL' export DISCORD_TOKEN='YOUR_DISCORD_TOKEN' export MAILGUN_API_KEY='YOUR_MAILGUN_API_KEY' export MAILGUN_DOMAIN='YOUR_MAILGUN_DOMAIN' +export 'SMTP_USER'='YOUR_SMTP_EMAIL_ADDRESS' +export 'SMTP_SERVER'='YOUR_SMTP_SERVER' +export 'SMTP_PORT'='YOUR_SMTP_SERVER_PORT' +export 'SMTP_PASSWORD'='YOUR_SMTP_PASSWORD' +export 'SMTP_USE_STARTTLS'='true' ``` Run the bot with: diff --git a/bot.py b/bot.py index 8f1aeee..df1c9f5 100644 --- a/bot.py +++ b/bot.py @@ -9,6 +9,8 @@ import requests from keep_alive import keep_alive import fnmatch +import smtplib +from email.mime.text import MIMEText conn = sqlite3.connect('bot.db') c = conn.cursor() @@ -122,6 +124,23 @@ def domain_wildcard_match(domain_to_verify, domains_allowed): return True return False +def smtp_send(email_address, verification_code): + user_email = os.environ.get('SMTP_USER') + smtp_server = os.environ.get('SMTP_SERVER') + smtp_port = os.environ.get('SMTP_PORT') + smtp_pswd = os.environ.get('SMTP_PASSWORD') + smtp_use_starttls = os.environ.get('SMTP_USE_STARTTLS') == 'true' + with smtplib.SMTP(smtp_server,smtp_port) as sv: + if smtp_use_starttls: + sv.starttls() + sv.login(user_email, smtp_pswd) + receiver = email_address + msg = MIMEText(f'Your verification code is {verification_code}. Please reply to EmailBot in the discord server') + msg['Subject'] = 'Verification code for Baobaomen discord' + msg['From'] = user_email + msg['To'] = receiver + sv.sendmail(user_email, receiver, msg.as_string()) + intents = discord.Intents.default() intents.members = True @@ -184,19 +203,23 @@ async def on_message(message): to_emails=message_content, subject='Verify your server email', html_content=str(random_code)) - try: - sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY')) - response = sg.send(emailmessage) - print(response.status_code) - print(response.body) - print(response.headers) - await message.channel.send("Email sent. **Reply here with your verification code**. If you haven't received it, check your spam folder.") + try : + smtp_send(message_content, random_code) + print('Email sent') except Exception as e: - mailgun_email = mailgun_send(message_content, random_code) - if mailgun_email.status_code == 200: + try: + sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY')) + response = sg.send(emailmessage) + print(response.status_code) + print(response.body) + print(response.headers) await message.channel.send("Email sent. **Reply here with your verification code**. If you haven't received it, check your spam folder.") - else: - await message.channel.send("Email failed to send.") + except Exception as ee: + mailgun_email = mailgun_send(message_content, random_code) + if mailgun_email.status_code == 200: + await message.channel.send("Email sent. **Reply here with your verification code**. If you haven't received it, check your spam folder.") + else: + await message.channel.send("Email failed to send.") else: await message.channel.send("Invalid email.") else: From 88ad2ae01c9520d6c1fa53939baf3783ab85e10c Mon Sep 17 00:00:00 2001 From: rqi14 Date: Wed, 3 Nov 2021 20:10:25 +0000 Subject: [PATCH 03/14] Fix bug - SMTP port not changed type to int --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index df1c9f5..e5b468e 100644 --- a/bot.py +++ b/bot.py @@ -127,7 +127,7 @@ def domain_wildcard_match(domain_to_verify, domains_allowed): def smtp_send(email_address, verification_code): user_email = os.environ.get('SMTP_USER') smtp_server = os.environ.get('SMTP_SERVER') - smtp_port = os.environ.get('SMTP_PORT') + smtp_port = int(os.environ.get('SMTP_PORT')) smtp_pswd = os.environ.get('SMTP_PASSWORD') smtp_use_starttls = os.environ.get('SMTP_USE_STARTTLS') == 'true' with smtplib.SMTP(smtp_server,smtp_port) as sv: From b7d13ec8daa576035db61ab5bdd9e5ef13e2b744 Mon Sep 17 00:00:00 2001 From: rqi14 Date: Thu, 4 Nov 2021 00:25:22 +0000 Subject: [PATCH 04/14] Fix no robot reply after sending email using smtp --- bot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bot.py b/bot.py index e5b468e..be1fa9e 100644 --- a/bot.py +++ b/bot.py @@ -206,6 +206,7 @@ async def on_message(message): try : smtp_send(message_content, random_code) print('Email sent') + await message.channel.send("Email sent. **Reply here with your verification code**. If you haven't received it, check your spam folder.") except Exception as e: try: sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY')) From 563d167dbde4d3d341ee53b56c233573f95de5d6 Mon Sep 17 00:00:00 2001 From: rqi14 Date: Thu, 4 Nov 2021 00:26:31 +0000 Subject: [PATCH 05/14] Fix indent --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index be1fa9e..7be4b2e 100644 --- a/bot.py +++ b/bot.py @@ -206,7 +206,7 @@ async def on_message(message): try : smtp_send(message_content, random_code) print('Email sent') - await message.channel.send("Email sent. **Reply here with your verification code**. If you haven't received it, check your spam folder.") + await message.channel.send("Email sent. **Reply here with your verification code**. If you haven't received it, check your spam folder.") except Exception as e: try: sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY')) From c94b7416c7dd3f5d3d6b2dc6385c7f1821b26969 Mon Sep 17 00:00:00 2001 From: rqi14 Date: Thu, 4 Nov 2021 00:32:31 +0000 Subject: [PATCH 06/14] Cooldown for on_message To prevent someone keeping sending messages to overload the API --- bot.py | 172 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 93 insertions(+), 79 deletions(-) diff --git a/bot.py b/bot.py index e5b468e..1e66a5b 100644 --- a/bot.py +++ b/bot.py @@ -1,3 +1,4 @@ +import typing import discord from discord.ext import commands import sqlite3 @@ -173,89 +174,102 @@ async def on_member_join(member): role = discord.utils.get(member.guild.roles, name=check_on_join[3]) await member.add_roles(role) -@client.event -async def on_message(message): - if message.author == client.user: - return - message_content = message.content.strip() - if (message.guild == None) and email_check(message_content): - users_guilds = get_users_guilds(message.author.id) - if len(users_guilds) >= 1: - guild_list = [i[1] for i in users_guilds if i[4] == 0] - verif_list = [] - for i in guild_list: - email_guild = get_emails_guilds(i, message_content) - if len(email_guild) > 0: - continue - guild_domains = get_domains(i) - if len(guild_domains) == 0: - continue - guild_domains = guild_domains.split('|') - if domain_wildcard_match(message_content.split("@")[1],guild_domains): - verif_list.append(i) - if len(verif_list) >= 1: - random_code = random.randint(100000, 999999) - for i in verif_list: - insert_code(random_code, message.author.id, i) - insert_email(message_content, message.author.id, i) - emailmessage = Mail( - from_email=os.environ.get('SENDGRID_EMAIL'), - to_emails=message_content, - subject='Verify your server email', - html_content=str(random_code)) - try : - smtp_send(message_content, random_code) - print('Email sent') - except Exception as e: - try: - sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY')) - response = sg.send(emailmessage) - print(response.status_code) - print(response.body) - print(response.headers) - await message.channel.send("Email sent. **Reply here with your verification code**. If you haven't received it, check your spam folder.") - except Exception as ee: - mailgun_email = mailgun_send(message_content, random_code) - if mailgun_email.status_code == 200: +class MessageCog(commands.Cog): + def __init__(self, bot): + self.bot = bot + self._cd = commands.CooldownMapping.from_cooldown(1, 6.0, commands.BucketType.member) # Change accordingly + # rate, per, BucketType + + def get_ratelimit(self, message: discord.Message) -> typing.Optional[int]: + """Returns the ratelimit left""" + bucket = self._cd.get_bucket(message) + return bucket.update_rate_limit() + + @commands.Cog.listener() + async def on_message(message): + if message.author == client.user: + return + message_content = message.content.strip() + if (message.guild == None) and email_check(message_content): + users_guilds = get_users_guilds(message.author.id) + if len(users_guilds) >= 1: + guild_list = [i[1] for i in users_guilds if i[4] == 0] + verif_list = [] + for i in guild_list: + email_guild = get_emails_guilds(i, message_content) + if len(email_guild) > 0: + continue + guild_domains = get_domains(i) + if len(guild_domains) == 0: + continue + guild_domains = guild_domains.split('|') + if domain_wildcard_match(message_content.split("@")[1],guild_domains): + verif_list.append(i) + if len(verif_list) >= 1: + random_code = random.randint(100000, 999999) + for i in verif_list: + insert_code(random_code, message.author.id, i) + insert_email(message_content, message.author.id, i) + emailmessage = Mail( + from_email=os.environ.get('SENDGRID_EMAIL'), + to_emails=message_content, + subject='Verify your server email', + html_content=str(random_code)) + try : + smtp_send(message_content, random_code) + print('Email sent') + except Exception as e: + try: + sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY')) + response = sg.send(emailmessage) + print(response.status_code) + print(response.body) + print(response.headers) await message.channel.send("Email sent. **Reply here with your verification code**. If you haven't received it, check your spam folder.") - else: - await message.channel.send("Email failed to send.") - else: - await message.channel.send("Invalid email.") - else: - await message.channel.send("You have not joined a server.") - elif (len(message_content) == 6) and message_content.isdigit(): - verif_code = int(message_content) - prev_codes_f = get_users_codes(message.author.id, verif_code) - prev_codes_g = [i for i in prev_codes_f if i[4] == 0] - prev_codes = [] - for i in prev_codes_g: - user_emails = get_emails_guilds(i[1], i[2]) - if len(user_emails) >= 1: - continue + except Exception as ee: + mailgun_email = mailgun_send(message_content, random_code) + if mailgun_email.status_code == 200: + await message.channel.send("Email sent. **Reply here with your verification code**. If you haven't received it, check your spam folder.") + else: + await message.channel.send("Email failed to send.") + else: + await message.channel.send("Invalid email.") else: - prev_codes.append(i) - if len(prev_codes) >= 1: - for i in prev_codes: - verify_user(message.author.id, i[1]) - curr_guild = client.get_guild(i[1]) - guild_db = get_guild(i[1]) - role = discord.utils.get(curr_guild.roles, name=guild_db[3]) - if role: - member = curr_guild.get_member(message.author.id) - if role not in member.roles: - await member.add_roles(role) + await message.channel.send("You have not joined a server.") + elif (len(message_content) == 6) and message_content.isdigit(): + verif_code = int(message_content) + prev_codes_f = get_users_codes(message.author.id, verif_code) + prev_codes_g = [i for i in prev_codes_f if i[4] == 0] + prev_codes = [] + for i in prev_codes_g: + user_emails = get_emails_guilds(i[1], i[2]) + if len(user_emails) >= 1: + continue else: - await curr_guild.create_role(name=guild_db[3]) + prev_codes.append(i) + if len(prev_codes) >= 1: + for i in prev_codes: + verify_user(message.author.id, i[1]) + curr_guild = client.get_guild(i[1]) + guild_db = get_guild(i[1]) role = discord.utils.get(curr_guild.roles, name=guild_db[3]) - member = curr_guild.get_member(message.author.id) - await member.add_roles(role) - await message.channel.send("You have been verified on " + client.get_guild(i[1]).name + ".") - else: - await message.channel.send("Incorrect code.") - elif message.guild == None: - await message.channel.send("Invalid email.") - await client.process_commands(message) + if role: + member = curr_guild.get_member(message.author.id) + if role not in member.roles: + await member.add_roles(role) + else: + await curr_guild.create_role(name=guild_db[3]) + role = discord.utils.get(curr_guild.roles, name=guild_db[3]) + member = curr_guild.get_member(message.author.id) + await member.add_roles(role) + await message.channel.send("You have been verified on " + client.get_guild(i[1]).name + ".") + else: + await message.channel.send("Incorrect code.") + elif message.guild == None: + await message.channel.send("Invalid email.") + await client.process_commands(message) + +client.add_cog(MessageCog(client)) @client.event async def on_guild_join(guild): From 2e2521bb8af65c8bd4b007635e7601dc894940d6 Mon Sep 17 00:00:00 2001 From: rqi14 Date: Thu, 4 Nov 2021 00:34:30 +0000 Subject: [PATCH 07/14] Merge --- bot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bot.py b/bot.py index 1e66a5b..6805ffc 100644 --- a/bot.py +++ b/bot.py @@ -218,6 +218,7 @@ async def on_message(message): try : smtp_send(message_content, random_code) print('Email sent') + await message.channel.send("Email sent. **Reply here with your verification code**. If you haven't received it, check your spam folder.") except Exception as e: try: sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY')) From 6e48714e29b1c328104688fe609ac1e326b74444 Mon Sep 17 00:00:00 2001 From: rqi14 Date: Thu, 4 Nov 2021 00:37:40 +0000 Subject: [PATCH 08/14] Fix bug in on_message cog --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 6805ffc..3af4622 100644 --- a/bot.py +++ b/bot.py @@ -186,7 +186,7 @@ def get_ratelimit(self, message: discord.Message) -> typing.Optional[int]: return bucket.update_rate_limit() @commands.Cog.listener() - async def on_message(message): + async def on_message(self, message): if message.author == client.user: return message_content = message.content.strip() From 704d911d9ab163fcaad0ebae5b76ca1c1d0b04f7 Mon Sep 17 00:00:00 2001 From: rqi14 Date: Thu, 4 Nov 2021 00:42:48 +0000 Subject: [PATCH 09/14] rate limit functionality --- bot.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/bot.py b/bot.py index 3af4622..1453bb9 100644 --- a/bot.py +++ b/bot.py @@ -189,6 +189,15 @@ def get_ratelimit(self, message: discord.Message) -> typing.Optional[int]: async def on_message(self, message): if message.author == client.user: return + # Getting the ratelimit left + ratelimit = self.get_ratelimit(message) + print(f'Rate limit: {ratelimit}') + if ratelimit is None: + # The user is not ratelimited, you can add the XP or level up the user here + pass + else: + await message.channel.send("You are rate-limited. Please try again later.") + message_content = message.content.strip() if (message.guild == None) and email_check(message_content): users_guilds = get_users_guilds(message.author.id) From 7d062ed2d9e15d46916734396cfa84e000c7510b Mon Sep 17 00:00:00 2001 From: rqi14 Date: Thu, 4 Nov 2021 00:44:30 +0000 Subject: [PATCH 10/14] rate limit - abort if limited --- bot.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 1453bb9..034d099 100644 --- a/bot.py +++ b/bot.py @@ -177,7 +177,7 @@ async def on_member_join(member): class MessageCog(commands.Cog): def __init__(self, bot): self.bot = bot - self._cd = commands.CooldownMapping.from_cooldown(1, 6.0, commands.BucketType.member) # Change accordingly + self._cd = commands.CooldownMapping.from_cooldown(1, 15.0, commands.BucketType.member) # Change accordingly # rate, per, BucketType def get_ratelimit(self, message: discord.Message) -> typing.Optional[int]: @@ -197,6 +197,7 @@ async def on_message(self, message): pass else: await message.channel.send("You are rate-limited. Please try again later.") + return message_content = message.content.strip() if (message.guild == None) and email_check(message_content): From 7b7526bfbfd6e4d85626c7c1f15cc4c922af05d0 Mon Sep 17 00:00:00 2001 From: rqi14 Date: Thu, 4 Nov 2021 00:46:13 +0000 Subject: [PATCH 11/14] Change to an appropriate email subject --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 034d099..1da31a1 100644 --- a/bot.py +++ b/bot.py @@ -137,7 +137,7 @@ def smtp_send(email_address, verification_code): sv.login(user_email, smtp_pswd) receiver = email_address msg = MIMEText(f'Your verification code is {verification_code}. Please reply to EmailBot in the discord server') - msg['Subject'] = 'Verification code for Baobaomen discord' + msg['Subject'] = 'Verify your discord server email' msg['From'] = user_email msg['To'] = receiver sv.sendmail(user_email, receiver, msg.as_string()) From 6c6d505ae57d57789285f884549105b23f1ee360 Mon Sep 17 00:00:00 2001 From: rqi14 Date: Thu, 4 Nov 2021 03:11:02 +0000 Subject: [PATCH 12/14] Add preliminary unverify support --- bot.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/bot.py b/bot.py index 1da31a1..f214f98 100644 --- a/bot.py +++ b/bot.py @@ -63,6 +63,10 @@ def verify_user(userid, guildid): c.execute("UPDATE users SET verified=1 WHERE userid=? AND guildid=?", (userid, guildid)) conn.commit() +def unverify_user(userid, guildid): + c.execute("UPDATE users SET verified=0 WHERE userid=? AND guildid=?", (userid, guildid)) + conn.commit() + def get_domains(guildid): return get_guild(guildid)[1] @@ -392,5 +396,22 @@ async def verify(ctx): elif user_prev_verify[4] == 0: await ctx.author.send(verify_msg(ctx.guild, check_on_join[1])) +@client.command() +async def unverify(ctx): + if ctx.guild: + check_on_join = get_guild(ctx.guild.id) + if check_on_join == None: + new_guild(ctx.guild.id) + unverify_user(ctx.author.id,ctx.guild.id) + insert_email("", ctx.author.id, ctx.guild.id) + curr_guild = client.get_guild(ctx.guild.id) + guild_db = get_guild(ctx.guild.id) + role = discord.utils.get(curr_guild.roles, name=guild_db[3]) + member = curr_guild.get_member(ctx.author.id) + await client.remove_roles(member, role) + await ctx.author.send('You have been unverified') + + + keep_alive() client.run(os.environ.get('DISCORD_TOKEN')) From b50f8781b644480def45cb8e877e1bc3e9bfa823 Mon Sep 17 00:00:00 2001 From: rqi14 Date: Thu, 4 Nov 2021 03:58:54 +0000 Subject: [PATCH 13/14] Bug fix - on_message processed all messages instead of dm only --- bot.py | 13 ++++++++----- poetry.lock | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/bot.py b/bot.py index f214f98..fbbd1dd 100644 --- a/bot.py +++ b/bot.py @@ -181,7 +181,7 @@ async def on_member_join(member): class MessageCog(commands.Cog): def __init__(self, bot): self.bot = bot - self._cd = commands.CooldownMapping.from_cooldown(1, 15.0, commands.BucketType.member) # Change accordingly + self._cd = commands.CooldownMapping.from_cooldown(1, 6.0, commands.BucketType.member) # Change accordingly # rate, per, BucketType def get_ratelimit(self, message: discord.Message) -> typing.Optional[int]: @@ -191,8 +191,10 @@ def get_ratelimit(self, message: discord.Message) -> typing.Optional[int]: @commands.Cog.listener() async def on_message(self, message): + if message.guild: + return if message.author == client.user: - return + return # Getting the ratelimit left ratelimit = self.get_ratelimit(message) print(f'Rate limit: {ratelimit}') @@ -282,7 +284,7 @@ async def on_message(self, message): await message.channel.send("Incorrect code.") elif message.guild == None: await message.channel.send("Invalid email.") - await client.process_commands(message) + # await client.process_commands(message) client.add_cog(MessageCog(client)) @@ -361,6 +363,7 @@ async def vstatus(ctx): new_guild(ctx.guild.id) check_on_join = get_guild(ctx.guild.id) on_join = bool(check_on_join[2]) + print('request vstatus') await ctx.send("```" + "Ping: " + "{0}ms".format(round(client.latency * 1000)) + "\n" + "User commands: " + "\n" + @@ -408,8 +411,8 @@ async def unverify(ctx): guild_db = get_guild(ctx.guild.id) role = discord.utils.get(curr_guild.roles, name=guild_db[3]) member = curr_guild.get_member(ctx.author.id) - await client.remove_roles(member, role) - await ctx.author.send('You have been unverified') + await member.remove_roles(role) + await ctx.author.send(f'You have been unverified on {curr_guild.name}.') diff --git a/poetry.lock b/poetry.lock index 9bcbdc7..790fd55 100644 --- a/poetry.lock +++ b/poetry.lock @@ -478,20 +478,39 @@ markupsafe = [ {file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"}, {file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"}, {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"}, + {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5"}, {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"}, {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"}, + {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f"}, + {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0"}, + {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7"}, {file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"}, {file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"}, {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"}, + {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193"}, {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"}, {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, + {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1"}, + {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1"}, + {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f"}, {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b"}, {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, + {file = "MarkupSafe-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c"}, + {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb"}, + {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014"}, + {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850"}, + {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85"}, + {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621"}, + {file = "MarkupSafe-1.1.1-cp39-cp39-win32.whl", hash = "sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39"}, + {file = "MarkupSafe-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8"}, {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, ] mccabe = [ From ac97da57a5e73e848eff0762c185cf21068b4690 Mon Sep 17 00:00:00 2001 From: rqi14 Date: Mon, 24 Jan 2022 14:31:58 +0000 Subject: [PATCH 14/14] Update README.md --- README.md | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 9784874..1b35a8c 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,12 @@ -

- -

- -**EmailBot** allows you to verify that your Discord server members have an email address with a specific domain. - -[![Discord](https://img.shields.io/discord/731028346569228288)](https://discord.gg/MfFMxu9) [![License](https://img.shields.io/badge/license-GPL-brightgreen)](LICENSE) - -> Invite: https://discord.com/api/oauth2/authorize?client_id=731027450607435846&permissions=268503040&scope=bot - -> Discord server: https://discord.gg/MfFMxu9 - ## Usage -After [inviting](https://discord.com/api/oauth2/authorize?client_id=731027450607435846&permissions=268503040&scope=bot) the bot to your server, a domain must be added using `.dominadd domain`. `.vstatus` is the help command: +After inviting the bot to your server, a domain must be added using `.dominadd domain`. `.vstatus` is the help command: ``` User commands: .verify -> Sends a DM to the user to verify their email .vstatus -> This help message + .unverify -> unverify self Admin commands: - A domain must be added before users can be verified. @@ -35,7 +24,7 @@ Verified role (default=Verified): Verified ## Example -Let's say you want a Discord server just for people who have a @randomuniversity.edu email address. Add this bot to your server and when someone joins, they will get a DM asking for their @randomuniversity.edu email address. The bot then emails them a verification code. If they reply with the correct code, they get the "Verified" role. +Let's say you want a Discord server just for people who have a @randomuniversity.edu email address. Add this bot to your server and when someone joins, they will get a DM asking for their @randomuniversity.edu email address. The bot then emails them a verification code. If they reply with the correct code, they get the "Verified" role. Wildcard can be used for email domain, such as *.randomuniversity.edu