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; } } }