Advertisement
Guest User

Untitled

a guest
Jul 17th, 2018
235
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
TCL 17.96 KB | None | 0 0
  1. # Script to grab titles from webpages
  2. # Updated version by teel @ IRCnet
  3. #
  4. # https://github.com/teeli/urltitle
  5. #
  6. # Detects URL from IRC channels and prints out the title
  7. #
  8. # Version Log:
  9. # 0.10     Fixed XPath parsing error and added regex fallback if XPath fails
  10. # 0.09     HTTPs redirects, case-insensitive HTTP header fix, other small bug fixes
  11. # 0.08     Changed putserv to puthelp to queue the messages
  12. # 0.07     Added Content-Type check (text/html only) and exceptino handling for tDom with a fallback to
  13. #          regexp if tDom fails.
  14. # 0.06     Added XPATH support to title parsing (only if tdom package is available)
  15. # 0.05     Added SNI support for TLS (with TLS version check)
  16. # 0.04     HTML parsing for titles added
  17. # 0.03c    HTTPS support is now optional and will be automatically dropeed if TCL TSL package does not exist
  18. # 0.03b    Some formatting
  19. # 0.03     HTTPS support
  20. # 0.02     Updated version by teel. Added support for redirects, trimmed titles (remove extra whitespaces),
  21. #          some optimization
  22. # 0.01a    Original version by rosc
  23. #
  24. ################################################################################################################
  25. #
  26. # Original script:
  27. # Copyright C.Leonhardt (rosc2112 at yahoo com) Aug.11.2007
  28. # http://members.dandy.net/~fbn/urltitle.tcl.txt
  29. # Loosely based on the tinyurl script by Jer and other bits and pieces of my own..
  30. #
  31. ################################################################################################################
  32. #
  33. # Usage:
  34. #
  35. # 1) Set the configs below
  36. # 2) .chanset #channelname +urltitle        ;# enable script
  37. # 3) .chanset #channelname +logurltitle     ;# enable logging
  38. # Then just input a url in channel and the script will retrieve the title from the corresponding page.
  39. #
  40. ################################################################################################################
  41.  
  42. namespace eval UrlTitle {
  43.   # CONFIG
  44.   variable ignore "bdkqr|dkqr" ;# User flags script will ignore input from
  45.   variable length 5            ;# minimum url length to trigger channel eggdrop use
  46.   variable delay 1             ;# minimum seconds to wait before another eggdrop use
  47.   variable timeout 5000        ;# geturl timeout (1/1000ths of a second)
  48.   variable fetchLimit 5        ;# How many times to process redirects before erroring
  49.  
  50.   # BINDS
  51.   bind pubm "-|-" {*://*} UrlTitle::handler
  52.   setudef flag urltitle        ;# Channel flag to enable script.
  53.   setudef flag logurltitle     ;# Channel flag to enable logging of script.
  54.  
  55.   # INTERNAL
  56.   variable last 1              ;# Internal variable, stores time of last eggdrop use, don't change..
  57.   variable scriptVersion 0.10
  58.  
  59.   # PACKAGES
  60.   package require http         ;# You need the http package..
  61.   variable httpsSupport false
  62.   variable htmlSupport false
  63.   variable tdomSupport false
  64.   if {![catch {variable tlsVersion [package require tls]}]} {
  65.     set httpsSupport true
  66.     if {[package vcompare $tlsVersion 1.6.4] < 0} {
  67.       putlog "UrlTitle: TCL TLS version 1.6.4 or newer is required for proper https support (SNI)"
  68.     }
  69.   }
  70.   if {![catch {package require htmlparse}]} {
  71.     set htmlSupport true
  72.   }
  73.   if {![catch {package require tdom}]} {
  74.     set tdomSupport true
  75.   }
  76.  
  77.   # Enable SNI support for TLS if suitable TLS version is installed
  78.   proc socket {args} {
  79.     variable tlsVersion
  80.     set opts [lrange $args 0 end-2]
  81.     set host [lindex $args end-1]
  82.     set port [lindex $args end]
  83.  
  84.     if {[package vcompare $tlsVersion 1.7.11] >= 0} {
  85.       # tls version 1.7.11 should support autoservername
  86.       ::tls::socket -autoservername true {*}$opts $host $port
  87.     } elseif {[package vcompare $tlsVersion 1.6.4] >= 0} {
  88.       ::tls::socket -ssl3 false -ssl2 false -tls1 true -servername $host {*}$opts $host $port
  89.     } else {
  90.       # default fallback without servername (SNI certs will not work)
  91.       ::tls::socket -ssl3 false -ssl2 false -tls1 true {*}$opts $host $port
  92.     }
  93.   }
  94.  
  95.   proc handler {nick host user chan text} {
  96.     variable httpsSupport
  97.     variable htmlSupport
  98.     variable delay
  99.     variable last
  100.     variable ignore
  101.     variable length
  102.     set unixtime [clock seconds]
  103.     if {[channel get $chan urltitle] && ($unixtime - $delay) > $last && (![matchattr $user $ignore])} {
  104.       foreach word [split $text] {
  105.         if {[string length $word] >= $length && [regexp {^(f|ht)tp(s|)://} $word] && \
  106.             ![regexp {://([^/:]*:([^/]*@|\d+(/|$))|.*/\.)} $word]} {
  107.           set last $unixtime
  108.           # enable https if supported
  109.           if {$httpsSupport} {
  110.             ::http::register https 443 [list UrlTitle::socket]
  111.           }
  112.           set urtitle [UrlTitle::parse $word]
  113.           if {$htmlSupport} {
  114.             set urtitle [::htmlparse::mapEscapes $urtitle]
  115.           }
  116.           # unregister https if supported
  117.           if {$httpsSupport} {
  118.             ::http::unregister https
  119.           }
  120.           if {$urtitle eq ""} {
  121.             break
  122.           }
  123.           if {[string length $urtitle]} {
  124.  
  125.             set html_mapping {
  126.               &lsquo; '
  127.              &rsquo; '
  128.               &#8217; '
  129.               &#8211; '
  130.               &apos; '
  131.              &#10; " "
  132.              &#010; " "
  133.              &sbquo; ‚
  134.              &ldquo; “
  135.              &rdquo; ”
  136.              &bdquo; „
  137.              &dagger; †
  138.              &Dagger; ‡
  139.              &permil; ‰
  140.              &lsaquo; ‹
  141.              &rsaquo; ›
  142.              &spades; ♠
  143.              &clubs; ♣
  144.              &hearts; ♥
  145.              &diams; ♦
  146.              &oline; ‾
  147.              &#8592; ←
  148.              &larr; ←
  149.              &#8593; ↑
  150.              &uarr; ↑
  151.              &#8594; →
  152.              &rarr; →
  153.              &#8595; ↓
  154.              &darr; ↓
  155.              &#8598; ↖
  156.              &nwarr; ↖
  157.              &#8599; ↗
  158.              &nearr; ↗
  159.              &#8601; ↙
  160.              &swarr; ↙
  161.              &#8600; ↘
  162.              &searr; ↘
  163.              &#9650; ▲
  164.              &#x25B2; ▲
  165.              &#9652; ▴
  166.              &#x25B4; ▴
  167.              &#9654; ▶
  168.              &#x25B6; ▶
  169.              &#9656; ▸
  170.              &#x25B8; ▸
  171.              &#9658; ►
  172.              &#x25BA; ►
  173.              &#9660; ▼
  174.              &#x25BC; ▼
  175.              &#9662; ▾
  176.              &#x25BE; ▾
  177.              &#9664; ◀
  178.              &#x25C0; ◀
  179.              &#9666; ◂
  180.              &#x25C2; ◂
  181.              &#9668; ◄
  182.              &#x25C4; ◄
  183.              &#x2122; ™
  184.              &#x27; '
  185.               &trade;
  186.               &#00; -
  187.               &#000; -
  188.               &#33; !
  189.               &#033; !
  190.               &#34; {"}
  191.               &#034; {"}
  192.               &quot; {"}
  193.              &#35; {#}
  194.              &#035; {#}
  195.              &#36; $
  196.              &#036; $
  197.              &#37; %
  198.              &#037; %
  199.              &#38; &
  200.              &#038; &
  201.              &amp; &
  202.              &#39; '
  203.              &#039; '
  204.              &#40; (
  205.              &#040; (
  206.              &#41; )
  207.              &#041; )
  208.              &#42; *
  209.              &#042; *
  210.              &#43; +
  211.              &#043; +
  212.              &#44; ,
  213.              &#044; ,
  214.              &#45; -
  215.              &#045; -
  216.              &#46; .
  217.              &#046; .
  218.              &#47; /
  219.              &#047; /
  220.              &frasl; /
  221.              &#48; -
  222.              &#048; -
  223.              &#58; :
  224.              &#058; :
  225.              &#59; ;
  226.              &#059; ;
  227.              &#60; <
  228.              &#060; <
  229.              &lt; <
  230.              &#61; =
  231.              &#061; =
  232.              &#62; >
  233.              &#062; >
  234.              &gt; >
  235.              &#63; ?
  236.              &#063; ?
  237.              &#64; @
  238.              &#064; @
  239.              &#65; -
  240.              &#065; -
  241.              &#91; [
  242.              &#091; [
  243.              &#92; \
  244.              &#092; \
  245.              &#93; ]
  246.              &#093; ]
  247.              &#94; ^
  248.              &#094; ^
  249.              &#95; _
  250.              &#095; _
  251.              &#96; `
  252.              &#096; `
  253.              &#97; -
  254.              &#097; -
  255.              &#123; {
  256.              &#124; |
  257.              &#125; }
  258.              &#126; ~
  259.              &#133; …
  260.              &hellip; …
  261.              &#150; –
  262.              &ndash; –
  263.              &#151; —
  264.              &mdash; —
  265.              &#152; -
  266.              &#159; &
  267.              &#160; &nbsp;
  268.              &#161; ¡
  269.              &iexcl; ¡
  270.              &#162; ¢
  271.              &cent; ¢
  272.              &#163; £
  273.              &pound; £
  274.              &#164; ¤
  275.              &curren; ¤
  276.              &#165; ¥
  277.              &yen; ¥
  278.              &#166; ¦
  279.              &brvbar; ¦
  280.              &brkbar; ¦
  281.              &#167; §
  282.              &sect; §
  283.              &#168; ¨
  284.              &uml; ¨
  285.              &die; ¨
  286.              &#169; ©
  287.              &copy; ©
  288.              &#170; ª
  289.              &ordf; ª
  290.              &#171; «
  291.              &laquo; «
  292.              &#172; ¬
  293.              &not; ¬
  294.              &#174; ®
  295.              &reg; ®
  296.              &#175; ¯
  297.              &macr; ¯
  298.              &hibar; ¯
  299.              &#176; °
  300.              &deg; °
  301.              &#177; ±
  302.              &plusmn; ±
  303.              &#178; ²
  304.              &sup2; ²
  305.              &#179; ³
  306.              &sup3; ³
  307.              &#180; ´
  308.              &acute; ´
  309.              &#181; µ
  310.              &micro; µ
  311.              &#182; ¶
  312.              &para; ¶
  313.              &#183; ·
  314.              &middot; ·
  315.              &#184; ¸
  316.              &cedil; ¸
  317.              &#185; ¹
  318.              &sup1; ¹
  319.              &#186; º
  320.              &ordm; º
  321.              &#187; »
  322.              &raquo; »
  323.              &#188; ¼
  324.              &frac14; ¼
  325.              &#189; ½
  326.              &frac12; ½
  327.              &#190; ¾
  328.              &frac34; ¾
  329.              &#191; ¿
  330.              &iquest; ¿
  331.              &#192; À
  332.              &Agrave; À
  333.              &#193; Á
  334.              &Aacute; Á
  335.              &#194; Â
  336.              &Acirc; Â
  337.              &#195; Ã
  338.              &Atilde; Ã
  339.              &#196; Ä
  340.              &Auml; Ä
  341.              &#197; Å
  342.              &Aring; Å
  343.              &#198; Æ
  344.              &AElig; Æ
  345.              &#199; Ç
  346.              &Ccedil; Ç
  347.              &#200; È
  348.              &Egrave; È
  349.              &#201; É
  350.              &Eacute; É
  351.              &#202; Ê
  352.              &Ecirc; Ê
  353.              &#203; Ë
  354.              &Euml; Ë
  355.              &#204; Ì
  356.              &Igrave; Ì
  357.              &#205; Í
  358.              &Iacute; Í
  359.              &#206; Î
  360.              &Icirc; Î
  361.              &#207; Ï
  362.              &Iuml; Ï
  363.              &#208; Ð
  364.              &ETH; Ð
  365.              &#209; Ñ
  366.              &Ntilde; Ñ
  367.              &#210; Ò
  368.              &Ograve; Ò
  369.              &#211; Ó
  370.              &Oacute; Ó
  371.              &#212; Ô
  372.              &Ocirc; Ô
  373.              &#213; Õ
  374.              &Otilde; Õ
  375.              &#214; Ö
  376.              &Ouml; Ö
  377.              &#215; ×
  378.              &times; ×
  379.              &#216; Ø
  380.              &Oslash; Ø
  381.              &#217; Ù
  382.              &Ugrave; Ù
  383.              &#218; Ú
  384.              &Uacute; Ú
  385.              &#219; Û
  386.              &Ucirc; Û
  387.              &#220; Ü
  388.              &Uuml; Ü
  389.              &#221; Ý
  390.              &Yacute; Ý
  391.              &#222; Þ
  392.              &THORN; Þ
  393.              &#223; ß
  394.              &szlig; ß
  395.              &#224; à
  396.              &agrave; à
  397.              &#225; á
  398.              &aacute; á
  399.              &#226; â
  400.              &acirc; â
  401.              &#227; ã
  402.              &atilde; ã
  403.              &#228; ä
  404.              &auml; ä
  405.              &#229; å
  406.              &aring; å
  407.              &#230; æ
  408.              &aelig; æ
  409.              &#231; ç
  410.              &ccedil; ç
  411.              &#232; è
  412.              &egrave; è
  413.              &#233; é
  414.              &eacute; é
  415.              &#234; ê
  416.              &ecirc; ê
  417.              &#235; ë
  418.              &euml; ë
  419.              &#236; ì
  420.              &igrave; ì
  421.              &#237; í
  422.              &iacute; í
  423.              &#238; î
  424.              &icirc; î
  425.              &#239; ï
  426.              &iuml; ï
  427.              &#240; ð
  428.              &eth; ð
  429.              &#241; ñ
  430.              &ntilde; ñ
  431.              &#242; ò
  432.              &ograve; ò
  433.              &#243; ó
  434.              &oacute; ó
  435.              &#244; ô
  436.              &ocirc; ô
  437.              &#245; õ
  438.              &otilde; õ
  439.              &#246; ö
  440.              &ouml; ö
  441.              &#247; ÷
  442.              &divide; ÷
  443.              &#248; ø
  444.              &oslash; ø
  445.              &#249; ù
  446.              &ugrave; ù
  447.              &#250; ú
  448.              &uacute; ú
  449.              &#251; û
  450.              &ucirc; û
  451.              &#252; ü
  452.              &uuml; ü
  453.              &#253; ý
  454.              &yacute; ý
  455.              &#254; þ
  456.              &thorn; þ
  457.              &#255; ÿ
  458.              &yuml; ÿ
  459.              &Alpha; Α
  460.              &alpha; α
  461.              &Beta; Β
  462.              &beta; β
  463.              &Gamma; Γ
  464.              &gamma; γ
  465.              &Delta; Δ
  466.              &delta; δ
  467.              &Epsilon; Ε
  468.              &epsilon; ε
  469.              &Zeta; Ζ
  470.              &zeta; ζ
  471.              &Eta; Η
  472.              &eta; η
  473.              &Theta; Θ
  474.              &theta; θ
  475.              &Iota; Ι
  476.              &iota; ι
  477.              &Kappa; Κ
  478.              &kappa; κ
  479.              &Lambda; Λ
  480.              &lambda; λ
  481.              &Mu; Μ
  482.              &mu; μ
  483.              &Nu; Ν
  484.              &nu; ν
  485.              &Xi; Ξ
  486.              &xi; ξ
  487.              &Omicron; Ο
  488.              &omicron; ο
  489.              &Pi; Π
  490.              &pi; π
  491.              &Rho; Ρ
  492.              &rho; ρ
  493.              &Sigma; Σ
  494.              &sigma; σ
  495.              &Tau; Τ
  496.              &tau; τ
  497.              &Upsilon; Υ
  498.              &upsilon; υ
  499.              &Phi; Φ
  500.              &phi; φ
  501.              &Chi; Χ
  502.              &chi; χ
  503.              &Psi; Ψ
  504.              &psi; ψ
  505.              &Omega; Ω
  506.              &omega; ω
  507.              &#9679; ●
  508.              &#8226; •
  509.              &#8734; ∞
  510.              &infin; ∞
  511.            }
  512.            set tit [string map $html_mapping $urtitle]
  513.            puthelp "PRIVMSG $chan :\002$tit"
  514.          }
  515.          break
  516.        }
  517.      }
  518.    }
  519.    # change to return 0 if you want the pubm trigger logged additionally..
  520.    return 1
  521.  }
  522.  
  523.  # General HTTP redirect handler
  524.  proc Fetch {url args} {
  525.    variable fetchLimit
  526.    for {set count 0} {$count < $fetchLimit} {incr count} {
  527.      set token [::http::geturl $url {*}$args]
  528.      if {[::http::status $token] ne "ok" || ![string match 3?? [::http::ncode $token]]} {
  529.        break
  530.      }
  531.      set meta [::http::meta $token]
  532.      if {[dict exists $meta Location]} {
  533.        set url [dict get $meta Location]
  534.      }
  535.      if {[dict exists $meta location]} {
  536.        set url [dict get $meta location]
  537.      }
  538.      ::http::cleanup $token
  539.    }
  540.    return $token
  541.  }
  542.  
  543.  proc parseTitleXPath {data} {
  544.    set title ""
  545.    if {[catch {set doc [dom parse -html -simple $data]} results]} {
  546.      # fallback to regex parsing if tdom fails
  547.      set title [parseTitleRegex $data]
  548.    } else {
  549.      # parse dom
  550.      set root [$doc documentElement]
  551.      set node [$root selectNodes {//head/title/text()}]
  552.      if {$node != ""} {
  553.        # return title if XPath was able to parse it
  554.        set title [$node data]
  555.      } else {
  556.        # Fallback to regex if XPath failed
  557.        set title [parseTitleRegex $data]
  558.      }
  559.    }
  560.  }
  561.  
  562.  proc parseTitleRegex {data} {
  563.    set title ""
  564.    # fallback to regex parsing if tdom fails
  565.    regexp -nocase {<title.*>(.*?)</title>} $data match title
  566.    set title [regsub -all -nocase {\s+} $title " "]
  567.    return $title
  568.  }
  569.  
  570.  proc parse {url} {
  571.    variable timeout
  572.    variable tdomSupport
  573.    set title ""
  574.    if {[info exists url] && [string length $url]} {
  575.      if {[catch {set http [Fetch $url -timeout $timeout]} results]} {
  576.        putlog "Connection to $url failed"
  577.        putlog "Error: $results"
  578.      } else {
  579.        if { [::http::status $http] == "ok" } {
  580.          set data [::http::data $http]
  581.          set status [::http::code $http]
  582.          set meta [::http::meta $http]
  583.  
  584.          # only parse html files for titles
  585.          if {
  586.            ([dict exists $meta Content-Type] && [string first "text/html" [dict get $meta Content-Type]] >= 0) ||
  587.            ([dict exists $meta content-type] && [string first "text/html" [dict get $meta content-type]] >= 0)
  588.          } {
  589.            switch -regexp -- $status {
  590.              "HTTP.*200.*" {
  591.                if {$tdomSupport} {
  592.                  # use XPATH if tdom is supported
  593.                  set title [parseTitleXPath $data]
  594.                } else {
  595.                  # fallback to regex parsing if tdom is not enabled
  596.                  set title [parseTitleRegex $data]
  597.                }
  598.              }
  599.              "HTTP\/[0-1]\.[0-1].3.*" {
  600.                if {[dict exists $meta Location]} {
  601.                  set title [UrlTitle::parse [dict get $meta Location]]
  602.                }
  603.                if {[dict exists $meta location]} {
  604.                  set title [UrlTitle::parse [dict get $meta location]]
  605.                }
  606.              }
  607.            }
  608.          }
  609.        } else {
  610.          putlog "Connection to $url failed"
  611.        }
  612.        ::http::cleanup $http
  613.      }
  614.    }
  615.    return $title
  616.  }
  617.  
  618.  
  619.  putlog "Initialized Url Title Grabber v$scriptVersion"
  620. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement