diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index d1ae438525c..3074c797f6e 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -11,8 +11,9 @@ #define CHAT_PRAYER 256 #define CHAT_RADIO 512 #define MEMBER_PUBLIC 1024 +#define CHAT_PULLR 2048 -#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|MEMBER_PUBLIC) +#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|MEMBER_PUBLIC|CHAT_PULLR) #define BE_TRAITOR 1 #define BE_OPERATIVE 2 diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index fac874e70d7..b277b48eda6 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -102,6 +102,9 @@ var/rename_cyborg = 0 var/ooc_during_round = 0 + var/comms_key = "default_pwd" //Server API key + var/comms_allowed = 0 //By default, the server does not allow messages to be sent to it, unless the key is strong enough (this is to prevent misconfigured servers from becoming victims) + //Used for modifying movement speed for mobs. //Unversal modifiers var/run_speed = 0 @@ -266,6 +269,10 @@ Tickcomp = 1 if("automute_on") automute_on = 1 + if("comms_key") + comms_key = value + if(value != "default_pwd" && length(value) > 6) //It's the default value or less than 6 characters long, warn badmins + comms_allowed = 1 else diary << "Unknown setting in configuration: '[name]'" diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 1f8cbdc07b7..d87d0e987a4 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -130,6 +130,8 @@ var/next_external_rsc = 0 if(holder) add_admin_verbs() admin_memo_show() + if((config.comms_key == "default_pwd" || length(config.comms_key) <= 6) && config.comms_allowed) //It's the default value or less than 6 characters long, but it somehow didn't disable comms. + src << "The server's API key is either too short or is the default value! Consider changing it immediately!" log_client_to_db() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 0c41ac80b17..7dcd76da6e3 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -208,6 +208,7 @@ datum/preferences dat += "Play lobby music: [(toggles & SOUND_LOBBY) ? "Yes" : "No"]
" dat += "Ghost ears: [(toggles & CHAT_GHOSTEARS) ? "Nearest Creatures" : "All Speech"]
" dat += "Ghost sight: [(toggles & CHAT_GHOSTSIGHT) ? "Nearest Creatures" : "All Emotes"]
" + dat += "Pull requests: [(toggles & CHAT_PULLR) ? "Yes" : "No"]
" if(config.allow_Metadata) dat += "OOC Notes: Edit
" @@ -684,7 +685,8 @@ datum/preferences if("ghost_sight") toggles ^= CHAT_GHOSTSIGHT - + if("pull_requests") + toggles ^= CHAT_PULLR if("save") save_preferences() save_character() diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm index 31eb62cd73d..2fc6ef47c14 100644 --- a/code/modules/client/preferences_toggles.dm +++ b/code/modules/client/preferences_toggles.dm @@ -55,6 +55,15 @@ src << "You will [(prefs.toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat." feedback_add_details("admin_verb","TP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/client/verb/togglePRs() + set name = "Show/Hide Pull Request Announcements" + set category = "Preferences" + set desc = "Toggles receiving a notification when new pull requests are created." + prefs.toggles ^= CHAT_PULLR + prefs.save_preferences() + src << "You will [(prefs.toggles & CHAT_PULLR) ? "now" : "no longer"] see new pull request announcements." + feedback_add_details("admin_verb","TPullR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + /client/verb/toggletitlemusic() set name = "Hear/Silence LobbyMusic" set category = "Preferences" diff --git a/code/world.dm b/code/world.dm index b620dfeff18..506b0cdd7b4 100644 --- a/code/world.dm +++ b/code/world.dm @@ -160,7 +160,17 @@ s["map_name"] = map_name ? map_name : "Unknown" return list2params(s) - + else if (copytext(T,1,9) == "announce") + var/input[] = params2list(T) + if(config.comms_allowed) + if(input["key"] != config.comms_key) + return "Bad Key" + else + #define CHAT_PULLR 2048 + for(var/client/C in clients) + if(C.prefs && (C.prefs.toggles & CHAT_PULLR)) + C << "PR: [input["announce"]]" + #undef CHAT_PULLR /world/Reboot(var/reason) #ifdef dellogging diff --git a/config/config.txt b/config/config.txt index 91dabaf17c1..8f71955fac1 100644 --- a/config/config.txt +++ b/config/config.txt @@ -144,3 +144,6 @@ TICKCOMP 0 ## Comment this out to disable automuting #AUTOMUTE_ON + +## Communication key for receiving data through world/Topic(), you don't want to give this out +#COMMS_KEY default_pwd \ No newline at end of file diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm index a425073e7f1..69fe141385b 100644 --- a/interface/stylesheet.dm +++ b/interface/stylesheet.dm @@ -50,6 +50,7 @@ h1.alert, h2.alert {color: #000000;} .userdanger {color: #ff0000; font-weight: bold;} .danger {color: #ff0000;} .warning {color: #ff0000; font-style: italic;} +.announce {color: #228b22; font-weight: bold;} .rose {color: #ff5050;} .info {color: #0000CC;} .notice {color: #000099;} diff --git a/tools/PR_announcer_bot/Meebey.SmartIrc4net.dll b/tools/PR_announcer_bot/Meebey.SmartIrc4net.dll new file mode 100644 index 00000000000..851c94700f7 Binary files /dev/null and b/tools/PR_announcer_bot/Meebey.SmartIrc4net.dll differ diff --git a/tools/PR_announcer_bot/StarkSoftProxy.dll b/tools/PR_announcer_bot/StarkSoftProxy.dll new file mode 100644 index 00000000000..a5210bed38a Binary files /dev/null and b/tools/PR_announcer_bot/StarkSoftProxy.dll differ diff --git a/tools/PR_announcer_bot/config.txt b/tools/PR_announcer_bot/config.txt new file mode 100644 index 00000000000..dfaa1046567 --- /dev/null +++ b/tools/PR_announcer_bot/config.txt @@ -0,0 +1,7 @@ +serverip = 127.0.0.1 //SS13 server IP +serverport = 7812 +commskey = this_is_a_test_key +GitHub_bot_name = testbot_github //It'll get the data from this bot +IRC_bot_name = testbot_BYOND //This'll be our name +IRC_server = irc.rizon.net:6670 //format - server:port +IRC_channel = #ircchannel \ No newline at end of file diff --git a/tools/PR_announcer_bot/output.txt b/tools/PR_announcer_bot/output.txt new file mode 100644 index 00000000000..07db6152b6d --- /dev/null +++ b/tools/PR_announcer_bot/output.txt @@ -0,0 +1 @@ +0131022900006397110110111117110991016191451161034511511697116105111110933286105115116978079876532111112101110101100321121171081083211410111311710111511632651001001153211511110910132981111141033210210197116117114101115329710811511132102105120101115321151111091013211511611710210246323551485248583210997115116101114464646106117115116951111101019510911111410195116101115116951001111101169510710510810895109101413210411611611211558474710310511610411798469911110947116103115116971161051111104745116103451151169711610511111047112117108108475148524832381071011216111610410511595105115959795116101115116951071011210 diff --git a/tools/PR_announcer_bot/sendkeys_ss13.exe b/tools/PR_announcer_bot/sendkeys_ss13.exe new file mode 100644 index 00000000000..4f9332811d9 Binary files /dev/null and b/tools/PR_announcer_bot/sendkeys_ss13.exe differ diff --git a/tools/PR_announcer_bot/sendkeys_ss13.sln b/tools/PR_announcer_bot/sendkeys_ss13.sln new file mode 100644 index 00000000000..0786a395f6a --- /dev/null +++ b/tools/PR_announcer_bot/sendkeys_ss13.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sendkeys_ss13", "sendkeys_ss13\sendkeys_ss13.csproj", "{5D939FCB-F326-4B9B-8CEC-B2538126392E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5D939FCB-F326-4B9B-8CEC-B2538126392E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D939FCB-F326-4B9B-8CEC-B2538126392E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D939FCB-F326-4B9B-8CEC-B2538126392E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D939FCB-F326-4B9B-8CEC-B2538126392E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/tools/PR_announcer_bot/sendkeys_ss13/App.config b/tools/PR_announcer_bot/sendkeys_ss13/App.config new file mode 100644 index 00000000000..72a71af99a7 --- /dev/null +++ b/tools/PR_announcer_bot/sendkeys_ss13/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/tools/PR_announcer_bot/sendkeys_ss13/Meebey.SmartIrc4net.dll b/tools/PR_announcer_bot/sendkeys_ss13/Meebey.SmartIrc4net.dll new file mode 100644 index 00000000000..851c94700f7 Binary files /dev/null and b/tools/PR_announcer_bot/sendkeys_ss13/Meebey.SmartIrc4net.dll differ diff --git a/tools/PR_announcer_bot/sendkeys_ss13/Program.cs b/tools/PR_announcer_bot/sendkeys_ss13/Program.cs new file mode 100644 index 00000000000..8d7d5856a98 --- /dev/null +++ b/tools/PR_announcer_bot/sendkeys_ss13/Program.cs @@ -0,0 +1,341 @@ +////////////////////////////////////////////////////////////////// +/////GitHub pull request announcer bot for IRC//////////////////// +/////Made by VistaPOWA for the /tg/station 13 code project./////// +/////This software is licensed under GPL3.//////////////////////// +/////Prequisites: Meebey's SmartIrc4Net library (incl, under GPL)/ +///// StarkSoft Proxy library (incl, under GPL)/////// +/////Usage: Edit the config.txt file to match the settings//////// +/////of your server's. Start the executable. Set up a Github hook/ +/////if you hadn't before to send IRC notifications to the//////// +/////channel of your choosing. Leave it running.////////////////// +/////IT IS PREFERABLE IF YOU RAN THIS LOCALLY. YOUR SERVER'S////// +/////API/COMMS KEY WILL BE SENT PLAINTEXT! ENSURE THAT THE API//// +/////KEY IS NOT PUBLICALLY AVAILABLE! IF LEAKED, CHANGE IT./////// +/////Support available @ Rizon's #coderbus, ask for VistaPOWA.//// +////////////////////////////////////////////////////////////////// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Meebey.SmartIrc4net; +using System.Net; +using System.Net.Sockets; +using System.IO; + +namespace sendkeys_ss13 +{ + public class Program + { + //default values + public static string serverIP = "127.0.0.1"; + public static int serverPort = 11111; + public static string commskey = "this_is_a_test_key"; + public static string Github_bot_name = "testbot_github"; + public static string IRC_bot_name = "testbot"; + public static string IRC_server = "test.net"; + public static int IRC_port = 11111; + public static string IRC_channel = "#channel"; + + public static string[] merge_archive; + public static bool mergeflag = false; + + public static IrcClient irc = new IrcClient(); + + public static int IRCReconnectAttempt = 0; + public static void Main(string[]args) + { + ReadConf(); + irc.OnChannelMessage += new IrcEventHandler(OnChannelMessage); + irc.SupportNonRfc = true; + try + { + irc.Connect(IRC_server, IRC_port); + IRCReconnectAttempt = 0; + } + catch (Exception) + { + IRCReconnectAttempt++; + if (IRCReconnectAttempt <= 3) + { + Console.WriteLine("IRC server is unavaible at the moment. Reconnect attempt {0}...", IRCReconnectAttempt); + System.Threading.Thread.Sleep(3000); //Reconnecting after 5 seconds. + Main(args); + } + else + { + Console.WriteLine("IRC server unreachable. Please check your configuration file."); + Console.ReadLine(); + return; + } + } + Console.WriteLine("Connected to IRC"); + irc.Login(IRC_bot_name, IRC_bot_name); + Console.WriteLine("Logged in"); + irc.RfcJoin(IRC_channel); + Console.WriteLine("Joining {0}", IRC_channel); + irc.Listen(); + } + + public static void ReadConf() + { + if (File.Exists("config.txt")) + { + StreamReader reader = new StreamReader("config.txt"); + string[] line = reader.ReadLine().Split(' '); + if (line[2] != null) + { + Match match1 = Regex.Match(line[2], @"(\d{1,3}.?){4}"); //rudimentary IP validation + if (match1.Success) + { + serverIP = line[2]; + Console.WriteLine("Read IP: " + serverIP); + } + else + { + Console.WriteLine("IP cannot be validated."); + return; + } + } + line = reader.ReadLine().Split(' '); + if (line[2] != null) + { + Match match2 = Regex.Match(line[2], @"\d{1,5}"); //rudimentary port validation + if (match2.Success && (Convert.ToInt32(line[2]) < 65535)) + { + serverPort = Convert.ToInt32(line[2]); + Console.WriteLine("Read port: " + serverPort); + } + else + { + Console.WriteLine("Port cannot be validated."); + return; + } + } + line = reader.ReadLine().Split(' '); + if (line[2] != null) + { + commskey = line[2]; + Console.WriteLine("Commskey read."); + } + else + { + Console.WriteLine("No Commskey!"); + return; + } + line = reader.ReadLine().Split(' '); + if (line[2] != null) + { + Github_bot_name = line[2]; + Console.WriteLine("Read Github bot name: " + Github_bot_name); + } + else + { + Console.WriteLine("No botname found."); + return; + } + line = reader.ReadLine().Split(' '); + if (line[2] != null) + { + IRC_bot_name = line[2]; + Console.WriteLine("Read IRC bot name: " + Github_bot_name); + } + else + { + Console.WriteLine("No botname found."); + return; + } + line = reader.ReadLine().Split(' '); + if (line[2] != null) + { + Match match3 = Regex.Match(line[2], @"(.+)\:(\d{1,5})"); //rudimentary port validation + if (match3.Success) + { + IRC_server = Convert.ToString(match3.Groups[1]); + Int32.TryParse(Convert.ToString(match3.Groups[2]), out IRC_port); + Console.WriteLine("Read IRC server: " + IRC_server + ":" + Convert.ToString(IRC_port)); + } + else + { + Console.WriteLine("Server:port invalid."); + return; + } + } + line = reader.ReadLine().Split(' '); + if (line[2] != null) + { + IRC_channel = line[2]; + Console.WriteLine("Read channel: " + IRC_channel); + } + else + { + Console.WriteLine("No channel found."); + return; + } + reader.Close(); + } + else + { + Console.WriteLine("Config file doesn't exist, using defaults"); + return; + } + } + + public static void OnChannelMessage(object sender, IrcEventArgs e) + { + if (e.Data.Nick == Github_bot_name) + { + string[] msg = e.Data.Message.Split(' '); + for (int i = 0; i < msg.Length; i++) + { + msg[i] = Regex.Replace(msg[i], @"[\x02\x1F\x0F\x16]|\x03(\d\d?(,\d\d?)?)?", String.Empty); //Sanitizing color codes + msg[i] = Regex.Replace(msg[i], @"[\\\&\=\;\<\>]", " "); //Filtering out some iffy characters + } + FormMessage(msg); + } + } + + private static void FormMessage(string[] msg, bool ShortenedURL = false) + { + using (StreamWriter output = new StreamWriter("output.txt")) + { + if (msg[2] == "closed") + { + merge_archive = msg; + mergeflag = true; + output.Close(); + } + else if ((msg[2] == "opened" || mergeflag) && msg[1] != "meant:") //Either we open a new PR or a PR was closed in the last message. Also protection from Whibyl's correction thingy! + { + if (msg[2] == "pushed") + { + msg = merge_archive; //We copy the "close" message and replace "close" with merge! The players won't know what him 'em! + msg[2] = "merged"; + } + mergeflag = false; + merge_archive = null; + string URL = msg[msg.Length - 1]; + if(!ShortenedURL) + URL = ShortenURL(URL); + msg[5] = "" + msg[5] + ""; + msg[0] = ""; //Repo name + msg[msg.Length - 1] = ""; //The URL itself + msg[msg.Length - 2] = ""; //Branch info + byte[] PACKETS = CreatePacket(msg); + PACKETS[1] = 0x83; + int len = 0; + for (int i = 1; i < msg.Length - 1; i++) + { + len += msg[i].Length + 1; //The length of the word and the space following it. + Console.Write(msg[i] + " "); + } + len -= 1; //Compensating for the lack of space at the end. + len += 14 + commskey.Length + 6; //Argument names + Commskey length + 6 null bytes + PACKETS[3] = (byte)len; + StringBuilder test = new StringBuilder(); + for (int i = 0; i < PACKETS.Length; i++) + { + test.Append(Convert.ToString(PACKETS[i])); + } + output.WriteLine(Convert.ToString(test)); + SendPacket(output, PACKETS); + } + else + { + mergeflag = false; + merge_archive = null; + output.Close(); + } + } + } + + public static int ServerReconnectAttempt = 0; + private static void SendPacket(StreamWriter output, byte[] PACKETS) + { + Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + IPEndPoint ip = new IPEndPoint(IPAddress.Parse(serverIP), serverPort); + try + { + server.Connect(ip); + server.Send(PACKETS); + Console.WriteLine("- sent ;)"); + output.Close(); + Console.WriteLine(); + } + catch (Exception) + { + ServerReconnectAttempt++; + if(ServerReconnectAttempt <= 5) + { + Console.WriteLine("Server is not available at the moment. Reconnect attempt {0}...", ServerReconnectAttempt); + System.Threading.Thread.Sleep(5000); //Reconnecting after 5 seconds. + SendPacket(output, PACKETS); + } + else + { + output.Close(); + Console.WriteLine("Server appears to be down for good. Press ENTER when you have restarted the server to continue."); + Console.ReadLine(); + ServerReconnectAttempt = 0; + SendPacket(output, PACKETS); + } + } + } + + public static int GitReconnectAttempt = 0; + private static string ShortenURL(string URL) //derived from GitIoSharp by dimapasko + { + WebRequest request = WebRequest.Create("http://git.io"); + request.ContentType = "application/x-www-form-urlencoded"; + request.Method = "POST"; + byte[] packet = Encoding.ASCII.GetBytes("url=" + URL); + request.ContentLength = packet.Length; + try + { + using (Stream stream = request.GetRequestStream()) + { + stream.Write(packet, 0, packet.Length); + GitReconnectAttempt = 0; + } + } + catch (Exception) + { + GitReconnectAttempt++; + if (GitReconnectAttempt <= 3) + { + Console.WriteLine("Git.IO is not available at the moment. Reconnect attempt {0}...", GitReconnectAttempt); + System.Threading.Thread.Sleep(3000); //Attempt to reconnect after 3 seconds. + ShortenURL(URL); + } + else + { + Console.WriteLine("Git.IO is down. Returning long URL."); + GitReconnectAttempt = 0; //Reset counter + return URL; + } + } + + HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + return Convert.ToString(new Uri(response.Headers[HttpResponseHeader.Location])); + } + + private static byte[] CreatePacket(string[] msg) + { + StringBuilder packet = new StringBuilder(); + packet.Append((char)'\x00', 8); //packet[1] is 0x83, packet[3] contain length + packet.Append("?announce="); + for (int i = 1; i < msg.Length - 1; i++) + { + if(i == msg.Length - 2) + packet.Append(msg[i]); + else + packet.Append(msg[i] + " "); + } + packet.Append("&key="); + packet.Append(commskey); + packet.Append((char)'\x00'); + return Encoding.ASCII.GetBytes(packet.ToString()); + } + } +} diff --git a/tools/PR_announcer_bot/sendkeys_ss13/Properties/AssemblyInfo.cs b/tools/PR_announcer_bot/sendkeys_ss13/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..669b610fc09 --- /dev/null +++ b/tools/PR_announcer_bot/sendkeys_ss13/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("sendkeys_ss13")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("sendkeys_ss13")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("197641d3-a97a-4255-b833-d6481ca4ef54")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// 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("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/tools/PR_announcer_bot/sendkeys_ss13/StarkSoftProxy.dll b/tools/PR_announcer_bot/sendkeys_ss13/StarkSoftProxy.dll new file mode 100644 index 00000000000..a5210bed38a Binary files /dev/null and b/tools/PR_announcer_bot/sendkeys_ss13/StarkSoftProxy.dll differ diff --git a/tools/PR_announcer_bot/sendkeys_ss13/sendkeys_ss13.csproj b/tools/PR_announcer_bot/sendkeys_ss13/sendkeys_ss13.csproj new file mode 100644 index 00000000000..07e25db3b15 --- /dev/null +++ b/tools/PR_announcer_bot/sendkeys_ss13/sendkeys_ss13.csproj @@ -0,0 +1,69 @@ + + + + + Debug + AnyCPU + {5D939FCB-F326-4B9B-8CEC-B2538126392E} + Exe + Properties + sendkeys_ss13 + sendkeys_ss13 + v4.0 + 512 + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + .\Meebey.SmartIrc4net.dll + + + .\StarkSoftProxy.dll + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file