Mixiダイアリーライター

現在、漫画日記をmixiに書いており、読みたいリストを管理するため、
以下の機能を実現するRubyスクリプトを作る。

  • 日記ファイル(.txt)から日記の投稿
    • ファイル名→タイトル
    • 内容→本文
  • 日記文中のTODOを管理
  • 日記タイトルのものがTODOリストにあった場合削除
  • 日記ファイルのフォルダ分け。
  • WWW::Mechanizeを使おう!
  • TODOリストをGmailへ送ろう!
  • YAML::Storeをつかってデータを管理しよう!
  • とりあえず動くようにしてみよう。

以下ができたものです。

midw.rb

#!ruby -Ks
require "rubygems"
require "mechanize"
require "kconv"
require "yaml"
require "yaml/store"
require "date"
require "pathname"
require "lib/gmail"

class Pathname
  def each_file
    if file?
      yield self
    else
      children.each do |child|
        child.each_file {|name| yield name }
      end
    end
  end
end

module Midw
  class Config
    attr_reader :email, :password, :send_dir, :history_dir
    
    def initialize
      conf = YAML.load(Pathname.new("mixi.conf").read)
      @email = conf[:email]
      @password = conf[:password]
      @send_dir = conf[:send_dir]
      @history_dir = conf[:history_dir]
    end
  end
  
  class Database
    attr_reader :change
    
    def initialize
      @db = YAML::Store.new("todo.yml")
      @db.transaction do
        @db["todo"] ||= []
      end
      @change = false
    end
    
    def insert(item)
      @db.transaction do
        @db["todo"] << item.chomp
      end
      @change = true
    end
    
    def list
      @db.transaction(true) do
        @db["todo"]
      end
    end
    
    def delete(&block)
      @db.transaction do
        @db["todo"].each do |item|
          if block.call(item)
	    @change = true          
	    @db["todo"].delete(item)
          end
        end
      end
    end
  end
  
  class Diary
    attr_reader :title, :body, :todo
    
    def initialize(path)
      @diary = path
      @title = @diary.basename(".txt").to_s
      @body = @diary.read
      @todo = search_todo
    end
    
    def mvdir(dir)
      @diary.rename("#{dir}\\#{Date.today}-#{@diary.basename}")
    end
    
    def todo_empty?
      @todo.empty?
    end

    private
    def search_todo
      to = []
      @body.each_line do |line|
        if /TODO:(.*)/ =~ line
          to << $1
        end
      end
      return to
    end
  end
  
  class Agent
    def initialize(email, pass)
      @agent = WWW::Mechanize.new
      page = @agent.get('http://mixi.jp/')
      login_form = page.forms[0]
      login_form["email"] = email
      login_form["password"] = pass
      @agent.submit(login_form)
    end
    
    def send_diary(title, body) 
      home = @agent.get("http://mixi.jp/home.pl")
      id = if /add_diary\.pl\?id=(\d+)/ =~ home.body
        $1
      end
      edit = @agent.get("http://mixi.jp/add_diary.pl?id=#{id}")
      edit_form = edit.forms[0]
      
      edit_form["diary_title"] = title.toeuc
      edit_form["diary_body"] = body.toeuc
      
      confirm = @agent.submit(edit_form)
      confirm_form = confirm.forms[0]
      @agent.submit(confirm_form)
      puts "日記送信! - #{title}"
    end
    
    include Gmail
    def send_mail(list)
      subject = "TODO-#{Date.today}"
      body = list.sort.join("\n")
      send_gmail(subject, body)
      puts body
      puts "Gmail送信!"
    end
  end
  
  class Application
    def initialize
      @db = Database.new
      @conf = Config.new
      @agent = Agent.new(@conf.email, @conf.password)
      @dir = mkdir
    end
    
    def exec
      Pathname.new(@conf.send_dir).each_file do |file|
        next unless /txt$/ =~ file.to_s
        diary = Diary.new(file)
        @agent.send_diary(diary.title, diary.body)
        @db.delete {|item| /#{diary.title}/ =~ item }
        ins_todo(diary) unless diary.todo_empty?
        diary.mvdir(@dir)
      end
      @agent.send_mail(@db.list) if @db.change
    end
    
    def ins_todo(diary)
      diary.todo.each do |e|
        @db.insert(e)
      end
    end
    
    def mkdir
      dir = Pathname.new(%Q|#{@conf.history_dir}\\#{Time.now.strftime("%Y-%m")}|)
      dir.mkpath unless dir.exist?
      dir
    end
  end
end

if __FILE__ == $0
Midw::Application.new.exec
end

mixi.conf

--- 
:email: mixi_address
:password: mixi_password
:send_dir: new
:history_dir: history

こんな感じで良いのだろうか・・
リファクタリングを学びたい。まずは「るびま」の添削記事を熟読しよう。