├── LICENSE ├── README.md ├── captchas ├── 1KrcC0cUpsTWhD7FRAFC.png ├── BRzIxoiIusBuehQeyMxK.png ├── K9KKoiyqsU8zVnljJ556.png ├── QfW5VusDpKBxYaolSQ4c.png ├── UrK525J2dBBHxZ49j0GS.png ├── ZNL4GX8W5NcJl3aThs3Q.png ├── a411TcCxsqINRTTs1Zp6.png ├── cLYoHIohv4Q1oQMfzdZQ.png ├── dB7xR41dbEkTIahMPvpr.png ├── dq8KzanfoJ9kEWYqWhTE.png ├── jK023dS8Jvat375H3FCl.png └── mO3BQ3G2ybohlm8WN37S.png ├── config.json └── main.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Chasa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Captcha Verification 2 | Pretty good project that I made, ngl lmao. 3 | 4 | ### Features 5 | * Auto-kick 6 | * 3 Attempts 7 | * No captcha is the same. (62^6 = 56,800,235,584 different captchas) 8 | * If bot is offline, they don't need the role to verify. 9 | * No Multi-Guild Support (yet™) 10 | 11 | No point hiding all of my code behind an encrypted wall, so here it is. 12 | Use it how you want to, even learn a couple things or two. I will go in detail (or sometimes briefly) about how the code works and functions. So if you're a coding nerd like me, you will probably enjoy this. :) 13 | 14 | If you have anything you'd like to add or just want to talk to people who are similar minded, join my [Discord Server](https://chasa.wtf). 15 | -------------------------------------------------------------------------------- /captchas/1KrcC0cUpsTWhD7FRAFC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itschasa/Captcha-Bot/06fc908d0e39813644f5fef9d35ec7cb0719260a/captchas/1KrcC0cUpsTWhD7FRAFC.png -------------------------------------------------------------------------------- /captchas/BRzIxoiIusBuehQeyMxK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itschasa/Captcha-Bot/06fc908d0e39813644f5fef9d35ec7cb0719260a/captchas/BRzIxoiIusBuehQeyMxK.png -------------------------------------------------------------------------------- /captchas/K9KKoiyqsU8zVnljJ556.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itschasa/Captcha-Bot/06fc908d0e39813644f5fef9d35ec7cb0719260a/captchas/K9KKoiyqsU8zVnljJ556.png -------------------------------------------------------------------------------- /captchas/QfW5VusDpKBxYaolSQ4c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itschasa/Captcha-Bot/06fc908d0e39813644f5fef9d35ec7cb0719260a/captchas/QfW5VusDpKBxYaolSQ4c.png -------------------------------------------------------------------------------- /captchas/UrK525J2dBBHxZ49j0GS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itschasa/Captcha-Bot/06fc908d0e39813644f5fef9d35ec7cb0719260a/captchas/UrK525J2dBBHxZ49j0GS.png -------------------------------------------------------------------------------- /captchas/ZNL4GX8W5NcJl3aThs3Q.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itschasa/Captcha-Bot/06fc908d0e39813644f5fef9d35ec7cb0719260a/captchas/ZNL4GX8W5NcJl3aThs3Q.png -------------------------------------------------------------------------------- /captchas/a411TcCxsqINRTTs1Zp6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itschasa/Captcha-Bot/06fc908d0e39813644f5fef9d35ec7cb0719260a/captchas/a411TcCxsqINRTTs1Zp6.png -------------------------------------------------------------------------------- /captchas/cLYoHIohv4Q1oQMfzdZQ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itschasa/Captcha-Bot/06fc908d0e39813644f5fef9d35ec7cb0719260a/captchas/cLYoHIohv4Q1oQMfzdZQ.png -------------------------------------------------------------------------------- /captchas/dB7xR41dbEkTIahMPvpr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itschasa/Captcha-Bot/06fc908d0e39813644f5fef9d35ec7cb0719260a/captchas/dB7xR41dbEkTIahMPvpr.png -------------------------------------------------------------------------------- /captchas/dq8KzanfoJ9kEWYqWhTE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itschasa/Captcha-Bot/06fc908d0e39813644f5fef9d35ec7cb0719260a/captchas/dq8KzanfoJ9kEWYqWhTE.png -------------------------------------------------------------------------------- /captchas/jK023dS8Jvat375H3FCl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itschasa/Captcha-Bot/06fc908d0e39813644f5fef9d35ec7cb0719260a/captchas/jK023dS8Jvat375H3FCl.png -------------------------------------------------------------------------------- /captchas/mO3BQ3G2ybohlm8WN37S.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itschasa/Captcha-Bot/06fc908d0e39813644f5fef9d35ec7cb0719260a/captchas/mO3BQ3G2ybohlm8WN37S.png -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | {"role": 870339389782376459, "channel": 870339395922837554, "guild": 870338653124198470} -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # Config 2 | 3 | # Length of Captcha 4 | length = 6 5 | 6 | # Bot Token 7 | TOKEN = "" 8 | 9 | import discord 10 | from discord.ext import commands 11 | import random 12 | from captcha.image import ImageCaptcha 13 | import string 14 | import json 15 | import os 16 | 17 | bot = commands.Bot(command_prefix="=", case_insensitive=True, intents=discord.Intents.all()) 18 | 19 | config = None 20 | verify_channel = None 21 | verify_role = None 22 | verify_guild = None 23 | 24 | @bot.event 25 | async def on_ready(): 26 | global config 27 | global verify_channel 28 | global verify_role 29 | global verify_guild 30 | print(f"{bot.user} is online.") 31 | print("Loading Config..") 32 | try: 33 | config = json.loads(open("config.json", "r").read()) 34 | except: 35 | print("No config found! Run =setup in your server!") 36 | else: 37 | verify_guild = bot.get_guild(config["guild"]) 38 | verify_channel = bot.get_channel(config["channel"]) 39 | verify_role = verify_guild.get_role(config["role"]) 40 | print("Loaded Config!") 41 | 42 | 43 | @bot.event 44 | async def on_member_join(member): 45 | global config 46 | global verify_channel 47 | global verify_role 48 | global verify_guild 49 | if member.guild.id == int(config["guild"]): 50 | await member.add_roles(verify_role) 51 | text = ''.join(random.choice(string.ascii_uppercase + string.digits + string.ascii_lowercase) for _ in range(length)) 52 | file_name = ''.join(random.choice(string.ascii_uppercase + string.digits + string.ascii_lowercase) for _ in range(20)) 53 | image = ImageCaptcha(width=280, height=90) 54 | captcha = image.generate(text) 55 | image.write(text, f"captchas\\{file_name}.png") 56 | file = discord.File(f"captchas//{file_name}.png", filename=f"{file_name}.png") 57 | embed = discord.Embed(title="Verification", description="This server is using Captcha Verification\n to protect their server.\n\nPlease type out the letters you see in\nthe captcha below.\n\n**Note:** The captcha is **case-sensitive.**\n\nYou have **30 seconds** to reply.", color=0x9f4fd1, image=f"attachment://") 58 | embed.set_image(url=f"attachment://{file_name}.png") 59 | del_msgs = [] 60 | msg = await verify_channel.send(content=member.mention, embed=embed, file=file) 61 | del_msgs.append(msg) 62 | def wait_for_reply(message): 63 | return message.channel == verify_channel and message.author == member 64 | for x in range(3): 65 | try: 66 | rpy = await bot.wait_for("message", check=wait_for_reply, timeout=30) 67 | except: 68 | try: await member.kick(reason="Verification Timeout.") 69 | except: pass 70 | break 71 | else: 72 | if rpy.content == text: 73 | await member.remove_roles(verify_role) 74 | for x in del_msgs: 75 | await x.delete() 76 | await rpy.delete() 77 | return 78 | else: 79 | if x != 2: 80 | msg = await verify_channel.send(f"{member.mention} Invalid, you have {2 - x} attempts left.") 81 | del_msgs.append(msg) 82 | del_msgs.append(rpy) 83 | try: await member.kick(reason="Too many attempts.") 84 | except: pass 85 | for x in del_msgs: 86 | try: 87 | await x.delete() 88 | except: 89 | continue 90 | await rpy.delete() 91 | 92 | @bot.event 93 | async def on_channel_create(channel): 94 | global config 95 | global verify_channel 96 | global verify_role 97 | global verify_guild 98 | if channel.id == int(config["channel"]): 99 | try: 100 | overwrites = {verify_role: discord.PermissionOverwrite( 101 | read_messages=False, 102 | send_messages=False, 103 | add_reactions=False 104 | )} 105 | await channel.edit(overwrites=overwrites) 106 | except: 107 | pass 108 | 109 | @bot.command() 110 | @commands.guild_only() 111 | @commands.has_permissions(administrator=True) 112 | async def setup(ctx): 113 | if os.path.exists("config.json"): 114 | await ctx.send("config.json already exists!") 115 | return 116 | global config 117 | msg = await ctx.send("Setting up guild...") 118 | role = await ctx.guild.create_role(name="Verifing") 119 | for channel in ctx.guild.channels: 120 | try: 121 | overwrites = {role: discord.PermissionOverwrite( 122 | read_messages=False, 123 | send_messages=False, 124 | add_reactions=False 125 | )} 126 | await channel.edit(overwrites=overwrites) 127 | except: 128 | pass 129 | overwrites = { 130 | ctx.guild.default_role: discord.PermissionOverwrite( 131 | read_messages=False, 132 | send_messages=False, 133 | ), 134 | role: discord.PermissionOverwrite( 135 | read_messages=True, 136 | send_messages=True, 137 | ) 138 | } 139 | channel = await ctx.guild.create_text_channel(name="verify-here", overwrites=overwrites, slowmode_delay=10) 140 | con_json = {"role": role.id, "channel": channel.id, "guild": ctx.guild.id} 141 | config = con_json 142 | conf = open("config.json", "a") 143 | conf.write(json.dumps(con_json)) 144 | conf.close() 145 | await msg.edit(content="Finished Setup!") 146 | 147 | @bot.command() 148 | @commands.guild_only() 149 | @commands.has_permissions(administrator=True) 150 | async def perms_setup(ctx): 151 | if not os.path.exists("config.json"): 152 | await ctx.send("config.json doesn't exists!") 153 | return 154 | global config 155 | msg = await ctx.send("Rechecking perms...") 156 | for channel in ctx.guild.channels: 157 | try: 158 | overwrites = {verify_role: discord.PermissionOverwrite( 159 | read_messages=False, 160 | send_messages=False, 161 | add_reactions=False 162 | )} 163 | await channel.edit(overwrites=overwrites) 164 | except: 165 | pass 166 | overwrites = { 167 | ctx.guild.default_role: discord.PermissionOverwrite( 168 | read_messages=False, 169 | send_messages=False, 170 | ), 171 | verify_role: discord.PermissionOverwrite( 172 | read_messages=True, 173 | send_messages=True, 174 | ) 175 | } 176 | await msg.edit("Finished Setup!") 177 | 178 | bot.run(TOKEN) 179 | --------------------------------------------------------------------------------