This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

Specific reading commands

Help for those learning Tcl or writing their own scripts.
Post Reply
F
Fill
Halfop
Posts: 80
Joined: Sun Jan 18, 2009 6:08 pm

Specific reading commands

Post by Fill »

Messing around with files and discovering new commands... :P

My question now is, if I have a certain file, how would I make the bt read that file to the channel BUT only reading the first word of every line?

Example:

Code: Select all

File1.txt
-----------

User1 Message1
User2 Message2
User3 Message3
And when typing !list, the bot sends this message to the channel:
User1, User2, User3

Thanks in advance,
Fill
User avatar
tomekk
Master
Posts: 255
Joined: Fri Nov 28, 2008 11:35 am
Location: Oswiecim / Poland
Contact:

Post by tomekk »

Code: Select all

set myfile [open "file.txt" r]
set whole_data [read $myfile]
close $myfile

set lines [split $whole_data "\n"]

foreach line $lines {
        if {$line != ""} {
                set split_words [split $line]
                set first_word [lindex $split_words 0]
                puts $first_word
        }
}
This can be one of many ways to do this.
Watch out for "spaces" in user names.
If user name have "space" in name then you need to use other separate char like ";", will be easier.

User1;Message1 or something else
F
Fill
Halfop
Posts: 80
Joined: Sun Jan 18, 2009 6:08 pm

Post by Fill »

tomekk wrote:

Code: Select all

set myfile [open "file.txt" r]
set whole_data [read $myfile]
close $myfile

set lines [split $whole_data "\n"]

foreach line $lines {
        if {$line != ""} {
                set split_words [split $line]
                set first_word [lindex $split_words 0]
                puts $first_word
        }
}
This can be one of many ways to do this.
Watch out for "spaces" in user names.
If user name have "space" in name then you need to use other separate char like ";", will be easier.

User1;Message1 or something else
Hi,

I replaced " puts $first_word" with "puthelp "NOTICE $nick $first_word"", because I prefer to send it via notice to the nickname that requested the listing. However, the list will be something like this:
[Thu-05:12:38pm] -@RoBotX- #cyber-world users list:
[Thu-05:12:40pm] -@RoBotX- User1
[Thu-05:12:42pm] -@RoBotX- User2
[Thu-05:12:44pm] -@RoBotX- User3
[Thu-05:12:46pm] -@RoBotX- User4
Whereas in fact I'd like it to be something like this:
[Thu-05:12:38pm] -@RoBotX- #cyber-world users list:
[Thu-05:12:40pm] -@RoBotX- User1 User2 User3 User4
Also, I'd like to ask you something else. If I have this file:
User1 Message1
User2 Message2
User2 Message3
User2 Message4
how would I make a process that sent message 2, then another with message 3 and finaly message4 to the channel when I type !user2 (I mean, make him read all lines with *User2* and send the messages to the channel).

Once again, thanks for the help and patience.

See ya
User avatar
speechles
Revered One
Posts: 1398
Joined: Sat Aug 26, 2006 10:19 pm
Location: emerald triangle, california (coastal redwoods)

Post by speechles »

Code: Select all

set myfile [open "file.txt" r]
set whole_data [read $myfile]
close $myfile

set lines [split $whole_data "\n"] 

set users [list]
foreach line $lines {
	if {[string length $line]} {
		lappend users [lindex [split $line] 0]]
	}
}
putserv "privmsg $nick :#yourchan users list:"
putserv "privmsg $nick :[join $users ", "]"
F
Fill
Halfop
Posts: 80
Joined: Sun Jan 18, 2009 6:08 pm

Post by Fill »

Hi again,

Tested that, and the output was this (changed it to PRIVMSG $chan):
[Thu-09:13:39pm] « @RoBotX » User1], Test], TestingUserlist]
And then I noticed you added a useless ] in the "lappend" command, so here's the final and correct and tested script:

Code: Select all

set myfile [open "file.txt" r]
set whole_data [read $myfile]
close $myfile

set lines [split $whole_data "\n"]

set users [list]
foreach line $lines {
   if {[string length $line]} {
      lappend users [lindex [split $line] 0]
   }
}
putserv "privmsg $nick :#yourchan users list:"
putserv "privmsg $nick :[join $users ", "]"
Thanks for the help speechles! Now, just need to fix the multiple messages issue. Any ideas?
User avatar
tomekk
Master
Posts: 255
Joined: Fri Nov 28, 2008 11:35 am
Location: Oswiecim / Poland
Contact:

Post by tomekk »

file:

Code: Select all

User1 Message1
User2 Message2a
User3 Message1
User2 Message2b
User3 Message3
tcl:

Code: Select all

set myfile [open "file.txt" r]
set whole_data [read $myfile]
close $myfile

set lines [split $whole_data "\n"]

# we are looking for User2
set user_name "User2"

foreach line $lines {
        if {$line != ""} {
                set split_words [split $line]
                set u_nick [lindex $split_words 0]
                set u_msg [lrange $split_words 1 end]
                if {[string match *$user_name* $line]} {
                        puts $u_msg
                }
        }
}
output:

Code: Select all

[tomekk@zonk]:/home# ./test.tcl
Message2a
Message2b
Format it as yourself.

And better make a bind something like this !user <username> will be easier for you than !user2 !user3 etc.

cheers
F
Fill
Halfop
Posts: 80
Joined: Sun Jan 18, 2009 6:08 pm

Post by Fill »

tomekk wrote:file:

Code: Select all

User1 Message1
User2 Message2a
User3 Message1
User2 Message2b
User3 Message3
tcl:

Code: Select all

set myfile [open "file.txt" r]
set whole_data [read $myfile]
close $myfile

set lines [split $whole_data "\n"]

# we are looking for User2
set user_name "User2"

foreach line $lines {
        if {$line != ""} {
                set split_words [split $line]
                set u_nick [lindex $split_words 0]
                set u_msg [lrange $split_words 1 end]
                if {[string match *$user_name* $line]} {
                        puts $u_msg
                }
        }
}
output:

Code: Select all

[tomekk@zonk]:/home# ./test.tcl
Message2a
Message2b
Format it as yourself.

And better make a bind something like this !user <username> will be easier for you than !user2 !user3 etc.

cheers
perfect!!! P-E-R-F-E-C-T!!! Thanks a lot :)

Everything's fine by now, but I have one last problem which I didn't remember that could occur. The userlist is getting bigger and bigger, and when I type !userlist, the list is so big that it exceeds the maximum /notice command characters allowed.

Eg.: !userlist
[Fri-05:43:16pm] -@RoBotX- #cyber-world users list:
[Fri-05:43:17pm] -@RoBotX- <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> <user> AND FINISHED (the rest of them aren't showed because the notice is too big)

So my idea was to split the list in notices of 50 users maximum, I mean, the first notice with the first 50 users, 2nd notice with the other 50, etc, etc, till the listing ends. This seems very compilcated to me, I don't see what can I do to solve this :S
User avatar
speechles
Revered One
Posts: 1398
Joined: Sat Aug 26, 2006 10:19 pm
Location: emerald triangle, california (coastal redwoods)

Post by speechles »

Code: Select all

set u_msg [lrange $split_words 1 end] 
This is improper and special characters will cause problems with this line.

Code: Select all

set u_msg [join [lrange $split_words 1 end]] 
This is an easier way to achieve what your after.

Code: Select all

variable spam:chan "#yourchan"
bind pub - !user spam:file:pub
bind msg - !user spam:file:msg

setudef flag users

proc spam:file:msg {nick uhost hand text} {
  spam:file:pub $nick $uhost $hand 0 $text
}

proc spam:file:pub {nick uhost hand chan text} {
  if {[string equal "0" $chan]} {
    set chan $nick
  } elseif {![channel get $chan users]} { return }
  set myfile [open "file.txt" r]
  set whole_data [read $myfile]
  close $myfile

  set lines [split $whole_data "\n"]

  set user [lindex [split $text] 0]
  if {![string length $user]} {
    set count 0 ; array set users
    foreach line $lines {
      if {[string length $line]} {
        lappend users($count) [lindex [split $line] 0]
        if {[llength $users($count)] > 49} { incr count }
      }
    }
    putserv "privmsg $chan :$::spam:chan users list:"
    foreach count [array names users] {
      putserv "privmsg $chan :[join [lsort -increasing $users($count)] ", "]"
    }
  } else {
    set found [lsearch -glob "$user *" $lines]
    if {$found} {
      putserv "privmsg $chan :nick: [lindex [split [lindex $lines $found]] 0] -- message: [join [lrange [split [lindex $lines $found]] 1 end]]"
    } else {
      putserv "privmsg $chan :The nickname ($user) does not have a message attached."
    }
  }
}
What should happen here is the same procedure is used for both message and public binding. If the command is issued without any nickname to search for, the script will return all the nicknames (as your request 50 per line). If the command is issued with a nickname to search for, the script will return that nickname and their message.
on partyline, issue this command to turn the script on .chanset #yourchan +users
then you simply type !users and there is your list of users.
or type !users nick and if nick is there, his message will be shown or if it doesn't exist a message saying so will be shown instead.
User avatar
tomekk
Master
Posts: 255
Joined: Fri Nov 28, 2008 11:35 am
Location: Oswiecim / Poland
Contact:

Post by tomekk »

Code: Select all

set u_msg [lrange $split_words 1 end]
This will work, it just add extra brackets.
But yeah, join can fix this "issue".

cheers
F
Fill
Halfop
Posts: 80
Joined: Sun Jan 18, 2009 6:08 pm

Post by Fill »

I got an error with "array set": should be "array set arrayName list"
User avatar
Sir_Fz
Revered One
Posts: 3794
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

Initialize the array with an empty list

Code: Select all

array set users [list]
F
Fill
Halfop
Posts: 80
Joined: Sun Jan 18, 2009 6:08 pm

Post by Fill »

done

once again, thanks for the help, keep up the good job :wink:
User avatar
Sir_Fz
Revered One
Posts: 3794
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

This line can cause incorrect behavior:

Code: Select all

set found [lsearch -glob "$user *" $lines]
if {$found} {
Since $found might return 0 if the index of the matched word is 0, the if statement will be processed as false rather than true. My suggestion is to add a check for the value of $found:

Code: Select all

if {$found != -1} {
F
Fill
Halfop
Posts: 80
Joined: Sun Jan 18, 2009 6:08 pm

Post by Fill »

ahm... good point, thanks for the tip
Post Reply