| View previous topic :: View next topic |
| Author |
Message |
Sarteck Voice
Joined: 14 Mar 2008 Posts: 11
|
Posted: Tue Aug 10, 2010 12:21 am Post subject: Best way to get Nickserv Identification Status of users |
|
|
Until recently, I've been running a PHP-IRC bot, because PHP is the language I'm most comfortable with. Unfortunately, it's just consuming too much CPU (which I was warned beforehand that it would, heh), so I'm trying to switch a lot of my functions over from PHP to Tcl, which I know next to nothing about. I've been getting the hang of the syntax easily enough, but there's just so much I don't know how to do. XD
Anyways, I used to have this timer set on the PHP Bot to check the user list every 3 minutes, and for each user it found that was not already in its namelist array (or was in it but without a status of 3), it added that user as the array key and their status code (0, 1, 2, or 3, NickServ's various Identification levels).
For example:
(PHP example)
| Code: | $userlist = array(
'Tom' => 3, // Identified
'Dick' => 0, // Nick Not Registered
'Harry => 1 // Nick Registered, but not Identified as owner
) |
I have been reading, and my understanding is that Tcl arrays are ONLY associative arrays--they are not indexes with numbers, like a lot of the languages I'm familiar with. That's cool, though, because what I've been using is an associative array.
The problem arises when I realize I don't know how I can make eggdrop listen for NOTICE responses from NickServ when it sends queries about the status. Or maybe I'm going about this entirely the wrong way, I'm not sure. XP
BASICALLY, I want to make sure that the users executing certain commands on the bot are IDENTIFIED with NickServ. I'd like to take that info and send it via POST to a PHP script, which will parse it and send it in turn to a MySQL server. (Later on down the line, I'd like to see if I can use Tcl to directly interface with MySQL, but there's a lot of PHP I'd have to re-write into Tcl in order to get my script running right, so for now I'll stick with Tcl -> POST for PHP -> MySQL.)
I'm already aware of how to send the POST data, have made a script, tested it, and everything works out A-OK.
If I could be allowed to double-post, I'll post a snippet of the PHP code in the next post, to give you a general idea of what I was doing. I know that my way was probably not the most elegant of solutions, but it worked. XP |
|
| Back to top |
|
 |
Sarteck Voice
Joined: 14 Mar 2008 Posts: 11
|
Posted: Tue Aug 10, 2010 12:22 am Post subject: The PHP snippet |
|
|
| Code: |
/// RESPONDS to Notices, adds/changes nicks to master table.
public function check_incoming($line, $args)
{
if (strtolower($line['fromNick']) != 'nickserv') {return;}
if ($args['cmd'] != 'status') {return;}
if ($args['arg2'] <= -1) {return;}
if ($args['arg2'] >= 4) {return;}
if (array_key_exists('arg3', $args)) {return;}
$this->_set_namelist($args['arg1'], $args['arg2']);
}
/// !get_names --- Gets list of names on the current channel and sends it to the parser
public function get_names($line=false, $args=false)
{
$channels = array('#void','#ClubBleach','#4thDivision','#Junibantai','#cbstaff','#die','#Central46');
$new_channel_index = ($this->last_channel_index >= (sizeof($channels)-1)) ? 0 : $this->last_channel_index + 1;
$channel = $channels[$new_channel_index];
$this->ircClass->sendRaw('names ' . $channel);
$this->getting_channel = $channel;
$this->last_channel_index = $new_channel_index;
return true;
}
/// RESPONDS to 353 --- For each Name provided by get_names, sends a /msg NickServ STATUS $name
public function parse_names($line, $args)
{
$names = explode(' ', $line['text']);
$channel = '';
if ($this->getting_channel)
{
$channel = $this->getting_channel;
$this->getting_channel = false;
$this->channel_list[$channel] = $names;
}
foreach ($names AS $name)
{
$name = $this->_get_real_name($name);
$this->ircClass->privMsg('NickServ', 'STATUS ' . $name);
}
return true;
}
|
|
|
| Back to top |
|
 |
Sarteck Voice
Joined: 14 Mar 2008 Posts: 11
|
|
| Back to top |
|
 |
Sarteck Voice
Joined: 14 Mar 2008 Posts: 11
|
Posted: Tue Aug 10, 2010 4:53 am Post subject: |
|
|
Quadruple posting ftw!
No, I'm posting to tell ya I think I've got it figured out now, after a bit of digging. Although I cannot find a way to make eggdrop listen for the 353 line returned from the NAMES command, I don't need it.
| Code: | chanlist <channel> [flags[&chanflags]]
Description: flags are any global flags; the '&' denotes to look for channel specific flags. Examples:
n
Global Owner
&n
Channel Owner
o&m
Global Op, Channel Master
Returns: list of nicknames currently on the bot's channel that have all of the flags specified;. If no flags are given, all of the nicknames are returned. Please note that if you're executing chanlist after a part or sign bind, the gone user will still be listed, so you can check for wasop, isop, etc. |
Seems that chanlist will work just great for me, and I don't have to parse user masks like I was doing with my PHP bot. X3
Here's the code I'm working with--mind you it's not tested yet.
| Code: |
bind notc - "*STATUS*" doSetStatus
bind time - * doGetNames
### Get Names on channel, send Status request to NickServ for each name on nicklist without STATUS of 3
### -- CALLED EVERY MINUTE by bind time - *
proc doGetNames {nick host handle text dest} {
global nicklist
foreach userraw [chanlist "#void"] {
if {nicklist($userraw) != 3} {
putserv "PRIVMSG NickServ :STATUS $userraw"
}
}
}
### Answers NickServ's status response notice, setting nicklist appropriately.
proc doSetStatus {nick host handle text dest} {
global nicklist
regexp {STATUS ([^ ]*) ([0-3])} $text NS_name NS_status
set nicklist($NS_name) $NS_status
}
|
I've probably got a few bugs, but I'm sure I'm on the right track. I'll make this a quintuple post to let you guys know how it turns out when it's done.
Eventually, this list of identified nicks will be able to display a "Who's Online" on the main page of our forum... or at least that's my intent. I'm aware there's already such a script out there, but mine would have to be modified to get the forum owner of the IRC nickname, something it would have to interface with the database for. |
|
| Back to top |
|
 |
willyw Revered One
Joined: 15 Jan 2009 Posts: 1175
|
Posted: Tue Aug 10, 2010 11:27 am Post subject: |
|
|
I'm not sure that I'm with you all the way, but I do have a couple comments. I hope they are useful to you.
| Sarteck wrote: | Quadruple posting ftw!
No, I'm posting to tell ya I think I've got it figured out now, after a bit of digging. Although I cannot find a way to make eggdrop listen for the 353 line returned from the NAMES command, I don't need it.
|
Sounds like you want to watch for a raw numeric from the server.
Is that it?
| Code: |
bind raw <flags> <keyword> <proc>
|
will do it. (if you change your mind and want to... or ever need this idea for something else)
Keyword in this case would be 353.
Look in your doc/ directory, for a file named tcl-commands.doc
How to use this bind is described in there, along with all the rest of the eggdrop specific tcl commands.
To make it easier to see what is going on, when experimenting like this - I issue this command in the partyline: .console +rv
Then, I can see raw incoming and outgoing traffic.
More info on the console flags can be had with : .help console
| Quote: |
| Code: | chanlist <channel> [flags[&chanflags]]
Description: flags are any global flags; the '&' denotes to look for channel specific flags. Examples:
n
Global Owner
&n
Channel Owner
o&m
Global Op, Channel Master
Returns: list of nicknames currently on the bot's channel that have all of the flags specified;. If no flags are given, all of the nicknames are returned. Please note that if you're executing chanlist after a part or sign bind, the gone user will still be listed, so you can check for wasop, isop, etc. |
Seems that chanlist will work just great for me, and I don't have to parse user masks like I was doing with my PHP bot. X3
...
|
This applies only to users that have an account in your bot.
If I understand you correctly, you wanted a way to determine if users in a channel were id'd with Nickserv.
What if there are nicks in the channel, that are id'd with Nickserv, but do not have accounts in your bot?
Are they important? |
|
| Back to top |
|
 |
willyw Revered One
Joined: 15 Jan 2009 Posts: 1175
|
Posted: Tue Aug 10, 2010 11:39 am Post subject: Re: Best way to get Nickserv Identification Status of users |
|
|
| Sarteck wrote: |
...
BASICALLY, I want to make sure that the users executing certain commands on the bot are IDENTIFIED with NickServ.
...
|
For what it is worth:
I've done this in the past.... ... made a script that would check to see if users were id'd with Nickserv or not.
However, I did it by checking for raw numerics, by having the bot send a /whois command on each nick in question, to the server.
Using raw binds, the return from the /whois command can be examined to determine if the user is id'd.
It worked. The problem can be that the script might not necessarily work on another server. The raw numerics returned can be a bit different, necessitating adjusting the script for each server.
I completely overlooked the /msg nickserv status
command. ... just never thought of it.
That's an interesting way of going about it, and I haven't tried to figure out which way is "best"... or if one even is "best".
Good luck with your project.  |
|
| Back to top |
|
 |
Sarteck Voice
Joined: 14 Mar 2008 Posts: 11
|
Posted: Wed Aug 11, 2010 6:19 am Post subject: |
|
|
Hey, Willy, thanks for that--I was assuming that chanlist would return all the names on a specified channel the bot is on--I didn't realize that it only takes into account those with an account on the bot. Well, if that's the case, I'll have to go about it with (as you said) using the raw bind.
Ah... On closer inspection... it appears you were mistaken. >.> Or mebbe you didn't know what I was asking for, I'm not sure. X3
| Code: | set nicklist("ClubBleach") 3
bind pub - !randomhan setRandomHan
bind notc - "*STATUS*" doSetStatus
bind time - "* * * * *" doGetNames
###############################################################################
### Procedures called by public bind events ###
###############################################################################
### Get valid users for randomhan, process CB Users, give han, report to channel
proc setRandomHan {nick host handle chan text} {
global nicklist
set numUsers $text
set identifiedUsers ""
foreach userraw [chanlist "#ClubBleach"] {
if {[info exists nicklist($userraw)]} {
if {$nicklist($userraw) == 3} {
lappend identifiedUsers $userraw
}
}
}
set CBUserData [setCBUsers $identifiedUsers $nick $numUsers]
foreach userline [split $CBUserData "@"] {
putserv "PRIVMSG #ClubBleach :$userline"
}
}
### Get Names on channel, send Status request to NickServ for each name on nicklist without STATUS of 3
### -- CALLED EVERY MINUTE by bind time - "* * * * *"
proc doGetNames {min hour day month year} {
global nicklist
foreach userraw [chanlist "#ClubBleach"] {
if {![info exists nicklist($userraw)]} {
set nicklist($userraw) 0
}
if {$nicklist($userraw) != 3} {
putserv "PRIVMSG NickServ :STATUS $userraw"
}
}
}
### Answers NickServ's status response notice, setting nicklist appropriately.
proc doSetStatus {nick host handle text dest} {
global nicklist
regexp {STATUS ([^ ]*) ([0-3])} $text hmm NS_name NS_status
set nicklist($NS_name) $NS_status
putserv "PRIVMSG Sarteck :$NS_name -- $NS_status"
}
### Get valid CB Users frim Identified User list.
### Process the random han in PHP, and then return the result to the bot to display in the chan.
proc setCBUsers {iduserlist nick numUsers} {
package require http
set url http://www.XXXXXXXXXXXXXXXX.org/mybot.php
set querystring [http::formatQuery "do" "new_randomhan" "users" $iduserlist "caller" $nick "numUsers" $numUsers]
set token [http::geturl $url -query $querystring]
set data [http::data $token]
http::cleanup $token
return $data
}
|
This is my code, and it works perfcetly, except for one bit....
| Code: | proc setRandomHan {nick host handle chan text} {
global nicklist
set numUsers $text
set identifiedUsers ""
foreach userraw [chanlist "#ClubBleach"] {
if {[info exists nicklist($userraw)]} {
if {$nicklist($userraw) == 3} {
lappend identifiedUsers $userraw
}
}
}
set CBUserData [setCBUsers $identifiedUsers $nick $numUsers]
foreach userline [split $CBUserData "@"] {
putserv "PRIVMSG #ClubBleach :$userline"
}
} |
The CBUsers procedure returns a string from the page it loads. This string is actually a list separated by "@" symbols. It works fine with about 10 or less users, but if I put in, say, 20 "lines" to CBUserData (each "line" separated by the "@" symbol), it usually stops after about 12-14 lines and doesn't PRIVMSG the channel with the rest. I'm not sure what I'm doing wrong there. |
|
| Back to top |
|
 |
willyw Revered One
Joined: 15 Jan 2009 Posts: 1175
|
Posted: Wed Aug 11, 2010 11:24 am Post subject: |
|
|
| Sarteck wrote: | Hey, Willy, thanks for that--I was assuming that chanlist would return all the names on a specified channel the bot is on--
|
It can.
| Quote: |
I didn't realize that it only takes into account those with an account on the bot.
|
It can, if an optional flag is used with the command.
| Quote: |
...
Or mebbe you didn't know what I was asking for, I'm not sure. X3
|
It was my error, as I focused on that which you'd quoted, which included the optional flag command.
Obviously, you do understand the use of the command.
| Quote: |
This is my code, and it works perfectly, except for one bit....
....
set CBUserData [setCBUsers $identifiedUsers $nick $numUsers]
foreach userline [split $CBUserData "@"] {
putserv "PRIVMSG #ClubBleach :$userline"
}
}[/code]
The CBUsers procedure returns a string from the page it loads. This string is actually a list separated by "@" symbols. It works fine with about 10 or less users, but if I put in, say, 20 "lines" to CBUserData (each "line" separated by the "@" symbol), it usually stops after about 12-14 lines and doesn't PRIVMSG the channel with the rest. I'm not sure what I'm doing wrong there. |
Without having anything to actually test and experiment with, it is much harder for me to try to figure out. (Perhaps you need a real TCL guru, eh? )
But I'll venture this:
I noticed this line:
| Code: |
foreach userline [split $CBUserData "@"] {
|
Not sure what effect using foreach might have.
When I do something like that, I do:
| Code: |
set userline [split $CBUserData "@"] {
|
I would have tested it, before posting..... this might be a waste of your time.... but give it a test. See what difference it makes.
I like your proc doSetStatus for determing if a nick is id'd with Nickserv. |
|
| Back to top |
|
 |
Sarteck Voice
Joined: 14 Mar 2008 Posts: 11
|
Posted: Wed Aug 11, 2010 5:41 pm Post subject: |
|
|
See, setRandomHan gives a random amount of "Hansatsu" (a "currency" on my forum) to a specified amount of users.
CBUserData gets the result from the CBUsers function. THat function calls a PHP page on my server through POST. The PHP Script sends back a string response (I make it "die($data)"), which goes to the CBUserData variable.
This string is actually a PHP Array that's been "imploded()" with "@" as the implode character.
If I had the PHP array
| Code: |
$data = array('Tom got 50 Han', 'Dick got 20 Han', 'Harry got 10 Han');
die(implode('@',$data));
|
Then CBUserData would now contain
'Tom got 50 Han@Dick got 20 Han@Harry got 10 Han'
So, I split that on the "@" character in Tcl to use a "foreach" that puts each message on one line. Get it?
The problem is, it seems to only send the first 12-14 lines. If I give Random Han to 20 or 30 people, it PRIVMSGs to the channel only 12-14 times. I do know that the PHP page sends the string in its entirety, but I'm wondering if maybe Tcl could be trimming it somehow? Would I have to declare a variable to be able to hold large amounts of text? Or is it something else entirely? |
|
| Back to top |
|
 |
Sarteck Voice
Joined: 14 Mar 2008 Posts: 11
|
Posted: Sat Aug 14, 2010 7:33 am Post subject: |
|
|
Just a follow up, here.
THe "bug" which made it seem as if my Bot was not sending every line of the split string; well, it turned out to be that it just would not repeat the same message twice or more in a row.
So if one of my users got awarded 2 Han, then the same user got awarded the same amount, since both the strings are the same, it wouldn't send the second line.
I don't know if that's a Tcl thing, or if it's an eggdrop thing, or simply if the server I'm on is what's not allowing it. However, I "fixed" it by putting an incrementing variable in the message line--thus, none of the lines are ever the same for the same run. X3
I based another script off of that, btw, to list which users are online on my forum home page. :3 It's pretty sweet.
No all I have to do is put in some kind of check to make sure that the NOTICES it receives back from NickServ are indeed from NickServ. (The way I currently have it written, it just checks for any notice beginning with "STATUS").
I also put in a timer to clear entries from the main nicklist variable every 15 minutes, so that it's not full of a bunch of "dead" users. |
|
| Back to top |
|
 |
nml375 Revered One
Joined: 04 Aug 2006 Posts: 2857
|
Posted: Sat Aug 14, 2010 9:58 am Post subject: |
|
|
That's a feature in fairly recent eggdrops. See the double-* settings in your config-file (current would be double-mode, double-server, double-help). _________________ NML_375, idling at #eggdrop@IrcNET |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|