#
# delicious bot mark I: accept no substitutes.
# 
# author: Erik Hollensbe
# note: sooner or later this'll have a permanent home, and cleaner code.
#

require 'rubygems'
gem 'net-yail'
gem 'www-delicious'
require 'www/delicious'
require 'net/yail'
require 'net/yail/IRCBot'
require 'uri'
require 'yaml'

class DeliciousBot < IRCBot
    def initialize(config, *args)
        @del = WWW::Delicious.new(config['delicious_username'], config['delicious_password'])
        @account = config['delicious_username']
        super(*args)
    end

    def add_custom_handlers
        @irc.prepend_handler :incoming_msg, method(:read_commands)
    end

    private

    #
    # actual commands
    #

    def tag_url(out, nick, url, tags)
        get_url(out, url) do |post|
            post.tags.push(*tags)
            write_post(out, nick, post, "tagging")
        end
    end

    def retitle_url(out, nick, url, title)
        get_url(out, url) do |post|
            post.title = title
            write_post(out, nick, post, "retitling")
        end
    end

    def store_urls(out, urls)
        urls.each { |url| @del.posts_add(:url => url, :title => url, :replace => true) }
        msg(out, "stored: #{urls.join(', ')}")
    rescue WWW::Delicious::Error => e
        p e.message
        msg(out, "error storing: #{urls.join(', ')}. sorry, bub.")
    end

    def delete_url(out, nick, url)
        get_url(out, url) do |post|
            @del.posts_delete(post.url)
            msg(out, "done, #{nick}")
        end
    rescue WWW::Delicious::Error
        msg(out, "error deleting #{url}")
    end

    #
    # command parser
    #
    def read_commands(hostinfo, nick, channel, text)
        out = channel or nick

        parts = text.split(/\s+/)

        command = parts.shift

        case command
        when "!help"
            msg(nick, "I respond to these commands:")
            msg(nick, %w(!help !ping !title !tag !delete !account).join(", "))
            msg(nick, "I also add any seen urls to our delicious account.")
        when "!account"
            msg(out, "Visit http://delicious.com/#{@account} to see links that have been stored.")
        when "!ping"
            msg(out, "Johnny five is alive!")
        when "!delete"
            if parts.length < 1
                msg(out, "usage: !delete ")
            else
                delete_url(out, nick, parts.shift)
            end
        when "!tag"
            if parts.length < 2
                msg(out, "usage: !tag  ")
            else
                tag_url(out, nick, parts.shift, parts.collect { |part| part.sub(/,*$/, '') })
            end
        when "!title"
            if parts.length < 2
                msg(out, "usage: !title  ")
            else
                retitle_url(out, nick, parts[0], parts[1..-1].join(" "))
            end
        else
            urls = URI.extract(text, %w(http))
            unless urls.empty?
                store_urls(out, urls)
            end
        end
    end

    #
    # utility methods
    #

    def get_url(out, url)
        posts = @del.posts_get(:url => url)
        if posts.empty?
            msg(out, "no such url: #{url}")
        else
            # XXX hack around a WWW::Delicious bug
            post = posts[0]
            post.url = post.url.to_s
            yield post
        end
    rescue WWW::Delicious::Error
        msg(out, "error handling url: #{url}")
    end

    def write_post(out, nick, post, action)
        # XXX hack around a WWW::Delicious bug
        @del.posts_delete(post.url)
        @del.posts_add(post)
        msg(out, "done, #{nick}.") 
    rescue WWW::Delicious::Error
        msg(out, "error #{action} #{post.url}")
    end

    #
    # ircbot class hooks
    #
    def welcome(text, args)
        @channels.each do |channel| 
            @irc.join(channel) 
            msg(channel, "Hello! Say '!help' for more information.")
        end 
    end
end

unless ARGV[0]
    STDERR.puts "usage: $0 <yaml config>"
    exit 1
end

config = YAML.load_file(ARGV[0])

t = DeliciousBot.new(
    config,
    {
        :irc_network => config["server"],
        :channels => config["channels"],
        :username => config["username"],
        :realname => config["realname"],
        :nicknames => config["nicknames"],
        :loud => config["loud"],
    }
)

t.connect_socket
t.start_listening
t.irc_loop</pre>
		</td>
		</tr>
		</table>
	
	</div>







</div>

<div id="right">
	




<div style="margin:0.5em 0 0em; font-size:0.75em;">
  <div style="float:left">
<a href="http://pastie.org/257140.txt" class="utility"><img alt="View" src="http://assets2.pastie.org/images/view.png?1228134075" style="vertical-align:middle" title="View the raw source of this pastie" /></a>
  </div>
<div style="padding-top:2px; margin-left:70px">
<span style="color:#999">or</span>
<a href="/pastes/257140/download" class="utility or">Download</a>	
</div>
</div>




  <p style="margin-top:1.5em">
  <label>Pasted</label><br />
  <span class="typo_date" title="Thu, 21 Aug 2008 11:41:24 GMT" id='paste_date'>August 21, 2008<br /> 7:41AM EDT</span>
  <script language="javascript">
  	e=$('paste_date');
  	e.innerHTML=get_local_time_for_date(e.title);
  </script>

  </p>


  







<p>
<label>Embed</label><br />
<input type="text" value="<script src='http://pastie.org/257140.js'></script>" onclick="this.select();" size="22">
</p>



  <p style="margin-top:1.5em;">
        
    
    <a href="/pastes/257140/reply">paste again</a>	
    
  </p>


<!-- <p style="margin-top:3em; font-size:0.6em;">
  
</p> -->


<div class="ads">
<label>Advertising</label>
<a href="http://peepcode.com/">
<img src="http://peepcode.com/system/uploads/2008/peepcode-nov.png" width="120" height="90" />
</a>
</div>




</div>

<br style="clear:both;" />

</div>

<div id="footer">
<p class="legal">
<a href="/legal/" style="color:#369;">Legal</a>
</p>
<p class="disclaim">
<strong>
	
	With great power comes great responsibility.<br />Pastie wisely.
	</strong>
</p>
<p class="credit">
  Created by <a href="http://blog.pastie.org/">Josh Goebel</a>
</p>
<br style="clear:both;" />
</div>

<script src="http://assets2.pastie.org/javascripts/prototype.js?1228134075" type="text/javascript"></script>
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-413537-1";
urchinTracker();
</script>
</body>
</html>