Winnap - Learning to Script

If you came here to learn how to write scripts for Winnap, you came to the write place ;). If you came here for a guide to run pre-made scripts, then you should look at Guide.htm in your \Docs\ folder. I am not the best at teaching people people coding languages, or learning them, especially when they're not GUI based. Coding in VBS is very different to coding in Visual Basic, because when you type a command in Visual Basic, it shows a 'ToolTip' with the arguments of it. Coding in Notepad doesn't ;p. However, you can STILL write VBS in Visual Basic 6. So, if you are used to using the VB6 IDE, then open a new window, create a Module, and do you coding HERE, instead of Notepad. Notepad works just as well, so don't rush out and "buy" a copy of VB6.
Note: If you use VB6, after saving your work as a .bas you'll need to rename it as a .txt file, edit it in Notepad to remove the "Attribute VB_Name" line at the top!
So, back to teaching. Firstly, once you are past the "basic" stages off scripting, read the Advanced Overview of Winnap Scripting text document. If you need the scripting engine improved, I will happily add new features to it, as long as I see them worthwhile (and I usually will). Now, open your new text document (in Notepad), and enter the Winnap Scripting Master Commands. What are these? They allow the script to take a bit more control over the way Winnap runs it, and allows for 100x easier debugging. So what do you need for most scripts? These commands (you only type the bold text, the rest is an explanation.) should be used for most scripts, especially while you are still writing them. However, depending on how large your script is, !extdebug will cause a slight hike in the memory usage of Winnap.

  • !include basic - This makes Winnap add the latest version of the internal module "basic" to your Script. This module allows your script to send data, and use the 'CharCount' function (counts the amount of time a string appears in another string).

  • !dodebug - This function does 'first-level' Winnap debugging, which adds a line to Script Debug with the Error description, Virtual Line and Column number. You will need this in your scripts to see where you went wrong.

  • !extdebug - This function is the 'next' level of debugging. Basically this forces Winnap to not only load the script into the scripting control, but load it as plain-text into the memory to read the line which failed to execute. This also helps a lot with debugging, and should always be used in combination with !dodebug.

Your on your way now :). Now, we write the basic procedures. Only the ones you need though, all versions of Winnap ignore the fact that some scripts don't pickup certain raised events and Script Engine Version 1.3 (I think, the Changes file got a little bit ran-down while Build 12 was underway) and upwards no longer leave irrelevant debug messages about unused events. All Raised events are documented in the Advanced Guide to Scripting file in your documents folder, so if you need more events than mentioned here they may be described there.

Our first event

Sub Init()
  Form.ScriptLog ScriptIndex, "My First Script v0.1 - Written by The Author", vbRed
  Form.ScriptLog ScriptIndex, "Script is running on nickname " & Nick, vbRed
End Sub

What does our script do now? This:

[7:26:43 PM] Script#2: Script is now running
[7:26:43 PM] Script#2: My First Script v0.1 - Written by The Author
[7:26:43 PM] Script#2: Script is running on nickname Coolman_mike

So, the script is now "recognized" as a script :). Winnap Initializes the script and the script does what it needs to do. By default, a script will timeout after processing for 10 seconds. This IS changeable with the !set_timeout command (!set_timeout 10000 would be 10 seconds, it is in MS). But, while a script is processing, it stops the user and Window from communicating with Winnap, and everything gets back logged. Most processing takes less than 1 second, or in cases of large text-based databases, under 5~. This DOES depend on factors of your computer, including CPU, RAM (to a degree) and definitely hard drive speed.. However, what we have done so far, isn't really "hard work". But hey, it's a script. Before you can get extremely far into scripting, you need to learn a little bit about the Napster protocol. However, firstly I'll show you some event handling. Before I do that, I should step you through the above script. The first thing is, 'Form' refers to frmMain inside the actual Winnap project. This allows access to all Public Functions and On-form objects. The only object you will ever need to use is chtRoom(i), for determining chat rooms a user is currently active in. All of the functions that can be used on the main form are descried in the advanced guide, referred to earlier in this guide. ScriptLog adds a line to the Script Debug log under the scripting pane in Winnap. ScriptIndex is the Array Index. This helps the human factor of Scripting differ between log messages from different scripts :P. The 2nd parameter, which is inside talking (") marks, is what you want logged, as you can see in my example. If you need to use talking marks inside a log message, or anything, you have to do something like this:

Form.ScriptLog ScriptIndex, "This is a " & Chr(34) & "quoted" & chr(34) & " string", vbRed

So what's Chr(34)? Character 34, which is a talking mark on computers. If you didn't know, there are 255 characters in the ASCII table. If you need to find out a characters "number", you can do something like Asc("A"), which would return 65. So now there is only one more thing to explain, which is vbRed. Why is it called this? Because Microsoft likes spamming its software and making us coders type more :p. If you were wondering, Winnap does not have its "very own unique scripting engine". It is based on Microsoft's Scripting OCX. I learnt how to make this control do all the hard work, yet still allow Winnap to tell it what to do or ask it to return values. Other colours you can use are vbBlack, vbBlue, vbCyan, vbGreen, vbMagenta, vbWhite, vbYellow. Upon using these colours you will release they are extremely inappropriate and hard to read, except for a few, and they if you are going to be doing a lot of multi-coloured script debugging you will need your own colours. Luckily, this is simple. Below I have included the colours used in the actual Winnap client, instead of Microsoft's "colours".

Public Const vbGold = 49344
Public Const vbDGreen = 32768
Public Const vbOrange = 33023
Public Const vbPurple = 8388736
Public Const vbBrown = 3697585
Public Const vbNPink = 10040783
Public Const vbCoolBlue = 8865288

Some of these colours aren't used anywhere in Winnap, but are still nice colours to have handy. That is how you would include a colour in a script, too. Of course, you probably have no idea what the numbers are. Colours have 'long values'. These values can be retrieved in VB by doing a simple Colour = RGB(Red, Green, Blue). There are programs on the internet, simple programs with slide bars, that allow you to make colours in HEX, HTML and Long Values. However, for most cases this is highly irrelevant, and the internal colours and extras I have provided will do just fine.

Some more events

Sub Tick()
  SPassed = SPassed + 1
End Sub

SPassed basically means seconds passed. It is a common variable for Winnap scripts, as I wrote all my scripts using it and the client, when testing how long a script has been running, actually ASKS the script, which means you could make the uptime completely inaccurate. However if you did, it'd be pointless because it isn't shown anywhere, except to a user when he clicks the script to check where its running or to terminate it. Naturally, you can have MORE code in your Events if needed. If, every second, you needed to do something it'd be fine. The same as with ANY Sub or Function. I am getting a bit ahead of myself, let me slow down ;). In the Actual "coding header", which is the top of your text file, you can put code. For example:

  • Const Whatever = "I do what I want" - This makes a "Constant", which in this case means its always accessible. Constants cannot be changed by the code, and constants are generally used in the case you will be using a variable which might change. For example, in Trivia.txt there is the Chan2Use constant, which is the channel Triva will run in. You cannot use a constant like: Const Whatever = YourFunctionName, because that ISN'T a Constant Expression.

  • Dim Whatever - Dim means "Dimension", I think, I have no idea what Dimension means in this scenario though. What Dim does is very similar to what Const does, but Dimmed strings are changed by code, and don't have = "Your string here" after the 'command', if that's what you call it.

Let's get straight into it. It is better if I show you a sample script, and teach you what each part does. This script will be called MathBot.txt and it will suck :P. Below, I have the script in a different font. Copy it into MathBot.txt and run it. It should work FINE :). Note: I was going to write a much simpler Math Script, with only + - * /, then I thought Square root would be cool, and decided I'd make it so that the spare Script system would process each argument sent.

!include basic
!dodebug
!extdebug
Const SVer = "0.1"

Sub Init()
Form.ScriptLog ScriptIndex, "My Math Bot v" & SVer & " - Written by Your Name Here", vbRed
Form.ScriptLog ScriptIndex, "Script is running on nickname " & Nick, vbRed
For i = 1 To Form.chtRoom.Ubound
If Form.chtRoom(i).CIndex = ServerIndex Then
If Form.chtRoom(i).InActive = False Then
'We found a room
Send 402, Form.chtRoom(i).Channel & " My Math Script v" & SVer & " is now running!"
End If
End If
Next
End Sub

Sub OnData(Data)
Dim Cmd
Dim User
Dim AText
Dim UScore
Cmd = Split(Data, " ")(0)
Select Case Cmd
Case 403
'Got a message in our room
User = Split(Data, " ")(2)
'403 Chan2Use User msg
AText = Mid(Data, 7 + Len(Split(Data, " ")(1)) + Len(User))
If Not AText = "" Then
If LCase(Split(AText, " ")(0)) = "!eval" then
Send 402, Split(Data, " ")(1) & " " & "Performing Calculation! If no result is sent, your formula failed"
Send 402, Split(Data, " ")(1) & " " & Mid(AText, 7) & " = " & Form.Script(0).Eval(Mid(AText, 7))
End If
End If
End Select
End Sub

Well, where to begin. First, I'll tell you how to USE the script. When you run it, it will send a message to every chat room you are in on the server you ran the script from. This is done in the Init() Procedure (Procedures are basically Subs or Functions). To use the script, in a room (any user can) type !eval 5 + 5 or another formula. For example:
[19:52:51] <Coolman_mike> My Math Script v0.1 is now running!
[19:53:39] <Coolman_mike> !eval (5 + 3) - 5 * 7
[19:53:39] <Coolman_mike> Performing Calculation! If no result is sent, your formula failed
[19:53:39] <Coolman_mike> (5 + 3) - 5 * 7 = -27
[19:53:50] <Coolman_mike> !eval ((5 + 3) - 5) * 7
[19:53:50] <Coolman_mike> Performing Calculation! If no result is sent, your formula failed
[19:53:51] <Coolman_mike> ((5 + 3) - 5) * 7 = 21

As you can see, you can run encapsulated formulas (or whatever they're called) in your script already, because instead of doing the newbie way we made Visual Basics Scripting Engine do it for us (there's nothing like being lazy). Here is something else you can do with Eval, though:
[19:56:10] <Coolman_mike> !eval Sqr(49)
[19:56:10] <Coolman_mike> Performing Calculation! If no result is sent, your formula failed
[19:56:10] <Coolman_mike> Sqr(49) = 7
[19:57:49] <Coolman_mike> Sqr means Sqare Root, as a Visual Basic Command
[19:58:08] <Coolman_mike> A problem with Eval? Sure, why not!
[19:58:18] <Coolman_mike> !eval "This computers time is " & Time
[19:58:18] <Coolman_mike> Performing Calculation! If no result is sent, your formula failed
[19:58:18] <Coolman_mike> "This computers time is " & Time = This computers time is 7:58:18 PM

As you can see, Eval actual "Evaluates" a line of code. 5 + 5 is code. In Scripting, you can do math, easily. With Eval you can use any Visual Basic (Scripting / VBS) command, as long as it returns a value. Fortunately, VBS is extremely secure for something written by Microsoft. Also, from Build 12 final and upwards the Scripting system on Array 0 uses "SafeSubset", which "Stops a script from running potentially harmful actions". Note: IF you need to use the Form.Script for .Eval, only use Form.Script on array 0. Using other arrays could potentially harm other scripts or (even more likely), your own. So, anyway, HOW does this script work...step by step!

First off, we have our scripts header, which is our ! commands and in this case, a Const command for the actual script interpreter. The Const variable is called SVer, and is 0.1 (at the time of writing). This is our version number. Next we have our Init procedure. What happens there? Alot. First we do our first 2 log entries. Then we have For i = 1 to Form.chtRoom.Ubound. Unless you've done VB oriented scripting you will have no idea what this means. For is basically a loop. i is the number that is used to count. As you can see, some things refer to Form.chtRoom(i) inside this loop, and i is from 1 to the amount of open chat rooms. UBound means all of the rooms included except the array master, array number 0. Our next line is: If Form.chtRoom(i).CIndex = ServerIndex Then. CIndex is a variable on chtRoom, indicating the server index the chat room. As you can see, this is an If statement. It's like algebra. If a = c Then DoSomething. If a is 1 and c is 1, then stuff WILL be done. If CIndex = ServerIndex, we continue. The next line is another If statement. You CAN join If statements together, for example in our case it COULD have been If Form.chtRoom(i).CIndex = ServerIndex AND If Form.chtRoom(i).InActive = False Then, however if condition 1 (CIndex = ServerIndex) is false, condition 2 (InActive = False) will STILL be checked. This is slower, so from the start I'm going to teach you the FAST way. Next you see 'We found a room. This begins with a ' (inverted comma?), which means its a comment and shouldn't be interpreted. Note: Interpreted means ran, basically. Like you interpret something someone says, and sometimes wrong ;). You can put comments AFTER a line of code too, using a ' aswell. So for example, we need to run the sub DoStuff, and we can have our code as "DoStuff 'this will do stuff". Of course commenting major areas of code is recommended, to stop you spending ages going over it to work out what the code does. Next, we have:
Send 402, Form.chtRoom(i).Channel & " My Math Script v" & SVer & " is now running!"

Send is a function in the internal module, basic. Parameter 1 is 402, which is the Napster command number. Parameter 2 is a string, or blank (some Napster commands are argument free). As I mentioned earlier, you might need a small understanding of the protocol to work with some more advanced scripts. For this script, 402 is the 'Send public message' command. The 2nd parameter includes the channel name first, then the text to put in the channel. As you can see, the string is broken in the middle. This is to include the SVer const mentioned earlier. Whenever you need to include a variable inside a string you just do this:
TheString = "This is the string. The time is " & Time & ". " & Date & " is the date"
Don't forget, using & is better than using + to join strings, because + is also a mathematical command. By the way, Time is a VB command and so is Date, along with Now which is basically Time & Date combined. There are ALOT of Visual Basic commands, and it helps alot to have Visual Basic installed to use the Object browser to find them (to access the object browser, press F2 in VB). Next we have 2 lines with only End If. These terminate our two previous If statements. Then there is the Next command. This means continue to the next number (in the For loop).

++ To be continued // Time of break ++

[20:26:45] <Coolman_mike> !eval now
[20:26:45] <Coolman_mike> Performing Calculation! If no result is sent, your formula failed
[20:26:45] <Coolman_mike> now = 7/20/2004 8:26:45 PM

Copyright 2004 - LFI.net
 Contact Coolman_mike@hotmail.com if you notice anything wrong with this