StealthBot.net: Intermediate Scripting - StealthBot.net

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • This topic is locked

Intermediate Scripting

#1 User is offline   The-Black-Ninja Icon

  • The Sex
  • Icon
  • Group: Scripting Moderators
  • Posts: 2,526
  • Joined: August-01 09

Posted October 30, 2009 - 01:38 PM

Intermediate Scripting
This is for scripters who are a little more learned in programming. This series of exercises will teach you about using For...Next loops, nested For...Next loops, and introduce you to grabbing information from a website, since this heavily involves isolating text from a string (see --> Scripting Basics <--) and the for loops we will talk about here.

Getting to know For...Next loops
This will show you how to properly format your script. Since this is the first thing you need to do, we're going to look at this first.

Using nested For loops
This will show you how use a nested for loop. This means using a loop within a loop. Learning this will get you out of SO many jams, so it's wise to look at this :P

Parsing websites
This tutorial will show you the various methods of parsing website data and displaying the results in your bot.

Reading/Writing to text files
This tutorial will show you the various methods of reading and writing to text files.

Reading/Writing to INI files
This tutorial will show you the 3 methods to write, read, and remove entries from ini files.

Working with Dictionaries
This tutorial will show you the basics for working with the Dictionary object.

#2 User is offline   The-Black-Ninja Icon

  • The Sex
  • Icon
  • Group: Scripting Moderators
  • Posts: 2,526
  • Joined: August-01 09

Posted October 30, 2009 - 01:40 PM

Getting to know For...Next loops
For...next loops will become your friend forever once you know how to use them. They're super easy simple and with these loops, you can arrange an array of date into chronological order!! Let's start out.

It can't get any simpler than this; a for...next loop takes a variable and counts up or down for X amount of times. In this example, we have the variable " i ". Think of that variable as our counter; we are going to set the counter to 1 and we will loop for 10 times:

Quote

For i = 1 To 5
AddChat vbGreen, "Loop counter: " & i
Next
Our output looks like this:

Quote

Loop counter: 1
Loop counter: 2
Loop counter: 3
Loop counter: 4
Loop counter: 5

Note that " i " isn't anything special, it's just a variable that's going to be increasing for 5 times. We could name it a, b, c, anything, we could even start it at 5 and go until 10:

Quote

For b = 5 to 10
AddChat vbGreen, "Loop counter: " & b
Next

Quote

Loop counter: 5
Loop counter: 6
Loop counter: 7
Loop counter: 8
Loop counter: 9
Loop counter: 10



Now, say we want to go backwards, counting backwards from 5 to 1. We'll have to insert a function called Step. What Step does is tell the loop how much to increase the counter. In our example above, Step 1 is assumed, which makes sense because the variables are increasing by 1. What do you think Step 2 would do? Increase the counter variable by 2 instead of 1? Yes. Visualize the output if we went from 1 to 10 using Step 2; 1, 3, 5, 7, 9! Okay, back to our reverse counting:

Quote

For i = 5 To 1 Step -1
AddChat vbGreen, "Loop counter: " & i
Next

Quote

Loop counter: 5
Loop counter: 4
Loop counter: 3
Loop counter: 2
Loop counter: 1
Very cool, eh? That's all there is to it! Let's check a real world example: You have a list of safelisted usernames and want to check if the user joining the channel is on that list.

Quote

safeList = Array("User1", "User2", "User3", "User4", "User5", "User6")

Sub Event_Userjoins(Username, Flags, Message, Ping, Product, Level, OriginalStatString, Banned)
'// Remember arrays start at 0 and UBound will return a number of items in an array
For i = 0 To UBound(safeList)
'// Start to compare the username to the safelisted user in the array for the current count
AddChat vbGreen, "Comparing " & LCase(Username) & " to " & Lcase(safeList(i))
If LCase(Username) = LCase(safeList(i)) Then
AddChat vbMagenta, "Name found! Safelisted user: " & Username
'// To save processing time, Exit for loop because we found what we're looking for and don't have to loop through the rest of the array
Exit For
End If
Next
End Sub


#3 User is offline   The-Black-Ninja Icon

  • The Sex
  • Icon
  • Group: Scripting Moderators
  • Posts: 2,526
  • Joined: August-01 09

Posted October 30, 2009 - 01:41 PM

Using nested For loops
Nested loops are where it starts to get tricky, but it's not THAT tricky once you understand how it's working.

When I was first starting out how to script, I had to learn this for myself and it took me a while to put what I'm looking at into words, so here you go for free lol public/style_emoticons/default/tongue.gif A nested loop is a loop within a loop. Say we're observing two variables, i and j, here's how the nested loop evaluates this:

Quote

Loop to first i variable
  • Evaluate all j variables

Loop to second i variable
  • Evaluate all j variables

Loop to third i variable
  • Evaluate all j variables

and so on...
Keep in mind that this is a very generic case, but this is more than likely how it's working. The best way to explain this is a real world situation.

You have two lists; a clan list from a two weeks ago and a clan list you just updated. Here are the lists:
2-week old clan list:
  • User1
  • User2
  • User3
  • User4
  • User5

Updated clan list:
  • User1
  • User2
  • User3
  • User4
  • User5
  • User6
  • User7
  • user8

Your goal is to evaluate the new list to see who's existing and who is new...nested for loops!! Let's just addchat all the variables with a simple check to notify us if they exist or if they don't exist. Note that for each loop, the counter variables MUST be different, ie. you can't have For i = 100 inside another loop that's For i = 5 to 100.

Quote

oldList = Array("User1", "User2", "User3", "User4", "User5")
newList = Array("User1", "User2", "User3", "User4", "User5", "User6", "User7", "User8")

'// Remember that arrays start at 0 and UBound(array) returns an integer, so this is really saying:
For i = 0 To UBound(newList)
For j = 0 To Ubound(oldList)
AddChat 151223, "(i) " & newList(i) & " : " & "(j) " & oldList(j)
AddChat vbMagenta, "Does " & newList(i) & " match " & oldList(j) & "?"
AddChat vbGreen, newList(i) = oldList(j)
Next
Next

I'll let you study the output for yourself. Notice that as the i variables progressed, there was a point where they didn't change, only the j variables were changing. This is because of what I said earlier; for every i variable, all the j variables are looped through before the i counter can increase, doubling the length of the loop.

Now, let's look at how we can set up a " bubble loop " to arrange some clan user's inactivity days in acsending order (least inactive to most inactive). It's still the same process as above, nested loops, but we're going to be using some variables to get some control on this loop because we don't want some wild loop happening, we want this double loop to not overwrite everything as it goes on.

Quote

Script("Name") = "test"
Script("Author") = "The-Black-Ninja"
Script("Major") = 1
Script("Minor") = 0
Script("Revision") = 0

Sub Event_PressedEnter(text)
If Left(text, 2) = "/a" Then
names = Array("User1", "User2", "User3", "User4", "User5", "User6", "User7", "User8", "User9", "User10")
inactiveDays = Array(12,3,22,34,6,9,10,11,12,12)

'// Set a variable to some really high number so that we have something to compare their times with something that we know they aren't going to exceed
maxCount = 5000

'// Loop through the days inactive only. This is so we can keep looping through all the days and constantly comparing if the day we're looking is higher or lower that something we've already looked at
For i = 0 To Ubound(inactiveDays)
For j = 0 To Ubound(inactiveDays)
'// Check if the days in the array are less than the maxCount (obviously it will be less)
If inactiveDAys(j) < maxCount Then
'// Set a temporary variable to reflect the loop counter we observed the result at
num = j
'// Set the maxCount variable equal to the current value of the array for the loop counter. This is so that as the loop goes on and on, our maxCount will get smaller and smaller until it can't get any smaller. Once it reaches that point, we have the lowest value and we can proceed.
maxCount = inactiveDAys(j)
End If
Next
'// We found the smallest value, so set it into out little output before we move on
output = output & names(num) & " (" & inactiveDays(num) & "), "

'// Temporarily alter our item so that we are setting the lowest number we found equal (or greater) than the maxCount so when we loop over it again, we won't be overwriting our lowest value with something we already found
inactiveDays(num) = 5000

'// Finally, reset our maxCount because we messed with its value earlier and so that we can continue comparing values.
maxCount = 5000
Next

AddChat vbGreen, "Inactive users: " & Left(output, Len(output)-2)
End If
End Sub

If you're confused about this, you should add a few addchats in throughout the loop so you can visually see how it's all working. It still takes me a few minutes to visualize what I'm trying to do if I haven't done this for a while, so don't feel bad if you can't understand it right away public/style_emoticons/default/smile.gif

#4 User is offline   The-Black-Ninja Icon

  • The Sex
  • Icon
  • Group: Scripting Moderators
  • Posts: 2,526
  • Joined: August-01 09

Posted October 30, 2009 - 01:43 PM

Parsing websites

The first thing anyone needs to know when parsing a website is a neat little feature in your browser that allows you to view the site's HTML code; View, then click Source. This HTML is what the bot will be looking at when you use the scInet object or you use the XMLHTTP object.

Just a quick note, due to the constraints of the post, I wasn't able to give the full HTML output in my examples, so when you see the quotes with the HTML stuff in there and when I split the title stuff, switch the { and ( brackets with the angle brackets, <.

scInet object
  • Simplest method to use when opening up webpages.
  • Can only run one instance at a time, ie. If you were busy opening up one webpage for a script and another script wants to use scInet, that script has to wait until the first one is done.

XMLHTTP
  • Needs a little more work than scInet
  • Can open multiple pages at a time
  • Usually has a faster parse time than scInet.


Okay, that's a little bit of background on these objects without going into too much detail, you can research them yourself if you want to find more information, but for now, let's jump right in.

Let's say you want to find the full clan name of the clan tag of the guy who just joined your channel. First, we need their clantag. There are two methods to use for this; GetInternalDataByUsername OR the new Channel object.

Quote

clan = GetInternalDataByUsername(Username, 0)

'// OR

clan = Channel.Users(Channel.GetUserIndex(Username)).Clan

I personally like using the Channel object better because all you need to do is change the .Clan to .Ping, .Flags, etc. without having to remember that 0 means clan or any of that stuff.

After we get their clan tag, we'll need to locate their clan webpage so we can tell the script where to look, in the HTML, for their clan's name, so go ahead and get to their page, ie. if they're on frozen throne and in Azeroth, their bnet page is this:
http://classic.battl...th&ClanTag=dota

Go ahead and view the source in your browser. A new window opens up with all the HTML for the site and we have to somehow figure out where their full clan name is in that mess. A simple CTRL+F solves this; search for their full name, " Defense of the Ancients ". There are two matches found, one at the top, and one further down in the code. I like using the one at the top because it's the easiest to get to :P

Tips when parsing HTML
  • When parsing HTML, think of it as one massive text string and you're trying to isolate bits and pieces from the string. Depending on how complex the HTML is determines how tricky or how easy this is going to be
  • Always try to parse the HTML in a way that makes it universal, ie. If you're dealing with clans on bnet pages, would it make sense to parse the HTML at occurances of "Azeroth"? No, because if you were to switch realms, Azeroth will get replaced with Lordaeron or the like
  • USE SPLIT!!! You are going to be in love with how Split makes parsing HTML so much easier. Split, in my opinion, is the absolute best way to isolate anything from HTML
  • When searching for what to split, always be sure that the text you choose occurs once or a few times before where you're wanting to be so you know what to input into your Split function. I always try to find text that occurs only once and that's closest to to where I want to be because it's just easier that way

Let's look at the code required to parse this. I'm going to give both examples of scInet and the XMLHTTP objects:

scInet

Quote

Sub Event_Userjoins(Username, Flags, Message, Ping, Product, Level, OriginalStatString, Banned)

'// Check if the object is in use before continuing
If scInet.StillExecuting Then
AddChat vbRed, "Bot is busy. Please try again later."
Exit Sub
End If

clan = Channel.Users(Channel.GetUserIndex(Username)).Clan

web = scInet.OpenURL("http://classic.battle.net/war3/ladder/w3xp-clan-profile.aspx?Gateway=Azeroth&ClanTag=" & clan)
fullName = Split(Split(web, "(title>")(1), "(/title>")(0)

I want to pause here and tell you what I've just done when using Split that way. The block of text we're looking at is this:

Quote

{!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
{HTML>
{HEAD>
{title>Frozen Throne - Azeroth - Defense of the Ancients - Clan Profile
{link rel="stylesheet" type="text/css" href="/war3/includes/war3-human-ie.css">
{link rel="stylesheet" type="text/css" href="war3-ladder-ranking.css">
{style type="text/css">

Our full clan name is inside the {title> tags, so what I'm doing is splitting the HTML so I have:

Quote

Frozen Throne - Azeroth - Defense of the Ancients

- Clan Profile
{link rel="stylesheet" type="text/css" href="/war3/includes/war3-human-ie.css">
{link rel="stylesheet" type="text/css" href="war3-ladder-ranking.css">
{style type="text/css">

Then splitting it again so I've just isolated what's inside the title tag, all in one step:

Quote

Frozen Throne - Azeroth - Defense of the Ancients - Clan

Profile

Moving on...

Quote

Sub Event_Userjoins(Username, Flags, Message, Ping, Product, Level, OriginalStatString, Banned)

'// Check if the object is in use before continuing
If scInet.StillExecuting Then
AddChat vbRed, "Bot is busy. Please try again later."
Exit Sub
End If

clan = Channel.Users(Channel.GetUserIndex(Username)).Clan

web = scInet.OpenURL("http://classic.battle.net/war3/ladder/w3xp-clan-profile.aspx?Gateway=Azeroth&ClanTag=" & clan)
fullName = Split(Split(web, "(title>")(1), "(/title>")(0)

'// Isolate the text we want. Convieniently, we can turn the block of text into an array :)
fullName = Split(fullName, " - ")(2)
AddChat vbGreen, Username & "'s clan: " &fullName & "(" & clan & ")"



XMLHTTP

Quote

Sub Event_Userjoins(Username, Flags, Message, Ping, Product, Level, OriginalStatString, Banned)

clan = Channel.Users(Channel.GetUserIndex(Username)).Clan

'// No need to check if the object is in use because XMLHTTP can run multiple times, so just create the object
Set webObj = CreateObject("Microsoft.XMLHTTP")

'// Tell it to "get" the webpage code
webObj.Open "GET", "http://classic.battle.net/war3/ladder/w3xp-clan-profile.aspx?Gateway=Azeroth&ClanTag=" & clan, False

'// Send the GET request
webObj.Send

'// Set what the object returns as a variable so we're not always calling the function
web = webObj.responseText

fullName = Split(Split(web, "(title>")(1), "(/title>")(0)

'// Isolate the text we want. Convieniently, we can turn the block of text into an array :)
fullName = Split(fullName, " - ")(2)
AddChat vbGreen, Username & "'s clan: " & fullName & "(" & clan & ")"

Note that if you're parsing different webpages, you're going to be using different methods for parsing them. That's not to say you aren't going to be using Split, you WILL be using split lol but I'm saying that stuff may not be laid out as easy as this example is, so you might need to use a few more splits, maybe even use a few loops depending on what you're doing, etc.

This stuff takes practice, plain and simple. Certain webpages still take me time to parse, especially if I've never been there before. Parsing bnet pages though, I can do in like 20-30 mins just because I've done so many scripts that needed to parse these pages.

#5 User is offline   The-Black-Ninja Icon

  • The Sex
  • Icon
  • Group: Scripting Moderators
  • Posts: 2,526
  • Joined: August-01 09

Posted October 31, 2009 - 03:51 AM

<a name="fso">Reading/Writing to text files</a>

Thanks to Neco for inspiration for the very last example.

When you want to read or write to files, you will need to use a FileSystemObject. A huge, HUGE source of information is right here:

http://msdn.microsof...28VS.85%29.aspx

We are only discussing the very basics of this object, but this object is super powerful for when you want to work with files so I highly recommend you give this site a quick look. It's just awesome. This object can retrieve how many files there are in a folder, how big a file is, when the file was last modified or accessed, it's massive..

Okay, down to it.


First, we need to create the object. I like to name it something simple:

Quote

Set FSO = CreateObject("Scripting.FileSystemObject")
After our object is created, we can start reading/writing to the file by first opening the file using OpenTextFile:

Quote

Set File = fso.OpenTextFile(filename, type, True/False)

filename is obviously the file's name, but when using the .OpenTextFile method, there are three types to choose how the file will behave once it's open:
  • 1 = Reading the file only
  • 2 = Overwrite; anything you write to the file will overwrite everything existing in the file already.
  • 8 = Append; anything you write to the file will go at the end of whatever's existing.

The True boolean is responsible for whether or not the file you specify gets automatically created if it doesn't exist, or use False to raise an error because it's not created. I usually use True because I like creating files on-the-fly. Note that if you open the file as read-only and you try to write stuff into the file, you will get an error because you haven't opened the file for that task.

After the file is open, we can use the .ReadAll method to read everything in the file:

Quote

AddChat vbGreen, File.ReadAll
OR we can turn the file into an array that splits everything at each new line and use a loop to give some control on how many lines we need. Say we only need the first 5 lines:

Quote

fileArray = Split(File.ReadAll, vbCrLf)

For i = 0 To 5
AddChat vbGreen, fileArray(i)
Next
Note that vbCrLf means Carriage Return and Line Feed, most text documents have this combination and is a code for when a text line has been terminated. Every time you're typing something in a word editor and you press enter, that's a CRLF code. Note that vbCrLf is the exactly the same as vbNewLine, so you can use either when you script.

If we're wanting to write to a text document, after we've opened the file, we can use the .WriteLine method:

Quote

File.WriteLine "WOOT!"

This part is very important, after you've finished with a file, you MUST CLOSE IT! Otherwise your script is going to error whenever it tries to access it again. This is accomplished by:

Quote

File.Close
Fairly straight forward stuff here, nothing too tricky. Let's write up an example.

Quote

Sub Event_PressedEnter(Text)

If Left(Text, 5) = "/test" Then
'// Create the object
Set fso = CreateObject("Scripting.FileSystemObject")

'// Create a file on-the-fly for writing
Set File = fso.OpenTextFile(BotPath & "FSO_test.txt", 8, True)

File.WriteLine "Woot! New Line"
File.WriteLine "Woot! Second Line"
File.WriteLine "Third line now!"

'// Close the file
File.Close

'// Let's open the file back up to read what we just wrote
Set File = fso.OpenTextFile(BotPath & "FSO_test.txt", 1, True)

AddChat vbGreen, File.ReadAll

'// Let's only display the second line, just for kicks
AddChat vbGreen, "The second line reads: " & Split(File.ReadAll, vbNewLine)(1)
File.Close

'// We have no use for anything in that file, we want to write a list of names now.
'// First we have to overwrite the entire file with one line, THEN we have to re-open the file as append or else we'll be overwriting everything and will only have 1 line in the end.
AddChat vbYellow, "Overwriting the file with a list of names now..."
Set File = fso.OpenTextFile(BotPath & "FSO_test.txt", 2, True)
File.WriteLine "Name1"
File.Close

Set File = fso.OpenTextFile(BotPath & "FSO_test.txt", 8, True)
File.WriteLine "Name2"
File.WriteLine "Name3"
File.WriteLine "Name4"
File.Close

Set File = fso.OpenTextFile(BotPath & "FSO_test.txt", 1, True)
AddChat vbGreen, File.ReadAll

'// Bleh, we don't want this file anymore. Let's delete it.
AddChat vbYellow, "Deleting file..."
fso.DeleteFile(BotPath & "FSO_test.txt")

'// Let's make sure it's gone
AddChat vbGreen, "Making sure file is gone. Does the file exist?"
AddChat vbYellow, fso.FileExists(BotPath & "FSO_test.txt")

'// To save memory, set our variable to nothing
Set File = Nothing
End If
End Sub


Let's say we have a file full of names and we want to see if someone exists in that list. We can use a Do loop, which is like a For loop only a Do loop loops until a condition is met.

Quote

Sub Event_PressedEnter(Text)

If Left(Text, 9) = "/findname" Then
If UBound(Split(Text)) < 1 Then
AddChat vbGreen, "Enter a name to find."
Exit Sub
End If

'// Create a list of names
Call MakeNameList

name = Split(Text)(1)

'// Let's make a boolean so we can check later if there was a found match
tMatch = False

Set fso = CreateObject("Scripting.FileSystemObject")
Set File = fso.OpenTextFile(BotPath & "FSO_test.txt", 8, True)

'// AtEndOfStream means the very end of the file, so this loop will continue to go on until it reaches the end of the file
Do Until File.AtEndOfStream
'// We can use File.ReadLine because we're wanting to read the individual lines as we go along
If Lcase(name) = Lcase(File.ReadLine) Then
'// Found match, set our boolean to true
tMatch = True
'// Exit the loop - we found what we were looking for
Exit Do
End If
Loop

'// Close the file and delete it because, after all, this is only a demo :P
File.Close
fso.DeleteFile(BotPath & "FSO_test.txt")

If tMatch Then
AddChat vbGreen, "Found match: " & name
Else
AddChat vbGreen, "No matches found."
End If

'// To save memory, set our variable to nothing
Set File = Nothing
End If
End Sub


Private Sub MakeNameList()

Set File = fso.OpenTextFile(BotPath & "FSO_test.txt", 8, True)

'// Using With eliminates the use for always typing File before .Whatever
With File
.WriteLine "Blake"
.WriteLine "Anna"
.WriteLine "Krystal"
.WriteLine "Jenn"
.WriteLine "Laura"
.WriteLine "Mike"
.WriteLine "Bryan"
.WriteLine "Alex"
.WriteLine "Eric"
.WriteLine "Ryan"
.WriteLine "Josh"
.WriteLine "David"
.WriteLine "Heather"
.Close
End With

'// To save memory, set our variable to nothing
Set File = Nothing
End Sub


Those are the most common applications for the FSO object. I can talk about the other methods, but I don't feel like re-writing what the link I posted already has, SO, any further questions, just make a post about it! :)

#6 User is offline   The-Black-Ninja Icon

  • The Sex
  • Icon
  • Group: Scripting Moderators
  • Posts: 2,526
  • Joined: August-01 09

Posted November 02, 2009 - 02:32 AM

<a name="dict"> Working with Dictionaries</a>

Dictionaries are wonderful objects that allow you to store many variables, called "keys", with any sub-information about the variable, called "items", all in one convinient object. Some more information can be found on Microsoft's MSDN website:
http://msdn.microsof...28VS.85%29.aspx

What do I mean be all that? Let's say you're wanting to come up with some sort of anti-flood for a command you've made where you only want a user to use the command once every 20 minutes. You COULD use some simple variables or even some arrays, but you would have to do some tricky stuff to add and remove users. In comes the dictionary object. With this object, you can store a user's name into the object, as well as have the time they used the command associated to their entry. This is what makes dictionaries so powerful; they can store a large amount of data into one neat array that allows for easy retrieval and removal.

Example time. First and foremost is we need to make the dictionary object Private or Public in our script. I like making the objects Private for most uses because I don't usually make scripts that will need to look at objects in other scripts. Next, we need to create the object AND we need to make it so that the object is going to ignore upper case and lower case:

Quote

Private userDict

Sub Event_Load()

Set userDict = CreateObject("Scripting.Dictionary")
'// Ignore cases
userDict.CompareMode = 1
End Sub
By setting CompareMode equal to 1, we're performing a text comparison, however you can also say " vbTextCompare " but I like using a 1 because it's easier than typing all that other stuff :P

Now we need to figure out how to add people to the dictionary. The method I love basically tells the dictionary that I want to directly set an item for a key equal to a value. If the key doesn't exist, it's created automatically:

Quote

userDict.Item(Username) = Now
Using that, I have told the script to set the item for the specified username equal to the current time and date (Now function). If we want to retrieve their item later on, we can simply use:

Quote

userDict.Item(Username)

Similarily, we can add multiple items to their key by setting the items as Arrays:

Quote

userDict.Item(Username) = Array(Now, commandName, clan)
To retrieve their items, we need to remember that their items are now in array format, so we can either isolate 1 element or use a For loop to display all of them:

Quote

userDict.Item(Username)(1)

'// OR

For Each item In userDict.Item(Username)
output = output & item & ", "
Next


Then, if we want to remove them from the dictionary, the method is even simpler:

Quote

userDict.Remove Username
Or if we want to remove everything from the dictionary:

Quote

userDict.RemoveAll


We can also check if different keys exist in the dictionary object by using:

Quote

userDict.Exists(Username)
This returns a Boolean; True means it exists, False means it does not.

Before we get to the example, there's a new function we need to look at and that is the DateDiff function (http://www.csidata.com/custserv/onlinehelp/VBSdocs/vbs95.htm) and I'm going to leave it up to you to read up on this function.

Quote

Private userDict '// Dictionary object
Private Const waitTime = 25 '// Minutes users have to wait before using the command again

Sub Event_Load()

Set userDict = CreateObject("Scripting.Dictionary")
'// Ignore cases
userDict.CompareMode = 1
End Sub

Sub Event_Usertalk(Username, Flags, Message, Ping)

If Message = BotVars.Trigger & "command" Then
'// Check if they exist in the dictionary or not
If userDict.Exists(Username) Then
'// They exist, so find out if they've waited 25 minutes
If DateDiff("n", userDict.Item(Username), Now) > waitTime Then
'// They've waited long enough
AddQ "You are authorized to use the command again."
Else
AddQ "You must wait: " & waitTime - DateDiff("n", userDict.Item(Username), Now) & " minutes before using the command again."
End If
Else
'// They don't exist, so allow them to do the command and add them to the dictionary
AddQ "You are authorized to use the command again."
userDict.Item(Username) = Now
End If
End If
End Sub


Say you had a few users in your dictionary object and just wanted to find a way to list all the users with all their arrayed items, so you've been adding users with: userDict.Item(Username) = Array(Now, commandName, clan):

Quote

'// Set some simple variables to represent the keys and items for the dictionary object
users = userDict.Keys
items = userDict.Items

'// All dictionary objects store their keys as arrays
For i = 0 To UBound(users)
AddChat 234234, users(i) & "'s items:"
'// Make another loop to loop through their items
For j = 0 To Ubound(items)
AddChat vbGreen, items(i)(j)
Next
Next


#7 User is offline   The-Black-Ninja Icon

  • The Sex
  • Icon
  • Group: Scripting Moderators
  • Posts: 2,526
  • Joined: August-01 09

Posted November 04, 2009 - 11:25 PM

Reading/Writing to INI files

INI files differ from txt files because the ini files are configuration files that have a standard setup of:

Quote

[heading]
name=value
'comment

What makes ini so useful are that they are very easy to delete and insert new entries to the file, however, reading everything that's in a section cannot be done using the ini methods, you need to use the FileSystemObject for that.

There really isn't much to know about ini files; there is no need to create an object and there is no need to open/close the file for whatever you want to do. Thanks to the new scripting system, there are now even more methods to read and write to an ini file:

Quote

'// Reading/Writing to the scripts.ini file for the current script directly:
'// To read...
GetSettingsEntry("entry name")
'// To write
WriteSettingsEntry "entry name", value

'// Reading/Writing to the scripts.ini file for the another script directly:
'// To read...
GetSettingsEntryEx("script name", "entry name")
'// To write...
WriteSettingsEntryEx "script name", "entry name", value, "Description is optional"

'// Reading/Writing to other ini files
'// To read...
GetConfigEntry("heading", "entry name", filepath)
'// To write...
WriteConfigEntry "heading", "entry name", value, filepath


Since the longest, and most common, method is WriteConfigEntry/GetConfigEntry, we will be focusing on that because if you can understand it, the other two are no brainers.

The best part about using ini files is that if the file you're specifying isn't there when using Write***, the file gets created automatically without any special coding. Note that when using Get*** to get a value for an entry, the value is anything to the right of the " = " in the file and the entry is to the left of the " = " sign, but if the value of an entry is totally deleted, or is replaced be a vbNullString, that entry gets removed from the file.

Quote

Sub Event_PressedEnter(Text)

If Left(Text, 10) = "/checkname" Then
cmdArr = Split(Text)

If UBound(cmdArr) < 1 Then
AddChat vbGreen, "Give me the name of someone to find!"
Exit Sub
End If

'// Specify the file path
filePath = BotPath & "config_test.ini"

'// Check if someone has an entry in the file
If GetConfigEntry("names", cmdArr(1), filePath) = vbNullString Then
AddChat vbGreen, cmdArr(1) & " doesn't exist in the ini! Adding them now..."
WriteConfigEntry "names", cmdArr(1), Now, filePath
Else
'// They exist
AddChat vbGreen, cmdArr(1) & " is in the ini! They were added on: " & GetConfigEntry("names", cmdArr(1), filePath)
End If

ElseIf Left(Text, 11) = "/deletename" Then
cmdArr = Split(Text)

If UBound(cmdArr) < 1 Then
AddChat vbGreen, "Give me the name of someone to delete!"
Exit Sub
End If

'// Specify the file path
filePath = BotPath & "config_test.ini"

'// Check if someone has an entry in the file
If GetConfigEntry("names", cmdArr(1), filePath) = vbNullString Then
AddChat vbGreen, cmdArr(1) & " doesn't exist in the ini! You need to add them first before deleting them."
Else
'// They exist
AddChat vbGreen, cmdArr(1) & " is in the ini! Deleting them now..."
WriteConfigEntry "names", cmdArr(1), vbNullString, filePath
End If
End If
End Sub


Page 1 of 1
  • You cannot start a new topic
  • This topic is locked

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users