birdTwitterでの自分のTweetsをtDiaryにまとめて投稿する - その1. 過去ログ編, Twitterでの自分のTweetsをtDiaryにまとめて投稿する - その2. 日次バッチ編, きょうのつぶやき

Twitterでの自分のTweetsをtDiaryにまとめて投稿する - その1. 過去ログ編

久々にこのブログを見た人は、左側の「最近の話題」を見てびっくりしてしまったかもしれませんが、この週末はいろいろ忙しい中、Twitterに溜まっていた自分の過去のつぶやき(Tweets)を、この自分のブログ(tDiary)に毎日まとめて投稿するスクリプトを作成したりしていました。忙しいとかえってそういうことをしたくなったりしますよね(笑。

どうしてそんなことしたくなったのか、というといくつか理由があって、1)Twitterを使うようになってブログの更新頻度が激減してしまっているのを何とかしたいのが第一(笑、2)一つの会社に管理されているTwitter内の自分の書き込みのバックアップを念のため取っておきたかった1、3)さらにTwitterに投稿している写真データ2もバックアップしておきたい、4)Twitterは利用しないがこっちは見ている人もいるかもしれない、などなどでした。Twitterを単なる利用者としてではなく、開発者として叩いてみておきたかった、という面もあります。

さて、Twitterでの自分のつぶやきをtDiaryへ登録する、という今回僕がやりたかったことと同じことをやっている人は、ググッてみると結構たくさんいらっしゃいます。しかし、僕がググった限り、僕のニーズにピッタリ合った方法は見つかりませんでした。主に問題だったのが、TwitPicに登録された写真の扱いで、写真へのTwitPicサイトへのリンクを作成したりしている人もたくさんいらっしゃったのですが、投稿された写真そのものをローカルにダウンロードしてバックアップしておく、という方法を取っている人は見つかりませんでした。また、同じようなことをしていても一部の処理を手動で行っていたり(僕はcron起動で毎日勝手に投稿してくれるような形にしたいと思っていました)、投稿されるTweetsのフォーマット・中身がイマイチだったり、そもそも投稿スクリプトが公開されていなかったりと、どうもぴったり来るものはなさそうだということがわかりました。

既存のソリューションをググッて探す一方で、自分でTwitter/TwitPicからつぶやきが写真を取り出して投稿するのがどのくらい難しいのかも調べ始めていたんですが、アクセスのための材料(ドキュメント・ライブラリ)も既に豊富にそろっており、そんなに難しくなさそうなことが伺えました。そんなわけで自分で作ってみることにしてしまったわけです。

一口に「自分のTweetsをまとめてtDiaryに再投稿する」といっても、この問題には大きく2つの側面があります。一つが既に1400tweetsあまりたまった自分の過去のつぶやきをどうするか、もう一つが今後毎日まとめ投稿をするための仕組み作りです。もちろん、両者に共通する技術要素は多いですが、異なる部分も多いと思いました。例えば前者(過去ログ)の問題は、ワンショットの処理となりますからテキトーなスクリプト+ある程度のマニュアル処理でも問題ありません。また今この瞬間に動きさえすれば良いので、最近話題の「Twitterの認証問題3」も関係ありません。そんなわけで、まずは前者の問題に取り組むことにしました。基本的な方針としては、後者の問題向けの知識を蓄えること+とにかく手間をかけないこと、としました。また、上でも書きましたが、Twitterに投稿されている自分のつぶやきをこのtDiary側へコピーすること、個人宛つぶやき(@〜で始まるつぶやき)は含めないこと、自分のTwitPicへ投稿した写真はローカルにダウンロードしたのち、tDiaryのimage_exプラグインを使って表示すること、あたりを最低限の要求仕様とすることにしました。

さてまず、前者後者共通してサーバ側での処理のために使うツールとしては、今回はrubyを選択することにしました。個人的にはまだperlやshほどrubyのコードは書いたことはなく、少し不安な(というかめんどくさい)面もあったんですが、特にネット系のツールをお手軽に書くための材料が豊富に揃っていること、個人的にそろそろ(というか遅過ぎるけど・汗)rubyにも慣れておきたいと思ったという辺りが主な理由です。結果的にはrubyの選択は大正解でしたね。とにかく何をやるにも楽で、短い時間でささっとコードを書かないといけない今回の僕のようなケースにはピッタリでした。

Twitterにはいろいろ公開されているAPIがありますが、その中で今回僕が使ったのは、id指定(スクリーンネーム指定)でつぶやきを時系列順で取得する、user_timeline APIだけです。まず最初に、自分のプログラムのデバッグでTwitter側に負荷をかけるのも忍びなかったため、とりあえず過去の自分のつぶやきを全て、JSON形式でダウンロードしておくことにしました。ワンショットでダウンロード出来ればよかったので、今回はwgetコマンドとrubyを使い、以下のようにして行ないました。

  • まず、wgetコマンドで最初(新しい方から)200件のつぶやきをJSON形式でダウンロードします。この時、既にTwitterへログイン済みの(cookieのついた)ブラウザならそのまま実行できますが、wgetのようなcookieを持たないクライアントを使う場合、BASIC認証を指定する必要があります。

    $ wget –user=SCREEN_NAME –password=PASSWORD -O 1.json http://api.twitter.com/1/statuses/user_timeline/SCREEN_NAME.json?count=200

  • 次にダウンロードされたJSONファイルを例えば下記のようなスクリプトを使ってrubyで読み、最後の要素が含む"id"値を調べます4

#!/usr/bin/env ruby  
require 'rubygems'  
require 'json/pure'  
  
json_doc = ""  
open("#{1.json", "r") do |file|  
  json_doc = file.read  
end  
JSON.parse(json_doc).each do |status|  
  puts "id = #{status['id']}"  
end  
  • さらに、上で調べた最後の要素(=一番古い要素)のidを使って、以下のように「それよりも古いつぶやき」を再びJSON形式でダウンロードします。

    $ wget –user=SCREEN_NAME –password=PASSWORD -O 2.json “http://api.twitter.com/1/statuses/user_timeline/SCREEN_NAME.json?count=200&max_id=[上で調べた一番古いつぶやきのid]”

  • 以上を、古いつぶやきがなくなるまで繰り返します。

ちなみに上記処理はとても単純な処理なので、上の処理自体を一つのrubyスクリプトにすることも簡単なわけですが、僕が試していたところ、上記のようなAPI呼出を間髪入れず実行してしまうと、時々TwitterがJSON形式のデータではなく何だか分からないHTMLデータを返すことがあり(もしかしたら鯨が出てたのかなぁ?)、今回はたかだか8回程度の繰り返しだったのでマニュアルで処理してしまいました。

さて、そうやって手元にJSON形式の過去つぶやきデータがダウンロードされたあとは、tDiaryへそれらを適当に整形してPOSTするだけです。最初、tDiaryへHTTP POSTでつぶやきを投稿するのではなく、直接ローカルにある日記データに追記してしまおうかとも考えたのですが、キャッシュやRSSを生成しているプラグインなどへの影響を考えて、またしてもwgetコマンドを使ってHTTP POSTする、という選択を取ることにしました5

過去ログPOSTに使ったスクリプトは下記の通りです。自分にとってスクラッチから書いた初めてのrubyスクリプト&ワンショットしか動かさないつもりだったので超テキトーな点はご容赦くだされ。

#!/usr/bin/env ruby  
  
require 'rubygems'  
require 'json/pure'  
require 'parsedate'  
require 'kconv'  
require 'cgi'  
require 'uri'  
  
SCREEN_NAME = 'SCREEN_NAME'  
TDIARY_UPDATE_URI = 'http://memo.digitune.org/update.rb'  
TWITTER_URI = 'http://twitter.com/'  
TWITPIC_URI = 'http://twitpic.com/'  
IMAGE_PATH = '/home/kazawa/src/tdiary/images/'  
all_tweets = {}  
$image_seq = 0  
  
(1..8).each do |i|  
  json_doc = ""  
  open("#{i}.json", "r") do |file|  
    json_doc = file.read  
  end  
  JSON.parse(json_doc).each do |status|  
    all_tweets[status['id']] = status  
  end  
end  
  
def link_uri(tweet)
  URI.extract(tweet, ["http", "https"]) do |uri|  
    tweet = tweet.gsub(uri, "<a href=\"#{uri}\">#{uri}</a>")
  end  
  tweet  
end  
  
def link_twitter(tweet)
  tweet = tweet.gsub(/@(\w+)/, "@<a href=\"#{TWITTER_URI}\\1\">\\1</a>")
  tweet  
end  
  
def download_twitpic(tweet, date)
  URI.extract(tweet) do |uri|  
    if /^#{TWITPIC_URI}/ =~ uri  
      res = `wget -O - #{uri} 2>/dev/null`  
      own_photo = nil  
      res.each_line do |line|  
        if /photo_username.*\">(\w+)<\// =~ line  
          puts "photo_username = #{$1.strip}"  
          own_photo = 1 if $1.strip == SCREEN_NAME  
        end  
      end  
      break if ! own_photo  
      url = ""  
      res = `wget -O - #{uri}/full 2>/dev/null`  
      res.each_line do |line|  
        if /img.*src=\"([^\"]+)\".*alt/ =~ line  
          url = $1  
          puts "url = #{url}"  
        end  
      end  
      puts "wget -O #{IMAGE_PATH}#{date}_#{$image_seq}.jpg --referer=#{uri}/full \"#{url}\""  
      system "wget -O #{IMAGE_PATH}#{date}_#{$image_seq}.jpg --referer=#{uri}/full \"#{url}\""  
      puts "convert #{IMAGE_PATH}#{date}_#{$image_seq}.jpg -resize 60x80 #{IMAGE_PATH}s#{date}_#{$image_seq}.jpg"  
      system "convert #{IMAGE_PATH}#{date}_#{$image_seq}.jpg -resize 60x80 #{IMAGE_PATH}s#{date}_#{$image_seq}.jpg"  
      tweet = "<%=image_right #{$image_seq}%>" + tweet  
      $image_seq += 1  
    end  
  end  
  tweet  
end  
  
def post_tweets(body, last_t)
  body = "きょうのつぶやき\n" + body  
  puts "body => #{body}"  
  post_data = "old=#{last_t.strftime('%Y%m%d')}&year=#{last_t.year}&month=#{last_t.month}&day=#{last_t.day}&title=&body=#{CGI.escape(body.toeuc)}&makerss_update=false&append=#{CGI.escape(' 追記 '.toeuc)}"  
  puts "wget -d --user TDIARY_USER --password TDIARY_PASS --referer #{TDIARY_UPDATE_URI} --post-data '#{post_data}' #{TDIARY_UPDATE_URI}"  
  system "wget -d --user TDIARY_USER --password TDIARY_PASS --referer #{TDIARY_UPDATE_URI} --post-data '#{post_data}' #{TDIARY_UPDATE_URI}"  
end  
  
body = ""  
last_t = nil  
last_date = nil  
all_tweets.keys.sort.each do |id|  
  status = all_tweets[id]  
  d = ParseDate::parsedate(status['created_at'])
  t = Time.gm(*d[0..5]).localtime  
  ts = t.strftime("%F")
  if last_date != nil && last_date != ts  
    post_tweets(body, last_t) if body != ""  
    $image_seq = 0  
    body = ""  
  end  
  if /^@/ =~ status['text']  
    puts ("skip: #{status['text']}")
    next  
  end  
  tweet = download_twitpic(status['text'], t.strftime('%Y%m%d'))
  tweet = link_twitter(link_uri(tweet))
  body = body + "<p>#{tweet} <font size=-2>(#{t.strftime('%H:%M')} #{status['source']}から)</font></p>\n"  
  last_t = t  
  last_date = ts  
end  
post_tweets(body, last_t) if body != ""  

随所に乱れ飛ぶputsはデバッグ表示ですので鬱陶しければ消しても大丈夫です。上記スクリプトはまるでrubyっぽくなかったり(汗、TwitPicのHTMLを超適当に読み込んでいたり、Twitterにハッシュタグに未対応だったり、サムネイルイメージのサイズが元画像にかかわらず固定だったりといろいろショボい箇所があるんですが、まぁとりあえず動いたのでこれはこれで良いのでは、と<ヲ。さて、その2. 日次バッチ編へ続きます。

Twitterでの自分のTweetsをtDiaryにまとめて投稿する - その2. 日次バッチ編

さて、過去ログの処理が終わったので、次は今後のための日次バッチの作成です。やるべきことは過去ログ編とほとんど変わらないため、スクリプトももうほとんどできている、といっても過言ではないのですが、上で書いたとおり、一点新しいつぶやきをJSON形式で取得するための、Twitter APIの認証部分については、上でやったようなテキトーなことではすぐに動かなくなってしまいますので6、もう少し真面目に考える必要がありました。

しかしまぁ最近は良い時代になったもので、そのような技術的課題に直面しても、ことオープンな世界の出来事であれば、ほぼ確実に先達が解決済みだったりします。今回のケースもグーグル先生にちょっと聞いてみさえすればすぐに、ruby+OAuthを実現しておられる方のページが見つかりました。僕が今回主に参考にしたのはこちらのページです。どうもありがとうございました>しばそんさん。

そんなわけで上記ページをベースに元のスクリプトをOAuthに対応させ、またTwitterのハッシュタグに対応させたり多少コードを整理したりした結果の、日次バッチ用スクリプトを以下に貼っておきます。僕はこのスクリプトを夜中の0:00に実行されるよう、cronに設定しています。あ、実行前に、最後に投稿した過去つぶやきのidを、last_id.txtファイルに書いておかないと上手く動きません。いろいろテキトー過ぎるスクリプトで申し訳ないッス…。

#! /usr/bin/ruby  
# encoding: utf-8  
  
require 'time'  
require 'rubygems'  
require 'oauth'  
require 'rubytter'  
require 'kconv'  
require 'parsedate'  
require 'cgi'  
require 'uri'  
require 'fileutils'  
  
# constants  
SCREEN_NAME = 'SCREEN_NAME'  
TDIARY_UPDATE_URI = 'http://memo.digitune.org/update.rb'  
TWITTER_URI = 'http://twitter.com/'  
SEARCH_PATH = 'search?q='  
TWITPIC_URI = 'http://twitpic.com/'  
IMAGE_PATH = '/home/kazawa/src/tdiary/images/'  
LAST_ID_PATH = '/home/kazawa/src/tweets2tdiary/last_id.txt'  
TITLE = "きょうのつぶやき\n"  
  
# secret information  
CONSUMER_KEY = 'CONSUMER_KEY'  
CONSUMER_SECRET = 'CONSUMER_SECRET'  
ACCESS_TOKEN = 'ACCESS_TOKEN'  
ACCESS_TOKEN_SECRET = 'ACCESS_TOKEN_SECRET'  
  
# global variables  
$image_seq = 0  
  
# functions  
def link_uri(tweet)
  URI.extract(tweet, ["http", "https"]) do |uri|  
    tweet = tweet.gsub(uri, "<a href=\"#{uri}\">#{uri}</a>")
  end  
  tweet  
end  
  
def link_twitter(tweet)
  tweet = tweet.gsub(/@(\w+)/, "@<a href=\"#{TWITTER_URI}\\1\">\\1</a>")
  tweet = tweet.gsub(/#(\w+)/, "<a href=\"#{TWITTER_URI}#{SEARCH_PATH}%23\\1\">#\\1</a>")
  tweet  
end  
  
def download_twitpic(tweet, date)
  URI.extract(tweet) do |uri|  
    if /^#{TWITPIC_URI}/ =~ uri  
      res = `wget -O - #{uri} 2>/dev/null`  
      own_photo = nil  
      res.each_line do |line|  
        if /photo_username.*\">(\w+)<\// =~ line  
          puts "DEBUG:photo_username = #{$1.strip}"  
          own_photo = 1 if $1.strip == SCREEN_NAME  
        end  
      end  
      break if ! own_photo  
      url = ""  
      res = `wget -O - #{uri}/full 2>/dev/null`  
      res.each_line do |line|  
        if /img.*src=\"([^\"]+)\".*alt/ =~ line  
          url = $1  
          puts "DEBUG:url = #{url}"  
        end  
      end  
      puts "DEBUG:wget -O #{IMAGE_PATH}#{date}_#{$image_seq}.jpg --referer=#{uri}/full \"#{url}\" 2>/dev/null"  
      system "wget -O #{IMAGE_PATH}#{date}_#{$image_seq}.jpg --referer=#{uri}/full \"#{url}\" 2>/dev/null"  
      puts "DEBUG:convert #{IMAGE_PATH}#{date}_#{$image_seq}.jpg -resize 60x80 #{IMAGE_PATH}s#{date}_#{$image_seq}.jpg"  
      system "convert #{IMAGE_PATH}#{date}_#{$image_seq}.jpg -resize 60x80 #{IMAGE_PATH}s#{date}_#{$image_seq}.jpg"  
      tweet = "<%=image_right #{$image_seq}%>" + tweet  
      $image_seq += 1  
    end  
  end  
  tweet  
end  
  
def post_tweets(body, last_t)
  body = TITLE + body  
  puts "DEBUG:body => #{body}"  
  post_data = "old=#{last_t.strftime('%Y%m%d')}&year=#{last_t.year}&month=#{last_t.month}&day=#{last_t.day}&title=&body=#{CGI.escape(body.toeuc)}&append=#{CGI.escape(' 追記 '.toeuc)}"  
  puts "DEBUG:wget -O /dev/null --user USERNAME --password PASSWORD --referer #{TDIARY_UPDATE_URI} --post-data '#{post_data}' #{TDIARY_UPDATE_URI} 2>/dev/null"  
  system "wget -O /dev/null --user USERNAME --password PASSWORD --referer #{TDIARY_UPDATE_URI} --post-data '#{post_data}' #{TDIARY_UPDATE_URI} 2>/dev/null"  
end  
  
# connect  
consumer = OAuth::Consumer.new(  
  CONSUMER_KEY,  
  CONSUMER_SECRET,  
  :site => 'http://twitter.com'  
)
  
access_token = OAuth::AccessToken.new(  
  consumer,  
  ACCESS_TOKEN,  
  ACCESS_TOKEN_SECRET  
)
  
client = OAuthRubytter.new(access_token)
  
# read last_id  
last_id = 0  
open(LAST_ID_PATH, "r") do |file|  
  last_id = file.gets.chomp.strip  
end  
puts "DEBUG:last_id = #{last_id}"  
  
# read tweets  
body = ""  
last_t = nil  
last_date = nil  
client.user_timeline('digitune', {:since_id => last_id, :count => 200}).reverse_each do |status|  
  puts "DEBUG:id = #{status.id}"  
  last_id = status.id  
  d = ParseDate::parsedate(status.created_at)
  t = Time.gm(*d[0..5]).localtime  
  ts = t.strftime("%F")
  if last_date != nil && last_date != ts  
    post_tweets(body, last_t) if body != ""  
    $image_seq = 0  
    body = ""  
  end  
  if /^@/ =~ status.text  
    puts "DEBUG:skip: #{status.text}"  
    next  
  end  
  tweet = download_twitpic(status.text, t.strftime('%Y%m%d'))
  tweet = link_twitter(link_uri(tweet))
  body = body + "<p>#{tweet} <font size=-2>(#{t.strftime('%H:%M')} #{status.source}から)</font></p>\n"  
  last_t = t  
  last_date = ts  
end  
post_tweets(body, last_t) if body != ""  
  
# write last_id  
FileUtils.cp(LAST_ID_PATH, LAST_ID_PATH + ".old")
open(LAST_ID_PATH, "w") do |file|  
  file.puts last_id  
end  

きょうのつぶやき

あーテステス #bot (19:20 webから)

TwitterのつぶやきをまとめてtDiaryに投稿するテキトーなスクリプトを書きました。あまりにテキトー過ぎでも驚かぬよう。>「Twitterでの自分のTweetsをtDiaryにまとめて投稿する」http://memo.digitune.org/?date=20100725 (22:29 webから)

image 0テストも兼ねて。鳥乃が作った我が家の愛犬、スー。 http://twitpic.com/28kc0o (22:39 twiccaから)

うおっと家庭内LANからお家サーバには素直には繋がらないんだった。えーとどうするんだっけ?(汗。androidに/etc/hostsってある? (23:18 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

後者。AMPには承認プロセスがないので。 RT @m_masaru: 逆にandroid TVにDMM.TV for Androidが来ないのはgoogleがピンはねできなくなるから承認が降りないのか、DMM自身がBD-Jと比べて市場に価値がないと思っているのかどっちなんだろう。 (09:48 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

武満徹の名曲、「〇と△の歌」を知らんのか。 RT @yukatan: RT @gamme: 今日の覚えとくべき「愛で勝った人は「愛は勝つ」なんて歌わない。地球は丸いなんてわざわざ歌わないじゃん」 (09:24 twiccaから)

まぁふつーは知らないわな(^_^;) (09:25 twiccaから)

発売前後の熱狂も冷めて、最近はdisられ気味なニュアンスで話題になることの多いiPadだけど、我が家ではごくフツーにリビングweb&youtube端末として活躍中。今欲しいのはまともなニコ動プレーヤーだなー。公式には期待できないのか…。 (09:35 twiccaから)

雨後の竹の子のように出ている電子書籍系アプリもそれなりには眺めてるけど、そもそも最近の僕の生活サイクルには「雑誌を読む」という時間が全くないのが最大の障壁。僕の中では雑誌はもう完全にwebに淘汰されてる。 (09:42 twiccaから)

そう考えると、雑誌的電子書籍メインのiPadより文庫的電子書籍メインのkindleの方が、こと電子書籍というコンテキストでは僕には向いてるのかもしれないな。 (09:48 twiccaから)

iPadもkindleも、最近街でも見かける機会が多くなってきました。面白いのは、kindleは男女同じくらいの割合で見かけるのに、iPadを外で使っているのは男性ばかり(サンプル数は両手分くらい)。やっぱりあの重量がネックなのかな。 (09:53 twiccaから)

今、外苑東通りをローダウンされたムラーノが通ってった…。い、意味分からん! (13:21 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

ふと思ったのだけれど、F1マシンを今のウィングによるダウンフォース主体の設計となるようなレギュレーションではなく、かつて一瞬流行ったグランドエフェクト主体の設計となるようなレギュレーションにすれば、後方乱気流の影響も限定出来て今よりバトルが増えたりしないかな? (08:54 twiccaから)

今深夜アニメでは「少女達が日常を楽しく過ごしているほのぼのとした世界」が人気、って…。結果だけ見るとまぁそうかもしれないけど、なんかそういう「マーケッターの言葉」でまとめられると、大事なことがごっそり抜け落ちちゃうような気がする。 (09:24 twiccaから)

そういや先週末現役高校生とレクる機会があったのだけれど、「今一番欲しいものはなんですか?」という質問に、ごくフツーに「現金」との答えが。しかも「ありきたりすぎて恥ずかしいんですけど…」と!それが最近だとありきたりな答えだ、ということにおっさんは驚いたわい。 (13:50 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

そういや、自宅のiPadのiOSを3.2.1にしてから、明らかにwifi安定したなぁ。 (00:35 twiccaから)

あまり仕分けしないで軒並み各ドラマ第一話予約したんだけど、今のところ脱落が少なくてピンチ。さぁどれを切ろうかなぁ…。 (00:39 twiccaから)

この日向センセと内田センセの立場の違いは面白い。個人的にここ数年仕事で英語に揉まれてきて思うのは、英語でそれなりに意思疎通できるようになるのは、言うほど難しくない、ということ。その辺りの認識の相違が根底にありそう。 http://bit.ly/cZ3xkl (09:32 twiccaから)

僕の場合、英語で仕事の最初の頃は、普段日本語で使っているのと同じようなレベルの言い回し、慣用表現、ニュアンスが伝えられないことがすごいストレスでした。でもそれって無駄なストレスなんですよね。 (09:39 twiccaから)

僕にとって英語で仕事するのは、慣れてない言語でプログラムする感じ。使えるシンタックスは限られてるしリファレンス首ったけだけど、手持ちの知識を総動員して組み合わせ、目的を達成する、って感じが似ている気がします。 (09:44 twiccaから)

読書話聴の中で一番苦労しているのはやっぱり聴くことだなぁ。リアルタイムに正確な処理を求められ手が抜けないから凄く疲れる。他の3つは自分でペースを決められるのでまだマシなんですよね。 (09:50 twiccaから)

飲み会終わりー。今日は音楽がすごい速く聴こえるよ。 (22:58 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

おはよーはよー。今日はアポロ月面着陸の日。Yahoo!ニュースの「今日は何の日?」クイズについたコメントを読んでいると、日本人でも案外沢山今でも「アポロ月着陸は嘘」だと思っている人がいそうな雰囲気。「今行けないのにそんな昔に行ける訳ない」とか、実に無邪気な進歩に対する信頼だ。 (07:46 webから)

昨日は下二人とレインボープールに行きました。芋洗い状態(って、フツーに言うよね?)でしたが楽しかった。日差しは強烈だったけどプールから出ると風が冷たくて、本当のシーズンはもう少し後かな?日焼けした肩が痛いです…。 (07:49 webから)

お、京セラ製android端末、Zioは物理キーがタッチセンサーなんだ。http://bit.ly/blZx60 (21:47 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

どうでもいいけど、simejiにはundoはないんかな。誤確定とか誤カタカナ変換後の復帰がめんどくさい。 (01:48 twiccaから)

お、バンパー無償配布なの?>iPhone4 (02:39 twiccaから)

疲れたから寝るらー (02:57 twiccaから)

せっかくのお天気の連休なのに、こんな時間まで寝てしまった…。 (13:08 twiccaから)

そういえば…と思い出して、昔会社でもらったCEO AWARDのケータイストラップをxperiaに付けてみたらピッタリだった。フツーのケータイに付けるとちょっとゴツ過ぎるんだけどね。 (13:42 webから)

バンパーが(デザイン的に)好かん、という人向けに、絶縁シールorコート(ペイント)的なものが出てきそう。つーか大抵の人は最初からケース的なものに入れて使っているのかしら?日本の場合。 (13:49 webから)

最後の歌練終了。明日は母校で本番だー。最後の二回でなんとか形になったかな? (22:06 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

日本人が飽きやすいのは、人より早く「飽きた」というのがカッコいい、みたいな風潮があるからかな?<と分かったようなことを書いてみる。 (08:22 webから)

僕は飽きやすい人をカッコいいとは思わないけどねー。仕事でも遊びでも、コツコツずっと続けられる人にリスペクトするっす。 (08:24 webから)

そういや先週、僕の実家に顔を見せに行ったら「お中元のメロンをゆうパックで送った」と言ってたのだけれど、未だ届かず。正常化宣言出てなかったっけ。熟しすぎてグチャグチャになったメロンは厳しいにゃあ! (08:32 webから)

androidの、アプリ利用中→通知到着→通知欄引き下げ→アプリ切り替え(例えばtweeter)→戻るボタン一発で元アプリへ復帰、の流れが秀逸過ぎる。しかもネスト可。iPadでいちいちhomeに戻らないといけないのがすごい苦痛なんですよね…。 (13:47 twiccaから)

tweeterってなんだww。twitter or tweetと読み替えておくんなまし。 (13:49 twiccaから)

前にも少し書いたけど、確かにタッチ主体で操作しているときに物理キーを押さないといけなくなると、その要求されるトルクの差に一瞬戸惑い、ストレスに感じることはあるな。 (20:30 twiccaから)

触れば良いタッチに対して、物理キーはとても「重い」んだよね。フツーのケータイのキーと比べてxperiaのキーが特別重いわけじゃないんだけど、落差が辛い。 (20:33 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

昨晩はキムタクドラマの最終回を見ました。うーん、微妙。全体的にふわっとした感じで、題材とミスマッチだったような。シューメイの可愛さばかりが際立っておりましたなぁ。シノリョーのあの演技はかなりのギリギリ感だった。「肉は腐りかけが旨い」ってヤツ?<チゲー (08:47 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

久々に青空が見えていますね、 (09:14 twiccaから)

読点と句点を間違えた…。 (09:14 twiccaから)

昨晩は「ナイトレイド」最終回をようやく見た。最後まで微妙だった。アニメオリジナル脚本で題材の目の付け所は面白いと思ったんだか、その脚本の出来とアニメータ、演出が微妙。作画は比較的安定してたのに、何であんなに動きがヘボいことが多かったのだろう…。 (09:33 twiccaから)

あと、sw2の1話も見たのだが、我が家的には(裏番組の)「メイド様」圧勝だったので早々に脱落決定。あれだけオタク少年向け記号てんこ盛りだと逆に引くわ。 (09:37 twiccaから)

ちなみに我が家ですでに脱落決定してるのは他にカンパネラ、セキレイあたり。屍鬼も(裏が強いので)危うい。オカルト学園は裏(なんだっけ?)を見ていたので1,2話見逃しているのだけれど、なんとなく3度目の正直で今度こそ見た方が良いみたいですね…。 (09:44 twiccaから)

オカルト学園の裏は役員共か。あれも我が家的には微妙だったからチェンジ無問題かも。 (09:56 twiccaから)

…朝からこんな風に深夜アニメのことをつぶやきまくっていると人格疑われそうだな(汗。 (09:59 twiccaから)

そういえば、僕の愛する3代目マーチ君が代替わりしてしまって悲しい…。 (10:03 twiccaから)

今日の銀杏並木には何故か高校生がいっはいだ。修学旅行かしら?ふるまいがいちいち社会人にはない自由奔放さ(遠慮のなさ、KYさ、と感じる人もいるでしょう)で、なんだか新鮮な感じ。 (12:57 twiccaから)

奔放に振る舞いつつも、群れで動かざるを得ない、あの頃のアンビバレントな心情が感じられて懐かしいですな。 (13:02 twiccaから)

どーでもいいけど、POBox Touchのフリック入力は「い行」を入力したいのに「う行」が入力されてしまうことが多すぎて腹立たしい。チューニング不足なんじゃないの。 (13:06 twiccaから)

実はこれまで、OpenWnnフリック対応版やPOBox Touchは試していても、一般に「androidでフリック入力と言えばこれ」と言われているsimejiは食わず嫌いで試していませんでした。で、今更ながらに試しているんですが、これスゴく良いですね!<をい (21:35 twiccaから)

前の2つで不満だった点(wnnはタップの取りこぼし、poboxはフリック方向の誤認識とフルキー/フリックの混在不可)がことごとく問題ない感じ。タップの取りこぼしは若干あるかなぁ。 (21:38 twiccaから)

実はほんの少し試したことはあったんですが、そのイケてないUIが微妙にヤで、すぐアンインストールしちゃったんですよね。設定も一見意味不明だし…。しかし、ほんと人は見た目じゃないのだなぁ<人? (21:44 twiccaから)

出張前に、会社ノートPCのUSB端子でxperiaに充電できるかテストー。そして無事完了。問題なく充電できそうだ。 (22:14 twiccaから)

First | Prev | 372 | 373 | 374 | 375 | 376 | Next | Last