Feel Physics Backyard

HoloLensの出張授業をする会社で、教材を開発しています

100314-mixi日記をGmailで取得するスクリプトを読みやすくしてみた

 

さらに新し記事があります:100316-mixi日記をGmailで取得するスクリプトを、さらに読みやすくしてみた

 

100313mixi_icon     100313gmail_log

前に作ったmixi日記をチェックして新しいものをGmailで送るプログラムを「短く」してみた。

$KCODE = 'UTF-8'

### 諸設定
# mixi
USERNAME = 'xxxxxxxx@xxxxxx.com'
PASSWORD = 'xxxxxxxx'
# Gmail
MAIL_ADDRESS = "xxxxxxxx@xxxxxx.com"
MAIL_PASS = "xxxxxxxx"
TO_ADDRESS = MAIL_ADDRESS
# テストモード
TEST_MODE = false

require 'mixi'
require 'gmail'

Mixi.new(USERNAME, PASSWORD).get_recent_diaries.each do |recent_diary|
  Gmail.new(MAIL_ADDRESS, MAIL_PASS).send(TO_ADDRESS, recent_diary[:title], recent_diary[:text])
end

設定を除くと3行。ちょっとやりすぎという気もするが、まあいいだろう。

上のプログラムでrequireしている2つのファイルは以下のとおり。

まず「mixi.rb」。ユーザー名とパスワードで初期化する。メソッドは、今のところ「get_recent_diaries」しかない。

require 'mechanize'
require 'time'

class Mixi
  def initialize(username, password)
    print "Logging in Mixi..."
    @agent = WWW::Mechanize.new
    page = @agent.get('http://mixi.jp/')
    form = page.forms[0]
    form.fields.find {|f| f.name == 'email'}.value = username
    form.fields.find {|f| f.name == 'password'}.value = password
    form.fields.find {|f| f.name == 'next_url'}.value = '/home.pl'
    page = @agent.submit(form, form.buttons.first)
    print "done\n"

    if /url=([^"])"/ =~ page.body
      redirect_url = 'http://mixi.jp' + $1.to_s
      @agent.get(redirect_url)
    end

    if File.exist? ".mixi_checker" and TEST_MODE == false
      f = File.open(".mixi_checker", "r")
      # timeライブラリのparseメソッドで文字列からTimeオブジェクトに変換する
      @last_checked_time = Time.parse(f.read)
      f.close
      f = File.open(".mixi_checker", "w")
      f.print Time.now
      f.close
    else
      @last_checked_time = Time.local(2009, 1, 1, 0, 0)
    end
  end

  def get_recent_news
    page_home = @agent.get('http://mixi.jp/home.pl')
    # <h2>お知らせ</h2>を探す
    contents_h2s = page_home.search(h2).inner_text
    contents_h2s.each do |c|
      if c == 'お知らせ'
        # その直後の<li>要素をお知らせ本文として取得する
        # TODO やり方がわからない
      end
    end
  end

  def get_recent_diaries
    @recent_diaries = []
    page_home = @agent.get('http://mixi.jp/home.pl')
    page_home.links.each do |link|
      url = link.href

      # ホームのリンクの中からマイミク日記を参照しているものを探す
      if url =~ /view_diary\.pl.*/
        puts "An entry is found. Now inspecting..."
        diary_page = @agent.get(url)

        # タイトルに「|」があればmixi日記と判断する
        diary_title = diary_page.title
        if diary_title =~ /\|/

          # 新旧判定のため、日付文字列からTimeオブジェクトを作成する
          diary_time_text = diary_page.at('dd').inner_text
          if /(\d\d\d\d)年(\d\d)月(\d\d)日(\d\d):(\d\d)/ =~ diary_time_text
            diary_time = Time.local $1, $2, $3, $4, $5
          else
            # TODO どうする?
          end

          # 新旧判定し、新しい記事なら配列@recent_diariesに格納する
          if diary_time > @last_checked_time
            puts "#{diary_time}: A new entry is found."
            # 日時がrecent_timesより新しいもののみメール送信する
            @recent_diaries.push({:title => diary_title,
                :text => diary_page.at('div#diary_body').inner_text})
            #              body = diary_time_text + "\n"
            #              body << diary_title + "\n"
            #              # <div id='diary_body'>の中身を日記本文として表示する
            #              body << diary_page.at('div#diary_body').inner_text + "\n\n"
          else
            puts "#{diary_time}: A past entry is found and ignored. "
          end
        else
          print "It looks like an external entry.\n"
        end
      end
    end
    @recent_diaries
  end
end

次が「gmail.rb」。メールアドレスとパスワードで初期化する。メソッドは「send」のみ。

require 'net/smtp'
require 'tlsmail'

class Gmail
  def initialize(mail_address, mail_pass)
    @mail_address = mail_address
    @mail_pass = mail_pass
    @smtpserver = Net::SMTP.new("smtp.gmail.com", 587)
    @smtpserver.enable_tls(OpenSSL::SSL::VERIFY_NONE)
  end

  def send(to_address, subject = "", body = "")
    puts "sending a mail..."
    message = <<-EndOfMail
From: #{@mail_address}
To: #{to_address}
Subject: #{subject}
Date: #{Time::now.strftime("%a, %d %b %Y %X %z")}

#{body}
    EndOfMail

    @smtpserver.start('myserverdomain', @mail_address, @mail_pass, :login) do |smtp|
      smtp.send_message message, @mail_address, to_address
    end
    # p message # for debug
  end
end

うーん、メイン部分を短くしても、ライブラリが長くなってしまうのではあまり意味が無い気がします。もっとお互いに独立したパーツに分割しなくては・・・

hl