From 028e06b2d67fbe97c9490eb4ce2e7cd1667ef124 Mon Sep 17 00:00:00 2001 From: jenz Date: Sat, 21 May 2022 23:10:17 +0200 Subject: [PATCH] initial commit for the discord verification bot checking ingame playtime --- discord_verificiation/README.md | 3 + .../python/discord_verification.py | 156 ++++++++++++++++++ discord_verificiation/python/settings.py | 17 ++ .../scripting/unloze_player_time.sp | 126 ++++++++++++++ .../systemctl/discord_verification.service | 9 + .../systemctl/discord_verification.timer | 8 + 6 files changed, 319 insertions(+) create mode 100644 discord_verificiation/README.md create mode 100644 discord_verificiation/python/discord_verification.py create mode 100644 discord_verificiation/python/settings.py create mode 100644 discord_verificiation/scripting/unloze_player_time.sp create mode 100644 discord_verificiation/systemctl/discord_verification.service create mode 100644 discord_verificiation/systemctl/discord_verification.timer diff --git a/discord_verificiation/README.md b/discord_verificiation/README.md new file mode 100644 index 00000000..2a38551f --- /dev/null +++ b/discord_verificiation/README.md @@ -0,0 +1,3 @@ +Manually allows ppl into the discord. + +You need to create a virtual environment with discord.py and mysql diff --git a/discord_verificiation/python/discord_verification.py b/discord_verificiation/python/discord_verification.py new file mode 100644 index 00000000..41924e2c --- /dev/null +++ b/discord_verificiation/python/discord_verification.py @@ -0,0 +1,156 @@ +#!/home/nonroot/discord_verification/venv/bin/python3 + +import discord +import math +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 from_steam64(sid): + y = int(sid) - 76561197960265728 + x = y % 2 + return "STEAM_0:{}:{}".format(x, (y - x) // 2) + +@client.event +async def on_message(message): + if message.author.bot: + return + if client.user.mentioned_in(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 + + with get_connection_xenforo() as conn: + with conn.cursor(buffered=True) as cur: #wtf is this buffered shit even + sql_statement = """ + select * from unloze_forum_2.xf_user_connected_account e + where e.provider_key = '%s' + """ + cur.execute(sql_statement, [discord_id]) + res = cur.fetchone() + if not res: + await message.channel.send(f"{target_name} Your discord account is not associated to any unloze forum account. Create a forum account and associate discord") + else: + sql_statement = """ + select * from unloze_forum_2.xf_user_connected_account e + where e.provider like %s and e.user_id = %s and LENGTH(e.provider_key) > 0 + """ + cur.execute(sql_statement, ["%steam", res[0]]) + res = cur.fetchone() + if not res: + await message.channel.send(f"{target_name} Your discord account is associated to an unloze forum account. But there is no steam account associated. Associate your steam account.") + else: + 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 = cur2.fetchone() + if not res: + await message.channel.send(f"{target_name} Your steam account has no play time at all on the gameservers. You need 200 hours.") + else: + ze_time = res[0] + mg_time = res[1] + zr_time = res[2] + jb_time = res[3] + allowed = res[4] + if allowed: + await message.channel.send(f"{target_name} You are already allowed into the discord server for surpassing 200 hours game time") + else: + ze_time_hours = math.floor((ze_time / 60) / 60) + ze_time_minutes = math.floor((ze_time / 60) - (ze_time_hours * 60)) + + mg_time_hours = math.floor((mg_time / 60) / 60) + mg_time_minutes = math.floor((mg_time / 60) - (mg_time_hours * 60)) + + zr_time_hours = math.floor((zr_time / 60) / 60) + zr_time_minutes = math.floor((zr_time / 60) - (zr_time_hours * 60)) + + jb_time_hours = math.floor((jb_time / 60) / 60) + jb_time_minutes = math.floor((jb_time / 60) - (jb_time_hours * 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)) + + await message.channel.send(f"Player: {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.") + +@loop(seconds = 10) +async def check_person_to_allow(): + global client + d = client + with get_connection_xenforo() as conn: + with conn.cursor(buffered=True) as cur: #wtf is this buffered shit even + for channel in d.get_all_channels(): + if channel.name == 'introduction-channel': + for member in channel.members: + discord_id = member.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 = cur.fetchone() + if res: + sql_statement = """ + select * from unloze_forum_2.xf_user_connected_account e + where e.provider like %s and e.user_id = %s and LENGTH(e.provider_key) > 0 + """ + cur.execute(sql_statement, ["%steam", res[0]]) + res = cur.fetchone() + if res: + 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 from unloze_playtimestats.player_time pt + where pt.steam_id = %s and discord_allowed = 0 + """ + cur2.execute(sql_statement, [steam_id2]) + res = cur2.fetchone() + if res: + ze_time = res[0] + mg_time = res[1] + zr_time = res[2] + jb_time = res[3] + ze_time = (ze_time / 60) / 60 + mg_time = (mg_time / 60) / 60 + zr_time = (zr_time / 60) / 60 + jb_time = (jb_time / 60) / 60 + total_time = ze_time + mg_time + zr_time + jb_time + if total_time > 200.0: + sql_statement = """ + update unloze_playtimestats.player_time + set discord_allowed = 1 where steam_id = %s + """ + cur.execute(sql_statement, [steam_id2]) + for channel1 in d.get_all_channels(): + if channel1.name == 'logs-discord-allowed': + await channel1.send(f"Allowed SteamID {steam_id2} into the discord server using the discord ID: {discord_id} and name {member.name}. Descriminator ID: {member.discriminator}") + member.remove_roles("new-comer") + break + +def main(): + check_person_to_allow.start() + client.run(token) + +if __name__ == '__main__': + main() diff --git a/discord_verificiation/python/settings.py b/discord_verificiation/python/settings.py new file mode 100644 index 00000000..2ca4d183 --- /dev/null +++ b/discord_verificiation/python/settings.py @@ -0,0 +1,17 @@ +import mysql.connector + +token = "" + +def get_connection_playtime(): + return mysql.connector.connect( + host="127.0.0.1", + port=3306, + user="unloze_playtimestats", + password="") + +def get_connection_xenforo(): + return mysql.connector.connect( + host="127.0.0.1", + port=3306, + user="unloze_xenforo_external", + password="") diff --git a/discord_verificiation/scripting/unloze_player_time.sp b/discord_verificiation/scripting/unloze_player_time.sp new file mode 100644 index 00000000..6b605b82 --- /dev/null +++ b/discord_verificiation/scripting/unloze_player_time.sp @@ -0,0 +1,126 @@ +#pragma semicolon 1 +#define PLUGIN_AUTHOR "jenz" +#define PLUGIN_VERSION "1.0" +#include + +Database g_hDatabase; + +public Plugin myinfo = +{ + name = "UNLOZE_player_time", + author = PLUGIN_AUTHOR, + description = "checks playtime on servers", + version = PLUGIN_VERSION, + url = "www.unloze.com" +}; + +public void OnMapStart() +{ + CreateTimer(10.0, time_query_activity, INVALID_HANDLE, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); +} + +public Action time_query_activity(Handle timer, any data) +{ + for (int client = 1; client <= MaxClients; client++) + if (IsValidClient(client) && !IsFakeClient(client) && IsPlayerAlive(client)) + { + char sAuthID[32]; + GetClientAuthId(client, AuthId_Steam2, sAuthID, sizeof(sAuthID), false); + char sIP[32]; + GetClientIP(client, sIP, sizeof(sIP)); + char sQuery[512]; + char sServer[64]; + int i_port = GetConVarInt(FindConVar("hostport")); + if (i_port == 27015) + { + Format(sServer, sizeof(sServer), "ze_time"); + } + else if (i_port == 27016) + { + Format(sServer, sizeof(sServer), "zr_time"); + } + else if (i_port == 27017) + { + Format(sServer, sizeof(sServer), "mg_time"); + } + else if (i_port == 27023) + { + Format(sServer, sizeof(sServer), "jb_time"); + } + else + { + continue; + } + char sName[MAX_NAME_LENGTH]; + GetClientName(client, sName, sizeof(sName)); + int size2 = 2 * strlen(sName) + 1; + char[] sEscapedName = new char[size2 + 1]; + g_hDatabase.Escape(sName, sEscapedName, size2 + 1); + Format(sQuery, sizeof(sQuery), "update unloze_playtimestats.player_time set `%s` = `%s` + 10, player_name = '%s' where steam_id = '%s' and ipv4 = '%s'", sServer, sServer, sEscapedName, sAuthID, sIP); + //LogError("sQuery: %s", sQuery); + g_hDatabase.Query(SQL_FinishedQuery, sQuery, _, DBPrio_High); + } + + return Plugin_Continue; +} + +public void OnPluginStart() +{ + Database.Connect(SQL_OnDatabaseConnect, "unloze_playtimestats"); +} + +public void SQL_OnDatabaseConnect(Database db, const char[] error, any data) +{ + if(!db || strlen(error)) + { + LogError("Database error: %s", error); + return; + } + g_hDatabase = db; + for (int i = 1; i <= MaxClients; i++) + OnClientPostAdminCheck(i); +} + +public void OnClientPostAdminCheck(int client) +{ + if(!IsValidClient(client) || IsFakeClient(client)) + return; + if (!g_hDatabase) + { + Database.Connect(SQL_OnDatabaseConnect, "unloze_playtimestats"); + return; + } + insert_client(client); +} + +public void insert_client(int client) +{ + char sAuthID[32]; + GetClientAuthId(client, AuthId_Steam2, sAuthID, sizeof(sAuthID), false); + char sName[MAX_NAME_LENGTH]; + GetClientName(client, sName, sizeof(sName)); + int size2 = 2 * strlen(sName) + 1; + char[] sEscapedName = new char[size2 + 1]; + g_hDatabase.Escape(sName, sEscapedName, size2 + 1); + char sIP[32]; + GetClientIP(client, sIP, sizeof(sIP)); + char sQuery[512]; + Format(sQuery, sizeof(sQuery), "INSERT INTO `player_time` (`steam_id`, `ipv4`, `player_name`, `ze_time`, `mg_time`, `zr_time`, `jb_time`) VALUES ('%s', '%s', '%s', 0, 0, 0, 0) ON DUPLICATE KEY UPDATE `player_name` = '%s'", sAuthID, sIP, sEscapedName, sEscapedName); + g_hDatabase.Query(SQL_FinishedQuery, sQuery, _, DBPrio_High); +} + +public void SQL_FinishedQuery(Database db, DBResultSet results, const char[] error, DataPack data) +{ + if (!db || strlen(error)) + { + LogError("Query error 3: %s", error); + } + delete data; +} + +stock bool IsValidClient(int client) +{ + if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client)) + return true; + return false; +} diff --git a/discord_verificiation/systemctl/discord_verification.service b/discord_verificiation/systemctl/discord_verification.service new file mode 100644 index 00000000..3dbfca4e --- /dev/null +++ b/discord_verificiation/systemctl/discord_verification.service @@ -0,0 +1,9 @@ +[Unit] +Description=runs discord verification + +[Service] +Type=simple +User=nonroot +Environment=PATH=/home/nonroot/discord_verification/venv/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/snap/bin +WorkingDirectory=/home/nonroot/discord_verification +ExecStart=/home/nonroot/discord_verification/discord_verification.py diff --git a/discord_verificiation/systemctl/discord_verification.timer b/discord_verificiation/systemctl/discord_verification.timer new file mode 100644 index 00000000..ea9c07b1 --- /dev/null +++ b/discord_verificiation/systemctl/discord_verification.timer @@ -0,0 +1,8 @@ +[Unit] +Description=Discord verification to allow players into discord + +[Timer] +OnCalendar=*-*-* *:25,55 + +[Install] +WantedBy=multi-user.target