Friday, March 14, 2014

XwitchBot

   I was asked to make a bot for twitch and so I did. It is called Xwitchbot (pronounced switch bot). I wouldn't call it a very good bot personally but it works. It provides some message handling, and is plugin based. Included is a single plugin that I made called Raffle2. As the name implies its used to hold raffles on twitch chats. To make plugins for this bot simply implement the interface "Globals.dll".

XwitchBot Files: https://www.mediafire.com/folder/aflc46sawa3rg/Xwitch
XwitchBot Download: http://www.mediafire.com/download/5oqmvpv3q51so78/XwitchBot.zip

Plugin Interface: http://www.mediafire.com/download/c80t7k4neh799cj/Globals.dll

Keep in mind that this is the first ever plugin based application I have ever made so it might lack some common practices etc. I am also mostly self taught and the implementation might not be optimal. All in all it works and I just wanted to share.

Doc:
The system is as follows. The main application loads the plugins in a pool of shared resources. That pool holds the IrcClient, message handler, and plugins as well as plugin resources. The IrcClient, MainUI, and PluginManager/Messagehandler are all on separate threads. Plugins can be on their own separate threads too if they are made so.

Here are some signatures and their description of the functions available in Globals.dll to make creating plugins easier.

Public Shared Function GetToSend() As String
Returns the first element in the list of messages to be sent to the server, and removes it from the list.

Public Shared Function GetRecvMsg(Optional ByVal RemoveOnGet As Boolean = True) As String
Returns the first element in the list of messages received by the server,
if RemoveOnGet is true remove the message from the list.

Public Shared Function GetConsoleMsg(Optional ByVal RemoveOnGet As Boolean = True) As String
Returns the first element in the list of messages to be shown as output,
If RemoveOnGet is true remove the message from list.

Public Shared Function ParseMessage(ByRef sourceInfo As Message, ByVal Input As String) As String
Returns a string replacing all fields with their respective information. sourceInfo is the Message where this function will get the required information from.

Public Shared Sub AddResource(ByVal newResource As Resource)
Adds a new Resource to the pool of resources.

Public Shared Sub AddResource(ByVal newResourceOrigin As String)
Adds a new Resource to the pool using a name.

Public Shared Sub RemoveResource(ByVal Origin As String)
Removes a Resource from the pool with the specified name (Origin)

Public Shared Sub RemoveResourceAt(ByVal index As Integer)
Removes a Resource from the pool at the specified index location

Public Shared Sub AddResourceElement(ByVal ResourceIndex As Integer, ByVal Type As String, ByVal Name As String, ByVal Value As Object)
Adds a resource element  to a resource in the pool at a given index location. Type, Name, and Value as specified.

Public Shared Sub AddResourceElement(ByVal ResourceOrigin As String, ByVal Type As String, ByVal Name As String, ByVal Value As Object)
Similar to the other but instead adds a resource element to a resource of a specified name (Origin)

Public Shared Sub RemoveResourceElementAt(ByVal ResourceIndex As Integer, ByVal ElementIndex As Integer)
Removes a resource element givent a resource index and the element index.

Public Shared Sub RemoveResourceElement(ByVal ResourceOrigin As String, ByVal Name As String)
Similar but removes a resource element with a specified name at the resource with the specified Origin

Public Shared Sub SetResourceElement(ByVal ResourceIndex As Integer, ByVal ElementIndex As Integer, ByVal Value As Object)
Given a resource index and a resource element index, change the value of the element.

Public Shared Function GetResourceElement(ByVal ResourceIndex As Integer, ByVal ElementIndex As Integer)
Returns the value at a specified resource element index at a resource index

Public Shared Sub AddToSend(ByVal msg As String)
Adds a message to the list of message to send to the server

Public Shared Sub AddToRecv(ByVal msg As String)
Adds a message to the list of messages that are received by the server

Public Shared Sub AddToConsole(ByVal msg As String)
Adds a message to the list of message that will be shown on the output

Public Shared Sub SetCurrentChan(ByVal newChan As String)
Sets the current channel the bot is in "Does NOT actually change the channel is in, used for message handling"

Public Shared Function GetCurrentChan() As String
Gets the current channel the bot is currently in "Does NOT actually get the channel the bot is currently in, used for message handling"

Public Shared Function GetResourceIndexOfOrigin(ByVal Origin As String) As Integer
Returns the index of a resource of a given name (Origin)

Public Shared Function GetElementIndexOfName(ByVal Name As String) As Integer()
Returns the resource index and element index for an element with a specific name

Public Shared Function GetElementIndexOfName(ByVal ResourceIndex As Integer, ByVal Name As String) As Integer
Returns the index of a resource element in the resource at the specified index

Public Shared Sub StopPluginManager()
Stops the plugin manager built into the bot and is used by default.

Public Shared Sub StartPluginManager(ByVal Owner As String, ByVal Server As String)
Starts the plugin manager built into the bot and is used by default.

Public Shared Sub StopConnectionClient()
Stops the IrcClients connection to the server

Public Shared Function StartConnectionClient(ByVal Server As String, ByVal Port As String, ByVal Nick As String, ByVal Channel As String, ByVal Pass As String, ByVal JoinMsg As String) As Boolean
Starts the IrcClients connection to a server, the return boolean indicates a successful or failed connection attempt.

The plugin must implement 3 things:
    ReadOnly Property Name() As String
    Function ProcessMessage(ByVal InputMessage As GlobalResources.Message) As Boolean
    Sub Config()

Messages are sorted into 2 types:
1) PRIVMSG (private message that is properly formatted in a way this bot can understand by default)
2) NS (non-sense/not-supported)

NS messages are not discarded, they are passed to all plugins (unless a plugin stops the chain) just like every other message, the difference is their type will be NS and a plugin would have to manually process that message in its raw form.

Messages that have been processed have a structure of the following:
    Public Structure Message
        Dim Type As MessageType
        Dim Nick As String
        Dim User As String
        Dim Host As String
        Dim Target As String
        Dim Message As String
        Dim Owner As String
        Dim Server As String
        Dim Raw As String
    End Structure

Message is where the message itself (what the user specifically send) is stored.
Raw is the message exactly as it was received by the bot with all heading information intact.

ResourceElements have the following structure
    Public Structure ResourceElement
        Dim Type As String
        Dim Name As String
        Dim Value As Object
    End Structure

Resource has the following structure
    Public Structure Resource
        Dim Origin As String
        Dim Resources As List(Of ResourceElement)
    End Structure

Here is the starting source for making a plugin:

For a complete source of Globals.dll :

Here is the source to my Raffle2 Plugin:

Source for UserList plugin:

And finally my horrible source for the bot itself:

As always if anyone has any issues or improvements please leave a comment :)