├── .vs └── SimpleIRCLib │ └── v14 │ └── .suo ├── FormExample ├── Home.md ├── App.config ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── Program.cs ├── FormExample.csproj ├── FormExample.md ├── DebugForm.resx ├── DebugForm.cs ├── IrcClientForm.resx ├── DebugForm.Designer.cs ├── IrcClientForm.Designer.cs └── IrcClientForm.cs ├── IrcLibTest ├── App.config ├── Properties │ └── AssemblyInfo.cs ├── IrcLibTest.csproj └── Program.cs ├── SimpleIRCLib ├── Home.md ├── SimpleIRCLib.csproj ├── IrcEventArgs.cs ├── DCCEventArgs.cs ├── SimpleIRCLib.md ├── SimpleIRC.cs ├── IrcCommands.cs ├── RFC1459Codes.cs ├── DCCClient.cs └── IrcClient.cs ├── LICENSE ├── SimpleIRCLib.sln ├── gitignore ├── .gitignore └── README.md /.vs/SimpleIRCLib/v14/.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EldinZenderink/SimpleIRCLib/HEAD/.vs/SimpleIRCLib/v14/.suo -------------------------------------------------------------------------------- /FormExample/Home.md: -------------------------------------------------------------------------------- 1 | # References 2 | 3 | ## [FormExample](FormExample) 4 | 5 | - [`DebugForm`](FormExample#debugform) 6 | - [`IrcClientForm`](FormExample#ircclientform) 7 | 8 | -------------------------------------------------------------------------------- /FormExample/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /IrcLibTest/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /FormExample/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SimpleIRCLib/Home.md: -------------------------------------------------------------------------------- 1 | # References 2 | 3 | ## [SimpleIRCLib](SimpleIRCLib) 4 | 5 | - [`DCCClient`](SimpleIRCLib#dccclient) 6 | - [`DCCDebugMessageArgs`](SimpleIRCLib#dccdebugmessageargs) 7 | - [`DCCEventArgs`](SimpleIRCLib#dcceventargs) 8 | - [`IrcClient`](SimpleIRCLib#ircclient) 9 | - [`IrcDebugMessageEventArgs`](SimpleIRCLib#ircdebugmessageeventargs) 10 | - [`IrcRawReceivedEventArgs`](SimpleIRCLib#ircrawreceivedeventargs) 11 | - [`IrcReceivedEventArgs`](SimpleIRCLib#ircreceivedeventargs) 12 | - [`IrcUserListReceivedEventArgs`](SimpleIRCLib#ircuserlistreceivedeventargs) 13 | - [`SimpleIRC`](SimpleIRCLib#simpleirc) 14 | 15 | -------------------------------------------------------------------------------- /FormExample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace FormExample 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | Application.Run(new IrcClientForm()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Eldin Zenderink 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /FormExample/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace FormExample.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SimpleIRCLib/SimpleIRCLib.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | true 6 | 2.2.1 7 | Eldin Zenderink 8 | None 9 | A easy to use, easy to implent, IRC library with DCC (Download) support for C#. 10 | See for more information: 11 | https://github.com/EldinZenderink/SimpleIRCLib 12 | https://github.com/EldinZenderink/SimpleIRCLib 13 | https://github.com/EldinZenderink/SimpleIRCLib/blob/master/LICENSE 14 | https://github.com/EldinZenderink/SimpleIRCLib 15 | GitHub 16 | C# IRC DCC PROTOCOL irc protocol simple 17 | -- Added byte list buffer to access data downloaded per second (for parsing during the download for example (espescially used within LittleWeeb to parse subtitles during download). 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /FormExample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FormExample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FormExample")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a46528e0-6bb9-4200-8276-3f840e0a7c72")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /IrcLibTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("IrcLibTest")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("IrcLibTest")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("27c58f1a-4851-4a5b-85f7-c387971543da")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SimpleIRCLib.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2005 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleIRCLib", "SimpleIRCLib\SimpleIRCLib.csproj", "{3D881A50-DB1A-464E-A51E-4CE5EB8BD5F1}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IrcLibTest", "IrcLibTest\IrcLibTest.csproj", "{27C58F1A-4851-4A5B-85F7-C387971543DA}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FormExample", "FormExample\FormExample.csproj", "{A46528E0-6BB9-4200-8276-3F840E0A7C72}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {3D881A50-DB1A-464E-A51E-4CE5EB8BD5F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {3D881A50-DB1A-464E-A51E-4CE5EB8BD5F1}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {3D881A50-DB1A-464E-A51E-4CE5EB8BD5F1}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {3D881A50-DB1A-464E-A51E-4CE5EB8BD5F1}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {27C58F1A-4851-4A5B-85F7-C387971543DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {27C58F1A-4851-4A5B-85F7-C387971543DA}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {27C58F1A-4851-4A5B-85F7-C387971543DA}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {27C58F1A-4851-4A5B-85F7-C387971543DA}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {A46528E0-6BB9-4200-8276-3F840E0A7C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {A46528E0-6BB9-4200-8276-3F840E0A7C72}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {A46528E0-6BB9-4200-8276-3F840E0A7C72}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {A46528E0-6BB9-4200-8276-3F840E0A7C72}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {584E8A95-B483-45A0-A38B-985C12EF6371} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /FormExample/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace FormExample.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FormExample.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /IrcLibTest/IrcLibTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {27C58F1A-4851-4A5B-85F7-C387971543DA} 8 | Exe 9 | Properties 10 | IrcLibTest 11 | IrcLibTest 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | ..\SimpleIRCLib\bin\Release\netstandard2.0\SimpleIRCLib.dll 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 65 | -------------------------------------------------------------------------------- /SimpleIRCLib/IrcEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | 6 | namespace SimpleIRCLib 7 | { 8 | /// 9 | /// Event class for receiving messages from specific channels and users, fired within IrcClient.cs 10 | /// 11 | public class IrcReceivedEventArgs 12 | { 13 | /// 14 | /// Event for receiving messages from server, contains information about who send a message, from where, with the message send. 15 | /// 16 | /// message the user send 17 | /// name of the user 18 | /// channel where the user send it to 19 | public IrcReceivedEventArgs(string message, string user, string channel) 20 | { 21 | Message = message; 22 | User = user; 23 | Channel = channel; 24 | } 25 | 26 | /// 27 | /// Containing message from user on a specific channel 28 | /// 29 | public string Message { get; } 30 | /// 31 | /// Containing user name whom send the message on a specific channel 32 | /// 33 | public string User { get; } 34 | /// 35 | /// Containing channel name where user send his/hers/its message 36 | /// 37 | public string Channel { get; } 38 | } 39 | 40 | /// 41 | /// Event class for receiving raw messages from the irc server, fired within IrcClient.cs 42 | /// 43 | public class IrcRawReceivedEventArgs 44 | { 45 | /// 46 | /// Event for handeling raw messages from the server without any parsing applied. 47 | /// 48 | /// message from server 49 | public IrcRawReceivedEventArgs(string message) 50 | { 51 | Message = message; 52 | } 53 | 54 | /// 55 | /// Containing raw message from the irc server 56 | /// 57 | public string Message { get; } 58 | } 59 | 60 | /// 61 | /// Event class for receiving a list with users per channel, fired within IrcClient.cs 62 | /// 63 | public class IrcUserListReceivedEventArgs 64 | { 65 | /// 66 | /// Event for getting the usersperchannel list from the server. 67 | /// 68 | /// Dictionary containg a list with names per key (channel) 69 | public IrcUserListReceivedEventArgs(Dictionary> usersPerChannel) 70 | { 71 | UsersPerChannel = usersPerChannel; 72 | } 73 | 74 | /// 75 | /// Dicitonary containing a list with user names per channel 76 | /// 77 | public Dictionary> UsersPerChannel { get; } 78 | } 79 | 80 | /// 81 | /// Event class for receiving debug messages from the IrcClient, fired within IrcClient.cs 82 | /// 83 | public class IrcDebugMessageEventArgs 84 | { 85 | /// 86 | /// Event for receiving debug messages from the client 87 | /// 88 | /// debug message itself 89 | /// type of message, handy for identifying where the message occured 90 | public IrcDebugMessageEventArgs(string message, string type) 91 | { 92 | Message = message; 93 | Type = type; 94 | } 95 | 96 | /// 97 | /// Containing debug message. 98 | /// 99 | public string Message { get; } 100 | /// 101 | /// Containing type of message, handy for determining where the message originates from 102 | /// 103 | public string Type { get; } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /FormExample/FormExample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A46528E0-6BB9-4200-8276-3F840E0A7C72} 8 | WinExe 9 | Properties 10 | FormExample 11 | FormExample 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | bin\Debug\FormExample.xml 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | bin\Release\FormExample.xml 36 | 37 | 38 | 39 | False 40 | ..\SimpleIRCLib\bin\Debug\SimpleIRCLib.dll 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | Form 57 | 58 | 59 | DebugForm.cs 60 | 61 | 62 | Form 63 | 64 | 65 | IrcClientForm.cs 66 | 67 | 68 | 69 | 70 | DebugForm.cs 71 | 72 | 73 | IrcClientForm.cs 74 | 75 | 76 | ResXFileCodeGenerator 77 | Resources.Designer.cs 78 | Designer 79 | 80 | 81 | True 82 | Resources.resx 83 | 84 | 85 | SettingsSingleFileGenerator 86 | Settings.Designer.cs 87 | 88 | 89 | True 90 | Settings.settings 91 | True 92 | 93 | 94 | 95 | 96 | 97 | 98 | 105 | -------------------------------------------------------------------------------- /gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | 84 | # Visual Studio profiler 85 | *.psess 86 | *.vsp 87 | *.vspx 88 | *.sap 89 | 90 | # TFS 2012 Local Workspace 91 | $tf/ 92 | 93 | # Guidance Automation Toolkit 94 | *.gpState 95 | 96 | # ReSharper is a .NET coding add-in 97 | _ReSharper*/ 98 | *.[Rr]e[Ss]harper 99 | *.DotSettings.user 100 | 101 | # JustCode is a .NET coding add-in 102 | .JustCode 103 | 104 | # TeamCity is a build add-in 105 | _TeamCity* 106 | 107 | # DotCover is a Code Coverage Tool 108 | *.dotCover 109 | 110 | # NCrunch 111 | _NCrunch_* 112 | .*crunch*.local.xml 113 | nCrunchTemp_* 114 | 115 | # MightyMoose 116 | *.mm.* 117 | AutoTest.Net/ 118 | 119 | # Web workbench (sass) 120 | .sass-cache/ 121 | 122 | # Installshield output folder 123 | [Ee]xpress/ 124 | 125 | # DocProject is a documentation generator add-in 126 | DocProject/buildhelp/ 127 | DocProject/Help/*.HxT 128 | DocProject/Help/*.HxC 129 | DocProject/Help/*.hhc 130 | DocProject/Help/*.hhk 131 | DocProject/Help/*.hhp 132 | DocProject/Help/Html2 133 | DocProject/Help/html 134 | 135 | # Click-Once directory 136 | publish/ 137 | 138 | # Publish Web Output 139 | *.[Pp]ublish.xml 140 | *.azurePubxml 141 | # TODO: Comment the next line if you want to checkin your web deploy settings 142 | # but database connection strings (with potential passwords) will be unencrypted 143 | *.pubxml 144 | *.publishproj 145 | 146 | # NuGet Packages 147 | *.nupkg 148 | # The packages folder can be ignored because of Package Restore 149 | **/packages/* 150 | # except build/, which is used as an MSBuild target. 151 | !**/packages/build/ 152 | # Uncomment if necessary however generally it will be regenerated when needed 153 | #!**/packages/repositories.config 154 | # NuGet v3's project.json files produces more ignoreable files 155 | *.nuget.props 156 | *.nuget.targets 157 | 158 | # Microsoft Azure Build Output 159 | csx/ 160 | *.build.csdef 161 | 162 | # Microsoft Azure Emulator 163 | ecf/ 164 | rcf/ 165 | 166 | # Windows Store app package directories and files 167 | AppPackages/ 168 | BundleArtifacts/ 169 | Package.StoreAssociation.xml 170 | _pkginfo.txt 171 | 172 | # Visual Studio cache files 173 | # files ending in .cache can be ignored 174 | *.[Cc]ache 175 | # but keep track of directories ending in .cache 176 | !*.[Cc]ache/ 177 | 178 | # Others 179 | ClientBin/ 180 | ~$* 181 | *~ 182 | *.dbmdl 183 | *.dbproj.schemaview 184 | *.pfx 185 | *.publishsettings 186 | node_modules/ 187 | orleans.codegen.cs 188 | 189 | # Since there are multiple workflows, uncomment next line to ignore bower_components 190 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 191 | #bower_components/ 192 | 193 | # RIA/Silverlight projects 194 | Generated_Code/ 195 | 196 | # Backup & report files from converting an old project file 197 | # to a newer Visual Studio version. Backup files are not needed, 198 | # because we have git ;-) 199 | _UpgradeReport_Files/ 200 | Backup*/ 201 | UpgradeLog*.XML 202 | UpgradeLog*.htm 203 | 204 | # SQL Server files 205 | *.mdf 206 | *.ldf 207 | 208 | # Business Intelligence projects 209 | *.rdl.data 210 | *.bim.layout 211 | *.bim_*.settings 212 | 213 | # Microsoft Fakes 214 | FakesAssemblies/ 215 | 216 | # GhostDoc plugin setting file 217 | *.GhostDoc.xml 218 | 219 | # Node.js Tools for Visual Studio 220 | .ntvs_analysis.dat 221 | 222 | # Visual Studio 6 build log 223 | *.plg 224 | 225 | # Visual Studio 6 workspace options file 226 | *.opt 227 | 228 | # Visual Studio LightSwitch build output 229 | **/*.HTMLClient/GeneratedArtifacts 230 | **/*.DesktopClient/GeneratedArtifacts 231 | **/*.DesktopClient/ModelManifest.xml 232 | **/*.Server/GeneratedArtifacts 233 | **/*.Server/ModelManifest.xml 234 | _Pvt_Extensions 235 | 236 | # Paket dependency manager 237 | .paket/paket.exe 238 | paket-files/ 239 | 240 | # FAKE - F# Make 241 | .fake/ 242 | 243 | # JetBrains Rider 244 | .idea/ 245 | *.sln.iml -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.suo## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | 84 | # Visual Studio profiler 85 | *.psess 86 | *.vsp 87 | *.vspx 88 | *.sap 89 | 90 | # TFS 2012 Local Workspace 91 | $tf/ 92 | 93 | # Guidance Automation Toolkit 94 | *.gpState 95 | 96 | # ReSharper is a .NET coding add-in 97 | _ReSharper*/ 98 | *.[Rr]e[Ss]harper 99 | *.DotSettings.user 100 | 101 | # JustCode is a .NET coding add-in 102 | .JustCode 103 | 104 | # TeamCity is a build add-in 105 | _TeamCity* 106 | 107 | # DotCover is a Code Coverage Tool 108 | *.dotCover 109 | 110 | # NCrunch 111 | _NCrunch_* 112 | .*crunch*.local.xml 113 | nCrunchTemp_* 114 | 115 | # MightyMoose 116 | *.mm.* 117 | AutoTest.Net/ 118 | 119 | # Web workbench (sass) 120 | .sass-cache/ 121 | 122 | # Installshield output folder 123 | [Ee]xpress/ 124 | 125 | # DocProject is a documentation generator add-in 126 | DocProject/buildhelp/ 127 | DocProject/Help/*.HxT 128 | DocProject/Help/*.HxC 129 | DocProject/Help/*.hhc 130 | DocProject/Help/*.hhk 131 | DocProject/Help/*.hhp 132 | DocProject/Help/Html2 133 | DocProject/Help/html 134 | 135 | # Click-Once directory 136 | publish/ 137 | 138 | # Publish Web Output 139 | *.[Pp]ublish.xml 140 | *.azurePubxml 141 | # TODO: Comment the next line if you want to checkin your web deploy settings 142 | # but database connection strings (with potential passwords) will be unencrypted 143 | *.pubxml 144 | *.publishproj 145 | 146 | # NuGet Packages 147 | *.nupkg 148 | # The packages folder can be ignored because of Package Restore 149 | **/packages/* 150 | # except build/, which is used as an MSBuild target. 151 | !**/packages/build/ 152 | # Uncomment if necessary however generally it will be regenerated when needed 153 | #!**/packages/repositories.config 154 | # NuGet v3's project.json files produces more ignoreable files 155 | *.nuget.props 156 | *.nuget.targets 157 | 158 | # Microsoft Azure Build Output 159 | csx/ 160 | *.build.csdef 161 | 162 | # Microsoft Azure Emulator 163 | ecf/ 164 | rcf/ 165 | 166 | # Windows Store app package directories and files 167 | AppPackages/ 168 | BundleArtifacts/ 169 | Package.StoreAssociation.xml 170 | _pkginfo.txt 171 | 172 | # Visual Studio cache files 173 | # files ending in .cache can be ignored 174 | *.[Cc]ache 175 | # but keep track of directories ending in .cache 176 | !*.[Cc]ache/ 177 | 178 | # Others 179 | ClientBin/ 180 | ~$* 181 | *~ 182 | *.dbmdl 183 | *.dbproj.schemaview 184 | *.pfx 185 | *.publishsettings 186 | node_modules/ 187 | orleans.codegen.cs 188 | 189 | # Since there are multiple workflows, uncomment next line to ignore bower_components 190 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 191 | #bower_components/ 192 | 193 | # RIA/Silverlight projects 194 | Generated_Code/ 195 | 196 | # Backup & report files from converting an old project file 197 | # to a newer Visual Studio version. Backup files are not needed, 198 | # because we have git ;-) 199 | _UpgradeReport_Files/ 200 | Backup*/ 201 | UpgradeLog*.XML 202 | UpgradeLog*.htm 203 | 204 | # SQL Server files 205 | *.mdf 206 | *.ldf 207 | 208 | # Business Intelligence projects 209 | *.rdl.data 210 | *.bim.layout 211 | *.bim_*.settings 212 | 213 | # Microsoft Fakes 214 | FakesAssemblies/ 215 | 216 | # GhostDoc plugin setting file 217 | *.GhostDoc.xml 218 | 219 | # Node.js Tools for Visual Studio 220 | .ntvs_analysis.dat 221 | 222 | # Visual Studio 6 build log 223 | *.plg 224 | 225 | # Visual Studio 6 workspace options file 226 | *.opt 227 | 228 | # Visual Studio LightSwitch build output 229 | **/*.HTMLClient/GeneratedArtifacts 230 | **/*.DesktopClient/GeneratedArtifacts 231 | **/*.DesktopClient/ModelManifest.xml 232 | **/*.Server/GeneratedArtifacts 233 | **/*.Server/ModelManifest.xml 234 | _Pvt_Extensions 235 | 236 | # Paket dependency manager 237 | .paket/paket.exe 238 | paket-files/ 239 | 240 | # FAKE - F# Make 241 | .fake/ 242 | 243 | # JetBrains Rider 244 | .idea/ 245 | *.sln.iml 246 | *.suo -------------------------------------------------------------------------------- /SimpleIRCLib/DCCEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | 6 | namespace SimpleIRCLib 7 | { 8 | /// 9 | /// Event Class for containing eventhandler for Download Updates from DCCClient.cs 10 | /// 11 | public class DCCEventArgs 12 | { 13 | /// 14 | /// Event for download updates, containging information about the following 15 | /// DccString : unparsed dccstring received from server, handy for debugging purposes 16 | /// FileName : file that is currently being downloaded 17 | /// FileSize : size of file that is currently being downloaded 18 | /// Ip : server address where file originates from 19 | /// Port : port of server where file originates from 20 | /// Pack : original pack that the user requested 21 | /// Bot : original bot where the user requested a pack (file) from 22 | /// BytesPerSecond : current download speed in bytes p/s 23 | /// KBytesPerSecond : current download speed in kbytes p/s 24 | /// MBytesPerSecond : current download speed in mbytes p/s 25 | /// Status : current download status, for example: (WAITING, DOWNLOADING, FAILED, ABORTED, etc) 26 | /// Progress : percentage downloaded (0-100%) (is int!) 27 | /// 28 | /// 29 | public DCCEventArgs(DCCClient currentClient) 30 | { 31 | DccString = currentClient.NewDccString; 32 | FileName = currentClient.NewFileName; 33 | FileSize = currentClient.NewFileSize; 34 | Ip = currentClient.NewIP; 35 | Port = currentClient.NewPortNum; 36 | Pack = currentClient.PackNum; 37 | Bot = currentClient.BotName; 38 | BytesPerSecond = currentClient.BytesPerSecond; 39 | KBytesPerSecond = currentClient.KBytesPerSecond; 40 | MBytesPerSecond = currentClient.MBytesPerSecond; 41 | Status = currentClient.Status; 42 | Progress = currentClient.Progress; 43 | FilePath = currentClient.CurrentFilePath; 44 | Buffer = currentClient.Buffer; 45 | } 46 | 47 | /// 48 | /// To access the latest downloaded data (per second). 49 | /// 50 | public List Buffer { get; } 51 | /// 52 | /// Raw DCC String used for getting the file location (server) and some basic file information 53 | /// 54 | public string DccString { get; } 55 | /// 56 | /// File name of the file being downloaded 57 | /// 58 | public string FileName { get; } 59 | /// 60 | /// FileSize of the file being downloaded 61 | /// 62 | public Int64 FileSize { get; } 63 | /// 64 | /// Server address of file location 65 | /// 66 | public string Ip { get; } 67 | /// 68 | /// Port of server of file location 69 | /// 70 | public int Port { get; } 71 | /// 72 | /// Pack ID of file on bot where file resides 73 | /// 74 | public string Pack { get; } 75 | /// 76 | /// Bot name where file resides 77 | /// 78 | public string Bot { get; } 79 | /// 80 | /// Download speed in: B/s 81 | /// 82 | public long BytesPerSecond { get; } 83 | /// 84 | /// Download speed in: KB/s 85 | /// 86 | public int KBytesPerSecond { get; } 87 | /// 88 | /// Download speed in: MB/s 89 | /// 90 | public int MBytesPerSecond { get; } 91 | /// 92 | /// Download status, such as: WAITING,DOWNLOADING,FAILED:[ERROR],ABORTED 93 | /// 94 | public string Status { get; } 95 | /// 96 | /// Progress from 0-100 (%) 97 | /// 98 | public int Progress { get; } 99 | /// 100 | /// Path to file that is being downloaded 101 | /// 102 | public string FilePath { get; } 103 | } 104 | 105 | /// 106 | /// Event Class for handeling debug events fired within DCCClient.cs 107 | /// 108 | public class DCCDebugMessageArgs 109 | { 110 | /// 111 | /// Event for debug messages specific to the DCC Client 112 | /// 113 | /// debug message 114 | /// type of debug message, handy for determing where message occured 115 | public DCCDebugMessageArgs(string message, string type) 116 | { 117 | Message = message; 118 | Type = type; 119 | } 120 | 121 | /// 122 | /// Containing debug message 123 | /// 124 | public string Message { get; } 125 | /// 126 | /// Containing debug type 127 | /// 128 | public string Type { get; } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /FormExample/FormExample.md: -------------------------------------------------------------------------------- 1 | ## `DebugForm` 2 | 3 | ```csharp 4 | public class FormExample.DebugForm 5 | : Form, IComponent, IDisposable, IOleControl, IOleObject, IOleInPlaceObject, IOleInPlaceActiveObject, IOleWindow, IViewObject, IViewObject2, IPersist, IPersistStreamInit, IPersistPropertyBag, IPersistStorage, IQuickActivate, ISupportOleDropSource, IDropTarget, ISynchronizeInvoke, IWin32Window, IArrangedElement, IBindableComponent, IContainerControl 6 | 7 | ``` 8 | 9 | Methods 10 | 11 | | Type | Name | Summary | 12 | | --- | --- | --- | 13 | | `void` | ClearButton_Click(`Object` sender, `EventArgs` e) | Clears a specific rich textbox | 14 | | `void` | DebugForm_FormClosing(`Object` sender, `FormClosingEventArgs` e) | Makes sure that the form doesn't actually close, but hides instead, so debug messages can still be appended! | 15 | | `void` | DebugForm_Load(`Object` sender, `EventArgs` e) | Register event handlers for the IrcClient and DCCClient when the form loads. | 16 | | `void` | Dispose(`Boolean` disposing) | Clean up any resources being used. | 17 | | `void` | OnDccDebugMessage(`Object` source, `DCCDebugMessageArgs` args) | Event for receiving debug messages from the DccClient | 18 | | `void` | OnDccDebugMessageLocal(`String` type, `String` message) | For appending the debug message on the main thread using invoke required. | 19 | | `void` | OnIrcDebugMessage(`Object` source, `IrcDebugMessageEventArgs` args) | Event for receiving debug messages from the IrcClient | 20 | | `void` | OnIrcDebugMessageLocal(`String` type, `String` message) | For appending the debug message on the main thread using invoke required. | 21 | | `void` | OnRawMessageReceived(`Object` source, `IrcRawReceivedEventArgs` args) | Event for receiving raw messages from the irc server. | 22 | | `void` | OnRawMessageReceivedLocal(`String` message) | For appending the rawmessage on the main thread using invoke required. | 23 | 24 | 25 | ## `IrcClientForm` 26 | 27 | This class is meant as example on how to use SimpleIRCLib, this does not mean that this is the correct way to program! It's meant to showcase a few of the available methods within SimpleIRCLib, you should figure out on your own how to implement it to suit your needs! It lacks a few options, such as leaving a specific channel, which will be implemented in the future. If your knowledged, you could send a raw message to the server containing commands to PART from a channel and use the OnRawMessageReceived event to check the server response. 28 | ```csharp 29 | public class FormExample.IrcClientForm 30 | : Form, IComponent, IDisposable, IOleControl, IOleObject, IOleInPlaceObject, IOleInPlaceActiveObject, IOleWindow, IViewObject, IViewObject2, IPersist, IPersistStreamInit, IPersistPropertyBag, IPersistStorage, IQuickActivate, ISupportOleDropSource, IDropTarget, ISynchronizeInvoke, IWin32Window, IArrangedElement, IBindableComponent, IContainerControl 31 | 32 | ``` 33 | 34 | Methods 35 | 36 | | Type | Name | Summary | 37 | | --- | --- | --- | 38 | | `void` | ConnectButton_Click(`Object` sender, `EventArgs` e) | Gets the values from the input fields and starts the client | 39 | | `void` | DisconnectButton_Click(`Object` sender, `EventArgs` e) | Disconnects the irc client, closes all open tabs. | 40 | | `void` | Dispose(`Boolean` disposing) | Clean up any resources being used. | 41 | | `void` | DownloadsList_MouseDoubleClick(`Object` sender, `MouseEventArgs` e) | Opens the folder where the selected file is being downloaded to | 42 | | `void` | Form1_FormClosing(`Object` sender, `FormClosingEventArgs` e) | Stops the irc client on form close, otherwise it would keep running in the background!!! | 43 | | `void` | MessageInput_KeyDown(`Object` sender, `KeyEventArgs` e) | Sends if enter is pressed. | 44 | | `void` | OnDccEvent(`Object` sender, `DCCEventArgs` args) | Event that fires when DCCClient starts downloading. | 45 | | `void` | OnMessagesReceived(`Object` sender, `IrcReceivedEventArgs` args) | Event handler for receiving messages from the Irc Client. | 46 | | `void` | OnMessagesReceivedLocal(`String` channel, `String` user, `String` message) | Method that gets invoked on the main thread, adds a message to the richtextbox within a the correct channel tab. | 47 | | `void` | OnUserListReceived(`Object` sender, `IrcUserListReceivedEventArgs` args) | Event that gets fired when a user list has been received. | 48 | | `void` | OnUserListReceivedLocal(`Dictionary>` userList) | Method to invoke on the main thread, checks if a tab for the chat exists with name of the channel, if not, it creates it, same goes for the tab with the user name list. | 49 | | `void` | SendToAll_Click(`Object` sender, `EventArgs` e) | Sends a message to all channels. | 50 | | `void` | SendToChannel_Click(`Object` sender, `EventArgs` e) | Sends a message to a specific channel. | 51 | | `void` | SetDownloadFolderButton_Click(`Object` sender, `EventArgs` e) | Set download directory to a custom directory | 52 | | `void` | ShowDebugButton_Click(`Object` sender, `EventArgs` e) | Opens the debug form | 53 | | `void` | UpdateDownloadList(`String` toUpdate, `String` fileName) | Updates the DownloadList object on the main form while the download is going, invoke is necesary because method is being called from a different Thread! | 54 | | `void` | UpdateProgressBar(`Int32` progress) | Updates the progress bar | 55 | | `void` | UpdateUserList_Click(`Object` sender, `EventArgs` e) | Gets the users in the current channel. | 56 | 57 | 58 | -------------------------------------------------------------------------------- /IrcLibTest/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SimpleIRCLib; 7 | using System.Threading; 8 | 9 | namespace IrcLibTest 10 | { 11 | class Program 12 | { 13 | 14 | private static SimpleIRC irc; 15 | static void Main(string[] args) 16 | { 17 | //setup vars 18 | string ip; 19 | int port; 20 | string username; 21 | string password; 22 | string channel; 23 | 24 | Console.WriteLine("Server IP(default is : irc.rizon.net) = "); 25 | if ((ip = Console.ReadLine()) == "") 26 | { 27 | ip = "irc.rizon.net"; 28 | } 29 | 30 | Console.WriteLine("Server Port(default is : 6697 with ssl enabled) = "); 31 | if (Console.ReadLine() != "") 32 | { 33 | port = Convert.ToInt32(Console.ReadLine()); 34 | } 35 | else 36 | { 37 | port = 6697; 38 | } 39 | 40 | Console.WriteLine("Username(default is : RareIRC_Client) = "); 41 | if ((username = Console.ReadLine()) == "") 42 | { 43 | username = "RareIRC_ConsoleTestClient"; 44 | } 45 | 46 | Console.WriteLine("Password(not working yet, default is : ) = "); 47 | if ((password = Console.ReadLine()) == "") 48 | { 49 | password = ""; 50 | } 51 | 52 | Console.WriteLine("Channel(default is : #RareIRC) = "); 53 | if ((channel = Console.ReadLine()) == "") 54 | { 55 | channel = "#RareIRC"; 56 | } 57 | 58 | irc = new SimpleIRC(); 59 | 60 | irc.SetupIrc(ip, username, channel, port); 61 | 62 | irc.IrcClient.OnDebugMessage += debugOutputCallback; 63 | irc.IrcClient.OnMessageReceived += chatOutputCallback; 64 | irc.IrcClient.OnRawMessageReceived += rawOutputCallback; 65 | irc.IrcClient.OnUserListReceived += userListCallback; 66 | 67 | irc.DccClient.OnDccDebugMessage += dccDebugCallback; 68 | irc.DccClient.OnDccEvent += downloadStatusChanged; 69 | 70 | irc.StartClient(); 71 | 72 | while (true) 73 | { 74 | 75 | string Input = Console.ReadLine(); 76 | if (Input != null || Input != "" || Input != String.Empty && irc.IsClientRunning()) 77 | { 78 | irc.SendMessageToAll(Input); 79 | } 80 | 81 | } 82 | } 83 | 84 | public static void downloadStatusChanged(object source, DCCEventArgs args) 85 | { 86 | Console.WriteLine("===============DCC EVENT==============="); 87 | Console.WriteLine("DOWNLOAD STATUS: " + args.Status); 88 | Console.WriteLine("DOWNLOAD FILENAME: " + args.FileName); 89 | Console.WriteLine("DOWNLOAD PROGRESS: " + args.Progress + "%"); 90 | Console.WriteLine("===============END DCC EVENT==============="); 91 | Console.WriteLine(""); 92 | } 93 | 94 | public static void chatOutputCallback(object source, IrcReceivedEventArgs args) 95 | { 96 | Console.WriteLine("===============IRC MESSAGE==============="); 97 | Console.WriteLine(args.Channel + " | " + args.User + ": " + args.Message); 98 | Console.WriteLine("===============END IRC MESSAGE==============="); 99 | Console.WriteLine(""); 100 | } 101 | 102 | public static void rawOutputCallback(object source, IrcRawReceivedEventArgs args) 103 | { 104 | Console.WriteLine("===============RAW MESSAGE==============="); 105 | Console.WriteLine("RAW: " + args.Message); 106 | Console.WriteLine("===============END RAW MESSAGE==============="); 107 | } 108 | 109 | public static void debugOutputCallback(object source, IrcDebugMessageEventArgs args) 110 | { 111 | Console.WriteLine("===============IRC DEBUG MESSAGE==============="); 112 | Console.WriteLine(args.Type + "|" + args.Message); 113 | Console.WriteLine("===============END IRC DEBUG MESSAGE==============="); 114 | } 115 | 116 | public static void userListCallback(object source, IrcUserListReceivedEventArgs args) 117 | { 118 | foreach(KeyValuePair> usersPerChannel in args.UsersPerChannel) 119 | { 120 | Console.WriteLine("===============USERS ON CHANNEL " + usersPerChannel.Key + " ==============="); 121 | foreach (string user in usersPerChannel.Value) 122 | { 123 | Console.WriteLine(user); 124 | } 125 | Console.WriteLine("===============END USERS ON CHANNEL " + usersPerChannel.Key + " ==============="); 126 | } 127 | } 128 | 129 | public static void dccDebugCallback(object source, DCCDebugMessageArgs args) 130 | { 131 | Console.WriteLine("===============IRC DEBUG MESSAGE==============="); 132 | Console.WriteLine(args.Type + "|" + args.Message); 133 | Console.WriteLine("===============END IRC DEBUG MESSAGE==============="); 134 | } 135 | 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SimpleIRCLib for Csharp 2 | **THIS LIBRARY IS STILL IN DEVELOPMENT** 3 | **STARTING AT V2.0.0 THIS LIBRARY IS NOT BACK-WARDS COMPATIBLE WITH PREVIOUS VERSIONS!** 4 | 5 | This library is designed to make communication through IRC easier to implement in your application. In comparison to other C# IRC libraries, this library also enables you to download using the DCC (XDCC) protocol, used by IRC. 6 | 7 | It's main features are: 8 | 9 | - Is simple to use. 10 | - Is simple to implement 11 | - It's lightweight 12 | - Multiple channel support 13 | - DCC Download support 14 | 15 | ### NuGet 16 | [NuGet Package](https://www.nuget.org/packages/SimpleIRCLib) 17 | 18 | ### Version 19 | 1.0.0: 20 | - First release version 21 | 22 | 1.0.1: 23 | - Fixed bug where leaving out debug callback would cause nullreferenceexception. 24 | 25 | 26 | 1.1.1: 27 | - Added split in username | message 28 | - Added quit/disconnect method 29 | - removed usesless getters and setters 30 | - fixed a few more less significant bugs 31 | 32 | 1.1.2: 33 | - Removed getDownloadProgress, now download information can be retreived within the downloadStatusChangedCallback. 34 | - Fixed error when you try to check if client is running before connecting to a server! 35 | 36 | 1.1.3: 37 | - Code mostly reworked by following feedback from this post: [reddit](https://www.reddit.com/r/csharp/comments/452i80/simple_irc_library_with_dcc_download_option_d/), such as: 38 | - removed static fields 39 | - removed inheriting classes 40 | - text now being parsed through regex 41 | - for receiving messages: a async task instead of a thread 42 | - getDownloadProgress/downloadStatusChangedCallback has different way of operation (see below) 43 | - addes status attribute for downloadstatus/progress 44 | 45 | 1.1.3 -> 1.1.7: 46 | - stability issues fixed 47 | 48 | 1.1.8: 49 | - bugfixes, see commit description 50 | 51 | 1.1.9: 52 | - bugfixes, see commit description 53 | 54 | 1.2.0 55 | - Functionality update: Added method to retreive all the users in the current channel, as well as in other channels (but most of them will be hidden, so not very usefull ^^). 56 | 57 | 1.2.1 58 | - Functionality update: Send Raw Messages (such as NICK, PRIVMSG etc.) 59 | - Functionality update: Retreive Raw Data 60 | - Functionality update: Send /msg using normal sendMessage() function 61 | - Functionality update: Receive Notice message just like PRIVMSG (end user sees the source of the notice, for example: NickServ: bla bla bla) 62 | - Code update: changed parsing messages a bit. 63 | 64 | 1.2.2 65 | - Fixed issue with downloading filesizes larger than 4Gb. 66 | 67 | 1.2.3 68 | - Abort download only deletes file if it was actually downloading the file.(had issues where it would still delete even if the file was already done downloading) 69 | 70 | 1.2.4 71 | - Bug where some DCC SEND messages from bots were not detected & parsed properly. 72 | - Should support IPv6 now. (Not really tested). 73 | - Added function to check if download thread is still running. 74 | - Added some debug messages for debugging purposes. 75 | - Default download directory is now set to the same directory where the libary resides. 76 | - Added flag to check if an error occured of any kind within the library (doesn't tell what kind of error yet). 77 | 78 | 2.0.0 79 | - Rewritten IrcConnect class (now called IrcClient) to prevent Race conditions! 80 | - Added timeout warnings. 81 | - Added support for TLS/SSL 82 | - Added better error handeling using the error codes from RFC 1459 IRC Protocol 83 | - Added full support for receiving and sending to seperate channels 84 | - Added comments and changed names to fit C# code convention 85 | - Under the hood DCC fixes for more stability and error handeling when downloads go wrong 86 | - **Changed Action based callback methods to Event handlers** 87 | 88 | 2.1.0 89 | - Support for multiple .NET FrameWorks such as: .NET 4.5, .NET 4.6, .NET 4.7 & .NET CORE 2.0 & .NET CORE 2.1 90 | - Renamed a few properties. 91 | 92 | 2.1.1 & 2.1.2 93 | - DCC Fixes 94 | 95 | 2.2.0 96 | - Moved from multiple target framework to single framework: NETStandard2.0. 97 | 98 | ### Wiki 99 | To get a better picture of the available methods and properties, go to this wiki: 100 | [SimpleIRCLib Wiki](https://github.com/EldinZenderink/SimpleIRCLib/wiki/SimpleIRCLib-Methods-Wiki#simpleirc) 101 | 102 | For a full WinForms example, go to: 103 | [WinForm Example](https://github.com/EldinZenderink/SimpleIRCLib/tree/master/FormExample) 104 | 105 | For a simplified console example: 106 | [Console Example](https://github.com/EldinZenderink/SimpleIRCLib/tree/master/IrcLibTest) 107 | 108 | ### Tutorial 109 | A winform example including video tutorial (v1.1.2) **OLD - NOT SUPPORTED FOR v2.0.0**: 110 | [YouTube](https://www.youtube.com/watch?v=Y5JPdwFwoSI) 111 | 112 | -New v2.0.0 and up tutorial comming soon! 113 | 114 | ### Development 115 | I will try to fix (significant) bugs as quick as possible, but due to my study taking a rollercoaster dive in a few days it might take a while before an actual update will appear. It is very barebone and does need some refinement. So, progress in development will come down to how much free time I have and how much of it I want to spend working on this library. 116 | 117 | ### Todos 118 | 119 | - Some DCC fixes, most things seem to work, but there are some odd cases where it might not work. 120 | - More readable code (getting better) 121 | - Renaming some stupidly named names 122 | 123 | 124 | ### Disclaimer 125 | This library is still in alpha stadium, many things might go wrong and therefore I am not 126 | responsible for whatever happens while you use this application. 127 | 128 | License 129 | ---- 130 | 131 | MIT 132 | 133 | 134 | **Free Software, Hell Yeah!** 135 | 136 | -------------------------------------------------------------------------------- /SimpleIRCLib/SimpleIRCLib.md: -------------------------------------------------------------------------------- 1 | ## `DCCClient` 2 | 3 | ```csharp 4 | public class SimpleIRCLib.DCCClient 5 | 6 | ``` 7 | 8 | Properties 9 | 10 | | Type | Name | Summary | 11 | | --- | --- | --- | 12 | | `String` | BotName | | 13 | | `Int64` | BytesPerSecond | | 14 | | `String` | CurrentFilePath | | 15 | | `Boolean` | IsDownloading | | 16 | | `Int32` | KBytesPerSecond | | 17 | | `Int32` | MBytesPerSecond | | 18 | | `String` | NewDccString | | 19 | | `String` | NewFileName | | 20 | | `Int64` | NewFileSize | | 21 | | `String` | NewIp | | 22 | | `String` | NewIp2 | | 23 | | `Int32` | NewPortNum | | 24 | | `String` | PackNum | | 25 | | `Int32` | Progress | | 26 | | `String` | Status | | 27 | 28 | 29 | Events 30 | 31 | | Type | Name | Summary | 32 | | --- | --- | --- | 33 | | `EventHandler` | OnDccDebugMessage | | 34 | | `EventHandler` | OnDccEvent | | 35 | 36 | 37 | Methods 38 | 39 | | Type | Name | Summary | 40 | | --- | --- | --- | 41 | | `Boolean` | AbortDownloader(`Int32` timeOut) | | 42 | | `Boolean` | CheckIfDownloading() | | 43 | | `void` | Downloader() | | 44 | | `void` | StartDownloader(`String` dccString, `String` downloaddir, `String` bot, `String` pack, `IrcClient` client) | | 45 | 46 | 47 | ## `DCCDebugMessageArgs` 48 | 49 | ```csharp 50 | public class SimpleIRCLib.DCCDebugMessageArgs 51 | 52 | ``` 53 | 54 | Properties 55 | 56 | | Type | Name | Summary | 57 | | --- | --- | --- | 58 | | `String` | Message | | 59 | | `String` | Type | | 60 | 61 | 62 | ## `DCCEventArgs` 63 | 64 | ```csharp 65 | public class SimpleIRCLib.DCCEventArgs 66 | 67 | ``` 68 | 69 | Properties 70 | 71 | | Type | Name | Summary | 72 | | --- | --- | --- | 73 | | `String` | Bot | | 74 | | `Int64` | BytesPerSecond | | 75 | | `String` | DccString | | 76 | | `String` | FileName | | 77 | | `Int64` | FileSize | | 78 | | `String` | Ip | | 79 | | `Int32` | KBytesPerSecond | | 80 | | `Int32` | MBytesPerSecond | | 81 | | `String` | Pack | | 82 | | `Int32` | Port | | 83 | | `Int32` | Progress | | 84 | | `String` | Status | | 85 | 86 | 87 | ## `IrcClient` 88 | 89 | ```csharp 90 | public class SimpleIRCLib.IrcClient 91 | 92 | ``` 93 | 94 | Events 95 | 96 | | Type | Name | Summary | 97 | | --- | --- | --- | 98 | | `EventHandler` | OnDebugMessageReceived | | 99 | | `EventHandler` | OnMessageReceived | | 100 | | `EventHandler` | OnRawMessageReceived | | 101 | | `EventHandler` | OnUserListReceived | | 102 | 103 | 104 | Methods 105 | 106 | | Type | Name | Summary | 107 | | --- | --- | --- | 108 | | `Boolean` | CheckIfDownloading() | | 109 | | `Boolean` | Connect() | | 110 | | `Boolean` | GetUsersInChannel(`String` channel = ) | | 111 | | `Boolean` | IsClientRunning() | | 112 | | `Boolean` | IsConnectionEstablished() | | 113 | | `Boolean` | QuitConnect() | | 114 | | `Boolean` | SendMessageToAll(`String` input) | | 115 | | `Boolean` | SendMessageToChannel(`String` input, `String` channel) | | 116 | | `Boolean` | SendRawMsg(`String` msg) | | 117 | | `void` | SetConnectionInformation(`String` ip, `String` username, `String` channel, `DCCClient` dccClient, `String` downloadDirectory, `Int32` port = 0, `String` password = , `Int32` timeout = 3000, `Boolean` enableSSL = True) | | 118 | | `void` | SetDownloadDirectory(`String` downloadDirectory) | | 119 | | `void` | StartReceivingChat() | | 120 | | `void` | StopClient() | | 121 | | `Boolean` | StopXDCCDownload() | | 122 | | `Boolean` | WriteIrc(`String` input) | | 123 | 124 | 125 | ## `IrcDebugMessageEventArgs` 126 | 127 | ```csharp 128 | public class SimpleIRCLib.IrcDebugMessageEventArgs 129 | 130 | ``` 131 | 132 | Properties 133 | 134 | | Type | Name | Summary | 135 | | --- | --- | --- | 136 | | `String` | Message | | 137 | | `String` | Type | | 138 | 139 | 140 | ## `IrcRawReceivedEventArgs` 141 | 142 | ```csharp 143 | public class SimpleIRCLib.IrcRawReceivedEventArgs 144 | 145 | ``` 146 | 147 | Properties 148 | 149 | | Type | Name | Summary | 150 | | --- | --- | --- | 151 | | `String` | Message | | 152 | 153 | 154 | ## `IrcReceivedEventArgs` 155 | 156 | ```csharp 157 | public class SimpleIRCLib.IrcReceivedEventArgs 158 | 159 | ``` 160 | 161 | Properties 162 | 163 | | Type | Name | Summary | 164 | | --- | --- | --- | 165 | | `String` | Channel | | 166 | | `String` | Message | | 167 | | `String` | User | | 168 | 169 | 170 | ## `IrcUserListReceivedEventArgs` 171 | 172 | ```csharp 173 | public class SimpleIRCLib.IrcUserListReceivedEventArgs 174 | 175 | ``` 176 | 177 | Properties 178 | 179 | | Type | Name | Summary | 180 | | --- | --- | --- | 181 | | `Dictionary>` | UsersPerChannel | | 182 | 183 | 184 | ## `SimpleIRC` 185 | 186 | ```csharp 187 | public class SimpleIRCLib.SimpleIRC 188 | 189 | ``` 190 | 191 | Properties 192 | 193 | | Type | Name | Summary | 194 | | --- | --- | --- | 195 | | `DCCClient` | DccClient | | 196 | | `IrcClient` | IrcClient | | 197 | 198 | 199 | Methods 200 | 201 | | Type | Name | Summary | 202 | | --- | --- | --- | 203 | | `Boolean` | CheckIfDownload() | | 204 | | `void` | GetUsersInCurrentChannel() | | 205 | | `void` | GetUsersInDifferentChannel(`String` channel) | | 206 | | `Boolean` | IsClientRunning() | | 207 | | `Boolean` | SendMessageToAll(`String` message) | | 208 | | `Boolean` | SendMessageToChannel(`String` message, `String` channel) | | 209 | | `Boolean` | SendRawMessage(`String` message) | | 210 | | `void` | SetCustomDownloadDir(`String` downloaddir) | | 211 | | `void` | SetupIrc(`String` ip, `String` username, `String` channel, `Int32` port = 0, `String` password = , `Int32` timeout = 3000, `Boolean` enableSSL = True) | | 212 | | `Boolean` | StartClient() | | 213 | | `Boolean` | StopClient() | | 214 | | `Boolean` | StopXDCCDownload() | | 215 | 216 | 217 | -------------------------------------------------------------------------------- /FormExample/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /FormExample/DebugForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /FormExample/DebugForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using SimpleIRCLib; 11 | 12 | namespace FormExample 13 | { 14 | public partial class DebugForm : Form 15 | { 16 | 17 | private readonly SimpleIRC _simpleIrc; 18 | 19 | /// 20 | /// Constructor for the debug form. 21 | /// 22 | /// SimpleIRC instance 23 | public DebugForm(SimpleIRC irc) 24 | { 25 | _simpleIrc = irc; 26 | InitializeComponent(); 27 | } 28 | 29 | /// 30 | /// Clears a specific rich textbox 31 | /// 32 | /// 33 | /// 34 | public void ClearButton_Click(object sender, EventArgs e) 35 | { 36 | RichTextBox selectedRtb = (RichTextBox)debugTabs.SelectedTab.Controls[0]; 37 | selectedRtb.Clear(); 38 | } 39 | 40 | /// 41 | /// Makes sure that the form doesn't actually close, but hides instead, so debug messages can still be appended! 42 | /// 43 | /// 44 | /// 45 | public void DebugForm_FormClosing(object sender, FormClosingEventArgs e) 46 | { 47 | if (e.CloseReason == CloseReason.UserClosing) 48 | { 49 | e.Cancel = true; 50 | Hide(); 51 | } 52 | } 53 | 54 | /// 55 | /// Register event handlers for the IrcClient and DCCClient when the form loads. 56 | /// 57 | /// 58 | /// 59 | public void DebugForm_Load(object sender, EventArgs e) 60 | { 61 | _simpleIrc.IrcClient.OnDebugMessage += OnIrcDebugMessage; 62 | _simpleIrc.IrcClient.OnRawMessageReceived += OnRawMessageReceived; 63 | _simpleIrc.DccClient.OnDccDebugMessage += OnDccDebugMessage; 64 | } 65 | 66 | /// 67 | /// Event for receiving debug messages from the IrcClient 68 | /// 69 | /// source class 70 | /// IrcDebugMessageEventArgs contains debug message and type 71 | public void OnIrcDebugMessage(object source, IrcDebugMessageEventArgs args) 72 | { 73 | OnIrcDebugMessageLocal(args.Type, args.Message); 74 | } 75 | 76 | /// 77 | /// For appending the debug message on the main thread using invoke required. 78 | /// 79 | /// Debug message type, handy for figuring out where the debug message came from 80 | /// message to append to the rich textbox 81 | public void OnIrcDebugMessageLocal(string type, string message) 82 | { 83 | if (this.InvokeRequired) 84 | { 85 | this.Invoke(new MethodInvoker(() => OnIrcDebugMessageLocal(type, message))); 86 | } 87 | else 88 | { 89 | if (debugTabs != null) 90 | { 91 | RichTextBox selectedRtb = (RichTextBox)debugTabs.TabPages[0].Controls[0]; 92 | selectedRtb.AppendText(type + " | " + message + Environment.NewLine); 93 | } 94 | } 95 | } 96 | 97 | /// 98 | /// Event for receiving raw messages from the irc server. 99 | /// 100 | /// source class 101 | /// IrcRawReceivedEventArgs contains the message received 102 | public void OnRawMessageReceived(object source, IrcRawReceivedEventArgs args) 103 | { 104 | OnRawMessageReceivedLocal(args.Message); 105 | } 106 | 107 | /// 108 | /// For appending the rawmessage on the main thread using invoke required. 109 | /// 110 | /// message to append to the rich textbox 111 | public void OnRawMessageReceivedLocal(string message) 112 | { 113 | if (this.InvokeRequired) 114 | { 115 | this.Invoke(new MethodInvoker(() => OnRawMessageReceivedLocal(message))); 116 | } 117 | else 118 | { 119 | if (debugTabs != null) 120 | { 121 | RichTextBox selectedRtb = (RichTextBox) debugTabs.TabPages[2].Controls[0]; 122 | selectedRtb.AppendText(message + Environment.NewLine); 123 | } 124 | } 125 | } 126 | 127 | /// 128 | /// Event for receiving debug messages from the DccClient 129 | /// 130 | /// source class 131 | /// DCCDebugMessageArgs contains the debug message and type 132 | public void OnDccDebugMessage(object source, DCCDebugMessageArgs args) 133 | { 134 | OnDccDebugMessageLocal(args.Type, args.Message); 135 | } 136 | 137 | /// 138 | /// For appending the debug message on the main thread using invoke required. 139 | /// 140 | /// Debug message type, handy for figuring out where the debug message came from 141 | /// message to append to the rich textbox 142 | public void OnDccDebugMessageLocal(string type, string message) 143 | { 144 | if (this.InvokeRequired) 145 | { 146 | this.Invoke(new MethodInvoker(() => OnDccDebugMessageLocal(type, message))); 147 | } 148 | else 149 | { 150 | if (debugTabs != null) 151 | { 152 | RichTextBox selectedRtb = (RichTextBox) debugTabs.TabPages[1].Controls[0]; 153 | selectedRtb.AppendText(type + " | " + message + Environment.NewLine); 154 | } 155 | } 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /FormExample/IrcClientForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | 124 | 181, 17 125 | 126 | -------------------------------------------------------------------------------- /FormExample/DebugForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace FormExample 2 | { 3 | partial class DebugForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.ClearButton = new System.Windows.Forms.Button(); 32 | this.debugTabs = new System.Windows.Forms.TabControl(); 33 | this.ircDebug = new System.Windows.Forms.TabPage(); 34 | this.dccDebug = new System.Windows.Forms.TabPage(); 35 | this.ircDebugRichTextbox = new System.Windows.Forms.RichTextBox(); 36 | this.dccDebugRichTextBox = new System.Windows.Forms.RichTextBox(); 37 | this.ircRawOutput = new System.Windows.Forms.TabPage(); 38 | this.rawIrcOutput = new System.Windows.Forms.RichTextBox(); 39 | this.debugTabs.SuspendLayout(); 40 | this.ircDebug.SuspendLayout(); 41 | this.dccDebug.SuspendLayout(); 42 | this.ircRawOutput.SuspendLayout(); 43 | this.SuspendLayout(); 44 | // 45 | // ClearButton 46 | // 47 | this.ClearButton.Location = new System.Drawing.Point(12, 394); 48 | this.ClearButton.Name = "ClearButton"; 49 | this.ClearButton.Size = new System.Drawing.Size(449, 23); 50 | this.ClearButton.TabIndex = 1; 51 | this.ClearButton.Text = "Clear"; 52 | this.ClearButton.UseVisualStyleBackColor = true; 53 | this.ClearButton.Click += new System.EventHandler(this.ClearButton_Click); 54 | // 55 | // debugTabs 56 | // 57 | this.debugTabs.Controls.Add(this.ircDebug); 58 | this.debugTabs.Controls.Add(this.dccDebug); 59 | this.debugTabs.Controls.Add(this.ircRawOutput); 60 | this.debugTabs.Location = new System.Drawing.Point(12, 0); 61 | this.debugTabs.Name = "debugTabs"; 62 | this.debugTabs.SelectedIndex = 0; 63 | this.debugTabs.Size = new System.Drawing.Size(460, 388); 64 | this.debugTabs.TabIndex = 2; 65 | // 66 | // ircDebug 67 | // 68 | this.ircDebug.Controls.Add(this.ircDebugRichTextbox); 69 | this.ircDebug.Location = new System.Drawing.Point(4, 22); 70 | this.ircDebug.Name = "ircDebug"; 71 | this.ircDebug.Padding = new System.Windows.Forms.Padding(3); 72 | this.ircDebug.Size = new System.Drawing.Size(452, 362); 73 | this.ircDebug.TabIndex = 0; 74 | this.ircDebug.Text = "IRC Debug"; 75 | this.ircDebug.UseVisualStyleBackColor = true; 76 | // 77 | // dccDebug 78 | // 79 | this.dccDebug.Controls.Add(this.dccDebugRichTextBox); 80 | this.dccDebug.Location = new System.Drawing.Point(4, 22); 81 | this.dccDebug.Name = "dccDebug"; 82 | this.dccDebug.Padding = new System.Windows.Forms.Padding(3); 83 | this.dccDebug.Size = new System.Drawing.Size(452, 362); 84 | this.dccDebug.TabIndex = 1; 85 | this.dccDebug.Text = "DCC Debug"; 86 | this.dccDebug.UseVisualStyleBackColor = true; 87 | // 88 | // ircDebugRichTextbox 89 | // 90 | this.ircDebugRichTextbox.Location = new System.Drawing.Point(6, 6); 91 | this.ircDebugRichTextbox.Name = "ircDebugRichTextbox"; 92 | this.ircDebugRichTextbox.Size = new System.Drawing.Size(439, 350); 93 | this.ircDebugRichTextbox.TabIndex = 0; 94 | this.ircDebugRichTextbox.Text = ""; 95 | // 96 | // dccDebugRichTextBox 97 | // 98 | this.dccDebugRichTextBox.Location = new System.Drawing.Point(6, 6); 99 | this.dccDebugRichTextBox.Name = "dccDebugRichTextBox"; 100 | this.dccDebugRichTextBox.Size = new System.Drawing.Size(440, 353); 101 | this.dccDebugRichTextBox.TabIndex = 0; 102 | this.dccDebugRichTextBox.Text = ""; 103 | // 104 | // ircRawOutput 105 | // 106 | this.ircRawOutput.Controls.Add(this.rawIrcOutput); 107 | this.ircRawOutput.Location = new System.Drawing.Point(4, 22); 108 | this.ircRawOutput.Name = "ircRawOutput"; 109 | this.ircRawOutput.Size = new System.Drawing.Size(452, 362); 110 | this.ircRawOutput.TabIndex = 2; 111 | this.ircRawOutput.Text = "Irc Raw Output"; 112 | this.ircRawOutput.UseVisualStyleBackColor = true; 113 | // 114 | // rawIrcOutput 115 | // 116 | this.rawIrcOutput.Location = new System.Drawing.Point(4, 4); 117 | this.rawIrcOutput.Name = "rawIrcOutput"; 118 | this.rawIrcOutput.Size = new System.Drawing.Size(441, 355); 119 | this.rawIrcOutput.TabIndex = 0; 120 | this.rawIrcOutput.Text = ""; 121 | // 122 | // DebugForm 123 | // 124 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 125 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 126 | this.ClientSize = new System.Drawing.Size(473, 427); 127 | this.Controls.Add(this.debugTabs); 128 | this.Controls.Add(this.ClearButton); 129 | this.Name = "DebugForm"; 130 | this.Text = "DebugForm"; 131 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DebugForm_FormClosing); 132 | this.Load += new System.EventHandler(this.DebugForm_Load); 133 | this.debugTabs.ResumeLayout(false); 134 | this.ircDebug.ResumeLayout(false); 135 | this.dccDebug.ResumeLayout(false); 136 | this.ircRawOutput.ResumeLayout(false); 137 | this.ResumeLayout(false); 138 | 139 | } 140 | 141 | #endregion 142 | private System.Windows.Forms.Button ClearButton; 143 | private System.Windows.Forms.TabControl debugTabs; 144 | private System.Windows.Forms.TabPage ircDebug; 145 | private System.Windows.Forms.RichTextBox ircDebugRichTextbox; 146 | private System.Windows.Forms.TabPage dccDebug; 147 | private System.Windows.Forms.RichTextBox dccDebugRichTextBox; 148 | private System.Windows.Forms.TabPage ircRawOutput; 149 | private System.Windows.Forms.RichTextBox rawIrcOutput; 150 | } 151 | } -------------------------------------------------------------------------------- /SimpleIRCLib/SimpleIRC.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | using System.Threading; 5 | 6 | namespace SimpleIRCLib 7 | { 8 | /// 9 | /// A combiner class that combines all the logic from both the IrcClient & DCCClient with simple methods to control these clients. 10 | /// 11 | public class SimpleIRC 12 | { 13 | 14 | 15 | /// 16 | /// Ip address of irc server 17 | /// 18 | public string NewIP{ get; set; } 19 | /// 20 | /// Port of irc server to connect to 21 | /// 22 | public int NewPort { get; set; } 23 | /// 24 | /// Username to register on irc server 25 | /// 26 | public string NewUsername { get; set; } 27 | /// 28 | /// List with channels seperated with ',' to join when connecting to IRC server 29 | /// 32 | /// Password to connect to a secured irc server 33 | /// 34 | public string NewPassword { get; set; } 35 | /// 36 | /// download directory used for DCCClient.cs 37 | /// 38 | public string DownloadDir { get; set; } 39 | 40 | /// 41 | /// Irc Client for sending and receiving messages to a irc server 42 | /// 43 | public IrcClient IrcClient { get; set; } 44 | /// 45 | /// DCCClient used by the IRCClient for starting a download on a separate thread using the DCC Protocol 46 | /// 47 | public DCCClient DccClient { get; set; } 48 | 49 | 50 | /// 51 | /// Constructor, sets up bot ircclient and dccclient, so that users can register event handlers. 52 | /// 53 | public SimpleIRC() 54 | { 55 | NewIP= ""; 56 | NewPort = 0; 57 | NewUsername = ""; 58 | NewPassword = ""; 59 | NewChannels = ""; 60 | DownloadDir = ""; 61 | IrcClient = new IrcClient(); 62 | DccClient = new DCCClient(); 63 | } 64 | 65 | 66 | /// 67 | /// Setup the client to be able to connect to the server 68 | /// 69 | /// Server address, possibly works with dns addresses (irc.xxx.x), but ip addresses works just fine (of type string) 70 | /// Username the client wants to use, of type string 71 | /// Channel(s) the client wants to connect to, possible to connect to multiple channels at once by seperating each channel with a ',' (Example: #chan1,#chan2), of type string 72 | /// Port, optional parameter, where default = 0 (Automatic port selection), is port of the server you want to connect to, of type int 73 | /// Password, optional parameter, where default value is "", can be used to connect to a password protected server. 74 | /// Timeout, optional parameter, where default value is 3000 milliseconds, the maximum time before a server needs to answer, otherwise errors are thrown. 75 | /// Timeout, optional parameter, where default value is 3000 milliseconds, the maximum time before a server needs to answer, otherwise errors are thrown. 76 | public void SetupIrc(string ip, string username, string channels, int port = 0, string password = "", int timeout = 3000, bool enableSSL = true) 77 | { 78 | NewIP= ip; 79 | NewPort = port; 80 | NewUsername = username; 81 | NewPassword = password; 82 | NewChannels = channels; 83 | DownloadDir = ""; 84 | 85 | IrcClient.SetConnectionInformation(ip, username, channels, DccClient, DownloadDir, port, password, timeout, enableSSL); 86 | 87 | } 88 | 89 | /// 90 | /// Sets the download directory for dcc downloads. 91 | /// 92 | /// Requires a path to a directory of type string as parameter. 93 | public void SetCustomDownloadDir(string downloaddir) 94 | { 95 | DownloadDir = downloaddir; 96 | IrcClient.SetDownloadDirectory(downloaddir); 97 | } 98 | 99 | /// 100 | /// Starts the irc client with the given parameters in the constructor 101 | /// 102 | /// true or false depending if it starts succesfully 103 | public bool StartClient() 104 | { 105 | if (IrcClient != null) 106 | { 107 | if (!IrcClient.IsConnectionEstablished()) 108 | { 109 | IrcClient.Connect(); 110 | 111 | int timeout = 0; 112 | while (!IrcClient.IsClientRunning()) 113 | { 114 | Thread.Sleep(1); 115 | if (timeout >= 3000) 116 | { 117 | return false; 118 | } 119 | timeout++; 120 | } 121 | return true; 122 | } 123 | } 124 | 125 | return false; 126 | } 127 | 128 | /// 129 | /// Checks if the client is running. 130 | /// 131 | /// true or false 132 | public bool IsClientRunning() 133 | { 134 | return IrcClient.IsClientRunning(); 135 | } 136 | 137 | /// 138 | /// Stops the client 139 | /// 140 | /// true or false depending on succes 141 | public bool StopClient() 142 | { 143 | //execute quit stuff 144 | bool check = false; 145 | 146 | check = IrcClient.StopClient(); 147 | check = IrcClient.StopXDCCDownload(); 148 | return check; 149 | } 150 | 151 | /// 152 | ///returns true or false upon calling this method, for telling you if the downlaod has been stopped or not 153 | /// 154 | /// 155 | public bool StopXDCCDownload() 156 | { 157 | return IrcClient.StopXDCCDownload(); 158 | } 159 | 160 | /// 161 | ///returns true or false upon calling this method, for telling you if the downlaod has been stopped or not 162 | /// 163 | /// 164 | public bool CheckIfDownload() 165 | { 166 | return IrcClient.CheckIfDownloading(); 167 | } 168 | 169 | /// 170 | ///get users in current channel 171 | /// 172 | public void GetUsersInCurrentChannel() 173 | { 174 | IrcClient.GetUsersInChannel(); 175 | } 176 | 177 | /// 178 | ///get users in different channel, parameter is the channel name of type string (example: "#yourchannel") 179 | /// 180 | /// 181 | public void GetUsersInDifferentChannel(string channel) 182 | { 183 | IrcClient.GetUsersInChannel(channel); 184 | } 185 | 186 | /// 187 | ///send message to all channels 188 | /// 189 | /// message to send 190 | /// true if succesfully send 191 | public bool SendMessageToAll(string message) 192 | { 193 | return IrcClient.SendMessageToAll(message); 194 | } 195 | 196 | /// 197 | /// Sends a message to a specific channel. 198 | /// 199 | /// message to send 200 | /// channel for destination 201 | /// true/false depending if sending was succesfull 202 | public bool SendMessageToChannel(string message, string channel) 203 | { 204 | return IrcClient.SendMessageToChannel(message, channel); 205 | } 206 | 207 | /// 208 | /// Sends a raw message to irc server 209 | /// 210 | /// message to send 211 | /// true/false depending if sending was succesfull 212 | public bool SendRawMessage(string message) 213 | { 214 | return IrcClient.SendRawMsg(message); 215 | } 216 | 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /SimpleIRCLib/IrcCommands.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Net.Security; 6 | using System.Net.Sockets; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace SimpleIRCLib 12 | { 13 | /// 14 | /// Class used for sending specific commands to the IRC server, and waiting for responses from the irc server before continueing 15 | /// 16 | class IrcCommands 17 | { 18 | /// 19 | /// reader to read from the irc server stream 20 | /// 21 | private readonly StreamReader _reader; 22 | 23 | /// 24 | /// reader to write to the irc server stream 25 | /// 26 | private readonly StreamWriter _writer; 27 | 28 | /// 29 | /// global error message string, used for defining the error that might occur with a readable string 30 | /// 31 | private string _errorMessage; 32 | 33 | /// 34 | /// global error integer, used for getting the specific error id specified within the IRC specs RFC 2812 35 | /// 36 | private int _responseNumber; 37 | 38 | /// 39 | /// user name that has been registered 40 | /// 41 | private string _username; 42 | 43 | /// 44 | /// channel that hs been joined 45 | /// 46 | private string _channels; 47 | 48 | /// 49 | /// Constructor, that requires the stream reader and writer set before initializing 50 | /// 51 | /// Stream to read/write from/to 52 | public IrcCommands(NetworkStream stream) 53 | { 54 | _reader = new StreamReader(stream); 55 | _writer = new StreamWriter(stream); 56 | } 57 | 58 | /// 59 | /// Constructor, that requires the stream reader and writer set before initializing 60 | /// 61 | /// Stream to read/write from/to 62 | public IrcCommands(SslStream stream) 63 | { 64 | _reader = new StreamReader(stream); 65 | _writer = new StreamWriter(stream); 66 | } 67 | 68 | /// 69 | /// Get the error message that probably has occured when calling this method 70 | /// 71 | /// returns error message 72 | public string GetErrorMessage() 73 | { 74 | return _errorMessage; 75 | } 76 | 77 | /// 78 | /// Get the error number that probably had occured when calling this method (RFC 2812) 79 | /// 80 | /// 81 | public int GetErrorNumber() 82 | { 83 | return _responseNumber; 84 | } 85 | 86 | /// 87 | /// Sets the password for a connection and waits if there is any response, if there is, it may continue, unless the reponse contains an error message 88 | /// 89 | /// password to set 90 | /// true/false depending if error occured 91 | public bool SetPassWord(string password) 92 | { 93 | _writer.WriteLine("PASS " + password + Environment.NewLine); 94 | _writer.Flush(); 95 | 96 | while (true) 97 | { 98 | string ircData = _reader.ReadLine(); 99 | if (ircData.Contains("462")) 100 | { 101 | _responseNumber = 462; 102 | _errorMessage = "PASSWORD ALREADY REGISTERED"; 103 | return false; 104 | } 105 | else if (ircData.Contains("461")) 106 | { 107 | _responseNumber = 461; 108 | _errorMessage = "PASSWORD COMMAND NEEDS MORE PARAMETERS"; 109 | return false; 110 | }else if (ircData.Contains("004")) 111 | { 112 | return true; 113 | } 114 | else 115 | { 116 | return true; 117 | } 118 | } 119 | } 120 | 121 | /// 122 | /// Sends the user and nick command to the irc server, checks for error messages (it waits for a reply to come through first, before deciding what to do). 123 | /// 124 | /// Username 125 | /// 126 | /// True/False, depending if error occured or not 127 | public bool JoinNetwork(string user, string channels) 128 | { 129 | _username = user; 130 | _channels = channels; 131 | _writer.WriteLine("NICK " + user + Environment.NewLine); 132 | _writer.Flush(); 133 | _writer.WriteLine("USER " + user + " 8 * :" + user + "_SimpleIRCLib" + Environment.NewLine); 134 | _writer.Flush(); 135 | 136 | while (true) 137 | { 138 | try 139 | { 140 | string ircData = _reader.ReadLine(); 141 | if (ircData != null) 142 | { 143 | if (ircData.Contains("PING")) 144 | { 145 | string pingID = ircData.Split(':')[1]; 146 | _writer.WriteLine("PONG :" + pingID); 147 | _writer.Flush(); 148 | } 149 | 150 | if (CheckMessageForError(ircData)) 151 | { 152 | if (_responseNumber == 266) 153 | { 154 | return JoinChannel(channels, user); 155 | } 156 | } 157 | } 158 | Thread.Sleep(1); 159 | } 160 | catch (Exception e) 161 | { 162 | 163 | Debug.WriteLine("RECEIVED: " + e.ToString()); 164 | return false; 165 | } 166 | } 167 | } 168 | 169 | /// 170 | /// Sends a join request to the irc server, then waits for a response before continueing 171 | /// 172 | /// Channels to join 173 | /// Username that joins 174 | /// True on sucess, false on error 175 | public bool JoinChannel(string channels, string username) 176 | { 177 | _channels = channels; 178 | 179 | _writer.WriteLine("JOIN " + channels + Environment.NewLine); 180 | _writer.Flush(); 181 | while (true) 182 | { 183 | 184 | string ircData = _reader.ReadLine(); 185 | if (ircData != null) 186 | { 187 | if (ircData.Contains("PING")) 188 | { 189 | string pingID = ircData.Split(':')[1]; 190 | _writer.WriteLine("PONG :" + pingID); 191 | _writer.Flush(); 192 | } 193 | 194 | if (ircData.Contains(username) && ircData.Contains("JOIN")) 195 | { 196 | return true; 197 | } 198 | } 199 | Thread.Sleep(1); 200 | } 201 | } 202 | 203 | /// 204 | /// Sends the set nickname request to the server, waits until a response is given from the server before deciding to continue 205 | /// 206 | /// Nickname 207 | /// True on success, false on error. 208 | public bool SetNickName(string nickname) 209 | { 210 | _writer.WriteLine("NICK " + nickname + Environment.NewLine); 211 | _writer.Flush(); 212 | 213 | while (true) 214 | { 215 | 216 | string ircData = _reader.ReadLine(); 217 | 218 | return CheckMessageForError(ircData); 219 | } 220 | } 221 | 222 | 223 | 224 | public bool CheckMessageForError(string message) 225 | { 226 | string codeString = message.Split(' ')[1].Trim(); 227 | if (int.TryParse(codeString, out _responseNumber)) 228 | { 229 | foreach (string errorMessage in RFC1459Codes.ListWithErrors) 230 | { 231 | if (errorMessage.Contains(codeString)) 232 | { 233 | _errorMessage = errorMessage; 234 | return false; 235 | } 236 | } 237 | 238 | _errorMessage = "Message does not contain Error Code!"; 239 | return true; 240 | } 241 | else 242 | { 243 | Debug.WriteLine("Could not parse number"); 244 | _responseNumber = 0; 245 | _errorMessage = "Message does not contain Error Code, could not parse number!"; 246 | return true; 247 | } 248 | 249 | 250 | } 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /SimpleIRCLib/RFC1459Codes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace SimpleIRCLib 8 | { 9 | /// 10 | /// Contians all the error codes specified by the RFC1459 protocol 11 | /// 12 | class RFC1459Codes 13 | { 14 | /// 15 | /// List with error messages. 16 | /// 17 | public static string[] ListWithErrors = new string[] { @" 18 | 401 ERR_NOSUCHNICK 19 | "" :No such nick/channel"" 20 | 21 | - Used to indicate the nickname parameter supplied to a 22 | command is currently unused. 23 | ", @" 24 | 25 | 402 ERR_NOSUCHSERVER 26 | "" :No such server"" 27 | 28 | - Used to indicate the server name given currently 29 | doesn't exist. 30 | ", @" 31 | 403 ERR_NOSUCHCHANNEL 32 | "" :No such channel"" 33 | 34 | - Used to indicate the given channel name is invalid. 35 | ", @" 36 | 404 ERR_CANNOTSENDTOCHAN 37 | "" :Cannot send to channel"" 38 | 39 | - Sent to a user who is either (a) not on a channel 40 | which is mode +n or (b) not a chanop (or mode +v) on 41 | a channel which has mode +m set and is trying to send 42 | a PRIVMSG message to that channel. 43 | ", @" 44 | 405 ERR_TOOMANYCHANNELS 45 | "" :You have joined too many \ 46 | channels"" 47 | - Sent to a user when they have joined the maximum 48 | number of allowed channels and they try to join 49 | another channel. 50 | ", @" 51 | 406 ERR_WASNOSUCHNICK 52 | "" :There was no such nickname"" 53 | 54 | - Returned by WHOWAS to indicate there is no history 55 | information for that nickname. 56 | ", @" 57 | 407 ERR_TOOMANYTARGETS 58 | "" :Duplicate recipients. No message delivered"" 59 | 60 | - Returned to a client which is attempting to send a 61 | PRIVMSG/NOTICE using the user@host destination format 62 | and for a user@host which has several occurrences. 63 | ", @" 64 | 409 ERR_NOORIGIN 65 | "":No origin specified"" 66 | 67 | - PING or PONG message missing the originator parameter 68 | which is required since these commands must work 69 | without valid prefixes. 70 | ", @" 71 | 411 ERR_NORECIPIENT 72 | "":No recipient given ()"" 73 | ", @" 74 | 412 ERR_NOTEXTTOSEND 75 | "":No text to send"" 76 | ", @" 77 | 413 ERR_NOTOPLEVEL 78 | "" :No toplevel domain specified"" 79 | ", @" 80 | 414 ERR_WILDTOPLEVEL 81 | "" :Wildcard in toplevel domain"" 82 | 83 | - 412 - 414 are returned by PRIVMSG to indicate that 84 | the message wasn't delivered for some reason. 85 | ERR_NOTOPLEVEL and ERR_WILDTOPLEVEL are errors that 86 | are returned when an invalid use of 87 | ""PRIVMSG $"" or ""PRIVMSG #"" is attempted. 88 | ", @" 89 | 421 ERR_UNKNOWNCOMMAND 90 | "" :Unknown command"" 91 | 92 | - Returned to a registered client to indicate that the 93 | command sent is unknown by the server. 94 | ", @" 95 | 422 ERR_NOMOTD 96 | "":MOTD File is missing"" 97 | 98 | - Server's MOTD file could not be opened by the server. 99 | ", @" 100 | 423 ERR_NOADMININFO 101 | "" :No administrative info available"" 102 | 103 | - Returned by a server in response to an ADMIN message 104 | when there is an error in finding the appropriate 105 | information. 106 | ", @" 107 | 424 ERR_FILEERROR 108 | "":File error doing on "" 109 | 110 | - Generic error message used to report a failed file 111 | operation during the processing of a message. 112 | ", @" 113 | 431 ERR_NONICKNAMEGIVEN 114 | "":No nickname given"" 115 | 116 | - Returned when a nickname parameter expected for a 117 | command and isn't found. 118 | ", @" 119 | 432 ERR_ERRONEUSNICKNAME 120 | "" :Erroneus nickname"" 121 | 122 | - Returned after receiving a NICK message which contains 123 | characters which do not fall in the defined set. See 124 | section x.x.x for details on valid nicknames. 125 | ", @" 126 | 433 ERR_NICKNAMEINUSE 127 | "" :Nickname is already in use"" 128 | 129 | - Returned when a NICK message is processed that results 130 | in an attempt to change to a currently existing 131 | nickname. 132 | ", @" 133 | 436 ERR_NICKCOLLISION 134 | "" :Nickname collision KILL"" 135 | 136 | - Returned by a server to a client when it detects a 137 | nickname collision (registered of a NICK that 138 | already exists by another server). 139 | ", @" 140 | 441 ERR_USERNOTINCHANNEL 141 | "" :They aren't on that channel"" 142 | 143 | - Returned by the server to indicate that the target 144 | user of the command is not on the given channel. 145 | ", @" 146 | 442 ERR_NOTONCHANNEL 147 | "" :You're not on that channel"" 148 | 149 | - Returned by the server whenever a client tries to 150 | perform a channel effecting command for which the 151 | client isn't a member. 152 | ", @" 153 | 443 ERR_USERONCHANNEL 154 | "" :is already on channel"" 155 | 156 | - Returned when a client tries to invite a user to a 157 | channel they are already on. 158 | ", @" 159 | 444 ERR_NOLOGIN 160 | "" :User not logged in"" 161 | 162 | - Returned by the summon after a SUMMON command for a 163 | user was unable to be performed since they were not 164 | logged in. 165 | ", @" 166 | 445 ERR_SUMMONDISABLED 167 | "":SUMMON has been disabled"" 168 | 169 | - Returned as a response to the SUMMON command. Must be 170 | returned by any server which does not implement it. 171 | ", @" 172 | 446 ERR_USERSDISABLED 173 | "":USERS has been disabled"" 174 | 175 | - Returned as a response to the USERS command. Must be 176 | returned by any server which does not implement it. 177 | ", @" 178 | 451 ERR_NOTREGISTERED 179 | "":You have not registered"" 180 | 181 | - Returned by the server to indicate that the client 182 | must be registered before the server will allow it 183 | to be parsed in detail. 184 | ", @" 185 | 461 ERR_NEEDMOREPARAMS 186 | "" :Not enough parameters"" 187 | 188 | - Returned by the server by numerous commands to 189 | indicate to the client that it didn't supply enough 190 | parameters. 191 | ", @" 192 | 462 ERR_ALREADYREGISTRED 193 | "":You may not reregister"" 194 | 195 | - Returned by the server to any link which tries to 196 | change part of the registered details (such as 197 | password or user details from second USER message). 198 | ", @" 199 | 463 ERR_NOPERMFORHOST 200 | "":Your host isn't among the privileged"" 201 | 202 | - Returned to a client which attempts to register with 203 | a server which does not been setup to allow 204 | connections from the host the attempted connection 205 | is tried. 206 | ", @" 207 | 464 ERR_PASSWDMISMATCH 208 | "":Password incorrect"" 209 | 210 | - Returned to indicate a failed attempt at registering 211 | a connection for which a password was required and 212 | was either not given or incorrect. 213 | ", @" 214 | 465 ERR_YOUREBANNEDCREEP 215 | "":You are banned from this server"" 216 | 217 | - Returned after an attempt to connect and register 218 | yourself with a server which has been setup to 219 | explicitly deny connections to you. 220 | ", @" 221 | 467 ERR_KEYSET 222 | "" :Channel key already set"" 223 | ", @" 224 | 471 ERR_CHANNELISFULL 225 | "" :Cannot join channel (+l)"" 226 | ", @" 227 | 472 ERR_UNKNOWNMODE 228 | "" :is unknown mode char to me"" 229 | ", @" 230 | 473 ERR_INVITEONLYCHAN 231 | "" :Cannot join channel (+i)"" 232 | ", @" 233 | 474 ERR_BANNEDFROMCHAN 234 | "" :Cannot join channel (+b)"" 235 | ", @" 236 | 475 ERR_BADCHANNELKEY 237 | "" :Cannot join channel (+k)"" 238 | ", @" 239 | 481 ERR_NOPRIVILEGES 240 | "":Permission Denied- You're not an IRC operator"" 241 | 242 | - Any command requiring operator privileges to operate 243 | must return this error to indicate the attempt was 244 | unsuccessful. 245 | ", @" 246 | 482 ERR_CHANOPRIVSNEEDED 247 | "" :You're not channel operator"" 248 | 249 | - Any command requiring 'chanop' privileges (such as 250 | MODE messages) must return this error if the client 251 | making the attempt is not a chanop on the specified 252 | channel. 253 | ", @" 254 | 483 ERR_CANTKILLSERVER 255 | "":You cant kill a server!"" 256 | 257 | - Any attempts to use the KILL command on a server 258 | are to be refused and this error returned directly 259 | to the client. 260 | ", @" 261 | 491 ERR_NOOPERHOST 262 | "":No O-lines for your host"" 263 | 264 | - If a client sends an OPER message and the server has 265 | not been configured to allow connections from the 266 | client's host as an operator, this error must be 267 | returned. 268 | ", @" 269 | 501 ERR_UMODEUNKNOWNFLAG 270 | "":Unknown MODE flag"" 271 | 272 | - Returned by the server to indicate that a MODE 273 | message was sent with a nickname parameter and that 274 | the a mode flag sent was not recognized. 275 | ", @" 276 | 502 ERR_USERSDONTMATCH 277 | "":Cant change mode for other users"" 278 | 279 | - Error sent to any user trying to view or change the 280 | user mode for a user other than themselves. 281 | " }; 282 | 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /FormExample/IrcClientForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace FormExample 2 | { 3 | partial class IrcClientForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.ServerInput = new System.Windows.Forms.TextBox(); 32 | this.PortInput = new System.Windows.Forms.TextBox(); 33 | this.UsernameInput = new System.Windows.Forms.TextBox(); 34 | this.ChannelsInput = new System.Windows.Forms.TextBox(); 35 | this.label1 = new System.Windows.Forms.Label(); 36 | this.label2 = new System.Windows.Forms.Label(); 37 | this.labelusername = new System.Windows.Forms.Label(); 38 | this.labelsomething = new System.Windows.Forms.Label(); 39 | this.ConnectButton = new System.Windows.Forms.Button(); 40 | this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker(); 41 | this.DisconnectButton = new System.Windows.Forms.Button(); 42 | this.MessageInput = new System.Windows.Forms.TextBox(); 43 | this.SendToAll = new System.Windows.Forms.Button(); 44 | this.DownloadsList = new System.Windows.Forms.ListBox(); 45 | this.ShowDebugButton = new System.Windows.Forms.Button(); 46 | this.SetDownloadFolderButton = new System.Windows.Forms.Button(); 47 | this.label3 = new System.Windows.Forms.Label(); 48 | this.label4 = new System.Windows.Forms.Label(); 49 | this.label5 = new System.Windows.Forms.Label(); 50 | this.DownloadProgressBar = new System.Windows.Forms.ProgressBar(); 51 | this.OpenFolderDialog = new System.Windows.Forms.FolderBrowserDialog(); 52 | this.UpdateUserList = new System.Windows.Forms.Button(); 53 | this.ircChatTabs = new System.Windows.Forms.TabControl(); 54 | this.SendToChannel = new System.Windows.Forms.Button(); 55 | this.userListTabs = new System.Windows.Forms.TabControl(); 56 | this.SuspendLayout(); 57 | // 58 | // ServerInput 59 | // 60 | this.ServerInput.Location = new System.Drawing.Point(49, 37); 61 | this.ServerInput.Name = "ServerInput"; 62 | this.ServerInput.Size = new System.Drawing.Size(162, 20); 63 | this.ServerInput.TabIndex = 0; 64 | // 65 | // PortInput 66 | // 67 | this.PortInput.Location = new System.Drawing.Point(49, 76); 68 | this.PortInput.Name = "PortInput"; 69 | this.PortInput.Size = new System.Drawing.Size(162, 20); 70 | this.PortInput.TabIndex = 1; 71 | // 72 | // UsernameInput 73 | // 74 | this.UsernameInput.Location = new System.Drawing.Point(49, 114); 75 | this.UsernameInput.Name = "UsernameInput"; 76 | this.UsernameInput.Size = new System.Drawing.Size(162, 20); 77 | this.UsernameInput.TabIndex = 2; 78 | // 79 | // ChannelsInput 80 | // 81 | this.ChannelsInput.Location = new System.Drawing.Point(49, 152); 82 | this.ChannelsInput.Name = "ChannelsInput"; 83 | this.ChannelsInput.Size = new System.Drawing.Size(162, 20); 84 | this.ChannelsInput.TabIndex = 3; 85 | // 86 | // label1 87 | // 88 | this.label1.AutoSize = true; 89 | this.label1.Location = new System.Drawing.Point(46, 21); 90 | this.label1.Name = "label1"; 91 | this.label1.Size = new System.Drawing.Size(38, 13); 92 | this.label1.TabIndex = 4; 93 | this.label1.Text = "Server"; 94 | // 95 | // label2 96 | // 97 | this.label2.AutoSize = true; 98 | this.label2.Location = new System.Drawing.Point(49, 60); 99 | this.label2.Name = "label2"; 100 | this.label2.Size = new System.Drawing.Size(26, 13); 101 | this.label2.TabIndex = 5; 102 | this.label2.Text = "Port"; 103 | // 104 | // labelusername 105 | // 106 | this.labelusername.AutoSize = true; 107 | this.labelusername.Location = new System.Drawing.Point(49, 99); 108 | this.labelusername.Name = "labelusername"; 109 | this.labelusername.Size = new System.Drawing.Size(55, 13); 110 | this.labelusername.TabIndex = 6; 111 | this.labelusername.Text = "Username"; 112 | // 113 | // labelsomething 114 | // 115 | this.labelsomething.AutoSize = true; 116 | this.labelsomething.Location = new System.Drawing.Point(49, 137); 117 | this.labelsomething.Name = "labelsomething"; 118 | this.labelsomething.Size = new System.Drawing.Size(156, 13); 119 | this.labelsomething.TabIndex = 7; 120 | this.labelsomething.Text = "Channel(s) (comma to seperate)"; 121 | // 122 | // ConnectButton 123 | // 124 | this.ConnectButton.Location = new System.Drawing.Point(49, 179); 125 | this.ConnectButton.Name = "ConnectButton"; 126 | this.ConnectButton.Size = new System.Drawing.Size(162, 23); 127 | this.ConnectButton.TabIndex = 8; 128 | this.ConnectButton.Text = "Connect"; 129 | this.ConnectButton.UseVisualStyleBackColor = true; 130 | this.ConnectButton.Click += new System.EventHandler(this.ConnectButton_Click); 131 | // 132 | // DisconnectButton 133 | // 134 | this.DisconnectButton.Location = new System.Drawing.Point(49, 208); 135 | this.DisconnectButton.Name = "DisconnectButton"; 136 | this.DisconnectButton.Size = new System.Drawing.Size(162, 23); 137 | this.DisconnectButton.TabIndex = 9; 138 | this.DisconnectButton.Text = "Disconnect"; 139 | this.DisconnectButton.UseVisualStyleBackColor = true; 140 | this.DisconnectButton.Click += new System.EventHandler(this.DisconnectButton_Click); 141 | // 142 | // MessageInput 143 | // 144 | this.MessageInput.Location = new System.Drawing.Point(233, 311); 145 | this.MessageInput.Name = "MessageInput"; 146 | this.MessageInput.Size = new System.Drawing.Size(500, 20); 147 | this.MessageInput.TabIndex = 11; 148 | this.MessageInput.KeyDown += new System.Windows.Forms.KeyEventHandler(this.MessageInput_KeyDown); 149 | // 150 | // SendToAll 151 | // 152 | this.SendToAll.Location = new System.Drawing.Point(752, 309); 153 | this.SendToAll.Name = "SendToAll"; 154 | this.SendToAll.Size = new System.Drawing.Size(83, 23); 155 | this.SendToAll.TabIndex = 12; 156 | this.SendToAll.Text = "Send To All"; 157 | this.SendToAll.UseVisualStyleBackColor = true; 158 | this.SendToAll.Click += new System.EventHandler(this.SendToAll_Click); 159 | // 160 | // DownloadsList 161 | // 162 | this.DownloadsList.FormattingEnabled = true; 163 | this.DownloadsList.HorizontalScrollbar = true; 164 | this.DownloadsList.Location = new System.Drawing.Point(106, 359); 165 | this.DownloadsList.Name = "DownloadsList"; 166 | this.DownloadsList.ScrollAlwaysVisible = true; 167 | this.DownloadsList.Size = new System.Drawing.Size(854, 121); 168 | this.DownloadsList.TabIndex = 13; 169 | this.DownloadsList.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.DownloadsList_MouseDoubleClick); 170 | // 171 | // ShowDebugButton 172 | // 173 | this.ShowDebugButton.Location = new System.Drawing.Point(49, 237); 174 | this.ShowDebugButton.Name = "ShowDebugButton"; 175 | this.ShowDebugButton.Size = new System.Drawing.Size(162, 23); 176 | this.ShowDebugButton.TabIndex = 14; 177 | this.ShowDebugButton.Text = "Show Debug"; 178 | this.ShowDebugButton.UseVisualStyleBackColor = true; 179 | this.ShowDebugButton.Click += new System.EventHandler(this.ShowDebugButton_Click); 180 | // 181 | // SetDownloadFolderButton 182 | // 183 | this.SetDownloadFolderButton.Location = new System.Drawing.Point(49, 266); 184 | this.SetDownloadFolderButton.Name = "SetDownloadFolderButton"; 185 | this.SetDownloadFolderButton.Size = new System.Drawing.Size(162, 23); 186 | this.SetDownloadFolderButton.TabIndex = 15; 187 | this.SetDownloadFolderButton.Text = "Choose Download Folder"; 188 | this.SetDownloadFolderButton.UseVisualStyleBackColor = true; 189 | this.SetDownloadFolderButton.Click += new System.EventHandler(this.SetDownloadFolderButton_Click); 190 | // 191 | // label3 192 | // 193 | this.label3.AutoSize = true; 194 | this.label3.Location = new System.Drawing.Point(241, 21); 195 | this.label3.Name = "label3"; 196 | this.label3.Size = new System.Drawing.Size(32, 13); 197 | this.label3.TabIndex = 16; 198 | this.label3.Text = "Chat:"; 199 | // 200 | // label4 201 | // 202 | this.label4.AutoSize = true; 203 | this.label4.Location = new System.Drawing.Point(46, 346); 204 | this.label4.Name = "label4"; 205 | this.label4.Size = new System.Drawing.Size(63, 13); 206 | this.label4.TabIndex = 17; 207 | this.label4.Text = "Downloads:"; 208 | // 209 | // label5 210 | // 211 | this.label5.AutoSize = true; 212 | this.label5.Location = new System.Drawing.Point(49, 486); 213 | this.label5.Name = "label5"; 214 | this.label5.Size = new System.Drawing.Size(51, 13); 215 | this.label5.TabIndex = 18; 216 | this.label5.Text = "Progress:"; 217 | // 218 | // DownloadProgressBar 219 | // 220 | this.DownloadProgressBar.Location = new System.Drawing.Point(106, 495); 221 | this.DownloadProgressBar.Name = "DownloadProgressBar"; 222 | this.DownloadProgressBar.Size = new System.Drawing.Size(854, 23); 223 | this.DownloadProgressBar.TabIndex = 19; 224 | // 225 | // UpdateUserList 226 | // 227 | this.UpdateUserList.Location = new System.Drawing.Point(966, 495); 228 | this.UpdateUserList.Name = "UpdateUserList"; 229 | this.UpdateUserList.Size = new System.Drawing.Size(229, 23); 230 | this.UpdateUserList.TabIndex = 21; 231 | this.UpdateUserList.Text = "Update User List"; 232 | this.UpdateUserList.UseVisualStyleBackColor = true; 233 | this.UpdateUserList.Click += new System.EventHandler(this.UpdateUserList_Click); 234 | // 235 | // ircChatTabs 236 | // 237 | this.ircChatTabs.Location = new System.Drawing.Point(233, 37); 238 | this.ircChatTabs.Name = "ircChatTabs"; 239 | this.ircChatTabs.SelectedIndex = 0; 240 | this.ircChatTabs.Size = new System.Drawing.Size(727, 252); 241 | this.ircChatTabs.TabIndex = 22; 242 | // 243 | // SendToChannel 244 | // 245 | this.SendToChannel.Location = new System.Drawing.Point(841, 309); 246 | this.SendToChannel.Name = "SendToChannel"; 247 | this.SendToChannel.Size = new System.Drawing.Size(112, 23); 248 | this.SendToChannel.TabIndex = 23; 249 | this.SendToChannel.Text = "Send To Channel"; 250 | this.SendToChannel.UseVisualStyleBackColor = true; 251 | this.SendToChannel.Click += new System.EventHandler(this.SendToChannel_Click); 252 | // 253 | // userListTabs 254 | // 255 | this.userListTabs.Location = new System.Drawing.Point(966, 37); 256 | this.userListTabs.Name = "userListTabs"; 257 | this.userListTabs.SelectedIndex = 0; 258 | this.userListTabs.Size = new System.Drawing.Size(229, 452); 259 | this.userListTabs.TabIndex = 24; 260 | // 261 | // IrcClientForm 262 | // 263 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 264 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 265 | this.ClientSize = new System.Drawing.Size(1207, 530); 266 | this.Controls.Add(this.userListTabs); 267 | this.Controls.Add(this.SendToChannel); 268 | this.Controls.Add(this.ircChatTabs); 269 | this.Controls.Add(this.UpdateUserList); 270 | this.Controls.Add(this.DownloadProgressBar); 271 | this.Controls.Add(this.label5); 272 | this.Controls.Add(this.label4); 273 | this.Controls.Add(this.label3); 274 | this.Controls.Add(this.SetDownloadFolderButton); 275 | this.Controls.Add(this.ShowDebugButton); 276 | this.Controls.Add(this.DownloadsList); 277 | this.Controls.Add(this.SendToAll); 278 | this.Controls.Add(this.MessageInput); 279 | this.Controls.Add(this.DisconnectButton); 280 | this.Controls.Add(this.ConnectButton); 281 | this.Controls.Add(this.labelsomething); 282 | this.Controls.Add(this.labelusername); 283 | this.Controls.Add(this.label2); 284 | this.Controls.Add(this.label1); 285 | this.Controls.Add(this.ChannelsInput); 286 | this.Controls.Add(this.UsernameInput); 287 | this.Controls.Add(this.PortInput); 288 | this.Controls.Add(this.ServerInput); 289 | this.Name = "IrcClientForm"; 290 | this.Text = "SimpleIRCLib Irc Client"; 291 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing); 292 | this.ResumeLayout(false); 293 | this.PerformLayout(); 294 | 295 | } 296 | 297 | #endregion 298 | 299 | private System.Windows.Forms.TextBox ServerInput; 300 | private System.Windows.Forms.TextBox PortInput; 301 | private System.Windows.Forms.TextBox UsernameInput; 302 | private System.Windows.Forms.TextBox ChannelsInput; 303 | private System.Windows.Forms.Label label1; 304 | private System.Windows.Forms.Label label2; 305 | private System.Windows.Forms.Label labelusername; 306 | private System.Windows.Forms.Label labelsomething; 307 | private System.Windows.Forms.Button ConnectButton; 308 | private System.ComponentModel.BackgroundWorker backgroundWorker1; 309 | private System.Windows.Forms.Button DisconnectButton; 310 | private System.Windows.Forms.TextBox MessageInput; 311 | private System.Windows.Forms.Button SendToAll; 312 | private System.Windows.Forms.ListBox DownloadsList; 313 | private System.Windows.Forms.Button ShowDebugButton; 314 | private System.Windows.Forms.Button SetDownloadFolderButton; 315 | private System.Windows.Forms.Label label3; 316 | private System.Windows.Forms.Label label4; 317 | private System.Windows.Forms.Label label5; 318 | private System.Windows.Forms.ProgressBar DownloadProgressBar; 319 | private System.Windows.Forms.FolderBrowserDialog OpenFolderDialog; 320 | private System.Windows.Forms.Button UpdateUserList; 321 | private System.Windows.Forms.TabControl ircChatTabs; 322 | private System.Windows.Forms.Button SendToChannel; 323 | private System.Windows.Forms.TabControl userListTabs; 324 | } 325 | } 326 | 327 | -------------------------------------------------------------------------------- /FormExample/IrcClientForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using System.IO; 4 | using System.Diagnostics; 5 | //the library 6 | using SimpleIRCLib; 7 | using System.Collections.Generic; 8 | 9 | namespace FormExample 10 | { 11 | /// 12 | /// This class is meant as example on how to use SimpleIRCLib, this does not mean that this is the correct way to program! 13 | /// It's meant to showcase a few of the available methods within SimpleIRCLib, you should figure out on your own how to implement it to suit your needs! 14 | /// It lacks a few options, such as leaving a specific channel, which will be implemented in the future. If your knowledged, you could send a raw message 15 | /// to the server containing commands to PART from a channel and use the OnRawMessageReceived event to check the server response. 16 | /// 17 | public partial class IrcClientForm : Form 18 | { 19 | //initiate irc client 20 | private readonly SimpleIRC _irc; 21 | 22 | //initiate debugform 23 | private readonly DebugForm _debugForm; 24 | 25 | private string _defaultDownloadDirectory; 26 | 27 | /// 28 | /// Form Contstructor, initializes SimpleIRC Library and registers event handlers. 29 | /// 30 | public IrcClientForm() 31 | { 32 | _irc = new SimpleIRC(); 33 | _irc.IrcClient.OnMessageReceived += OnMessagesReceived; 34 | _irc.IrcClient.OnUserListReceived += OnUserListReceived; 35 | _irc.DccClient.OnDccEvent += OnDccEvent; 36 | _debugForm = new DebugForm(_irc); 37 | _defaultDownloadDirectory = Directory.GetCurrentDirectory(); 38 | 39 | InitializeComponent(); 40 | } 41 | 42 | /// 43 | /// Gets the values from the input fields and starts the client 44 | /// 45 | /// 46 | /// 47 | public void ConnectButton_Click(object sender, EventArgs e) 48 | { 49 | if (ServerInput.Text != "" && PortInput.Text != "" && UsernameInput.Text != "" && ChannelsInput.Text != "" && _irc.IsClientRunning() == false) 50 | { 51 | int port = -1; 52 | if ((port = int.Parse(PortInput.Text)) != -1) 53 | { 54 | //parameters as follows: ip or address to irc server, username, password(not functional), channels, and method to execute when message is received (see line 103) 55 | _irc.SetupIrc(ServerInput.Text, UsernameInput.Text, ChannelsInput.Text, int.Parse(PortInput.Text)); 56 | 57 | //Sets event handlers for all the possible events (!IMPORTANT: do this after intializing irc.SetupIRC !!!) 58 | 59 | 60 | _irc.StartClient(); 61 | } 62 | } else 63 | { 64 | MessageBox.Show("You need to fill in all the information fields!"); 65 | } 66 | } 67 | 68 | /// 69 | /// Disconnects the irc client, closes all open tabs. 70 | /// 71 | /// 72 | /// 73 | public void DisconnectButton_Click(object sender, EventArgs e) 74 | { 75 | if (_irc.StopClient()) 76 | { 77 | ircChatTabs.TabPages.Clear(); 78 | userListTabs.TabPages.Clear(); 79 | } 80 | } 81 | 82 | /// 83 | /// Sends if enter is pressed. 84 | /// 85 | /// 86 | /// 87 | public void MessageInput_KeyDown(object sender, KeyEventArgs e) 88 | { 89 | if(e.KeyCode == Keys.Enter) 90 | { 91 | if (MessageInput.Text != "" && _irc.IsClientRunning()) 92 | { 93 | _irc.SendMessageToAll(MessageInput.Text); 94 | } 95 | } 96 | 97 | } 98 | 99 | /// 100 | /// Event handler for receiving messages from the Irc Client. 101 | /// 102 | /// Values of the class that fired the event 103 | /// IrcReceivedEventArgs containing the message information 104 | public void OnMessagesReceived(object sender, IrcReceivedEventArgs args) 105 | { 106 | OnMessagesReceivedLocal(args.Channel, args.User, args.Message); 107 | } 108 | 109 | /// 110 | /// Method that gets invoked on the main thread, adds a message to the richtextbox within a the correct channel tab. 111 | /// 112 | /// channel messaged was received on 113 | /// user that send the message to the channel 114 | /// message that the user had send on the channel 115 | public void OnMessagesReceivedLocal(string channel, string user, string message) 116 | { 117 | if (this.ircChatTabs.InvokeRequired) 118 | { 119 | this.ircChatTabs.Invoke(new MethodInvoker(() => OnMessagesReceivedLocal(channel, user, message))); 120 | } 121 | else 122 | { 123 | //searches for the tab for the correct channel 124 | bool found = false; 125 | int index = 0; 126 | foreach (TabPage tab in ircChatTabs.TabPages) 127 | { 128 | if (channel.Contains(tab.Name)) 129 | { 130 | found = true; 131 | break; 132 | } 133 | 134 | index++; 135 | } 136 | 137 | //if the tab has been found, add a message to the richtextbox within that tab. 138 | if (found) 139 | { 140 | if (ircChatTabs.TabPages[index].Controls.ContainsKey(channel)) 141 | { 142 | RichTextBox selectedRtb = (RichTextBox)ircChatTabs.TabPages[index].Controls[channel]; 143 | selectedRtb.AppendText(user + " : " + message + Environment.NewLine); 144 | selectedRtb.ScrollToCaret(); 145 | } 146 | } 147 | 148 | } 149 | } 150 | 151 | /// 152 | /// Event that gets fired when a user list has been received. 153 | /// 154 | /// Values of the class that fired the event 155 | /// IrcUserListReceivedEventArgs contains the Dictionary where the key is the channel and the list contains the usernames 156 | public void OnUserListReceived(object sender, IrcUserListReceivedEventArgs args ) 157 | { 158 | OnUserListReceivedLocal(args.UsersPerChannel); 159 | } 160 | 161 | /// 162 | /// Method to invoke on the main thread, checks if a tab for the chat exists with name of the channel, if not, it creates it, same goes for the tab with the user name list. 163 | /// 164 | /// Dictionary where the key is the channel and the list contains the usernames 165 | public void OnUserListReceivedLocal(Dictionary> userList) 166 | { 167 | if (this.InvokeRequired) 168 | { 169 | this.Invoke(new MethodInvoker(() => OnUserListReceivedLocal(userList))); 170 | } 171 | else 172 | { 173 | //iterate through each channel 174 | foreach (KeyValuePair> channelsAndUsers in userList) 175 | { 176 | //search for a tab with the same channel name within the chatTabs 177 | bool foundChatTab = false; 178 | int indexChatTab = 0; 179 | foreach (TabPage tab in ircChatTabs.TabPages) 180 | { 181 | if (channelsAndUsers.Key.Equals(tab.Name)) 182 | { 183 | Debug.WriteLine("FOUND TAB: " + tab.Name); 184 | foundChatTab = true; 185 | break; 186 | } 187 | 188 | indexChatTab++; 189 | } 190 | 191 | if (!foundChatTab) 192 | { 193 | TabPage newTab = new TabPage(channelsAndUsers.Key); 194 | newTab.Name = channelsAndUsers.Key; 195 | RichTextBox rtb = new RichTextBox(); 196 | rtb.Dock = DockStyle.Fill; 197 | rtb.BorderStyle = BorderStyle.None; 198 | rtb.Name = channelsAndUsers.Key; 199 | newTab.Controls.Add(rtb); 200 | ircChatTabs.TabPages.Add(newTab); 201 | } 202 | 203 | //search for a tab with the same channel name within the userListTabs 204 | bool foundUserListTab = false; 205 | int userListTabIndex = 0; 206 | foreach (TabPage tab in userListTabs.TabPages) 207 | { 208 | if (channelsAndUsers.Key.Equals(tab.Name)) 209 | { 210 | foundUserListTab = true; 211 | break; 212 | } 213 | 214 | userListTabIndex++; 215 | } 216 | 217 | if (!foundUserListTab) 218 | { 219 | TabPage newTab = new TabPage(channelsAndUsers.Key); 220 | newTab.Name = channelsAndUsers.Key; 221 | RichTextBox rtb = new RichTextBox(); 222 | rtb.Dock = DockStyle.Fill; 223 | rtb.BorderStyle = BorderStyle.None; 224 | rtb.Name = channelsAndUsers.Key; 225 | foreach (string user in channelsAndUsers.Value) 226 | { 227 | rtb.AppendText(user + Environment.NewLine); 228 | } 229 | rtb.ScrollToCaret(); 230 | newTab.Controls.Add(rtb); 231 | userListTabs.TabPages.Add(newTab); 232 | } 233 | else 234 | { 235 | 236 | if (userListTabs.TabPages[userListTabIndex].Controls.ContainsKey(channelsAndUsers.Key)) 237 | { 238 | RichTextBox selectedRtb = (RichTextBox)userListTabs.TabPages[userListTabIndex].Controls[channelsAndUsers.Key]; 239 | foreach (string user in channelsAndUsers.Value) 240 | { 241 | selectedRtb.AppendText(user + Environment.NewLine); 242 | } 243 | selectedRtb.ScrollToCaret(); 244 | } 245 | } 246 | } 247 | } 248 | } 249 | 250 | /// 251 | /// Event that fires when DCCClient starts downloading. 252 | /// 253 | /// Values of the class that fired the event 254 | /// DCCEventArgs contains all the information about the download update 255 | public void OnDccEvent(object sender, DCCEventArgs args) 256 | { 257 | string fileName = args.FileName; 258 | int downloadProgress = args.Progress; 259 | string downloadSpeed = args.KBytesPerSecond.ToString(); 260 | string status = args.Status; 261 | 262 | string fullDownloadInformation = fileName + " | " + status + " | " + downloadSpeed + " kb/s | " + _defaultDownloadDirectory; 263 | 264 | UpdateDownloadList(fullDownloadInformation, fileName); 265 | 266 | UpdateProgressBar(downloadProgress); 267 | 268 | if (status.Contains("COMPLETED")) 269 | { 270 | UpdateProgressBar(100); 271 | } 272 | 273 | } 274 | 275 | /// 276 | /// Updates the DownloadList object on the main form while the download is going, invoke is necesary because 277 | /// method is being called from a different Thread! 278 | /// 279 | /// string that needs to be added/updated 280 | /// the filename which is used for searching the item in the download list for updating 281 | public void UpdateDownloadList(string toUpdate, string fileName) 282 | { 283 | if (this.DownloadsList.InvokeRequired) 284 | { 285 | this.DownloadsList.Invoke(new MethodInvoker(() => UpdateDownloadList(toUpdate, fileName))); 286 | } 287 | else 288 | { 289 | int indexOfDownloadItem = 0; 290 | for (int i = indexOfDownloadItem; i < DownloadsList.Items.Count; ++i) 291 | { 292 | string lbString = DownloadsList.Items[i].ToString(); 293 | if (lbString.Contains(fileName)) 294 | { 295 | indexOfDownloadItem = i; 296 | break; 297 | } 298 | } 299 | 300 | try 301 | { 302 | DownloadsList.Items.RemoveAt(indexOfDownloadItem); 303 | DownloadsList.Items.Insert(indexOfDownloadItem, toUpdate); 304 | DownloadsList.SelectedIndex = indexOfDownloadItem; 305 | } 306 | catch 307 | { 308 | DownloadsList.Items.Add(toUpdate); 309 | } 310 | } 311 | } 312 | 313 | /// 314 | /// Updates the progress bar 315 | /// 316 | /// defines the current progress 317 | public void UpdateProgressBar(int progress) 318 | { 319 | if (this.DownloadProgressBar.InvokeRequired) 320 | { 321 | this.DownloadProgressBar.Invoke(new MethodInvoker(() => UpdateProgressBar(progress))); 322 | } else 323 | { 324 | this.DownloadProgressBar.Value = progress; 325 | } 326 | } 327 | 328 | /// 329 | /// Opens the debug form 330 | /// 331 | /// 332 | /// 333 | public void ShowDebugButton_Click(object sender, EventArgs e) 334 | { 335 | try 336 | { 337 | _debugForm.Show(); 338 | } catch 339 | { 340 | 341 | } 342 | } 343 | 344 | /// 345 | /// Opens the folder where the selected file is being downloaded to 346 | /// 347 | /// 348 | /// 349 | public void DownloadsList_MouseDoubleClick(object sender, MouseEventArgs e) 350 | { 351 | int currentlySelected = DownloadsList.SelectedIndex; 352 | try 353 | { 354 | string currentItem = DownloadsList.Items[currentlySelected].ToString(); 355 | 356 | if (currentItem.Contains("|")) 357 | { 358 | string fileLocation = currentItem.Split('|')[currentItem.Split('|').Length - 1].Trim(); 359 | Process.Start(fileLocation); 360 | } 361 | } 362 | catch 363 | { 364 | 365 | } 366 | } 367 | 368 | /// 369 | /// Set download directory to a custom directory 370 | /// 371 | /// 372 | /// 373 | public void SetDownloadFolderButton_Click(object sender, EventArgs e) 374 | { 375 | DialogResult result = OpenFolderDialog.ShowDialog(); 376 | if (result == DialogResult.OK) 377 | { 378 | string newDownloadDirectory = OpenFolderDialog.SelectedPath; 379 | _defaultDownloadDirectory = newDownloadDirectory; 380 | _irc.SetCustomDownloadDir(newDownloadDirectory); 381 | } 382 | } 383 | 384 | /// 385 | /// Stops the irc client on form close, otherwise it would keep running in the background!!! 386 | /// 387 | /// 388 | /// 389 | public void Form1_FormClosing(object sender, FormClosingEventArgs e) 390 | { 391 | if (_irc.IsClientRunning()) 392 | { 393 | _irc.StopClient(); 394 | } 395 | } 396 | 397 | /// 398 | /// Gets the users in the current channel. 399 | /// 400 | /// 401 | /// 402 | public void UpdateUserList_Click(object sender, EventArgs e) 403 | { 404 | RichTextBox selectedRtb = (RichTextBox)userListTabs.SelectedTab.Controls[0]; 405 | selectedRtb.Clear(); 406 | if (_irc.IsClientRunning()) 407 | { 408 | _irc.GetUsersInDifferentChannel(userListTabs.SelectedTab.Name); 409 | } 410 | } 411 | 412 | /// 413 | /// Sends a message to a specific channel. 414 | /// 415 | /// 416 | /// 417 | public void SendToChannel_Click(object sender, EventArgs e) 418 | { 419 | string channel = ircChatTabs.SelectedTab.Name; 420 | _irc.SendMessageToChannel(MessageInput.Text, channel); 421 | } 422 | 423 | /// 424 | /// Sends a message to all channels. 425 | /// 426 | /// 427 | /// 428 | public void SendToAll_Click(object sender, EventArgs e) 429 | { 430 | _irc.SendMessageToAll(MessageInput.Text); 431 | } 432 | 433 | } 434 | } 435 | -------------------------------------------------------------------------------- /SimpleIRCLib/DCCClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | using System.Net; 4 | using System.Net.Sockets; 5 | using System.Threading; 6 | using System.IO; 7 | using System.Text; 8 | using System.Collections.Generic; 9 | 10 | namespace SimpleIRCLib 11 | { 12 | /// 13 | /// Class for downloading files using the DCC protocol on a sperarate thread from the main IRC Client thread. 14 | /// 15 | public class DCCClient 16 | { 17 | 18 | /// 19 | /// For firing update event using DCCEventArgs from DCCEventArgs.cs 20 | /// 21 | public event EventHandler OnDccEvent; 22 | /// 23 | /// For firing debug event using DCCDebugMessageArgs from DCCEventArgs.cs 24 | /// 25 | public event EventHandler OnDccDebugMessage; 26 | 27 | /// 28 | /// Raw DCC String used for getting the file location (server) and some basic file information 29 | /// 30 | public string NewDccString { get; set; } 31 | /// 32 | /// File name of the file being downloaded 33 | /// 34 | public string NewFileName { get; set; } 35 | /// 36 | /// Pack ID of file on bot where file resides 37 | /// 38 | public int NewPortNum { get; set; } 39 | /// 40 | /// FileSize of the file being downloaded 41 | /// 42 | public Int64 NewFileSize { get; set; } 43 | /// 44 | /// Port of server of file location 45 | /// 46 | public string NewIP{ get; set; } 47 | /// 48 | /// Progress from 0-100 (%) 49 | /// 50 | public int Progress { get; set; } 51 | /// 52 | /// Download status, such as: WAITING,DOWNLOADING,FAILED:[ERROR],ABORTED 53 | /// 54 | public string Status { get; set; } 55 | /// 56 | /// Download speed in: KB/s 57 | /// 58 | public Int64 BytesPerSecond { get; set; } 59 | /// 60 | /// Download speed in: MB/s 61 | /// 62 | public int KBytesPerSecond { get; set; } 63 | /// 64 | /// Download status, such as: WAITING,DOWNLOADING,FAILED:[ERROR],ABORTED 65 | /// 66 | public int MBytesPerSecond { get; set; } 67 | /// 68 | /// Bot name where file resides 69 | /// 70 | public string BotName { get; set; } 71 | /// 72 | /// Pack ID of file on bot where file resides 73 | /// 74 | public string PackNum { get; set; } 75 | /// 76 | /// Check for status of DCCClient 77 | /// 78 | public bool IsDownloading { get; set; } 79 | /// 80 | /// Path to the file that is being downloaded, or has been downloaded 81 | /// 82 | public string CurrentFilePath { get; set; } 83 | 84 | /// 85 | /// To provide the latest data downloaded to outside the library 86 | /// 87 | public List Buffer { get; set; } 88 | 89 | /// 90 | /// Local bool to tell the while loop within the download thread to stop. 91 | /// 92 | private bool _shouldAbort = false; 93 | 94 | 95 | 96 | /// 97 | /// Client that is currently running, used for sending abort messages when a download fails, or a dcc string fails to parse. 98 | /// 99 | private IrcClient _ircClient; 100 | 101 | /// 102 | /// Current download directory that will be used when starting a download 103 | /// 104 | private string _curDownloadDir; 105 | 106 | /// 107 | /// Thread where download logic is running 108 | /// 109 | private Thread _downloader; 110 | 111 | /// 112 | /// Initial constructor. 113 | /// 114 | public DCCClient() 115 | { 116 | IsDownloading = false; 117 | } 118 | 119 | /// 120 | /// Starts a downloader by parsing the received message from the irc server on information 121 | /// 122 | /// message from irc server 123 | /// download directory 124 | /// bot where the file came from 125 | /// pack on bot where the file came from 126 | /// irc client used the moment it received the dcc message, used for sending abort messages when download fails unexpectedly 127 | public void StartDownloader(string dccString, string downloaddir, string bot, string pack, IrcClient client) 128 | { 129 | if ((dccString ?? downloaddir ?? bot ?? pack) != null && dccString.Contains("SEND") && !IsDownloading) 130 | { 131 | NewDccString = dccString; 132 | _curDownloadDir = downloaddir; 133 | BotName = bot; 134 | PackNum = pack; 135 | _ircClient = client; 136 | 137 | //parsing the data for downloader thread 138 | 139 | UpdateStatus("PARSING"); 140 | bool isParsed = ParseData(dccString); 141 | 142 | //try to set the necesary information for the downloader 143 | if (isParsed) 144 | { 145 | _shouldAbort = false; 146 | //start the downloader thread 147 | _downloader = new Thread(new ThreadStart(this.Downloader)); 148 | _downloader.IsBackground = true; 149 | _downloader.Start(); 150 | } 151 | else 152 | { 153 | OnDccDebugMessage?.Invoke(this, 154 | new DCCDebugMessageArgs( 155 | "Can't parse dcc string and start downloader, failed to parse data, removing from que\n", "DCC STARTER")); 156 | _ircClient.SendMessageToAll("/msg " + BotName + " xdcc remove " + PackNum); 157 | _ircClient.SendMessageToAll("/msg " + BotName + " xdcc cancel"); 158 | } 159 | } 160 | else 161 | { 162 | if (IsDownloading) 163 | { 164 | OnDccDebugMessage?.Invoke(this, 165 | new DCCDebugMessageArgs("You are already downloading! Ignore SEND request\n", "DCC STARTER")); 166 | } 167 | else 168 | { 169 | OnDccDebugMessage?.Invoke(this, 170 | new DCCDebugMessageArgs("DCC String does not contain SEND and/or invalid values for parsing! Ignore SEND request\n", "DCC STARTER")); 171 | } 172 | } 173 | } 174 | 175 | /// 176 | /// Parses the received DCC string 177 | /// 178 | /// dcc string 179 | /// returns true if parsing was succesfull, false if failed 180 | private bool ParseData(string dccString) 181 | { 182 | /* 183 | * :_bot PRIVMSG nickname :DCC SEND \"filename\" ip_networkbyteorder port filesize 184 | *AnimeDispenser!~desktop@Rizon-6AA4F43F.ip-37-187-118.eu PRIVMSG WeebIRCDev :DCC SEND "[LNS] Death Parade - 02 [BD 720p] [7287AE5C].mkv" 633042523 59538 258271780 185 | *HelloKitty!~nyaa@ny.aa.ny.aa PRIVMSG WeebIRCDev :DCC SEND [Coalgirls]_Spirited_Away_(1280x692_Blu-ray_FLAC)_[5805EE6B].mkv 3281692293 35567 10393049211 186 | :[EWG]-bOnez!EWG@CRiTEN-BB8A59E9.ip-158-69-126.net PRIVMSG LittleWeeb_jtokck :DCC SEND The.Good.Doctor.S01E13.Seven.Reasons.1080p.AMZN.WEB-DL.DD+5.1.H.264-QOQ.mkv 2655354388 55000 1821620363 187 | *Ginpa2:DCC SEND "[HorribleSubs] Dies Irae - 05 [480p].mkv" 84036312 35016 153772128 188 | */ 189 | 190 | dccString = RemoveSpecialCharacters(dccString).Substring(1); 191 | OnDccDebugMessage?.Invoke(this, 192 | new DCCDebugMessageArgs("DCCClient: DCC STRING: " + dccString, "DCC PARSER")); 193 | 194 | 195 | if (!dccString.Contains(" :DCC")) 196 | { 197 | BotName = dccString.Split(':')[0]; 198 | if (dccString.Contains("\"")) 199 | { 200 | NewFileName = dccString.Split('"')[1]; 201 | 202 | OnDccDebugMessage?.Invoke(this, 203 | new DCCDebugMessageArgs("DCCClient1: FILENAME PARSED: " + NewFileName, "DCC PARSER")); 204 | string[] thaimportantnumbers = dccString.Split('"')[2].Trim().Split(' '); 205 | if (thaimportantnumbers[0].Contains(":")) 206 | { 207 | NewIP= thaimportantnumbers[0]; 208 | } 209 | else 210 | { 211 | try 212 | { 213 | 214 | OnDccDebugMessage?.Invoke(this, 215 | new DCCDebugMessageArgs("DCCClient1: PARSING FOLLOWING IPBYTES: " + thaimportantnumbers[0], "DCC PARSER")); 216 | string ipAddress = UInt64ToIPAddress(Int64.Parse(thaimportantnumbers[0])); 217 | NewIP= ipAddress; 218 | } 219 | catch 220 | { 221 | return false; 222 | } 223 | } 224 | 225 | OnDccDebugMessage?.Invoke(this, 226 | new DCCDebugMessageArgs("DCCClient1: IP PARSED: " + NewIP, "DCC PARSER")); 227 | NewPortNum = int.Parse(thaimportantnumbers[1]); 228 | NewFileSize = Int64.Parse(thaimportantnumbers[2]); 229 | 230 | return true; 231 | } 232 | else 233 | { 234 | NewFileName = dccString.Split(' ')[2]; 235 | 236 | 237 | OnDccDebugMessage?.Invoke(this, 238 | new DCCDebugMessageArgs("DCCClient2: FILENAME PARSED: " + NewFileName, "DCC PARSER")); 239 | 240 | if (dccString.Split(' ')[3].Contains(":")) 241 | { 242 | NewIP= dccString.Split(' ')[3]; 243 | } 244 | else 245 | { 246 | try 247 | { 248 | 249 | 250 | OnDccDebugMessage?.Invoke(this, 251 | new DCCDebugMessageArgs("DCCClient2: PARSING FOLLOWING IPBYTES DIRECTLY: " + dccString.Split(' ')[3], "DCC PARSER")); 252 | string ipAddress = UInt64ToIPAddress(Int64.Parse(dccString.Split(' ')[3])); 253 | NewIP= ipAddress; 254 | } 255 | catch 256 | { 257 | 258 | return false; 259 | } 260 | } 261 | OnDccDebugMessage?.Invoke(this, 262 | new DCCDebugMessageArgs("DCCClient2: IP PARSED: " + NewIP, "DCC PARSER")); 263 | NewPortNum = int.Parse(dccString.Split(' ')[4]); 264 | NewFileSize = Int64.Parse(dccString.Split(' ')[5]); 265 | return true; 266 | } 267 | } else 268 | { 269 | BotName = dccString.Split('!')[0]; 270 | if (dccString.Contains("\"")) 271 | { 272 | NewFileName = dccString.Split('"')[1]; 273 | 274 | OnDccDebugMessage?.Invoke(this, 275 | new DCCDebugMessageArgs("DCCClient3: FILENAME PARSED: " + NewFileName, "DCC PARSER")); 276 | string[] thaimportantnumbers = dccString.Split('"')[2].Trim().Split(' '); 277 | 278 | if (thaimportantnumbers[0].Contains(":")) 279 | { 280 | NewIP= thaimportantnumbers[0]; 281 | } 282 | else 283 | { 284 | try 285 | { 286 | 287 | OnDccDebugMessage?.Invoke(this, 288 | new DCCDebugMessageArgs("DCCClient3: PARSING FOLLOWING IPBYTES DIRECTLY: " + thaimportantnumbers[0], "DCC PARSER")); 289 | string ipAddress = UInt64ToIPAddress(Int64.Parse(thaimportantnumbers[0])); 290 | NewIP= ipAddress; 291 | } 292 | catch 293 | { 294 | return false; 295 | } 296 | } 297 | 298 | 299 | OnDccDebugMessage?.Invoke(this, 300 | new DCCDebugMessageArgs("DCCClient3: IP PARSED: " + NewIP, "DCC PARSER")); 301 | NewPortNum = int.Parse(thaimportantnumbers[1]); 302 | NewFileSize = Int64.Parse(thaimportantnumbers[2]); 303 | return true; 304 | } else 305 | { 306 | NewFileName = dccString.Split(' ')[5]; 307 | 308 | OnDccDebugMessage?.Invoke(this, 309 | new DCCDebugMessageArgs("DCCClient4: FILENAME PARSED: " + NewFileName, "DCC PARSER")); 310 | 311 | if (dccString.Split(' ')[6].Contains(":")) 312 | { 313 | NewIP= dccString.Split(' ')[6]; 314 | } else 315 | { 316 | try 317 | { 318 | 319 | OnDccDebugMessage?.Invoke(this, 320 | new DCCDebugMessageArgs("DCCClient4: PARSING FOLLOWING IPBYTES DIRECTLY: " + dccString.Split(' ')[6], "DCC PARSER")); 321 | string ipAddress = UInt64ToIPAddress(Int64.Parse(dccString.Split(' ')[6])); 322 | NewIP= ipAddress; 323 | } 324 | catch 325 | { 326 | return false; 327 | } 328 | 329 | } 330 | 331 | OnDccDebugMessage?.Invoke(this, 332 | new DCCDebugMessageArgs("DCCClient4: IP PARSED: " + NewIP, "DCC PARSER")); 333 | NewPortNum = int.Parse(dccString.Split(' ')[7]); 334 | NewFileSize = Int64.Parse(dccString.Split(' ')[8]); 335 | return true; 336 | 337 | } 338 | 339 | 340 | } 341 | 342 | } 343 | 344 | /// 345 | /// Method ran within downloader thread, starts a connection to the file server, and receives the file accordingly, sends updates using event handler during the download. 346 | /// 347 | public void Downloader() 348 | { 349 | 350 | UpdateStatus("WAITING"); 351 | 352 | Buffer = new List(); 353 | 354 | //combining download directory path with filename 355 | 356 | if (_curDownloadDir != null) 357 | { 358 | if (_curDownloadDir != string.Empty) 359 | { 360 | if (_curDownloadDir.Length > 0) 361 | { 362 | if (!Directory.Exists(_curDownloadDir)) 363 | { 364 | Directory.CreateDirectory(_curDownloadDir); 365 | } 366 | } 367 | else 368 | { 369 | _curDownloadDir = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Downloads"); 370 | if (!Directory.Exists(_curDownloadDir)) 371 | { 372 | Directory.CreateDirectory(_curDownloadDir); 373 | } 374 | } 375 | } 376 | else 377 | { 378 | _curDownloadDir = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Downloads"); 379 | if (!Directory.Exists(_curDownloadDir)) 380 | { 381 | Directory.CreateDirectory(_curDownloadDir); 382 | } 383 | } 384 | } 385 | else 386 | { 387 | _curDownloadDir = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Downloads"); 388 | if (!Directory.Exists(_curDownloadDir)) 389 | { 390 | Directory.CreateDirectory(_curDownloadDir); 391 | } 392 | } 393 | 394 | string dlDirAndFileName = Path.Combine(_curDownloadDir, NewFileName); 395 | CurrentFilePath = dlDirAndFileName; 396 | try 397 | { 398 | if (!File.Exists(dlDirAndFileName)) 399 | { 400 | OnDccDebugMessage?.Invoke(this, 401 | new DCCDebugMessageArgs("File does not exist yet, start connection with: " + NewIP + ":" + NewPortNum + Environment.NewLine, "DCC DOWNLOADER")); 402 | Thread.Sleep(500); 403 | //start connection with tcp server 404 | 405 | IPAddress ip = IPAddress.Parse(NewIP); 406 | 407 | using (TcpClient dltcp = new TcpClient(ip.AddressFamily)) 408 | { 409 | 410 | dltcp.Connect(ip, NewPortNum); 411 | using (NetworkStream dlstream = dltcp.GetStream()) 412 | { 413 | //succesfully connected to tcp server, status is downloading 414 | UpdateStatus("DOWNLOADING"); 415 | 416 | //values to keep track of progress 417 | Int64 bytesReceived = 0; 418 | Int64 oldBytesReceived = 0; 419 | Int64 oneprocent = NewFileSize / 100; 420 | DateTime start = DateTime.Now; 421 | bool timedOut = false; 422 | 423 | //values to keep track of download position 424 | int count; 425 | 426 | //to me this buffer size seemed to be the most efficient. 427 | byte[] buffer; 428 | if (NewFileSize > 1048576) 429 | { 430 | OnDccDebugMessage?.Invoke(this, 431 | new DCCDebugMessageArgs("Big file, big buffer (1 mb) \n ", "DCC DOWNLOADER")); 432 | buffer = new byte[16384]; 433 | } else if(NewFileSize < 1048576 && NewFileSize > 2048) 434 | { 435 | OnDccDebugMessage?.Invoke(this, 436 | new DCCDebugMessageArgs("Smaller file (< 1 mb), smaller buffer (2 kb) \n ", "DCC DOWNLOADER")); 437 | buffer = new byte[2048]; 438 | } else if (NewFileSize < 2048 && NewFileSize > 128) 439 | { 440 | OnDccDebugMessage?.Invoke(this, 441 | new DCCDebugMessageArgs("Small file (< 2kb mb), small buffer (128 b) \n ", "DCC DOWNLOADER")); 442 | buffer = new byte[128]; 443 | } else 444 | { 445 | OnDccDebugMessage?.Invoke(this, 446 | new DCCDebugMessageArgs("Tiny file (< 128 b), tiny buffer (2 b) \n ", "DCC DOWNLOADER")); 447 | buffer = new byte[2]; 448 | } 449 | 450 | 451 | //create file to write to 452 | using (FileStream writeStream = new FileStream(dlDirAndFileName, FileMode.Append, FileAccess.Write, FileShare.Read)) 453 | { 454 | writeStream.SetLength(NewFileSize); 455 | IsDownloading = true; 456 | //download while connected and filesize is not reached 457 | while (dltcp.Connected && bytesReceived < NewFileSize && !_shouldAbort) 458 | { 459 | if (_shouldAbort) 460 | { 461 | dltcp.Close(); 462 | dlstream.Dispose(); 463 | writeStream.Close(); 464 | } 465 | //keep track of progress 466 | DateTime end = DateTime.Now; 467 | if (end.Second != start.Second) 468 | { 469 | 470 | BytesPerSecond = bytesReceived - oldBytesReceived; 471 | KBytesPerSecond = (int)(BytesPerSecond / 1024); 472 | MBytesPerSecond = (KBytesPerSecond / 1024); 473 | oldBytesReceived = bytesReceived; 474 | start = DateTime.Now; 475 | UpdateStatus("DOWNLOADING"); 476 | Buffer.Clear(); 477 | } 478 | 479 | //count bytes received 480 | count = dlstream.Read(buffer, 0, buffer.Length); 481 | 482 | //write to buffer 483 | Buffer.AddRange(buffer); 484 | 485 | //write to file 486 | writeStream.Write(buffer, 0, count); 487 | 488 | //count bytes received 489 | bytesReceived += count; 490 | 491 | Progress = (int)(bytesReceived / oneprocent); 492 | } 493 | 494 | //close all connections and streams (just to be save) 495 | dltcp.Close(); 496 | dlstream.Dispose(); 497 | writeStream.Close(); 498 | 499 | IsDownloading = false; 500 | 501 | if (_shouldAbort) 502 | { 503 | try 504 | { 505 | OnDccDebugMessage?.Invoke(this, 506 | new DCCDebugMessageArgs("Downloader Stopped", "DCC DOWNLOADER")); 507 | OnDccDebugMessage?.Invoke(this, 508 | new DCCDebugMessageArgs("File " + CurrentFilePath + " will be deleted due to aborting", "DCC DOWNLOADER")); 509 | File.Delete(CurrentFilePath); 510 | 511 | } 512 | catch (Exception e) 513 | { 514 | OnDccDebugMessage?.Invoke(this, 515 | new DCCDebugMessageArgs("File " + CurrentFilePath + " probably doesn't exist :X", "DCC DOWNLOADER")); 516 | OnDccDebugMessage?.Invoke(this, 517 | new DCCDebugMessageArgs(e.ToString(), "DCC DOWNLOADER")); 518 | } 519 | 520 | UpdateStatus("ABORTED"); 521 | } else 522 | { 523 | 524 | //consider 95% downloaded as done, files are sequentually downloaded, sometimes download stops early, but the file still is usable 525 | if (Progress < 95 && !_shouldAbort) 526 | { 527 | UpdateStatus("FAILED"); 528 | OnDccDebugMessage?.Invoke(this, 529 | new DCCDebugMessageArgs("Download stopped at < 95 % finished, deleting file: " + NewFileName + " \n", "DCC DOWNLOADER")); 530 | OnDccDebugMessage?.Invoke(this, 531 | new DCCDebugMessageArgs("Download stopped at : " + bytesReceived + " bytes, a total of " + Progress + "%", "DCC DOWNLOADER")); 532 | File.Delete(dlDirAndFileName); 533 | timedOut = false; 534 | 535 | 536 | } 537 | else if (timedOut && Progress < 95 && !_shouldAbort) 538 | { 539 | UpdateStatus("FAILED: TIMED OUT"); 540 | OnDccDebugMessage?.Invoke(this, 541 | new DCCDebugMessageArgs("Download timed out at < 95 % finished, deleting file: " + NewFileName + " \n", "DCC DOWNLOADER")); 542 | OnDccDebugMessage?.Invoke(this, 543 | new DCCDebugMessageArgs("Download stopped at : " + bytesReceived + " bytes, a total of " + Progress + "%", "DCC DOWNLOADER")); 544 | File.Delete(dlDirAndFileName); 545 | timedOut = false; 546 | } 547 | else if (!_shouldAbort) 548 | { 549 | //make sure that in the event something happens and the downloader calls delete after finishing, the file will remain where it is. 550 | dlDirAndFileName = ""; 551 | UpdateStatus("COMPLETED"); 552 | } 553 | 554 | } 555 | _shouldAbort = false; 556 | 557 | } 558 | } 559 | } 560 | } 561 | else 562 | { 563 | OnDccDebugMessage?.Invoke(this, 564 | new DCCDebugMessageArgs("File already exists, removing from xdcc que!\n", "DCC DOWNLOADER")); 565 | _ircClient.SendMessageToAll("/msg " + BotName + " xdcc remove " + PackNum); 566 | _ircClient.SendMessageToAll("/msg " + BotName + " xdcc cancel"); 567 | UpdateStatus("FAILED: ALREADY EXISTS"); 568 | } 569 | OnDccDebugMessage?.Invoke(this, 570 | new DCCDebugMessageArgs("File has been downloaded! \n File Location:" + CurrentFilePath , "DCC DOWNLOADER")); 571 | 572 | } 573 | catch (SocketException e) 574 | { 575 | OnDccDebugMessage?.Invoke(this, 576 | new DCCDebugMessageArgs("Something went wrong while downloading the file! Removing from xdcc que to be sure! Error:\n" + e.ToString(), "DCC DOWNLOADER")); 577 | _ircClient.SendMessageToAll("/msg " + BotName + " xdcc remove " + PackNum); 578 | _ircClient.SendMessageToAll("/msg " + BotName + " xdcc cancel"); 579 | UpdateStatus("FAILED: CONNECTING"); 580 | } 581 | catch (Exception ex) 582 | { 583 | OnDccDebugMessage?.Invoke(this, 584 | new DCCDebugMessageArgs("Something went wrong while downloading the file! Removing from xdcc que to be sure! Error:\n" + ex.ToString(), "DCC DOWNLOADER")); 585 | _ircClient.SendMessageToAll("/msg " + BotName + " xdcc remove " + PackNum); 586 | _ircClient.SendMessageToAll("/msg " + BotName + " xdcc cancel"); 587 | UpdateStatus("FAILED: UNKNOWN"); 588 | } 589 | IsDownloading = false; 590 | } 591 | 592 | /// 593 | /// Fires the event with the update about the download currently running 594 | /// 595 | /// the current status of the download 596 | private void UpdateStatus(string statusin) 597 | { 598 | Status = statusin; 599 | OnDccEvent?.Invoke(this, new DCCEventArgs(this)); 600 | } 601 | 602 | /// 603 | /// Stops a download if one is running, checks if the donwnloader thread actually stops. 604 | /// 605 | /// true if stopped succesfully 606 | public bool AbortDownloader(int timeOut) 607 | { 608 | if (CheckIfDownloading()) 609 | { 610 | OnDccDebugMessage?.Invoke(this, 611 | new DCCDebugMessageArgs("File " + CurrentFilePath + " will be deleted after aborting.", "DCC DOWNLOADER")); 612 | 613 | _shouldAbort = true; 614 | 615 | int timeout = 0; 616 | while (CheckIfDownloading()) 617 | { 618 | if (timeout > timeOut) 619 | { 620 | return false; 621 | } 622 | timeout++; 623 | Thread.Sleep(1); 624 | } 625 | 626 | return true; 627 | } 628 | else 629 | { 630 | return false; 631 | } 632 | } 633 | 634 | /// 635 | /// Checks if download is still running. 636 | /// 637 | /// true if still downloading 638 | public bool CheckIfDownloading() 639 | { 640 | return IsDownloading; 641 | } 642 | 643 | /// 644 | /// Removes special characters from a string (used for filenames) 645 | /// 646 | /// string to parse 647 | /// string wihtout special chars 648 | private string RemoveSpecialCharacters(string str) 649 | { 650 | StringBuilder sb = new StringBuilder(); 651 | foreach (char c in str) 652 | { 653 | if (c > 31 && c < 219) 654 | { 655 | sb.Append(c); 656 | } 657 | } 658 | return sb.ToString(); 659 | } 660 | 661 | /// 662 | /// Reverses IP from little endian to big endian or vice versa depending on what succeeds. 663 | /// 664 | /// ip string 665 | /// reversed ip string 666 | private string ReverseIp(string ip) 667 | { 668 | string[] parts = ip.Trim().Split('.'); 669 | if(parts.Length >= 3) 670 | { 671 | OnDccDebugMessage?.Invoke(this, 672 | new DCCDebugMessageArgs("DCCClient: converting ip: " + ip, "DCC IP PARSER")); 673 | string NewIP= parts[3] + "." + parts[2] + "." + parts[1] + "." + parts[0]; 674 | OnDccDebugMessage?.Invoke(this, 675 | new DCCDebugMessageArgs("DCCClient: to: " + NewIP, "DCC IP PARSER")); 676 | 677 | return NewIP; 678 | } else 679 | { 680 | OnDccDebugMessage?.Invoke(this, 681 | new DCCDebugMessageArgs("DCCClient: converting ip: " + ip, "DCC IP PARSER")); 682 | OnDccDebugMessage?.Invoke(this, 683 | new DCCDebugMessageArgs("DCCClient: amount of parts: " + parts.Length, "DCC IP PARSER")); 684 | return "0.0.0.0"; 685 | } 686 | } 687 | 688 | /// 689 | /// Converts a long/int64 to a ip string. 690 | /// 691 | /// int64 numbers representing IP address 692 | /// string with ip 693 | private string UInt64ToIPAddress(Int64 address) 694 | { 695 | string ip = string.Empty; 696 | for (int i = 0; i < 4; i++) 697 | { 698 | int num = (int)(address / Math.Pow(256, (3 - i))); 699 | address = address - (long)(num * Math.Pow(256, (3 - i))); 700 | if (i == 0) 701 | { 702 | ip = num.ToString(); 703 | } 704 | else 705 | { 706 | ip = ip + "." + num.ToString(); 707 | } 708 | } 709 | return ip; 710 | } 711 | } 712 | } 713 | -------------------------------------------------------------------------------- /SimpleIRCLib/IrcClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Net.Sockets; 4 | using System.IO; 5 | using System.Threading; 6 | using System.Text.RegularExpressions; 7 | using System.Collections.Generic; 8 | using System.Diagnostics; 9 | using System.Net.Security; 10 | 11 | namespace SimpleIRCLib 12 | { 13 | /// 14 | /// For running IRC Client logic, here is where all the magic happens 15 | /// 16 | public class IrcClient 17 | { 18 | 19 | /// 20 | /// Event Handler for firing when a (parsed) message is received on a channel from other users, event uses IrcReceivedEventArgs from IrcEventArgs.cs 21 | /// 22 | public event EventHandler OnMessageReceived; 23 | 24 | /// 25 | /// Event Handler for firing when a raw message is received from the irc server, event uses IrcRawReceivedEventArgs from IrcEventArgs.cs 26 | /// 27 | public event EventHandler OnRawMessageReceived; 28 | 29 | /// 30 | /// Event Handler for firing when a list with users per channel is received, event uses IrcUserListReceivedEventArgs from IrcEventArgs.cs 31 | /// 32 | public event EventHandler OnUserListReceived; 33 | 34 | /// 35 | /// Event Handler for firing when this client wants to send a debug message, event uses IrcDebugMessageEventArgs from IrcEventArgs.cs 36 | /// 37 | public event EventHandler OnDebugMessage; 38 | 39 | /// 40 | /// Port of irc server to connect to 41 | /// 42 | private int _NewPort; 43 | /// 44 | /// Username to register on irc server 45 | /// 46 | private string _NewUsername; 47 | /// 48 | /// Password to connect to a secured irc server 49 | /// 50 | private string _newPassword; 51 | /// 52 | /// Ip address of irc server 53 | /// 54 | private string _newIp; 55 | /// 56 | /// List with channels seperated with ',' to join when connecting to IRC server 57 | /// 58 | private string _NewChannelss; 59 | /// 60 | /// timeout before throwing timeout errors (using OnDebugMessage) 61 | /// 62 | private int _timeOut; 63 | /// 64 | /// download directory used for DCCClient.cs 65 | /// 66 | private string _downloadDirectory; 67 | /// 68 | /// for enabling tls/ssl secured connection to the irc server 69 | /// 70 | private bool _enableSSL; 71 | /// 72 | /// for checking if a connection is succesfully established 73 | /// 74 | private bool _isConnectionEstablised; 75 | /// 76 | /// for checking if client has started listening to the server 77 | /// 78 | private bool _IsClientRunning; 79 | /// 80 | /// packnumber used to initialize dccclient downloader 81 | /// 82 | private string _packNumber; 83 | /// 84 | /// bot used to initialzie dccclient downloader 85 | /// 86 | private string _bot; 87 | /// 88 | /// DCCClient to be used for downloading 89 | /// 90 | private DCCClient _dccClient; 91 | /// 92 | /// TcpClient used for connecting to the irc server 93 | /// 94 | private TcpClient _tcpClient; 95 | /// 96 | /// IRC commands 97 | /// 98 | private IrcCommands _ircCommands; 99 | /// 100 | /// unsecure network stream for listening and reading to the irc server 101 | /// 102 | private NetworkStream _networkStream; 103 | /// 104 | /// secure network stream for listening and reading to the irc server 105 | /// 106 | private SslStream _networkSStream; 107 | /// 108 | /// used for writing to the irc server 109 | /// 110 | private StreamWriter _streamWriter; 111 | /// 112 | /// used for reading from the irc server 113 | /// 114 | private StreamReader _streamReader; 115 | /// 116 | /// receiver task 117 | /// 118 | private Task _receiverTask = null; 119 | /// 120 | /// used for stopping the receiver task 121 | /// 122 | private bool _stopTask = false; 123 | 124 | /// 125 | /// Default constructor, needed so that the client can register events before starting the connection. 126 | /// 127 | public IrcClient() 128 | { 129 | _isConnectionEstablised = false; 130 | _IsClientRunning = false; 131 | } 132 | 133 | /// 134 | /// Sets up the information needed for the client to start a connection to the irc server. Sends a warning to the debug message event if ports are out of the standard specified ports for IRC. 135 | /// 136 | /// Server address, possibly works with dns addresses (irc.xxx.x), but ip addresses works just fine (of type string) 137 | /// Username the client wants to use, of type string 138 | /// Channel(s) the client wants to connect to, possible to connect to multiple channels at once by seperating each channel with a ',' (Example: #chan1,#chan2), of type string 139 | /// DCC Client, for downloading using the DCC protocol 140 | /// Download Directory, used by the DCC CLient to store files in the specified directory, if left empty, it will create a "Download" directory within the same folder where this library resides 141 | /// Port, optional parameter, where default = 0 (Automatic port selection), is port of the server you want to connect to, of type int 142 | /// Password, optional parameter, where default value is "", can be used to connect to a password protected server. 143 | /// Timeout, optional parameter, where default value is 3000 milliseconds, the maximum time before a server needs to answer, otherwise errors are thrown. 144 | /// Timeout, optional parameter, where default value is 3000 milliseconds, the maximum time before a server needs to answer, otherwise errors are thrown. 145 | public void SetConnectionInformation(string ip, string username, string channels, 146 | DCCClient dccClient, string downloadDirectory, int port = 0, string password = "", int timeout = 3000, bool enableSSL = true) 147 | { 148 | _newIp = ip; 149 | _NewPort = port; 150 | _NewUsername = username; 151 | _newPassword = password; 152 | _NewChannelss = channels; 153 | _isConnectionEstablised = false; 154 | _IsClientRunning = false; 155 | _timeOut = timeout; 156 | _downloadDirectory = downloadDirectory; 157 | _dccClient = dccClient; 158 | _enableSSL = enableSSL; 159 | 160 | if (_enableSSL) 161 | { 162 | if (port == 0) 163 | { 164 | _NewPort = 6697; 165 | } else if (port != 6697) 166 | { 167 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("PORT: " + port.ToString() + " IS NOT COMMONLY USED FOR TLS/SSL CONNECTIONS, PREFER TO USE 6697 FOR SSL!", "SETUP WARNING")); 168 | } 169 | } 170 | else 171 | { 172 | if (port == 0) 173 | { 174 | _NewPort = 6667; 175 | } 176 | else if (port < 6665 && port > 6669) 177 | { 178 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("PORT: " + port.ToString() + " IS NOT COMMONLY USED FOR NON TLS/SSL CONNECTIONS, PREFER TO USE PORTS BETWEEN 6665 & 6669!", "SETUP WARNING")); 179 | } 180 | } 181 | } 182 | 183 | /// 184 | /// Changes the download directory, will apply to the next instantiated download. 185 | /// 186 | /// Path to directory (creates it if it does not exist) 187 | public void SetDownloadDirectory(string downloadDirectory) 188 | { 189 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("SET DOWNLOAD DIRECTORY: " + downloadDirectory, "SETTING DOWNLOAD DIRECTORY")); 190 | _downloadDirectory = downloadDirectory; 191 | } 192 | 193 | /// 194 | /// Starts the connection to the irc server, sends the register user command and register nick name command. 195 | /// 196 | /// true/false depending if error coccured 197 | public bool Connect() 198 | { 199 | try 200 | { 201 | _isConnectionEstablised = false; 202 | _receiverTask = new Task(StartReceivingChat); 203 | _receiverTask.Start(); 204 | 205 | int timeout = 0; 206 | while (!_isConnectionEstablised) 207 | { 208 | Thread.Sleep(1); 209 | if (timeout > _timeOut) 210 | { 211 | return false; 212 | } 213 | timeout++; 214 | } 215 | 216 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("IRC CLIENT SUCCESFULLY RUNNING", "IRC SETUP")); 217 | return true; 218 | } 219 | catch(Exception e) 220 | { 221 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs(e.ToString(), "SETUP ERROR")); 222 | return false; 223 | } 224 | } 225 | 226 | /// 227 | /// Starts quiting procedure, sends QUIT message to server and waits until server closes connection with the client, after that, it shuts down every reader and stream, and stops the receiver task. 228 | /// 229 | /// 230 | public bool QuitConnect() 231 | { 232 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("STARTING IRC CLIENT SHUTDOWN PROCEDURE", "QUIT")); 233 | //send quit to server 234 | if (WriteIrc("QUIT")) 235 | { 236 | int timeout = 0; 237 | while (_tcpClient.Connected) 238 | { 239 | Thread.Sleep(1); 240 | if (timeout >= _timeOut) 241 | { 242 | return false; 243 | } 244 | timeout++; 245 | } 246 | 247 | _stopTask = true; 248 | Thread.Sleep(200); 249 | //stop everything in right order 250 | _receiverTask.Dispose(); 251 | _streamReader.Dispose(); 252 | _networkStream.Close(); 253 | _streamWriter.Close(); 254 | _tcpClient.Close(); 255 | 256 | _isConnectionEstablised = false; 257 | 258 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("FINISHED SHUTDOWN PROCEDURE", "QUIT")); 259 | return true; 260 | 261 | } 262 | else 263 | { 264 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("COULD NOT WRITE QUIT COMMAND TO SERVER", "QUIT")); 265 | return true; 266 | } 267 | } 268 | 269 | /// 270 | /// Starts the receiver task. 271 | /// 272 | public void StartReceivingChat() 273 | { 274 | 275 | _tcpClient = new TcpClient(_newIp, _NewPort); 276 | 277 | int timeout = 0; 278 | while (!_tcpClient.Connected) 279 | { 280 | Thread.Sleep(1); 281 | 282 | if (timeout >= _timeOut) 283 | { 284 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("TIMEOUT, COULD NOT CONNECT TO TCP SOCKET", "IRC SETUP")); 285 | } 286 | timeout++; 287 | } 288 | 289 | 290 | try 291 | { 292 | 293 | if (!_enableSSL) 294 | { 295 | _networkStream = _tcpClient.GetStream(); Thread.Sleep(500); 296 | _streamReader = new StreamReader(_networkStream); 297 | _streamWriter = new StreamWriter(_networkStream); 298 | _ircCommands = new IrcCommands(_networkStream); 299 | } 300 | else 301 | { 302 | _networkSStream = new SslStream(_tcpClient.GetStream()); 303 | _networkSStream.AuthenticateAsClient(_newIp); 304 | _streamReader = new StreamReader(_networkSStream); 305 | _streamWriter = new StreamWriter(_networkSStream); 306 | _ircCommands = new IrcCommands(_networkSStream); 307 | 308 | } 309 | 310 | 311 | 312 | _isConnectionEstablised = true; 313 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("CONNECTED TO TCP SOCKET", "IRC SETUP")); 314 | 315 | 316 | 317 | if (_newPassword.Length > 0) 318 | { 319 | if (!_ircCommands.SetPassWord(_newPassword)) 320 | { 321 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs(_ircCommands.GetErrorMessage(), "IRC SETUP ERROR")); 322 | _isConnectionEstablised = false; 323 | } 324 | } 325 | Debug.WriteLine("Joining channels: " + _NewChannelss); 326 | if (!_ircCommands.JoinNetwork(_NewUsername, _NewChannelss)) 327 | { 328 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs(_ircCommands.GetErrorMessage(), "IRC SETUP ERROR")); 329 | _isConnectionEstablised = false; 330 | } 331 | } 332 | catch (Exception ex) 333 | { 334 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs(ex.ToString(), "IRC SETUP")); 335 | } 336 | 337 | 338 | 339 | if (_isConnectionEstablised) 340 | { 341 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("CONNECTED TO IRC SERVER", "IRC SETUP")); 342 | _stopTask = false; 343 | Task.Run(() => ReceiveChat()); 344 | } 345 | } 346 | 347 | /// 348 | /// Receiver task, receives messages from server, handles joining intial join to channels, if the server responses with a 004 (which is a welcome message, meaning it has succesfully connected) 349 | /// Handles PRIVMSG messages 350 | /// Handles PING messages 351 | /// Handles JOIN messages 352 | /// Handles QUIT messages (though it's not yet possible to determine which channels these users have left 353 | /// Handles 353 messages (Users list per channel) 354 | /// Handles 366 messages (Finished user list per channel) 355 | /// Handles DCC SEND messages 356 | /// 357 | private void ReceiveChat() 358 | { 359 | try 360 | { 361 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("STARTING LISTENER!", "IRC RECEIVER")); 362 | 363 | 364 | Dictionary> usersPerChannelDictionary = new Dictionary>(); 365 | 366 | _IsClientRunning = true; 367 | _isConnectionEstablised = true; 368 | while (!_stopTask) 369 | { 370 | 371 | string ircData = _streamReader.ReadLine(); 372 | 373 | OnRawMessageReceived?.Invoke(this, new IrcRawReceivedEventArgs(ircData)); 374 | 375 | 376 | 377 | if (ircData.Contains("PING")) 378 | { 379 | string pingID = ircData.Split(':')[1]; 380 | WriteIrc("PONG :" + pingID); 381 | } 382 | if ( ircData.Contains("PRIVMSG")) 383 | { 384 | 385 | 386 | //:MrRareie!~MrRareie_@Rizon-AC4B78B2.cm-3-2a.dynamic.ziggo.nl PRIVMSG #RareIRC :wassup 387 | 388 | 389 | 390 | try 391 | { 392 | string messageAndChannel = ircData.Split(new string[] { "PRIVMSG" }, StringSplitOptions.None)[1]; 393 | string message = messageAndChannel.Split(':')[1].Trim(); 394 | string channel = messageAndChannel.Split(':')[0].Trim(); 395 | string user = ircData.Split(new string[] { "PRIVMSG" }, StringSplitOptions.None)[0].Split('!')[0].Substring(1); 396 | 397 | channel = channel.Replace("=", string.Empty); 398 | 399 | OnMessageReceived?.Invoke(this, new IrcReceivedEventArgs(message, user, channel)); 400 | } 401 | catch(Exception ex) 402 | { 403 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs(ex.ToString(), "MESSAGE RECEIVED ERROR (PRIVMSG)")); 404 | } 405 | 406 | 407 | 408 | } 409 | else if (ircData.Contains("JOIN")) 410 | { 411 | //RAW: :napiz!~napiz@Rizon-BF96A69D.dyn.optonline.net JOIN :#NIBL 412 | 413 | 414 | try 415 | { 416 | string channel = ircData.Split(new string[] { "JOIN" }, StringSplitOptions.None)[1].Split(':')[1]; 417 | string userThatJoined = ircData.Split(new string[] { "JOIN" }, StringSplitOptions.None)[0].Split(':')[1].Split('!')[0]; 418 | 419 | OnMessageReceived?.Invoke(this, new IrcReceivedEventArgs("User Joined", userThatJoined, channel)); 420 | } 421 | catch (Exception ex) 422 | { 423 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs(ex.ToString(), "MESSAGE RECEIVED ERROR (JOIN)")); 424 | } 425 | 426 | } 427 | else if (ircData.Contains("QUIT")) 428 | { 429 | 430 | //RAW: :MrRareie!~MrRareie_@Rizon-AC4B78B2.cm-3-2a.dynamic.ziggo.nl QUIT 431 | try 432 | { 433 | string user = ircData.Split(new string[] { "QUIT" }, StringSplitOptions.None)[0].Split('!')[0].Substring(1); 434 | 435 | OnMessageReceived?.Invoke(this, new IrcReceivedEventArgs("User Left", user, "unknown")); 436 | } 437 | catch (Exception ex) 438 | { 439 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs(ex.ToString(), "MESSAGE RECEIVED ERROR (JOIN)")); 440 | }; 441 | } 442 | 443 | if (ircData.Contains("DCC SEND") && ircData.Contains(_NewUsername)) 444 | { 445 | _dccClient.StartDownloader(ircData, _downloadDirectory, _bot, _packNumber, this); 446 | } 447 | 448 | //RareIRC_Client = #weebirc :RareIRC_Client 449 | if (ircData.Contains(" 353 ")) 450 | { 451 | //:irc.x2x.cc 353 RoflHerp = #RareIRC :RoflHerp @MrRareie 452 | try 453 | { 454 | string channel = ircData.Split(new[] { " " + _NewUsername + " ="}, StringSplitOptions.None)[1].Split(':')[0].Replace(" ", string.Empty); 455 | string userListFullString = ircData.Split(new[] { " " + _NewUsername + " =" }, StringSplitOptions.None)[1].Split(':')[1]; 456 | 457 | 458 | if (!channel.Contains(_NewUsername) && !channel.Contains("=")) 459 | { 460 | string[] users = userListFullString.Split(' '); 461 | if (usersPerChannelDictionary.ContainsKey(channel)) 462 | { 463 | usersPerChannelDictionary.TryGetValue(channel, out var currentUsers); 464 | 465 | 466 | foreach (string name in users) 467 | { 468 | if (!name.Contains(_NewUsername)) 469 | { 470 | currentUsers.Add(name); 471 | } 472 | } 473 | usersPerChannelDictionary[channel.Trim()] = currentUsers; 474 | } 475 | else 476 | { 477 | List currentUsers = new List(); 478 | foreach (string name in users) 479 | { 480 | currentUsers.Add(name); 481 | } 482 | usersPerChannelDictionary.Add(channel.Trim(), currentUsers); 483 | } 484 | } 485 | 486 | 487 | } catch (Exception ex) 488 | { 489 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs(ex.ToString(), "MESSAGE RECEIVED ERROR (USERLIST)")); 490 | } 491 | 492 | 493 | } 494 | 495 | if(ircData.ToLower().Contains(" 366 ")) 496 | { 497 | OnUserListReceived?.Invoke(this, new IrcUserListReceivedEventArgs(usersPerChannelDictionary)); 498 | usersPerChannelDictionary.Clear(); 499 | } 500 | Thread.Sleep(1); 501 | } 502 | 503 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("RECEIVER HAS STOPPED RUNNING", "MESSAGE RECEIVER")); 504 | 505 | QuitConnect(); 506 | _stopTask = false; 507 | } catch (Exception ioex) 508 | { 509 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("LOST CONNECTION: " + ioex.ToString(), "MESSAGE RECEIVER")); 510 | if (_isConnectionEstablised) 511 | { 512 | _stopTask = false; 513 | QuitConnect(); 514 | } 515 | } 516 | _IsClientRunning = false; 517 | } 518 | 519 | 520 | /// 521 | /// Sends message to all channels, if message is not one of the following: 522 | /// /msg [bot] xdcc send [pack] 523 | /// /msg [bot] xdcc cancel 524 | /// /msg [bot] xdcc remove [pack] 525 | /// /names [channels] (can be empty) 526 | /// /join [channels] 527 | /// /quit 528 | /// /msg [channel/user] [message] 529 | /// 530 | /// String to send 531 | /// true / false depending if it could send the message to the server 532 | public bool SendMessageToAll(string input) 533 | { 534 | 535 | input = input.Trim(); 536 | Regex regex1 = new Regex(@"^(?=.*(?(?<=/msg)(.*)(?=xdcc)))(?=.*(?(?<=(send)+(\s))(.*)))"); 537 | Match matches1 = regex1.Match(input.ToLower()); 538 | Regex regex2 = new Regex(@"^(?=.*(?(?<=/msg)(.*)(?=xdcc)))(?=.*(?(?<=(cancel))(.*)))"); 539 | Match matches2 = regex2.Match(input.ToLower()); 540 | Regex regex3 = new Regex(@"^(?=.*(?(?<=/msg)(.*)(?=xdcc)))(?=.*(?(?<=(remove)+(\s))(.*)))"); 541 | Match matches3 = regex3.Match(input.ToLower()); 542 | 543 | if (matches1.Success) 544 | { 545 | _bot = matches1.Groups["botname"].Value.Trim(); 546 | _packNumber = matches1.Groups["packnum"].Value.Trim(); 547 | string xdccdl = "PRIVMSG " + _bot + " :XDCC SEND " + _packNumber; 548 | return WriteIrc(xdccdl); 549 | } 550 | else if (matches2.Success) 551 | { 552 | _bot = matches2.Groups["botname"].Value; 553 | string xdcccl = "PRIVMSG " + _bot + " :XDCC CANCEL"; 554 | return WriteIrc(xdcccl); 555 | } 556 | else if (matches3.Success) 557 | { 558 | _bot = matches3.Groups["botname"].Value; 559 | _packNumber = matches3.Groups["packnum"].Value; 560 | string xdccdl = "PRIVMSG " + _bot + " :XDCC REMOVE " + _packNumber; 561 | return WriteIrc(xdccdl); 562 | } else if (input.ToLower().Contains("/names")) 563 | { 564 | if (input.Contains("#")) 565 | { 566 | string channelList = input.Split(' ')[1]; 567 | return GetUsersInChannel(channelList); 568 | } else 569 | { 570 | return GetUsersInChannel(""); 571 | } 572 | } 573 | else if (input.ToLower().Contains("/join")) 574 | { 575 | 576 | if (input.Split(' ').Length > 0) 577 | { 578 | string channels = input.Split(' ')[1]; 579 | _NewChannelss += channels; 580 | return WriteIrc("JOIN " + channels); 581 | } 582 | else 583 | { 584 | return false; 585 | } 586 | } 587 | else if(input.ToLower().Contains("/quit")) 588 | { 589 | return QuitConnect(); 590 | } 591 | else if (input.ToLower().Contains("/msg")) 592 | { 593 | return WriteIrc(input.Replace("/msg", "PRIVMSG")); 594 | } 595 | else 596 | { 597 | return WriteIrc("PRIVMSG " + _NewChannelss + " :" + input); 598 | } 599 | 600 | 601 | } 602 | 603 | 604 | /// 605 | /// Sends message to specific channels, if message is not one of the following: 606 | /// /msg [bot] xdcc send [pack] 607 | /// /msg [bot] xdcc cancel 608 | /// /msg [bot] xdcc remove [pack] 609 | /// /names [channels] (can be empty) 610 | /// /join [channels] 611 | /// /quit 612 | /// /msg [channel/user] [message] 613 | /// 614 | /// String to send 615 | /// Channel(s) to send to 616 | /// true / false depending if it could send the message to the server 617 | public bool SendMessageToChannel(string input, string channel) 618 | { 619 | 620 | input = input.Trim(); 621 | Regex regex1 = new Regex(@"^(?=.*(?(?<=/msg)(.*)(?=xdcc)))(?=.*(?(?<=(send)+(\s))(.*)))"); 622 | Match matches1 = regex1.Match(input.ToLower()); 623 | Regex regex2 = new Regex(@"^(?=.*(?(?<=/msg)(.*)(?=xdcc)))(?=.*(?(?<=(cancel))(.*)))"); 624 | Match matches2 = regex2.Match(input.ToLower()); 625 | Regex regex3 = new Regex(@"^(?=.*(?(?<=/msg)(.*)(?=xdcc)))(?=.*(?(?<=(remove)+(\s))(.*)))"); 626 | Match matches3 = regex3.Match(input.ToLower()); 627 | 628 | if (matches1.Success) 629 | { 630 | _bot = matches1.Groups["botname"].Value.Trim(); 631 | _packNumber = matches1.Groups["packnum"].Value.Trim(); 632 | string xdccdl = "PRIVMSG " + _bot + " :XDCC SEND " + _packNumber; 633 | return WriteIrc(xdccdl); 634 | } 635 | else if (matches2.Success) 636 | { 637 | _bot = matches2.Groups["botname"].Value; 638 | string xdcccl = "PRIVMSG " + _bot + " :XDCC CANCEL"; 639 | return WriteIrc(xdcccl); 640 | } 641 | else if (matches3.Success) 642 | { 643 | _bot = matches3.Groups["botname"].Value; 644 | _packNumber = matches3.Groups["packnum"].Value; 645 | string xdccdl = "PRIVMSG " + _bot + " :XDCC REMOVE " + _packNumber; 646 | return WriteIrc(xdccdl); 647 | } 648 | else if (input.ToLower().Contains("/names")) 649 | { 650 | if (input.Contains("#")) 651 | { 652 | string channelList = input.Split(' ')[1]; 653 | return GetUsersInChannel(channelList); 654 | } 655 | else 656 | { 657 | return GetUsersInChannel(channel); 658 | } 659 | } 660 | else if (input.ToLower().Contains("/join")) 661 | { 662 | 663 | if (input.Split(' ').Length > 0) 664 | { 665 | string channels = input.Split(' ')[1]; 666 | _NewChannelss += channels; 667 | return WriteIrc("JOIN " + channels); 668 | } 669 | else 670 | { 671 | return false; 672 | } 673 | } 674 | else if (input.ToLower().Contains("/quit")) 675 | { 676 | return QuitConnect(); 677 | } 678 | else if (input.ToLower().Contains("/msg")) 679 | { 680 | return WriteIrc(input.Replace("/msg", "PRIVMSG")); 681 | } 682 | else 683 | { 684 | return WriteIrc("PRIVMSG " + channel + " :" + input); 685 | } 686 | 687 | 688 | } 689 | 690 | /// 691 | /// Sends a raw message to the irc server, without any parsing applied 692 | /// 693 | /// message to send 694 | /// true/false depending if it could write to the irc server 695 | public bool SendRawMsg(string msg) 696 | { 697 | return WriteIrc(msg); 698 | } 699 | 700 | /// 701 | /// Sends the get names for specific channels or for all channels. 702 | /// 703 | /// channel, optional, default = "" = all channels, 704 | /// true/false depending if it could write to the server 705 | public bool GetUsersInChannel(string channel = "") 706 | { 707 | 708 | if (channel != "") 709 | { 710 | return WriteIrc("NAMES " + channel); 711 | } else 712 | { 713 | return WriteIrc("NAMES " + _NewChannelss); 714 | } 715 | } 716 | 717 | /// 718 | /// Writes a message to the irc server. 719 | /// 720 | /// Message to send 721 | /// true/false depending if it could write to the irc server 722 | public bool WriteIrc(string input) 723 | { 724 | try 725 | { 726 | _streamWriter.Write(input + Environment.NewLine); 727 | _streamWriter.Flush(); 728 | return true; 729 | } catch(Exception e) 730 | { 731 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("Could not send message" + input + ", _tcpClient client is not running :X, error : " + e.ToString(), "MESSAGE SENDER")); ; 732 | return false; 733 | } 734 | 735 | } 736 | 737 | /// 738 | /// Stops a download if a download is running. 739 | /// 740 | /// true/false depending if an error occured or not 741 | public bool StopXDCCDownload() 742 | { 743 | try 744 | { 745 | return !_dccClient.AbortDownloader(_timeOut); 746 | } catch (Exception e) 747 | { 748 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("Could not stop XDCC Download, error: " + e.ToString(), "IRC CLIENT XDCC STOP")); 749 | return true; 750 | } 751 | } 752 | 753 | /// 754 | /// Checks if a download is running or not. 755 | /// 756 | /// true/false depending if a download is running, or if an error occured 757 | public bool CheckIfDownloading() 758 | { 759 | try 760 | { 761 | return _dccClient.CheckIfDownloading(); 762 | } 763 | catch (Exception e) 764 | { 765 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("Could not check if download has started, error: " + e.ToString(), "IRC CLIENT XDCC CHECK")); 766 | return false; 767 | } 768 | } 769 | 770 | /// 771 | /// Stops the client. 772 | /// 773 | public bool StopClient() 774 | { 775 | _stopTask = true; 776 | OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("CLOSING CLIENT", "CLOSE")); 777 | return QuitConnect(); 778 | } 779 | 780 | /// 781 | /// Gets the connection status 782 | /// 783 | /// true/false depending on the connection status 784 | public bool IsConnectionEstablished() 785 | { 786 | return _isConnectionEstablised; 787 | } 788 | 789 | /// 790 | /// Gets the client status 791 | /// 792 | /// true or false depending if the client is running or not 793 | public bool IsClientRunning() 794 | { 795 | return _IsClientRunning; 796 | } 797 | } 798 | 799 | 800 | } 801 | --------------------------------------------------------------------------------