Attribute VB_Name = "Commands"
Option Explicit

'----------------------------------------------------------
'  Myriad
'  Commands Module
'  May 20, 2004
'----------------------------------------------------------

Public Const ACCESS_SAFELIST& = 1&
Public Const ACCESS_SHITLIST& = 2&
Public Const ACCESS_LOCKED& = 4&
Public Const ACCESS_TRACKED& = 8&
Public Const ACCESS_TAGBAN& = 16&
Public Const ACCESS_MASTER& = 32&

Public Users As Collection
Private IterI As Long, cDBFile As String
Public Trigger As String, Master As String, GetWHCT As Long

Public Enum WildcardSource
    wsChannel
    wsDatabase
End Enum

Public Enum CommandSources
    csNormal
    csWhispered
    csWindow
End Enum

Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, _
    ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, _
    ByVal uIDEvent As Long) As Long
    
Private TriggerFinger As Long

Public Function CheckServer() As String
    'I only did all servers for East & West, then just plain Europe & Asia
    CheckServer = ""
    If Bot.Server = "useast.battle.net" Then
        CheckServer = "@USEast"
    ElseIf Bot.Server = "uswest.battle.net" Then
        CheckServer = "@USWest"
    ElseIf Bot.Server = "europe.battle.net" Then
        CheckServer = "@Europe"
    ElseIf Bot.Server = "asia.battle.net" Then
        CheckServer = "@Asia"
    ElseIf Bot.Server = "63.240.202.139" Then
        CheckServer = "@USEast"
    ElseIf Bot.Server = "63.240.202.138" Then
        CheckServer = "@USEast"
    ElseIf Bot.Server = "63.240.202.134" Then
        CheckServer = "@USEast"
    ElseIf Bot.Server = "63.240.202.131" Then
        CheckServer = "@USEast"
    ElseIf Bot.Server = "63.240.202.130" Then
        CheckServer = "@USEast"
    ElseIf Bot.Server = "63.240.202.129" Then
        CheckServer = "@USEast"
    ElseIf Bot.Server = "63.240.202.128" Then
        CheckServer = "@USEast"
    ElseIf Bot.Server = "63.240.202.127" Then
        CheckServer = "@USEast"
    ElseIf Bot.Server = "63.240.202.126" Then
        CheckServer = "@USEast"
    ElseIf Bot.Server = "63.240.202.122" Then
        CheckServer = "@USEast"
    ElseIf Bot.Server = "63.240.202.121" Then
        CheckServer = "@USEast"
    ElseIf Bot.Server = "63.240.202.120" Then
        CheckServer = "@USEast"
    ElseIf Bot.Server = "63.241.83.7" Then
        CheckServer = "@USWest"
    ElseIf Bot.Server = "63.241.83.8" Then
        CheckServer = "@USWest"
    ElseIf Bot.Server = "63.241.83.9" Then
        CheckServer = "@USWest"
    ElseIf Bot.Server = "63.241.83.11" Then
        CheckServer = "@USWest"
    ElseIf Bot.Server = "63.241.83.12" Then
        CheckServer = "@USWest"
    ElseIf Bot.Server = "63.241.83.13" Then
        CheckServer = "@USWest"
    ElseIf Bot.Server = "63.241.83.107" Then
        CheckServer = "@USWest"
    ElseIf Bot.Server = "63.241.83.108" Then
        CheckServer = "@USWest"
    ElseIf Bot.Server = "63.241.83.109" Then
        CheckServer = "@USWest"
    ElseIf Bot.Server = "63.241.83.110" Then
        CheckServer = "@USWest"
    ElseIf Bot.Server = "63.241.83.111" Then
        CheckServer = "@USWest"
    ElseIf Bot.Server = "63.241.83.112" Then
        CheckServer = "@USWest"
    Else
        CheckServer = ""
    End If
    'that was a lot of typing :)
    
End Function

Public Sub NullTruncateString(nString As String)
    Dim i&
    i = InStr(nString, Chr$(0))
    If i = 0 Then Exit Sub
    
    nString = Left$(nString, i - 1)
End Sub

Public Function StrToFlags(ByVal Flags As String) As Long
    Dim i&
    StrToFlags = 0
    Flags = UCase$(Flags)
    For i = 1 To Len(Flags)
        Select Case Mid$(Flags, i, 1)
            Case "S": StrToFlags = StrToFlags Or ACCESS_SAFELIST
            Case "Z", "B": StrToFlags = StrToFlags Or ACCESS_SHITLIST
            Case "L": StrToFlags = StrToFlags Or ACCESS_LOCKED
            'Case "Z": StrToFlags = StrToFlags Or ACCESS_TRACKED
            Case "T": StrToFlags = StrToFlags Or ACCESS_TAGBAN
            Case "M": StrToFlags = StrToFlags Or ACCESS_MASTER
        End Select
    Next i
End Function

Public Sub UserDbg(Username As String)
    Dim a&, F&
    If GetUser(Username, a, F) Then
        Debug.Print Username & Space$(1) & a & Space$(1) & FlagsToStr(F)
    Else
        Debug.Print Username & " [not found]"
    End If
End Sub

Public Function FlagsToStr(Flags As Long) As String
    FlagsToStr = ""
    If Flags And ACCESS_SAFELIST Then FlagsToStr = FlagsToStr & "S"
    If Flags And ACCESS_SHITLIST Then FlagsToStr = FlagsToStr & "B"
    If Flags And ACCESS_LOCKED Then FlagsToStr = FlagsToStr & "L"
    'If Flags And ACCESS_TRACKED Then FlagsToStr = FlagsToStr & "T"
    If Flags And ACCESS_TAGBAN Then FlagsToStr = FlagsToStr & "T"
    If Flags And ACCESS_MASTER Then FlagsToStr = FlagsToStr & "M"
End Function


Public Sub LoadDatabase(DBFile As String)
    Set Users = New Collection
On Error GoTo LD_Error
    Dim tS$, tU As DatabaseUser, tF() As String, i&, F%
    LogEvent "Loading user database from file " & DBFile & "."
    cDBFile = DBFile
    F = FreeFile()
    Open App.Path & "\" & DBFile For Input As #F
    While Not EOF(F)
        Set tU = New DatabaseUser
        Line Input #F, tS
        tS = Trim$(tS)
        If LenB(tS) Then
            tF = Split(tS, " ")
            If UBound(tF) = 2 Then
                tU.Username = tF(0)
                tU.Access = CLng(Val(tF(1)))
                tU.Flags = StrToFlags(tF(2))
                Users.Add tU, LCase$(tF(0))
            ElseIf UBound(tF) = 1 Then
                tU.Username = tF(0)
                If IsNumeric(tF(1)) Then
                    tU.Access = CLng(Val(tF(1)))
                Else
                    tU.Flags = StrToFlags(tF(1))
                End If
                Users.Add tU, LCase$(tF(0))
            End If
        End If
        i = i + 1
    Wend
    Close #F
    LogEvent "Loaded " & i & " users into memory."
    Exit Sub
LD_Error:
    LogEvent "Error loading database file: " & Err.Description, etError
End Sub

Public Sub WriteDatabase(Optional ByVal DBFile As String = "")
On Error GoTo WD_Error
    Dim i&, F%
    If LenB(DBFile) = 0 Then DBFile = cDBFile
    'you wanted it here so it'll show up every time
    'DB is written; not just by save button.
    LogEvent "Writing user database to " & DBFile & "."
    F = FreeFile()
    Open App.Path & "\" & DBFile For Output As #F
    For i = 1 To Users.Count()
        If Users(i).Flags > 0 Then
            Print #F, Users(i).Username & " " & Users(i).Access & " " & FlagsToStr(Users(i).Flags)
        Else
            Print #F, Users(i).Username & " " & Users(i).Access
        End If
    Next i
    LogEvent "Wrote " & Users.Count() & " users.", etSuccess
    Close #F
    Exit Sub
WD_Error:
    LogEvent "Error writing user database: " & Err.Description, etError
End Sub

Public Sub ClearMemDatabase()
    Set Users = New Collection
End Sub
Public Sub AddUser(ByVal Username As String, ByVal Access As Long, Optional ByVal Flags As Long = 0)
    Dim tU As DatabaseUser
    Set tU = New DatabaseUser
    With tU
        .Username = Username
        .Access = Access
        .Flags = Flags
    End With
    Users.Add tU, LCase$(Username)
    
    'Username = GetConfig("username")
    'Channel = GetConfig("channel")
    'Product = GetConfig("product")
    'Icon = LCase(Product)
    'AddWebbot ("username, channel, icon")
       
End Sub

Public Function ModifyUser(ByVal Username As String, ByVal Access As Long, Optional ByVal Flags As Long = 0) As Boolean
On Error GoTo MU_Error
    With Users(LCase$(Username))
        .Access = Access
        .Flags = Flags
    End With
    ModifyUser = True
    Exit Function
MU_Error:
    ModifyUser = False
End Function

Public Function RemoveUser(ByVal Username As String) As Boolean
On Error GoTo RU_Error
    RemoveUser = False
    Users.Remove LCase$(Username)
    RemoveUser = True
RU_Error:
End Function

Public Function CompareUsers(ByVal a As String, ByVal B As String, _
    Optional ByVal MastersAlwaysEqual As Boolean = True)
    Dim AccA&, FlgA&, ExA As Boolean, AccB&, FlgB&, ExB As Boolean

    ExA = GetUser(a, AccA, FlgA)
    ExB = GetUser(B, AccB, FlgB)
    
    If ExA And Not ExB Then
        CompareUsers = 1
        Exit Function
    ElseIf Not ExA And ExB Then
        CompareUsers = -1
        Exit Function
    End If
    
    If (FlgA And ACCESS_MASTER) = ACCESS_MASTER And (FlgB And ACCESS_MASTER) <> ACCESS_MASTER Then
        CompareUsers = 1
        Exit Function
    ElseIf (FlgA And ACCESS_MASTER) <> ACCESS_MASTER And (FlgB And ACCESS_MASTER) = ACCESS_MASTER Then
        CompareUsers = -1
        Exit Function
    ElseIf MastersAlwaysEqual And (FlgA And ACCESS_MASTER) = ACCESS_MASTER And (FlgB And ACCESS_MASTER) = ACCESS_MASTER Then
        CompareUsers = 0
        Exit Function
    End If
    
    If AccA > AccB Then
        CompareUsers = 1
        Exit Function
    ElseIf AccA < AccB Then
        CompareUsers = -1
        Exit Function
    End If
End Function


'----------------------------------------------------------
'  Iterator
'----------------------------------------------------------

Public Function MoreUsers() As Boolean
    MoreUsers = False
    If IterI <= Users.Count() Then MoreUsers = True
End Function

Public Sub NextUser(Username As String, Access As Long, Flags As Long)
On Error Resume Next
    With Users(IterI)
        Username = .Username
        Access = .Access
        Flags = .Flags
    End With
    IterI = IterI + 1
End Sub

Public Sub ResetI()
    IterI = 0
End Sub




Public Function GetUsers() As Collection
    Dim i&, userOut As Collection
    Set userOut = New Collection
    For i = 1 To Users.Count()
        userOut.Add Users(i), Users(i).Username
    Next i
    Set GetUsers = userOut
End Function

Public Function UserExists(ByVal Username$) As Boolean
On Error GoTo UE_Error
    Username = LCase$(Username)
    Dim tU As Long
    tU = Users(Username).Flags
    UserExists = True
    Exit Function
UE_Error:
    UserExists = False
End Function

Public Function IsMaster(ByVal Username$) As Boolean
On Error GoTo IM_Error
    If Username = "*N/A*" Then
        IsMaster = True
        Exit Function
    End If
    Username = LCase$(Username)
    'Dim tU As DatabaseUser
    IsMaster = False
    'Set tU = Users(Username)
    If (Users(Username).Flags And ACCESS_MASTER) Then
        IsMaster = True
    End If
    Exit Function
IM_Error:
    Debug.Print Err.Description
    IsMaster = False
End Function

Public Function IsSafelisted(ByVal Username$) As Boolean
On Error GoTo IS_Error
    Username = LCase$(Username)
    Dim tU As DatabaseUser
    IsSafelisted = False
    tU = Users(Username)
    If tU.Flags And ACCESS_SAFELIST Then
        IsSafelisted = True
    End If
    Exit Function
IS_Error:
    IsSafelisted = False
End Function

Public Function IsShitlisted(ByVal Username$) As Boolean
On Error GoTo IS_Error
    Username = LCase$(Username)
    Dim tU As DatabaseUser
    IsShitlisted = False
    tU = Users(Username)
    If tU.Flags And ACCESS_SHITLIST Then
        IsShitlisted = True
    End If
    Exit Function
IS_Error:
    IsShitlisted = False
End Function

Public Function IsLocked(ByVal Username$) As Boolean
On Error GoTo IL_Error
    Username = LCase$(Username)
    Dim tU As DatabaseUser
    IsLocked = False
    tU = Users(Username)
    If tU.Flags And ACCESS_LOCKED Then
        IsLocked = True
    End If
    Exit Function
IL_Error:
    IsLocked = False
End Function

Public Function GetUser(ByVal Username$, Access&, Flags&) As Boolean
On Error GoTo GU_Error
    Username = LCase$(Username)
    Access = 0
    Flags = 0
    GetUser = False
    With Users(Username)
        Access = .Access
        Flags = .Flags
    End With
    GetUser = True
GU_Error:
End Function

Public Function GetAccess(ByVal Username$) As Long
On Error GoTo GA_Error
    If Username = "*N/A*" Then
        GetAccess = 2140000000
        Exit Function
    End If
    Username = LCase$(Username)
    GetAccess = 0
    GetAccess = Users(Username).Access
    Exit Function
GA_Error:
    GetAccess = 0
End Function

'Public Function IsMaster(ByVal Username$) As Boolean
'    If StrComp(Master, Username, vbTextCompare) = 0 Then
'        IsMaster = True
'    Else
'        IsMaster = False
'    End If
'End Function

Public Function GetFlags(ByVal Username$) As Long
On Error GoTo GA_Error
    Username = LCase$(Username)
    GetFlags = 0
    GetFlags = Users(Username).Flags
    Exit Function
GA_Error:
    GetFlags = 0
End Function

'-----------------------------------------------------------------------------------
'  Wildcard Matcher
'-----------------------------------------------------------------------------------
Public Function WildcardMatch(ByVal Pattern As String, ByVal Source As WildcardSource, _
    Matches() As String, Optional ByVal ExInfo As String = "", _
    Optional ByVal CheckSafelist As Boolean = False) As Long
On Error GoTo WM_Error

    Dim i&, j&
    
    WildcardMatch = 0
    
    Pattern = Replace(Pattern, "[", "[[]") '<- must be first
    Pattern = Replace(Pattern, "#", "[#]")
    Pattern = Replace(Pattern, "?", "[?]")
    
    Select Case Source
        Case wsChannel
            If Bot.UsersInChannel = 0 Then Exit Function
            For i = 1 To Bot.ChannelUsers.Count()
                With Bot.ChannelUsers(i)
                    If LCase$(.Username) Like Pattern Then
                        If CheckSafelist Then
                            If Not IsSafelisted(.Username) Then
                                ReDim Preserve Matches(j) As String
                                Matches(j) = .Username
                                j = j + 1
                            End If
                        Else
                            ReDim Preserve Matches(j) As String
                            Matches(j) = .Username
                            j = j + 1
                        End If
                    End If
                End With
            Next i
    End Select
    WildcardMatch = j
WM_Error:
End Function

Public Function UserInChannel(ByVal Username As String) As Boolean
On Error GoTo UIC_Error
    UserInChannel = False
    Dim i&
    Username = LCase$(Username)
    
    If Bot.UsersInChannel = 0 Then Exit Function
    For i = 1 To Bot.ChannelUsers.Count()
        With Bot.ChannelUsers(i)
            If LCase$(.Username) = Username Then
                UserInChannel = True
                Exit Function
            End If
        End With
    Next i
UIC_Error:
End Function

Public Sub WildcardAction(Source&, UserAccess&, UserFlags&, Action$, ByVal Pattern$, Optional ByVal Message As String = "")
    Dim i&, C&, Matches() As String, tA&, tF&
    C = WildcardMatch(LCase$(Pattern), wsChannel, Matches)
    If C = 0 Then Exit Sub
    If LenB(Message) = 0 Then _
        Message = Pattern
    For i = 0 To (C - 1)
        GetUser StripRealm(Matches(i)), tA, tF
        If (Source = 2) Then
            qAdd "/" & Action & Space$(1) & D2Username(Matches(i)) & "@USEast" & Space$(1) & Message
        ElseIf (tA <= UserAccess) And ((tF And ACCESS_MASTER) <> ACCESS_MASTER) And ((tF And ACCESS_SAFELIST) <> ACCESS_SAFELIST) Then
            qAdd "/" & Action & Space$(1) & D2Username(Matches(i)) & Space$(1) & Message
        End If
    Next i
End Sub

'-----------------------------------------------------------------------------------
'  Tagbans
'-----------------------------------------------------------------------------------
Public Function TagbanCheck(ByVal Username$) As Boolean
    Dim i&, Pattern$
    Username = LCase$(Username)
    TagbanCheck = False
    
    For i = 1 To Users.Count()
        With Users(i)
            If (.Flags And ACCESS_TAGBAN) = ACCESS_TAGBAN Then
                Pattern = Replace(.Username, "[", "[[]") '<- must be first
                Pattern = Replace(Pattern, "#", "[#]")
                Pattern = Replace(Pattern, "?", "[?]")
                If Username Like LCase$(Pattern) Then
                    qAdd "/ban " & D2Username(Username) & " TB: " & .Username
                    TagbanCheck = True
                    Exit Function
                End If
            End If
        End With
    Next i
End Function

Public Sub cmdOut(User$, Source&, Text$, Optional ByVal Priority As Long = 2)
    Select Case Source
        Case csNormal: qAdd Text, Priority
        Case csWhispered: qAdd "/w " & FixUsername(User) & Space$(1) & Text, Priority
        Case csWindow: AddC Text, vbYellow
    End Select
End Sub

Public Function GetPing(Username As String, Ping As Long) As Boolean
On Error GoTo GP_Error
    GetPing = False
    Ping = Bot.ChannelUsers(LCase$(Username)).Ping
    GetPing = True
GP_Error:
End Function

'ok so now for the real commands

Public Function ProcessCommand(ByVal Command$, ByVal Username$, Optional ByVal Source As CommandSources = csNormal) As Boolean
On Error GoTo ProcessCommand_Error
    Dim lngWork&, kWork As Boolean, kWork2 As Boolean, _
        dblWork As Double, i&, tA&, tF&, cA&, cF&, vA&, vF&, sTemp$ 'temporary holders
    Dim intAltTrig As Integer, strAltTrig As String
    
    If Username = "*N/A*" And Source <> 2 Then Exit Function
    If Source <> 2 Then
        'First, check to see if this is a real command by
        'looking for the trigger.
        If Left$(Command, Len(Trigger)) <> Trigger Then
            'Trigger not present.
            ProcessCommand = False 'command not processed
            Select Case Command
                Case "?trigger"
                    If GetAccess(Username) >= 20 Then
                        
                        intAltTrig = Asc(Trigger)
                        If Len(intAltTrig) = 1 Then
                            strAltTrig = "00" & intAltTrig
                        Else
                            strAltTrig = "0" & intAltTrig
                        End If
                        cmdOut Username, Source, "My trigger is " & Trigger & " (Alt + " & strAltTrig & ")"
                    End If
            End Select
            Exit Function
        End If
        
        'OK, so it's a command.  Remove the trigger from it.
        Command = Mid$(Command, Len(Trigger) + 1)
        
        'Note that all the Len(Trigger) stuff means that
        'you can have triggers longer than one character.
    Else
        Command = Mid$(Command, 2)
    End If
    
    If LenB(Command) = 0 Then Exit Function
    
    'Divide the command into words for easier processing.
    Dim Words() As String
    Words = Split(Command, " ")

    'Figure out which command we have.
    Select Case Words(0)
        Case "fp", "flood", "floodprotection", "floodmode"
            ProcessCommand = True
            GetUser Username, tA, tF
            If tA >= 100 And UBound(Words) > 0 Then
                Select Case Words(1)
                    Case "0", "off"
                        cmdOut Username, Source, "Flood protection is already off."
                    Case "1", "low"
                        qClear
                        FPEnable
                        Bot.floodLevel = flLimitActions
                        Bot.Say "Flood protection set to LOW.  Limiting commands."
                    Case "2", "medium"
                        qClear
                        FPEnable
                        Bot.floodLevel = flAlternateParser
                        Bot.Say "Flood protection set to MEDIUM.  Using alternate parser."
                    Case "3", "high"
                        qClear
                        FPEnable
                        Bot.floodLevel = flNoSafelist
                        Bot.Say "Flood protection set to HIGH.  Bypassing safelist!"
                    Case "4", "suicidal"
                        If Not IsMaster(Username) Then Exit Function
                        qClear
                        FPEnable
                        Bot.floodLevel = flQueueBypass
                        Bot.Say "SUICIDAL?!  You're off your rocker for sure..."
                End Select
            End If
        Case "ver", "version", "about"
            'Check for access.
            ProcessCommand = True
            If (Source = csWindow) Or (GetAccess(Username) >= 20) Then
                'Do stuff with this command.
                If (UBound(Words) > 0) Then
                    If (LCase$(Words(1)) = "full") Then
                        cmdOut Username, Source, GetVersion() & " Build " & verBuild & " by Cloaked and Scope"
                    Else
                        cmdOut Username, Source, GetVersion() & " by Cloaked and Scope"
                    End If
                Else
                    cmdOut Username, Source, GetVersion() & " by Cloaked and Scope"
                End If
            End If
        Case "say", "s"
            If UBound(Words) = 0 Then Exit Function
            If (Source = csWindow) Or (GetAccess(Username) >= 40) Then
                If Not IsMaster(Username) And Mid$(Command, Len(Words(0)) + 2, 1) = "/" Then _
                    Exit Function
                qAdd Mid$(Command, Len(Words(0)) + 2)
                ProcessCommand = True
            End If
        Case "ban", "kick", "b", "k"
            If UBound(Words) = 0 Then Exit Function
            'ooh quick & dirty hack
            If Words(0) = "b" Then
                Words(0) = "ban"
            ElseIf Words(0) = "k" Then
                Words(0) = "kick"
            End If
            'all better :D
            
            'Check for Battle.Net exploit.
            If Left$(Words(1), 1) = """" Or Right$(Words(1), 1) = """" Or Left$(Words(1), 1) = "," _
            Or Right$(Words(1), 1) = "," Then
                If Not UserInChannel(Words(1)) Then
                    LogEvent Username & " attempted to use a Battle.Net exploit to " & Words(0) & " a user.", _
                        etError
                    Exit Function
                End If
            End If
                
            If InStr(Words(1), "*") Then
                ProcessCommand = True
                GetUser Username, tA, tF
                If (Source = csWindow) Or ((Words(0) = "ban" And tA >= 60) Or (Words(0) = "kick" And tA >= 50)) Then
                    If UBound(Words) > 1 Then
                        WildcardAction Source, tA, tF, Words(0), Words(1), Mid$(Command, Len(Words(0)) + Len(Words(1)) + 3)
                    Else
                        WildcardAction Source, tA, tF, Words(0), Words(1)
                    End If
                End If
            Else
                GetUser Username, cA, cF
                If (Source <> csWindow) And ((Words(0) = "ban" And cA < 60) Or (Words(0) = "kick" And cA < 50)) Then Exit Function
                
                If (Bot.Client = bpWarCraft3 Or bpWarCraft3x) And InStr(Words(1), "@") = 0 Then
                    Words(1) = Words(1) & CheckServer
                End If
                
                'StripRealm() will remove the .ban User@USEast safelist bypass.
                kWork = GetUser(StripRealm(Words(1)), tA, tF)
                
                If kWork And (Source <> 2) And (cA <= tA Or ((((tF And ACCESS_SAFELIST) = ACCESS_SAFELIST) Or ((tF And ACCESS_MASTER) = ACCESS_MASTER)) And ((cF And ACCESS_MASTER) <> ACCESS_MASTER))) Then Exit Function
                If UBound(Words) > 1 Then
                    qAdd "/" & Words(0) & Space$(1) & D2Username(Words(1)) & Space$(1) & Mid$(Command, Len(Words(0)) + Len(Words(1)) + 3)
                Else
                    qAdd "/" & Words(0) & Space$(1) & D2Username(Words(1))
                End If
                ProcessCommand = True
            End If
            'Words is an array of all the words in the command.
            'It starts with 0, so the first word (ban) is Words(0)
            'Words(1) is the user to ban
            'So GetAccess(Username) > GetAccess(Words(1) will make it
            'only work if the person doing .ban's access is higher
            'than the person he's trying to ban
            'I'll just leave this here
            '                   command access check          "I have more access than he does" check
            '                  |------------------------|    |----------------------------------------|
            'If (Source = 2) Or (GetAccess(Username) >= 60 And GetAccess(Username) > GetAccess(Words(1)) And IsSafelisted(Words(1)) = False) Then
            '    qAdd "/ban " & Mid$(Command, 5)
            '    ProcessCommand = True
            'End If
        Case "resign", "rs"
            ProcessCommand = True
            If (Source = csWindow) Or (GetAccess(Username) >= 80) Then
                qAdd "/resign", 1
            End If
        Case "rejoin", "rj"
            ProcessCommand = True
            If (Source = csWindow) Or (GetAccess(Username) >= 80) Then
                Bot.BinaryRejoin
            End If
        Case "designate", "des", "d"
            If UBound(Words) < 1 Then Exit Function
            ProcessCommand = True
            If (Source = csWindow) Or (GetAccess(Username) >= 90) Then
                qAdd "/designate " & D2Username(Words(1)), 1
                cmdOut Username, Source, "I have designated " & Words(1) & "."
                ProcessCommand = True
            End If
        Case "op", "giveops"
            ProcessCommand = True
            If UBound(Words) < 1 Then Exit Function
            If (Source = csWindow) Or (GetAccess(Username) >= 90) Then
                qAdd "/designate " & D2Username(Words(1)), 1
                qAdd "/resign", 1
            End If
        Case "uptime", "utime", "ut"
            ProcessCommand = True
            If (Source = csWindow) Or (GetAccess(Username) >= 90) Then
                cmdOut Username, Source, "System uptime: " & _
                    ConvertTime(GetTickCount()) & _
                    "; Bot Uptime: " & _
                    ConvertTime(GetTickCount() - startupTime), 3
            End If
        Case "whois", "find", "a", "whoami", "mya"
            If Words(0) <> "whois" Then
                ProcessCommand = True
            Else
                ProcessCommand = False
            End If
            If (Source = csWindow) Or (GetAccess(Username) >= 20) Then
                If UBound(Words) = 0 Then
                    lngWork = GetAccess(Username)
                    
                    If lngWork > 20 Then
                        If GetFlags(Username) > 0 Then
                            cmdOut Username, Source, "You have access " & lngWork & " and flags " & FlagsToStr(GetFlags(Username)) & "."
                        Else
                            cmdOut Username, Source, "You have access " & lngWork & " and no flags."
                        End If
                        ProcessCommand = True
                    End If
                Else
                    If UserExists(Words(1)) Then
                        lngWork = GetFlags(Words(1))
                        
                        If lngWork > 0 Then
                            cmdOut Username, Source, Words(1) & ": " & GetAccess(Words(1)) & " " & FlagsToStr(lngWork)
                        Else
                            cmdOut Username, Source, Words(1) & ": " & GetAccess(Words(1))
                        End If
                    Else
                        cmdOut Username, Source, Words(1) & " was not found in the database."

                    End If
                    If Source <> 2 And Words(0) <> "whois" And Words(0) <> "whoami" Then _
                        ProcessCommand = True
                End If
            End If
        Case "flip"
            ProcessCommand = True
            If (Source = csWindow) Or (GetAccess(Username) >= 20) Then
                lngWork = Rand(1, 2)
                If lngWork = 1 Then
                    cmdOut Username, Source, "Heads", 4
                Else
                    cmdOut Username, Source, "Tails", 4
                End If
            End If
        Case "unban", "u"
            If UBound(Words) = 0 Then Exit Function
            ProcessCommand = True
            If (Source = 2) Or (GetAccess(Username) >= 60 And IsShitlisted(Words(1)) = False) Then
                If Bot.Client = bpWarCraft3 Or bpWarCraft3x Then
                    qAdd "/unban " & D2Username(Words(1)) & "@USEast"
                Else
                    qAdd "/unban " & D2Username(Words(1))
                    End If
            End If
        Case "play", "start"
            ProcessCommand = True
            If (Source <> csWindow) And (Not IsMaster(Username)) Then _
                Exit Function
            If WinampVer = 0 Then
                FindWinamp
                If WinampVer = 0 Then
                    cmdOut Username, Source, "Error: Winamp is not running.", 4
                    Exit Function
                End If
            End If
            If UBound(Words) = 0 Then
                PlaySong
                cmdOut Username, Source, "Started play.", 4
            Else
                If IsNumeric(Words(1)) Then
                    SetPlayListPosition CInt(Val(Words(1))) - 1
                    PlaySong
                    cmdOut Username, Source, "Playing song #" & Words(1) & ".", 4
                Else
                    sTemp = PlaySongByName(Mid$(Command, 6))
                    If LenB(sTemp) Then
                        cmdOut Username, Source, "Playing song " & sTemp, 4
                    Else
                        cmdOut Username, Source, "Error: Could not find any songs that match that pattern.", 4
                    End If
                End If
            End If
        Case "vol", "volume", "setvol"
            ProcessCommand = True
            If UBound(Words) = 0 Then
                If Source = csWindow Then _
                    AddC "Usage: /" & Words(0) & " {0-100}", vbYellow, 4
                Exit Function
            End If
            If (Source <> csWindow) And (Not IsMaster(Username)) Then _
                Exit Function
            If WinampVer = 0 Then
                FindWinamp
                If WinampVer = 0 Then
                    cmdOut Username, Source, "Error: Winamp is not running.", 4
                    Exit Function
                End If
            End If
            
            'convert the logical 0-100 scale to
            'SetVolume's 0-255 scale
            If Val(Words(1)) > 100 Then
                SetVolume 255
                cmdOut Username, Source, "Volume set to 100%.", 4
            ElseIf Val(Words(1)) <= 0 Then
                SetVolume 0
                cmdOut Username, Source, "Volume muted.", 4
            Else
                SetVolume CInt(Val(Words(1)) / 100 * 255)
                cmdOut Username, Source, "Volume set to " & Words(1) & "%.", 4
            End If
        Case "stop"
            ProcessCommand = True
            If (Source <> csWindow) And (Not IsMaster(Username)) Then _
                Exit Function
            If WinampVer = 0 Then
                FindWinamp
                If WinampVer = 0 Then
                    cmdOut Username, Source, "Error: Winamp is not running.", 4
                    Exit Function
                End If
            End If
            StopSong
            cmdOut Username, Source, "Stopped play in Winamp.", 4
        Case "next", "skip"
            ProcessCommand = True
            If (Source <> csWindow) And (Not IsMaster(Username)) Then _
                Exit Function
            If WinampVer = 0 Then
                FindWinamp
                If WinampVer = 0 Then
                    cmdOut Username, Source, "Error: Winamp is not running."
                    Exit Function
                End If
            End If
            NextTrack
            cmdOut Username, Source, "Skipped to the next track."
        Case "back", "prev", "last"
            ProcessCommand = True
            If (Source <> csWindow) And (Not IsMaster(Username)) Then _
                Exit Function
            If WinampVer = 0 Then
                FindWinamp
                If WinampVer = 0 Then
                    cmdOut Username, Source, "Error: Winamp is not running."
                    Exit Function
                End If
            End If
            PreviousTrack
            cmdOut Username, Source, "Skipped to the previous track."
        Case "mp3"
            ProcessCommand = True
            
            If UBound(Words) = 0 And GetAccess(Username) > 20 Then
                If WinampVer = 0 Then
                    FindWinamp
                    If WinampVer = 0 Then
                        cmdOut Username, Source, "Error: Winamp is not running."
                        Exit Function
                    End If
                End If
                cmdOut Username, Source, "Now Playing: " & GetSong()
            ElseIf Words(1) = "load" And (Source = csWindow Or IsMaster(Username)) Then
                If WinampVer = 0 Then
                    LoadWinamp
                    cmdOut Username, Source, "Winamp loaded."
                Else
                    cmdOut Username, Source, "Winamp is already running."
                End If
            End If
        Case "loadwinamp"
            If IsMaster(Username) Then
                If WinampVer = 0 Then
                    LoadWinamp
                    cmdOut Username, Source, "Winamp loaded."
                Else
                    cmdOut Username, Source, "Winamp is already running."
                End If
            End If
        Case "winampfound"
            If IsMaster(Username) Then
                If WinampVer = 0 Then
                    cmdOut Username, Source, "Winamp is not loaded or not located."
                Else
                    cmdOut Username, Source, "Winamp is running and found. (v" & _
                        WinampVer & ")"
                End If
            End If
        Case "findwinamp"
            ProcessCommand = True
            If (Source <> csWindow) And (Not IsMaster(Username)) Then _
                Exit Function
            FindWinamp
            If WinampVer = 0 Then
                cmdOut Username, Source, "Error: Winamp is not running."
            Else
                cmdOut Username, Source, "Found Winamp running."
            End If
        Case "os"
            ProcessCommand = True
            If (Source = csWindow) Or (GetAccess(Username) >= 20) Then
                cmdOut Username, Source, GetOSVersionString()
            End If
        Case "dns"
            ProcessCommand = True
            If UBound(Words) > 0 And ((Source = csWindow) Or (GetAccess(Username) >= 20)) Then
                cmdOut Username, Source, Words(1) & ": " & DNSLookup(Words(1))
            End If
        Case "ipbans"
            ProcessCommand = True
            If UBound(Words) > 0 And ((Source = csWindow) Or (GetAccess(Username) >= 80)) Then
                Select Case LCase$(Words(1))
                    Case "on"
                        If Not useIPBans Then
                            useIPBans = True
                            SweepChannel False, False, False, False, True
                            cmdOut Username, Source, "IP-bans were enabled."
                            WriteConfig "IPBans", "Yes", "Moderation"
                        Else
                            cmdOut Username, Source, "IP-bans are already enabled."
                        End If
                    Case "off"
                        If useIPBans Then
                            useIPBans = False
                            cmdOut Username, Source, "IP-bans were disabled."
                            WriteConfig "IPBans", "No", "Moderation"
                        Else
                            cmdOut Username, Source, "IP-bans are already disabled."
                        End If
                    Case Else
                        cmdOut Username, Source, "Usage: " & Trigger & "ipbans [on|off]"
                End Select
            ElseIf GetAccess(Username) >= 20 Then
                If useIPBans Then
                    cmdOut Username, Source, "IP-bans are currently enabled."
                Else
                    cmdOut Username, Source, "IP-bans are currently disabled."
                End If
            End If
        Case "plugbans", "pb"
            ProcessCommand = True
            If GetAccess(Username) >= 80 And UBound(Words) > 0 Then
                Select Case LCase$(Words(1))
                    Case "on"
                        If Not usePlugBans Then
                            usePlugBans = True
                            EnablePlugBans
                            cmdOut Username, Source, "Plugbans were enabled."
                            WriteConfig "PlugBans", "Yes", "Moderation"
                        Else
                            cmdOut Username, Source, "Plugbans are already enabled."
                        End If
                    Case "off"
                        If usePlugBans Then
                            usePlugBans = False
                            cmdOut Username, Source, "Plugbans were disabled."
                            WriteConfig "PlugBans", "No", "Moderation"
                        Else
                            cmdOut Username, Source, "Plugbans are already disabled."
                        End If
                    Case Else
                        cmdOut Username, Source, "Usage: " & Trigger & "plugbans [on|off]"
                End Select
            ElseIf GetAccess(Username) >= 20 Then
                If usePlugBans Then
                    cmdOut Username, Source, "Plugbans are currently enabled."
                Else
                    cmdOut Username, Source, "Plugbans are currently disabled."
                End If
            End If
        Case "phrasebans", "phb"
            ProcessCommand = True
            If GetAccess(Username) >= 80 And UBound(Words) > 0 Then
                Select Case LCase$(Words(1))
                    Case "on"
                        If Not usePhrasebans Then
                            usePhrasebans = True
                            cmdOut Username, Source, "Phrasebans are now enabled."
                            WriteConfig "Phrasebans", "Yes", "Moderation"
                        Else
                            cmdOut Username, Source, "Phrasebans are already enabled."
                        End If
                    Case "off"
                        If usePhrasebans Then
                            usePhrasebans = False
                            cmdOut Username, Source, "Phrasebans are now disabled."
                            WriteConfig "Phrasebans", "No", "Moderation"
                        Else
                            cmdOut Username, Source, "Phrasebans are already disabled."
                        End If
                    Case Else
                        cmdOut Username, Source, "Usage: " & Trigger & "phrasebans [on|off]"
                End Select
            ElseIf GetAccess(Username) >= 20 Then
                If usePhrasebans Then
                    cmdOut Username, Source, "Phrasebans are currently enabled."
                Else
                    cmdOut Username, Source, "Phrasebans are currently disabled."
                End If
            End If
        Case "clientbans", "cb"
            ProcessCommand = True
            If UBound(Words) > 0 Then
                If GetAccess(Username) >= 80 Then
                    Select Case LCase$(Words(1))
                        Case "on"
                            If Not useClientBans Then
                                useClientBans = True
                                EnableClientBans
                                cmdOut Username, Source, "Clientbans were enabled."
                                WriteConfig "ClientBans", "Yes", "Moderation"
                            Else
                                cmdOut Username, Source, "Clientbans are already enabled."
                            End If
                        Case "off"
                            If useClientBans Then
                                useClientBans = False
                                cmdOut Username, Source, "Clientbans were disabled."
                                WriteConfig "ClientBans", "No", "Moderation"
                            Else
                                cmdOut Username, Source, "Clientbans are already disabled."
                            End If
                        Case Else
                            If IsClientbannable(UCase$(Words(1))) Then
                                If UBound(Words) > 1 Then
                                    Select Case LCase$(Words(2))
                                        Case "on"
                                            SetClientBan Words(1), True
                                            If useClientBans Then
                                                cmdOut Username, Source, ClientKeyToName(ClientStrToKey(Words(1))) & " clients will now be banned."
                                                SweepChannel False, False, False, True, False
                                            Else
                                                cmdOut Username, Source, ClientKeyToName(ClientStrToKey(Words(1))) & " clients will be banned once client-bans are enabled."
                                            End If
                                        Case "off"
                                            SetClientBan Words(1), False
                                            cmdOut Username, Source, ClientKeyToName(ClientStrToKey(Words(1))) & " clients will not be automatically banned."
                                        Case Else
                                            cmdOut Username, Source, "Usage: " & Trigger & "clientbans {on|off|*client* [on|off]}"
                                    End Select
                                Else
                                    If IsClientbannable(UCase$(Words(1))) Then
                                        If IsClientbanned(Words(1)) Then
                                            cmdOut Username, Source, ClientKeyToName(ClientStrToKey(Words(1))) & " clients are client-banned."
                                        Else
                                            cmdOut Username, Source, ClientKeyToName(ClientStrToKey(Words(1))) & " clients are not client-banned."
                                        End If
                                    Else
                                        cmdOut Username, Source, "Usage: " & Trigger & "clientbans {on|off|*client* [on|off]}"
                                    End If
                                End If
                            Else
                                cmdOut Username, Source, "Usage: " & Trigger & "clientbans {on|off|*client* [on|off]}"
                            End If
                    End Select
                ElseIf GetAccess(Username) >= 20 Then
                    If IsClientbannable(Words(1)) Then
                        If IsClientbanned(Words(1)) Then
                            cmdOut Username, Source, ClientKeyToName(ClientStrToKey(Words(1))) & " clients are client-banned."
                        Else
                            cmdOut Username, Source, ClientKeyToName(ClientStrToKey(Words(1))) & " clients are not client-banned."
                        End If
                    End If
                End If
            ElseIf GetAccess(Username) >= 20 Then
                If useClientBans Then
                    cmdOut Username, Source, "Client-bans are enabled."
                Else
                    cmdOut Username, Source, "Client-bans are disabled."
                End If
            End If
            'holy shit, heh
        Case "idlebans", "ib"
            ProcessCommand = True
            If GetAccess(Username) >= 80 And UBound(Words) > 0 Then
                For i = 1 To UBound(Words)
                    Select Case Words(i)
                        Case "on"
                            If Not useIdleBans Then
                                kWork = True
                            Else
                                kWork = False
                            End If
                            useIdleBans = True
                        Case "off"
                            If useIdleBans Then
                                kWork = True
                            Else
                                kWork = False
                            End If
                            useIdleBans = False
                        Case "min", "minutes", "minute"
                            kWork2 = True
                        Case "sec", "seconds", "second"
                            kWork2 = False
                        Case Else
                            If IsNumeric(Words(i)) Then
                                If Val(Words(i)) > 0 Then
                                    dblWork = Val(Words(i))
                                Else
                                    If useIdleBans Then
                                        kWork = True
                                    Else
                                        kWork = False
                                    End If
                                    useIdleBans = False
                                End If
                            End If
                    End Select
                Next i
                
                If dblWork > 0 Then
                    WriteConfig "IdleBanDelay", dblWork, "Moderation"
                    If kWork2 Then
                        WriteConfig "IdleBanUnit", "minutes", "Moderation"
                        idleBanDelay = CLng(dblWork * 60000)
                        If useIdleBans Then
                            If kWork Then
                                cmdOut Username, Source, "Idle bans enabled and delay set to " & dblWork & " minutes."
                                StartIdleBans
                                WriteConfig "IdleBans", "On", "Moderation"
                            Else
                                cmdOut Username, Source, "Idle ban delay set to " & dblWork & " minutes."
                            End If
                        Else
                            cmdOut Username, Source, "Idle ban delay set to " & dblWork & " minutes (though idle bans are still off)."
                            WriteConfig "IdleBans", "Off", "Moderation"
                        End If
                    Else
                        WriteConfig "IdleBanUnit", "seconds", "Moderation"
                        idleBanDelay = CLng(dblWork * 1000)
                        If useIdleBans Then
                            If kWork Then
                                cmdOut Username, Source, "Idle bans enabled and delay set to " & dblWork & " seconds."
                                StartIdleBans
                                WriteConfig "IdleBans", "On", "Moderation"
                            Else
                                cmdOut Username, Source, "Idle ban delay set to " & dblWork & " seconds."
                            End If
                        Else
                            cmdOut Username, Source, "Idle ban delay set to " & dblWork & " seconds (though idle bans are still off)."
                            WriteConfig "IdleBans", "Off", "Moderation"
                        End If
                    End If
                Else
                    If useIdleBans Then
                        If kWork Then
                            cmdOut Username, Source, "Idle bans are now enabled."
                            StartIdleBans
                            WriteConfig "IdleBans", "On", "Moderation"
                        Else
                            cmdOut Username, Source, "Idle bans were already enabled."
                        End If
                    Else
                        If kWork Then
                            StopIdleBans
                            cmdOut Username, Source, "Idle bans are now disabled."
                            WriteConfig "IdleBans", "Off", "Moderation"
                        Else
                            cmdOut Username, Source, "Idle bans were already disabled."
                        End If
                    End If
                End If
            ElseIf GetAccess(Username) >= 20 Then
                If useIdleBans Then
                    cmdOut Username, Source, "Idle bans are currently enabled."
                Else
                    cmdOut Username, Source, "Idle bans are currently disabled."
                End If
            End If
        Case "lockdown", "ld"
            ProcessCommand = True
            If GetAccess(Username) >= 80 And UBound(Words) > 0 Then
                Select Case LCase$(Words(1))
                    'doing .lockdown on preserve will not cause
                    'non-safelisted users currently in the channel
                    'to be banned
                    
                    Case "on"
                        If Not useLockdown Then
                            cmdOut Username, Source, "Lockdown enabled."
                            If UBound(Words) > 1 Then
                                If LCase$(Words(2)) <> "preserve" Then
                                    EnableLockdown
                                Else
                                    useLockdown = True
                                End If
                            Else
                                EnableLockdown
                            End If
                            WriteConfig "Lockdown", "On", "Moderation"
                        Else
                            cmdOut Username, Source, "Lockdown is already enabled."
                        End If
                    Case "off"
                        If useLockdown Then
                            useLockdown = False
                            cmdOut Username, Source, "Lockdown disabled."
                            WriteConfig "Lockdown", "Off", "Moderation"
                        Else
                            cmdOut Username, Source, "Lockdown is already disabled."
                        End If
                    Case "msg", "message", "m"
                        If UBound(Words) = 1 Then
                            cmdOut Username, Source, "Current message: " & lockdownMessage
                        Else
                            lockdownMessage = Mid$(Command, Len(Words(0)) + Len(Words(1)) + 3)
                            WriteConfig "LockdownMessage", lockdownMessage, "Moderation"
                            cmdOut Username, Source, "Lockdown message changed."
                        End If
                    Case Else
                        cmdOut Username, Source, "Usage: " & Trigger & "lockdown [on [preserve]|off|message]"
                End Select
            ElseIf GetAccess(Username) >= 20 Then
                If useLockdown Then
                    If Bot.HasOps Then
                        cmdOut Username, Source, "Channel is currently locked down."
                    Else
                        cmdOut Username, Source, "Channel lockdown is enabled, but I do not have ops."
                    End If
                Else
                    cmdOut Username, Source, "Channel lockdown is disabled."
                End If
            End If
        Case "idle"
            ProcessCommand = True
            If GetAccess(Username) >= 60 Then
                If UBound(Words) = 0 And Not IsQueueBusy() Then
                    cmdOut Username, Source, GenerateIdleMessage()
                Else
                    Select Case Words(1)
                        Case "on"
                            StartIdling
                            cmdOut Username, Source, "Turned on anti-idle."
                        Case "off"
                            StopIdling
                            cmdOut Username, Source, "Turned off anti-idle."
                        Case "uptime"
                            idleType = idleUptime
                            WriteConfig "Mode", "Uptime", "Idle"
                            cmdOut Username, Source, "Idle messages will now show the bot and system uptime."
                        Case "custom"
                            WriteConfig "Mode", "Custom", "Idle"
                            If UBound(Words) > 1 Then
                                idleMsg = Mid$(Command, Len(Trigger) + 12)
                                idleType = idleMessage
                                WriteConfig "Message", idleMsg, "Idle"
                                cmdOut Username, Source, "Switched to the specified custom idle message."
                            Else
                                idleType = idleMessage
                                cmdOut Username, Source, "Switched to the custom idle message."
                            End If
                        Case "version"
                            idleType = idleBot
                            WriteConfig "Mode", "Version", "Idle"
                            cmdOut Username, Source, "Switched to the bot version idle message."
                        Case "mp3"
                            idleType = idleMp3
                            WriteConfig "Mode", "MP3", "Idle"
                            cmdOut Username, Source, "Idle messages will now show the current Winamp song."
                        Case "quote", "quotes"
                            idleType = idleQuotes
                            WriteConfig "Mode", "Quotes", "Idle"
                            cmdOut Username, Source, "Idle messages will now show a random quote."
                        Case Else
                            If IsNumeric(Words(1)) Then
                                If UBound(Words) = 1 Then
                                    idleDelay = 60000 * CLng(Val(Words(1)))
                                    cmdOut Username, Source, "Idle delay is now " & Words(1) & " minute(s)."
                                Else
                                    Select Case Words(2)
                                        Case "min", "mins", "minutes", "minute"
                                            idleDelay = 60000 * CLng(Val(Words(1)))
                                            cmdOut Username, Source, "Idle delay is now " & Words(1) & " minute(s)."
                                        Case "sec", "secs", "seconds", "second"
                                            idleDelay = 1000 * CLng(Val(Words(1)))
                                            cmdOut Username, Source, "Idle delay is now " & Words(1) & " second(s)."
                                        Case Else
                                            cmdOut Username, Source, "Unknown time unit """ & Words(2) & """."
                                    End Select
                                End If
                            Else
                                cmdOut Username, Source, "Unknown idle command """ & Words(1) & """."
                            End If
                    End Select
                End If
                ProcessCommand = True
            End If
        Case "greet", "greetings"
            ProcessCommand = True
            If GetAccess(Username) >= 60 And UBound(Words) > 0 Then
                Select Case LCase$(Words(1))
                    Case "on"
                        If Not useGreets Then
                            useGreets = True
                            WriteConfig "Enabled", "Yes", "Greetings"
                            cmdOut Username, Source, "Greet messages were turned on."
                        Else
                            cmdOut Username, Source, "Greet messages are already on."
                        End If
                    Case "off"
                        If useGreets Then
                            useGreets = False
                            WriteConfig "Enabled", "No", "Greetings"
                            cmdOut Username, Source, "Greet messages were turned off."
                        Else
                            cmdOut Username, Source, "Greet messages are already off."
                        End If
                    Case "whisperon"
                        whisperGreets = True
                        WriteConfig "Whisper", "Yes", "Greetings"
                        cmdOut Username, Source, "Greet messages will be whispered."
                    Case "whisperoff"
                        whisperGreets = False
                        WriteConfig "Whisper", "No", "Greetings"
                        cmdOut Username, Source, "Greet messages will not be whispered."
                    Case "whisper"
                        If UBound(Words) > 1 Then
                        Select Case LCase$(Words(2))
                            Case "on"
                                whisperGreets = True
                                WriteConfig "Whisper", "Yes", "Greetings"
                                cmdOut Username, Source, "Greet messages will be whispered."
                            Case "off"
                                whisperGreets = False
                                WriteConfig "Whisper", "No", "Greetings"
                                cmdOut Username, Source, "Greet messages will not be whispered."
                            Case Else
                                cmdOut Username, Source, "Usage: " & Trigger & Words(0) & " whisper {on|off}"
                        End Select
                        End If
                    Case "msg", "message"
                        If UBound(Words) = 1 Then
                            cmdOut Username, Source, "Current message: " & greetMessage
                        Else
                            greetMessage = Mid$(Command, Len(Words(0)) + Len(Words(1)) + 3)
                            WriteConfig "Message", greetMessage, "Greetings"
                            cmdOut Username, Source, "Greet message changed."
                        End If
                    Case Else
                        cmdOut Username, Source, "Usage: " & Trigger & Words(0) & " [on|off|message [message]|whisperon|whisperoff|whisper {on|off}]"
                End Select
            Else
                If useGreets Then
                    If whisperGreets Then
                        cmdOut Username, Source, "Greet messages are enabled and will be whispered."
                    Else
                        cmdOut Username, Source, "Greet messages are enabled."
                    End If
                Else
                    cmdOut Username, Source, "Greet messages are disabled."
                End If
            End If
        Case "cq", "clearqueue"
            ProcessCommand = True
            If GetAccess(Username) >= 70 Then
                qClear
                cmdOut Username, Source, "Queue cleared."
            End If
        Case "quit", "exit", "kill"
            If Source = csWindow Then
                LogEvent "/" & Words(0) & " typed in main window."
                Shutdown
            Else
                If IsMaster(Username) Then
                    LogEvent Username & " used ." & Words(0) & "."
                    Shutdown
                Else
                    LogEvent Username & " used ." & Words(0) & ", but is not a master."
                End If
            End If
        Case "sweepban", "sb"
            ProcessCommand = True
            If GetAccess(Username) >= 90 Then
                'AddC "OK"
                Bot.TriggeredEvent = "sweepban"
                Bot.EventTime = GetTickCount() + 95
                Bot.TriggerHappy = True
                Bot.Say "/who " & Mid$(Command, 10)
                If TriggerFinger > 0 Then _
                    KillTimer 0, TriggerFinger
                TriggerFinger = SetTimer(0, 0, 95, AddressOf PullTrigger)
            End If
        Case "ip", "ipban"
            If UBound(Words) = 0 Then Exit Function
            If GetAccess(Username) >= 50 Then
                If useIPBans Then
                    If (Source = 2) Or (GetAccess(Username) > GetAccess(Words(1)) And IsSafelisted(Words(1)) = False) Then
                        qAdd "/squelch " & D2Username(Words(1))
                        ProcessCommand = True
                        qAdd D2Username(Words(1)) & " has been IP-Banned."
                    Else
                        cmdOut Username, Source, "You do not have access to do that."
                    End If
                Else
                    cmdOut Username, Source, "IP-bans are currently disabled."
                End If
            End If
        Case "unip", "unipban"
            If UBound(Words) = 0 Then Exit Function
            If GetAccess(Username) >= 50 Then
                If useIPBans Then
                    If (Source = 2) Or (GetAccess(Username) > GetAccess(Words(1)) And IsSafelisted(Words(1)) = False) Then
                        qAdd "/unsquelch " & D2Username(Words(1))
                        qAdd "/unban " & D2Username(Words(1))
                        ProcessCommand = True
                        qAdd D2Username(Words(1)) & " has been Un-IPBanned"
                    Else
                        cmdOut Username, Source, "You do not have access to do that."
                    End If
                Else
                    cmdOut Username, Source, "IP-bans are currently disabled."
                End If
            End If
        Case "server"
            ProcessCommand = True
            If (Source = 2) Or GetAccess(Username) >= 40 Then
                cmdOut Username, Source, "is on " & GetConfig("Server")
            End If
        Case "settrigger", "st"
            ProcessCommand = True
            If UBound(Words) < 1 Then Exit Function
            If (Source = 2) Or IsMaster(Username) Then
                Trigger = Words(1)
                WriteConfig "Trigger", Words(1)
                cmdOut Username, Source, "Trigger set to: " & Trigger
            End If
        Case "ping", "myping", "pingme"
            ProcessCommand = True
            If (Source = 2) Or GetAccess(Username) > 20 Then
                If UBound(Words) < 1 Then
                    If Source = 2 Then
                        AddC "Your ping is 0ms, since you typed this in the bot window!", vbYellow
                        Exit Function
                    End If
                    
                    If (GetPing(Username, tA)) Then
                        cmdOut Username, Source, Username & ", your ping is " & tA & "ms."
                    Else
                        cmdOut Username, Source, "I don't see you in the channel."
                    End If
                Else
                    If (GetPing(Words(1), tA)) Then
                        cmdOut Username, Source, "Battle.Net pinged " & Words(1) & " at " & tA & "ms."
                    Else
                        cmdOut Username, Source, "I don't see " & Words(1) & " in the channel."
                    End If
                End If
            End If
        Case "sp", "selfping"
            ProcessCommand = True
            If (Source = 2) Or GetAccess(Username) > 20 Then
                If (GetPing(Bot.RealUsername, tA)) Then
                    cmdOut Username, Source, "My ping is " & tA & "ms."
                Else
                    cmdOut Username, Source, "Funny, I don't see myself in the channel..."
                End If
            End If
        Case "add", "set"
            ProcessCommand = True
            If Source = 2 Then
                If UBound(Words) > 1 Then
                    sTemp = Words(1)
                    If Words(0) = "set" Then
                        GetUser sTemp, tA, tF
                    End If
                    
                    For i = 2 To UBound(Words)
                        If IsNumeric(Words(i)) Then
                            tA = Words(i)
                        Else
                            Select Case Left$(Words(i), 1)
                                Case "+"
                                    tF = tF Or StrToFlags(Words(i))
                                Case "-"
                                    tF = tF Xor StrToFlags(Words(i))
                                Case Else
                                    tF = StrToFlags(Words(i))
                            End Select
                        End If
                    Next i
                    
                    If (Bot.Client = bpWarCraft3 Or Bot.Client = bpWarCraft3x) And InStr(Words(1), "@") = 0 Then
                        sTemp = sTemp & CheckServer
                    Else
                        sTemp = sTemp
                    End If
                    
                    If Not UserExists(sTemp) Then
                        AddUser sTemp, tA, tF
                        AddC "User " & sTemp & " was added.", vbGreen
                        WriteDatabase
                    Else
                        If ModifyUser(sTemp, tA, tF) Then
                            AddC "User " & sTemp & " was modified.", vbGreen
                            WriteDatabase
                        Else
                            AddC "Could not modify user " & sTemp & ".", vbRed
                        End If
                    End If
                Else
                    AddC "Error: Malformed command.", vbRed
                End If
            Else
                If UBound(Words) > 1 Then
                    If (Bot.Client = bpWarCraft3 Or Bot.Client = bpWarCraft3x) And InStr(Words(1), "@") = 0 Then
                        sTemp = Words(1) & CheckServer
                    Else
                        sTemp = Words(1)
                        End If
                    If Words(0) = "set" Then
                        tA = GetAccess(sTemp)
                        tF = GetFlags(sTemp)
                    End If
                    
                    For i = 2 To UBound(Words)
                        If IsNumeric(Words(i)) Then
                            tA = Words(i)
                        Else
                            Select Case Left$(Words(i), 1)
                                Case "+"
                                    tF = tF Or StrToFlags(Words(i))
                                Case "-"
                                    tF = tF Xor StrToFlags(Words(i))
                                Case Else
                                    tF = StrToFlags(Words(i))
                            End Select
                        End If
                    Next i
                    
                    If Not GetUser(Username, cA, cF) Then Exit Function
                    
                    If cA <= tA Then
                        cmdOut Username, Source, "You do not have enough access to do that."
                        Exit Function
                    End If
                    
                    If (tF And ACCESS_TAGBAN) = ACCESS_TAGBAN Then
                        cmdOut Username, Source, "Use " & Trigger & "tagadd to add tagbans."
                        Exit Function
                    End If
                    
                    If ((cF And ACCESS_MASTER) <> ACCESS_MASTER) And (cA < 70) And (((tF And ACCESS_SAFELIST) = ACCESS_SAFELIST) Or ((tF And ACCESS_SHITLIST) = ACCESS_SHITLIST)) Then
                        cmdOut Username, Source, "You do not have enough access to safe/shitlist a user."
                        Exit Function
                    End If
                    
                    If ((tF And ACCESS_MASTER) = ACCESS_MASTER) And ((cF And ACCESS_MASTER) <> ACCESS_MASTER) Then
                        cmdOut Username, Source, "You must be a master to create other masters."
                        Exit Function
                    End If
                    
                    If ((cF And ACCESS_MASTER) <> ACCESS_MASTER) And (cA < 100) And ((tF And ACCESS_LOCKED) = ACCESS_LOCKED) Then
                        cmdOut Username, Source, "You must be a master or have at least 100 access to lock a user."
                        Exit Function
                    End If
                    
                    If Not GetUser(sTemp, vA, vF) Then
                        AddUser sTemp, tA, tF
                        cmdOut Username, Source, "User " & sTemp & " was added."
                        WriteDatabase
                    Else
                        If cA <= vA Then
                            cmdOut Username, Source, "You do not have enough access to modify user " & sTemp & "."
                            Exit Function
                        End If
                        
                        If ((cF And ACCESS_MASTER) <> ACCESS_MASTER) And ((vF And ACCESS_MASTER) = ACCESS_MASTER) Then
                            cmdOut Username, Source, "You must be a master to modify another master."
                            Exit Function
                        End If
                        
                        If ((cF And ACCESS_MASTER) <> ACCESS_MASTER) And (cA < 100) And ((vF And ACCESS_LOCKED) = ACCESS_LOCKED) Then
                            cmdOut Username, Source, "You must be a master or have at least 100 access to modify a locked user."
                            Exit Function
                        End If
                    
                        If ModifyUser(sTemp, tA, tF) Then
                            cmdOut Username, Source, "User " & sTemp & " was modified."
                            WriteDatabase
                        Else
                            cmdOut Username, Source, "User " & sTemp & " was not modified due to an error."
                        End If
                    End If
                End If
            End If
        Case "rem", "remove"
            ProcessCommand = True
            If Source = 2 Then
                If UBound(Words) > 0 Then
                    If RemoveUser(Words(1)) Then
                        AddC "User " & Words(1) & " was removed from the database.", vbGreen
                    Else
                        AddC "User " & Words(1) & " was not found in the database.", vbRed
                    End If
                Else
                    AddC "Usage: /" & Words(0) & " user"
                End If
            Else
                If UBound(Words) > 0 Then
                    If Not GetUser(Username, cA, cF) Then Exit Function
                    If cA <= 0 Then Exit Function
                    If Not GetUser(Words(1), tA, tF) Then
                        cmdOut Username, Source, "User " & Words(1) & " was not found."
                        Exit Function
                    End If
                    
                    If cA <= tA Then
                        cmdOut Username, Source, "You do not have enough access to remove user " & Words(1) & "."
                        Exit Function
                    End If
                    
                    If (tF And ACCESS_TAGBAN) = ACCESS_TAGBAN Then
                        cmdOut Username, Source, "Use " & Trigger & "tagdel to remove tagbans."
                        Exit Function
                    End If
                    
                    If ((cF And ACCESS_MASTER) <> ACCESS_MASTER) Then
                        If (cA < 100) And ((tF And ACCESS_LOCKED) = ACCESS_LOCKED) Then
                            cmdOut Username, Source, "You must be a master or have at least 100 access to lock a user."
                            Exit Function
                        ElseIf (tF And ACCESS_MASTER) = ACCESS_MASTER Then
                            cmdOut Username, Source, "You must be a master to remove a master."
                            Exit Function
                        End If
                    End If
                    
                    If RemoveUser(Words(1)) Then
                        cmdOut Username, Source, "User " & Words(1) & " was removed."
                        WriteDatabase
                    Else
                        cmdOut Username, Source, "User " & Words(1) & " could not be removed due to an error."
                    End If
                Else
                    cmdOut Username, Source, "Usage: " & Trigger & Words(0) & " user"
                End If
            End If
        Case "tagadd", "tagban", "ta"
            ProcessCommand = True
            If (Source = 2) Or (GetAccess(Username) >= 75) Then
                If UBound(Words) > 0 Then
                    If GetUser(Words(1), cA, cF) Then
                        If (cF And ACCESS_TAGBAN) <> ACCESS_TAGBAN Then
                            cmdOut Username, Source, "You cannot add a tagban that is the same as a user."
                            Exit Function
                        Else
                            cmdOut Username, Source, Words(1) & " is already tagbanned."
                        End If
                    Else
                        AddUser Words(1), 0, ACCESS_TAGBAN
                        cmdOut Username, Source, Words(1) & " is now tagbanned."
                        WriteDatabase
                    End If
                Else
                    If Source = 2 Then
                        AddC "Usage: /" & Words(0) & " tag", vbYellow
                    Else
                        cmdOut Username, Source, "Usage: " & Trigger & Words(0) & " tag"
                    End If
                End If
            End If
        Case "tagdel", "untagban", "tagunban", "td"
            ProcessCommand = True
            If (Source = 2) Or (GetAccess(Username) >= 75) Then
                If UBound(Words) > 0 Then
                    If GetUser(Words(1), cA, cF) Then
                        If (cF And ACCESS_TAGBAN) <> ACCESS_TAGBAN Then
                            cmdOut Username, Source, Words(1) & " is not tagbanned."
                            Exit Function
                        ElseIf RemoveUser(Words(1)) Then
                            cmdOut Username, Source, Words(1) & " is no longer tagbanned."
                            WriteDatabase
                        Else
                            cmdOut Username, Source, Words(1) & " could not be removed due to an error."
                        End If
                    Else
                        cmdOut Username, Source, Words(1) & " is not tagbanned."
                    End If
                Else
                    If Source = 2 Then
                        AddC "Usage: /" & Words(0) & " tag", vbYellow
                    Else
                        cmdOut Username, Source, "Usage: " & Trigger & Words(0) & " tag"
                    End If
                End If
            End If
        Case "join", "home", "joinhome"
            ProcessCommand = True
            If (Source = 2) Or (GetAccess(Username) >= 80) Then
                If UBound(Words) > 0 Then
                    qAdd "/join " & Mid$(Command, 6)
                Else
                    qAdd "/join " & Bot.Home
                End If
            End If
        Case "scq", "silentclearqueue"
            ProcessCommand = True
            If GetAccess(Username) >= 70 Then
                qClear
            End If
        Case "save"
            ProcessCommand = True
            If (Source = 2) Or (GetAccess(Username) >= 40) Then
                If UBound(Words) > 0 Then
                    qAdd "Saved Configuration Lists"
                End If
            End If
        Case "profile"
            ProcessCommand = True
            If (Source = 2) Or (GetAccess(Username) >= 40) Then
                If UBound(Words) > 0 Then
                    RequestProfile Words(1)
                End If
            End If
        Case "reconnect", "rc"
            ProcessCommand = True
            If (Source = csWindow) Or (IsMaster(Username)) Then
                LogEvent "Reconnecting."
                DisconnectBot
                ConnectBot
            End If
        Case "setvar", "getvar", "var"
            ProcessCommand = True
            If (Source = csWindow) Or (IsMaster(Username)) Then
                If UBound(Words) = 0 Then
                    cmdOut Username, Source, "Usage: " & Trigger & " {field} [value]"
                    Exit Function
                End If
                
                If UBound(Words) = 1 Then
                    Select Case Words(1)
                        Case "username", "un"
                            cmdOut Username, Source, "Username: " & Bot.Username & " (duh)"
                        Case "password", "pw"
                           If (Source = csWindow) Then
                                AddC "Password: " & Bot.Password
                            Else
                                cmdOut Username, Source, "Error: Permission denied."
                            End If
                        Case "server"
                            cmdOut Username, Source, "Server: " & Bot.Server
                        Case "hashed"
                            If Bot.UseBNLS Then
                                cmdOut Username, Source, "Hashed: No"
                            Else
                                cmdOut Username, Source, "Hashed: Yes"
                            End If
                        Case "home", "homechannel"
                            cmdOut Username, Source, "Home Channel: " & Bot.Home
                        Case "cdkey", "key"
                            cmdOut Username, Source, "CD-Key: " & Bot.cdkey
                        Case "lodkey", "tftkey", "expkey", "exkey", "expcdkey", _
                        "excdkey", "lodcdkey", "tftcdkey"
                            cmdOut Username, Source, "Expansion CD-Key: " & Bot.ExCDKey
                        Case "client", "product", "game"
                            cmdOut Username, Source, "Product: " & ClientKeyToName(Bot.Client) & " (" & ClientKeyToStr(Bot.Client) & ")"
                        Case Else
                            cmdOut Username, Source, "Error: Unrecognized field."
                    End Select
                Else
                    Select Case Words(1)
                        Case "username", "un"
                            WriteConfig "Username", Words(2)
                            cmdOut Username, Source, "Set username to: " & Words(2)
                        Case "password", "pw"
                            If (Source = csWindow) Then
                                WriteConfig "Password", Words(2)
                                AddC "Set password to: " & Words(2)
                            ElseIf (Source = csWhispered) Then
                                WriteConfig "Password", Words(2)
                                cmdOut Username, Source, "Set password to: " & Words(2)
                            Else
                                cmdOut Username, Source, "Error: You must whisper that or type it in the bot window."
                            End If
                        Case "server"
                            WriteConfig "Server", Words(2)
                            cmdOut Username, Source, "Set server to: " & Words(2)
                        Case "hashed"
                            Select Case Words(2)
                                Case "yes", "y", "true", "on", "1", "active", "enabled"
                                    WriteConfig "Hashed", "Yes"
                                    cmdOut Username, Source, "Bot will now use local hashing."
                                Case "no", "n", "false", "off", "0", "inactive", "disabled"
                                    WriteConfig "Hashed", "No"
                                    cmdOut Username, Source, "Bot will now use BNLS."
                                Case Else
                                    cmdOut Username, Source, "Error: Unrecognized value."
                            End Select
                            
                        Case "home", "homechannel"
                            sTemp = Mid$(Command, Len(Words(0)) + Len(Words(1)) + 3)
                            WriteConfig "HomeChan", sTemp
                            Bot.Home = sTemp
                            cmdOut Username, Source, "Set home channel to: " & sTemp
                        Case "cdkey", "key"
                            WriteConfig "CDKey", Words(2)
                            cmdOut Username, Source, "Set CD-key to: " & Words(2)
                        Case "lodkey", "tftkey", "expkey", "exkey", "expcdkey", _
                        "excdkey", "lodcdkey", "tftcdkey"
                            WriteConfig "ExCDKey", Words(2)
                            cmdOut Username, Source, "Set CD-key to: " & Words(2)
                        Case "client", "product", "game"
                            Words(2) = UCase$(Words(2))
                            If ClientStrToKey(Words(2)) = bpUnknown Then
                                cmdOut Username, Source, "Error: Unrecognized product."
                            Else
                                WriteConfig "Product", Words(2)
                                cmdOut Username, Source, "Set product to: " & ClientKeyToName(ClientStrToKey(Words(2))) & " (" & Words(2) & ")"
                            End If
                        Case "trigger"
                            Trigger = Words(2)
                            WriteConfig "Trigger", Words(2)
                            cmdOut Username, Source, "Set trigger to: " & Words(2)
                        Case Else
                            cmdOut Username, Source, "Error: Unrecognized field."
                    End Select
                End If 'UBound(Words) <> 1
            End If '(access check)
        Case "reloaddatabase", "rd", "reloaddb", "dbload"
            ProcessCommand = True
            If (Source = csWindow) Or (GetAccess(Username) >= 70) Then
                LogEvent "Reloading database from file..."
                LoadDatabase "access.txt"
                cmdOut Username, Source, "Reloaded the database from file."
            End If
        Case "generatestar", "star", "sexp", "generatesexp"
             ProcessCommand = True
             If (Source = csWindow) Or (GetAccess(Username) >= 70) Then
                 Randomize
                 cmdOut Username, Source, "Myriad Generated Key - " & Int(Rnd * 9) & Int(Rnd * 9) & Int(Rnd * 9) & Int(Rnd * 9) & Int(Rnd * 9) & Int(Rnd * 9) & Int(Rnd * 9) & Int(Rnd * 9) & Int(Rnd * 9) & Int(Rnd * 9) & Int(Rnd * 9) & Int(Rnd * 9) & Int(Rnd * 9)
          End If
        Case "network", "nw"
            ProcessCommand = True
            If (Source = csWindow) Or (GetAccess(Username) >= 50) Then
            If Not Bot.UseBNLS Then
                cmdOut Username, Source, "Myriad is using Local Hashes to connect."
            Else
                cmdOut Username, Source, "Myriad is using BNLS (Battle.Net Logon Server) to connect."
            End If
        End If
        Case "mail", "sendmail"
            ProcessCommand = True
            If (Source = 2) Or (GetAccess(Username) >= 30) Then
            Add_Mail Words(1), Users(Username).Username, Mid$(Command, Len(Words(0)) + Len(Words(1)) + 3)
            cmdOut Username, Source, "Added mail for " & Words(1)
            End If
        Case "inbox", "read", "readmail"
            ProcessCommand = True
            If (Source = 2) Or (GetAccess(Username) >= 30) Then
            Dim Mail As sMail
            Do
                Mail = Get_Mail(Username)
                If Len(Mail.Message) <> 0 Then
                    If GetConfig("Product") = "WAR3" Or GetConfig("Product") = "W3XP" Then
                        cmdOut Username, Source, "/w " & Mail.Receiver & "@USEast <From: " & Mail.Sender & "> [" & Mail.Time & "] " & Mail.Message & " -- " & Mail.Date
                    Else
                        cmdOut Username, Source, "/w " & Mail.Receiver & " <From: " & Mail.Sender & "> [" & Mail.Time & "] " & Mail.Message & " -- " & Mail.Date
                    End If
                End If
            Loop Until Mail.Message = ""
            End If
        Case "motd", "messageoftheday"
            ProcessCommand = True
            If UBound(Words) = 0 And (Source = csWindow Or GetAccess(Username) >= 30) Then
                cmdOut Username, Source, "Message of the day: " + UserClan.MOTD
            ElseIf (Source = csWindow) Or (GetAccess(Username) >= 90) Then
                If UserClan.Rank < rankShaman Then
                    cmdOut Username, Source, "Sorry, I am not a Shaman or Chieftain in this Clan and am not allowed to change the message of the day."
                Else
                    UserClan.SetMOTD Mid$(Command, Len(Words(0)) + 2)
                    UserClan.RequestMOTD
                End If
            End If
        Case "ddp"
            ProcessCommand = True
            If (Source = csWindow Or GetAccess(Username) >= 100 Or IsMaster(Username)) Then
                If (UBound(Words) < 1) Then
                    cmdOut Username, Source, "You must specify the user to designate."
                    Exit Function
                End If
                
                If (Not UserClan.Active) Then
                    cmdOut Username, Source, "Error: I am not in a clan."
                    Exit Function
                End If
                
                If (UserClan.Rank < rankChieftain) Then
                    cmdOut Username, Source, "Error: I must be a chieftain to perform this command."
                    Exit Function
                End If
                
                cmdOut Username, Source, "Beginning DDP process, please wait..."
                UserClan.DDP Username, Source, Words(1)
            End If
        Case "invite"
            ProcessCommand = True
            If (Source = csWindow Or GetAccess(Username) >= 100 Or IsMaster(Username)) Then
                If (UBound(Words) < 1) Then
                    cmdOut Username, Source, "You must specify the user to invite."
                    Exit Function
                End If
                
                If (Not UserClan.Active) Then
                    cmdOut Username, Source, "Error: I am not in a clan."
                    Exit Function
                End If
                
                If (UserClan.Rank < rankShaman) Then
                    cmdOut Username, Source, "Error: I must be at least a shaman to perform this command."
                    Exit Function
                End If
                
                cmdOut Username, Source, "Sending an invitation to " & Words(1) & "..."
                Select Case Source
                    Case csWindow
                        UserClan.Invite Words(1), asCommand, "***WINDOW***" 'oh yes this is hackish!
                    Case csWhispered
                        UserClan.Invite Words(1), asCommand, Username
                    Case Else
                        UserClan.Invite Words(1), asCommand
                End Select
            End If
        Case "promote"
            ProcessCommand = True
            If (Source = csWindow Or GetAccess(Username) >= 100 Or IsMaster(Username)) Then
                If (UBound(Words) < 1) Then
                    cmdOut Username, Source, "You must specify the user to promote."
                    Exit Function
                End If
                
                If (Not UserClan.Active) Then
                    cmdOut Username, Source, "Error: I am not in a clan."
                    Exit Function
                End If
                
                If (UserClan.Rank < rankShaman) Then
                    cmdOut Username, Source, "Error: I must be at least a shaman to perform this command."
                    Exit Function
                End If
                
                HandlePromote Username, Source, Words(1)
            End If
        Case "demote"
            ProcessCommand = True
            If (Source = csWindow Or GetAccess(Username) >= 100 Or IsMaster(Username)) Then
                If (UBound(Words) < 1) Then
                    cmdOut Username, Source, "You must specify the user to demote."
                    Exit Function
                End If
                
                If (Not UserClan.Active) Then
                    cmdOut Username, Source, "Error: I am not in a clan."
                    Exit Function
                End If
                
                If (UserClan.Rank < rankShaman) Then
                    cmdOut Username, Source, "Error: I must be at least a shaman to perform this command."
                    Exit Function
                End If
                
                HandleDemote Username, Source, Words(1)
            End If
        Case "discharge", "expel", "oust", "exile"
            ' "remove" is already taken ;)
            ProcessCommand = True
            If (Source = csWindow Or GetAccess(Username) >= 100 Or IsMaster(Username)) Then
                If (UBound(Words) < 1) Then
                    cmdOut Username, Source, "You must specify the user to remove from the clan."
                    Exit Function
                End If
                
                If (Not UserClan.Active) Then
                    cmdOut Username, Source, "Error: I am not in a clan."
                    Exit Function
                End If
                
                If (UserClan.Rank < rankShaman) Then
                    cmdOut Username, Source, "Error: I must be at least a shaman to perform this command."
                    Exit Function
                End If
                
                HandleDischarge Username, Source, Words(1)
            End If
        Case "rank"
            ProcessCommand = True
            If (Source = csWindow Or GetAccess(Username) >= 100 Or IsMaster(Username)) Then
                
                If (Not UserClan.Active) Then
                    cmdOut Username, Source, "Error: I am not in a clan."
                    Exit Function
                End If
                
                If (UBound(Words) < 1) Then
                    HandleRank Username, Source
                Else
                    HandleRank Username, Source, Words(1)
                End If
            End If
        Case "meeting", "meet"
            ProcessCommand = True
            
            If (UBound(Words) = 0 And (Source = csWindow Or GetAccess(Username) >= 20)) Then
                If (Meeting Is Nothing) Then
                    cmdOut Username, Source, "No meeting is in progress.", 3
                Else
                    If (Meeting.FloorTaken) Then
                        cmdOut Username, Source, "Meeting in progress, and only masters and " & Meeting.UserOnFloor & _
                            " may speak."
                    ElseIf (Not Meeting.FloorOpen) Then
                        cmdOut Username, Source, "Meeting in progress, and only masters may speak."
                    Else
                        cmdOut Username, Source, "Meeting in progress, but the floor is open for discussion."
                    End If
                End If
            ElseIf (Source = csWindow Or IsMaster(Username)) Then
                Select Case LCase$(Words(1))
                    Case "on", "start", "begin"
                        Set Meeting = New Meeting
                        cmdOut Username, Source, "Meeting started.  Floor is open for discussion."
                    Case "off", "stop", "end"
                        Set Meeting = Nothing
                        cmdOut Username, Source, "Meeting ended.  Free speech restored."
                    Case "floor", "grant", "give"
                        If (Meeting Is Nothing) Then
                            cmdOut Username, Source, "No meeting is in progress.", 3
                            Exit Function
                        End If
                        
                        If UBound(Words) = 1 Then
                            If (Meeting.FloorTaken) Then
                                cmdOut Username, Source, Meeting.UserOnFloor & " has the floor."
                            Else
                                cmdOut Username, Source, "The floor is open."
                            End If
                        Else
                            Meeting.UserOnFloor = Words(2)
                            cmdOut Username, Source, Words(2) & " now has the floor.  Only he/she may speak."
                        End If
                    Case "open"
                        If (Meeting Is Nothing) Then
                            cmdOut Username, Source, "No meeting is in progress.", 3
                            Exit Function
                        End If
                        Meeting.FloorOpen = True
                        cmdOut Username, Source, "The floor is now open for discussion."
                    Case "close", "restrict"
                        If (Meeting Is Nothing) Then
                            cmdOut Username, Source, "No meeting is in progress.", 3
                            Exit Function
                        End If
                        Meeting.FloorOpen = False
                        cmdOut Username, Source, "The floor is now closed: only masters may speak."
                    Case Else
                        cmdOut Username, Source, "Usage: " & Trigger & Words(0) & " [on|off|floor [user]|open]"
                End Select
            End If
        Case Else
            ProcessCommand = False
    End Select
    Exit Function
ProcessCommand_Error:
    ProcessCommand = False
    LogEvent "Command processing error: " & Err.Description & " (#" & Err.Number & ")", etError
End Function

Private Sub HandlePromote(Username As String, ByVal Source As CommandSources, Target As String)
    Dim U As ClanMember
    
    Set U = UserClan.GetMember(Target)
    If (U Is Nothing) Then
        cmdOut Username, Source, "This clan has no member named """ & Target & """."
        Exit Sub
    End If
    
    Select Case U.Rank
        Case rankNewPeon
            cmdOut Username, Source, Target & " is a newly-joined peon and cannot be promoted yet."
            Exit Sub
        Case rankPeon
            cmdOut Username, Source, "Promoting " & Target & " to a grunt..."
            UserClan.Promote Target, asCommand, GetClanKey(Username, Source)
        Case rankGrunt
            If (UserClan.Rank < rankChieftain) Then
                cmdOut Username, Source, "Error: I must be a chieftain to promote a grunt to a shaman."
            Else
                cmdOut Username, Source, "Promoting " & Target & " to a shaman..."
                UserClan.Promote Target, asCommand, GetClanKey(Username, Source)
            End If
        Case rankShaman
            cmdOut Username, Source, "Error: Cannot promote a shaman (change chieftain) using this command; must use bot GUI."
    End Select
End Sub

Private Sub HandleDemote(Username As String, ByVal Source As CommandSources, Target As String)
    Dim U As ClanMember
    
    Set U = UserClan.GetMember(Target)
    If (U Is Nothing) Then
        cmdOut Username, Source, "This clan has no member named """ & Target & """."
        Exit Sub
    End If
    
    Select Case U.Rank
        Case rankNewPeon, rankPeon
            cmdOut Username, Source, Target & " is a peon (the lowest rank) and cannot be further demoted."
        Case rankGrunt
            cmdOut Username, Source, "Demoting " & Target & " to a peon..."
            UserClan.Demote Target, asCommand, GetClanKey(Username, Source)
        Case rankShaman
            If (UserClan.Rank < rankChieftain) Then
                cmdOut Username, Source, "Error: I must be a chieftain to demote a shaman to a grunt."
            Else
                cmdOut Username, Source, "Demoting " & Target & " to a grunt..."
                UserClan.Demote Target, asCommand, GetClanKey(Username, Source)
            End If
        Case rankChieftain
            cmdOut Username, Source, Target & " is the clan chieftain and cannot be demoted."
    End Select
End Sub

Private Sub HandleDischarge(Username As String, ByVal Source As CommandSources, Target As String)
    Dim U As ClanMember
    
    Set U = UserClan.GetMember(Target)
    If (U Is Nothing) Then
        cmdOut Username, Source, "This clan has no member named """ & Target & """."
        Exit Sub
    End If
    
    Select Case U.Rank
        Case rankNewPeon
            cmdOut Username, Source, Target & " has not been in the clan for at least a week and cannot leave yet."
        Case rankPeon, rankGrunt
            cmdOut Username, Source, "Removing " & Target & " from the clan..."
            UserClan.Remove Target, asCommand, GetClanKey(Username, Source)
        Case rankShaman
            If (UserClan.Rank < rankChieftain) Then
                cmdOut Username, Source, "Error: I must be a chieftain to remove a shaman."
            Else
                cmdOut Username, Source, "Removing " & Target & " from the clan..."
                UserClan.Remove Target, asCommand, GetClanKey(Username, Source)
            End If
        Case rankChieftain
            cmdOut Username, Source, Target & " is the clan chieftain and cannot be overthrown."
    End Select
End Sub

Private Sub HandleRank(Username As String, ByVal Source As CommandSources, Optional Target As String = vbNullString)
    Dim U As ClanMember, Rank As ClanRanks, Msg As String
    
    If (LenB(Target) = 0) Then
        Rank = UserClan.Rank
        Msg = "My rank is "
    Else
        Set U = UserClan.GetMember(Target)
        If (U Is Nothing) Then
            cmdOut Username, Source, "This clan has no member named """ & Target & """."
            Exit Sub
        End If
        Rank = U.Rank
        Msg = U.Username & " has a rank of "
    End If
    Select Case Rank
        Case rankNewPeon: Msg = Msg & "peon (with less than one week in clan)."
        Case rankPeon: Msg = Msg & "peon."
        Case rankGrunt: Msg = Msg & "grunt."
        Case rankShaman: Msg = Msg & "shaman."
        Case rankChieftain: Msg = Msg & "chieftain."
    End Select
    
    cmdOut Username, Source, Msg
End Sub

Private Function GetClanKey(Username As String, ByVal Source As CommandSources)
    Select Case Source
        Case csWindow
            GetClanKey = "***WINDOW***" 'oh yes this is hackish!
        Case csWhispered
            GetClanKey = Username
        Case Else
            GetClanKey = vbNullString
    End Select
End Function

Private Function StripRealm(Username As String)
    Select Case Bot.Client
        Case bpStarCraft, bpBroodWar, bpDiablo, bpDiablo2, bpDiablo2x, bpWarCraft2
            If LCase$(Right$(Username, 7)) = "@useast" Then
                StripRealm = Left$(Username, (Len(Username) - 7))
            ElseIf LCase$(Right$(Username, 7)) = "@uswest" Then
                StripRealm = Left$(Username, (Len(Username) - 7))
            ElseIf LCase$(Right$(Username, 7)) = "@europe" Then
                StripRealm = Left$(Username, (Len(Username) - 7))
            ElseIf LCase$(Right$(Username, 5)) = "@asia" Then
                StripRealm = Left$(Username, (Len(Username) - 5))
            Else
                StripRealm = Username
            End If
        Case bpWarCraft3, bpWarCraft3x
            If LCase$(Right$(Username, 8)) = "@azeroth" Then
                StripRealm = Left$(Username, (Len(Username) - 8))
            ElseIf LCase$(Right$(Username, 10)) = "@lordaeron" Then
                StripRealm = Left$(Username, (Len(Username) - 10))
            ElseIf LCase$(Right$(Username, 10)) = "@northrend" Then
                StripRealm = Left$(Username, (Len(Username) - 10))
            ElseIf LCase$(Right$(Username, 9)) = "@kalimdor" Then
                StripRealm = Left$(Username, (Len(Username) - 9))
            Else
                StripRealm = Username
            End If
        Case Else
            'should be never
            StripRealm = Username
    End Select
End Function

Private Sub PullTrigger(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal dwTime As Long)
    'AddC "Pulling trigger..."
    Bot.TriggerEvent
    KillTimer 0, TriggerFinger
    TriggerFinger = 0
End Sub

'Public Function ProcessCommand(ByVal Command$, ByVal Username$)
'    If StrComp(Left$(Command, Len(Trigger)), Trigger, vbTextCompare) <> 0 Then
'        ProcessCommand = False
'        Exit Function
'    End If
'
'    Command = Mid$(Command, Len(Trigger) + 1)
'
'    Dim Words() As String
'    Words = Split(Command, " ")
'
'    Select Case Words(0)
'        Case "about", "ver", "version"
'            If GetAccess(Username) >= 20 Then
'                qAdd GetVersion()
'                ProcessCommand = True
'            End If
'    End Select
'End Function
