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.

Need help with IPinfo Script

Help for those learning Tcl or writing their own scripts.
s
sysusr
Voice
Posts: 7
Joined: Tue Dec 13, 2016 12:19 am

Need help with IPinfo Script

Post by sysusr »

So far I have the following code to read data from ipinfo.io

Example of the site: https://ipinfo.io/8.8.8.8/json

Code: Select all

proc geo {n u h c t} {
        catch {set http [::http::geturl http://ipinfo.io/[lindex $t 0]/json -timeout 6000]} error
        if {[string match "*error*" $error]} { putserv "PRIVMSG $c :connect error!" ; return 0 }
        if {[string match "*timeout*" $error]} { putserv "PRVMSG $c :timeout!"; return 0 }
        set html [::http::data $http]
        if {[string match "*Not Found*" $html]} { putserv "PRIVMSG $c :GeoIP: No data found." ; return }
        regexp -line -- {<"ip":>(.*)</ip>} $html -> ipz
        regexp -line -- {<"hostname":>(.*)</hostname>} $html -> hostname
        regexp -line -- {<"city":>(.*)</city>} $html -> city
        regexp -line -- {<"region">(.*)</region>} $html -> region
        regexp -line -- {<"country":>(.*)</country>} $html -> country
        regexp -line -- {<"loc":>(.*)</loc>} $html -> loc
        regexp -line -- {<"org":>(.*)</org>} $html -> org
        putserv "PRIVMSG $c :IP: $ipz - Hostname: $hostname - City: $city - Region: $region - Country: $country - Location: $loc - Organization: $org"
        http::cleanup $http
}
But I am getting the following error....
[11:09:20] Tcl error [geo]: can't read "ipz": no such variable
Does anyone have any suggestion or help why I am getting this error? Thanks
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

If the output is in json format why do you complicate things and not parse it as a dictionary with ::json::json2dict instead?

Here's a proof of concept.

Code: Select all

package require http
package require json

proc geo {nick uhost hand chan text} {
	set lookup [lindex [split $text] 0]
	catch {set http [::http::geturl http://ipinfo.io/$lookup/json -timeout 6000]} error 
	set data [::http::data $http]
	set json [::json::json2dict $data]
	::http::cleanup $http
	foreach ele [dict keys $json] { set $ele [dict get $json $ele] } 
	putserv "PRIVMSG $chan :IP: $ip - Hostname: $hostname - City: $city - Region: $region - Country: $country - Location: $loc - Organization: $org"
}
You can either grab json.tcl file and load it before your geo script or install tcllib package.
Once the game is over, the king and the pawn go back in the same box.
s
sysusr
Voice
Posts: 7
Joined: Tue Dec 13, 2016 12:19 am

Post by sysusr »

Not sure what you mean. But I tried to load json and it broke. I already have tcllib package installed on my box. Just looking for the simplest way to parse the data
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

If you have tcllib then you don't need that separate json.tcl file, it should work without it.
Once the game is over, the king and the pawn go back in the same box.
s
sysusr
Voice
Posts: 7
Joined: Tue Dec 13, 2016 12:19 am

Post by sysusr »

caesar wrote:If you have tcllib then you don't need that separate json.tcl file, it should work without it.
Unfortunately it still does not work. Any other suggestion?
w
willyw
Revered One
Posts: 1205
Joined: Thu Jan 15, 2009 12:55 am

Post by willyw »

You might like to be SURE that you have json, etc.

In the partyline, do:
.tcl package names

and it will return a list of everything. Check to be sure that it is finding what you want/need.

( You will need to have the use of .tcl for owner's use, enabled in eggdrop.conf for this to work. )
For a fun (and popular) Trivia game, visit us at: irc.librairc.net #science-fiction . Over 300K Q & A to play in BogusTrivia !
s
sysusr
Voice
Posts: 7
Joined: Tue Dec 13, 2016 12:19 am

Post by sysusr »

willyw wrote:You might like to be SURE that you have json, etc.

In the partyline, do:
.tcl package names

and it will return a list of everything. Check to be sure that it is finding what you want/need.

( You will need to have the use of .tcl for owner's use, enabled in eggdrop.conf for this to work. )
OK i got the script working but when the field is blank it has another error.
[10:51:01] Tcl error [who]: can't read "hostname": no such variable
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

Here's a sneaky method. Replace:

Code: Select all

foreach ele [dict keys $json] { set $ele [dict get $json $ele] } 
with:

Code: Select all

set keys [dict keys $json]
set expecting {ip hostname city region country loc postal phone org}
foreach ele $expecting {
	if {[lsearch $keys $ele] != -1} {
		set $ele [dict get $json $ele]
	} else {
		set $ele "n/a"
	}
}
Once the game is over, the king and the pawn go back in the same box.
s
sysusr
Voice
Posts: 7
Joined: Tue Dec 13, 2016 12:19 am

Post by sysusr »

Forgot to reply back. Script works flawless now. Thank you
S
Sadie05
Voice
Posts: 1
Joined: Sun Jan 27, 2019 4:41 pm

Re: Need help with IPinfo Script

Post by Sadie05 »

I tried but It's a little complicated :x
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

Care to elaborate on what you tried and is complicated? Here is an updated code that validates user input and if the ip is in correct format (for example 1.1.1.1).

Code: Select all

package require http
package require json

bind pub * !geo fetch:geo

proc fetch:geo {nick uhost hand chan text} {
	if {[scan $text {%s} lookup] != 1} {
		puthelp "PRIVMSG $chan :Error, syntax is: !geo <ip>"
		return
	}
	if {![regexp {([0-9]+\.)([0-9]+\.)([0-9]+\.)([0-9]+)} $lookup]} {
		puthelp "PRIVMSG $chan :Error, the IP you mentioned is not valid."
		return
	}
	catch {set http [::http::geturl http://ipinfo.io/$lookup/json -timeout 6000]} error
	set data [::http::data $http]
	set json [::json::json2dict $data]
	::http::cleanup $http
	set keys [dict keys $json]
	foreach ele {ip hostname city region country loc postal phone org} {
		set $ele [expr {[lsearch $keys $ele] > -1 ? [dict get $json $ele] : "n/a"}]
	}
	puthelp "PRIVMSG $chan :IP: $ip - Hostname: $hostname - City: $city - Region: $region - Country: $country - Location: $loc - Organization: $org"
}
Once the game is over, the king and the pawn go back in the same box.
S
Stefano1990
Voice
Posts: 25
Joined: Mon Jun 04, 2018 10:07 am
Contact:

Script help

Post by Stefano1990 »

Can u make this script and to show on connect client Nick IP Country Code and msg connect client on channel #opers

and to make save blacklist list countrycode on #opers !add blcountry AA | !del blcountry AA | !blcountry list

if the country code is on blacklist to show only this msg one #oper during client Global connect

INFO:Client Global Connecting : [G-ZLine] : Jimmy 46.34.57.23 Germany De [BlackCountry]

to take gzline *@IP 2h: Your Country Is Not Allowed In This Network

and to make save exemp list on channel #opers !add exemp 46.34.* US | !del exemp 46.34.* US |
!exemp list

if the Ip + country code is on exemp list to show only this msg one #oper during client Global connect

INFO: Client Global Connecting : Jimmy 46.34.57.23 Germany De

if the Ip dont have his Country Code on exemp to be gzline
same and for the Country Code when dont have his Ip on exemp
example: this to be add for Client Global Connect wrote:

Code: Select all

bind raw - NOTICE server:notices

proc server:notices {from keyword text} {
  global outputchan
      if {[string match -nocase "*client connecting*" $text]} {
        set hostmask [lindex [split $text] 6]
     puthelp "PRIVMSG #Opers :$nick -  $IP - $country" 
        return 0
      }
} 

Use your common sense and try not to make me look too much like I know what I'm doing.
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

Keep this in mind about ipinfo.io website:
If you need to make under 1,000 requests a day to our API and it's for non-commercial use, or you just want to test things out, signup for our free plan.
meaning that they offer a paid lookup service, so if you do a few of them then I guess that they won't mind, but if you plan to whois every IP that is connecting (meaning a lot of traffic) should consider either getting a paid account or another service, maybe an addon for the IRC server itself.

Anyway, if whatever you get from:

Code: Select all

set hostmask [lindex [split $text] 6]
isn't a valid IP in the format x.x.x.x this won't work, you would have to reverse DNS to get the actual IP.

Give this untested code a try:

Code: Select all

bind raw - NOTICE server:notices

proc server:notices {from keyword text} {
	if {[string match -nocase "*client connecting*" $text]} {
		set hostmask [lindex [split $text] 6]
		if {![regexp {([0-9]+\.)([0-9]+\.)([0-9]+\.)([0-9]+)} $lookup]} return
		catch {set http [::http::geturl http://ipinfo.io/$lookup/json -timeout 6000]} error
		set data [::http::data $http]
		set json [::json::json2dict $data]
		::http::cleanup $http
		set keys [dict keys $json]
		foreach ele {ip hostname city region country loc postal phone org} {
			set $ele [expr {[lsearch $keys $ele] > -1 ? [dict get $json $ele] : "n/a"}]
		}
		puthelp "PRIVMSG #Opers :$nick -  $ip - $country"
	}
}
Duno from what position in that raw notice you get the $nick from cos you didn't give me an example so left it as is and it's up to you to fix it.

Edit: There are multiple paid and free options you should consider if plan to filter every connection. Just do a ip to country database lookup on Google.
Last edited by caesar on Mon Jan 28, 2019 3:52 pm, edited 1 time in total.
Once the game is over, the king and the pawn go back in the same box.
s
sysusr
Voice
Posts: 7
Joined: Tue Dec 13, 2016 12:19 am

Post by sysusr »

i have a slight inquiry since your last update, you can no longer look up IPv6 addresses

so i decided to remove the regex that requires numerical digits and it worked just fine
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

I just noticed that I copy/paste the code you gave me and didn't double check the variables, so instead of:

Code: Select all

set hostmask [lindex [split $text] 6] 
should have been:

Code: Select all

set lookup [lindex [split $text] 6] 
Anyway, back to what you asked. We can just use TCLib's IP to validate a Ipv4 or IPv6 that will return -1 if the IP isn't valid, 4 for IPv4 and 6 for IPv6. Simple, no?

Basically we change these two lines:

Code: Select all

      set hostmask [lindex [split $text] 6]
      if {![regexp {([0-9]+\.)([0-9]+\.)([0-9]+\.)([0-9]+)} $lookup]} return 
with:

Code: Select all

      set lookup [lindex [split $text] 6]
      if {[::ip::version $lookup] < 4} return
and above:

Code: Select all

bind raw - NOTICE server:notices 
simply add:

Code: Select all

package require ip
Once the game is over, the king and the pawn go back in the same box.
Post Reply