mirror of
https://github.com/AsgardEternal/DiscordWhitelist.git
synced 2024-12-28 22:29:13 -06:00
feat: implement basic structure of pulling data & whitelisting
This commit is contained in:
parent
5f99751adc
commit
91ecee4c05
118
autowl/Cogs/Group.py
Normal file
118
autowl/Cogs/Group.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import discord
|
||||||
|
from autowl import config
|
||||||
|
from autowl.bot import Bot
|
||||||
|
from discord.ext import commands
|
||||||
|
from discord import app_commands
|
||||||
|
|
||||||
|
|
||||||
|
class Group(commands.Cog, name="group"):
|
||||||
|
def __init__(self, client: Bot):
|
||||||
|
self.client = client
|
||||||
|
|
||||||
|
@app_commands.command()
|
||||||
|
async def add(
|
||||||
|
self,
|
||||||
|
interaction: discord.Interaction,
|
||||||
|
role: discord.Role,
|
||||||
|
):
|
||||||
|
|
||||||
|
if self.client.whitelist.get(role.name):
|
||||||
|
await interaction.response.send_message(
|
||||||
|
f"**{role.name}** is already added, cannot add it again!"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
dropdown = discord.ui.Select(
|
||||||
|
min_values=1,
|
||||||
|
max_values=20,
|
||||||
|
placeholder="Choose group permissions in Squad",
|
||||||
|
options=[
|
||||||
|
discord.SelectOption(
|
||||||
|
label="changemap", description="Allows users to change the map"
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="pause", description="Pause server gameplay"
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="cheat", description="Use server cheat commands"
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="private", description="Password protect server"
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="balance", description="Group Ignores server team balance"
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="chat", description="Admin chat and Server broadcast"
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="kick",
|
||||||
|
description="Allows user to kick players from the server",
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="ban",
|
||||||
|
description="Allows user to ban players from the server",
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="config", description="Change server config"
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="cameraman", description="Admin spectate mode"
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="immune", description="Cannot be kicked / banned"
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="manageserver", description="Shutdown server"
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="featuretest",
|
||||||
|
description="Any features added for testing by dev team",
|
||||||
|
),
|
||||||
|
discord.SelectOption(label="reserve", description="Reserve slot"),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="demos",
|
||||||
|
description="Record Demos on the server side via admin commands",
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="clientdemos",
|
||||||
|
description="Record Demos on the client side via commands or the replay UI.",
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="debug",
|
||||||
|
description="show admin stats command and other debugging info",
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="teamchange", description="No timer limits on team change"
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="forceteamchange",
|
||||||
|
description="Can issue the ForceTeamChange command",
|
||||||
|
),
|
||||||
|
discord.SelectOption(
|
||||||
|
label="canseeadminchat",
|
||||||
|
description="This group can see the admin chat and teamkill/admin-join notifications",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
view = discord.ui.View()
|
||||||
|
view.add_item(dropdown)
|
||||||
|
|
||||||
|
async def perms_handler(interaction: discord.Interaction):
|
||||||
|
perms = "\n - ".join(dropdown.values)
|
||||||
|
dropdown.disabled = True
|
||||||
|
await interaction.response.edit_message(view=view)
|
||||||
|
await interaction.followup.send(
|
||||||
|
f"Adding **{role.name}** to whitelist with permissions:\n - {perms}\n\n"
|
||||||
|
)
|
||||||
|
self.client.whitelist[f"{role.name}"] = config.WhitelistGroup(
|
||||||
|
permissions=dropdown.values, discord_role_id=role.id, members={}
|
||||||
|
)
|
||||||
|
print(self.client.whitelist)
|
||||||
|
|
||||||
|
dropdown.callback = perms_handler
|
||||||
|
|
||||||
|
ctx: commands.Context = await self.client.get_context(interaction)
|
||||||
|
|
||||||
|
|
||||||
|
await ctx.send(view=view)
|
27
autowl/Cogs/Whitelist.py
Normal file
27
autowl/Cogs/Whitelist.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import discord
|
||||||
|
from autowl import config
|
||||||
|
from autowl.bot import Bot
|
||||||
|
from discord.ext import commands
|
||||||
|
from discord import app_commands
|
||||||
|
|
||||||
|
|
||||||
|
class Whitelist(commands.Cog):
|
||||||
|
def __init__(self, client: Bot):
|
||||||
|
self.client = client
|
||||||
|
|
||||||
|
@app_commands.command()
|
||||||
|
async def register(self, interaction: discord.Interaction, steam64: int):
|
||||||
|
ctx: commands.Context = await self.client.get_context(interaction)
|
||||||
|
if not ctx.guild:
|
||||||
|
ctx.reply("This command must be ran within a discord server!")
|
||||||
|
return
|
||||||
|
|
||||||
|
steam64_updated = False
|
||||||
|
for role in ctx.author.roles:
|
||||||
|
for group in self.client.whitelist:
|
||||||
|
if role.id == group.discord_role_id:
|
||||||
|
steam64_updated = True
|
||||||
|
group.members[ctx.author.id] = config.WhitelistMember(ctx.author.name, steam64)
|
||||||
|
|
||||||
|
if steam64_updated:
|
||||||
|
ctx.reply(f"Updated {ctx.author.name}'s whitelist steam64 to {steam64}!")
|
4
autowl/Cogs/__init__.py
Normal file
4
autowl/Cogs/__init__.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from .Whitelist import Whitelist
|
||||||
|
from .Group import Group
|
||||||
|
|
||||||
|
__all__ = ["Whitelist", "Group"]
|
@ -1,19 +0,0 @@
|
|||||||
import os
|
|
||||||
from sys import stderr
|
|
||||||
import discord
|
|
||||||
|
|
||||||
|
|
||||||
# run init stuff inside this function
|
|
||||||
def init():
|
|
||||||
# make sure this prints the discord token
|
|
||||||
# set this up as a runtime environment variable, DO NOT HARDCODE THE TOKEN
|
|
||||||
distoken = os.environ.get("DISCORD_TOKEN")
|
|
||||||
if not distoken:
|
|
||||||
print("Unable to find discord token in environment!", file=stderr)
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
print(f"discord token:{distoken}")
|
|
||||||
|
|
||||||
|
|
||||||
init()
|
|
@ -1,28 +1,65 @@
|
|||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
import autowl.bot as bot
|
||||||
from os import environ
|
from os import environ
|
||||||
from sys import stderr
|
from autowl.config import DiscordClientConfig
|
||||||
from multiprocessing import Process
|
|
||||||
import autowl.fileServer as fileServer
|
log = logging.getLogger(__name__)
|
||||||
import autowl.discordBot as discordBot
|
|
||||||
|
|
||||||
|
class CustomFormat(logging.Formatter):
|
||||||
|
grey = "\x1b[38;20m"
|
||||||
|
yellow = "\x1b[33;20m"
|
||||||
|
red = "\x1b[31;20m"
|
||||||
|
bold_red = "\x1b[31;1m"
|
||||||
|
reset = "\x1b[0m"
|
||||||
|
format = (
|
||||||
|
"[%(asctime)s][%(levelname)s][%(name)s.%(funcName)s:%(lineno)d] %(message)s"
|
||||||
|
)
|
||||||
|
|
||||||
|
FORMATS = {
|
||||||
|
logging.DEBUG: grey + format + reset,
|
||||||
|
logging.INFO: grey + format + reset,
|
||||||
|
logging.WARNING: yellow + format + reset,
|
||||||
|
logging.ERROR: red + format + reset,
|
||||||
|
logging.CRITICAL: bold_red + format + reset,
|
||||||
|
}
|
||||||
|
|
||||||
|
def format(self, record):
|
||||||
|
log_fmt = self.FORMATS.get(record.levelno)
|
||||||
|
formatter = logging.Formatter(log_fmt)
|
||||||
|
return formatter.format(record)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_logging():
|
||||||
|
log_level = environ.get("LOG_LEVEL") or "INFO"
|
||||||
|
|
||||||
|
ch = logging.StreamHandler(stream=sys.stdout)
|
||||||
|
ch.setFormatter(CustomFormat())
|
||||||
|
|
||||||
|
log.setLevel(log_level)
|
||||||
|
discord_log = logging.getLogger("discord")
|
||||||
|
discord_log.setLevel(log_level)
|
||||||
|
discord_http_log = logging.getLogger("discord.http")
|
||||||
|
discord_http_log.setLevel(log_level)
|
||||||
|
|
||||||
|
logging.basicConfig(level=log_level, handlers=[ch])
|
||||||
|
|
||||||
|
|
||||||
# main runtime function
|
|
||||||
def main():
|
def main():
|
||||||
if disToken := environ.get('DISCORD_TOKEN'):
|
setup_logging()
|
||||||
print(f"Received discord token: {disToken}")
|
|
||||||
# Call into main action here, basically launch the bot via import to a lower module
|
if disToken := environ.get("DISCORD_TOKEN"):
|
||||||
|
bot_config = DiscordClientConfig(disToken)
|
||||||
|
try:
|
||||||
|
bot.Bot(bot_config).start_bot()
|
||||||
|
except Exception as e:
|
||||||
|
log.critical(f"Bot exited critically, error: {e}")
|
||||||
|
raise e
|
||||||
else:
|
else:
|
||||||
print("Unable to access DISCORD_TOKEN in environment!", file=stderr)
|
log.error("Unable to access DISCORD_TOKEN in environment!")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
fsproc = Process(target=fileServer.startServer)
|
|
||||||
disbot = Process(target=discordBot.startBot, args=(disToken,))
|
|
||||||
|
|
||||||
fsproc.start()
|
|
||||||
disbot.start()
|
|
||||||
|
|
||||||
fsproc.join()
|
|
||||||
disbot.join()
|
|
||||||
|
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
52
autowl/bot.py
Normal file
52
autowl/bot.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import logging
|
||||||
|
import discord
|
||||||
|
from discord.ext import commands
|
||||||
|
from autowl import config
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Bot(commands.Bot):
|
||||||
|
whitelist = config.Whitelist({}).whitelist
|
||||||
|
|
||||||
|
def __init__(self, config: config.DiscordClientConfig):
|
||||||
|
self.config = config
|
||||||
|
intents = discord.Intents.default()
|
||||||
|
intents.message_content = True
|
||||||
|
intents.members = True
|
||||||
|
super().__init__(
|
||||||
|
command_prefix=commands.when_mentioned_or("&"),
|
||||||
|
intents=intents,
|
||||||
|
help_command=commands.DefaultHelpCommand(dm_help=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
async def on_ready(self):
|
||||||
|
log.info(f"Logged in as '{self.user}' ({self.user.id})")
|
||||||
|
log.info(
|
||||||
|
f"Have access to the following guilds: "
|
||||||
|
f"{', '.join([str(guild.name) + ' (' + str(guild.id) + ')' for guild in self.guilds])}"
|
||||||
|
)
|
||||||
|
|
||||||
|
for guild in self.guilds:
|
||||||
|
self.tree.copy_global_to(guild=guild)
|
||||||
|
await self.tree.sync(guild=guild)
|
||||||
|
log.info(f"Synced guild: {guild.name}")
|
||||||
|
|
||||||
|
await self.tree.sync()
|
||||||
|
|
||||||
|
async def setup_hook(self):
|
||||||
|
log.info("Setting up bot")
|
||||||
|
from autowl import Cogs
|
||||||
|
|
||||||
|
await self.add_cog(Cogs.Whitelist(self))
|
||||||
|
await self.add_cog(Cogs.Group(self))
|
||||||
|
|
||||||
|
def start_bot(self):
|
||||||
|
log.info("Starting discord bot")
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.run(self.config.login_token, log_handler=None)
|
||||||
|
except discord.errors.LoginFailure as e:
|
||||||
|
log.debug(f"Received login failure: {e}")
|
||||||
|
log.error("Failed to login to discord, check your discord token!")
|
||||||
|
raise e
|
34
autowl/config.py
Normal file
34
autowl/config.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DiscordClientConfig:
|
||||||
|
login_token: str
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class WhitelistMember:
|
||||||
|
discord_username: str
|
||||||
|
steam64: int
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class WhitelistGroup:
|
||||||
|
permissions: list[str]
|
||||||
|
discord_role_id: int
|
||||||
|
members: dict[int, WhitelistMember]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Whitelist:
|
||||||
|
whitelist: dict[str, WhitelistGroup]
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
for key in self.whitelist:
|
||||||
|
yield self.whitelist[key]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class PermGroup:
|
||||||
|
group_name: str
|
||||||
|
permissions: list[str]
|
@ -1,105 +0,0 @@
|
|||||||
import discord
|
|
||||||
from sys import stderr
|
|
||||||
|
|
||||||
MY_GUILD = discord.Object(id=1064037361786302475)
|
|
||||||
adminsroleids = [1067044106439761950]
|
|
||||||
generalwl = dict(name='Whitelist', discordid=1067044106439761950, permslist=['reserve'], members=[])
|
|
||||||
masterwllist = [generalwl]
|
|
||||||
|
|
||||||
|
|
||||||
def removewlmember(wllist, userid):
|
|
||||||
memberrmindex = -1
|
|
||||||
for i in range(len(wllist['members'])):
|
|
||||||
if wllist['members'][i]['userid'] == userid:
|
|
||||||
memberrmindex = i
|
|
||||||
if memberrmindex < 0:
|
|
||||||
return
|
|
||||||
wllist['members'].remove(wllist['members'][memberrmindex])
|
|
||||||
|
|
||||||
|
|
||||||
async def updatefile(wllist):
|
|
||||||
with open(f"remoteAdmins/{wllist['name']}", 'w') as file:
|
|
||||||
rawperm = ''
|
|
||||||
for perm in wllist['permslist']:
|
|
||||||
rawperm = f"{rawperm},{perm}"
|
|
||||||
file.write(f"Group={wllist['name']}:{rawperm}\n\n")
|
|
||||||
for wluser in wllist['members']:
|
|
||||||
file.write(f"Admin={wluser['steamid']}:{wllist['name']} // discord:{wluser['username']} ({wluser['userid']})\n")
|
|
||||||
|
|
||||||
|
|
||||||
class WhiteLister(discord.Client):
|
|
||||||
def __init__(self, *, intents: discord.Intents):
|
|
||||||
super().__init__(intents=intents)
|
|
||||||
self.tree = discord.app_commands.CommandTree(self)
|
|
||||||
|
|
||||||
async def on_ready(self):
|
|
||||||
print(f"Logged on as {self.user}")
|
|
||||||
|
|
||||||
async def on_member_update(self, before, after):
|
|
||||||
print(f"user '{after.name} ({after.id})' started member update")
|
|
||||||
rmrolesid = []
|
|
||||||
for befrole in before.roles:
|
|
||||||
rmrolesid.append(befrole.id)
|
|
||||||
for aftrole in after.roles:
|
|
||||||
for befrole in before.roles:
|
|
||||||
if befrole.id == aftrole.id:
|
|
||||||
rmrolesid.remove(aftrole.id)
|
|
||||||
|
|
||||||
for rmroleid in rmrolesid:
|
|
||||||
for wllist in masterwllist:
|
|
||||||
if wllist['discordid'] == rmroleid:
|
|
||||||
removewlmember(wllist, before.id)
|
|
||||||
await updatefile(wllist)
|
|
||||||
|
|
||||||
async def setup_hook(self):
|
|
||||||
self.tree.copy_global_to(guild=MY_GUILD)
|
|
||||||
await self.tree.sync(guild=MY_GUILD)
|
|
||||||
|
|
||||||
|
|
||||||
async def hellofunc(interaction: discord.Interaction, steam64id: str):
|
|
||||||
print(f"user '{interaction.user.name} ({interaction.user.id})' attempting whitelist")
|
|
||||||
hasrole = False
|
|
||||||
for userrole in interaction.user.roles:
|
|
||||||
if userrole.id == WHITELISTID:
|
|
||||||
hasrole = True
|
|
||||||
if not hasrole:
|
|
||||||
print(f"user '{interaction.user.name} ({interaction.user.id})' does not have whitelist role")
|
|
||||||
await interaction.response.send_message(f"ERROR: user does not have whitelist role!")
|
|
||||||
return
|
|
||||||
for wlentry in generalwhitelist:
|
|
||||||
if wlentry[0] == steam64id:
|
|
||||||
print(f"user '{interaction.user.name} ({interaction.user.id})' used an existing steam id")
|
|
||||||
await interaction.response.send_message(f"ERROR: steam64id already exists in whitelist!")
|
|
||||||
return
|
|
||||||
if wlentry[1] == interaction.user.id:
|
|
||||||
print(f"user '{interaction.user.name} ({interaction.user.id})' used an existing discord id")
|
|
||||||
await interaction.response.send_message(f"ERROR: discord user id already exists in whitelist!")
|
|
||||||
return
|
|
||||||
username = interaction.user.name
|
|
||||||
if not (interaction.user.nick is None):
|
|
||||||
username = interaction.user.nick
|
|
||||||
newwlentry = dict(steamid=steam64id, userid=interaction.user.id, username=username)
|
|
||||||
generalwl["members"].append(newwlentry)
|
|
||||||
print(f"user '{interaction.user.name} ({interaction.user.id})' added with steamid '{steam64id}'")
|
|
||||||
await updateFile()
|
|
||||||
await interaction.response.send_message(
|
|
||||||
f'Added {newwlentry[2]} ({newwlentry[1]}) with steamid: {newwlentry[0]}, to glbwhitelist!')
|
|
||||||
|
|
||||||
def startBot(discordtoken):
|
|
||||||
print("starting discord bot")
|
|
||||||
intents = discord.Intents.default()
|
|
||||||
intents.message_content = True
|
|
||||||
intents.members = True
|
|
||||||
|
|
||||||
client = WhiteLister(intents=intents)
|
|
||||||
|
|
||||||
@client.tree.command()
|
|
||||||
async def hello(interaction: discord.Interaction, steam64id: str):
|
|
||||||
await hellofunc(interaction, steam64id)
|
|
||||||
|
|
||||||
try:
|
|
||||||
print("discord bot started!")
|
|
||||||
client.run(discordtoken)
|
|
||||||
except:
|
|
||||||
print("Invalid discord token!", file=stderr)
|
|
||||||
exit(1)
|
|
@ -1,34 +0,0 @@
|
|||||||
import http.server
|
|
||||||
import socketserver
|
|
||||||
from urllib.parse import urlparse
|
|
||||||
from urllib.parse import parse_qs
|
|
||||||
from sys import stderr
|
|
||||||
|
|
||||||
PORT = 8000
|
|
||||||
|
|
||||||
|
|
||||||
class serveRA(http.server.SimpleHTTPRequestHandler):
|
|
||||||
def do_GET(self):
|
|
||||||
self.send_response(200)
|
|
||||||
self.send_header("Content-type", "text")
|
|
||||||
self.end_headers()
|
|
||||||
query = parse_qs(urlparse(self.path).query)
|
|
||||||
if 'serverName' in query:
|
|
||||||
servername = query['serverName'][0]
|
|
||||||
try:
|
|
||||||
file = open(f"remoteAdmins/{servername}.cfg", 'rb')
|
|
||||||
except:
|
|
||||||
print("failed to open file!", file=stderr)
|
|
||||||
return
|
|
||||||
|
|
||||||
self.copyfile(file, self.wfile)
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def startServer():
|
|
||||||
handler = serveRA
|
|
||||||
|
|
||||||
with socketserver.TCPServer(("", PORT), handler) as httpd:
|
|
||||||
print(f"Server started at localhost:{PORT}")
|
|
||||||
httpd.serve_forever()
|
|
||||||
|
|
@ -2,12 +2,11 @@
|
|||||||
"WhiteListGroupName": {
|
"WhiteListGroupName": {
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"discord_role_id": "",
|
"discord_role_id": "",
|
||||||
"members": [
|
"members": {
|
||||||
{
|
"discord_id": {
|
||||||
"discord_id": "",
|
|
||||||
"steam64": "",
|
"steam64": "",
|
||||||
"discord_username": ""
|
"discord_username": ""
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,101 +0,0 @@
|
|||||||
Group=1039155511066636329:
|
|
||||||
Group=Odin:changemap,pause,balance,chat,kick,ban,cameraman,teamchange,forceteamchange,canseeadminchat,reserve,config
|
|
||||||
Group=SrAdmin:changemap,balance,chat,kick,ban,cameraman,teamchange,forceteamchange,canseeadminchat,reserve
|
|
||||||
Group=JrAdmin:balance,chat,kick,ban,teamchange,canseeadminchat,reserve
|
|
||||||
Group=Whitelist:reserve
|
|
||||||
Group=CAS:reserve
|
|
||||||
Group=HC:reserve
|
|
||||||
Group=SLT:reserve
|
|
||||||
Group=BR1:reserve
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// The format for adding admins is:
|
|
||||||
// Admin=<Steam ID #>:<Group Name>
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// Admin=123456:Admin // Adam the admin
|
|
||||||
// Admin=654321:Moderator // Molly the moderator
|
|
||||||
//
|
|
||||||
// Add your own below:
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// === 1039155511066636329 ===
|
|
||||||
|
|
||||||
// === Odin ===
|
|
||||||
Admin=76561197986710399:Odin // Kinsher - Server Administrator
|
|
||||||
Admin=76561199101367413:Odin // Atrocity -
|
|
||||||
Admin=76561198001193856:Odin // Xikky -
|
|
||||||
Admin=76561199028579724:Odin // iiTherRealMcCoy -
|
|
||||||
Admin=76561198153769543:Odin // MaxRecon -
|
|
||||||
Admin=76561198067016254:Odin // SheHulk -
|
|
||||||
Admin=76561198404402665:Odin // Malinoff -
|
|
||||||
Admin=76561198073942737:Odin // Someoneulove -
|
|
||||||
Admin=76561198356666755:Odin // Teggy -
|
|
||||||
Admin=76561198855097026:Odin // SooperGloo -
|
|
||||||
|
|
||||||
// === SrAdmin ===
|
|
||||||
Admin=76561198339174737:SrAdmin // Frizz -
|
|
||||||
Admin=76561198373523022:SrAdmin // Lt_Longsword -
|
|
||||||
Admin=76561199201845769:SrAdmin // Buddy -
|
|
||||||
Admin=76561198015328506:SrAdmin // Ray -
|
|
||||||
Admin=76561198329170534:SrAdmin // Freeman -
|
|
||||||
Admin=76561199018771290:SrAdmin // Omega -
|
|
||||||
Admin=76561198046579272:SrAdmin // Coiffee -
|
|
||||||
Admin=76561198203568744:SrAdmin // Elon -
|
|
||||||
Admin=76561198799111045:SrAdmin // Kin_Seward -
|
|
||||||
Admin=76561198206734757:SrAdmin // RangerSix -
|
|
||||||
Admin=76561199094282718:SrAdmin // Epimetheus -
|
|
||||||
Admin=76561199127559778:SrAdmin // Chemji -
|
|
||||||
Admin=76561198059250541:SrAdmin // Mirage40K -
|
|
||||||
Admin=76561198081576045:SrAdmin // Rabbid_Squirrel -
|
|
||||||
Admin=76561198124658412:SrAdmin // Sweetwater -
|
|
||||||
Admin=76561198107367726:SrAdmin // wolf.rayne -
|
|
||||||
|
|
||||||
// === JrAdmin ===
|
|
||||||
Admin=76561198003130199:JrAdmin // Sexo - Primary Seeder
|
|
||||||
|
|
||||||
// === Whitelist ===
|
|
||||||
Admin=76561198090760895:Whitelist // Treay ~ Sam - For Asgard IT Started 01/09/2023
|
|
||||||
Admin=76561198106004468:Whitelist // Trippy Chivas - devbryanbar@gmail.com
|
|
||||||
Admin=76561198209119887:Whitelist // RIOTYouth1 - aclerc1220@gmail.com
|
|
||||||
Admin=76561198312514319:Whitelist // {ASG} Scarface - logangrimes11@gmail.com
|
|
||||||
Admin=76561198983371735:Whitelist // {ASG} young sloth - logangrimes11@gmail.com
|
|
||||||
Admin=76561198221715432:Whitelist // Skillet - Server Administrator
|
|
||||||
Admin=76561198026192477:Whitelist // LtJamesFox - Nevetsu@hotmail.com
|
|
||||||
Admin=76561198059124010:Whitelist // tcandan88(4skin) - ducati979@aol.com
|
|
||||||
Admin=76561199062085282:Whitelist // Dick Deflator - Granted Whitelist for 3 month's started 12/01/2022/Ends 02/28/2023
|
|
||||||
Admin=76561198059462064:Whitelist // Bagels - adroessler10@gmail.com
|
|
||||||
Admin=76561198119385943:Whitelist // Hypothermiack -
|
|
||||||
Admin=76561199123384670:Whitelist // TapatioTimmy - camdenricketts4@gmail.com
|
|
||||||
Admin=76561199285813056:Whitelist // TheGoochSlooth - justintestorelli@gmail.com
|
|
||||||
Admin=76561197963075020:Whitelist // Subterfuge - jwlind@gmail.com
|
|
||||||
Admin=76561198128034210:Whitelist // Kybar - carbarykyle@gmail.com
|
|
||||||
Admin=76561198049739312:Whitelist // Juggernaut - robledoaustin@yahoo.com
|
|
||||||
Admin=76561197979663830:Whitelist // DamiSupreme - alexdemiane93@gmail.com
|
|
||||||
Admin=76561199241025555:Whitelist // Dang Li Wang - n.hinesly0602@gmail.com
|
|
||||||
Admin=76561199241627472:Whitelist // Jenna Tools - n.hinesly0602@gmail.com
|
|
||||||
Admin=76561199302780874:Whitelist // Mr_poopy_diaper - Attached to (ASG) Kybar (carbarykyle@gmail.com)
|
|
||||||
Admin=76561198801895406:Whitelist // OneBarStatus - jacobadams135@yahoo.com
|
|
||||||
|
|
||||||
// === CAS ===
|
|
||||||
Admin=7656119844551138:CAS // Albertime - CAS
|
|
||||||
Admin=76561198094918611:CAS // JF - CAS
|
|
||||||
Admin=76561198153409985:CAS // Jashy - CAS
|
|
||||||
Admin=76561198150626482:CAS // Oscar - CAS
|
|
||||||
Admin=76561198248146940:CAS // Skay - CAS
|
|
||||||
|
|
||||||
// === HC ===
|
|
||||||
Admin=76561198043032389:HC // Sir Peabody - HC
|
|
||||||
Admin=76561197982328479:HC // Kameron - HC
|
|
||||||
Admin=76561198101099268:HC // Evans - HC
|
|
||||||
Admin=76561198249614886:HC // Brodizle - HC
|
|
||||||
Admin=76561198191984002:HC // Skeebler - HC
|
|
||||||
|
|
||||||
// === SLT ===
|
|
||||||
Admin=76561198149412908:SLT // EnderDevs - SLT
|
|
||||||
Admin=76561198448114730:SLT // JoeBrandonCheated - SLT
|
|
||||||
|
|
||||||
// === BR1 ===
|
|
||||||
Admin=76561199060693600:BR1 // Madtopher - BR1
|
|
||||||
Admin=76561198037486479:BR1 // Dr. Hammerstein - BR1
|
|
||||||
Admin=76561198315718944:BR1 // Bags - BR1
|
|
Loading…
Reference in New Issue
Block a user