]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - lib/rbot/core/utils/extends.rb
plugin(search): fix search and gcalc, closes #28, #29
[user/henk/code/ruby/rbot.git] / lib / rbot / core / utils / extends.rb
index fc7119fa8c7df89d4bbf969ac88733e28d479635..08278261fdfa435b21991a069cd66cb7664b9d31 100644 (file)
@@ -108,22 +108,33 @@ class ::Array
     self.delete_at(index)
   end
 
-  # shuffle and shuffle! are defined in Ruby >= 1.8.7
-
-  # This method returns a new array with the same items as
-  # the receiver, but shuffled
-  unless method_defined? :shuffle
-    def shuffle
-      sort_by { rand }
+  # This method deletes a given object _el_ if it's found at the given
+  # position _pos_. The position can be either an integer or a range.
+  def delete_if_at(el, pos)
+    idx = self.index(el)
+    if pos === idx
+      self.delete_at(idx)
+    else
+      nil
     end
   end
 
-  # This method shuffles the items in the array
-  unless method_defined? :shuffle!
-    def shuffle!
-      replace shuffle
+  # Taken from Ruby backports:
+  # shuffle and shuffle! are defined in Ruby >= 1.8.7
+
+  # This method returns a new array with the
+  # same items as the receiver, but shuffled
+  def shuffle
+    dup.shuffle!
+  end unless method_defined? :shuffle
+
+  def shuffle!
+    size.times do |i|
+      r = i + Kernel.rand(size - i)
+      self[i], self[r] = self[r], self[i]
     end
-  end
+    self
+  end unless method_defined? :shuffle!
 end
 
 module ::Enumerable
@@ -245,6 +256,29 @@ class ::String
       warning "unknown :a_href option #{val} passed to ircify_html" if val
     end
 
+    # If opts[:img] is defined, it should be a String. Each image
+    # will be replaced by the string itself, replacing occurrences of
+    # %{alt} %{dimensions} and %{src} with the alt text, image dimensions
+    # and URL
+    if val = opts[:img]
+      if val.kind_of? String
+        txt.gsub!(/<img\s+(.*?)\s*\/?>/) do |imgtag|
+          attrs = Hash.new
+          imgtag.scan(/([[:alpha:]]+)\s*=\s*(['"])?(.*?)\2/) do |key, quote, value|
+            k = key.downcase.intern rescue 'junk'
+            attrs[k] = value
+          end
+          attrs[:alt] ||= attrs[:title]
+          attrs[:width] ||= '...'
+          attrs[:height] ||= '...'
+          attrs[:dimensions] ||= "#{attrs[:width]}x#{attrs[:height]}"
+          val % attrs
+        end
+      else
+        warning ":img option is not a string"
+      end
+    end
+
     # Paragraph and br tags are converted to whitespace
     txt.gsub!(/<\/?(p|br)(?:\s+[^>]*)?\s*\/?\s*>/i, ' ')
     txt.gsub!("\n", ' ')
@@ -307,7 +341,7 @@ class ::String
   # This method will strip all HTML crud from the receiver
   #
   def riphtml
-    self.gsub(/<[^>]+>/, '').gsub(/&amp;/,'&').gsub(/&quot;/,'"').gsub(/&lt;/,'<').gsub(/&gt;/,'>').gsub(/&ellip;/,'...').gsub(/&apos;/, "'").gsub("\n",'')
+    Utils.decode_html_entities(self.gsub("\n",' ').gsub(/<\s*br\s*\/?\s*>/, ' ').gsub(/<[^>]+>/, '')).gsub(/\s+/,' ')
   end
 
   # This method tries to find an HTML title in the string,
@@ -336,8 +370,29 @@ class ::String
       "#{pre}#{self}#{post}"
     end
   end
-end
 
+  # Format a string using IRC colors
+  #
+  def colorformat
+    txt = self.dup
+
+    txt.gsub!(/\*([^\*]+)\*/, Bold + '\\1' + NormalText)
+
+    return txt
+  end
+  
+  # Removes non-ASCII symbols from string
+  def remove_nonascii(replace='')
+    encoding_options = {
+      :invalid           => :replace,  # Replace invalid byte sequences
+      :undef             => :replace,  # Replace anything not defined in ASCII
+      :replace           => replace,   
+      :universal_newline => true       # Always break lines with \n
+    }
+
+    self.encode(Encoding.find('ASCII'), encoding_options)
+  end
+end
 
 # Extensions to the Regexp class, with some common and/or complex regular
 # expressions.
@@ -476,12 +531,16 @@ module ::Irc
           new_m = o[:class].new(o[:bot], o[:server], o[:source], o[:target], string)
           new_m.recurse_depth = o[:depth]
           if from
-            # the created message will reply to the originating message
+            # the created message will reply to the originating message, but we
+            # must remember to set 'replied' on the fake message too, to
+            # prevent infinite loops that could be created for example with the reaction
+            # plugin by setting up a reaction to ping with cmd:ping
             class << new_m
               self
             end.send(:define_method, :reply) do |*args|
               debug "replying to '#{from.message}' with #{args.first}"
               from.reply(*args)
+              new_m.replied = true
             end
             # the created message will follow originating message's in_thread
             new_m.in_thread = from.in_thread if from.respond_to?(:in_thread)