mirror of
https://github.com/imayushsaini/Bombsquad-Ballistica-Modded-Server.git
synced 2025-11-14 17:46:03 +00:00
rework on player restriction , exposing rest apis
This commit is contained in:
parent
af7fb5a586
commit
bf4c01c291
10 changed files with 883 additions and 361 deletions
|
|
@ -157,9 +157,12 @@ def get_player_info(arguments, client_id):
|
|||
if account['client_id'] == int(arguments[0]):
|
||||
send(pdata.get_detailed_info(account["pbid"]), client_id)
|
||||
|
||||
|
||||
def get_recents(client_id):
|
||||
for players in serverdata.recents:
|
||||
send(f"{players['client_id']} {players['deviceId']} {players['pbid']}", client_id)
|
||||
send(
|
||||
f"{players['client_id']} {players['deviceId']} {players['pbid']}", client_id)
|
||||
|
||||
|
||||
def changepartysize(arguments):
|
||||
if len(arguments) == 0:
|
||||
|
|
@ -201,9 +204,9 @@ def kikvote(arguments, clientid):
|
|||
cl_id = int(arguments[1])
|
||||
for ros in ba.internal.get_game_roster():
|
||||
if ros["client_id"] == cl_id:
|
||||
if ros["account_id"] in serverdata.clients:
|
||||
serverdata.clients[ros["account_id"]
|
||||
]["canStartKickVote"] = True
|
||||
pdata.enable_kick_vote(ros["account_id"])
|
||||
logger.log(
|
||||
f'kick vote enabled for {ros["account_id"]} {ros["display_string"]}')
|
||||
send(
|
||||
"Upon server restart, Kick-vote will be enabled for this person", clientid)
|
||||
return
|
||||
|
|
@ -220,9 +223,10 @@ def kikvote(arguments, clientid):
|
|||
if ros["client_id"] == cl_id:
|
||||
_ba.disable_kickvote(ros["account_id"])
|
||||
send("Kick-vote disabled for this person", clientid)
|
||||
if ros["account_id"] in serverdata.clients:
|
||||
serverdata.clients[ros["account_id"]
|
||||
]["canStartKickVote"] = False
|
||||
logger.log(
|
||||
f'kick vote disabled for {ros["account_id"]} {ros["display_string"]}')
|
||||
pdata.disable_kick_vote(
|
||||
ros["account_id"], 2, "by chat command")
|
||||
return
|
||||
except:
|
||||
return
|
||||
|
|
@ -272,17 +276,19 @@ def end(arguments):
|
|||
def ban(arguments):
|
||||
try:
|
||||
cl_id = int(arguments[0])
|
||||
ac_id = ""
|
||||
duration = int(arguments[1]) if len(arguments) >= 2 else 0.5
|
||||
for ros in ba.internal.get_game_roster():
|
||||
if ros["client_id"] == cl_id:
|
||||
ac_id = ros['account_id']
|
||||
pdata.ban_player(ros['account_id'])
|
||||
logger.log("banned "+ros["display_string"])
|
||||
if ac_id in serverdata.clients:
|
||||
serverdata.clients[ac_id]["isBan"] = True
|
||||
pdata.ban_player(ros['account_id'], duration,
|
||||
"by chat command")
|
||||
logger.log(f'banned {ros["display_string"]} by chat command')
|
||||
|
||||
for account in serverdata.recents: # backup case if player left the server
|
||||
if account['client_id'] == int(arguments[0]):
|
||||
pdata.ban_player(account["pbid"])
|
||||
pdata.ban_player(
|
||||
account["pbid"], duration, "by chat command")
|
||||
logger.log(
|
||||
f'banned {ros["display_string"]} by chat command, recents')
|
||||
kick(arguments)
|
||||
except:
|
||||
pass
|
||||
|
|
@ -298,17 +304,18 @@ def mute(arguments):
|
|||
serverdata.muted = True
|
||||
try:
|
||||
cl_id = int(arguments[0])
|
||||
ac_id = ""
|
||||
duration = int(arguments[1]) if len(arguments) >= 2 else 0.5
|
||||
for ros in ba.internal.get_game_roster():
|
||||
if ros["client_id"] == cl_id:
|
||||
pdata.mute(ros['account_id'])
|
||||
ac_id = ros['account_id']
|
||||
logger.log("muted "+ros["display_string"])
|
||||
if ac_id in serverdata.clients:
|
||||
serverdata.clients[ac_id]["isMuted"] = True
|
||||
logger.log(f'muted {ros["display_string"]}')
|
||||
pdata.mute(ac_id, duration, "muted by chat command")
|
||||
return
|
||||
for account in serverdata.recents: # backup case if player left the server
|
||||
if account['client_id'] == int(arguments[0]):
|
||||
pdata.mute(account["pbid"])
|
||||
pdata.mute(account["pbid"], duration,
|
||||
"muted by chat command, from recents")
|
||||
except:
|
||||
pass
|
||||
return
|
||||
|
|
@ -319,14 +326,16 @@ def un_mute(arguments):
|
|||
serverdata.muted = False
|
||||
try:
|
||||
cl_id = int(arguments[0])
|
||||
ac_id = ""
|
||||
for ros in ba.internal.get_game_roster():
|
||||
if ros["client_id"] == cl_id:
|
||||
pdata.unmute(ros['account_id'])
|
||||
ac_id = ros['account_id']
|
||||
if ac_id in serverdata.clients:
|
||||
serverdata.clients[ac_id]["isMuted"] = False
|
||||
logger.log(f'unmuted {ros["display_string"]} by chat command')
|
||||
return
|
||||
for account in serverdata.recents: # backup case if player left the server
|
||||
if account['client_id'] == int(arguments[0]):
|
||||
pdata.unmute(account["pbid"])
|
||||
logger.log(
|
||||
f'unmuted {ros["display_string"]} by chat command, recents')
|
||||
except:
|
||||
pass
|
||||
|
||||
|
|
@ -485,6 +494,7 @@ def set_custom_tag(arguments):
|
|||
except:
|
||||
return
|
||||
|
||||
|
||||
def remove_custom_tag(arguments):
|
||||
try:
|
||||
session = ba.internal.get_foreground_host_session()
|
||||
|
|
@ -494,6 +504,7 @@ def remove_custom_tag(arguments):
|
|||
except:
|
||||
return
|
||||
|
||||
|
||||
def remove_custom_effect(arguments):
|
||||
try:
|
||||
session = ba.internal.get_foreground_host_session()
|
||||
|
|
@ -503,6 +514,7 @@ def remove_custom_effect(arguments):
|
|||
except:
|
||||
return
|
||||
|
||||
|
||||
def set_custom_effect(arguments):
|
||||
try:
|
||||
session = ba.internal.get_foreground_host_session()
|
||||
|
|
|
|||
22
dist/ba_root/mods/chatHandle/handlechat.py
vendored
22
dist/ba_root/mods/chatHandle/handlechat.py
vendored
|
|
@ -6,14 +6,17 @@ from chatHandle.ChatCommands import Main
|
|||
from tools import logger, servercheck
|
||||
from chatHandle.chatFilter import ChatFilter
|
||||
from features import votingmachine
|
||||
import ba, _ba
|
||||
from playersData import pdata
|
||||
import ba
|
||||
import _ba
|
||||
import ba.internal
|
||||
import setting
|
||||
|
||||
from datetime import datetime
|
||||
settings = setting.get_settings_data()
|
||||
|
||||
|
||||
def filter_chat_message(msg, client_id):
|
||||
now = datetime.now()
|
||||
if client_id == -1:
|
||||
if msg.startswith("/"):
|
||||
Main.Command(msg, client_id)
|
||||
|
|
@ -45,18 +48,20 @@ def filter_chat_message(msg, client_id):
|
|||
if msg in ["end", "dv", "nv", "sm"] and settings["allowVotes"]:
|
||||
votingmachine.vote(acid, client_id, msg)
|
||||
|
||||
|
||||
if acid in serverdata.clients and serverdata.clients[acid]["verified"]:
|
||||
|
||||
if serverdata.muted:
|
||||
_ba.screenmessage("Server on mute", transient=True, clients=[client_id])
|
||||
_ba.screenmessage("Server on mute",
|
||||
transient=True, clients=[client_id])
|
||||
return
|
||||
|
||||
elif serverdata.clients[acid]["isMuted"]:
|
||||
_ba.screenmessage("You are on mute", transient=True, clients=[client_id])
|
||||
elif acid in pdata.get_blacklist()["muted-ids"] and now < datetime.strptime(pdata.get_blacklist()["muted-ids"][acid]["till"], "%Y-%m-%d %H:%M:%S"):
|
||||
_ba.screenmessage(
|
||||
"You are on mute, maybe try after some time", transient=True, clients=[client_id])
|
||||
return None
|
||||
elif servercheck.get_account_age(serverdata.clients[acid]["accountAge"]) < settings['minAgeToChatInHours']:
|
||||
_ba.screenmessage("New accounts not allowed to chat here", transient=True, clients=[client_id])
|
||||
_ba.screenmessage("New accounts not allowed to chat here",
|
||||
transient=True, clients=[client_id])
|
||||
return None
|
||||
else:
|
||||
if msg.startswith(",") and settings["allowTeamChat"]:
|
||||
|
|
@ -66,5 +71,6 @@ def filter_chat_message(msg, client_id):
|
|||
return msg
|
||||
|
||||
else:
|
||||
_ba.screenmessage("Fetching your account info , Wait a minute", transient=True, clients=[client_id])
|
||||
_ba.screenmessage("Fetching your account info , Wait a minute",
|
||||
transient=True, clients=[client_id])
|
||||
return None
|
||||
|
|
|
|||
163
dist/ba_root/mods/playersData/pdata.py
vendored
163
dist/ba_root/mods/playersData/pdata.py
vendored
|
|
@ -4,6 +4,8 @@
|
|||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
import shutil
|
||||
import copy
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import time
|
||||
|
|
@ -17,13 +19,13 @@ import _ba
|
|||
import ba.internal
|
||||
import json
|
||||
import datetime
|
||||
from tools.ServerUpdate import contributeData , checkSpammer
|
||||
from tools.ServerUpdate import checkSpammer
|
||||
import setting
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
|
||||
setti=setting.get_settings_data()
|
||||
settings = setting.get_settings_data()
|
||||
|
||||
PLAYERS_DATA_PATH = os.path.join(
|
||||
_ba.env()["python_directory_user"], "playersData" + os.sep
|
||||
|
|
@ -71,10 +73,8 @@ def get_profiles() -> dict:
|
|||
if CacheData.profiles == {}:
|
||||
try:
|
||||
if os.stat(PLAYERS_DATA_PATH+"profiles.json").st_size > 1000000:
|
||||
newpath = PLAYERS_DATA_PATH + "profiles.json"+str(datetime.datetime.now())
|
||||
newpath = f'{PLAYERS_DATA_PATH}profiles-{str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))}.json'
|
||||
shutil.copyfile(PLAYERS_DATA_PATH + "profiles.json", newpath)
|
||||
if setti["contributeData"]:
|
||||
contributeData(newpath)
|
||||
profiles = {"pb-sdf": {}}
|
||||
print("resetting profiles")
|
||||
else:
|
||||
|
|
@ -95,6 +95,20 @@ def get_profiles() -> dict:
|
|||
else:
|
||||
return CacheData.profiles
|
||||
|
||||
|
||||
def get_profiles_archive_index():
|
||||
return [x for x in os.listdir(PLAYERS_DATA_PATH) if x.startswith("profiles")]
|
||||
|
||||
|
||||
def get_old_profiles(filename):
|
||||
try:
|
||||
f = open(PLAYERS_DATA_PATH + filename, "r")
|
||||
profiles = json.load(f)
|
||||
return profiles
|
||||
except:
|
||||
return {}
|
||||
|
||||
|
||||
def get_blacklist() -> dict:
|
||||
if CacheData.blacklist == {}:
|
||||
try:
|
||||
|
|
@ -104,19 +118,22 @@ def get_blacklist() -> dict:
|
|||
print('error opening blacklist json')
|
||||
return {
|
||||
"ban": {
|
||||
"ids":[],
|
||||
"ips":[],
|
||||
"deviceids":[]
|
||||
"ids": {},
|
||||
"ips": {},
|
||||
"deviceids": {}
|
||||
},
|
||||
"muted-ids":[]
|
||||
"muted-ids": {},
|
||||
"kick-vote-disabled": {}
|
||||
}
|
||||
|
||||
return CacheData.blacklist
|
||||
|
||||
|
||||
def update_blacklist():
|
||||
with open(PLAYERS_DATA_PATH + "blacklist.json", "w") as f:
|
||||
json.dump(CacheData.blacklist, f, indent=4)
|
||||
|
||||
|
||||
def commit_profiles(data={}) -> None:
|
||||
"""Commits the given profiles in the database.
|
||||
|
||||
|
|
@ -127,6 +144,7 @@ def commit_profiles(data={}) -> None:
|
|||
# with OpenJson(PLAYERS_DATA_PATH + "profiles.json") as profiles_file:
|
||||
# profiles_file.dump(CacheData.profiles, indent=4)
|
||||
|
||||
|
||||
def get_detailed_info(pbid):
|
||||
main_account = get_info(pbid)
|
||||
if main_account == None:
|
||||
|
|
@ -167,11 +185,8 @@ def add_profile(
|
|||
"display_string": display_string,
|
||||
"profiles": [],
|
||||
"name": current_name,
|
||||
"isBan": False,
|
||||
"isMuted": False,
|
||||
"accountAge": account_age,
|
||||
"registerOn": time.time(),
|
||||
"canStartKickVote": True,
|
||||
"spamCount": 0,
|
||||
"lastSpam": time.time(),
|
||||
"totaltimeplayer": 0,
|
||||
|
|
@ -190,14 +205,15 @@ def add_profile(
|
|||
cid = ros['client_id']
|
||||
ip = _ba.get_client_ip(cid)
|
||||
serverdata.clients[account_id]["lastIP"] = ip
|
||||
serverdata.recents.append({"client_id":cid,"deviceId":display_string,"pbid": account_id})
|
||||
serverdata.recents.append(
|
||||
{"client_id": cid, "deviceId": display_string, "pbid": account_id})
|
||||
serverdata.recents = serverdata.recents[-20:]
|
||||
device_id = _ba.get_client_public_device_uuid(cid)
|
||||
if (device_id == None):
|
||||
device_id = _ba.get_client_device_uuid(cid)
|
||||
checkSpammer({'id':account_id,'display':display_string,'ip':ip,'device':device_id})
|
||||
if device_id in get_blacklist()["ban"]["deviceids"]:
|
||||
serverdata.clients[account_id]["isBan"]=True
|
||||
checkSpammer({'id': account_id, 'display': display_string,
|
||||
'ip': ip, 'device': device_id})
|
||||
if device_id in get_blacklist()["ban"]["deviceids"] or account_id in get_blacklist()["ban"]["ids"]:
|
||||
ba.internal.disconnect_client(cid)
|
||||
serverdata.clients[account_id]["deviceUUID"] = device_id
|
||||
|
||||
|
|
@ -259,7 +275,7 @@ def update_profile(
|
|||
commit_profiles()
|
||||
|
||||
|
||||
def ban_player(account_id: str) -> None:
|
||||
def ban_player(account_id: str, duration_in_days: float, reason: str) -> None:
|
||||
"""Bans the player.
|
||||
|
||||
Parameters
|
||||
|
|
@ -267,27 +283,51 @@ def ban_player(account_id: str) -> None:
|
|||
account_id : str
|
||||
account id of the player to be banned
|
||||
"""
|
||||
profiles = get_profiles()
|
||||
if account_id in profiles:
|
||||
profiles[account_id]["isBan"] = True
|
||||
CacheData.profiles=profiles
|
||||
# _thread.start_new_thread(commit_profiles, (profiles,))
|
||||
cid = -1
|
||||
for ros in ba.internal.get_game_roster():
|
||||
if ros['account_id'] == account_id:
|
||||
cid = ros['client_id']
|
||||
ip = _ba.get_client_ip(cid)
|
||||
current_profiles = get_profiles()
|
||||
ip = ""
|
||||
device_id = ""
|
||||
if account_id in current_profiles:
|
||||
ip = current_profiles[account_id]["lastIP"]
|
||||
device_id = current_profiles[account_id]["deviceUUID"]
|
||||
|
||||
device_id = _ba.get_client_public_device_uuid(cid)
|
||||
if(device_id==None):
|
||||
device_id = _ba.get_client_device_uuid(cid)
|
||||
CacheData.blacklist["ban"]["ips"].append(ip)
|
||||
ban_time = datetime.now() + timedelta(days=duration_in_days)
|
||||
|
||||
CacheData.blacklist["ban"]["ids"].append(account_id)
|
||||
CacheData.blacklist["ban"]["deviceids"].append(device_id)
|
||||
CacheData.blacklist["ban"]["ips"][ip] = {"till": ban_time.strftime(
|
||||
"%Y-%m-%d %H:%M:%S"), "reason": f'linked with account {account_id}'}
|
||||
CacheData.blacklist["ban"]["ids"][account_id] = {
|
||||
"till": ban_time.strftime("%Y-%m-%d %H:%M:%S"), "reason": reason}
|
||||
CacheData.blacklist["ban"]["deviceids"][device_id] = {"till": ban_time.strftime(
|
||||
"%Y-%m-%d %H:%M:%S"), "reason": f'linked with account {account_id}'}
|
||||
_thread.start_new_thread(update_blacklist, ())
|
||||
|
||||
def mute(account_id: str) -> None:
|
||||
|
||||
def unban_player(account_id):
|
||||
current_profiles = get_profiles()
|
||||
ip = ""
|
||||
device_id = ""
|
||||
if account_id in current_profiles:
|
||||
ip = current_profiles[account_id]["lastIP"]
|
||||
device_id = current_profiles[account_id]["deviceUUID"]
|
||||
|
||||
CacheData.blacklist["ban"]["ips"].pop(ip, None)
|
||||
CacheData.blacklist["ban"]["deviceids"].pop(device_id, None)
|
||||
CacheData.blacklist["ban"]["ids"].pop(account_id, None)
|
||||
_thread.start_new_thread(update_blacklist, ())
|
||||
|
||||
|
||||
def disable_kick_vote(account_id, duration, reason):
|
||||
ban_time = datetime.now() + timedelta(days=duration)
|
||||
CacheData.blacklist["kick-vote-disabled"][account_id] = {"till": ban_time.strftime(
|
||||
"%Y-%m-%d %H:%M:%S"), "reason": reason}
|
||||
_thread.start_new_thread(update_blacklist, ())
|
||||
|
||||
|
||||
def enable_kick_vote(account_id):
|
||||
CacheData.blacklist["kick-vote-disabled"].pop(account_id, None)
|
||||
_thread.start_new_thread(update_blacklist, ())
|
||||
|
||||
|
||||
def mute(account_id: str, duration_in_days: float, reason: str) -> None:
|
||||
"""Mutes the player.
|
||||
|
||||
Parameters
|
||||
|
|
@ -295,11 +335,11 @@ def mute(account_id: str) -> None:
|
|||
account_id : str
|
||||
acccount id of the player to be muted
|
||||
"""
|
||||
profiles = get_profiles()
|
||||
if account_id in profiles:
|
||||
profiles[account_id]["isMuted"] = True
|
||||
CacheData.profiles=profiles
|
||||
ban_time = datetime.now() + timedelta(days=duration_in_days)
|
||||
|
||||
CacheData.blacklist["muted-ids"][account_id] = {"till": ban_time.strftime(
|
||||
"%Y-%m-%d %H:%M:%S"), "reason": reason}
|
||||
_thread.start_new_thread(update_blacklist, ())
|
||||
|
||||
|
||||
def unmute(account_id: str) -> None:
|
||||
|
|
@ -310,11 +350,8 @@ def unmute(account_id: str) -> None:
|
|||
account_id : str
|
||||
acccount id of the player to be unmuted
|
||||
"""
|
||||
profiles = get_profiles()
|
||||
if account_id in profiles:
|
||||
profiles[account_id]["isMuted"] = False
|
||||
CacheData.profiles=profiles
|
||||
_thread.start_new_thread(commit_profiles, (profiles,))
|
||||
CacheData.blacklist["muted-ids"].pop(account_id, None)
|
||||
_thread.start_new_thread(update_blacklist, ())
|
||||
|
||||
|
||||
def update_spam(account_id: str, spam_count: int, last_spam: float) -> None:
|
||||
|
|
@ -558,6 +595,10 @@ def get_custom() -> dict:
|
|||
custom = json.load(f)
|
||||
f.close()
|
||||
CacheData.custom = custom
|
||||
for account_id in custom["customeffects"]:
|
||||
custom["customeffects"][account_id] = [custom["customeffects"][account_id]] if type(
|
||||
custom["customeffects"][account_id]) is str else custom["customeffects"][account_id]
|
||||
|
||||
return CacheData.custom
|
||||
|
||||
|
||||
|
|
@ -573,7 +614,8 @@ def set_effect(effect: str, account_id: str) -> None:
|
|||
"""
|
||||
custom = get_custom()
|
||||
if account_id in custom["customeffects"]:
|
||||
effects = [custom["customeffects"][account_id]] if type(custom["customeffects"][account_id]) is str else custom["customeffects"][account_id]
|
||||
effects = [custom["customeffects"][account_id]] if type(
|
||||
custom["customeffects"][account_id]) is str else custom["customeffects"][account_id]
|
||||
effects.append(effect)
|
||||
custom["customeffects"][account_id] = effects
|
||||
else:
|
||||
|
|
@ -598,6 +640,22 @@ def set_tag(tag: str, account_id: str) -> None:
|
|||
commit_c()
|
||||
|
||||
|
||||
def get_roles():
|
||||
return CacheData.roles
|
||||
|
||||
|
||||
def update_roles(roles):
|
||||
CacheData.roles = roles
|
||||
|
||||
|
||||
def get_custom_perks():
|
||||
return CacheData.custom
|
||||
|
||||
|
||||
def update_custom_perks(custom):
|
||||
CacheData.custom = custom
|
||||
|
||||
|
||||
def remove_effect(account_id: str) -> None:
|
||||
"""Removes the effect from player.
|
||||
|
||||
|
|
@ -609,7 +667,6 @@ def remove_effect(account_id: str) -> None:
|
|||
custom = get_custom()
|
||||
custom["customeffects"].pop(account_id)
|
||||
CacheData.custom = custom
|
||||
commit_c()
|
||||
|
||||
|
||||
def remove_tag(account_id: str) -> None:
|
||||
|
|
@ -623,7 +680,6 @@ def remove_tag(account_id: str) -> None:
|
|||
custom = get_custom()
|
||||
custom["customtag"].pop(account_id)
|
||||
CacheData.custom = custom
|
||||
commit_c()
|
||||
|
||||
|
||||
def commit_c():
|
||||
|
|
@ -654,27 +710,30 @@ def load_white_list() -> None:
|
|||
for account_id in data:
|
||||
CacheData.whitelist.append(account_id)
|
||||
|
||||
|
||||
def load_cache():
|
||||
""" to be called on server boot"""
|
||||
get_profiles()
|
||||
get_custom()
|
||||
get_roles()
|
||||
|
||||
import shutil
|
||||
import copy
|
||||
|
||||
def dump_cache():
|
||||
if CacheData.profiles != {}:
|
||||
shutil.copyfile(PLAYERS_DATA_PATH + "profiles.json",PLAYERS_DATA_PATH + "profiles.json.backup")
|
||||
shutil.copyfile(PLAYERS_DATA_PATH + "profiles.json",
|
||||
PLAYERS_DATA_PATH + "profiles.json.backup")
|
||||
profiles = copy.deepcopy(CacheData.profiles)
|
||||
with open(PLAYERS_DATA_PATH + "profiles.json", "w") as f:
|
||||
json.dump(profiles, f, indent=4)
|
||||
if CacheData.roles != {}:
|
||||
shutil.copyfile(PLAYERS_DATA_PATH + "roles.json",PLAYERS_DATA_PATH + "roles.json.backup")
|
||||
shutil.copyfile(PLAYERS_DATA_PATH + "roles.json",
|
||||
PLAYERS_DATA_PATH + "roles.json.backup")
|
||||
roles = copy.deepcopy(CacheData.roles)
|
||||
with open(PLAYERS_DATA_PATH + "roles.json", "w") as f:
|
||||
json.dump(roles, f, indent=4)
|
||||
if CacheData.custom != {}:
|
||||
shutil.copyfile(PLAYERS_DATA_PATH + "custom.json",PLAYERS_DATA_PATH + "custom.json.backup")
|
||||
shutil.copyfile(PLAYERS_DATA_PATH + "custom.json",
|
||||
PLAYERS_DATA_PATH + "custom.json.backup")
|
||||
custom = copy.deepcopy(CacheData.custom)
|
||||
with open(PLAYERS_DATA_PATH + "custom.json", "w") as f:
|
||||
json.dump(custom, f, indent=4)
|
||||
|
|
|
|||
363
dist/ba_root/mods/plugins/bcs_plugin.py
vendored
363
dist/ba_root/mods/plugins/bcs_plugin.py
vendored
|
|
@ -2,119 +2,43 @@
|
|||
# coding: utf-8
|
||||
|
||||
# ba_meta require api 7
|
||||
from typing import Optional, Any, Dict, List, Type, Sequence
|
||||
from ba._gameactivity import GameActivity
|
||||
import ba,_ba
|
||||
import ba.internal
|
||||
import json
|
||||
# from gunicorn.app.base import BaseApplication
|
||||
# from gunicorn.workers import ggevent as gevent_worker
|
||||
|
||||
from flask import Flask, request, jsonify
|
||||
from functools import wraps
|
||||
import os
|
||||
|
||||
import _thread
|
||||
# from stats import mystats
|
||||
# import uvicorn
|
||||
from . import bombsquad_service
|
||||
|
||||
os.environ['FLASK_APP'] = 'bombsquadflaskapi.py'
|
||||
os.environ['FLASK_ENV'] = 'development'
|
||||
from stats import mystats
|
||||
|
||||
stats={}
|
||||
leaderboard={}
|
||||
top200={}
|
||||
|
||||
class BsDataThread(object):
|
||||
def __init__(self):
|
||||
self.Timer = ba.Timer( 8,ba.Call(self.refreshStats),timetype = ba.TimeType.REAL,repeat = True)
|
||||
self.Timerr = ba.Timer( 10,ba.Call(self.startThread),timetype = ba.TimeType.REAL,repeat = True)
|
||||
|
||||
def startThread(self):
|
||||
_thread.start_new_thread(self.refreshLeaderboard,())
|
||||
|
||||
def refreshLeaderboard(self):
|
||||
global leaderboard
|
||||
global top200
|
||||
_t200={}
|
||||
|
||||
lboard=mystats.get_all_stats()
|
||||
leaderboard=lboard
|
||||
try:
|
||||
entries = [(a['scores'], a['kills'], a['deaths'], a['games'], a['name'], a['aid'],a['last_seen']) for a in lboard.values()]
|
||||
except:
|
||||
print("stats reset is required , please clear out stats.json records , or download fresh stats.json from github")
|
||||
import _ba
|
||||
_ba.quit()
|
||||
entries.sort(key=lambda x: x[1] or 0, reverse=True)
|
||||
rank=0
|
||||
for entry in entries:
|
||||
rank+=1
|
||||
if rank >201:
|
||||
break
|
||||
_t200[entry[5]]={"rank":rank,"scores":int(entry[0]),"games":int(entry[3]),"kills":int(entry[1]),"deaths":int(entry[2]),"name_html":entry[4],"last_seen":entry[6]}
|
||||
top200=_t200
|
||||
|
||||
def refreshStats(self):
|
||||
|
||||
liveplayers={}
|
||||
nextMap=''
|
||||
currentMap=''
|
||||
global stats
|
||||
for i in ba.internal.get_game_roster():
|
||||
|
||||
|
||||
try:
|
||||
liveplayers[i['account_id']]={'name':i['players'][0]['name_full'],'client_id':i['client_id'],'device_id':i['display_string']}
|
||||
except:
|
||||
liveplayers[i['account_id']]={'name':"<in-lobby>",'clientid':i['client_id'],'device_id':i['display_string']}
|
||||
try:
|
||||
nextMap=ba.internal.get_foreground_host_session().get_next_game_description().evaluate()
|
||||
|
||||
current_game_spec=ba.internal.get_foreground_host_session()._current_game_spec
|
||||
gametype: Type[GameActivity] =current_game_spec['resolved_type']
|
||||
|
||||
currentMap=gametype.get_settings_display_string(current_game_spec).evaluate()
|
||||
except:
|
||||
pass
|
||||
minigame={'current':currentMap,'next':nextMap}
|
||||
# system={'cpu':"p.cpu_percent()",'ram':p.virtual_memory().percent}
|
||||
system={'cpu':"null",'ram':'null'}
|
||||
stats['system']=system
|
||||
stats['roster']=liveplayers
|
||||
stats['chats']=ba.internal.get_chat_messages()
|
||||
stats['playlist']=minigame
|
||||
stats['teamInfo']=self.getTeamInfo()
|
||||
|
||||
#print(self.getTeamInfo());
|
||||
|
||||
def getTeamInfo(self):
|
||||
data={}
|
||||
|
||||
session=ba.internal.get_foreground_host_session()
|
||||
data['sessionType']=type(session).__name__
|
||||
teams=session.sessionteams
|
||||
for team in teams:
|
||||
data[team.id]={'name':team.name.evaluate(),
|
||||
'color':list(team.color),
|
||||
'score':team.customdata['score'],
|
||||
'players':[]
|
||||
}
|
||||
for player in team.players:
|
||||
teamplayer={'name':player.getname(),
|
||||
'device_id':player.inputdevice.get_v1_account_name(True),
|
||||
'inGame':player.in_game,
|
||||
'character':player.character,
|
||||
'account_id':player.get_v1_account_id()
|
||||
}
|
||||
data[team.id]['players'].append(teamplayer)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
|
||||
BsDataThread()
|
||||
|
||||
|
||||
|
||||
import flask
|
||||
from flask import request, jsonify
|
||||
|
||||
app = flask.Flask(__name__)
|
||||
app = Flask(__name__)
|
||||
app.config["DEBUG"] = False
|
||||
SECRET_KEY = "my_secret_key"
|
||||
|
||||
|
||||
@app.after_request
|
||||
def add_cors_headers(response):
|
||||
# Allow requests from any origin
|
||||
response.headers['Access-Control-Allow-Origin'] = '*'
|
||||
# Allow specific headers
|
||||
response.headers['Access-Control-Allow-Headers'] = 'Content-Type,Authorization,Secret-Key'
|
||||
# Allow specific HTTP methods
|
||||
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE'
|
||||
return response
|
||||
|
||||
|
||||
def check_admin(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
if "Secret-Key" not in request.headers or request.headers["Secret-Key"] != SECRET_KEY:
|
||||
return jsonify({"message": "Invalid secret key provided."}), 401
|
||||
return func(*args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
|
||||
@app.route('/', methods=['GET'])
|
||||
|
|
@ -122,26 +46,219 @@ def home():
|
|||
return '''Nothing here :)'''
|
||||
|
||||
|
||||
# A route to return all of the available entries in our catalog.
|
||||
@app.route('/getStats', methods=['GET'])
|
||||
def api_all():
|
||||
return json.dumps(stats)
|
||||
@app.route('/api/live-stats', methods=['GET'])
|
||||
def get_live_stats():
|
||||
return jsonify(bombsquad_service.get_stats()), 200
|
||||
|
||||
@app.route('/getLeaderboard',methods=['GET'])
|
||||
def get_l():
|
||||
return json.dumps(leaderboard)
|
||||
|
||||
@app.route('/getTop200',methods=['GET'])
|
||||
@app.route('/api/top-200', methods=['GET'])
|
||||
def get_top200():
|
||||
return json.dumps(top200)
|
||||
return jsonify(bombsquad_service.get_top_200()), 200
|
||||
|
||||
|
||||
class InitalRun:
|
||||
def __init__(self):
|
||||
print("start flask")
|
||||
flask_run = _thread.start_new_thread(app.run, ("0.0.0.0",5000,False ))
|
||||
# ============ Admin only =========
|
||||
|
||||
|
||||
@app.route('/api/login', methods=['POST'])
|
||||
@check_admin
|
||||
def login():
|
||||
return jsonify({"message": "Successful"}), 200
|
||||
|
||||
|
||||
@app.route('/api/current-leaderboard', methods=['GET'])
|
||||
@check_admin
|
||||
def get_complete_leaderboard():
|
||||
return jsonify(bombsquad_service.get_complete_leaderboard()), 200
|
||||
|
||||
|
||||
@app.route('/api/server-settings', methods=['GET'])
|
||||
@check_admin
|
||||
def get_server_settings():
|
||||
return jsonify(bombsquad_service.get_server_settings()), 200
|
||||
|
||||
|
||||
@app.route('/api/roles', methods=['GET'])
|
||||
@check_admin
|
||||
def get_roles():
|
||||
return jsonify(bombsquad_service.get_roles()), 200
|
||||
|
||||
|
||||
@app.route('/api/roles', methods=['POST'])
|
||||
@check_admin
|
||||
def update_roles():
|
||||
try:
|
||||
data = request.get_json()
|
||||
bombsquad_service.update_roles(data)
|
||||
response = {
|
||||
'message': 'Roles updated successfully'}
|
||||
return jsonify(response), 201
|
||||
except Exception as e:
|
||||
return jsonify({'message': 'Error processing request', 'error': str(e)}), 400
|
||||
|
||||
|
||||
@app.route('/api/perks', methods=['GET'])
|
||||
@check_admin
|
||||
def get_perks():
|
||||
return jsonify(bombsquad_service.get_perks()), 200
|
||||
|
||||
|
||||
@app.route('/api/perks', methods=['POST'])
|
||||
@check_admin
|
||||
def update_perks():
|
||||
try:
|
||||
data = request.get_json()
|
||||
bombsquad_service.update_perks(data)
|
||||
response = {
|
||||
'message': 'Custom perks updated successfully'}
|
||||
return jsonify(response), 201
|
||||
except Exception as e:
|
||||
return jsonify({'message': 'Error processing request', 'error': str(e)}), 400
|
||||
|
||||
|
||||
@app.route('/api/server-settings', methods=['POST'])
|
||||
@check_admin
|
||||
def update_server_settings():
|
||||
try:
|
||||
data = request.get_json()
|
||||
bombsquad_service.update_server_settings(data)
|
||||
response = {
|
||||
'message': 'Settings updated successfully, server may need restart'}
|
||||
return jsonify(response), 201
|
||||
except Exception as e:
|
||||
return jsonify({'message': 'Error processing request', 'error': str(e)}), 400
|
||||
|
||||
|
||||
@app.route('/api/db-list', methods=['GET'])
|
||||
@check_admin
|
||||
def fetch_dB_list():
|
||||
key = request.args.get('type')
|
||||
if key is None:
|
||||
return "type required", 400
|
||||
if key == "logs":
|
||||
return jsonify(bombsquad_service.get_logs_db_list()), 200
|
||||
elif key == "players":
|
||||
return jsonify(bombsquad_service.get_profiles_db_list()), 200
|
||||
else:
|
||||
return jsonify({"message": "Invalid db type"}), 400
|
||||
|
||||
|
||||
@app.route('/api/search-logs', methods=['GET'])
|
||||
@check_admin
|
||||
def search_logs():
|
||||
key = request.args.get('key')
|
||||
db = request.args.get('db')
|
||||
if key is None or db is None:
|
||||
return jsonify({"message": "key and db required"}), 400
|
||||
return jsonify(bombsquad_service.get_matching_logs(key, db)), 200
|
||||
|
||||
|
||||
@app.route('/api/search-player', methods=['GET'])
|
||||
@check_admin
|
||||
def search_players():
|
||||
key = request.args.get('key')
|
||||
db = request.args.get('db')
|
||||
if key is None or db is None:
|
||||
return jsonify({"message": "key and db required"}), 400
|
||||
return jsonify(bombsquad_service.search_player_profile(key, db)), 200
|
||||
|
||||
|
||||
@app.route('/api/get-player-info', methods=['GET'])
|
||||
@check_admin
|
||||
def get_player():
|
||||
account_id = request.args.get('account-id')
|
||||
if account_id is None:
|
||||
return jsonify({"message": "account-id required"}), 400
|
||||
return jsonify(bombsquad_service.get_player_details(account_id)), 200
|
||||
|
||||
|
||||
@app.route('/api/update-player', methods=['POST'])
|
||||
@check_admin
|
||||
def update_player():
|
||||
account_id = request.args.get('account-id')
|
||||
action = request.args.get('action')
|
||||
duration = int(request.args.get('duration'))
|
||||
if account_id is None or action is None:
|
||||
return "account-id and action required", 400
|
||||
if action == "ban":
|
||||
bombsquad_service.ban_player(account_id, duration)
|
||||
elif action == "unban":
|
||||
bombsquad_service.unban_player(account_id)
|
||||
elif action == "mute":
|
||||
bombsquad_service.mute_player(account_id, duration)
|
||||
elif action == "unmute":
|
||||
bombsquad_service.unmute_player(account_id)
|
||||
elif action == "disable-kick-vote":
|
||||
bombsquad_service.disable_kick_vote(account_id, duration)
|
||||
elif action == "enable-kick-vote":
|
||||
bombsquad_service.enable_kick_vote(account_id)
|
||||
else:
|
||||
return jsonify({"message": "Invalid Action"}), 400
|
||||
return jsonify({"message": f"{action} done"}), 201
|
||||
|
||||
|
||||
@app.route('/api/config', methods=['GET'])
|
||||
@check_admin
|
||||
def get_config():
|
||||
return jsonify(bombsquad_service.get_server_config()), 200
|
||||
|
||||
|
||||
@app.route('/api/action', methods=['POST'])
|
||||
@check_admin
|
||||
def do_action():
|
||||
action = request.args.get('action')
|
||||
value = request.args.get('value')
|
||||
bombsquad_service.do_action(action, value)
|
||||
return jsonify({"message": f'{action} done'}), 200
|
||||
|
||||
|
||||
@app.route('/api/config', methods=['POST'])
|
||||
@check_admin
|
||||
def update_server_config():
|
||||
try:
|
||||
data = request.get_json()
|
||||
bombsquad_service.update_server_config(data)
|
||||
response = {
|
||||
'message': 'config updated successfully, server will restart'}
|
||||
return jsonify(response), 201
|
||||
except Exception as e:
|
||||
return jsonify({'message': 'Error processing request', 'error': str(e)}), 400
|
||||
|
||||
# from flask_asgi import FlaskASGI
|
||||
# asgi_app = FlaskASGI(app)
|
||||
|
||||
|
||||
# class FlaskApplication(BaseApplication):
|
||||
# def __init__(self, app, options=None):
|
||||
# self.options = options or {}
|
||||
# self.application = app
|
||||
# super(FlaskApplication, self).__init__()
|
||||
|
||||
# def load_config(self):
|
||||
# config = {key: value for key, value in self.options.items(
|
||||
# ) if key in self.cfg.settings and value is not None}
|
||||
# for key, value in config.items():
|
||||
# self.cfg.set(key.lower(), value)
|
||||
|
||||
# def load(self):
|
||||
# return self.application
|
||||
|
||||
|
||||
# def start_uvicorn():
|
||||
# uvicorn.run("main:app", host='0.0.0.0', port=5000,
|
||||
# reload=False, log_level="debug", workers=3, use_colors=True, no_signal=True)
|
||||
# flask_run = _thread.start_new_thread(app.run, ("0.0.0.0", 5000, False))
|
||||
|
||||
|
||||
def enable():
|
||||
InitalRun()
|
||||
# SAMPLE OUTPUT
|
||||
# {'system': {'cpu': 80, 'ram': 34}, 'roster': {}, 'chats': [], 'playlist': {'current': 'Meteor Shower @ Rampage', 'next': 'Assault @ Step Right Up'}, 'teamInfo': {'sessionType': 'DualTeamSession', 0: {'name': 'Blue', 'color': (0.1, 0.25, 1.0), 'score': 1, 'players': [{'name': 'Jolly', 'device_id': '\ue030PC295588', 'inGame': True, 'character': 'xmas', 'account_id': 'pb-IF4TVWwZUQ=='}]}, 1: {'name': 'Red', 'color': (1.0, 0.25, 0.2), 'score': 0, 'players': []}}}
|
||||
flask_run = _thread.start_new_thread(app.run, ("0.0.0.0", 5000, False))
|
||||
# uvicorn_thread = threading.Thread(target=start_uvicorn)
|
||||
# uvicorn_thread.start()
|
||||
# options = {
|
||||
# 'bind': '0.0.0.0:8000',
|
||||
# 'workers': 4,
|
||||
# 'worker_class': 'gevent'
|
||||
# }
|
||||
|
||||
# flask_app = FlaskApplication(app, options)
|
||||
# gevent_worker.GeventWorker(app.wsgi_app).init_process()
|
||||
# flask_app.run()
|
||||
|
|
|
|||
257
dist/ba_root/mods/plugins/bombsquad_service.py
vendored
Normal file
257
dist/ba_root/mods/plugins/bombsquad_service.py
vendored
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
import ba
|
||||
import _ba
|
||||
import ba.internal
|
||||
from stats import mystats
|
||||
from typing import Optional, Any, Dict, List, Type, Sequence
|
||||
from ba._gameactivity import GameActivity
|
||||
from playersData import pdata
|
||||
from serverData import serverdata
|
||||
from tools import servercheck, logger
|
||||
import setting
|
||||
from datetime import datetime
|
||||
import _thread
|
||||
import os
|
||||
import yaml
|
||||
stats = {}
|
||||
leaderboard = {}
|
||||
top200 = {}
|
||||
|
||||
serverinfo = {}
|
||||
|
||||
|
||||
class BsDataThread(object):
|
||||
def __init__(self):
|
||||
global stats
|
||||
stats["name"] = _ba.app.server._config.party_name
|
||||
stats["discord"] = "https://discord.gg/ucyaesh"
|
||||
stats["vapidKey"] = "sjfbsdjfdsf"
|
||||
|
||||
self.refresh_stats_cache_timer = ba.Timer(8, ba.Call(self.refreshStats),
|
||||
timetype=ba.TimeType.REAL, repeat=True)
|
||||
self.refresh_leaderboard_cache_timer = ba.Timer(10, ba.Call(
|
||||
self.refreshLeaderboard), timetype=ba.TimeType.REAL, repeat=True)
|
||||
|
||||
def startThread(self):
|
||||
_thread.start_new_thread(self.refreshLeaderboard, ())
|
||||
|
||||
def refreshLeaderboard(self):
|
||||
global leaderboard
|
||||
global top200
|
||||
|
||||
lboard = mystats.get_cached_stats()
|
||||
leaderboard = lboard
|
||||
sorted_data = sorted(lboard.values(), key=lambda x: x["rank"])
|
||||
top_200_players = sorted_data[:200]
|
||||
|
||||
top200 = {player["aid"]: player for player in top_200_players}
|
||||
|
||||
def refreshStats(self):
|
||||
global stats
|
||||
global serverinfo
|
||||
liveplayers = {}
|
||||
nextMap = ''
|
||||
currentMap = ''
|
||||
|
||||
for i in ba.internal.get_game_roster():
|
||||
try:
|
||||
liveplayers[i['account_id']] = {
|
||||
'name': i['players'][0]['name_full'], 'client_id': i['client_id'], 'device_id': i['display_string']}
|
||||
except:
|
||||
liveplayers[i['account_id']] = {
|
||||
'name': "<in-lobby>", 'client_id': i['client_id'], 'device_id': i['display_string']}
|
||||
try:
|
||||
nextMap = ba.internal.get_foreground_host_session(
|
||||
).get_next_game_description().evaluate()
|
||||
|
||||
current_game_spec = ba.internal.get_foreground_host_session()._current_game_spec
|
||||
gametype: Type[GameActivity] = current_game_spec['resolved_type']
|
||||
|
||||
currentMap = gametype.get_settings_display_string(
|
||||
current_game_spec).evaluate()
|
||||
except:
|
||||
pass
|
||||
current_games = {'current': currentMap, 'next': nextMap}
|
||||
# system={'cpu':"p.cpu_percent()",'ram':p.virtual_memory().percent}
|
||||
system = {'cpu': "null", 'ram': 'null'}
|
||||
stats['system'] = system
|
||||
stats['roster'] = liveplayers
|
||||
stats['chats'] = ba.internal.get_chat_messages()
|
||||
stats['playlist'] = current_games
|
||||
stats['teamInfo'] = self.getTeamInfo()
|
||||
stats["sessionType"] = type(
|
||||
ba.internal.get_foreground_host_session()).__name__
|
||||
|
||||
# print(self.getTeamInfo());
|
||||
|
||||
def getTeamInfo(self):
|
||||
data = {}
|
||||
session = ba.internal.get_foreground_host_session()
|
||||
if session:
|
||||
teams = session.sessionteams
|
||||
for team in teams:
|
||||
data[str(team.id)] = {'name': team.name if isinstance(team.name, str) else team.name.evaluate(),
|
||||
'color': list(team.color),
|
||||
'score': team.customdata['score'],
|
||||
'players': []
|
||||
}
|
||||
for player in team.players:
|
||||
teamplayer = {'name': player.getname(),
|
||||
'device_id': player.inputdevice.get_v1_account_name(True),
|
||||
'inGame': player.in_game,
|
||||
'character': player.character,
|
||||
'account_id': player.get_v1_account_id()
|
||||
}
|
||||
data[str(team.id)]['players'].append(teamplayer)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
BsDataThread()
|
||||
|
||||
|
||||
def get_stats():
|
||||
return stats
|
||||
|
||||
|
||||
def get_complete_leaderboard():
|
||||
return leaderboard
|
||||
|
||||
|
||||
def get_top_200():
|
||||
return top200
|
||||
|
||||
|
||||
def get_server_settings():
|
||||
return setting.get_settings_data()
|
||||
|
||||
|
||||
def update_server_settings(settings):
|
||||
logger.log(f'updating server settings, request from web')
|
||||
setting.commit(settings)
|
||||
|
||||
|
||||
def get_roles():
|
||||
return pdata.get_roles()
|
||||
|
||||
|
||||
def get_perks():
|
||||
# TODO wire with spaz_effects to fetch list of effects.
|
||||
return {"perks": pdata.get_custom_perks(), "availableEffects": ["spark", "glow", "fairydust"]}
|
||||
|
||||
|
||||
def update_perks(custom):
|
||||
logger.log(f'updating custom perks, request from web')
|
||||
pdata.update_custom_perks(custom)
|
||||
|
||||
|
||||
def update_roles(roles):
|
||||
logger.log("updated roles from web")
|
||||
return pdata.update_roles(roles)
|
||||
|
||||
|
||||
def get_profiles_db_list():
|
||||
return pdata.get_profiles_archive_index()
|
||||
|
||||
|
||||
def get_logs_db_list():
|
||||
return serverdata.get_stats_index()
|
||||
|
||||
|
||||
def get_matching_logs(key: str, filename: str):
|
||||
logs = serverdata.read_logs(filename)
|
||||
matching_lines = [line.strip() for line in logs.split('\n') if key in line]
|
||||
return matching_lines
|
||||
|
||||
|
||||
def search_player_profile(search_key: str, db: str):
|
||||
selectedDB = {}
|
||||
if db == "profiles.json":
|
||||
selectedDB = pdata.get_profiles()
|
||||
|
||||
elif db in pdata.get_profiles_archive_index():
|
||||
selectedDB = pdata.get_old_profiles(db)
|
||||
|
||||
matching_objects = {}
|
||||
for key in selectedDB.keys():
|
||||
if (search_key == key or
|
||||
any(search_key.lower() in s.lower() for s in selectedDB[key].get("display_string", [])) or
|
||||
search_key.lower() in selectedDB[key].get("name", "").lower()):
|
||||
matching_objects[key] = selectedDB[key]
|
||||
return matching_objects
|
||||
|
||||
|
||||
def get_player_details(account_id: str):
|
||||
current_time = datetime.now()
|
||||
current_profiles = pdata.get_profiles()
|
||||
ip = ""
|
||||
device_id = ""
|
||||
if account_id in current_profiles:
|
||||
ip = current_profiles[account_id]["lastIP"]
|
||||
device_id = current_profiles[account_id]["deviceUUID"]
|
||||
extra_info = pdata.get_detailed_info(account_id)
|
||||
isBanned = False
|
||||
isMuted = False
|
||||
isKickVoteDisabled = False
|
||||
haveBanReason = servercheck.check_ban(ip, device_id, account_id, False)
|
||||
if haveBanReason:
|
||||
isBanned = True
|
||||
extra_info += " , Banned for > " + haveBanReason
|
||||
if account_id in pdata.get_blacklist()["muted-ids"] and current_time < datetime.strptime(pdata.get_blacklist()["muted-ids"][account_id]["till"], "%Y-%m-%d %H:%M:%S"):
|
||||
isMuted = True
|
||||
extra_info += f', Muted for > { pdata.get_blacklist()["muted-ids"][account_id]["reason"] } , till > {pdata.get_blacklist()["muted-ids"][account_id]["till"]} ,'
|
||||
if account_id in pdata.get_blacklist()["kick-vote-disabled"] and current_time < datetime.strptime(pdata.get_blacklist()["kick-vote-disabled"][account_id]["till"], "%Y-%m-%d %H:%M:%S"):
|
||||
isKickVoteDisabled = True
|
||||
extra_info += f', Kick vote disabled for > { pdata.get_blacklist()["kick-vote-disabled"][account_id]["reason"] } , till > {pdata.get_blacklist()["kick-vote-disabled"][account_id]["till"]} '
|
||||
|
||||
return {"extra": extra_info, "isBan": isBanned, "isMuted": isMuted, "isKickVoteDisabled": isKickVoteDisabled}
|
||||
|
||||
|
||||
def unban_player(account_id):
|
||||
logger.log(f'unbanning {account_id} , request from web')
|
||||
pdata.unban_player(account_id)
|
||||
|
||||
|
||||
def unmute_player(account_id):
|
||||
logger.log(f'unmuting {account_id} , request from web')
|
||||
pdata.unmute(account_id)
|
||||
|
||||
|
||||
def enable_kick_vote(account_id):
|
||||
logger.log(f'enabling kick vote for {account_id} , request from web')
|
||||
pdata.enable_kick_vote(account_id)
|
||||
|
||||
# TODO take duration input
|
||||
|
||||
|
||||
def ban_player(account_id, duration):
|
||||
logger.log(f'banning {account_id} , request from web')
|
||||
pdata.ban_player(account_id, duration, "manually from website")
|
||||
|
||||
|
||||
def mute_player(account_id, duration):
|
||||
logger.log(f'muting {account_id} , request from web')
|
||||
pdata.mute(account_id, duration, "manually from website")
|
||||
|
||||
|
||||
def disable_kick_vote(account_id, duration):
|
||||
logger.log(f'disable {account_id} , request from web')
|
||||
pdata.disable_kick_vote(account_id, duration, "manually from website")
|
||||
|
||||
|
||||
def get_server_config():
|
||||
return _ba.app.server._config.__dict__
|
||||
|
||||
|
||||
def update_server_config(config):
|
||||
current_dir = os.getcwd()
|
||||
file_path = os.path.join(current_dir, '..', 'config.yaml')
|
||||
|
||||
with open(file_path, "w") as f:
|
||||
f.write(yaml.dump(config))
|
||||
|
||||
|
||||
def do_action(action, value):
|
||||
if action == "message":
|
||||
_ba.pushcall(ba.Call(_ba.chatmessage, value), from_other_thread=True)
|
||||
elif action == "quit":
|
||||
_ba.pushcall(ba.Call(_ba.quit), from_other_thread=True)
|
||||
29
dist/ba_root/mods/serverData/serverdata.py
vendored
29
dist/ba_root/mods/serverData/serverdata.py
vendored
|
|
@ -1,8 +1,37 @@
|
|||
# Released under the MIT License. See LICENSE for details.
|
||||
|
||||
import fcntl
|
||||
import _ba
|
||||
import os
|
||||
clients = {}
|
||||
cachedclients = []
|
||||
muted = False
|
||||
coopmode = False
|
||||
ips = {}
|
||||
recents = []
|
||||
|
||||
|
||||
SERVER_DATA_PATH = os.path.join(
|
||||
_ba.env()["python_directory_user"], "serverData" + os.sep
|
||||
)
|
||||
|
||||
|
||||
def get_stats_index():
|
||||
return [x for x in os.listdir(SERVER_DATA_PATH) if "log" in x]
|
||||
|
||||
|
||||
def read_logs(filename):
|
||||
file_path = SERVER_DATA_PATH+filename
|
||||
if not os.path.exists(file_path):
|
||||
return ""
|
||||
file = open(file_path, "r")
|
||||
fcntl.flock(file.fileno(), fcntl.LOCK_SH)
|
||||
contents = ""
|
||||
try:
|
||||
contents = file.read()
|
||||
|
||||
finally:
|
||||
fcntl.flock(file.fileno(), fcntl.LOCK_UN)
|
||||
file.close()
|
||||
|
||||
return contents
|
||||
|
|
|
|||
6
dist/ba_root/mods/setting.py
vendored
6
dist/ba_root/mods/setting.py
vendored
|
|
@ -30,6 +30,10 @@ def get_settings_data() -> dict:
|
|||
with open(SETTINGS_PATH, mode="r", encoding="utf-8") as data:
|
||||
return json.load(data)
|
||||
|
||||
def refresh_cache() -> None:
|
||||
get_settings_data.cache_clear()
|
||||
# lets cache it again
|
||||
get_settings_data()
|
||||
|
||||
def commit(data: dict) -> None:
|
||||
"""Commits the data in setting file.
|
||||
|
|
@ -41,3 +45,5 @@ def commit(data: dict) -> None:
|
|||
"""
|
||||
with open(SETTINGS_PATH, mode="w", encoding="utf-8") as setting_file:
|
||||
json.dump(data, setting_file, indent=4)
|
||||
# settings updated ok now update the cache
|
||||
refresh_cache()
|
||||
|
|
|
|||
44
dist/ba_root/mods/stats/mystats.py
vendored
44
dist/ba_root/mods/stats/mystats.py
vendored
|
|
@ -6,29 +6,17 @@ import os
|
|||
import shutil
|
||||
import threading
|
||||
import datetime
|
||||
import custom_hooks
|
||||
|
||||
import urllib.request
|
||||
from ba._activitytypes import *
|
||||
from ba import _activitytypes as ba_actypes
|
||||
from ba._lobby import JoinInfo
|
||||
from typing import Any, Dict, Optional
|
||||
from ba._team import EmptyTeam # pylint: disable=W0611
|
||||
from ba._player import EmptyPlayer # pylint: disable=W0611
|
||||
from ba._music import setmusic, MusicType
|
||||
from ba._activity import Activity
|
||||
|
||||
damage_data = {}
|
||||
# Don't touch the above line
|
||||
"""
|
||||
mystats module for BombSquad version 1.5.29
|
||||
Provides functionality for dumping player stats to disk between rounds.
|
||||
"""
|
||||
|
||||
ranks = []
|
||||
top3Name = []
|
||||
# False-positive from pylint due to our class-generics-filter.
|
||||
|
||||
# variables
|
||||
our_settings = setting.get_settings_data()
|
||||
# where our stats file and pretty html output will go
|
||||
|
||||
base_path = os.path.join(_ba.env()['python_directory_user'], "stats" + os.sep)
|
||||
statsfile = base_path + 'stats.json'
|
||||
cached_stats = {}
|
||||
|
|
@ -47,16 +35,14 @@ statsDefault = {
|
|||
"last_seen": "2022-04-26 17:01:13.715014"
|
||||
}
|
||||
}
|
||||
# <th><b>Total Damage</b></th> #removed this line as it isn't crt data
|
||||
|
||||
# useful functions
|
||||
|
||||
seasonStartDate = None
|
||||
|
||||
|
||||
def get_all_stats():
|
||||
global seasonStartDate
|
||||
if os.path.exists(statsfile):
|
||||
renameFile = False
|
||||
with open(statsfile, 'r', encoding='utf8') as f:
|
||||
try:
|
||||
jsonData = json.loads(f.read())
|
||||
|
|
@ -83,7 +69,7 @@ def get_all_stats():
|
|||
|
||||
def backupStatsFile():
|
||||
shutil.copy(statsfile, statsfile.replace(
|
||||
".json", "") + str(seasonStartDate) + ".json")
|
||||
".json", "") + str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + ".json")
|
||||
|
||||
|
||||
def dump_stats(s: dict):
|
||||
|
|
@ -107,23 +93,27 @@ def get_stats_by_id(account_id: str):
|
|||
else:
|
||||
return None
|
||||
|
||||
|
||||
def get_cached_stats():
|
||||
return cached_stats
|
||||
|
||||
|
||||
def get_sorted_stats(stats):
|
||||
entries = [(a['scores'], a['kills'], a['deaths'], a['games'],
|
||||
a['name'], a['aid']) for a in stats.values()]
|
||||
# this gives us a list of kills/names sorted high-to-low
|
||||
entries.sort(key=lambda x: x[1] or 0, reverse=True)
|
||||
return entries
|
||||
|
||||
|
||||
def refreshStats():
|
||||
global cached_stats
|
||||
# lastly, write a pretty html version.
|
||||
# our stats url could point at something like this...
|
||||
pStats = get_all_stats()
|
||||
cached_stats = pStats
|
||||
|
||||
|
||||
entries = [(a['scores'], a['kills'], a['deaths'], a['games'],
|
||||
a['name'], a['aid']) for a in pStats.values()]
|
||||
# this gives us a list of kills/names sorted high-to-low
|
||||
entries.sort(key=lambda x: x[1] or 0, reverse=True)
|
||||
entries = get_sorted_stats(pStats)
|
||||
rank = 0
|
||||
toppers = {}
|
||||
toppersIDs = []
|
||||
_ranks = []
|
||||
for entry in entries:
|
||||
|
|
|
|||
39
dist/ba_root/mods/tools/logger.py
vendored
39
dist/ba_root/mods/tools/logger.py
vendored
|
|
@ -17,7 +17,7 @@ import shutil
|
|||
import threading
|
||||
import setting
|
||||
import _ba
|
||||
|
||||
import fcntl
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
|
||||
|
|
@ -33,6 +33,7 @@ if SETTINGS["discordbot"]["enable"]:
|
|||
|
||||
WEBHOOK_URL = SETTINGS["discordWebHook"]["webhookURL"]
|
||||
|
||||
|
||||
@dataclass
|
||||
class RecentLogs:
|
||||
"""Saves the recent logs."""
|
||||
|
|
@ -54,7 +55,7 @@ def log(msg: str, mtype: str = "sys") -> None:
|
|||
message = msg.replace("||", "|")
|
||||
discord_bot.push_log("***" + mtype + ":***" + message)
|
||||
|
||||
current_time = datetime.datetime.now()
|
||||
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
msg = f"{current_time} + : {msg} \n"
|
||||
|
||||
if SETTINGS["discordWebHook"]["enable"]:
|
||||
|
|
@ -102,14 +103,38 @@ class dumplogs(threading.Thread):
|
|||
elif self.type == "cmndlog":
|
||||
log_path = SERVER_DATA_PATH + "cmndusage.log"
|
||||
else:
|
||||
log_path = SERVER_DATA_PATH + "logs.log"
|
||||
log_path = SERVER_DATA_PATH + "systemlogs.log"
|
||||
if os.path.exists(log_path):
|
||||
if os.stat(log_path).st_size > 1000000:
|
||||
shutil.copy(log_path, log_path+str(datetime.datetime.now()))
|
||||
os.remove(log_path)
|
||||
with open(log_path, mode="a+", encoding="utf-8") as file:
|
||||
for msg in self.msg:
|
||||
self.copy_file(
|
||||
log_path, log_path+str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
|
||||
|
||||
self.write_file(log_path, self.msg)
|
||||
|
||||
def write_file(self, file_path, data):
|
||||
file = open(file_path, "a+", encoding="utf-8")
|
||||
fcntl.flock(file.fileno(), fcntl.LOCK_EX)
|
||||
|
||||
try:
|
||||
for msg in data:
|
||||
file.write(msg)
|
||||
finally:
|
||||
fcntl.flock(file.fileno(), fcntl.LOCK_UN)
|
||||
file.close()
|
||||
|
||||
def copy_file(self, file_path, dest_path):
|
||||
lock_file = open(file_path, "r")
|
||||
fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
|
||||
try:
|
||||
shutil.copy(file_path, dest_path)
|
||||
except Exception as e:
|
||||
print("Error occurred while copying file:", str(e))
|
||||
finally:
|
||||
fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)
|
||||
lock_file.close()
|
||||
os.remove(lock_file)
|
||||
|
||||
|
||||
def send_webhook_message():
|
||||
global webhook_queue
|
||||
|
|
|
|||
109
dist/ba_root/mods/tools/servercheck.py
vendored
109
dist/ba_root/mods/tools/servercheck.py
vendored
|
|
@ -7,7 +7,7 @@ import _ba
|
|||
import ba.internal
|
||||
import urllib.request
|
||||
import json
|
||||
import datetime
|
||||
from datetime import datetime
|
||||
import time
|
||||
import ba
|
||||
from ba._general import Call
|
||||
|
|
@ -23,11 +23,13 @@ blacklist = pdata.get_blacklist()
|
|||
settings = setting.get_settings_data()
|
||||
ipjoin = {}
|
||||
|
||||
|
||||
class checkserver(object):
|
||||
def start(self):
|
||||
self.players = []
|
||||
|
||||
self.t1 = ba.Timer(1, ba.Call(self.check), repeat=True, timetype=ba.TimeType.REAL)
|
||||
self.t1 = ba.Timer(1, ba.Call(self.check),
|
||||
repeat=True, timetype=ba.TimeType.REAL)
|
||||
|
||||
def check(self):
|
||||
newPlayers = []
|
||||
|
|
@ -36,16 +38,15 @@ class checkserver(object):
|
|||
for ros in ba.internal.get_game_roster():
|
||||
ip = _ba.get_client_ip(ros["client_id"])
|
||||
device_id = _ba.get_client_public_device_uuid(ros["client_id"])
|
||||
# if not ros["account_id"]:
|
||||
# logger.log(f'Player disconnected, None account Id || {ros["display_string"] } IP {ip} {device_id}' ,
|
||||
# "playerjoin")
|
||||
# ba.internal.disconnect_client(ros["client_id"], 0)
|
||||
if (device_id == None):
|
||||
device_id = _ba.get_client_device_uuid(ros["client_id"])
|
||||
if device_id not in deviceClientMap:
|
||||
deviceClientMap[device_id] = [ros["client_id"]]
|
||||
else:
|
||||
deviceClientMap[device_id].append(ros["client_id"])
|
||||
if len(deviceClientMap[device_id]) >= settings['maxAccountPerIP']:
|
||||
_ba.chatmessage(f"Only {settings['maxAccountPerIP']} player per IP allowed, disconnecting this device.", clients=[ros["client_id"]])
|
||||
_ba.chatmessage(f"Only {settings['maxAccountPerIP']} player per IP allowed, disconnecting this device.", clients=[
|
||||
ros["client_id"]])
|
||||
ba.internal.disconnect_client(ros["client_id"])
|
||||
logger.log(f'Player disconnected, reached max players per device || {ros["account_id"]}',
|
||||
"playerjoin")
|
||||
|
|
@ -55,7 +56,8 @@ class checkserver(object):
|
|||
else:
|
||||
ipClientMap[ip].append(ros["client_id"])
|
||||
if len(ipClientMap[ip]) >= settings['maxAccountPerIP']:
|
||||
_ba.chatmessage(f"Only {settings['maxAccountPerIP']} player per IP allowed, disconnecting this device.", clients=[ros["client_id"]])
|
||||
_ba.chatmessage(f"Only {settings['maxAccountPerIP']} player per IP allowed, disconnecting this device.", clients=[
|
||||
ros["client_id"]])
|
||||
ba.internal.disconnect_client(ros["client_id"])
|
||||
logger.log(f'Player disconnected, reached max players per IP address || {ros["account_id"]}',
|
||||
"playerjoin")
|
||||
|
|
@ -92,7 +94,8 @@ class checkserver(object):
|
|||
_ba.screenmessage("Not in whitelist,contact admin",
|
||||
color=(1, 0, 0), transient=True,
|
||||
clients=[ros['client_id']])
|
||||
logger.log(f'{d_str} || { ros["account_id"]} | kicked > not in whitelist')
|
||||
logger.log(
|
||||
f'{d_str} || { ros["account_id"]} | kicked > not in whitelist')
|
||||
ba.internal.disconnect_client(ros['client_id'])
|
||||
|
||||
return
|
||||
|
|
@ -101,14 +104,15 @@ class checkserver(object):
|
|||
if ros['account_id'] in serverdata.clients:
|
||||
on_player_join_server(ros['account_id'],
|
||||
serverdata.clients[
|
||||
ros['account_id']], ip)
|
||||
ros['account_id']], ip, device_id)
|
||||
else:
|
||||
LoadProfile(ros['account_id'], ip).start() # from local cache, then call on_player_join_server
|
||||
# from local cache, then call on_player_join_server
|
||||
LoadProfile(ros['account_id'], ip, device_id).start()
|
||||
|
||||
self.players = newPlayers
|
||||
|
||||
|
||||
def on_player_join_server(pbid, player_data, ip):
|
||||
def on_player_join_server(pbid, player_data, ip, device_id):
|
||||
global ipjoin
|
||||
now = time.time()
|
||||
# player_data=pdata.get_info(pbid)
|
||||
|
|
@ -124,7 +128,7 @@ def on_player_join_server(pbid, player_data, ip):
|
|||
if now - lastjoin < 15:
|
||||
joincount += 1
|
||||
if joincount > 2:
|
||||
_ba.screenmessage("Joining too fast , slow down dude",
|
||||
_ba.screenmessage("Joining too fast , slow down dude", # its not possible now tho, network layer will catch it before reaching here
|
||||
color=(1, 0, 1), transient=True,
|
||||
clients=[clid])
|
||||
logger.log(f'{pbid} || kicked for joining too fast')
|
||||
|
|
@ -141,40 +145,40 @@ def on_player_join_server(pbid, player_data, ip):
|
|||
if pbid in serverdata.clients:
|
||||
serverdata.clients[pbid]["lastJoin"] = now
|
||||
|
||||
if player_data != None: # player data not in serevrdata or in local.json cache
|
||||
serverdata.recents.append({"client_id":clid,"deviceId":device_string,"pbid":pbid})
|
||||
if player_data != None: # player data is in serevrdata or in local.json cache
|
||||
serverdata.recents.append(
|
||||
{"client_id": clid, "deviceId": device_string, "pbid": pbid})
|
||||
serverdata.recents = serverdata.recents[-20:]
|
||||
if player_data["isBan"] or get_account_age(player_data["accountAge"]) < \
|
||||
if check_ban(ip, device_id, pbid):
|
||||
_ba.chatmessage(
|
||||
'sad ,your account is flagged contact server owner for unban', clients=[clid])
|
||||
ba.internal.disconnect_client(clid)
|
||||
return
|
||||
if get_account_age(player_data["accountAge"]) < \
|
||||
settings["minAgeToJoinInHours"]:
|
||||
for ros in ba.internal.get_game_roster():
|
||||
if ros['account_id'] == pbid:
|
||||
if not player_data["isBan"]:
|
||||
_ba.screenmessage(
|
||||
"New Accounts not allowed here , come back later",
|
||||
color=(1, 0, 0), transient=True,
|
||||
clients=[ros['client_id']])
|
||||
logger.log(pbid + " | kicked > reason:Banned account")
|
||||
_ba.screenmessage(
|
||||
"Contact server owner, your account not allowed here",
|
||||
color=(1, 0, 0), transient=True,
|
||||
clients=[ros['client_id']])
|
||||
ba.internal.disconnect_client(ros['client_id'])
|
||||
|
||||
return
|
||||
else:
|
||||
current_time = datetime.now()
|
||||
if pbid not in serverdata.clients:
|
||||
if check_ban(clid,pbid):
|
||||
return
|
||||
# ahh , lets reset if plyer joining after some long time
|
||||
serverdata.clients[pbid] = player_data
|
||||
serverdata.clients[pbid]["warnCount"] = 0
|
||||
serverdata.clients[pbid]["lastWarned"] = time.time()
|
||||
serverdata.clients[pbid]["verified"] = False
|
||||
serverdata.clients[pbid]["rejoincount"] = 1
|
||||
serverdata.clients[pbid]["lastJoin"] = time.time()
|
||||
if not player_data["canStartKickVote"]:
|
||||
if pbid in blacklist["kick-vote-disabled"] and current_time < datetime.strptime(blacklist["kick-vote-disabled"][pbid]["till"], "%Y-%m-%d %H:%M:%S"):
|
||||
_ba.disable_kickvote(pbid)
|
||||
|
||||
|
||||
serverdata.clients[pbid]["lastIP"] = ip
|
||||
|
||||
device_id = _ba.get_client_public_device_uuid(clid)
|
||||
|
|
@ -182,7 +186,8 @@ def on_player_join_server(pbid, player_data, ip):
|
|||
device_id = _ba.get_client_device_uuid(clid)
|
||||
serverdata.clients[pbid]["deviceUUID"] = device_id
|
||||
verify_account(pbid, player_data) # checked for spoofed ids
|
||||
logger.log(pbid+" ip: "+serverdata.clients[pbid]["lastIP"]+", Device id: "+device_id)
|
||||
logger.log(
|
||||
f'{pbid} ip: {serverdata.clients[pbid]["lastIP"]} , Device id: {device_id}')
|
||||
_ba.screenmessage(settings["regularWelcomeMsg"] + " " + device_string,
|
||||
color=(0.60, 0.8, 0.6), transient=True,
|
||||
clients=[clid])
|
||||
|
|
@ -201,19 +206,33 @@ def on_player_join_server(pbid, player_data, ip):
|
|||
|
||||
# pdata.add_profile(pbid,d_string,d_string)
|
||||
|
||||
def check_ban(clid, pbid):
|
||||
ip = _ba.get_client_ip(clid)
|
||||
|
||||
device_id = _ba.get_client_public_device_uuid(clid)
|
||||
if(device_id==None):
|
||||
device_id = _ba.get_client_device_uuid(clid)
|
||||
if (ip in blacklist["ban"]['ips'] or device_id in blacklist['ban']['deviceids'] or pbid in blacklist["ban"]["ids"]):
|
||||
_ba.chatmessage('sad ,your account is flagged contact server owner for unban',clients=[clid])
|
||||
logger.log(pbid + " | kicked > reason: Banned account")
|
||||
ba.internal.disconnect_client(clid)
|
||||
def check_ban(ip, device_id, pbid, log=True):
|
||||
current_time = datetime.now()
|
||||
|
||||
if ip in blacklist["ban"]['ips'] and current_time < datetime.strptime(blacklist["ban"]["ips"][ip]["till"], "%Y-%m-%d %H:%M:%S"):
|
||||
msg = f' reason: matched IP | {blacklist["ban"]["ips"][ip]["reason"]} , Till : {blacklist["ban"]["ips"][ip]["till"]}'
|
||||
if log:
|
||||
logger.log(f'{pbid} | kicked > {msg}')
|
||||
return True
|
||||
return msg
|
||||
elif device_id in blacklist["ban"]["deviceids"] and current_time < datetime.strptime(blacklist["ban"]["deviceids"][device_id]["till"], "%Y-%m-%d %H:%M:%S"):
|
||||
msg = f'reason: matched deviceId | {blacklist["ban"]["deviceids"][device_id]["reason"]}, Till : {blacklist["ban"]["deviceids"][device_id]["till"]}'
|
||||
if log:
|
||||
logger.log(
|
||||
f'{pbid} | kicked > {msg}')
|
||||
return True
|
||||
return msg
|
||||
elif pbid in blacklist["ban"]["ids"] and current_time < datetime.strptime(blacklist["ban"]["ids"][pbid]["till"], "%Y-%m-%d %H:%M:%S"):
|
||||
msg = f'reason: matched ID | {blacklist["ban"]["ids"][pbid]["reason"]} , Till : {blacklist["ban"]["ids"][pbid]["till"]}'
|
||||
if log:
|
||||
logger.log(
|
||||
f'{pbid} | kicked > {msg}')
|
||||
return True
|
||||
return msg
|
||||
return False
|
||||
|
||||
|
||||
def verify_account(pb_id, p_data):
|
||||
d_string = ""
|
||||
for ros in ba.internal.get_game_roster():
|
||||
|
|
@ -260,7 +279,7 @@ def get_account_creation_date(pb_id):
|
|||
else:
|
||||
creation_time = account_creation["created"]
|
||||
creation_time = map(str, creation_time)
|
||||
creation_time = datetime.datetime.strptime("/".join(creation_time),
|
||||
creation_time = datetime.strptime("/".join(creation_time),
|
||||
"%Y/%m/%d/%H/%M/%S")
|
||||
# Convert to IST
|
||||
creation_time += datetime.timedelta(hours=5, minutes=30)
|
||||
|
|
@ -285,14 +304,15 @@ def get_device_accounts(pb_id):
|
|||
# ============ file I/O =============
|
||||
|
||||
class LoadProfile(threading.Thread):
|
||||
def __init__(self, pb_id, ip):
|
||||
def __init__(self, pb_id, ip, device_id):
|
||||
threading.Thread.__init__(self)
|
||||
self.pbid = pb_id
|
||||
self.ip = ip
|
||||
self.device_id = device_id
|
||||
|
||||
def run(self):
|
||||
player_data = pdata.get_info(self.pbid)
|
||||
_ba.pushcall(Call(on_player_join_server, self.pbid, player_data, self.ip),
|
||||
_ba.pushcall(Call(on_player_join_server, self.pbid, player_data, self.ip, self.device_id),
|
||||
from_other_thread=True)
|
||||
|
||||
|
||||
|
|
@ -316,7 +336,8 @@ def my_acc_age(pb_id):
|
|||
|
||||
|
||||
def save_age(age, pb_id, display_string):
|
||||
_ba.pushcall(Call(pdata.add_profile,pb_id, display_string,display_string, age), from_other_thread=True)
|
||||
_ba.pushcall(Call(pdata.add_profile, pb_id, display_string,
|
||||
display_string, age), from_other_thread=True)
|
||||
time.sleep(2)
|
||||
thread2 = FetchThread(
|
||||
target=get_device_accounts,
|
||||
|
|
@ -352,8 +373,8 @@ def kick_by_pb_id(pb_id, msg):
|
|||
|
||||
|
||||
def get_account_age(ct):
|
||||
creation_time = datetime.datetime.strptime(ct, "%Y-%m-%d %H:%M:%S")
|
||||
now = datetime.datetime.now()
|
||||
creation_time = datetime.strptime(ct, "%Y-%m-%d %H:%M:%S")
|
||||
now = datetime.now()
|
||||
delta = now - creation_time
|
||||
delta_hours = delta.total_seconds() / (60 * 60)
|
||||
return delta_hours
|
||||
|
|
@ -364,18 +385,18 @@ def reportSpam(id):
|
|||
profiles = pdata.get_profiles()
|
||||
if id in profiles:
|
||||
count = profiles[id]["spamCount"]
|
||||
|
||||
if now - profiles[id]["lastSpam"] < 2 * 24 * 60 * 60:
|
||||
count += 1
|
||||
if count > 3:
|
||||
logger.log(id+" auto banned for spamming")
|
||||
profiles[id]["isBan"] = True
|
||||
# by default ban for 1 day , change here if you want
|
||||
pdata.ban_player(id, 1, "auto ban exceed warn count")
|
||||
else:
|
||||
count = 0
|
||||
|
||||
profiles[id]["spamCount"] = count
|
||||
profiles[id]["lastSpam"] = now
|
||||
pdata.commit_profiles(profiles)
|
||||
|
||||
|
||||
def on_join_request(ip):
|
||||
now = time.time()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue