346 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			346 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#!/home/nonroot/discord_verification/venv/bin/python3
 | 
						|
 | 
						|
import discord
 | 
						|
import math
 | 
						|
import requests
 | 
						|
from discord.ext import commands
 | 
						|
from discord.ext.tasks import loop
 | 
						|
from discord import HTTPException
 | 
						|
from settings import token, get_connection_playtime, get_connection_xenforo
 | 
						|
 | 
						|
intents = discord.Intents.default()
 | 
						|
intents.members = True
 | 
						|
client = discord.Client(intents=intents)
 | 
						|
 | 
						|
def count_hours(res_all_):
 | 
						|
    ip_counter = 0
 | 
						|
    total_time_hours = 0
 | 
						|
    total_time_minutes = 0
 | 
						|
    ze_time_hours = 0
 | 
						|
    ze_time_minutes = 0
 | 
						|
    zr_time_hours = 0
 | 
						|
    zr_time_minutes = 0
 | 
						|
    mg_time_hours = 0
 | 
						|
    mg_time_minutes = 0
 | 
						|
    jb_time_hours = 0
 | 
						|
    jb_time_minutes = 0
 | 
						|
 | 
						|
    if res_all_:
 | 
						|
        for res in res_all_:
 | 
						|
            ip_counter += 1
 | 
						|
            ze_time = res[0]
 | 
						|
            mg_time = res[1]
 | 
						|
            zr_time = res[2]
 | 
						|
            jb_time = res[3]
 | 
						|
            allowed = res[4]
 | 
						|
            ze_time_hours_local = math.floor((ze_time / 60) / 60)
 | 
						|
            ze_time_hours += ze_time_hours_local
 | 
						|
            ze_time_minutes += math.floor((ze_time / 60) - (ze_time_hours_local * 60))
 | 
						|
 | 
						|
            mg_time_hours_local = math.floor((mg_time / 60) / 60)
 | 
						|
            mg_time_hours += mg_time_hours_local
 | 
						|
            mg_time_minutes += math.floor((mg_time / 60) - (mg_time_hours_local * 60))
 | 
						|
 | 
						|
            zr_time_hours_local = math.floor((zr_time / 60) / 60)
 | 
						|
            zr_time_hours += zr_time_hours_local
 | 
						|
            zr_time_minutes += math.floor((zr_time / 60) - (zr_time_hours_local * 60))
 | 
						|
 | 
						|
            jb_time_hours_local = math.floor((jb_time / 60) / 60)
 | 
						|
            jb_time_hours += jb_time_hours_local
 | 
						|
            jb_time_minutes += math.floor((jb_time / 60) - (jb_time_hours_local * 60))
 | 
						|
 | 
						|
        extra_hour_ze = math.floor(ze_time_minutes / 60)
 | 
						|
        if extra_hour_ze > 0:
 | 
						|
            ze_time_hours += extra_hour_ze
 | 
						|
            ze_time_minutes -= extra_hour_ze * 60
 | 
						|
 | 
						|
        extra_hour_mg = math.floor(mg_time_minutes / 60)
 | 
						|
        if extra_hour_mg > 0:
 | 
						|
            mg_time_hours += extra_hour_mg
 | 
						|
            mg_time_minutes -= extra_hour_mg * 60
 | 
						|
 | 
						|
        extra_hour_zr = math.floor(zr_time_minutes / 60)
 | 
						|
        if extra_hour_zr > 0:
 | 
						|
            zr_time_hours += extra_hour_zr
 | 
						|
            zr_time_minutes -= extra_hour_zr * 60
 | 
						|
 | 
						|
        extra_hour_jb = math.floor(jb_time_minutes / 60)
 | 
						|
        if extra_hour_jb > 0:
 | 
						|
            jb_time_hours += extra_hour_jb
 | 
						|
            jb_time_minutes -= extra_hour_jb * 60
 | 
						|
 | 
						|
        total_time_hours = ze_time_hours + mg_time_hours + zr_time_hours + jb_time_hours
 | 
						|
        total_time_minutes = ze_time_minutes + mg_time_minutes + zr_time_minutes + jb_time_minutes
 | 
						|
        extra_hour = math.floor(total_time_minutes / 60)
 | 
						|
        if extra_hour > 0:
 | 
						|
            total_time_hours += extra_hour
 | 
						|
            total_time_minutes = math.floor(total_time_minutes - (extra_hour * 60))
 | 
						|
    return ip_counter, total_time_hours, total_time_minutes, ze_time_hours, ze_time_minutes, zr_time_hours, zr_time_minutes, mg_time_hours, mg_time_minutes, jb_time_hours, jb_time_minutes
 | 
						|
 | 
						|
async def generate_hours_message(steam_id2_, steam_id64_, res_all_, steam_account, discord_id, res_user_id, target_name, message, first_account, steam_id2__):
 | 
						|
    extra_msg = ""
 | 
						|
    if first_account:
 | 
						|
        extra_msg = "\n\nSECOND STEAM ACCOUNT:\n"
 | 
						|
 | 
						|
    #ofc some fucking steam players have dynamic ip's
 | 
						|
    if steam_id2_ and steam_id2_ != steam_id2__:
 | 
						|
        first_account = True
 | 
						|
        steam_account = f"{extra_msg}Steam ID: {steam_id2_}. \nSteam URL: https://steamcommunity.com/profiles/{steam_id64_} \n"
 | 
						|
        ip_counter, total_time_hours, total_time_minutes, ze_time_hours, ze_time_minutes, zr_time_hours, zr_time_minutes, mg_time_hours, mg_time_minutes, jb_time_hours, jb_time_minutes = count_hours(res_all_)
 | 
						|
 | 
						|
        await message.channel.send(f"""{steam_account}Your steam Account(s) connected from a total of {ip_counter} different IP addresses.\nYour discord account ({discord_id}) is associated to an unloze forum account: https://unloze.com/members/.{res_user_id[0]}/\nPlayer: {target_name}\nZE playtime: {ze_time_hours} hours {ze_time_minutes} minutes.\nMG playtime: {mg_time_hours} hours {mg_time_minutes} minutes.\nZR playtime: {zr_time_hours} hours {zr_time_minutes} minutes.\nJB playtime: {jb_time_hours} hours {jb_time_minutes} minutes. \n\nYou need a total of 200 hours gametime for being allowed into the discord automatically: \nTotal Playtime: {total_time_hours} hours {total_time_minutes} minutes.""")
 | 
						|
    return first_account
 | 
						|
 | 
						|
def xenforo_query(cur, discord_id):
 | 
						|
    sql_statement = """
 | 
						|
        select * from unloze_forum_2.xf_user_connected_account e
 | 
						|
        where e.provider_key = '%s'
 | 
						|
        """
 | 
						|
    cur.execute(sql_statement, [discord_id])
 | 
						|
    res_user_id = cur.fetchone()
 | 
						|
    return res_user_id
 | 
						|
 | 
						|
def run_steam_queries(res_user_id, cur):
 | 
						|
	#have to check both steam and th_cap_steam
 | 
						|
    sql_statement = """
 | 
						|
        select * from unloze_forum_2.xf_user_connected_account e
 | 
						|
        where e.provider = 'steam' and e.user_id = %s and LENGTH(e.provider_key) > 0
 | 
						|
        """
 | 
						|
    cur.execute(sql_statement, [res_user_id[0]])
 | 
						|
    res = cur.fetchone()
 | 
						|
 | 
						|
    res_all_1, steam_id2_1, steam_id64_1 = check_both_steam_connections_types(res)
 | 
						|
 | 
						|
    sql_statement = """
 | 
						|
        select * from unloze_forum_2.xf_user_connected_account e
 | 
						|
        where e.provider = 'th_cap_steam' and e.user_id = %s and LENGTH(e.provider_key) > 0
 | 
						|
    """
 | 
						|
    cur.execute(sql_statement, [res_user_id[0]])
 | 
						|
    res = cur.fetchone()
 | 
						|
 | 
						|
    res_all_2, steam_id2_2, steam_id64_2 = check_both_steam_connections_types(res)
 | 
						|
 | 
						|
    return res_all_1, steam_id2_1, steam_id64_1, res_all_2, steam_id2_2, steam_id64_2
 | 
						|
 | 
						|
def from_steam64(sid):
 | 
						|
    y = int(sid) - 76561197960265728
 | 
						|
    x = y % 2 
 | 
						|
    return "STEAM_0:{}:{}".format(x, (y - x) // 2)
 | 
						|
 | 
						|
def check_both_steam_connections_types(res):
 | 
						|
    if not res:
 | 
						|
        return None, None, None
 | 
						|
    steam_id64 = res[2].decode("utf-8")
 | 
						|
    steam_id2 = from_steam64(steam_id64)
 | 
						|
    with get_connection_playtime() as conn2:
 | 
						|
        with conn2.cursor(buffered=True) as cur2:
 | 
						|
            sql_statement = """
 | 
						|
                select ze_time, mg_time, zr_time, jb_time, discord_allowed from unloze_playtimestats.player_time pt
 | 
						|
                 where pt.steam_id = %s
 | 
						|
            """
 | 
						|
            cur2.execute(sql_statement, [steam_id2])
 | 
						|
            res_all = cur2.fetchall()
 | 
						|
        conn2.close()
 | 
						|
    return res_all, steam_id2, steam_id64
 | 
						|
 | 
						|
def gen_steam_acount_str(steam_id2_1, steam_id2_2, steam_id64_1, steam_id64_2):
 | 
						|
    steam_account = ""
 | 
						|
    if steam_id2_1:
 | 
						|
        steam_account += f"Steam ID: {steam_id2_1} \nSteam URL: https://steamcommunity.com/profiles/{steam_id64_1} \n"
 | 
						|
    if steam_id2_2 and steam_id2_2 not in steam_account:
 | 
						|
        steam_account += f"Steam ID: {steam_id2_2} \nSteam URL: https://steamcommunity.com/profiles/{steam_id64_2} \n"
 | 
						|
    return steam_account
 | 
						|
 | 
						|
@client.event
 | 
						|
async def on_message(message):
 | 
						|
    if message.author.bot:
 | 
						|
        return
 | 
						|
    if client.user.mentioned_in(message):
 | 
						|
        if ('#STEAM_') in message.content:
 | 
						|
            steam_id = message.content.split("#")[1]
 | 
						|
            with get_connection_playtime() as conn2:
 | 
						|
                with conn2.cursor(buffered=True) as cur2:
 | 
						|
                    sql_statement = """
 | 
						|
                        select ze_time, mg_time, zr_time, jb_time, discord_allowed from unloze_playtimestats.player_time pt
 | 
						|
                         where pt.steam_id = %s
 | 
						|
                    """
 | 
						|
                    cur2.execute(sql_statement, [steam_id])
 | 
						|
                    res_all = cur2.fetchall()
 | 
						|
                conn2.close()
 | 
						|
            if not res_all:
 | 
						|
                await message.channel.send("Steam ID not found/valid")
 | 
						|
                return
 | 
						|
            ip_counter, total_time_hours, total_time_minutes, ze_time_hours, ze_time_minutes, zr_time_hours, zr_time_minutes, mg_time_hours, mg_time_minutes, jb_time_hours, jb_time_minutes = count_hours(res_all)
 | 
						|
            await message.channel.send(f"""Steam ID: {steam_id} \nZE playtime: {ze_time_hours} hours {ze_time_minutes} minutes.\nMG playtime: {mg_time_hours} hours {mg_time_minutes} minutes.\nZR playtime: {zr_time_hours} hours {zr_time_minutes} minutes.\nJB playtime: {jb_time_hours} hours {jb_time_minutes} minutes. """)
 | 
						|
            return
 | 
						|
        msg = message
 | 
						|
        discord_id = message.author.id
 | 
						|
        target_name = message.author.name
 | 
						|
        for t in message.mentions:
 | 
						|
            if not t.bot:
 | 
						|
                discord_id = t.id
 | 
						|
                target_name = t.name
 | 
						|
                break
 | 
						|
        if discord_id == message.author.id:
 | 
						|
            try:
 | 
						|
                msg_content = message.content.split("> ")[1]
 | 
						|
                for member1 in message.channel.members:
 | 
						|
                    if member1.name.startswith(msg_content) or member1.name.lower().startswith(msg_content):
 | 
						|
                        discord_id = member1.id
 | 
						|
                        target_name = member1.name
 | 
						|
                        break
 | 
						|
            except Exception:
 | 
						|
                pass
 | 
						|
        
 | 
						|
        with get_connection_xenforo() as conn:
 | 
						|
            with conn.cursor(buffered=True) as cur: #wtf is this buffered shit even
 | 
						|
                res_user_id = xenforo_query(cur, discord_id)
 | 
						|
                if not res_user_id:
 | 
						|
                    await message.channel.send(f"{target_name} Your discord account ({discord_id}) is not associated to any unloze forum account. Create a forum account and associate discord")
 | 
						|
                else:
 | 
						|
                    res_all_1, steam_id2_1, steam_id64_1, res_all_2, steam_id2_2, steam_id64_2 = run_steam_queries(res_user_id, cur)
 | 
						|
                    steam_account = gen_steam_acount_str(steam_id2_1, steam_id2_2, steam_id64_1, steam_id64_2)
 | 
						|
                    if res_all_1 is None and res_all_2 is None:
 | 
						|
                        await message.channel.send(f"{target_name} Your discord account ({discord_id}) is associated to an unloze forum account: https://unloze.com/members/.{res_user_id[0]}/\nBut there is no steam account associated. Associate your steam account.")
 | 
						|
                    elif (res_all_1 is not None and res_all_2 is not None and len(res_all_1) == 0 and len(res_all_2) == 0) or (res_all_1 is not None and len(res_all_1) == 0 and res_all_2 is None) or (res_all_2 is not None and len(res_all_2) == 0 and res_all_1 is None):
 | 
						|
                        await message.channel.send(f"{steam_account}Your discord account ({discord_id}) is associated to an unloze forum account: https://unloze.com/members/.{res_user_id[0]}/\nPlayer: {target_name}\nYour steam Account(s) have no play time at all on the gameservers. You need 200 hours for being allowed into the discord server.")
 | 
						|
                    else:
 | 
						|
                        first_account = False
 | 
						|
                        first_account = await generate_hours_message(steam_id2_1, steam_id64_1, res_all_1, steam_account, discord_id, res_user_id, target_name, message, first_account, None)
 | 
						|
                        await generate_hours_message(steam_id2_2, steam_id64_2, res_all_2, steam_account, discord_id, res_user_id, target_name, message, first_account, steam_id2_1)
 | 
						|
            conn.close()
 | 
						|
 | 
						|
 | 
						|
async def update_asn(ipv4, steam_id2_, client, discord_id, member, bad_asn, steam_account, res_user_id, cur2, conn2):
 | 
						|
    do_allow = True
 | 
						|
    try:
 | 
						|
        r = requests.get(f"https://ipinfo.io/{ipv4}")
 | 
						|
        asn = r.json()["org"].split(" ")[0]
 | 
						|
    except Exception:
 | 
						|
        asn = 'failed'
 | 
						|
    sql_statement = """
 | 
						|
            update unloze_playtimestats.player_time
 | 
						|
            set asn = %s where ipv4 = %s
 | 
						|
    """
 | 
						|
    cur2.execute(sql_statement, [asn, ipv4])
 | 
						|
    for asn1 in bad_asn:
 | 
						|
        if asn == asn1:
 | 
						|
            do_allow = False
 | 
						|
            sql_statement = """
 | 
						|
               update unloze_playtimestats.player_time
 | 
						|
               set discord_allowed = 1 where steam_id = %s
 | 
						|
            """
 | 
						|
            if asn == 'failed':
 | 
						|
                asn_status = f"Users IP address failed ASN verification:\nIPV4: {ipv4}\n"
 | 
						|
            else:
 | 
						|
                asn_status = f"Users ASN is related to a bad guy:\nASN: {asn}.\nIPV4: {ipv4}\n "
 | 
						|
            cur2.execute(sql_statement, [steam_id2_])
 | 
						|
            conn2.commit() #manual comitting should really not be needed. the context manager should handle that if this mysql package was properly made xd
 | 
						|
            for channel1 in client.get_all_channels():
 | 
						|
                if channel1.name == 'logs-discord-allowed':
 | 
						|
                    await channel1.send(f"!!!WARNING!!! \n{steam_account}Discord account ({discord_id}) is associated to an unloze forum account: https://unloze.com/members/.{res_user_id[0]}/\nName {member.name}. Descriminator ID: {member.discriminator}.\n\nUSER WILL NOT AUTOMATICALLY BE ALLOWED INTO THE DISCORD SERVER DUE TO POTENTIALLY BEING A SUSPICIOUS ACCOUNT.\n{asn_status}!!!WARNING!!!")
 | 
						|
                    break
 | 
						|
            break
 | 
						|
    if do_allow:
 | 
						|
        sql_statement = """
 | 
						|
            select `type` from vpn_check.ip_table it 
 | 
						|
            where it.ip = %s
 | 
						|
        """
 | 
						|
        cur2.execute(sql_statement, [ipv4])
 | 
						|
        res = cur2.fetchone()
 | 
						|
        if res:
 | 
						|
            vpn_type = res[0]
 | 
						|
            if vpn_type == 1:
 | 
						|
                do_allow = False
 | 
						|
                sql_statement = """
 | 
						|
                   update unloze_playtimestats.player_time
 | 
						|
                   set discord_allowed = 1 where steam_id = %s
 | 
						|
                """
 | 
						|
                cur2.execute(sql_statement, [steam_id2_])
 | 
						|
                conn2.commit()
 | 
						|
                for channel1 in client.get_all_channels():
 | 
						|
                    if channel1.name == 'logs-discord-allowed':
 | 
						|
                        await channel1.send(f"!!!WARNING!!! \n{steam_account}Discord account ({discord_id}) is associated to an unloze forum account: https://unloze.com/members/.{res_user_id[0]}/\nName {member.name}. Descriminator ID: {member.discriminator}.\n\nUSER WILL NOT AUTOMATICALLY BE ALLOWED INTO THE DISCORD SERVER DUE TO USING A VPN: {ipv4}.\n!!!WARNING!!!")
 | 
						|
    return do_allow
 | 
						|
 | 
						|
async def verify_player(res_all_, steam_id2_, steam_account, member, discord_id, client, res_user_id, bad_asn, steam_id2__, cur2, conn2):
 | 
						|
    total_time_hours = 0
 | 
						|
    if res_all_ is not None and len(res_all_) > 0 and steam_id2_ is not None and steam_id2_ != steam_id2__:
 | 
						|
        ip_counter, total_time_hours, total_time_minutes, ze_time_hours, ze_time_minutes, zr_time_hours, zr_time_minutes, mg_time_hours, mg_time_minutes, jb_time_hours, jb_time_minutes = count_hours(res_all_)
 | 
						|
    if total_time_hours >= 200.0:
 | 
						|
        sql_statement = """
 | 
						|
            select * from unloze_playtimestats.player_time
 | 
						|
            where steam_id = %s and discord_allowed = 1
 | 
						|
            limit 1
 | 
						|
        """
 | 
						|
        cur2.execute(sql_statement, [steam_id2_])
 | 
						|
        res = cur2.fetchone()
 | 
						|
        if not res:
 | 
						|
            sql_statement = """
 | 
						|
                select asn, ipv4 from unloze_playtimestats.player_time
 | 
						|
                    where steam_id = %s
 | 
						|
            """
 | 
						|
            cur2.execute(sql_statement, [steam_id2_])
 | 
						|
            res_all = cur2.fetchall()
 | 
						|
            do_allow = True
 | 
						|
            for res in res_all:
 | 
						|
                asn = res[0]
 | 
						|
                ipv4 = res[1]
 | 
						|
                if asn is None:
 | 
						|
                    do_allow = await update_asn(ipv4, steam_id2_, client, discord_id, member, bad_asn, steam_account, res_user_id, cur2, conn2)
 | 
						|
                else:
 | 
						|
                    for asn1 in bad_asn:
 | 
						|
                        if asn == asn1:
 | 
						|
                            do_allow = False
 | 
						|
                            break
 | 
						|
                if not do_allow:
 | 
						|
                    break
 | 
						|
            if do_allow:
 | 
						|
                sql_statement = """
 | 
						|
                       update unloze_playtimestats.player_time
 | 
						|
                       set discord_allowed = 1 where steam_id = %s
 | 
						|
                    """
 | 
						|
                cur2.execute(sql_statement, [steam_id2_])
 | 
						|
                for channel1 in client.get_all_channels():
 | 
						|
                    if channel1.name == 'logs-discord-allowed':
 | 
						|
                        await channel1.send(f"{steam_account}Was allowed into the discord server. Discord account ({discord_id}) is associated to an unloze forum account: https://unloze.com/members/.{res_user_id[0]}/\nName {member.name}. Descriminator ID: {member.discriminator}")
 | 
						|
                        try:
 | 
						|
                            for role in member.roles:
 | 
						|
                                if role.name == "new-comer":
 | 
						|
                                    await member.remove_roles(role)
 | 
						|
                                    break
 | 
						|
                        except Exception:
 | 
						|
                            import traceback
 | 
						|
                            error_msg = traceback.format_exc()
 | 
						|
                            print("member name: ", member.name)
 | 
						|
                            print("traceback happened: ", error_msg)
 | 
						|
                        break
 | 
						|
                conn2.commit() #manual comitting should really not be needed. the context manager should handle that if this mysql package was properly made xd
 | 
						|
 | 
						|
@loop(seconds = 10)
 | 
						|
async def check_person_to_allow():
 | 
						|
    bad_asn = ["AS3352", "failed"]
 | 
						|
    with get_connection_xenforo() as conn:
 | 
						|
        with conn.cursor(buffered=True) as cur: #wtf is this buffered shit even
 | 
						|
            for channel in client.get_all_channels():
 | 
						|
                if channel.name == 'introduction-channel':
 | 
						|
                    for member in channel.members:
 | 
						|
                        discord_id = member.id
 | 
						|
                        res_user_id = xenforo_query(cur, discord_id)
 | 
						|
                        if not res_user_id:
 | 
						|
                            continue
 | 
						|
                        res_all_1, steam_id2_1, steam_id64_1, res_all_2, steam_id2_2, steam_id64_2 = run_steam_queries(res_user_id, cur)
 | 
						|
                        with get_connection_playtime() as conn2:
 | 
						|
                            with conn2.cursor(buffered=True) as cur2:
 | 
						|
                                steam_account = gen_steam_acount_str(steam_id2_1, steam_id2_2, steam_id64_1, steam_id64_2)
 | 
						|
                                await verify_player(res_all_1, steam_id2_1, steam_account, member, discord_id, client, res_user_id, bad_asn, None, cur2, conn2)
 | 
						|
                                await verify_player(res_all_2, steam_id2_2, steam_account, member, discord_id, client, res_user_id, bad_asn, steam_id2_1, cur2, conn2)
 | 
						|
        conn.close()
 | 
						|
 | 
						|
def main():
 | 
						|
    check_person_to_allow.start()
 | 
						|
    client.run(token)
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    main()
 |