From a0fdbf4244d9eca4a593ffe2e64e15859447b95f Mon Sep 17 00:00:00 2001 From: jenz Date: Wed, 11 Feb 2026 19:49:15 +0100 Subject: [PATCH] added top player activity tracking for ze with vip rewards --- .../python/main_ze_player_activity.py | 223 ++++++++++++++++++ stoat_admin_activity_ze/python/settings.py | 2 + stoat_admin_activity_ze/sql/create_tables.sql | 8 + .../systemd/stoat_player_activity_ze.service | 10 + .../systemd/stoat_player_activity_ze.timer | 8 + 5 files changed, 251 insertions(+) create mode 100644 stoat_admin_activity_ze/python/main_ze_player_activity.py create mode 100644 stoat_admin_activity_ze/systemd/stoat_player_activity_ze.service create mode 100644 stoat_admin_activity_ze/systemd/stoat_player_activity_ze.timer diff --git a/stoat_admin_activity_ze/python/main_ze_player_activity.py b/stoat_admin_activity_ze/python/main_ze_player_activity.py new file mode 100644 index 0000000..ed3f91f --- /dev/null +++ b/stoat_admin_activity_ze/python/main_ze_player_activity.py @@ -0,0 +1,223 @@ +#!/home/nonroot/stoat_admin_activity_ze/venv/bin/python3 +from settings import get_connection_unloze_playtime, stoat_token, stoat_url_top_15_ze, api_key +import requests +from datetime import datetime +import sys + +unloze_user_upgrade_api = f"https://unloze.com/api/private_user_upgrade_api.php?api_key={api_key}&steam_id=" + +def check_if_new_weekly_session(): + with get_connection_unloze_playtime() as conn: + with conn.cursor() as cur: + sql_statement = f""" + select 1 from unloze_playtimestats.player_activity_ze limit 1 + """ + cur.execute(sql_statement) + res = cur.fetchone() + return res + +def check_if_oldest_timestamp_older_than_week(): + with get_connection_unloze_playtime() as conn: + with conn.cursor() as cur: + sql_statement = f""" + SELECT MIN(inserted_on) < CURDATE() - INTERVAL 7 DAY AS is_older_than_week, MIN(inserted_on) as oldest_timestamp + FROM unloze_playtimestats.player_activity_ze + """ + cur.execute(sql_statement) + res = cur.fetchone() + return res + +def get_top15_player_activity_ze(): + with get_connection_unloze_playtime() as conn: + with conn.cursor() as cur: + #excluding the autism bots + sql_statement = f""" + select pt.steam_id, pt.player_name, SUM(pt.ze_time) - pa.ze_time_start_week AS time_this_week + from unloze_playtimestats.player_activity_ze pa + inner join unloze_playtimestats.player_time pt + on pa.steamid = pt.steam_id + where pa.steamid not in ('STEAM_0:0:518094602', 'STEAM_0:0:204398871', 'STEAM_0:1:60189040', 'STEAM_0:0:610560766') + GROUP BY pt.steam_id, pt.player_name + ORDER BY time_this_week DESC + limit 15 + """ + cur.execute(sql_statement) + res = cur.fetchall() + return res + +def get_untracked_players_active_in_last_week(): + with get_connection_unloze_playtime() as conn: + with conn.cursor() as cur: + sql_statement = f""" + SELECT + pt.steam_id, + pt.player_name, + SUM(pt.ze_time) AS total_time + FROM unloze_playtimestats.player_time pt + WHERE pt.steam_id IN ( + SELECT DISTINCT pt_inner.steam_id + FROM unloze_playtimestats.player_time pt_inner + LEFT JOIN unloze_playtimestats.player_activity_ze pt1 + ON pt1.steamid = pt_inner.steam_id + WHERE pt_inner.modified_on > CURDATE() - INTERVAL 7 DAY + AND pt1.steamid IS NULL + ) + GROUP BY pt.steam_id; + """ + cur.execute(sql_statement) + res = cur.fetchall() + return res + +def insert_untracked_players(player_timestats_to_insert): + with get_connection_unloze_playtime() as conn: + with conn.cursor() as cur: + placeholders = ','.join(['(%s, %s, %s)'] * len(player_timestats_to_insert)) + flattened_values = [val for row in player_timestats_to_insert for val in row] + + sql_statement = f""" + INSERT INTO unloze_playtimestats.player_activity_ze + (steamid, name, ze_time_start_week) + VALUES {placeholders} + """ + cur.execute(sql_statement, flattened_values) + conn.commit() + +def send_post_message_to_stoat(): + message = f"This is the beginning of a new Weekly Session started at **{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}** for Zombie Escape Players. First results come in around 30 minutes." + headers = { + "x-bot-token": f"{stoat_token}", + "Content-Type": "application/json" + } + data = { + "content": message + } + response = requests.post(stoat_url_top_15_ze, headers=headers, json=data) + +def send_patch_message_to_stoat(top15_weekly_activity_ze, oldest_timestamp): + message = f"Started Weekly Time Tracking from **{oldest_timestamp}** until **{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}** for Zombie Escape Players:\n\n" + + for index, player in enumerate(top15_weekly_activity_ze): + steam_id = player[0] + name = player[1] + time_this_week = player[2] + + hours_server = int((time_this_week / 60) / 60) + minutes_server = int((time_this_week / 60) % 60) + message += f"{index + 1}: {name} ({steam_id}) Playtime: {hours_server} hours and {minutes_server} minutes.\n\n" + + message += f"When one week has gone by will VIP rewards be automatically given to top15. This message is updated every 30 minutes." + headers = { + "x-bot-token": f"{stoat_token}", + "Content-Type": "application/json" + } + + data = { + "content": message + } + + #get most recent message that has to be edited. + last_message_to_patch = requests.get(stoat_url_top_15_ze + "?limit=1", headers=headers) + if last_message_to_patch.status_code > 299: + print(last_message_to_patch.status_code, " ", last_message_to_patch.text) + sys.exit(1) + + latest_message_id = last_message_to_patch.json()[0]['_id'] + + response = requests.patch(stoat_url_top_15_ze + f"/{latest_message_id}", headers=headers, json=data) + if response.status_code > 299: + print(response.status_code, " ", response.text) + sys.exit(1) + +def send_final_stoat_edit(players_vip_status): + message = "Finished Time Tracking from **{oldest_timestamp}** until **{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}** for Zombie Escape Players. The final results of the week are:\n\n" + for index, player_vip_status in enumerate(players_vip_status): + steamid, name, hours_server, minutes_server, reward_status, days_rewarded = player_vip_status + message += f"{index + 1}: {name} ({steam_id}) Playtime: {hours_server} hours and {minutes_server} minutes. {reward_status} Reward was {days_rewarded} days.\n\n" + + headers = { + "x-bot-token": f"{stoat_token}", + "Content-Type": "application/json" + } + + data = { + "content": message + } + + #get most recent message that has to be edited. + last_message_to_patch = requests.get(stoat_url_top_15_ze + "?limit=1", headers=headers) + if last_message_to_patch.status_code > 299: + print(last_message_to_patch.status_code, " ", last_message_to_patch.text) + sys.exit(1) + + latest_message_id = last_message_to_patch.json()[0]['_id'] + + response = requests.patch(stoat_url_top_15_ze + f"/{latest_message_id}", headers=headers, json=data) + if response.status_code > 299: + print(response.status_code, " ", response.text) + sys.exit(1) + +def truncate_player_activity_ze(): + with get_connection_unloze_playtime() as conn: + with conn.cursor() as cur: + sql_statement = f""" + truncate table unloze_playtimestats.player_activity_ze + """ + cur.execute(sql_statement) + conn.commit() + +def steamid_to_commid(steamid): + steamid64ident = 76561197960265728 + sid_split = steamid.split(':') + commid = int(sid_split[2]) * 2 + if sid_split[1] == '1': + commid += 1 + commid += steamid64ident + return commid + +def give_vip_rewards(top15_weekly_activity_ze): + players_vip_status = [] + for index, result in enumerate(top15_weekly_activity_ze): + steamid = result[0] + name = result[1] + time_this_week = result[2] + hours_server = int((time_this_week / 60) / 60) + minutes_server = int((time_this_week / 60) % 60) + + if index < 5: + days_rewarded = 7 + if index < 10: + days_rewarded = 3 + if index < 15: + days_rewarded = 1 + steam_community_id = steamid_to_commid(steamid) + + print(f'index: {index}. steamid: {steamid}. name: {name}. days_rewarded: {days_rewarded}') + r = requests.get(f"{unloze_user_upgrade_api}{steam_community_id}&days_reward={days_rewarded}") + if r.content.decode('utf8').startswith("NOACCOUNT"): #not registed with associated steam account + players_vip_status.append([steamid, name, hours_server, minutes_server, "NO FORUM ACCOUNT ASSOCIATED WITH STEAM.", days_rewarded]) + else: + players_vip_status.append([steamid, name, hours_server, minutes_server, "VIP REWARDED.", days_rewarded]) + return players_vip_status + +def main(): + #if new session variable is None + same_weekly_session = check_if_new_weekly_session() + + player_timestats_to_insert = get_untracked_players_active_in_last_week() + if player_timestats_to_insert: + insert_untracked_players(player_timestats_to_insert) + + if same_weekly_session: + top15_weekly_activity_ze = get_top15_player_activity_ze() + timestamp_older_than_week, oldest_timestamp = check_if_oldest_timestamp_older_than_week() + send_patch_message_to_stoat(top15_weekly_activity_ze, oldest_timestamp) + + if timestamp_older_than_week: + players_vip_status = give_vip_rewards(top15_weekly_activity_ze) + send_final_stoat_edit(players_vip_status, oldest_timestamp) + truncate_player_activity_ze() + else: + send_post_message_to_stoat() + +if __name__ == '__main__': + main() diff --git a/stoat_admin_activity_ze/python/settings.py b/stoat_admin_activity_ze/python/settings.py index de9727c..8166745 100644 --- a/stoat_admin_activity_ze/python/settings.py +++ b/stoat_admin_activity_ze/python/settings.py @@ -5,6 +5,8 @@ import mysql.connector stoat_token = "" stoat_url = "" +stoat_url_top_15_ze = "" +api_key = "" def get_connection_unloze_playtime(): return mysql.connector.connect( diff --git a/stoat_admin_activity_ze/sql/create_tables.sql b/stoat_admin_activity_ze/sql/create_tables.sql index e6708a0..5402e59 100644 --- a/stoat_admin_activity_ze/sql/create_tables.sql +++ b/stoat_admin_activity_ze/sql/create_tables.sql @@ -5,3 +5,11 @@ CREATE TABLE unloze_playtimestats.admin_activity_ze ( `inserted_on` datetime DEFAULT current_timestamp(), PRIMARY KEY (`steamid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE unloze_playtimestats.player_activity_ze ( + `name` varchar(255) NOT NULL, + `steamid` varchar(255) NOT NULL, + `ze_time_start_week` bigint(20) NOT NULL, + `inserted_on` datetime DEFAULT current_timestamp(), + PRIMARY KEY (`steamid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; diff --git a/stoat_admin_activity_ze/systemd/stoat_player_activity_ze.service b/stoat_admin_activity_ze/systemd/stoat_player_activity_ze.service new file mode 100644 index 0000000..4676e89 --- /dev/null +++ b/stoat_admin_activity_ze/systemd/stoat_player_activity_ze.service @@ -0,0 +1,10 @@ +[Unit] +Description=runs top player activity ze checks for stoat + +[Service] +Type=simple +User=nonroot +Environment=PYTHONUNBUFFERED=1 +Environment=PATH=/home/nonroot/stoat_admin_activity_ze/venv/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/snap/bin +WorkingDirectory=/home/nonroot/stoat_admin_activity_ze +ExecStart=/home/nonroot/stoat_admin_activity_ze/main_ze_player_activity.py diff --git a/stoat_admin_activity_ze/systemd/stoat_player_activity_ze.timer b/stoat_admin_activity_ze/systemd/stoat_player_activity_ze.timer new file mode 100644 index 0000000..04367a9 --- /dev/null +++ b/stoat_admin_activity_ze/systemd/stoat_player_activity_ze.timer @@ -0,0 +1,8 @@ +[Unit] +Description=writes a message every 30 minutes on stoat about the top player activity on ze + +[Timer] +OnCalendar=*-*-* *:0/30:00 + +[Install] +WantedBy=multi-user.target