Chat Refactor (#79) [TGSDeploy]

* Chat refactor: Service changes

* Settings migration

* First pass at implementing the commandline

* WIP irc modes

* Wip

* Fix it

* Working

* Fix dickscord

* Some readme updates

* Fixes

* PMs are admin etc

* Compiling

* Final touches

* Version bump to 3.0.86.0
This commit is contained in:
Jordan Brown
2017-06-28 14:18:59 -04:00
committed by GitHub
parent e989d7b356
commit fb432c8fc3
29 changed files with 1385 additions and 887 deletions
+20 -6
View File
@@ -19,7 +19,7 @@ Requires python 2.7/3.6 to be installed for changelog generation
1. Go to the `Repository` Tab and set the remote address and branch of the git you with to track
1. Hit the clone button
1. While waiting go to the BYOND tab and install the BYOND version you wish
1. You may also configure an IRC or discord bot for the server on the chat tab
1. You may also configure an IRC and/or discord bot for the server on the chat tab
1. Once the clone is complete you may set up a committer identity, user name, and password on the `Repository` tab for pushing changelog updates
1. Go to the `Server` tab and click the `Initialize Game Folders` button
1. Optionally change the `Project Path` Setting from tgstation to wherever the dme/dmb pair are in your repository
@@ -31,20 +31,34 @@ This process is identical to the above steps in command line mode. You can alway
1. Launch TGCommandLine.exe (running with no parameters puts you in interactive mode)
1. `config move-server D:\tgstation`
1. `repo setup https://github.com/tgstation/tgstation master`
1. `byond update 511.1382`
1. `chat set-provider irc`
1. `byond update 511.1385`
1. `irc nick TGS3Test`
1. `irc set-auth-mode channel-mode`
1. `irc set-auth-level %`
1. `irc setup-auth NickServ "id hunter2"` Yes this is the real password, please use it only for testing
1. `chat enable`
1. `irc join coderbus dev`
1. `irc join devbus dev`
1. `irc join adminbus admin`
1. `irc join adminbus wd`
1. `irc join tgstation13 game`
1. `irc enable`
1. `discord set-token Rjfa93jlksjfj934jlkjasf8a08wfl.asdjfj08e44` See https://discordapp.com/developers/docs/topics/oauth2#bots
1. `discord set-auth-mode role-id`
1. `discord addmin 192837419273409` See how to get a role id: https://www.reddit.com/r/discordapp/comments/5bezg2/role_id/. Note that if you `discord set-auth-mode user-id` you'll need to use user ids (Enable developer mode, right click user, `Copy ID`)
1. `discord join 12341234453235 dev` This is a channel id (Enable developer mode, right click channel, `Copy ID`)
1. `discord join 34563456344245 dev`
1. `discord join 23452362574456 admin`
1. `discord join 23452362574456 wd`
1. `discord join 53457345736788 game`
1. `discord enable`
1. `repo set-name tgstation-server` These two lines specify the changelog's committer identity. They are not mirrored in the GUI
1. `repo set-email tgstation-server@tgstation13.org`
1. `repo set-credentials` And follow the prompts
1. `dm project-name tgstation`
1. `repo python-path C:\Python27`
1. `dd autostart on`
1. Use `repo status` To check the clone job status
1. `repo status` To check the clone job status
1. `dm initialize --wait`
1. `dm compile --wait`
1. `dd start`
## Updating
+407 -195
View File
@@ -4,78 +4,30 @@ using TGServiceInterface;
namespace TGCommandLine
{
class ChatCommand : RootCommand
{
public ChatCommand()
{
Keyword = "chat";
Children = new Command[] { new ChatAnnounceCommand(), new ChatStatusCommand(), new ChatSetAdminChannelCommand(), new ChatEnableCommand(), new ChatDisableCommand(), new ChatReconnectCommand(), new ChatListAdminsCommand(), new ChatAddminCommand(), new ChatDeadminCommand(), new ChatSetProviderCommand(), new ChatJoinCommand(), new ChatPartCommand() };
}
protected override string GetHelpText()
{
return "Manages general chat settings";
}
}
class ChatSetProviderCommand : Command {
public ChatSetProviderCommand()
{
Keyword = "set-provider";
RequiredParameters = 1;
}
protected override string GetHelpText()
{
return "Set the chat provider";
}
protected override string GetArgumentString()
{
return "<irc|discord> [if discord, add the bot token]";
}
public override ExitCode Run(IList<string> parameters)
{
var Chat = Server.GetComponent<ITGChat>();
string res;
switch (parameters[0].ToLower())
{
case "irc":
res = Chat.SetProviderInfo(new TGIRCSetupInfo());
break;
case "discord":
if(parameters.Count < 2)
{
Console.WriteLine("Missing discord bot token!");
return ExitCode.BadCommand;
}
res = Chat.SetProviderInfo(new TGDiscordSetupInfo() { BotToken = parameters[1] });
break;
default:
Console.WriteLine("Invalid provider!");
return ExitCode.BadCommand;
}
Console.WriteLine(res ?? "Success!");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
}
class IRCCommand : RootCommand
{
public IRCCommand()
{
Keyword = "irc";
Children = new Command[] { new IRCNickCommand(), new IRCAuthCommand(), new IRCDisableAuthCommand(), new IRCServerCommand() };
}
public override ExitCode Run(IList<string> parameters)
{
if (Server.GetComponent<ITGChat>().ProviderInfo().Provider != TGChatProvider.IRC)
{
Console.WriteLine("The current provider is not IRC. Please switch providers first!");
return ExitCode.ServerError;
}
return base.Run(parameters);
Children = new Command[] { new IRCNickCommand(), new IRCAuthCommand(), new IRCDisableAuthCommand(), new IRCServerCommand(), new ChatJoinCommand(TGChatProvider.IRC), new ChatPartCommand(TGChatProvider.IRC), new ChatListAdminsCommand(TGChatProvider.IRC), new ChatReconnectCommand(TGChatProvider.IRC), new ChatAddminCommand(TGChatProvider.IRC), new ChatDeadminCommand(TGChatProvider.IRC), new ChatEnableCommand(TGChatProvider.IRC), new ChatDisableCommand(TGChatProvider.IRC), new ChatStatusCommand(TGChatProvider.IRC), new IRCAuthModeCommand(), new IRCAuthLevelCommand() };
}
protected override string GetHelpText()
{
return "Manages the IRC bot";
}
}
class DiscordCommand : RootCommand
{
public DiscordCommand()
{
Keyword = "discord";
Children = new Command[] { new DiscordSetTokenCommand(), new ChatJoinCommand(TGChatProvider.Discord), new ChatPartCommand(TGChatProvider.Discord), new ChatListAdminsCommand(TGChatProvider.Discord), new ChatReconnectCommand(TGChatProvider.Discord), new ChatAddminCommand(TGChatProvider.Discord), new ChatDeadminCommand(TGChatProvider.Discord), new ChatEnableCommand(TGChatProvider.Discord), new ChatDisableCommand(TGChatProvider.Discord), new ChatStatusCommand(TGChatProvider.Discord) , new DiscordAuthModeCommand() };
}
protected override string GetHelpText()
{
return "Manages the Discord bot";
}
}
class IRCNickCommand : Command
{
public IRCNickCommand()
@@ -96,7 +48,7 @@ namespace TGCommandLine
public override ExitCode Run(IList<string> parameters)
{
var Chat = Server.GetComponent<ITGChat>();
Chat.SetProviderInfo(new TGIRCSetupInfo(Chat.ProviderInfo())
Chat.SetProviderInfo(new TGIRCSetupInfo(Chat.ProviderInfos()[(int)TGChatProvider.IRC])
{
Nickname = parameters[0],
});
@@ -106,25 +58,48 @@ namespace TGCommandLine
class ChatJoinCommand : Command
{
public ChatJoinCommand()
readonly int providerIndex;
public ChatJoinCommand(TGChatProvider pI)
{
Keyword = "join";
RequiredParameters = 1;
RequiredParameters = 2;
providerIndex = (int)pI;
}
protected override string GetArgumentString()
{
return "<channel>";
return "<channel> <dev|wd|game|admin>";
}
protected override string GetHelpText()
{
return "Joins a channel for listening and broadcasting";
return "Joins a channel for listening and broadcasting of the specified message type (Developer, Watchdog, Game, Admin)";
}
public override ExitCode Run(IList<string> parameters)
{
var IRC = Server.GetComponent<ITGChat>();
var channels = IRC.Channels();
var info = IRC.ProviderInfos()[providerIndex];
IList<string> channels;
switch (parameters[1].ToLower())
{
case "dev":
channels = info.DevChannels;
break;
case "wd":
channels = info.WatchdogChannels;
break;
case "game":
channels = info.GameChannels;
break;
case "admin":
channels = info.AdminChannels;
break;
default:
Console.WriteLine("Invalid parameter: " + parameters[1]);
return ExitCode.BadCommand;
}
var lowerParam = parameters[0].ToLower();
foreach (var I in channels)
{
@@ -134,74 +109,97 @@ namespace TGCommandLine
return ExitCode.BadCommand;
}
}
Array.Resize(ref channels, channels.Length + 1);
channels[channels.Length - 1] = parameters[0];
IRC.SetChannels(channels, null);
channels.Add(parameters[0]);
switch (parameters[1].ToLower())
{
case "dev":
info.DevChannels = channels;
break;
case "wd":
info.WatchdogChannels = channels;
break;
case "game":
info.GameChannels = channels;
break;
case "admin":
info.AdminChannels = channels;
break;
}
var res = IRC.SetProviderInfo(info);
if(res != null)
{
Console.WriteLine(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
class ChatPartCommand : Command
{
public ChatPartCommand()
readonly int providerIndex;
public ChatPartCommand(TGChatProvider pI)
{
Keyword = "part";
RequiredParameters = 1;
RequiredParameters = 2;
providerIndex = (int)pI;
}
protected override string GetArgumentString()
{
return "<channel>";
return "<channel> <dev|wd|game|admin>";
}
protected override string GetHelpText()
{
return "Stops listening and broadcasting on a channel";
return "Stops listening and broadcasting on a channel for the specified message type (Developer, Watchdog, Game, Admin)";
}
public override ExitCode Run(IList<string> parameters)
{
var IRC = Server.GetComponent<ITGChat>();
var channels = IRC.Channels();
var lowerParam = parameters[0].ToLower();
if (lowerParam[0] != '#')
lowerParam = "#" + lowerParam;
var new_channels = new List<string>();
foreach (var I in channels)
{
if (I.ToLower() == lowerParam)
continue;
new_channels.Add(I);
}
if (new_channels.Count == 0)
{
Console.WriteLine("Error: Cannot part from the last channel!");
return ExitCode.BadCommand;
}
IRC.SetChannels(new_channels.ToArray(), null);
return ExitCode.Normal;
}
}
class ChatAnnounceCommand : Command
{
public ChatAnnounceCommand()
{
Keyword = "announce";
RequiredParameters = 1;
}
protected override string GetArgumentString()
{
return "<message>";
}
protected override string GetHelpText()
{
return "Sends a message to all connected channels";
}
var info = IRC.ProviderInfos()[providerIndex];
IList<string> channels;
public override ExitCode Run(IList<string> parameters)
{
var res = Server.GetComponent<ITGChat>().SendMessage("SCP: " + parameters[0]);
switch (parameters[1].ToLower())
{
case "dev":
channels = info.DevChannels;
break;
case "wd":
channels = info.WatchdogChannels;
break;
case "game":
channels = info.GameChannels;
break;
case "admin":
channels = info.AdminChannels;
break;
default:
Console.WriteLine("Invalid parameter: " + parameters[1]);
return ExitCode.BadCommand;
}
var lowerParam = parameters[0].ToLower();
if ((TGChatProvider)providerIndex == TGChatProvider.IRC && lowerParam[0] != '#')
lowerParam = "#" + lowerParam;
channels.Remove(lowerParam);
switch (parameters[1].ToLower())
{
case "dev":
info.DevChannels = channels;
break;
case "wd":
info.WatchdogChannels = channels;
break;
case "game":
info.GameChannels = channels;
break;
case "admin":
info.AdminChannels = channels;
break;
}
var res = IRC.SetProviderInfo(info);
if (res != null)
{
Console.WriteLine("Error: " + res);
Console.WriteLine(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
@@ -209,9 +207,11 @@ namespace TGCommandLine
}
class ChatListAdminsCommand : Command
{
public ChatListAdminsCommand()
readonly int providerIndex;
public ChatListAdminsCommand(TGChatProvider pI)
{
Keyword = "list-admins";
providerIndex = (int)pI;
}
protected override string GetHelpText()
@@ -221,17 +221,56 @@ namespace TGCommandLine
public override ExitCode Run(IList<string> parameters)
{
var res = Server.GetComponent<ITGChat>().ListAdmins();
foreach (var I in res)
Console.WriteLine(I);
var info = Server.GetComponent<ITGChat>().ProviderInfos()[providerIndex];
string authType;
switch ((TGChatProvider)providerIndex)
{
case TGChatProvider.IRC:
if (info.AdminsAreSpecial)
authType = "Mode:";
else
authType = "Nicknames:";
break;
case TGChatProvider.Discord:
if (info.AdminsAreSpecial)
authType = "Role IDs:";
else
authType = "User IDs:";
break;
default:
Console.WriteLine(String.Format("Invalid provider: {0}!", providerIndex));
return ExitCode.ServerError;
}
Console.WriteLine("Authorized " + authType);
if (info.AdminsAreSpecial && (TGChatProvider)providerIndex == TGChatProvider.IRC)
switch(new TGIRCSetupInfo(info).AuthLevel)
{
case IRCMode.Voice:
Console.WriteLine("+");
break;
case IRCMode.Halfop:
Console.WriteLine("%");
break;
case IRCMode.Op:
Console.WriteLine("@");
break;
case IRCMode.Owner:
Console.WriteLine("~");
break;
}
else
foreach (var I in info.AdminList)
Console.WriteLine(I);
return ExitCode.Normal;
}
}
class ChatReconnectCommand : Command
{
public ChatReconnectCommand()
readonly TGChatProvider providerIndex;
public ChatReconnectCommand(TGChatProvider pI)
{
Keyword = "reconnect";
providerIndex = pI;
}
protected override string GetHelpText()
@@ -241,7 +280,7 @@ namespace TGCommandLine
public override ExitCode Run(IList<string> parameters)
{
var res = Server.GetComponent<ITGChat>().Reconnect();
var res = Server.GetComponent<ITGChat>().Reconnect(providerIndex);
if (res != null)
{
Console.WriteLine("Error: " + res);
@@ -252,68 +291,221 @@ namespace TGCommandLine
}
class ChatAddminCommand : Command
{
public ChatAddminCommand()
readonly int providerIndex;
public ChatAddminCommand(TGChatProvider pI)
{
Keyword = "addmin";
RequiredParameters = 1;
providerIndex = (int)pI;
}
protected override string GetArgumentString()
{
return "[nick]";
}
protected override string GetHelpText()
{
return "Add a user which can use restricted commands in the admin channel";
return "Add a user which can use restricted commands in the admin channels";
}
public override ExitCode Run(IList<string> parameters)
{
var IRC = Server.GetComponent<ITGChat>();
var mins = new List<string>(IRC.ListAdmins());
var newmin = parameters[0];
var info = IRC.ProviderInfos()[providerIndex];
var newmin = parameters[0].ToLower();
foreach (var I in mins)
if (I.ToLower() == newmin.ToLower())
{
Console.WriteLine(newmin + " is already an admin!");
return ExitCode.Normal;
}
if (info.AdminsAreSpecial && (TGChatProvider)providerIndex == TGChatProvider.IRC)
{
Console.WriteLine("Invalid auth mode for this command!");
return ExitCode.BadCommand;
}
mins.Add(newmin);
IRC.SetAdmins(mins.ToArray());
if (info.AdminList.Contains(newmin))
{
Console.WriteLine(parameters[0] + " is already an admin!");
return ExitCode.BadCommand;
}
var al = info.AdminList;
al.Add(newmin);
info.AdminList = al;
var res = IRC.SetProviderInfo(info);
if (res != null)
{
Console.WriteLine(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
class IRCAuthModeCommand : Command
{
public IRCAuthModeCommand()
{
Keyword = "set-auth-mode";
RequiredParameters = 1;
}
protected override string GetArgumentString()
{
return "<channel-mode|nickname>";
}
protected override string GetHelpText()
{
return "Switch between admin command authorization via user channel mode or nicknames";
}
public override ExitCode Run(IList<string> parameters)
{
var IRC = Server.GetComponent<ITGChat>();
var info = IRC.ProviderInfos()[(int)TGChatProvider.IRC];
var lowerparam = parameters[0].ToLower();
if (lowerparam == "channel-mode")
info.AdminsAreSpecial = true;
else if (lowerparam == "nickname")
info.AdminsAreSpecial = false;
else
{
Console.WriteLine("Invalid parameter: " + parameters[0]);
return ExitCode.BadCommand;
}
var res = IRC.SetProviderInfo(info);
if (res != null)
{
Console.WriteLine(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
class DiscordAuthModeCommand : Command
{
public DiscordAuthModeCommand()
{
Keyword = "set-auth-mode";
RequiredParameters = 1;
}
protected override string GetArgumentString()
{
return "<role-id|user-id>";
}
protected override string GetHelpText()
{
return "Switch between admin command authorization via user roles or individual users";
}
public override ExitCode Run(IList<string> parameters)
{
var IRC = Server.GetComponent<ITGChat>();
var info = IRC.ProviderInfos()[(int)TGChatProvider.Discord];
var lowerparam = parameters[0].ToLower();
if (lowerparam == "role-id")
info.AdminsAreSpecial = true;
else if (lowerparam == "user-id")
info.AdminsAreSpecial = false;
else
{
Console.WriteLine("Invalid parameter: " + parameters[0]);
return ExitCode.BadCommand;
}
var res = IRC.SetProviderInfo(info);
if (res != null)
{
Console.WriteLine(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
class IRCAuthLevelCommand : Command
{
public IRCAuthLevelCommand()
{
Keyword = "set-auth-level";
RequiredParameters = 1;
}
protected override string GetArgumentString()
{
return "<+|%|@|~>";
}
protected override string GetHelpText()
{
return "Set the required channel mode for users to use admin commands";
}
public override ExitCode Run(IList<string> parameters)
{
var IRC = Server.GetComponent<ITGChat>();
var info = new TGIRCSetupInfo(IRC.ProviderInfos()[(int)TGChatProvider.IRC]);
switch (parameters[0])
{
case "+":
info.AuthLevel = IRCMode.Voice;
break;
case "%":
info.AuthLevel = IRCMode.Halfop;
break;
case "@":
info.AuthLevel = IRCMode.Op;
break;
case "~":
info.AuthLevel = IRCMode.Owner;
break;
default:
Console.WriteLine("Invalid parameter: " + parameters[0]);
return ExitCode.BadCommand;
}
var res = IRC.SetProviderInfo(info);
if (res != null)
{
Console.WriteLine(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
class ChatDeadminCommand : Command
{
public ChatDeadminCommand()
readonly int providerIndex;
public ChatDeadminCommand(TGChatProvider pI)
{
Keyword = "deadmin";
RequiredParameters = 1;
providerIndex = (int)pI;
}
protected override string GetArgumentString()
{
return "[nick]";
return "<nick>";
}
protected override string GetHelpText()
{
return "Remove a user which can use restricted commands in the admin channel";
return "Remove a user which can use restricted commands in the admin channels";
}
public override ExitCode Run(IList<string> parameters)
{
var IRC = Server.GetComponent<ITGChat>();
var mins = new List<string>(IRC.ListAdmins());
var deadmin = parameters[0];
var info = IRC.ProviderInfos()[providerIndex];
var newmin = parameters[0].ToLower();
if (info.AdminsAreSpecial && (TGChatProvider)providerIndex == TGChatProvider.IRC)
{
Console.WriteLine("Invalid auth mode for this command!");
return ExitCode.BadCommand;
}
if (!info.AdminList.Contains(newmin))
{
Console.WriteLine(parameters[0] + " is not an admin!");
return ExitCode.BadCommand;
}
foreach (var I in mins)
if (I.ToLower() == deadmin.ToLower())
{
mins.Remove(I);
IRC.SetAdmins(mins.ToArray());
return ExitCode.Normal;
}
Console.WriteLine(deadmin + " is not an admin!");
var al = info.AdminList;
al.Remove(newmin);
info.AdminList = al;
var res = IRC.SetProviderInfo(info);
if (res != null)
{
Console.WriteLine(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
@@ -337,7 +529,7 @@ namespace TGCommandLine
public override ExitCode Run(IList<string> parameters)
{
var IRC = Server.GetComponent<ITGChat>();
IRC.SetProviderInfo(new TGIRCSetupInfo(IRC.ProviderInfo())
IRC.SetProviderInfo(new TGIRCSetupInfo(IRC.ProviderInfos()[(int)TGChatProvider.IRC])
{
AuthTarget = parameters[0],
AuthMessage = parameters[1]
@@ -359,7 +551,7 @@ namespace TGCommandLine
public override ExitCode Run(IList<string> parameters)
{
var IRC = Server.GetComponent<ITGChat>();
IRC.SetProviderInfo(new TGIRCSetupInfo(IRC.ProviderInfo())
IRC.SetProviderInfo(new TGIRCSetupInfo(IRC.ProviderInfos()[(int)TGChatProvider.IRC])
{
AuthTarget = null,
AuthMessage = null,
@@ -370,9 +562,11 @@ namespace TGCommandLine
class ChatStatusCommand : Command
{
public ChatStatusCommand()
readonly int providerIndex;
public ChatStatusCommand(TGChatProvider pI)
{
Keyword = "status";
providerIndex = (int)pI;
}
protected override string GetHelpText()
{
@@ -381,56 +575,33 @@ namespace TGCommandLine
public override ExitCode Run(IList<string> parameters)
{
var IRC = Server.GetComponent<ITGChat>();
Console.WriteLine("Currently configured broadcast channels:");
Console.WriteLine("\tAdmin Channel: " + IRC.AdminChannel());
foreach (var I in IRC.Channels())
var info = IRC.ProviderInfos()[providerIndex];
Console.WriteLine("Currently configured channels:");
Console.WriteLine("Admin:");
foreach (var I in info.AdminChannels)
Console.WriteLine("\t" + I);
string provider;
switch (IRC.ProviderInfo().Provider)
{
case TGChatProvider.Discord:
provider = "Discord";
break;
case TGChatProvider.IRC:
provider = "IRC";
break;
default:
provider = "Unknown";
break;
}
Console.WriteLine("Provider: " + provider);
Console.WriteLine("Chat bot is: " + (!IRC.Enabled() ? "Disabled" : IRC.Connected() ? "Connected" : "Disconnected"));
return ExitCode.Normal;
}
}
class ChatSetAdminChannelCommand : Command
{
public ChatSetAdminChannelCommand()
{
Keyword = "set-admin-channel";
RequiredParameters = 1;
}
protected override string GetArgumentString()
{
return "<channel>";
}
protected override string GetHelpText()
{
return "Sets the admin chat channel";
}
public override ExitCode Run(IList<string> parameters)
{
Server.GetComponent<ITGChat>().SetChannels(null, parameters[0]);
Console.WriteLine("Watchdog:");
foreach (var I in info.WatchdogChannels)
Console.WriteLine("\t" + I);
Console.WriteLine("Game:");
foreach (var I in info.GameChannels)
Console.WriteLine("\t" + I);
Console.WriteLine("Developer:");
foreach (var I in info.DevChannels)
Console.WriteLine("\t" + I);
Console.WriteLine("Chat bot is: " + (!info.Enabled ? "Disabled" : IRC.Connected(info.Provider) ? "Connected" : "Disconnected"));
return ExitCode.Normal;
}
}
class ChatEnableCommand : Command
{
public ChatEnableCommand()
readonly int providerIndex;
public ChatEnableCommand(TGChatProvider pI)
{
Keyword = "enable";
providerIndex = (int)pI;
}
protected override string GetHelpText()
{
return "Enables the chat bot";
@@ -438,17 +609,27 @@ namespace TGCommandLine
public override ExitCode Run(IList<string> parameters)
{
Server.GetComponent<ITGChat>().SetEnabled(true);
var Chat = Server.GetComponent<ITGChat>();
var info = Chat.ProviderInfos()[providerIndex];
info.Enabled = true;
var res = Chat.SetProviderInfo(info);
if (res != null)
{
Console.WriteLine(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
class ChatDisableCommand : Command
{
public ChatDisableCommand()
readonly int providerIndex;
public ChatDisableCommand(TGChatProvider pI)
{
Keyword = "disable";
providerIndex = (int)pI;
}
protected override string GetHelpText()
{
return "Disables the chat bot";
@@ -456,7 +637,15 @@ namespace TGCommandLine
public override ExitCode Run(IList<string> parameters)
{
Server.GetComponent<ITGChat>().SetEnabled(true);
var Chat = Server.GetComponent<ITGChat>();
var info = Chat.ProviderInfos()[providerIndex];
info.Enabled = false;
var res = Chat.SetProviderInfo(info);
if (res != null)
{
Console.WriteLine(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
@@ -486,7 +675,7 @@ namespace TGCommandLine
return ExitCode.BadCommand;
}
var Chat = Server.GetComponent<ITGChat>();
var PI = new TGIRCSetupInfo(Chat.ProviderInfo())
var PI = new TGIRCSetupInfo(Chat.ProviderInfos()[(int)TGChatProvider.IRC])
{
URL = splits[0]
};
@@ -504,6 +693,29 @@ namespace TGCommandLine
Console.WriteLine(res ?? "Success");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
}
class DiscordSetTokenCommand : Command
{
public DiscordSetTokenCommand()
{
Keyword = "set-token";
RequiredParameters = 1;
}
protected override string GetArgumentString()
{
return "<bot-token>";
}
protected override string GetHelpText()
{
return "Sets the discord API bot token";
}
public override ExitCode Run(IList<string> parameters)
{
var Chat = Server.GetComponent<ITGChat>();
var res = Chat.SetProviderInfo(new TGDiscordSetupInfo(Chat.ProviderInfos()[(int)TGChatProvider.Discord]) { BotToken = parameters[0] });
Console.WriteLine(res ?? "Success");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
}
}
+2 -2
View File
@@ -22,5 +22,5 @@ using System.Runtime.InteropServices;
// Build Number
// Revision
//
[assembly: AssemblyVersion("3.0.85.4")]
[assembly: AssemblyFileVersion("3.0.85.4")]
[assembly: AssemblyVersion("3.0.86.0")]
[assembly: AssemblyFileVersion("3.0.86.0")]
+1 -1
View File
@@ -15,7 +15,7 @@ namespace TGCommandLine
public RootCommand()
{
if (IsRealRoot()) //stack overflows
Children = new Command[] { new UpdateCommand(), new TestmergeCommand(), new IRCCommand(), new RepoCommand(), new BYONDCommand(), new DMCommand(), new DDCommand(), new ConfigCommand(), new ChatCommand() };
Children = new Command[] { new UpdateCommand(), new TestmergeCommand(), new RepoCommand(), new BYONDCommand(), new DMCommand(), new DDCommand(), new ConfigCommand(), new IRCCommand(), new DiscordCommand() };
}
public override ExitCode Run(IList<string> parameters)
{
+3
View File
@@ -23,6 +23,9 @@
<setting name="UpgradeRequired" serializeAs="String">
<value>True</value>
</setting>
<setting name="LastChatProvider" serializeAs="String">
<value>0</value>
</setting>
</TGControlPanel.Properties.Settings>
<TGControlPanel.Properties.Settings1>
<setting name="LastPageIndex" serializeAs="String">
+90 -42
View File
@@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using TGServiceInterface;
@@ -10,16 +7,22 @@ namespace TGControlPanel
{
partial class Main
{
TGChatProvider modifyingProvider;
bool updatingChat = false;
TGChatProvider ModifyingProvider
{
get { return (TGChatProvider)Properties.Settings.Default.LastChatProvider; }
set { Properties.Settings.Default.LastChatProvider = (int)value; }
}
void LoadChatPage()
{
updatingChat = true;
var Chat = Server.GetComponent<ITGChat>();
var PI = Chat.ProviderInfo();
modifyingProvider = PI.Provider;
switch (modifyingProvider)
var PI = Chat.ProviderInfos()[(int)ModifyingProvider];
ChatAdminsTextBox.Visible = true;
IRCModesComboBox.Visible = false;
switch (ModifyingProvider)
{
case TGChatProvider.Discord:
var DPI = new TGDiscordSetupInfo(PI);
@@ -34,6 +37,11 @@ namespace TGControlPanel
ChatPortTitle.Visible = false;
ChatNicknameText.Visible = false;
ChatNicknameTitle.Visible = false;
ChatAdminsTitle.Text = String.Format("Admin {0} IDs:", DPI.AdminsAreSpecial ? "Role" : "User");
ChannelsTitle.Text = "Broadcast/Listening Channel IDs:";
AdminModeNormal.Text = "User IDs";
AdminModeSpecial.Text = "Role IDs";
break;
case TGChatProvider.IRC:
var IRC = new TGIRCSetupInfo(PI);
@@ -53,36 +61,49 @@ namespace TGControlPanel
ChatNicknameText.Visible = true;
ChatNicknameTitle.Visible = true;
ChatNicknameText.Text = IRC.Nickname;
ChatAdminsTitle.Text = String.Format("Admin {0}:", IRC.AdminsAreSpecial ? "Req Mode" : "Nicknames");
ChannelsTitle.Text = "Broadcast/Listening Channels:";
AdminModeNormal.Text = "Nicknames";
AdminModeSpecial.Text = "Channel Mode";
if (IRC.AdminsAreSpecial)
{
ChatAdminsTextBox.Visible = false;
IRCModesComboBox.Visible = true;
IRCModesComboBox.SelectedIndex = (int)IRC.AuthLevel;
}
break;
default:
MessageBox.Show("This is a bug, I'll try and recover. Provider was " + modifyingProvider.ToString());
MessageBox.Show(Chat.SetProviderInfo(new TGIRCSetupInfo()) ?? "Success!");
Properties.Settings.Default.LastChatProvider = (int)TGChatProvider.IRC;
LoadChatPage();
return;
}
var Enabled = Chat.Enabled();
ChatEnabledCheckbox.Checked = Enabled;
if (!Enabled)
AdminModeNormal.Checked = !PI.AdminsAreSpecial;
AdminModeSpecial.Checked = PI.AdminsAreSpecial;
ChatEnabledCheckbox.Checked = PI.Enabled;
if (!PI.Enabled)
ChatStatusLabel.Text = "Disabled";
else if (Chat.Connected())
else if (Chat.Connected(ModifyingProvider))
ChatStatusLabel.Text = "Connected";
else
ChatStatusLabel.Text = "Disconnected";
ChatReconnectButton.Enabled = Enabled;
ChatReconnectButton.Enabled = PI.Enabled;
AdminChannelText.Text = Chat.AdminChannel();
ChatAdminsTextBox.Text = "";
foreach (var I in Chat.ListAdmins())
ChatAdminsTextBox.Text += I + "\r\n";
ChatChannelsTextBox.Text = "";
foreach (var I in Chat.Channels())
ChatChannelsTextBox.Text += I + "\r\n";
AssignListToTextbox(PI.AdminList, ChatAdminsTextBox);
AssignListToTextbox(PI.WatchdogChannels, WDChannelsTextbox);
AssignListToTextbox(PI.AdminChannels, AdminChannelsTextbox);
AssignListToTextbox(PI.DevChannels, DevChannelsTextbox);
AssignListToTextbox(PI.GameChannels, GameChannelsTextbox);
updatingChat = false;
}
static void AssignListToTextbox(IList<string> a, TextBox b)
{
b.Text = "";
foreach (var I in a)
b.Text += I + Environment.NewLine;
}
private void ChatRefreshButton_Click(object sender, EventArgs e)
{
LoadChatPage();
@@ -90,7 +111,7 @@ namespace TGControlPanel
private void ChatReconnectButton_Click(object sender, EventArgs e)
{
Server.GetComponent<ITGChat>().Reconnect();
Server.GetComponent<ITGChat>().Reconnect(ModifyingProvider);
LoadChatPage();
}
@@ -112,9 +133,7 @@ namespace TGControlPanel
{
if (!updatingChat && DiscordProviderSwitch.Checked)
{
var res = Server.GetComponent<ITGChat>().SetProviderInfo(new TGDiscordSetupInfo());
if (res != null)
MessageBox.Show(res);
ModifyingProvider = TGChatProvider.Discord;
LoadChatPage();
}
}
@@ -123,44 +142,73 @@ namespace TGControlPanel
{
if (!updatingChat && IRCProviderSwitch.Checked)
{
var res = Server.GetComponent<ITGChat>().SetProviderInfo(new TGIRCSetupInfo());
if (res != null)
MessageBox.Show(res);
ModifyingProvider = TGChatProvider.IRC;
LoadChatPage();
}
}
void SetAdminsAreSpecial(bool value)
{
var Chat = Server.GetComponent<ITGChat>();
var PI = Chat.ProviderInfos()[(int)ModifyingProvider];
PI.AdminsAreSpecial = value;
var res = Chat.SetProviderInfo(PI);
if (res != null)
MessageBox.Show(res);
LoadChatPage();
}
private void AdminModeNormal_CheckedChanged(object sender, EventArgs e)
{
if (!updatingChat && AdminModeNormal.Checked)
SetAdminsAreSpecial(false);
}
private void AdminModeSpecial_CheckedChanged(object sender, EventArgs e)
{
if (!updatingChat && AdminModeSpecial.Checked)
SetAdminsAreSpecial(true);
}
private void ChatApplyButton_Click(object sender, EventArgs e)
{
var Chat = Server.GetComponent<ITGChat>();
string res;
switch (modifyingProvider)
string res = null;
TGChatSetupInfo wip = null;
switch (ModifyingProvider)
{
case TGChatProvider.Discord:
res = Chat.SetProviderInfo(new TGDiscordSetupInfo() { BotToken = AuthField1.Text });
wip = new TGDiscordSetupInfo()
{
BotToken = AuthField1.Text
};
break;
case TGChatProvider.IRC:
res = Chat.SetProviderInfo(new TGIRCSetupInfo() {
wip = new TGIRCSetupInfo()
{
AuthMessage = AuthField2.Text,
AuthTarget = AuthField1.Text,
Nickname = ChatNicknameText.Text,
URL = ChatServerText.Text,
Port = (ushort)ChatPortSelector.Value,
});
AuthLevel = (IRCMode)IRCModesComboBox.SelectedIndex,
};
break;
default:
res = "You really shouldn't be able to read this.";
break;
}
if (res == null)
{
wip.AdminChannels = new List<string>(AdminChannelsTextbox.Text.Split('\n'));
wip.WatchdogChannels = new List<string>(WDChannelsTextbox.Text.Split('\n'));
wip.DevChannels = new List<string>(DevChannelsTextbox.Text.Split('\n'));
wip.GameChannels = new List<string>(GameChannelsTextbox.Text.Split('\n'));
wip.Enabled = ChatEnabledCheckbox.Checked;
res = Server.GetComponent<ITGChat>().SetProviderInfo(wip);
}
if (res != null)
MessageBox.Show(res);
Chat.SetChannels(SplitByLine(ChatChannelsTextBox), AdminChannelText.Text);
Chat.SetAdmins(SplitByLine(ChatAdminsTextBox));
Chat.SetEnabled(ChatEnabledCheckbox.Checked);
LoadChatPage();
}
}
+188 -41
View File
@@ -105,6 +105,16 @@
this.ServerStatusLabel = new System.Windows.Forms.Label();
this.ServerStatusTitle = new System.Windows.Forms.Label();
this.ChatPanel = new System.Windows.Forms.TabPage();
this.label5 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.IRCModesComboBox = new System.Windows.Forms.ComboBox();
this.label1 = new System.Windows.Forms.Label();
this.AdminChannelsTextbox = new System.Windows.Forms.TextBox();
this.WDChannelsTextbox = new System.Windows.Forms.TextBox();
this.GameChannelsTextbox = new System.Windows.Forms.TextBox();
this.DevChannelsTextbox = new System.Windows.Forms.TextBox();
this.ChatRefreshButton = new System.Windows.Forms.Button();
this.ChatNicknameText = new System.Windows.Forms.TextBox();
this.ChatNicknameTitle = new System.Windows.Forms.Label();
@@ -117,8 +127,6 @@
this.AuthField1Title = new System.Windows.Forms.Label();
this.AuthField2 = new System.Windows.Forms.TextBox();
this.AuthField1 = new System.Windows.Forms.TextBox();
this.AdminChannelTitle = new System.Windows.Forms.Label();
this.AdminChannelText = new System.Windows.Forms.TextBox();
this.ChatReconnectButton = new System.Windows.Forms.Button();
this.ChatStatusLabel = new System.Windows.Forms.Label();
this.ChatStatusTitle = new System.Windows.Forms.Label();
@@ -130,7 +138,9 @@
this.ChannelsTitle = new System.Windows.Forms.Label();
this.ChatAdminsTextBox = new System.Windows.Forms.TextBox();
this.ChatAdminsTitle = new System.Windows.Forms.Label();
this.ChatChannelsTextBox = new System.Windows.Forms.TextBox();
this.panel1 = new System.Windows.Forms.Panel();
this.AdminModeSpecial = new System.Windows.Forms.RadioButton();
this.AdminModeNormal = new System.Windows.Forms.RadioButton();
this.ConfigPanel = new System.Windows.Forms.TabPage();
this.ConfigApply = new System.Windows.Forms.Button();
this.ConfigDownloadRepo = new System.Windows.Forms.Button();
@@ -180,6 +190,7 @@
this.ChatPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.ChatPortSelector)).BeginInit();
this.ChatProviderSelectorPanel.SuspendLayout();
this.panel1.SuspendLayout();
this.ConfigPanel.SuspendLayout();
this.ConfigPanels.SuspendLayout();
this.AdminsPanel.SuspendLayout();
@@ -1170,6 +1181,16 @@
// ChatPanel
//
this.ChatPanel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(39)))), ((int)(((byte)(40)))), ((int)(((byte)(34)))));
this.ChatPanel.Controls.Add(this.label5);
this.ChatPanel.Controls.Add(this.label4);
this.ChatPanel.Controls.Add(this.label3);
this.ChatPanel.Controls.Add(this.label2);
this.ChatPanel.Controls.Add(this.IRCModesComboBox);
this.ChatPanel.Controls.Add(this.label1);
this.ChatPanel.Controls.Add(this.AdminChannelsTextbox);
this.ChatPanel.Controls.Add(this.WDChannelsTextbox);
this.ChatPanel.Controls.Add(this.GameChannelsTextbox);
this.ChatPanel.Controls.Add(this.DevChannelsTextbox);
this.ChatPanel.Controls.Add(this.ChatRefreshButton);
this.ChatPanel.Controls.Add(this.ChatNicknameText);
this.ChatPanel.Controls.Add(this.ChatNicknameTitle);
@@ -1182,8 +1203,6 @@
this.ChatPanel.Controls.Add(this.AuthField1Title);
this.ChatPanel.Controls.Add(this.AuthField2);
this.ChatPanel.Controls.Add(this.AuthField1);
this.ChatPanel.Controls.Add(this.AdminChannelTitle);
this.ChatPanel.Controls.Add(this.AdminChannelText);
this.ChatPanel.Controls.Add(this.ChatReconnectButton);
this.ChatPanel.Controls.Add(this.ChatStatusLabel);
this.ChatPanel.Controls.Add(this.ChatStatusTitle);
@@ -1193,7 +1212,7 @@
this.ChatPanel.Controls.Add(this.ChannelsTitle);
this.ChatPanel.Controls.Add(this.ChatAdminsTextBox);
this.ChatPanel.Controls.Add(this.ChatAdminsTitle);
this.ChatPanel.Controls.Add(this.ChatChannelsTextBox);
this.ChatPanel.Controls.Add(this.panel1);
this.ChatPanel.Location = new System.Drawing.Point(4, 22);
this.ChatPanel.Name = "ChatPanel";
this.ChatPanel.Padding = new System.Windows.Forms.Padding(3);
@@ -1201,6 +1220,117 @@
this.ChatPanel.TabIndex = 4;
this.ChatPanel.Text = "Chat";
//
// label5
//
this.label5.AutoSize = true;
this.label5.Font = new System.Drawing.Font("Verdana", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label5.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
this.label5.Location = new System.Drawing.Point(686, 219);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(148, 18);
this.label5.TabIndex = 43;
this.label5.Text = "Game Messages:";
this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// label4
//
this.label4.AutoSize = true;
this.label4.Font = new System.Drawing.Font("Verdana", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label4.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
this.label4.Location = new System.Drawing.Point(516, 219);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(136, 18);
this.label4.TabIndex = 42;
this.label4.Text = "Developer Info:";
this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Font = new System.Drawing.Font("Verdana", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label3.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
this.label3.Location = new System.Drawing.Point(686, 61);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(135, 18);
this.label3.TabIndex = 41;
this.label3.Text = "Administration:";
this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Font = new System.Drawing.Font("Verdana", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label2.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
this.label2.Location = new System.Drawing.Point(516, 61);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(153, 18);
this.label2.TabIndex = 40;
this.label2.Text = "Server Watchdog:";
this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// IRCModesComboBox
//
this.IRCModesComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.IRCModesComboBox.FormattingEnabled = true;
this.IRCModesComboBox.Items.AddRange(new object[] {
"Voice - +",
"Halfop - %",
"Op - @",
"Owner - ~"});
this.IRCModesComboBox.Location = new System.Drawing.Point(369, 170);
this.IRCModesComboBox.Name = "IRCModesComboBox";
this.IRCModesComboBox.Size = new System.Drawing.Size(141, 21);
this.IRCModesComboBox.TabIndex = 38;
this.IRCModesComboBox.Visible = false;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Font = new System.Drawing.Font("Verdana", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
this.label1.Location = new System.Drawing.Point(30, 174);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(110, 18);
this.label1.TabIndex = 39;
this.label1.Text = "Admin Auth:";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// AdminChannelsTextbox
//
this.AdminChannelsTextbox.Location = new System.Drawing.Point(689, 82);
this.AdminChannelsTextbox.Multiline = true;
this.AdminChannelsTextbox.Name = "AdminChannelsTextbox";
this.AdminChannelsTextbox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.AdminChannelsTextbox.Size = new System.Drawing.Size(167, 120);
this.AdminChannelsTextbox.TabIndex = 37;
//
// WDChannelsTextbox
//
this.WDChannelsTextbox.Location = new System.Drawing.Point(516, 82);
this.WDChannelsTextbox.Multiline = true;
this.WDChannelsTextbox.Name = "WDChannelsTextbox";
this.WDChannelsTextbox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.WDChannelsTextbox.Size = new System.Drawing.Size(167, 120);
this.WDChannelsTextbox.TabIndex = 36;
//
// GameChannelsTextbox
//
this.GameChannelsTextbox.Location = new System.Drawing.Point(689, 240);
this.GameChannelsTextbox.Multiline = true;
this.GameChannelsTextbox.Name = "GameChannelsTextbox";
this.GameChannelsTextbox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.GameChannelsTextbox.Size = new System.Drawing.Size(167, 120);
this.GameChannelsTextbox.TabIndex = 35;
//
// DevChannelsTextbox
//
this.DevChannelsTextbox.Location = new System.Drawing.Point(516, 240);
this.DevChannelsTextbox.Multiline = true;
this.DevChannelsTextbox.Name = "DevChannelsTextbox";
this.DevChannelsTextbox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.DevChannelsTextbox.Size = new System.Drawing.Size(167, 120);
this.DevChannelsTextbox.TabIndex = 34;
//
// ChatRefreshButton
//
this.ChatRefreshButton.Location = new System.Drawing.Point(174, 335);
@@ -1323,7 +1453,6 @@
this.AuthField2.Name = "AuthField2";
this.AuthField2.Size = new System.Drawing.Size(151, 20);
this.AuthField2.TabIndex = 22;
this.AuthField2.UseSystemPasswordChar = true;
//
// AuthField1
//
@@ -1331,26 +1460,6 @@
this.AuthField1.Name = "AuthField1";
this.AuthField1.Size = new System.Drawing.Size(151, 20);
this.AuthField1.TabIndex = 21;
this.AuthField1.UseSystemPasswordChar = true;
//
// AdminChannelTitle
//
this.AdminChannelTitle.AutoSize = true;
this.AdminChannelTitle.Font = new System.Drawing.Font("Verdana", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.AdminChannelTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
this.AdminChannelTitle.Location = new System.Drawing.Point(30, 174);
this.AdminChannelTitle.Name = "AdminChannelTitle";
this.AdminChannelTitle.Size = new System.Drawing.Size(138, 18);
this.AdminChannelTitle.TabIndex = 20;
this.AdminChannelTitle.Text = "Admin Channel:";
this.AdminChannelTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// AdminChannelText
//
this.AdminChannelText.Location = new System.Drawing.Point(174, 172);
this.AdminChannelText.Name = "AdminChannelText";
this.AdminChannelText.Size = new System.Drawing.Size(149, 20);
this.AdminChannelText.TabIndex = 19;
//
// ChatReconnectButton
//
@@ -1441,9 +1550,9 @@
this.ChatProviderTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
this.ChatProviderTitle.Location = new System.Drawing.Point(20, 15);
this.ChatProviderTitle.Name = "ChatProviderTitle";
this.ChatProviderTitle.Size = new System.Drawing.Size(125, 18);
this.ChatProviderTitle.Size = new System.Drawing.Size(144, 18);
this.ChatProviderTitle.TabIndex = 13;
this.ChatProviderTitle.Text = "Chat Provider:";
this.ChatProviderTitle.Text = "Editing Provider:";
this.ChatProviderTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// ChannelsTitle
@@ -1451,7 +1560,7 @@
this.ChannelsTitle.AutoSize = true;
this.ChannelsTitle.Font = new System.Drawing.Font("Verdana", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.ChannelsTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
this.ChannelsTitle.Location = new System.Drawing.Point(628, 15);
this.ChannelsTitle.Location = new System.Drawing.Point(565, 15);
this.ChannelsTitle.Name = "ChannelsTitle";
this.ChannelsTitle.Size = new System.Drawing.Size(234, 18);
this.ChannelsTitle.TabIndex = 11;
@@ -1464,7 +1573,7 @@
this.ChatAdminsTextBox.Multiline = true;
this.ChatAdminsTextBox.Name = "ChatAdminsTextBox";
this.ChatAdminsTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.ChatAdminsTextBox.Size = new System.Drawing.Size(231, 311);
this.ChatAdminsTextBox.Size = new System.Drawing.Size(141, 311);
this.ChatAdminsTextBox.TabIndex = 10;
//
// ChatAdminsTitle
@@ -1479,14 +1588,40 @@
this.ChatAdminsTitle.Text = "Admins:";
this.ChatAdminsTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// ChatChannelsTextBox
// panel1
//
this.ChatChannelsTextBox.Location = new System.Drawing.Point(631, 49);
this.ChatChannelsTextBox.Multiline = true;
this.ChatChannelsTextBox.Name = "ChatChannelsTextBox";
this.ChatChannelsTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.ChatChannelsTextBox.Size = new System.Drawing.Size(231, 311);
this.ChatChannelsTextBox.TabIndex = 0;
this.panel1.Controls.Add(this.AdminModeSpecial);
this.panel1.Controls.Add(this.AdminModeNormal);
this.panel1.Location = new System.Drawing.Point(174, 168);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(202, 25);
this.panel1.TabIndex = 15;
//
// AdminModeSpecial
//
this.AdminModeSpecial.AutoSize = true;
this.AdminModeSpecial.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
this.AdminModeSpecial.Location = new System.Drawing.Point(87, 8);
this.AdminModeSpecial.Name = "AdminModeSpecial";
this.AdminModeSpecial.Size = new System.Drawing.Size(94, 17);
this.AdminModeSpecial.TabIndex = 13;
this.AdminModeSpecial.TabStop = true;
this.AdminModeSpecial.Text = "Channel Mode";
this.AdminModeSpecial.UseVisualStyleBackColor = true;
this.AdminModeNormal.CheckedChanged += new System.EventHandler(this.AdminModeSpecial_CheckedChanged);
//
// AdminModeNormal
//
this.AdminModeNormal.AutoSize = true;
this.AdminModeNormal.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
this.AdminModeNormal.Location = new System.Drawing.Point(3, 8);
this.AdminModeNormal.Name = "AdminModeNormal";
this.AdminModeNormal.Size = new System.Drawing.Size(78, 17);
this.AdminModeNormal.TabIndex = 12;
this.AdminModeNormal.TabStop = true;
this.AdminModeNormal.Text = "Nicknames";
this.AdminModeNormal.UseVisualStyleBackColor = true;
this.AdminModeNormal.CheckedChanged += new System.EventHandler(this.AdminModeNormal_CheckedChanged);
//
// ConfigPanel
//
@@ -1881,6 +2016,8 @@
((System.ComponentModel.ISupportInitialize)(this.ChatPortSelector)).EndInit();
this.ChatProviderSelectorPanel.ResumeLayout(false);
this.ChatProviderSelectorPanel.PerformLayout();
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
this.ConfigPanel.ResumeLayout(false);
this.ConfigPanel.PerformLayout();
this.ConfigPanels.ResumeLayout(false);
@@ -1950,7 +2087,6 @@
private System.Windows.Forms.TextBox ServerPathTextbox;
private System.Windows.Forms.Label LatestVersionLabel;
private System.Windows.Forms.Label LatestVersionTitle;
private System.Windows.Forms.TextBox ChatChannelsTextBox;
private System.Windows.Forms.Label ChannelsTitle;
private System.Windows.Forms.TextBox ChatAdminsTextBox;
private System.Windows.Forms.Label ChatAdminsTitle;
@@ -1962,8 +2098,6 @@
private System.Windows.Forms.RadioButton IRCProviderSwitch;
private System.Windows.Forms.Label ChatProviderTitle;
private System.Windows.Forms.Button ChatReconnectButton;
private System.Windows.Forms.Label AdminChannelTitle;
private System.Windows.Forms.TextBox AdminChannelText;
private System.Windows.Forms.Label AuthField2Title;
private System.Windows.Forms.Label AuthField1Title;
private System.Windows.Forms.TextBox AuthField2;
@@ -2028,5 +2162,18 @@
private System.Windows.Forms.ComboBox VisibilitySelector;
private System.ComponentModel.BackgroundWorker ServerStartBGW;
private System.Windows.Forms.Button RepoRefreshButton;
private System.Windows.Forms.ComboBox IRCModesComboBox;
private System.Windows.Forms.TextBox AdminChannelsTextbox;
private System.Windows.Forms.TextBox WDChannelsTextbox;
private System.Windows.Forms.TextBox GameChannelsTextbox;
private System.Windows.Forms.TextBox DevChannelsTextbox;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.RadioButton AdminModeSpecial;
private System.Windows.Forms.RadioButton AdminModeNormal;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
}
}
+2 -2
View File
@@ -25,5 +25,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("3.0.85.4")]
[assembly: AssemblyFileVersion("3.0.85.4")]
[assembly: AssemblyVersion("3.0.86.0")]
[assembly: AssemblyFileVersion("3.0.86.0")]
+12
View File
@@ -58,5 +58,17 @@ namespace TGControlPanel.Properties {
this["UpgradeRequired"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int LastChatProvider {
get {
return ((int)(this["LastChatProvider"]));
}
set {
this["LastChatProvider"] = value;
}
}
}
}
@@ -11,5 +11,8 @@
<Setting Name="UpgradeRequired" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="LastChatProvider" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
</Settings>
</SettingsFile>
@@ -25,5 +25,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("3.0.85.4")]
[assembly: AssemblyFileVersion("3.0.85.4")]
[assembly: AssemblyVersion("3.0.86.0")]
[assembly: AssemblyFileVersion("3.0.86.0")]
+4 -26
View File
@@ -34,42 +34,17 @@
<setting name="ServerVisiblity" serializeAs="String">
<value>2</value>
</setting>
<setting name="ChatEnabled" serializeAs="String">
<value>False</value>
</setting>
<setting name="DDAutoStart" serializeAs="String">
<value>False</value>
</setting>
<setting name="PythonPath" serializeAs="String">
<value>C:\Python27</value>
</setting>
<setting name="ChatProvider" serializeAs="String">
<value>0</value>
</setting>
<setting name="ChatProviderData" serializeAs="String">
<value>NEEDS INITIALIZING</value>
</setting>
<setting name="ChatAdmins" serializeAs="Xml">
<value>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>theghostofwhibyl1</string>
</ArrayOfString>
</value>
</setting>
<setting name="ChatChannels" serializeAs="Xml">
<value>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>#botbus</string>
</ArrayOfString>
</value>
</setting>
<setting name="ChatAdminChannel" serializeAs="String">
<value>#botbus</value>
</setting>
<setting name="ChatProviderEntropy" serializeAs="String">
<value>John Madden</value>
<value />
</setting>
<setting name="UpgradeRequired" serializeAs="String">
<value>True</value>
@@ -83,6 +58,9 @@
<setting name="ReattachPort" serializeAs="String">
<value>0</value>
</setting>
<setting name="SettingsVersion" serializeAs="String">
<value>0</value>
</setting>
</TGServerService.Properties.Settings>
</userSettings>
</configuration>
+5 -5
View File
@@ -163,7 +163,7 @@ namespace TGServerService
var vi = (VersionInfo)param;
using (var client = new WebClient())
{
SendMessage(String.Format("BYOND: Updating to version {0}.{1}...", vi.major, vi.minor));
SendMessage(String.Format("BYOND: Updating to version {0}.{1}...", vi.major, vi.minor), ChatMessageType.DeveloperInfo);
//DOWNLOADING
@@ -173,7 +173,7 @@ namespace TGServerService
}
catch
{
SendMessage("BYOND: Update download failed. Does the specified version exist?");
SendMessage("BYOND: Update download failed. Does the specified version exist?", ChatMessageType.DeveloperInfo);
lastError = String.Format("Download of BYOND version {0}.{1} failed! Does it exist?", vi.major, vi.minor);
TGServerService.WriteWarning(String.Format("Failed to update BYOND to version {0}.{1}!", vi.major, vi.minor), TGServerService.EventID.BYONDUpdateFail);
lock (ByondLock)
@@ -216,7 +216,7 @@ namespace TGServerService
default:
RequestRestart();
lastError = "Update staged. Awaiting server restart...";
SendMessage(String.Format("BYOND: Staging complete. Awaiting server restart...", vi.major, vi.minor));
SendMessage(String.Format("BYOND: Staging complete. Awaiting server restart...", vi.major, vi.minor), ChatMessageType.DeveloperInfo);
TGServerService.WriteInfo(String.Format("BYOND update {0}.{1} staged", vi.major, vi.minor), TGServerService.EventID.BYONDUpdateStaged);
break;
}
@@ -273,14 +273,14 @@ namespace TGServerService
Directory.Move(StagingDirectoryInner, ByondDirectory);
Program.DeleteDirectory(StagingDirectory);
lastError = null;
SendMessage("BYOND: Update completed!");
SendMessage("BYOND: Update completed!", ChatMessageType.DeveloperInfo);
TGServerService.WriteInfo(String.Format("BYOND update {0} completed!", GetVersion(TGByondVersion.Installed)), TGServerService.EventID.BYONDUpdateComplete);
return true;
}
catch (Exception e)
{
lastError = e.ToString();
SendMessage("BYOND: Update failed!");
SendMessage("BYOND: Update failed!", ChatMessageType.DeveloperInfo);
TGServerService.WriteError("BYOND update failed!", TGServerService.EventID.BYONDUpdateFail);
return false;
}
+149 -234
View File
@@ -1,26 +1,58 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Security.Cryptography;
using System.Text;
using System.Web.Script.Serialization;
using TGServiceInterface;
namespace TGServerService
{
interface ITGChatProvider : ITGChatBase, IDisposable
/// <summary>
/// Type of chat message, these may be OR'd together
/// </summary>
[Flags]
enum ChatMessageType
{
AdminInfo = 1,
GameInfo = 2,
WatchdogInfo = 4,
DeveloperInfo = 8,
}
interface ITGChatProvider : IDisposable
{
/// <summary>
/// Sets info for the provider
/// </summary>
/// <param name="info">The info to set</param>
/// <returns>null on success, error message on failure</returns>
string SetProviderInfo(TGChatSetupInfo info);
/// <summary>
/// Gets the info of the provider
/// </summary>
/// <returns>The info for the chat provider</returns>
TGChatSetupInfo ProviderInfo();
/// <summary>
/// Called with chat message info
/// </summary>
event OnChatMessage OnChatMessage;
/// <summary>
/// Connects the chat provider
/// Connects the chat provider if it's enabled
/// </summary>
/// <returns>null on success, error message on failure</returns>
string Connect();
/// <summary>
/// Forces a reconnection of the chat provider if it's enabled
/// </summary>
/// <returns>null on success, error message on failure</returns>
string Reconnect();
/// <summary>
/// Checks if the chat provider is connected
/// </summary>
/// <returns>true if the provider is connected, false otherwise</returns>
bool Connected();
/// <summary>
/// Disconnects the chat provider
@@ -34,72 +66,70 @@ namespace TGServerService
/// <param name="channel">The channel to send to</param>
/// <returns>null on success, error message on failure</returns>
string SendMessageDirect(string message, string channel);
/// <summary>
/// Broadcast a message to appropriate channels based on the message type
/// </summary>
/// <param name="msg">The message to send</param>
/// <param name="mt">The message type</param>
void SendMessage(string msg, ChatMessageType mt);
}
/// <summary>
/// Callback for the chat provider recieving a message
/// </summary>
/// <param name="ChatProvider">The chat provider the message came from</param>
/// <param name="speaker">The username of the speaker</param>
/// <param name="channel">The name of the channel</param>
/// <param name="message">The message text</param>
/// <param name="tagged">true if the bot was mentioned in the first word, false otherwise</param>
public delegate void OnChatMessage(string speaker, string channel, string message, bool tagged);
delegate void OnChatMessage(ITGChatProvider ChatProvider, string speaker, string channel, string message, bool isAdmin, bool isAdminChannel);
partial class TGStationServer : ITGChat
{
ITGChatProvider ChatProvider;
TGChatProvider currentProvider;
IList<ITGChatProvider> ChatProviders;
object ChatLock = new object();
public void InitChat(TGChatSetupInfo info = null)
public void InitChat()
{
if (info == null)
info = ProviderInfo();
currentProvider = info.Provider;
try
var infos = InitProviderInfos();
ChatProviders = new List<ITGChatProvider>(infos.Count);
foreach (var info in infos)
{
switch (info.Provider)
ITGChatProvider ChatProvider;
try
{
case TGChatProvider.Discord:
ChatProvider = new TGDiscordChatProvider(info);
break;
case TGChatProvider.IRC:
ChatProvider = new TGIRCChatProvider(info);
break;
default:
TGServerService.WriteError(String.Format("Invalid chat provider: {0}", info.Provider), TGServerService.EventID.InvalidChatProvider);
break;
switch (info.Provider)
{
case TGChatProvider.Discord:
ChatProvider = new TGDiscordChatProvider(info);
break;
case TGChatProvider.IRC:
ChatProvider = new TGIRCChatProvider(info);
break;
default:
TGServerService.WriteError(String.Format("Invalid chat provider: {0}", info.Provider), TGServerService.EventID.InvalidChatProvider);
continue;
}
}
}
catch (Exception e)
{
TGServerService.WriteError(String.Format("Failed to start chat provider {0}! Error: {1}", info.Provider, e.ToString()), TGServerService.EventID.ChatProviderStartFail);
return;
}
ChatProvider.OnChatMessage += ChatProvider_OnChatMessage;
if (Properties.Settings.Default.ChatEnabled)
{
catch (Exception e)
{
TGServerService.WriteError(String.Format("Failed to start chat provider {0}! Error: {1}", info.Provider, e.ToString()), TGServerService.EventID.ChatProviderStartFail);
continue;
}
ChatProvider.OnChatMessage += ChatProvider_OnChatMessage;
var res = ChatProvider.Connect();
if (res != null)
TGServerService.WriteWarning(String.Format("Unable to connect to chat! Provider {0}, Error: {1}", ChatProvider.GetType().ToString(), res), TGServerService.EventID.ChatConnectFail);
ChatProviders.Add(ChatProvider);
}
}
private void ChatProvider_OnChatMessage(string speaker, string channel, string message, bool tagged)
private void ChatProvider_OnChatMessage(ITGChatProvider ChatProvider, string speaker, string channel, string message, bool isAdmin, bool isAdminChannel)
{
var splits = message.Trim().Split(' ');
var s0l = splits[0].ToLower();
if (s0l == "!check")
{
ChatProvider.SendMessageDirect(StatusString(HasChatAdmin(speaker, channel) == null), channel);
return;
}
if (!tagged)
return;
if (splits.Length == 1 && splits[0] == "")
{
ChatProvider.SendMessageDirect("Hi!", channel);
@@ -110,37 +140,48 @@ namespace TGServerService
var command = asList[0].ToLower();
asList.RemoveAt(0);
ChatProvider.SendMessageDirect(ChatCommand(command, speaker, channel, asList), channel);
ChatProvider.SendMessageDirect(ChatCommand(command, speaker, channel, asList, isAdmin, isAdminChannel), channel);
}
string HasChatAdmin(string speaker, string channel)
string HasChatAdmin(bool isAdmin, bool isAdminChannel)
{
var Config = Properties.Settings.Default;
if (!Config.ChatAdmins.Contains(speaker.ToLower()))
if (!isAdmin)
return "You are not authorized to use that command!";
if (channel.ToLower() != Config.ChatAdminChannel.ToLower())
return "Use this command in the admin channel!";
if (!isAdminChannel)
return "Use this command in an admin channel!";
return null;
}
//cleanup
//cleanup and save
void DisposeChat()
{
if (ChatProvider != null)
var infosList = new List<IList<string>>();
foreach (var ChatProvider in ChatProviders)
{
infosList.Add(ChatProvider.ProviderInfo().DataFields);
ChatProvider.Dispose();
ChatProvider = null;
}
ChatProviders = null;
var rawdata = new JavaScriptSerializer().Serialize(infosList);
var Config = Properties.Settings.Default;
byte[] plaintext = Encoding.UTF8.GetBytes(rawdata);
Config.ChatProviderData = Program.EncryptData(plaintext, out string entrp);
Config.ChatProviderEntropy = entrp;
}
//Do stuff with words that were spoken to us
string ChatCommand(string command, string speaker, string channel, IList<string> parameters)
string ChatCommand(string command, string speaker, string channel, IList<string> parameters, bool isAdmin, bool isAdminChannel)
{
TGServerService.WriteInfo(String.Format("Chat Command from {0}: {1} {2}", speaker, command, String.Join(" ", parameters)), TGServerService.EventID.ChatCommand);
var adminmessage = HasChatAdmin(isAdmin, isAdminChannel);
switch (command)
{
case "check":
return StatusString(HasChatAdmin(speaker, channel) == null);
return StatusString(adminmessage == null);
case "byond":
if (parameters.Count > 0)
if (parameters[0].ToLower() == "--staged")
@@ -149,27 +190,25 @@ namespace TGServerService
return GetVersion(TGByondVersion.Latest) ?? "Unknown";
return GetVersion(TGByondVersion.Staged) ?? "Uninstalled";
case "status":
return HasChatAdmin(speaker, channel) ?? SendCommand(SCIRCStatus);
return adminmessage ?? SendCommand(SCIRCStatus);
case "adminwho":
return HasChatAdmin(speaker, channel) ?? SendCommand(SCAdminWho);
return adminmessage ?? SendCommand(SCAdminWho);
case "ahelp":
var res = HasChatAdmin(speaker, channel);
if (res != null)
return res;
if (adminmessage != null)
return adminmessage;
if (parameters.Count < 2)
return "Usage: ahelp <ckey> <message>";
var ckey = parameters[0];
parameters.RemoveAt(0);
return SendPM(ckey, speaker, String.Join(" ", parameters));
case "namecheck":
res = HasChatAdmin(speaker, channel);
if (res != null)
return res;
if (adminmessage != null)
return adminmessage;
if (parameters.Count < 1)
return "Usage: namecheck <target>";
return NameCheck(parameters[0], speaker);
case "prs":
var PRs = MergedPullRequests(out res);
var PRs = MergedPullRequests(out string res);
if (PRs == null)
return res;
if (PRs.Count == 0)
@@ -186,100 +225,34 @@ namespace TGServerService
return "Unknown command: " + command;
}
//public api
public string SetEnabled(bool enable)
public IList<TGChatSetupInfo> ProviderInfos()
{
lock (ChatLock)
{
Properties.Settings.Default.ChatEnabled = enable;
if (!enable && Connected())
ChatProvider.Disconnect();
else if (enable && !Connected())
return ChatProvider != null ? ChatProvider.Connect() : "Null chat provider!";
return null;
}
var infosList = new List<TGChatSetupInfo>();
foreach (var ChatProvider in ChatProviders)
infosList.Add(ChatProvider.ProviderInfo());
return infosList;
}
//public api
public string[] Channels()
{
lock (ChatLock)
{
return CollectionToArray(Properties.Settings.Default.ChatChannels);
}
}
//what it says on the tin
string[] CollectionToArray(StringCollection sc)
{
string[] strArray = new string[sc.Count];
sc.CopyTo(strArray, 0);
return strArray;
}
//public api
public string AdminChannel()
{
lock (ChatLock)
{
return Properties.Settings.Default.ChatAdminChannel;
}
}
//public api
public bool Enabled()
{
lock (ChatLock)
{
return Properties.Settings.Default.ChatEnabled;
}
}
//public api
public string[] ListAdmins()
{
lock (ChatLock)
{
return CollectionToArray(Properties.Settings.Default.ChatAdmins);
}
}
//public api
public void SetAdmins(string[] admins)
{
var si = new StringCollection();
foreach (var I in admins)
si.Add(I.Trim().ToLower());
lock (ChatLock)
{
Properties.Settings.Default.ChatAdmins = si;
}
}
//public api
public TGChatSetupInfo ProviderInfo()
IList<TGChatSetupInfo> InitProviderInfos()
{
lock (ChatLock)
{
var Config = Properties.Settings.Default;
var rawdata = Config.ChatProviderData;
if (rawdata == "NEEDS INITIALIZING")
switch ((TGChatProvider)Config.ChatProvider)
{
case TGChatProvider.Discord:
return new TGDiscordSetupInfo();
case TGChatProvider.IRC:
return new TGIRCSetupInfo();
default:
TGServerService.WriteError("Invalid chat provider: " + Config.ChatProvider.ToString(), TGServerService.EventID.InvalidChatProvider);
return null;
}
return new List<TGChatSetupInfo>() { new TGIRCSetupInfo(), new TGDiscordSetupInfo() };
byte[] plaintext;
try
{
plaintext = ProtectedData.Unprotect(Convert.FromBase64String(Config.ChatProviderData), Convert.FromBase64String(Config.ChatProviderEntropy), DataProtectionScope.CurrentUser);
var Deserializer = new JavaScriptSerializer();
return new TGChatSetupInfo(Deserializer.Deserialize<List<string>>(Encoding.UTF8.GetString(plaintext)), (TGChatProvider)Config.ChatProvider);
plaintext = Program.DecryptData(rawdata, Config.ChatProviderEntropy);
var lists = new JavaScriptSerializer().Deserialize<List<List<string>>>(Encoding.UTF8.GetString(plaintext));
var output = new List<TGChatSetupInfo>(lists.Count);
foreach (var l in lists)
output.Add(new TGChatSetupInfo(l));
return output;
}
catch
{
@@ -287,7 +260,7 @@ namespace TGServerService
}
}
//if we get here we want to retry
return ProviderInfo();
return InitProviderInfos();
}
//public api
@@ -297,34 +270,10 @@ namespace TGServerService
{
lock (ChatLock)
{
var Serializer = new JavaScriptSerializer();
var rawdata = Serializer.Serialize(info.DataFields);
var Config = Properties.Settings.Default;
Config.ChatProvider = (int)info.Provider;
Config.ChatProviderData = rawdata;
byte[] plaintext = Encoding.UTF8.GetBytes(rawdata);
// Generate additional entropy (will be used as the Initialization vector)
byte[] entropy = new byte[20];
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(entropy);
}
byte[] ciphertext = ProtectedData.Protect(plaintext, entropy, DataProtectionScope.CurrentUser);
Config.ChatProviderEntropy = Convert.ToBase64String(entropy, 0, entropy.Length);
Config.ChatProviderData = Convert.ToBase64String(ciphertext, 0, ciphertext.Length);
if (ChatProvider != null && info.Provider == currentProvider)
return ChatProvider.SetProviderInfo(info);
else
{
DisposeChat();
InitChat(info);
return null;
}
foreach (var ChatProvider in ChatProviders)
if (info.Provider == ChatProvider.ProviderInfo().Provider)
return ChatProvider.SetProviderInfo(info);
return "Error: Invalid provider: " + info.Provider.ToString();
}
}
catch (Exception e)
@@ -333,75 +282,41 @@ namespace TGServerService
}
}
//trims and adds the leading #
string SanitizeChannelName(string working)
//public api
public bool Connected(TGChatProvider providerType)
{
if (String.IsNullOrWhiteSpace(working))
return null;
working = working.Trim();
if (working[0] != '#')
return "#" + working;
return working;
foreach (var I in ChatProviders)
if (I.ProviderInfo().Provider == providerType)
return I.Connected();
return false;
}
//public api
public void SetChannels(string[] channels = null, string adminchannel = null)
public string Reconnect(TGChatProvider providerType)
{
foreach (var I in ChatProviders)
if (I.ProviderInfo().Provider == providerType)
return I.Reconnect();
return "Could not find specified provider!";
}
/// <summary>
/// Broadcast a message to appropriate channels based on the message type
/// </summary>
/// <param name="msg">The message to send</param>
/// <param name="mt">The message type</param>
public void SendMessage(string msg, ChatMessageType mt)
{
var Config = Properties.Settings.Default;
lock (ChatLock)
{
if (channels != null)
{
var oldchannels = Config.ChatChannels;
var si = new StringCollection();
foreach (var c in channels)
foreach (var ChatProvider in ChatProviders)
try
{
var Res = SanitizeChannelName(c);
if (Res != null)
si.Add(Res);
ChatProvider.SendMessage(msg, mt);
}catch(Exception e)
{
TGServerService.WriteWarning(String.Format("Chat broadcast failed (Provider: {3}) (Flags: {0}) (Message: {1}): {2}", mt, msg, e.ToString(), ChatProvider.ProviderInfo().Provider), TGServerService.EventID.ChatBroadcastFail);
}
if (!si.Contains(Config.ChatAdminChannel))
si.Add(Config.ChatAdminChannel);
Config.ChatChannels = si;
}
adminchannel = SanitizeChannelName(adminchannel);
if (adminchannel != null)
{
Config.ChatAdminChannel = adminchannel;
if (!Config.ChatChannels.Contains(adminchannel))
Config.ChatChannels.Add(adminchannel);
}
if (channels != null && Connected())
ChatProvider.SetChannels(CollectionToArray(Config.ChatChannels), Config.ChatAdminChannel);
}
}
//public api
public bool Connected()
{
lock (ChatLock)
{
return ChatProvider != null ? ChatProvider.Connected() : false;
}
}
//public api
public string Reconnect()
{
lock (ChatLock)
{
if (!Properties.Settings.Default.ChatEnabled)
return "Chat is disabled!";
return ChatProvider != null ? ChatProvider.Reconnect() : "Null chat provider!";
}
}
//public api
public string SendMessage(string msg, bool adminOnly = false)
{
lock (ChatLock)
{
return ChatProvider != null ? ChatProvider.SendMessage(msg, adminOnly) : "Null chat provider!";
}
}
}
+9 -9
View File
@@ -179,7 +179,7 @@ namespace TGServerService
}
try
{
SendMessage("DM: Setting up symlinks...");
SendMessage("DM: Setting up symlinks...", ChatMessageType.DeveloperInfo);
CleanGameFolder();
Program.DeleteDirectory(GameDir);
@@ -211,7 +211,7 @@ namespace TGServerService
{
lock (CompilerLock)
{
SendMessage("DM: Setup failed!");
SendMessage("DM: Setup failed!", ChatMessageType.DeveloperInfo);
lastCompilerError = e.ToString();
compilerCurrentStatus = TGCompilerStatus.Uninitialized;
return;
@@ -301,7 +301,7 @@ namespace TGServerService
}
if(!silent)
SendMessage("DM: Compiling...");
SendMessage("DM: Compiling...", ChatMessageType.DeveloperInfo);
var resurrectee = GetStagingDir();
@@ -331,7 +331,7 @@ namespace TGServerService
if (repobusy_check)
{
SendMessage("DM: Copy aborted, repo locked!");
SendMessage("DM: Copy aborted, repo locked!", ChatMessageType.DeveloperInfo);
lock (CompilerLock)
{
lastCompilerError = "The repo could not be locked for copying";
@@ -368,7 +368,7 @@ namespace TGServerService
if (!File.Exists(dmePath))
{
var errorMsg = String.Format("Could not find {0}!", dmeName);
SendMessage("DM: " + errorMsg);
SendMessage("DM: " + errorMsg, ChatMessageType.DeveloperInfo);
TGServerService.WriteError(errorMsg, TGServerService.EventID.DMCompileCrash);
lock (CompilerLock)
{
@@ -464,7 +464,7 @@ namespace TGServerService
}
var staged = DaemonStatus() != TGDreamDaemonStatus.Offline;
var msg = String.Format("Compile complete!{0}", !staged ? "" : " Server will update next round.");
SendMessage("DM: " + msg);
SendMessage("DM: " + msg, ChatMessageType.DeveloperInfo);
TGServerService.WriteInfo(msg, TGServerService.EventID.DMCompileSuccess);
lock (CompilerLock)
{
@@ -476,7 +476,7 @@ namespace TGServerService
}
else
{
SendMessage("DM: Compile failed!"); //Also happens for warnings
SendMessage("DM: Compile failed!", ChatMessageType.DeveloperInfo); //Also happens for warnings
TGServerService.WriteWarning("Compile error: " + OutputList.ToString(), TGServerService.EventID.DMCompileError);
lock (CompilerLock)
{
@@ -493,7 +493,7 @@ namespace TGServerService
}
catch (Exception e)
{
SendMessage("DM: Compiler thread crashed!");
SendMessage("DM: Compiler thread crashed!", ChatMessageType.DeveloperInfo);
TGServerService.WriteError("Compile manager errror: " + e.ToString(), TGServerService.EventID.DMCompileCrash);
lock (CompilerLock)
{
@@ -510,7 +510,7 @@ namespace TGServerService
{
compilerCurrentStatus = TGCompilerStatus.Initialized;
compilationCancellationRequestation = false;
SendMessage("DM: Compile cancelled!");
SendMessage("DM: Compile cancelled!", ChatMessageType.DeveloperInfo);
TGServerService.WriteInfo("Compilation cancelled", TGServerService.EventID.DMCompileCancel);
}
}
+77 -45
View File
@@ -1,6 +1,7 @@
using Discord;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TGServiceInterface;
@@ -20,6 +21,11 @@ namespace TGServerService
Init(info);
}
public TGChatSetupInfo ProviderInfo()
{
return DiscordConfig;
}
void Init(TGChatSetupInfo info)
{
DiscordConfig = new TGDiscordSetupInfo(info);
@@ -27,29 +33,50 @@ namespace TGServerService
client.MessageReceived += Client_MessageReceived;
}
private bool CheckAdmin(User u)
{
if (!DiscordConfig.AdminsAreSpecial)
return DiscordConfig.AdminList.Contains(u.Id.ToString());
foreach (var I in u.Roles)
if (DiscordConfig.AdminList.Contains(I.Id.ToString()))
return true;
return false;
}
private void Client_MessageReceived(object sender, MessageEventArgs e)
{
var isValidChannel = Properties.Settings.Default.ChatChannels.Contains("#" + e.Channel.Name) || e.Channel.IsPrivate;
if (!isValidChannel)
return;
var tagged = e.Channel.IsPrivate && e.User.Id != client.CurrentUser.Id;
if (tagged && !SeenPrivateChannels.ContainsKey(e.Channel.Id))
var pm = e.Channel.IsPrivate && e.User.Id != client.CurrentUser.Id;
if (pm && !SeenPrivateChannels.ContainsKey(e.Channel.Id))
SeenPrivateChannels.Add(e.Channel.Id, e.Channel);
var splits = new List<string>(e.Message.Text.Trim().Split(' '));
if (splits[0] == "@" + client.CurrentUser.Name)
{
splits.RemoveAt(0);
tagged = true;
}
OnChatMessage(e.User.Id.ToString(), e.Channel.Id.ToString(), String.Join(" ", splits), tagged);
bool found = false;
var formattedMessage = e.Message.RawText;
foreach (var u in e.Message.MentionedUsers)
if(u.Id == client.CurrentUser.Id)
{
found = true;
formattedMessage = formattedMessage.Replace(u.Mention, "");
break;
}
if (!found && !pm)
return;
formattedMessage = formattedMessage.Trim();
var cid = e.Channel.Id.ToString();
OnChatMessage(this, e.User.Id.ToString(), cid, formattedMessage, CheckAdmin(e.User), pm || DiscordConfig.AdminChannels.Contains(cid));
}
public string Connect()
{
try
{
if (Connected() || !DiscordConfig.Enabled)
return null;
lock (DiscordLock)
{
SeenPrivateChannels.Clear();
@@ -105,35 +132,36 @@ namespace TGServerService
}
}
public string SendMessage(string msg, bool adminOnly = false)
public void SendMessage(string msg, ChatMessageType mt)
{
try
if (!Connected())
return;
lock (DiscordLock)
{
lock (DiscordLock)
{
var tasks = new List<Task>();
var Config = Properties.Settings.Default;
foreach (var I in client.Servers)
foreach (var J in I.TextChannels)
{
var SendToThisChannel = adminOnly ? ("#" + J.Name) == Config.ChatAdminChannel : Config.ChatChannels.Contains("#" + J.Name);
if (SendToThisChannel)
tasks.Add(J.SendMessage(msg));
}
foreach (var I in tasks)
I.Wait();
TGServerService.WriteInfo(String.Format("Discord Send{0}: {1}", adminOnly ? " (ADMIN)" : "", msg), adminOnly ? TGServerService.EventID.ChatAdminBroadcast : TGServerService.EventID.ChatBroadcast);
return null;
}
}
catch (Exception e)
{
return e.ToString();
var tasks = new List<Task>();
var Config = Properties.Settings.Default;
foreach (var I in client.Servers)
foreach (var J in I.TextChannels)
{
var cid = J.Id.ToString();
var wdc = DiscordConfig.WatchdogChannels;
bool SendToThisChannel = (mt.HasFlag(ChatMessageType.AdminInfo) && DiscordConfig.AdminChannels.Contains(cid))
|| (mt.HasFlag(ChatMessageType.DeveloperInfo) && DiscordConfig.DevChannels.Contains(cid))
|| (mt.HasFlag(ChatMessageType.GameInfo) && DiscordConfig.GameChannels.Contains(cid))
|| (mt.HasFlag(ChatMessageType.WatchdogInfo) && DiscordConfig.WatchdogChannels.Contains(cid));
if (SendToThisChannel)
tasks.Add(J.SendMessage(msg));
}
foreach (var I in tasks)
I.Wait();
}
}
public string SendMessageDirect(string message, string channelname)
{
if (!Connected())
return "Disconnected.";
try
{
lock (DiscordLock)
@@ -157,12 +185,6 @@ namespace TGServerService
return e.ToString();
}
}
public void SetChannels(string[] channels = null, string adminchannel = null)
{
//noop
}
void DisconnectAndDispose()
{
try
@@ -181,10 +203,20 @@ namespace TGServerService
{
lock (DiscordLock)
{
DisconnectAndDispose();
Init(info);
if (Properties.Settings.Default.ChatEnabled)
Connect();
var odc = DiscordConfig;
DiscordConfig = new TGDiscordSetupInfo(info);
if (DiscordConfig.BotToken != odc.BotToken)
{
DisconnectAndDispose();
Init(info);
}
if (DiscordConfig.Enabled)
{
if (!Connected())
return Reconnect();
}
else
Disconnect();
}
return null;
}
+8 -8
View File
@@ -46,7 +46,7 @@ namespace TGServerService
if (Proc == null)
throw new Exception("GetProcessById returned null!");
TGServerService.WriteInfo("Reattached to running DD process!", TGServerService.EventID.DDReattachSuccess);
SendMessage("DD: Update complete. Watch dog reactivated...");
SendMessage("DD: Update complete. Watch dog reactivated...", ChatMessageType.WatchdogInfo);
//start wd
InitInterop();
@@ -93,7 +93,7 @@ namespace TGServerService
Thread.Sleep(1000);
}
else
SendMessage("DD: Detaching watch dog for update!");
SendMessage("DD: Detaching watch dog for update!", ChatMessageType.WatchdogInfo);
}
else if (Detach)
{
@@ -184,7 +184,7 @@ namespace TGServerService
return "Restart already in progress";
try
{
SendMessage("DD: Hard restart triggered");
SendMessage("DD: Hard restart triggered", ChatMessageType.WatchdogInfo);
RestartInProgress = true;
Stop();
var res = Start();
@@ -206,7 +206,7 @@ namespace TGServerService
{
if (!RestartInProgress)
{
SendMessage("DD: Server started, watchdog active...");
SendMessage("DD: Server started, watchdog active...", ChatMessageType.WatchdogInfo);
TGServerService.WriteInfo("Watchdog started", TGServerService.EventID.DDWatchdogStarted);
}
else
@@ -242,14 +242,14 @@ namespace TGServerService
{
++retries;
var sleep_time = (int)Math.Min(Math.Pow(2, retries), 3600); //max of one hour
SendMessage(String.Format("DD: Watchdog server startup failed! Retrying in {0} seconds...", sleep_time));
SendMessage(String.Format("DD: Watchdog server startup failed! Retrying in {0} seconds...", sleep_time), ChatMessageType.WatchdogInfo);
Thread.Sleep(sleep_time * 1000);
}
else
{
retries = 0;
var msg = "DD: DreamDaemon crashed! Watchdog rebooting DD...";
SendMessage(msg);
SendMessage(msg, ChatMessageType.WatchdogInfo);
TGServerService.WriteWarning(msg, TGServerService.EventID.DDWatchdogRebootingServer);
}
}
@@ -280,7 +280,7 @@ namespace TGServerService
}
catch (Exception e)
{
SendMessage("DD: Watchdog thread crashed!");
SendMessage("DD: Watchdog thread crashed!", ChatMessageType.WatchdogInfo);
TGServerService.WriteError("Watch dog thread crashed: " + e.ToString(), TGServerService.EventID.DDWatchdogCrash);
}
finally
@@ -292,7 +292,7 @@ namespace TGServerService
AwaitingShutdown = ShutdownRequestPhase.None;
if (!RestartInProgress)
{
SendMessage("DD: Server stopped, watchdog exiting...");
SendMessage("DD: Server stopped, watchdog exiting...", ChatMessageType.WatchdogInfo);
TGServerService.WriteInfo("Watch dog exited", TGServerService.EventID.DDWatchdogExit);
}
else
+96 -54
View File
@@ -11,7 +11,6 @@ namespace TGServerService
{
const string PrivateMessageMarker = "---PRIVATE-MSG---";
IrcFeatures irc;
int reconnectAttempt = 0;
object IRCLock = new object();
@@ -19,15 +18,30 @@ namespace TGServerService
public event OnChatMessage OnChatMessage;
public TGChatSetupInfo ProviderInfo()
{
return IRCConfig;
}
public TGIRCChatProvider(TGChatSetupInfo info)
{
IRCConfig = new TGIRCSetupInfo(info);
irc = new IrcFeatures() { SupportNonRfc = true };
irc = new IrcFeatures()
{
SupportNonRfc = true,
CtcpUserInfo = TGServerService.Version,
AutoRejoin = true,
AutoRejoinOnKick = true,
AutoRelogin = true,
AutoRetry = true,
AutoRetryLimit = 5,
AutoRetryDelay = 5,
ActiveChannelSyncing = true,
};
irc.OnChannelMessage += Irc_OnChannelMessage;
irc.OnQueryMessage += Irc_OnQueryMessage;
irc.CtcpUserInfo = TGServerService.Version;
}
//public api
public string SendMessageDirect(string message, string channel)
{
@@ -55,32 +69,62 @@ namespace TGServerService
var convertedInfo = (TGIRCSetupInfo)info;
var serverChange = convertedInfo.URL != IRCConfig.URL || convertedInfo.Port != IRCConfig.Port;
IRCConfig = convertedInfo;
if (serverChange)
if (!IRCConfig.Enabled)
{
Disconnect();
return null;
}
else if (serverChange || !Connected())
return Reconnect();
else if (convertedInfo.Nickname != irc.Nickname)
if (IRCConfig.Nickname != irc.Nickname)
irc.RfcNick(convertedInfo.Nickname);
Login();
JoinChannels();
return null;
}
public void SetChannels(string[] channels = null, string adminchannel = null)
private bool CheckAdmin(IrcMessageData e)
{
lock (IRCLock) {
var channelsList = new List<string>(channels);
var Config = Properties.Settings.Default;
foreach (var I in irc.JoinedChannels)
if (!channelsList.Contains(I))
irc.RfcPart(I);
foreach (var I in channelsList)
if (!irc.JoinedChannels.Contains(I))
irc.RfcJoin(I);
if (IRCConfig.AdminsAreSpecial)
{
var Chan = irc.GetChannel(e.Channel);
var user = (NonRfcChannelUser)irc.GetChannelUser(e.Channel, e.Nick);
if (user != null)
switch (IRCConfig.AuthLevel)
{
case IRCMode.Voice:
if (user.IsVoice)
return true;
goto case IRCMode.Halfop;
case IRCMode.Halfop:
if (user.IsHalfop)
return true;
goto case IRCMode.Op;
case IRCMode.Op:
if (user.IsOp)
return true;
goto case IRCMode.Owner;
case IRCMode.Owner:
if (user.IsOwner)
return true;
break;
}
}
else
{
var lowerNick = e.Nick.ToLower();
foreach (var I in IRCConfig.AdminList)
if (lowerNick == I.ToLower())
return true;
}
return false;
}
//private message
private void Irc_OnQueryMessage(object sender, IrcEventArgs e)
{
OnChatMessage(e.Data.Nick, e.Data.Nick + PrivateMessageMarker, e.Data.Message, true);
OnChatMessage(this, e.Data.Nick, e.Data.Nick + PrivateMessageMarker, e.Data.Message, CheckAdmin(e.Data), true);
}
private void Irc_OnChannelMessage(object sender, IrcEventArgs e)
@@ -91,20 +135,33 @@ namespace TGServerService
var test = splits[0];
if (test.Length > 1 && test[test.Length - 1] == ':')
test = test.Substring(0, test.Length - 1);
var tagged = test.ToLower() == irc.Nickname.ToLower();
if (test.ToLower() != irc.Nickname.ToLower())
return;
if (tagged)
{
splits.RemoveAt(0);
formattedMessage = String.Join(" ", splits);
}
splits.RemoveAt(0);
formattedMessage = String.Join(" ", splits);
OnChatMessage(e.Data.Nick, e.Data.Channel, formattedMessage, tagged);
OnChatMessage(this, e.Data.Nick, e.Data.Channel, formattedMessage, CheckAdmin(e.Data), IRCConfig.AdminChannels.Contains(e.Data.Channel.ToLower()));
}
//Joins configured channels
void JoinChannels()
{
foreach (var I in Properties.Settings.Default.ChatChannels)
var hs = new HashSet<string>(); //for unique inserts
foreach (var I in IRCConfig.AdminChannels)
hs.Add(I);
foreach (var I in IRCConfig.DevChannels)
hs.Add(I);
foreach (var I in IRCConfig.GameChannels)
hs.Add(I);
foreach (var I in IRCConfig.WatchdogChannels)
hs.Add(I);
var ToPart = new List<string>();
foreach (var I in irc.JoinedChannels)
if (!hs.Remove(I))
ToPart.Add(I);
foreach (var I in ToPart)
irc.RfcPart(I);
foreach (var I in hs)
irc.RfcJoin(I);
}
//runs the login command
@@ -119,7 +176,7 @@ namespace TGServerService
//public api
public string Connect()
{
if (Connected())
if (Connected() || !IRCConfig.Enabled)
return null;
lock (IRCLock)
{
@@ -128,20 +185,10 @@ namespace TGServerService
try
{
irc.Connect(IRCConfig.URL, IRCConfig.Port);
reconnectAttempt = 0;
}
catch (Exception e)
{
reconnectAttempt++;
if (reconnectAttempt <= 5)
{
Thread.Sleep(5000); //Reconnecting after 5 seconds.
return Connect();
}
else
{
return "IRC server unreachable: " + e.ToString();
}
return "IRC server unreachable: " + e.ToString();
}
try
@@ -154,6 +201,7 @@ namespace TGServerService
}
Login();
JoinChannels();
new Thread(new ThreadStart(IRCListen)) { IsBackground = true }.Start();
return null;
}
@@ -210,27 +258,21 @@ namespace TGServerService
}
}
//public api
public string SendMessage(string message, bool adminOnly)
public void SendMessage(string message, ChatMessageType mt)
{
try
if (!Connected())
return;
lock (IRCLock)
{
if (!Connected())
return "Disconnected.";
lock (IRCLock)
foreach (var cid in irc.JoinedChannels)
{
var Config = Properties.Settings.Default;
if (adminOnly)
irc.SendMessage(SendType.Message, Config.ChatAdminChannel, message);
else
foreach (var I in Config.ChatChannels)
irc.SendMessage(SendType.Message, I, message);
bool SendToThisChannel = (mt.HasFlag(ChatMessageType.AdminInfo) && IRCConfig.AdminChannels.Contains(cid))
|| (mt.HasFlag(ChatMessageType.DeveloperInfo) && IRCConfig.DevChannels.Contains(cid))
|| (mt.HasFlag(ChatMessageType.GameInfo) && IRCConfig.GameChannels.Contains(cid))
|| (mt.HasFlag(ChatMessageType.WatchdogInfo) && IRCConfig.WatchdogChannels.Contains(cid));
if (SendToThisChannel)
irc.SendMessage(SendType.Message, cid, message);
}
TGServerService.WriteInfo(String.Format("IRC Send{0}: {1}", adminOnly ? " (ADMIN)" : "", message), adminOnly ? TGServerService.EventID.ChatAdminBroadcast : TGServerService.EventID.ChatBroadcast);
return null;
}
catch (Exception e)
{
return e.ToString();
}
}
+2 -2
View File
@@ -45,13 +45,13 @@ namespace TGServerService
switch (cmd)
{
case SRIRCBroadcast:
SendMessage("GAME: " + String.Join(" ", splits));
SendMessage("GAME: " + String.Join(" ", splits), ChatMessageType.GameInfo);
break;
case SRKillProcess:
KillMe();
break;
case SRIRCAdminChannelMessage:
SendMessage("RELAY: " + String.Join(" ", splits), true);
SendMessage("RELAY: " + String.Join(" ", splits), ChatMessageType.AdminInfo);
break;
case SRWorldReboot:
TGServerService.WriteInfo("World Rebooted", TGServerService.EventID.WorldReboot);
+20
View File
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace TGServerService
{
@@ -45,6 +47,24 @@ namespace TGServerService
}
}
public static string EncryptData(byte[] data, out string sentropy)
{
// Generate additional entropy (will be used as the Initialization vector)
byte[] entropy = new byte[20];
using (var rng = new RNGCryptoServiceProvider())
rng.GetBytes(entropy);
byte[] ciphertext = ProtectedData.Protect(data, entropy, DataProtectionScope.CurrentUser);
sentropy = Convert.ToBase64String(entropy, 0, entropy.Length);
return Convert.ToBase64String(ciphertext, 0, ciphertext.Length);
}
public static byte[] DecryptData(string data, string entropy)
{
return ProtectedData.Unprotect(Convert.FromBase64String(data), Convert.FromBase64String(entropy), DataProtectionScope.CurrentUser);
}
public static void CopyDirectory(string sourceDirName, string destDirName, IList<string> ignore = null, bool ignoreIfNotExists = false)
{
// If the destination directory doesn't exist, create it.
+2 -2
View File
@@ -25,5 +25,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("3.0.85.4")]
[assembly: AssemblyFileVersion("3.0.85.4")]
[assembly: AssemblyVersion("3.0.86.0")]
[assembly: AssemblyFileVersion("3.0.86.0")]
+13 -65
View File
@@ -119,18 +119,6 @@ namespace TGServerService.Properties {
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool ChatEnabled {
get {
return ((bool)(this["ChatEnabled"]));
}
set {
this["ChatEnabled"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
@@ -155,18 +143,6 @@ namespace TGServerService.Properties {
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int ChatProvider {
get {
return ((int)(this["ChatProvider"]));
}
set {
this["ChatProvider"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("NEEDS INITIALIZING")]
@@ -181,47 +157,7 @@ namespace TGServerService.Properties {
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<ArrayOfString xmlns:xsi=\"http://www.w3." +
"org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <s" +
"tring>theghostofwhibyl1</string>\r\n</ArrayOfString>")]
public global::System.Collections.Specialized.StringCollection ChatAdmins {
get {
return ((global::System.Collections.Specialized.StringCollection)(this["ChatAdmins"]));
}
set {
this["ChatAdmins"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<ArrayOfString xmlns:xsi=\"http://www.w3." +
"org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <s" +
"tring>#botbus</string>\r\n</ArrayOfString>")]
public global::System.Collections.Specialized.StringCollection ChatChannels {
get {
return ((global::System.Collections.Specialized.StringCollection)(this["ChatChannels"]));
}
set {
this["ChatChannels"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("#botbus")]
public string ChatAdminChannel {
get {
return ((string)(this["ChatAdminChannel"]));
}
set {
this["ChatAdminChannel"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("John Madden")]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string ChatProviderEntropy {
get {
return ((string)(this["ChatProviderEntropy"]));
@@ -278,5 +214,17 @@ namespace TGServerService.Properties {
this["ReattachPort"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int SettingsVersion {
get {
return ((int)(this["SettingsVersion"]));
}
set {
this["SettingsVersion"] = value;
}
}
}
}
+4 -22
View File
@@ -26,38 +26,17 @@
<Setting Name="ServerVisiblity" Type="System.Int32" Scope="User">
<Value Profile="(Default)">2</Value>
</Setting>
<Setting Name="ChatEnabled" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="DDAutoStart" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="PythonPath" Type="System.String" Scope="User">
<Value Profile="(Default)">C:\Python27</Value>
</Setting>
<Setting Name="ChatProvider" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="ChatProviderData" Type="System.String" Scope="User">
<Value Profile="(Default)">NEEDS INITIALIZING</Value>
</Setting>
<Setting Name="ChatAdmins" Type="System.Collections.Specialized.StringCollection" Scope="User">
<Value Profile="(Default)">&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
&lt;string&gt;theghostofwhibyl1&lt;/string&gt;
&lt;/ArrayOfString&gt;</Value>
</Setting>
<Setting Name="ChatChannels" Type="System.Collections.Specialized.StringCollection" Scope="User">
<Value Profile="(Default)">&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
&lt;string&gt;#botbus&lt;/string&gt;
&lt;/ArrayOfString&gt;</Value>
</Setting>
<Setting Name="ChatAdminChannel" Type="System.String" Scope="User">
<Value Profile="(Default)">#botbus</Value>
</Setting>
<Setting Name="ChatProviderEntropy" Type="System.String" Scope="User">
<Value Profile="(Default)">John Madden</Value>
<Value Profile="(Default)" />
</Setting>
<Setting Name="UpgradeRequired" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
@@ -71,5 +50,8 @@
<Setting Name="ReattachPort" Type="System.UInt16" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="SettingsVersion" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
</Settings>
</SettingsFile>
+13 -13
View File
@@ -113,7 +113,7 @@ namespace TGServerService
var BranchName = ts.b;
try
{
SendMessage(String.Format("REPO: {2} started: Cloning {0} branch of {1} ...", BranchName, RepoURL, Repository.IsValid(RepoPath) ? "Full reset" : "Setup"));
SendMessage(String.Format("REPO: {2} started: Cloning {0} branch of {1} ...", BranchName, RepoURL, Repository.IsValid(RepoPath) ? "Full reset" : "Setup"), ChatMessageType.DeveloperInfo);
try
{
DisposeRepo();
@@ -161,7 +161,7 @@ namespace TGServerService
}
Program.CopyDirectory(RepoData, StaticDataDir, null, true);
File.Copy(RepoPath + LibMySQLFile, StaticDirs + LibMySQLFile, true);
SendMessage("REPO: Clone complete!");
SendMessage("REPO: Clone complete!", ChatMessageType.DeveloperInfo);
TGServerService.WriteInfo("Repository {0}:{1} successfully cloned", TGServerService.EventID.RepoClone);
}
finally
@@ -172,7 +172,7 @@ namespace TGServerService
catch(Exception e)
{
SendMessage("REPO: Setup failed!");
SendMessage("REPO: Setup failed!", ChatMessageType.DeveloperInfo);
TGServerService.WriteWarning(String.Format("Failed to clone {2}:{0}: {1}", BranchName, e.ToString(), RepoURL), TGServerService.EventID.RepoCloneFail);
}
finally
@@ -297,7 +297,7 @@ namespace TGServerService
var result = LoadRepo();
if (result != null)
return result;
SendMessage("REPO: Checking out object: " + sha);
SendMessage("REPO: Checking out object: " + sha, ChatMessageType.DeveloperInfo);
try
{
var Opts = new CheckoutOptions()
@@ -307,13 +307,13 @@ namespace TGServerService
};
Commands.Checkout(Repo, sha, Opts);
var res = ResetNoLock(null);
SendMessage("REPO: Checkout complete!");
SendMessage("REPO: Checkout complete!", ChatMessageType.DeveloperInfo);
TGServerService.WriteInfo("Repo checked out " + sha, TGServerService.EventID.RepoCheckout);
return res;
}
catch (Exception e)
{
SendMessage("REPO: Checkout failed!");
SendMessage("REPO: Checkout failed!", ChatMessageType.DeveloperInfo);
TGServerService.WriteWarning(String.Format("Repo checkout of {0} failed: {1}", sha, e.ToString()), TGServerService.EventID.RepoCheckoutFail);
return e.ToString();
}
@@ -333,7 +333,7 @@ namespace TGServerService
{
case MergeStatus.Conflicts:
ResetNoLock(null);
SendMessage("REPO: Merge conflicted, aborted.");
SendMessage("REPO: Merge conflicted, aborted.", ChatMessageType.DeveloperInfo);
return "Merge conflict occurred.";
case MergeStatus.UpToDate:
return RepoErrorUpToDate;
@@ -349,7 +349,7 @@ namespace TGServerService
var result = LoadRepo();
if (result != null)
return result;
SendMessage(String.Format("REPO: Updating origin branch...({0})", reset ? "Hard Reset" : "Merge"));
SendMessage(String.Format("REPO: Updating origin branch...({0})", reset ? "Hard Reset" : "Merge"), ChatMessageType.DeveloperInfo);
try
{
if (Repo.Head == null || !Repo.Head.IsTracking)
@@ -383,7 +383,7 @@ namespace TGServerService
}
catch (Exception E)
{
SendMessage("REPO: Update failed!");
SendMessage("REPO: Update failed!", ChatMessageType.DeveloperInfo);
TGServerService.WriteWarning(String.Format("Repo{0} update failed", reset ? " hard" : ""), reset ? TGServerService.EventID.RepoHardUpdateFail : TGServerService.EventID.RepoMergeUpdateFail);
return E.ToString();
}
@@ -456,7 +456,7 @@ namespace TGServerService
var res = LoadRepo() ?? ResetNoLock(trackedBranch ? (Repo.Head.TrackedBranch ?? Repo.Head) : Repo.Head);
if (res == null)
{
SendMessage(String.Format("REPO: Hard reset to {0}branch", trackedBranch ? "tracked " : ""));
SendMessage(String.Format("REPO: Hard reset to {0}branch", trackedBranch ? "tracked " : ""), ChatMessageType.DeveloperInfo);
if (trackedBranch)
DeletePRList();
TGServerService.WriteInfo(String.Format("Repo branch reset{0}", trackedBranch ? " to tracked branch" : ""), trackedBranch ? TGServerService.EventID.RepoResetTracked : TGServerService.EventID.RepoReset);
@@ -518,7 +518,7 @@ namespace TGServerService
var result = LoadRepo();
if (result != null)
return result;
SendMessage(String.Format("REPO: {2}erging PR #{0}...", PRNumber, impliedUpdate ? "Test m" : "M"));
SendMessage(String.Format("REPO: {2}erging PR #{0}...", PRNumber, impliedUpdate ? "Test m" : "M"), ChatMessageType.DeveloperInfo);
try
{
//only supported with github
@@ -550,7 +550,7 @@ namespace TGServerService
branch = Repo.Branches[LocalBranchName];
if (branch == null)
{
SendMessage("REPO: PR could not be fetched. Does it exist?");
SendMessage("REPO: PR could not be fetched. Does it exist?", ChatMessageType.DeveloperInfo);
return String.Format("PR #{0} could not be fetched. Does it exist?", PRNumber);
}
@@ -600,7 +600,7 @@ namespace TGServerService
}
catch (Exception E)
{
SendMessage("REPO: PR merge failed!");
SendMessage("REPO: PR merge failed!", ChatMessageType.DeveloperInfo);
TGServerService.WriteWarning(String.Format("Failed to merge pull request #{0}: {1}", PRNumber, E.ToString()), TGServerService.EventID.RepoPRMergeFail);
return E.ToString();
}
+15 -2
View File
@@ -40,7 +40,7 @@ namespace TGServerService
DDWatchdogStarted = 2500,
ChatSend = 2600,
ChatBroadcast = 2700,
ChatAdminBroadcast = 2800,
//ChatAdminBroadcast = 2800,
ChatDisconnectFail = 2900,
TopicSent = 3000,
TopicFailed = 3100,
@@ -73,6 +73,8 @@ namespace TGServerService
ServiceShutdownFail = 6100,
WorldReboot = 6200,
ServerUpdateApplied = 6300,
ChatBroadcastFail = 6400,
IRCLogModes = 6500,
}
static TGServerService ActiveService; //So everyone else can write to our eventlog
@@ -92,7 +94,13 @@ namespace TGServerService
ActiveService.EventLog.WriteEntry(message, EventLogEntryType.Warning, (int)id);
}
ServiceHost host; //the WCF host
ServiceHost host; //the WCF host
void MigrateSettings(int oldVersion, int newVersion)
{
if (oldVersion == newVersion && newVersion == 0) //chat refactor
Properties.Settings.Default.ChatProviderData = "NEEDS INITIALIZING"; //reset chat settings to be safe
}
//you should seriously not add anything here
//Use OnStart instead
@@ -102,7 +110,12 @@ namespace TGServerService
{
if (Properties.Settings.Default.UpgradeRequired)
{
var newVersion = Properties.Settings.Default.SettingsVersion;
Properties.Settings.Default.Upgrade();
var oldVersion = Properties.Settings.Default.SettingsVersion;
MigrateSettings(oldVersion, newVersion);
Properties.Settings.Default.UpgradeRequired = false;
Properties.Settings.Default.Save();
}
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="TG Station Server" Language="1033" Version="3.0.85.4" Manufacturer="/tg/station 13" UpgradeCode="663badae-ddca-4aa9-8f3f-3b7b20332eac">
<Product Id="*" Name="TG Station Server" Language="1033" Version="3.0.86.0" Manufacturer="/tg/station 13" UpgradeCode="663badae-ddca-4aa9-8f3f-3b7b20332eac">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
+234 -106
View File
@@ -2,13 +2,14 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Web.Script.Serialization;
namespace TGServiceInterface
{
/// <summary>
/// The type of chat provider
/// </summary>
public enum TGChatProvider
public enum TGChatProvider : int
{
/// <summary>
/// IRC chat provider
@@ -17,7 +18,30 @@ namespace TGServiceInterface
/// <summary>
/// Discord chat provider
/// </summary>
Discord,
Discord = 1,
}
/// <summary>
/// Supported irc permission modes
/// </summary>
public enum IRCMode : int
{
/// <summary>
/// +
/// </summary>
Voice,
/// <summary>
/// %
/// </summary>
Halfop,
/// <summary>
/// @
/// </summary>
Op,
/// <summary>
/// ~
/// </summary>
Owner,
}
/// <summary>
@@ -28,6 +52,16 @@ namespace TGServiceInterface
[KnownType(typeof(TGDiscordSetupInfo))]
public class TGChatSetupInfo
{
const int AdminListIndex = 0;
const int AdminModeIndex = 1;
const int AdminChannelIndex = 2;
const int DevChannelIndex = 3;
const int WDChannelIndex = 4;
const int GameChannelIndex = 5;
const int ProviderIndex = 6;
const int EnabledIndex = 7;
protected const int BaseIndex = 8;
protected readonly bool InitializeFields;
/// <summary>
/// Constructs a TGChatSetupInfo from optional past data
/// </summary>
@@ -35,10 +69,56 @@ namespace TGServiceInterface
/// <param name="numFields">The number of fields in this chat provider</param>
protected TGChatSetupInfo(TGChatSetupInfo baseInfo, int numFields)
{
DataFields = baseInfo != null ? baseInfo.DataFields : new List<string>(numFields);
if (baseInfo == null)
numFields += BaseIndex;
InitializeFields = baseInfo == null || baseInfo.DataFields.Count != numFields;
if (InitializeFields)
{
DataFields = new List<string>(numFields);
for (var I = 0; I < numFields; ++I)
DataFields.Add(null);
AdminList = new List<string>();
AdminChannels = new List<string>();
DevChannels = new List<string>();
GameChannels = new List<string>();
WatchdogChannels = new List<string>();
AdminsAreSpecial = false;
Enabled = false;
}
else
DataFields = baseInfo.DataFields;
}
TGChatSetupInfo Specialize()
{
switch (Provider)
{
case TGChatProvider.IRC:
return new TGIRCSetupInfo(this);
case TGChatProvider.Discord:
return new TGDiscordSetupInfo(this);
default:
throw new Exception("Invalid provider!");
}
}
//trims and adds the leading #
protected virtual string SanitizeChannelName(string working)
{
return Specialize().SanitizeChannelName(working);
}
void SanitizeChannelNames(IList<string> working)
{
for (var I = 0; I < working.Count; ++I)
if (String.IsNullOrWhiteSpace(working[I]))
{
working.RemoveAt(I);
--I;
}
else
working[I] = SanitizeChannelName(working[I].Trim());
}
/// <summary>
@@ -46,17 +126,91 @@ namespace TGServiceInterface
/// </summary>
/// <param name="DeserializedData">The data</param>
/// <param name="provider">The chat provider</param>
public TGChatSetupInfo(IList<string> DeserializedData, TGChatProvider provider)
public TGChatSetupInfo(IList<string> DeserializedData)
{
DataFields = DeserializedData;
Provider = provider;
}
/// <summary>
/// The list of admin entries
/// </summary>
public IList<string> AdminList
{
get { return new JavaScriptSerializer().Deserialize<IList<string>>(DataFields[AdminListIndex]); }
set { DataFields[AdminListIndex] = new JavaScriptSerializer().Serialize(value); }
}
/// <summary>
/// If AdminList corresponds to a Provider specific recognization method
/// </summary>
public bool AdminsAreSpecial
{
get { return Convert.ToBoolean(DataFields[AdminModeIndex]); }
set { DataFields[AdminModeIndex] = Convert.ToString(value); }
}
/// <summary>
/// The channels from which admin commands/messages can be sent/received
/// </summary>
public IList<string> AdminChannels
{
get { return new JavaScriptSerializer().Deserialize<IList<string>>(DataFields[AdminChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[AdminChannelIndex] = new JavaScriptSerializer().Serialize(value);
}
}
/// <summary>
/// The channels to which repo and compile messages are sent
/// </summary>
public IList<string> DevChannels
{
get { return new JavaScriptSerializer().Deserialize<IList<string>>(DataFields[DevChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[DevChannelIndex] = new JavaScriptSerializer().Serialize(value);
}
}
/// <summary>
/// The channels to which watchdog messages are sent
/// </summary>
public IList<string> WatchdogChannels
{
get { return new JavaScriptSerializer().Deserialize<IList<string>>(DataFields[WDChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[WDChannelIndex] = new JavaScriptSerializer().Serialize(value);
}
}
/// <summary>
/// The channels to which game messages are sent
/// </summary>
public IList<string> GameChannels
{
get { return new JavaScriptSerializer().Deserialize<IList<string>>(DataFields[GameChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[GameChannelIndex] = new JavaScriptSerializer().Serialize(value);
}
}
/// <summary>
/// If this chat provider is enabled
/// </summary>
public bool Enabled
{
get { return Convert.ToBoolean(DataFields[EnabledIndex]); }
set { DataFields[EnabledIndex] = Convert.ToString(value); }
}
/// <summary>
/// The type of provider
/// </summary>
[DataMember]
public TGChatProvider Provider { get; protected set; }
public TGChatProvider Provider
{
get { return (TGChatProvider)Convert.ToInt32(DataFields[ProviderIndex]); }
set { DataFields[ProviderIndex] = Convert.ToString((int)value); }
}
/// <summary>
/// Raw access to the underlying data
@@ -67,6 +221,7 @@ namespace TGServiceInterface
/// <summary>
/// Chat provider for IRC
/// Admin entries should be user nicknames in normal mode or required flags in special mode
/// </summary>
[DataContract]
public class TGIRCSetupInfo : TGChatSetupInfo
@@ -76,7 +231,8 @@ namespace TGServiceInterface
const int NickIndex = 2;
const int AuthTargetIndex = 3;
const int AuthMessageIndex = 4;
const int FieldsLen = 5;
const int AuthLevelIndex = 5;
const int FieldsLen = 6;
/// <summary>
/// Construct IRC setup info from optional generic info. Defaults to TGS3 on rizons IRC server
@@ -85,54 +241,78 @@ namespace TGServiceInterface
public TGIRCSetupInfo(TGChatSetupInfo baseInfo = null) : base(baseInfo, FieldsLen)
{
Provider = TGChatProvider.IRC;
if (baseInfo == null)
if (InitializeFields)
{
Nickname = "TGS3";
URL = "irc.rizon.net";
Port = 6667;
AuthTarget = "";
AuthMessage = "";
AdminsAreSpecial = true;
AuthLevel = IRCMode.Op;
}
}
protected override string SanitizeChannelName(string working)
{
if (working[0] != '#')
return "#" + working;
return working;
}
/// <summary>
/// The port of the IRC server
/// </summary>
public ushort Port {
get { return Convert.ToUInt16(DataFields[PortIndex]); }
set { DataFields[PortIndex] = value.ToString(); }
get { return Convert.ToUInt16(DataFields[BaseIndex + PortIndex]); }
set { DataFields[BaseIndex + PortIndex] = value.ToString(); }
}
/// <summary>
/// The URL of the IRC server
/// </summary>
public string URL
{
get { return DataFields[URLIndex]; }
set { DataFields[URLIndex] = value; }
get { return DataFields[BaseIndex + URLIndex]; }
set { DataFields[BaseIndex + URLIndex] = value; }
}
/// <summary>
/// The nickname of the IRC bot
/// </summary>
public string Nickname
{
get { return DataFields[NickIndex]; }
set { DataFields[NickIndex] = value; }
get { return DataFields[BaseIndex + NickIndex]; }
set { DataFields[BaseIndex + NickIndex] = value; }
}
/// <summary>
/// The target for sending authentication messages
/// </summary>
public string AuthTarget
{
get { return DataFields[AuthTargetIndex]; }
set { DataFields[AuthTargetIndex] = value; }
get { return DataFields[BaseIndex + AuthTargetIndex]; }
set { DataFields[BaseIndex + AuthTargetIndex] = value; }
}
/// <summary>
/// The authentication message
/// </summary>
public string AuthMessage
{
get { return DataFields[AuthMessageIndex]; }
set { DataFields[AuthMessageIndex] = value; }
get { return DataFields[BaseIndex + AuthMessageIndex]; }
set { DataFields[BaseIndex + AuthMessageIndex] = value; }
}
/// <summary>
/// The minimum mode required to use admin bot commands when in special auth mode
/// </summary>
public IRCMode AuthLevel
{
get { return (IRCMode)Convert.ToInt32(DataFields[BaseIndex + AuthLevelIndex]); }
set { DataFields[BaseIndex + AuthLevelIndex] = Convert.ToString((int)value); }
}
}
/// <summary>
/// Chat provider for Discord
/// Admin entires should be user ids in normal mode or group ids in special mode
/// </summary>
[DataContract]
public class TGDiscordSetupInfo : TGChatSetupInfo
{
@@ -145,8 +325,20 @@ namespace TGServiceInterface
public TGDiscordSetupInfo(TGChatSetupInfo baseInfo = null) : base(baseInfo, FieldsLen)
{
Provider = TGChatProvider.Discord;
if (baseInfo == null)
BotToken = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
if (InitializeFields)
BotToken = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; //needless to say, this is fake
}
protected override string SanitizeChannelName(string working)
{
try
{
Convert.ToUInt64(working);
}
catch
{
throw new Exception("Invalid Discord channel ID!");
}
return working;
}
/// <summary>
@@ -154,109 +346,45 @@ namespace TGServiceInterface
/// </summary>
public string BotToken
{
get { return DataFields[BotTokenIndex]; }
set { DataFields[BotTokenIndex] = value; }
get { return DataFields[BaseIndex + BotTokenIndex]; }
set { DataFields[BaseIndex + BotTokenIndex] = value; }
}
}
/// <summary>
/// Used internally
/// </summary>
[ServiceContract]
public interface ITGChatBase
{
/// <summary>
/// Set the chat provider info
/// </summary>
/// <param name="info"></param>
[OperationContract]
string SetProviderInfo(TGChatSetupInfo info);
/// <summary>
/// Set the channels to join
/// </summary>
/// <param name="channels">The names of the channels to join and broadcast to</param>
/// <param name="adminchannel">The name of the channel which accepts admin commands. Need not be in the channels parameter</param>
[OperationContract]
void SetChannels(string[] channels = null, string adminchannel = null);
/// <summary>
/// Checks connection status
/// </summary>
/// <returns>true if connected, false otherwise</returns>
[OperationContract]
bool Connected();
/// <summary>
/// Reconnect to the chat service
/// </summary>
/// <returns>null on success, error message on failure</returns>
[OperationContract]
string Reconnect();
/// <summary>
/// Send a message to the chat service
/// </summary>
/// <param name="msg">The message to send</param>
/// <param name="adminOnly">true if the message should only be sent to the admin channel, false otherwise</param>
/// <returns></returns>
[OperationContract]
string SendMessage(string msg, bool adminOnly = false);
}
/// <summary>
/// Interface for handling chat bot
/// </summary>
[ServiceContract]
public interface ITGChat : ITGChatBase
public interface ITGChat
{
/// <summary>
/// Set the chat provider info
/// </summary>
/// <param name="info">The info to set</param>
[OperationContract]
string SetProviderInfo(TGChatSetupInfo info);
/// <summary>
/// Returns the chat provider info
/// </summary>
/// <returns></returns>
/// <param name="providerType">The type of provider to get info for</param>
/// <returns>The chat provider info for the selected provider</returns>
[OperationContract]
TGChatSetupInfo ProviderInfo();
/// <summary>
/// Get channels we are set to connect to, includes the admin channel
/// </summary>
/// <returns>An array of channels</returns>
[OperationContract]
string[] Channels();
IList<TGChatSetupInfo> ProviderInfos();
/// <summary>
/// Get the channel from which secure commands can be sent
/// Checks connection status
/// </summary>
/// <returns>The name of the channel</returns>
/// <param name="providerType">The type of provider to check if connected</param>
/// <returns>true if connected, false otherwise</returns>
[OperationContract]
string AdminChannel();
bool Connected(TGChatProvider providerType);
/// <summary>
/// Check if the configuration allows the IRC bot
/// Reconnect to the chat service
/// </summary>
/// <returns>true if the bot is enabled, false otherwise</returns>
/// <param name="providerType">The type of provider to reconnect</param>
/// <returns>null on success, error message on failure</returns>
[OperationContract]
bool Enabled();
/// <summary>
/// Enable or disable the chat provider
/// </summary>
/// <param name="enable">true to enable, false to disable</param>
/// <returns>null on success, connection error message on failure</returns>
[OperationContract]
string SetEnabled(bool enable);
/// <summary>
/// Print out the users who can use admin restricted commands over IRC from the admin channel
/// </summary>
/// <returns>A list of irc nicknames</returns>
[OperationContract]
string[] ListAdmins();
/// <summary>
/// Set the users who can use admin restricted commands over IRC from the admin channel
/// </summary>
/// <param name="nicknames">The list of irc admin nicknames</param>
[OperationContract]
void SetAdmins(string[] nicknames);
string Reconnect(TGChatProvider providerType);
}
}
@@ -25,5 +25,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("3.0.85.4")]
[assembly: AssemblyFileVersion("3.0.85.4")]
[assembly: AssemblyVersion("3.0.86.0")]
[assembly: AssemblyFileVersion("3.0.86.0")]
@@ -36,6 +36,7 @@
<ItemGroup>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Web.Extensions" />
</ItemGroup>
<ItemGroup>
<Compile Include="Byond.cs" />