マイペースなプログラミング日記

x86エミュレータやFPGA、WebGLにお熱なd-kamiがマイペースに書くブログ

mixiの最新日記をTwitterに書き込む

Rubymixiの最新日記をTwitterに書き込むプログラムを作ってみた。ファイルは3つで本体とmixi.rbとtwitter.rbがある。成功しようが失敗しようが何も表示しない。mixiへのログインが失敗した時にどうなるか不明。多分twitter.rbの部分でエラーが発生してtwitterの書き込みが失敗すると思う。

#! /usr/bin/ruby -Ku

require './twitter'
require './mixi'

mixi_email = "******@****.co.jp"
mixi_pass = "*******"

twitter_user = '*******'
twitter_pass = '*******'

mixi = Mixi.new
mixi.login(mixi_email, mixi_pass)
diary = mixi.getDiaries(1)[0]

contents = diary.contents.gsub(/<br \/>/, '\n')
contents = contents.gsub(/<[^>]+>/, '')

twitter = Twitter.new(twitter_user, twitter_pass)
twitter.update(contents)

mixi.rb

#! /usr/bin/ruby -Ku

require 'net/http'
require 'kconv'

class MixiUser
    attr_reader :id
    attr_reader :name

    def initialize(id, name)
        @id = id
        @name = name
    end
end

class MixiDiary
    attr_reader :title
    attr_reader :contents

    def initialize(title, contents)
        @title = title
        @contents = contents
    end
end

class TopicTitle
    attr_reader :title
    attr_reader :community

    def initialize(title, community)
        @title = title
        @community = community
    end
end

class Mixi
    def login(user, password)
        http = Net::HTTP.start('mixi.jp')
        response = http.post('/login.pl', "email=#{user}&password=#{password}&next_url=./home.pl")
        @cookie = response['Set-Cookie'].split(',').join(';')
    end

    def getFootPrints()
        http = Net::HTTP.start('mixi.jp')
        response = http.get("/show_log.pl", 'Cookie' => @cookie)
        body = response.body.toutf8

        users = Array.new

        body.scan(/<a href="show_friend.pl\?id=(\d+)">([^<]+)<\/a>/){|id, name|
            users << MixiUser.new(id, name)
        }

        return users
    end

    def getNewDiaryTitles()
        http = Net::HTTP.start('mixi.jp')
        response = http.get('/new_friend_diary.pl', 'Cookie' => @cookie)
        body = response.body.toutf8

        titles = Array.new

        body.scan(/<a href="view_diary.pl\?id=(\d+)&owner_id=(\d+)">([^<]+)<\/a>/){|id, owner_id, title|
            titles << title
        }

        return titles
    end

    def getDiaries()
        getDiaries(30)
    end

    def getDiaries(limit)

        diaries = Array.new
        index = 0

        getDiaryPaths.each{|path|
            index += 1
            if index > limit
                break
            end

            http = Net::HTTP.start('mixi.jp')
            response = http.get('/' + path, 'Cookie' => @cookie)
            body = response.body.toutf8

            title = ""
            contents = ""

            body.scan(/<dt>([^<]+)<span>/){|scanTitle|
                 title = scanTitle[0]
            }

            body.scan(/<div id="diary_body">(.+?)<\/div>/m){|scanContents|
                contents = scanContents[0]
            }

           diaries << MixiDiary.new(title, contents)  
        }

        return diaries
    end

    def getDiaryPaths()
        http = Net::HTTP.start('mixi.jp')
        response = http.get('/list_diary.pl', 'Cookie' => @cookie)
        body = response.body.toutf8

        paths = Array.new

        body.scan(/<input[^>]+><a href="(view_diary.pl\?id=\d+&owner_id=\d+)">[^<]+<\/a>/){|path|
            paths << path[0]
        }

        return paths
    end

    def getNewTopicTitles()
        http = Net::HTTP.start('mixi.jp')
        response = http.get('/new_bbs.pl', 'Cookie' => @cookie)
        body = response.body.toutf8

        titles = Array.new

        body.scan(/<a href="view_bbs.pl\?id=\d+&comment_count=\d+&comm_id=\d+">([^<]+)<\/a> \((.+?)\)<\/dd>/){|title, community|
            titles << TopicTitle.new(title, community)
        }

        return titles
    end
end

twitter.rb

#! /usr/bin/ruby -Ku

require 'net/http'
require 'rexml/document'
require 'uri'

class User
    attr_reader :id
    attr_reader :name
    attr_reader :screen_name
    attr_reader :description
    attr_reader :url
    attr_reader :followers_count
    attr_reader :friends_count
    attr_reader :statuses_count
    attr_reader :location
    attr_reader :profile_image_url

    def initialize(element)
        @id = element.elements['id'].text()
        @name = element.elements['name'].text()
        @screen_name = element.elements['screen_name'].text()
        @description = element.elements['description'].text()
        @url = element.elements['url'].text()
        @followes_count = element.elements['followers_count'].text()
        @friends_count = element.elements['friends_count'].text()
        @statuses_count = element.elements['statuses_count'].text()
        @location = element.elements['location'].text()
        @profile_image_url = element.elements['profile_image_url'].text()
    end
end

class Status
    attr_reader :id
    attr_reader :text
    attr_reader :user

    def initialize(element)
        @id = element.elements['id'].text()
        @text = element.elements['text'].text()
        @user = User.new(element.elements['user'])
    end
end

class Twitter
    TwitterServer = 'twitter.com'

    def initialize(username, password)
        @username = username
        @password = password
    end

    def verify_credentials()
        request = Net::HTTP::Get.new('/account/verify_credentials.xml')
        request.basic_auth(@username, @password)
        http = Net::HTTP.start(TwitterServer)

        response = http.request(request)
        doc = REXML::Document.new(response.body)
        user = User.new(doc.elements['/user'])

        return user
    end

    def friends_timeline
        request = Net::HTTP::Get.new("/statuses/friends_timeline/#{@username}.xml")
        request.basic_auth(@username, @password)
        http = Net::HTTP.start(TwitterServer)
        response = http.request(request)
        doc = REXML::Document.new(response.body)

        statuses = Array.new

        doc.get_elements('/statuses/status').each{|element|
            status = Status.new(element)
            statuses << status
        }

        return statuses
    end

    def update(status)
        request = Net::HTTP::Post.new('/statuses/update.xml')
        submit = URI.escape(status)

        request.basic_auth(@username, @password)
        http = Net::HTTP.start(TwitterServer)
        response = http.request(request, "status=#{submit}&source=test")

        doc = REXML::Document.new(response.body)
        status = Status.new(doc.elements['/status'])

        return status
    end
end