# # 0.3 - ? # - switch from decode_html to htmlparse::mapEscape # - fix issue with encoding getting ascii # - add !g1 for one result # - strip remaining html from api result # # 0.2 - May 10 2010 # - fix for garbled utf chars in api queries # - added +google channel flag to enable # - strip html from !convert as some formatting may be present # - fix decode_html to convert html utf to hex # - convert to exponent # # 0.1 - Some time in April 2010 # - Initial release # # Created Feb 28 2010 # # License: Public domain # # Requires Tcl 8.5+ # Requires tcllib for json # package require http package require json package require htmlparse namespace eval google { #variable output_cmd "cd::putnow" variable output_cmd "putserv" # Not enforced for API queries variable useragent "Lynx/2.8.8dev.2 libwww-FM/2.14 SSL-MM/1.4.1" variable convert_url "http://www.google.ca/search" variable convert_regexp {.*?(.*?).*?
} variable api_url "http://ajax.googleapis.com/ajax/services/search/" variable api_referer "http://www.egghelp.org" bind pub -|- "!g" google::search bind pub -|- "!google" google::search bind pub -|- "!g1" google::search1 bind pub -|- "!news" google::news bind pub -|- "!images" google::images bind pub -|- "!convert" google::convert setudef flag google } proc google::convert_fetch {terms} { http::config -useragent $google::useragent set query [http::formatQuery q $terms] set token [http::geturl ${google::convert_url}?${query}] set data [http::data $token] set ncode [http::ncode $token] http::cleanup $token # debug #set fid [open "g-debug.txt" w] #puts $fid $data #close $fid if {$ncode != 200} { error "HTTP query failed: $ncode" } return $data } proc google::convert_parse {html} { if {![regexp -- $google::convert_regexp $html -> result]} { error "Parse error or no result" } set result [htmlparse::mapEscapes $result] # change num to ^num (exponent) set result [regsub -all -- {(.*?)} $result {^\1}] # strip rest of html code return [regsub -all -- {<.*?>} $result ""] } # Query normal html for conversions proc google::convert {nick uhost hand chan argv} { if {![channel get $chan google]} { return } if {[string length $argv] == 0} { $google::output_cmd "PRIVMSG $chan :Please provide a query." return } if {[catch {google::convert_fetch $argv} data]} { $google::output_cmd "PRIVMSG $chan :Error fetching results: $data." return } if {[catch {google::convert_parse $data} result]} { $google::output_cmd "PRIVMSG $chan :Error: $result." return } $google::output_cmd "PRIVMSG $chan :\002$result\002" } # Output for results from api query proc google::output {chan url title content} { regsub -all -- {(?:|)} $title "\002" title regsub -all -- {<.*?>} $title "" title set output "$title @ $url" $google::output_cmd "PRIVMSG $chan :[htmlparse::mapEscapes $output]" } # Return results from API query of $url proc google::api_fetch {terms url} { set query [http::formatQuery v "1.0" q $terms safe off] set headers [list Referer $google::api_referer] set token [http::geturl ${url}?${query} -headers $headers -method GET] set data [http::data $token] set ncode [http::ncode $token] http::cleanup $token # debug #set fid [open "g-debug.txt" w] #fconfigure $fid -translation binary -encoding binary #puts $fid $data #close $fid if {$ncode != 200} { error "HTTP query failed: $ncode" } return [json::json2dict $data] } # Validate input and then return list of results proc google::api_validate {argv url} { if {[string length $argv] == 0} { error "Please supply search terms." } if {[catch {google::api_fetch $argv $url} data]} { error "Error fetching results: $data." } set response [dict get $data responseData] set results [dict get $response results] if {[llength $results] == 0} { error "No results." } return $results } # Query api proc google::api_handler {chan argv url {num {}}} { if {[catch {google::api_validate $argv $url} results]} { $google::output_cmd "PRIVMSG $chan :$results" return } foreach result $results { if {$num != "" && [incr count] > $num} { return } dict with result { # $language holds lang in news results, doesn't exist in web results if {![info exists language] || $language == "en"} { google::output $chan $unescapedUrl $title $content } } } } # Regular API search proc google::search {nick uhost hand chan argv} { if {![channel get $chan google]} { return } google::api_handler $chan $argv ${google::api_url}web } # Regular API search, 1 result proc google::search1 {nick uhost hand chan argv} { if {![channel get $chan google]} { return } google::api_handler $chan $argv ${google::api_url}web 1 } # News from API proc google::news {nick uhost hand chan argv} { if {![channel get $chan google]} { return } google::api_handler $chan $argv ${google::api_url}news } # Images from API proc google::images {nick uhost hand chan argv} { if {![channel get $chan google]} { return } google::api_handler $chan $argv ${google::api_url}images }