rbot 0.9.9 → 0.9.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/AUTHORS +8 -0
- data/ChangeLog +51 -0
- data/INSTALL +4 -0
- data/README +1 -0
- data/REQUIREMENTS +11 -0
- data/TODO +2 -0
- data/bin/rbot +21 -2
- data/data/rbot/languages/german.lang +4 -1
- data/data/rbot/languages/russian.lang +75 -0
- data/data/rbot/plugins/autoop.rb +42 -51
- data/data/rbot/plugins/bans.rb +205 -0
- data/data/rbot/plugins/bash.rb +56 -0
- data/data/rbot/plugins/chucknorris.rb +74 -0
- data/data/rbot/plugins/chucknorris.yml.gz +0 -0
- data/data/rbot/plugins/deepthoughts.rb +95 -0
- data/data/rbot/plugins/demauro.rb +95 -0
- data/data/rbot/plugins/digg.rb +51 -0
- data/data/rbot/plugins/figlet.rb +24 -0
- data/data/rbot/plugins/forecast.rb +133 -0
- data/data/rbot/plugins/freshmeat.rb +13 -7
- data/data/rbot/plugins/google.rb +2 -0
- data/data/rbot/plugins/grouphug.rb +36 -0
- data/data/rbot/plugins/imdb.rb +92 -0
- data/data/rbot/plugins/insult.rb +8 -1
- data/data/rbot/plugins/iplookup.rb +227 -0
- data/data/rbot/plugins/karma.rb +2 -2
- data/data/rbot/plugins/keywords.rb +470 -0
- data/data/rbot/plugins/lart.rb +132 -146
- data/data/rbot/plugins/lastfm.rb +25 -0
- data/data/rbot/plugins/markov.rb +204 -0
- data/data/rbot/plugins/math.rb +5 -1
- data/data/rbot/plugins/nickserv.rb +71 -11
- data/data/rbot/plugins/opme.rb +19 -19
- data/data/rbot/plugins/quakeauth.rb +2 -2
- data/data/rbot/plugins/quotes.rb +40 -25
- data/data/rbot/plugins/remind.rb +1 -1
- data/data/rbot/plugins/rot13.rb +2 -2
- data/data/rbot/plugins/roulette.rb +49 -15
- data/data/rbot/plugins/rss.rb +585 -0
- data/data/rbot/plugins/rubyurl.rb +39 -0
- data/data/rbot/plugins/seen.rb +2 -1
- data/data/rbot/plugins/slashdot.rb +5 -5
- data/data/rbot/plugins/spell.rb +5 -0
- data/data/rbot/plugins/theyfightcrime.rb +121 -0
- data/data/rbot/plugins/threat.rb +55 -0
- data/data/rbot/plugins/tinyurl.rb +39 -0
- data/data/rbot/plugins/topic.rb +204 -0
- data/data/rbot/plugins/urban.rb +71 -0
- data/data/rbot/plugins/url.rb +399 -4
- data/data/rbot/plugins/wow.rb +123 -0
- data/data/rbot/plugins/wserver.rb +1 -1
- data/data/rbot/templates/levels.rbot +2 -0
- data/lib/rbot/auth.rb +207 -96
- data/lib/rbot/channel.rb +5 -5
- data/lib/rbot/config.rb +125 -24
- data/lib/rbot/dbhash.rb +87 -21
- data/lib/rbot/httputil.rb +181 -13
- data/lib/rbot/ircbot.rb +525 -179
- data/lib/rbot/ircsocket.rb +330 -54
- data/lib/rbot/message.rb +66 -23
- data/lib/rbot/messagemapper.rb +25 -17
- data/lib/rbot/plugins.rb +244 -115
- data/lib/rbot/post-clean.rb +1 -0
- data/lib/rbot/{post-install.rb → post-config.rb} +1 -1
- data/lib/rbot/rbotconfig.rb +29 -14
- data/lib/rbot/registry.rb +111 -72
- data/lib/rbot/rfc2812.rb +208 -197
- data/lib/rbot/timer.rb +4 -0
- data/lib/rbot/utils.rb +2 -2
- metadata +127 -104
- data/data/rbot/plugins/rss.rb.disabled +0 -414
- data/lib/rbot/keywords.rb +0 -433
| @@ -0,0 +1,71 @@ | |
| 1 | 
            +
            require 'cgi'
         | 
| 2 | 
            +
            begin
         | 
| 3 | 
            +
              require 'rubyful_soup'
         | 
| 4 | 
            +
            rescue
         | 
| 5 | 
            +
              warning "could not load rubyful_soup, urban dictionary disabled"
         | 
| 6 | 
            +
              warning "please get it from http://www.crummy.com/software/RubyfulSoup/"
         | 
| 7 | 
            +
              warning "or install it via gem"
         | 
| 8 | 
            +
              return
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
            require 'uri/common'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            class UrbanPlugin < Plugin
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              def help( plugin, topic="")
         | 
| 15 | 
            +
                "urban [word] [n]. Give the [n]th definition of [word] from urbandictionary.com."
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              def privmsg( m )
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                unless(m.params && m.params.length > 0)
         | 
| 21 | 
            +
                  m.reply "incorrect usage: " + help(m.plugin)
         | 
| 22 | 
            +
                  return
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                paramArray = m.params.split(' ')
         | 
| 26 | 
            +
                definitionN = 0
         | 
| 27 | 
            +
                if m.params == 'random' then
         | 
| 28 | 
            +
                  uri = URI.parse( "http://www.urbandictionary.com/random.php" )
         | 
| 29 | 
            +
                else 
         | 
| 30 | 
            +
                  if( paramArray.last.to_i != 0 ) then
         | 
| 31 | 
            +
                    definitionN = paramArray.last.to_i - 1
         | 
| 32 | 
            +
                    query = m.params.chomp( paramArray.last )
         | 
| 33 | 
            +
                    query.rstrip!
         | 
| 34 | 
            +
                  else
         | 
| 35 | 
            +
                    query = m.params
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
                  uri = URI.parse( "http://www.urbandictionary.com/define.php?term=#{ URI.escape query}" )
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                soup = BeautifulSoup.new( @bot.httputil.get_cached( uri ) )
         | 
| 41 | 
            +
                if titleNavi = soup.find_all( 'td', :attrs => { 'class' => 'def_word' } )[0] then
         | 
| 42 | 
            +
                  title = titleNavi.contents
         | 
| 43 | 
            +
                  results = soup.find_all( 'div', :attrs => { 'class' => 'def_p' } )
         | 
| 44 | 
            +
                  # debug PP.pp(results,'')
         | 
| 45 | 
            +
                  output = Array.new
         | 
| 46 | 
            +
                  if results[definitionN] then
         | 
| 47 | 
            +
                    results[definitionN].p.contents.each { |s| output.push( strip_tags( s.to_s ) ) }
         | 
| 48 | 
            +
                    m.reply "\002#{title}\002 - #{output}"
         | 
| 49 | 
            +
                  else
         | 
| 50 | 
            +
                    m.reply "#{query} does not have #{definitionN + 1} definitions."
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                else
         | 
| 53 | 
            +
                  m.reply "#{m.params} not found."
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              def strip_tags(html)
         | 
| 59 | 
            +
                html.gsub(/<.+?>/,'').
         | 
| 60 | 
            +
                gsub(/&/,'&').
         | 
| 61 | 
            +
                gsub(/"/,'"').
         | 
| 62 | 
            +
                gsub(/</,'<').
         | 
| 63 | 
            +
                gsub(/>/,'>').
         | 
| 64 | 
            +
                gsub(/&ellip;/,'...').
         | 
| 65 | 
            +
                gsub(/'/, "'").
         | 
| 66 | 
            +
                gsub("\n",'')
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
            end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            plugin = UrbanPlugin.new
         | 
| 71 | 
            +
            plugin.register( "urban" )
         | 
    
        data/data/rbot/plugins/url.rb
    CHANGED
    
    | @@ -1,17 +1,401 @@ | |
| 1 | 
            +
            require 'net/http'
         | 
| 2 | 
            +
            require 'uri'
         | 
| 3 | 
            +
            require 'cgi'
         | 
| 4 | 
            +
             | 
| 1 5 | 
             
            Url = Struct.new("Url", :channel, :nick, :time, :url)
         | 
| 6 | 
            +
            TITLE_RE = /<\s*?title\s*?>(.+?)<\s*?\/title\s*?>/im
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            UNESCAPE_TABLE = {
         | 
| 9 | 
            +
                'raquo' => '>>',
         | 
| 10 | 
            +
                'quot' => '"',
         | 
| 11 | 
            +
                'micro' => 'u',
         | 
| 12 | 
            +
                'copy' => '(c)',
         | 
| 13 | 
            +
                'trade' => '(tm)',
         | 
| 14 | 
            +
                'reg' => '(R)',
         | 
| 15 | 
            +
                '#174' => '(R)',
         | 
| 16 | 
            +
                '#8220' => '"',
         | 
| 17 | 
            +
                '#8221' => '"',
         | 
| 18 | 
            +
                '#8212' => '--',
         | 
| 19 | 
            +
                '#39' => '\'',
         | 
| 20 | 
            +
            =begin
         | 
| 21 | 
            +
                # extras codes, for future use...
         | 
| 22 | 
            +
                'zwnj' => '‌',
         | 
| 23 | 
            +
                'aring' => '\xe5',
         | 
| 24 | 
            +
                'gt' => '>',
         | 
| 25 | 
            +
                'yen' => '\xa5',
         | 
| 26 | 
            +
                'ograve' => '\xf2',
         | 
| 27 | 
            +
                'Chi' => 'Χ',
         | 
| 28 | 
            +
                'bull' => '•',
         | 
| 29 | 
            +
                'Egrave' => '\xc8',
         | 
| 30 | 
            +
                'Ntilde' => '\xd1',
         | 
| 31 | 
            +
                'upsih' => 'ϒ',
         | 
| 32 | 
            +
                'Yacute' => '\xdd',
         | 
| 33 | 
            +
                'asymp' => '≈',
         | 
| 34 | 
            +
                'radic' => '√',
         | 
| 35 | 
            +
                'otimes' => '⊗',
         | 
| 36 | 
            +
                'nabla' => '∇',
         | 
| 37 | 
            +
                'aelig' => '\xe6',
         | 
| 38 | 
            +
                'oelig' => 'œ',
         | 
| 39 | 
            +
                'equiv' => '≡',
         | 
| 40 | 
            +
                'Psi' => 'Ψ',
         | 
| 41 | 
            +
                'auml' => '\xe4',
         | 
| 42 | 
            +
                'circ' => 'ˆ',
         | 
| 43 | 
            +
                'Acirc' => '\xc2',
         | 
| 44 | 
            +
                'Epsilon' => 'Ε',
         | 
| 45 | 
            +
                'Yuml' => 'Ÿ',
         | 
| 46 | 
            +
                'Eta' => 'Η',
         | 
| 47 | 
            +
                'lt' => '<',
         | 
| 48 | 
            +
                'Icirc' => '\xce',
         | 
| 49 | 
            +
                'Upsilon' => 'Υ',
         | 
| 50 | 
            +
                'ndash' => '–',
         | 
| 51 | 
            +
                'there4' => '∴',
         | 
| 52 | 
            +
                'Prime' => '″',
         | 
| 53 | 
            +
                'prime' => '′',
         | 
| 54 | 
            +
                'psi' => 'ψ',
         | 
| 55 | 
            +
                'Kappa' => 'Κ',
         | 
| 56 | 
            +
                'rsaquo' => '›',
         | 
| 57 | 
            +
                'Tau' => 'Τ',
         | 
| 58 | 
            +
                'darr' => '↓',
         | 
| 59 | 
            +
                'ocirc' => '\xf4',
         | 
| 60 | 
            +
                'lrm' => '‎',
         | 
| 61 | 
            +
                'zwj' => '‍',
         | 
| 62 | 
            +
                'cedil' => '\xb8',
         | 
| 63 | 
            +
                'Ecirc' => '\xca',
         | 
| 64 | 
            +
                'not' => '\xac',
         | 
| 65 | 
            +
                'amp' => '&',
         | 
| 66 | 
            +
                'AElig' => '\xc6',
         | 
| 67 | 
            +
                'oslash' => '\xf8',
         | 
| 68 | 
            +
                'acute' => '\xb4',
         | 
| 69 | 
            +
                'lceil' => '⌈',
         | 
| 70 | 
            +
                'laquo' => '\xab',
         | 
| 71 | 
            +
                'shy' => '\xad',
         | 
| 72 | 
            +
                'rdquo' => '”',
         | 
| 73 | 
            +
                'ge' => '≥',
         | 
| 74 | 
            +
                'Igrave' => '\xcc',
         | 
| 75 | 
            +
                'Ograve' => '\xd2',
         | 
| 76 | 
            +
                'euro' => '€',
         | 
| 77 | 
            +
                'dArr' => '⇓',
         | 
| 78 | 
            +
                'sdot' => '⋅',
         | 
| 79 | 
            +
                'nbsp' => '\xa0',
         | 
| 80 | 
            +
                'lfloor' => '⌊',
         | 
| 81 | 
            +
                'lArr' => '⇐',
         | 
| 82 | 
            +
                'Auml' => '\xc4',
         | 
| 83 | 
            +
                'larr' => '←',
         | 
| 84 | 
            +
                'Atilde' => '\xc3',
         | 
| 85 | 
            +
                'Otilde' => '\xd5',
         | 
| 86 | 
            +
                'szlig' => '\xdf',
         | 
| 87 | 
            +
                'clubs' => '♣',
         | 
| 88 | 
            +
                'diams' => '♦',
         | 
| 89 | 
            +
                'agrave' => '\xe0',
         | 
| 90 | 
            +
                'Ocirc' => '\xd4',
         | 
| 91 | 
            +
                'Iota' => 'Ι',
         | 
| 92 | 
            +
                'Theta' => 'Θ',
         | 
| 93 | 
            +
                'Pi' => 'Π',
         | 
| 94 | 
            +
                'OElig' => 'Œ',
         | 
| 95 | 
            +
                'Scaron' => 'Š',
         | 
| 96 | 
            +
                'frac14' => '\xbc',
         | 
| 97 | 
            +
                'egrave' => '\xe8',
         | 
| 98 | 
            +
                'sub' => '⊂',
         | 
| 99 | 
            +
                'iexcl' => '\xa1',
         | 
| 100 | 
            +
                'frac12' => '\xbd',
         | 
| 101 | 
            +
                'sbquo' => '‚',
         | 
| 102 | 
            +
                'ordf' => '\xaa',
         | 
| 103 | 
            +
                'sum' => '∑',
         | 
| 104 | 
            +
                'prop' => '∝',
         | 
| 105 | 
            +
                'Uuml' => '\xdc',
         | 
| 106 | 
            +
                'ntilde' => '\xf1',
         | 
| 107 | 
            +
                'sup' => '⊃',
         | 
| 108 | 
            +
                'theta' => 'θ',
         | 
| 109 | 
            +
                'prod' => '∏',
         | 
| 110 | 
            +
                'nsub' => '⊄',
         | 
| 111 | 
            +
                'hArr' => '⇔',
         | 
| 112 | 
            +
                'rlm' => '‏',
         | 
| 113 | 
            +
                'THORN' => '\xde',
         | 
| 114 | 
            +
                'infin' => '∞',
         | 
| 115 | 
            +
                'yuml' => '\xff',
         | 
| 116 | 
            +
                'Mu' => 'Μ',
         | 
| 117 | 
            +
                'le' => '≤',
         | 
| 118 | 
            +
                'Eacute' => '\xc9',
         | 
| 119 | 
            +
                'thinsp' => ' ',
         | 
| 120 | 
            +
                'ecirc' => '\xea',
         | 
| 121 | 
            +
                'bdquo' => '„',
         | 
| 122 | 
            +
                'Sigma' => 'Σ',
         | 
| 123 | 
            +
                'fnof' => 'ƒ',
         | 
| 124 | 
            +
                'Aring' => '\xc5',
         | 
| 125 | 
            +
                'tilde' => '˜',
         | 
| 126 | 
            +
                'frac34' => '\xbe',
         | 
| 127 | 
            +
                'emsp' => ' ',
         | 
| 128 | 
            +
                'mdash' => '—',
         | 
| 129 | 
            +
                'uarr' => '↑',
         | 
| 130 | 
            +
                'permil' => '‰',
         | 
| 131 | 
            +
                'Ugrave' => '\xd9',
         | 
| 132 | 
            +
                'rarr' => '→',
         | 
| 133 | 
            +
                'Agrave' => '\xc0',
         | 
| 134 | 
            +
                'chi' => 'χ',
         | 
| 135 | 
            +
                'forall' => '∀',
         | 
| 136 | 
            +
                'eth' => '\xf0',
         | 
| 137 | 
            +
                'rceil' => '⌉',
         | 
| 138 | 
            +
                'iuml' => '\xef',
         | 
| 139 | 
            +
                'gamma' => 'γ',
         | 
| 140 | 
            +
                'lambda' => 'λ',
         | 
| 141 | 
            +
                'harr' => '↔',
         | 
| 142 | 
            +
                'rang' => '〉',
         | 
| 143 | 
            +
                'xi' => 'ξ',
         | 
| 144 | 
            +
                'dagger' => '†',
         | 
| 145 | 
            +
                'divide' => '\xf7',
         | 
| 146 | 
            +
                'Ouml' => '\xd6',
         | 
| 147 | 
            +
                'image' => 'ℑ',
         | 
| 148 | 
            +
                'alefsym' => 'ℵ',
         | 
| 149 | 
            +
                'igrave' => '\xec',
         | 
| 150 | 
            +
                'otilde' => '\xf5',
         | 
| 151 | 
            +
                'Oacute' => '\xd3',
         | 
| 152 | 
            +
                'sube' => '⊆',
         | 
| 153 | 
            +
                'alpha' => 'α',
         | 
| 154 | 
            +
                'frasl' => '⁄',
         | 
| 155 | 
            +
                'ETH' => '\xd0',
         | 
| 156 | 
            +
                'lowast' => '∗',
         | 
| 157 | 
            +
                'Nu' => 'Ν',
         | 
| 158 | 
            +
                'plusmn' => '\xb1',
         | 
| 159 | 
            +
                'Euml' => '\xcb',
         | 
| 160 | 
            +
                'real' => 'ℜ',
         | 
| 161 | 
            +
                'sup1' => '\xb9',
         | 
| 162 | 
            +
                'sup2' => '\xb2',
         | 
| 163 | 
            +
                'sup3' => '\xb3',
         | 
| 164 | 
            +
                'Oslash' => '\xd8',
         | 
| 165 | 
            +
                'Aacute' => '\xc1',
         | 
| 166 | 
            +
                'cent' => '\xa2',
         | 
| 167 | 
            +
                'oline' => '‾',
         | 
| 168 | 
            +
                'Beta' => 'Β',
         | 
| 169 | 
            +
                'perp' => '⊥',
         | 
| 170 | 
            +
                'Delta' => 'Δ',
         | 
| 171 | 
            +
                'loz' => '◊',
         | 
| 172 | 
            +
                'pi' => 'π',
         | 
| 173 | 
            +
                'iota' => 'ι',
         | 
| 174 | 
            +
                'empty' => '∅',
         | 
| 175 | 
            +
                'euml' => '\xeb',
         | 
| 176 | 
            +
                'brvbar' => '\xa6',
         | 
| 177 | 
            +
                'iacute' => '\xed',
         | 
| 178 | 
            +
                'para' => '\xb6',
         | 
| 179 | 
            +
                'micro' => '\xb5',
         | 
| 180 | 
            +
                'cup' => '∪',
         | 
| 181 | 
            +
                'weierp' => '℘',
         | 
| 182 | 
            +
                'uuml' => '\xfc',
         | 
| 183 | 
            +
                'part' => '∂',
         | 
| 184 | 
            +
                'icirc' => '\xee',
         | 
| 185 | 
            +
                'delta' => 'δ',
         | 
| 186 | 
            +
                'omicron' => 'ο',
         | 
| 187 | 
            +
                'upsilon' => 'υ',
         | 
| 188 | 
            +
                'Iuml' => '\xcf',
         | 
| 189 | 
            +
                'Lambda' => 'Λ',
         | 
| 190 | 
            +
                'Xi' => 'Ξ',
         | 
| 191 | 
            +
                'kappa' => 'κ',
         | 
| 192 | 
            +
                'ccedil' => '\xe7',
         | 
| 193 | 
            +
                'Ucirc' => '\xdb',
         | 
| 194 | 
            +
                'cap' => '∩',
         | 
| 195 | 
            +
                'mu' => 'μ',
         | 
| 196 | 
            +
                'scaron' => 'š',
         | 
| 197 | 
            +
                'lsquo' => '‘',
         | 
| 198 | 
            +
                'isin' => '∈',
         | 
| 199 | 
            +
                'Zeta' => 'Ζ',
         | 
| 200 | 
            +
                'supe' => '⊇',
         | 
| 201 | 
            +
                'deg' => '\xb0',
         | 
| 202 | 
            +
                'and' => '∧',
         | 
| 203 | 
            +
                'tau' => 'τ',
         | 
| 204 | 
            +
                'pound' => '\xa3',
         | 
| 205 | 
            +
                'hellip' => '…',
         | 
| 206 | 
            +
                'curren' => '\xa4',
         | 
| 207 | 
            +
                'int' => '∫',
         | 
| 208 | 
            +
                'ucirc' => '\xfb',
         | 
| 209 | 
            +
                'rfloor' => '⌋',
         | 
| 210 | 
            +
                'ensp' => ' ',
         | 
| 211 | 
            +
                'crarr' => '↵',
         | 
| 212 | 
            +
                'ugrave' => '\xf9',
         | 
| 213 | 
            +
                'notin' => '∉',
         | 
| 214 | 
            +
                'exist' => '∃',
         | 
| 215 | 
            +
                'uArr' => '⇑',
         | 
| 216 | 
            +
                'cong' => '≅',
         | 
| 217 | 
            +
                'Dagger' => '‡',
         | 
| 218 | 
            +
                'oplus' => '⊕',
         | 
| 219 | 
            +
                'times' => '\xd7',
         | 
| 220 | 
            +
                'atilde' => '\xe3',
         | 
| 221 | 
            +
                'piv' => 'ϖ',
         | 
| 222 | 
            +
                'ni' => '∋',
         | 
| 223 | 
            +
                'Phi' => 'Φ',
         | 
| 224 | 
            +
                'lsaquo' => '‹',
         | 
| 225 | 
            +
                'Uacute' => '\xda',
         | 
| 226 | 
            +
                'Omicron' => 'Ο',
         | 
| 227 | 
            +
                'ang' => '∠',
         | 
| 228 | 
            +
                'ne' => '≠',
         | 
| 229 | 
            +
                'iquest' => '\xbf',
         | 
| 230 | 
            +
                'eta' => 'η',
         | 
| 231 | 
            +
                'yacute' => '\xfd',
         | 
| 232 | 
            +
                'Rho' => 'Ρ',
         | 
| 233 | 
            +
                'uacute' => '\xfa',
         | 
| 234 | 
            +
                'Alpha' => 'Α',
         | 
| 235 | 
            +
                'zeta' => 'ζ',
         | 
| 236 | 
            +
                'Omega' => 'Ω',
         | 
| 237 | 
            +
                'nu' => 'ν',
         | 
| 238 | 
            +
                'sim' => '∼',
         | 
| 239 | 
            +
                'sect' => '\xa7',
         | 
| 240 | 
            +
                'phi' => 'φ',
         | 
| 241 | 
            +
                'sigmaf' => 'ς',
         | 
| 242 | 
            +
                'macr' => '\xaf',
         | 
| 243 | 
            +
                'minus' => '−',
         | 
| 244 | 
            +
                'Ccedil' => '\xc7',
         | 
| 245 | 
            +
                'ordm' => '\xba',
         | 
| 246 | 
            +
                'epsilon' => 'ε',
         | 
| 247 | 
            +
                'beta' => 'β',
         | 
| 248 | 
            +
                'rArr' => '⇒',
         | 
| 249 | 
            +
                'rho' => 'ρ',
         | 
| 250 | 
            +
                'aacute' => '\xe1',
         | 
| 251 | 
            +
                'eacute' => '\xe9',
         | 
| 252 | 
            +
                'omega' => 'ω',
         | 
| 253 | 
            +
                'middot' => '\xb7',
         | 
| 254 | 
            +
                'Gamma' => 'Γ',
         | 
| 255 | 
            +
                'Iacute' => '\xcd',
         | 
| 256 | 
            +
                'lang' => '〈',
         | 
| 257 | 
            +
                'spades' => '♠',
         | 
| 258 | 
            +
                'rsquo' => '’',
         | 
| 259 | 
            +
                'uml' => '\xa8',
         | 
| 260 | 
            +
                'thorn' => '\xfe',
         | 
| 261 | 
            +
                'ouml' => '\xf6',
         | 
| 262 | 
            +
                'thetasym' => 'ϑ',
         | 
| 263 | 
            +
                'or' => '∨',
         | 
| 264 | 
            +
                'raquo' => '\xbb',
         | 
| 265 | 
            +
                'acirc' => '\xe2',
         | 
| 266 | 
            +
                'ldquo' => '“',
         | 
| 267 | 
            +
                'hearts' => '♥',
         | 
| 268 | 
            +
                'sigma' => 'σ',
         | 
| 269 | 
            +
                'oacute' => '\xf3',
         | 
| 270 | 
            +
            =end
         | 
| 271 | 
            +
            }
         | 
| 2 272 |  | 
| 3 273 | 
             
            class UrlPlugin < Plugin
         | 
| 4 274 | 
             
              BotConfig.register BotConfigIntegerValue.new('url.max_urls',
         | 
| 5 275 | 
             
                :default => 100, :validate => Proc.new{|v| v > 0},
         | 
| 6 276 | 
             
                :desc => "Maximum number of urls to store. New urls replace oldest ones.")
         | 
| 277 | 
            +
              BotConfig.register BotConfigBooleanValue.new('url.display_link_info',
         | 
| 278 | 
            +
                :default => false, 
         | 
| 279 | 
            +
                :desc => "Get the title of any links pasted to the channel and display it (also tells if the link is broken or the site is down)")
         | 
| 7 280 |  | 
| 8 281 | 
             
              def initialize
         | 
| 9 282 | 
             
                super
         | 
| 10 283 | 
             
                @registry.set_default(Array.new)
         | 
| 11 284 | 
             
              end
         | 
| 285 | 
            +
             | 
| 12 286 | 
             
              def help(plugin, topic="")
         | 
| 13 287 | 
             
                "urls [<max>=4] => list <max> last urls mentioned in current channel, urls search [<max>=4] <regexp> => search for matching urls. In a private message, you must specify the channel to query, eg. urls <channel> [max], urls search <channel> [max] <regexp>"
         | 
| 14 288 | 
             
              end
         | 
| 289 | 
            +
             | 
| 290 | 
            +
              def unescape_title(htmldata)
         | 
| 291 | 
            +
                # first pass -- let CGI try to attack it...
         | 
| 292 | 
            +
                htmldata = CGI::unescapeHTML htmldata
         | 
| 293 | 
            +
                
         | 
| 294 | 
            +
                # second pass -- destroy the remaining bits...
         | 
| 295 | 
            +
                htmldata.gsub(/(&(.+?);)/) {
         | 
| 296 | 
            +
                    symbol = $2
         | 
| 297 | 
            +
                    
         | 
| 298 | 
            +
                    # remove the 0-paddng from unicode integers
         | 
| 299 | 
            +
                    if symbol =~ /#(.+)/
         | 
| 300 | 
            +
                        symbol = "##{$1.to_i.to_s}"
         | 
| 301 | 
            +
                    end
         | 
| 302 | 
            +
                    
         | 
| 303 | 
            +
                    # output the symbol's irc-translated character, or a * if it's unknown
         | 
| 304 | 
            +
                    UNESCAPE_TABLE[symbol] || '*'
         | 
| 305 | 
            +
                }
         | 
| 306 | 
            +
              end
         | 
| 307 | 
            +
             | 
| 308 | 
            +
              def get_title_from_html(pagedata)
         | 
| 309 | 
            +
                return unless TITLE_RE.match(pagedata)
         | 
| 310 | 
            +
                title = $1.strip.gsub(/\s*\n+\s*/, " ")
         | 
| 311 | 
            +
                title = unescape_title title
         | 
| 312 | 
            +
                title = title[0..255] if title.length > 255
         | 
| 313 | 
            +
                "[Link Info] title: #{title}"
         | 
| 314 | 
            +
              end
         | 
| 315 | 
            +
             | 
| 316 | 
            +
              def read_data_from_response(response, amount)
         | 
| 317 | 
            +
                
         | 
| 318 | 
            +
                amount_read = 0
         | 
| 319 | 
            +
                chunks = []
         | 
| 320 | 
            +
                
         | 
| 321 | 
            +
                response.read_body do |chunk|   # read body now
         | 
| 322 | 
            +
                  
         | 
| 323 | 
            +
                  amount_read += chunk.length
         | 
| 324 | 
            +
                  
         | 
| 325 | 
            +
                  if amount_read > amount
         | 
| 326 | 
            +
                    amount_of_overflow = amount_read - amount
         | 
| 327 | 
            +
                    chunk = chunk[0...-amount_of_overflow]
         | 
| 328 | 
            +
                  end
         | 
| 329 | 
            +
                  
         | 
| 330 | 
            +
                  chunks << chunk
         | 
| 331 | 
            +
             | 
| 332 | 
            +
                  break if amount_read >= amount
         | 
| 333 | 
            +
                  
         | 
| 334 | 
            +
                end
         | 
| 335 | 
            +
                
         | 
| 336 | 
            +
                chunks.join('')
         | 
| 337 | 
            +
                
         | 
| 338 | 
            +
              end
         | 
| 339 | 
            +
             | 
| 340 | 
            +
             | 
| 341 | 
            +
              def get_title_for_url(uri_str, depth=10)
         | 
| 342 | 
            +
                # This god-awful mess is what the ruby http library has reduced me to.
         | 
| 343 | 
            +
                # Python's HTTP lib is so much nicer. :~(
         | 
| 344 | 
            +
                
         | 
| 345 | 
            +
                if depth == 0
         | 
| 346 | 
            +
                    raise "Error: Maximum redirects hit."
         | 
| 347 | 
            +
                end
         | 
| 348 | 
            +
                
         | 
| 349 | 
            +
                debug "+ Getting #{uri_str}"
         | 
| 350 | 
            +
                url = URI.parse(uri_str)
         | 
| 351 | 
            +
                return if url.scheme !~ /https?/
         | 
| 352 | 
            +
             | 
| 353 | 
            +
                title = nil
         | 
| 354 | 
            +
                
         | 
| 355 | 
            +
                debug "+ connecting to #{url.host}:#{url.port}"
         | 
| 356 | 
            +
                http = @bot.httputil.get_proxy(url)
         | 
| 357 | 
            +
                http.start { |http|
         | 
| 358 | 
            +
                  url.path = '/' if url.path == ''
         | 
| 359 | 
            +
             | 
| 360 | 
            +
                  http.request_get(url.path, "User-Agent" => "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)") { |response|
         | 
| 361 | 
            +
                    
         | 
| 362 | 
            +
                    case response
         | 
| 363 | 
            +
                      when Net::HTTPRedirection, Net::HTTPMovedPermanently then
         | 
| 364 | 
            +
                        # call self recursively if this is a redirect
         | 
| 365 | 
            +
                        redirect_to = response['location']  || './'
         | 
| 366 | 
            +
                        debug "+ redirect location: #{redirect_to.inspect}"
         | 
| 367 | 
            +
                        url = URI.join url.to_s, redirect_to
         | 
| 368 | 
            +
                        debug "+ whee, redirecting to #{url.to_s}!"
         | 
| 369 | 
            +
                        return get_title_for_url(url.to_s, depth-1)
         | 
| 370 | 
            +
                      when Net::HTTPSuccess then
         | 
| 371 | 
            +
                        if response['content-type'] =~ /^text\//
         | 
| 372 | 
            +
                          # since the content is 'text/*' and is small enough to
         | 
| 373 | 
            +
                          # be a webpage, retrieve the title from the page
         | 
| 374 | 
            +
                          debug "+ getting #{url.request_uri}"
         | 
| 375 | 
            +
                          data = read_data_from_response(response, 50000)
         | 
| 376 | 
            +
                          return get_title_from_html(data)
         | 
| 377 | 
            +
                        else
         | 
| 378 | 
            +
                          # content doesn't have title, just display info.
         | 
| 379 | 
            +
                          size = response['content-length'].gsub(/(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/,'\1,\2')
         | 
| 380 | 
            +
                          return "[Link Info] type: #{response['content-type']}#{size ? ", size: #{size} bytes" : ""}"
         | 
| 381 | 
            +
                        end
         | 
| 382 | 
            +
                      when Net::HTTPClientError then
         | 
| 383 | 
            +
                        return "[Link Info] Error getting link (#{response.code} - #{response.message})"
         | 
| 384 | 
            +
                      when Net::HTTPServerError then
         | 
| 385 | 
            +
                        return "[Link Info] Error getting link (#{response.code} - #{response.message})"
         | 
| 386 | 
            +
                      else
         | 
| 387 | 
            +
                        return nil
         | 
| 388 | 
            +
                    end # end of "case response"
         | 
| 389 | 
            +
                      
         | 
| 390 | 
            +
                  } # end of request block
         | 
| 391 | 
            +
                } # end of http start block
         | 
| 392 | 
            +
             | 
| 393 | 
            +
                return title
         | 
| 394 | 
            +
                
         | 
| 395 | 
            +
              rescue SocketError => e
         | 
| 396 | 
            +
                return "[Link Info] Error connecting to site (#{e.message})"
         | 
| 397 | 
            +
              end
         | 
| 398 | 
            +
             | 
| 15 399 | 
             
              def listen(m)
         | 
| 16 400 | 
             
                return unless m.kind_of?(PrivMessage)
         | 
| 17 401 | 
             
                return if m.address?
         | 
| @@ -20,10 +404,21 @@ class UrlPlugin < Plugin | |
| 20 404 | 
             
                  if m.message =~ /((f|ht)tps?:\/\/.*?)(?:\s+|$)/
         | 
| 21 405 | 
             
                    urlstr = $1
         | 
| 22 406 | 
             
                    list = @registry[m.target]
         | 
| 407 | 
            +
             | 
| 408 | 
            +
                    if @bot.config['url.display_link_info']
         | 
| 409 | 
            +
                      debug "Getting title for #{urlstr}..."
         | 
| 410 | 
            +
                      title = get_title_for_url urlstr
         | 
| 411 | 
            +
                      if title
         | 
| 412 | 
            +
                        m.reply title
         | 
| 413 | 
            +
                        debug "Title found!"
         | 
| 414 | 
            +
                      else
         | 
| 415 | 
            +
                        debug "Title not found!"
         | 
| 416 | 
            +
                      end        
         | 
| 417 | 
            +
                    end
         | 
| 418 | 
            +
                
         | 
| 23 419 | 
             
                    # check to see if this url is already listed
         | 
| 24 | 
            -
                    return if list.find {|u|
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                    }
         | 
| 420 | 
            +
                    return if list.find {|u| u.url == urlstr }
         | 
| 421 | 
            +
                    
         | 
| 27 422 | 
             
                    url = Url.new(m.target, m.sourcenick, Time.new, urlstr)
         | 
| 28 423 | 
             
                    debug "#{list.length} urls so far"
         | 
| 29 424 | 
             
                    if list.length > @bot.config['url.max_urls']
         | 
| @@ -58,7 +453,7 @@ class UrlPlugin < Plugin | |
| 58 453 | 
             
                string = params[:string]
         | 
| 59 454 | 
             
                max = 10 if max > 10
         | 
| 60 455 | 
             
                max = 1 if max < 1
         | 
| 61 | 
            -
                regex = Regexp.new(string)
         | 
| 456 | 
            +
                regex = Regexp.new(string, Regexp::IGNORECASE)
         | 
| 62 457 | 
             
                list = @registry[channel].find_all {|url|
         | 
| 63 458 | 
             
                  regex.match(url.url) || regex.match(url.nick)
         | 
| 64 459 | 
             
                }
         |