using axXez.TS3.Protocol;
using axXez.Utils;
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace axXez.TS3.Bot
{
/// Global bot configuration — loaded from settings/bot.json and writable via environment variables.
public class Settings : ConfigFile
{
// Query connection
/// Hostname or IP of the TeamSpeak server.
[JsonInclude]
public string IP { get; internal set; } = "localhost";
/// ServerQuery port — 10022 for SSH (default) or 10011 for plain TCP.
[JsonInclude]
public int Port { get; internal set; } = 10022;
/// Transport protocol for the ServerQuery connection. SSH is recommended; required for TeamSpeak 6.
[JsonInclude]
[JsonConverter(typeof(JsonStringEnumConverter))]
public QueryTransportType Transport { get; internal set; } = QueryTransportType.SSH;
[JsonInclude]
internal string LoginName { get; set; } = "serveradmin";
[JsonInclude]
internal string Password { get; set; } = null;
/// Virtual server ID to select after connecting.
[JsonInclude]
public int ServerID { get; internal set; } = 1;
/// Seconds of idle time before sending a query-level keep-alive. Set to 0 to disable.
public int KeepAliveInterval { get; set; } = 300;
/// Maximum outgoing ServerQuery commands per second. Controls the fixed-rate send loop slot timing.
public int CommandsPerSecond { get; set; } = 3;
/// Milliseconds to wait for a server response before declaring the connection dead and forcing a reconnect.
public int ResponseTimeout { get; set; } = 30000;
/// Delay in milliseconds before attempting a reconnect after a lost connection.
public int ReconnectDelay { get; set; } = 10000;
/// Whether to automatically disable the server's query flood protection on startup. Not recommended for production — leave this false and raise the server threshold instead.
public bool AutoDisableFloodProtection { get; set; } = false;
// Bot
/// Nickname the bot will use on the server; null keeps the query login's default name.
public string Name { get; set; } = null;
/// Name of the channel the bot will move to on connect; null stays in the default channel.
public string DefaultChannel { get; set; } = null;
/// Interval in milliseconds between channel list refresh polls.
public int ChannelUpdateInterval { get; set; } = 10000;
/// Interval in milliseconds between client list refresh polls.
public int ClientUpdateInterval { get; set; } = 5000;
/// Whether to load and activate plugins on startup.
public bool EnablePlugins { get; set; } = true;
/// Whether to write bot activity to the log output.
public bool EnableLogs { get; set; } = true;
/// Whether to include verbose/debug entries in log output.
public bool VerboseLogs { get; set; } = false;
/// Server group names or client UIDs whose members are treated as admins.
public List Admins { get; set; } = new() { "Server Admin" };
/// Server group names or client UIDs whose members are treated as moderators.
public List Moderators { get; set; } = new();
/// Server group names or client UIDs whose members are treated as regular users.
public List Users { get; set; } = new() { "Normal" };
/// Whether clients not in the guest group are automatically treated as users even if not listed in .
public bool NonGuestsAreUsers { get; set; } = true;
/// Whether clients in the guest group are permitted to interact with the bot.
public bool AllowGuests { get; set; } = false;
/// Full type names of modules to activate on startup.
public List ActiveModules { get; set; } = new();
/// Milliseconds between commands from the same user. Set to 0 or negative to disable.
public int UserCommandCooldown { get; set; } = 500;
internal void ApplyEnvironmentVariables()
{
// ServerConnection settings (TS_)
if (Environment.GetEnvironmentVariable("TS_IP") is string ip)
IP = ip;
if (Environment.GetEnvironmentVariable("TS_PORT") is string port && int.TryParse(port, out int p))
Port = p;
if (Environment.GetEnvironmentVariable("TS_TRANSPORT") is string transport && Enum.TryParse(transport, true, out var tv))
Transport = tv;
if (Environment.GetEnvironmentVariable("TS_LOGIN") is string login)
LoginName = login;
if (Environment.GetEnvironmentVariable("TS_PASSWORD") is string pwd)
Password = pwd;
if (Environment.GetEnvironmentVariable("TS_SERVER_ID") is string sid && int.TryParse(sid, out int s))
ServerID = s;
if (Environment.GetEnvironmentVariable("TS_NAME") is string name)
Name = name;
if (Environment.GetEnvironmentVariable("TS_DEFAULT_CHANNEL") is string channel)
DefaultChannel = channel;
if (Environment.GetEnvironmentVariable("TS_AUTO_DISABLE_FLOOD_PROTECTION") is string adfp && bool.TryParse(adfp, out bool adfpv))
AutoDisableFloodProtection = adfpv;
if (Environment.GetEnvironmentVariable("TS_CHANNEL_UPDATE_INTERVAL") is string cui && int.TryParse(cui, out int cuiv))
ChannelUpdateInterval = cuiv;
if (Environment.GetEnvironmentVariable("TS_CLIENT_UPDATE_INTERVAL") is string clui && int.TryParse(clui, out int cluiv))
ClientUpdateInterval = cluiv;
// QueryClient settings (QUERY_)
if (Environment.GetEnvironmentVariable("QUERY_KEEPALIVE_INTERVAL") is string kai && int.TryParse(kai, out int kaiv))
KeepAliveInterval = kaiv;
if (Environment.GetEnvironmentVariable("QUERY_COMMANDS_PER_SECOND") is string cps && int.TryParse(cps, out int cpsv))
CommandsPerSecond = cpsv;
if (Environment.GetEnvironmentVariable("QUERY_RESPONSE_TIMEOUT") is string rt && int.TryParse(rt, out int rtv))
ResponseTimeout = rtv;
if (Environment.GetEnvironmentVariable("QUERY_RECONNECT_DELAY") is string rd && int.TryParse(rd, out int rdv))
ReconnectDelay = rdv;
// BotContext settings (BOT_)
if (Environment.GetEnvironmentVariable("BOT_ENABLE_LOGS") is string logs && bool.TryParse(logs, out bool logsv))
EnableLogs = logsv;
if (Environment.GetEnvironmentVariable("BOT_VERBOSE_LOGS") is string verbose && bool.TryParse(verbose, out bool verbosev))
VerboseLogs = verbosev;
if (Environment.GetEnvironmentVariable("BOT_ENABLE_PLUGINS") is string plugins && bool.TryParse(plugins, out bool pluginsv))
EnablePlugins = pluginsv;
if (Environment.GetEnvironmentVariable("BOT_ADMINS") is string admins)
foreach (var entry in admins.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
if (!Admins.Contains(entry)) Admins.Add(entry);
if (Environment.GetEnvironmentVariable("BOT_MODERATORS") is string mods)
foreach (var entry in mods.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
if (!Moderators.Contains(entry)) Moderators.Add(entry);
if (Environment.GetEnvironmentVariable("BOT_USERS") is string users)
foreach (var entry in users.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
if (!Users.Contains(entry)) Users.Add(entry);
if (Environment.GetEnvironmentVariable("BOT_NON_GUESTS_ARE_USERS") is string ngu && bool.TryParse(ngu, out bool nguv))
NonGuestsAreUsers = nguv;
if (Environment.GetEnvironmentVariable("BOT_ALLOW_GUESTS") is string ag && bool.TryParse(ag, out bool agv))
AllowGuests = agv;
if (Environment.GetEnvironmentVariable("BOT_ACTIVE_MODULES") is string modules)
foreach (var entry in modules.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
if (!ActiveModules.Contains(entry)) ActiveModules.Add(entry);
if (Environment.GetEnvironmentVariable("BOT_COMMAND_COOLDOWN") is string cd && int.TryParse(cd, out int cdv))
UserCommandCooldown = cdv;
}
}
}