root/platform/tdiary/util/image2flickr.rb

Revision 37332, 9.4 kB (checked in by drry, 2 years ago)
  • fixed regexes.
  • fixed HTML.
  • et cetera.
  • Property svn:executable set to *
Line 
1#!/usr/bin/env ruby
2# -*- coding: utf-8 -*-
3# = Image2Flickr
4#   imageプラグインからflickrプラグインへのマイグレーションツール
5#
6# Author:: MATSUOKA Kohei <http://www.machu.jp/>
7# Copyright:: Copyright (c) MATSUOKA Kohei <http://www.machu.jp/>
8# License:: GPL <http://www.gnu.org/copyleft/gpl.html>
9#
10# USEGE:
11#   imageプラグインからflickrプラグインへ移行するためのツールです。
12#   このツールの機能は、以下の2つです。
13#   (1) tDiaryのimageプラグインを利用して日記に載せた写真を、
14#       Flickrへアップロードします。
15#   (2) 日記データのimageプラグインの呼び出しを、
16#       flickrプラグインへと置き換えます。
17#       古い日記データは .bak.YYYYmmddHHMMSS を付けてバックアップします。
18#
19#   == 注意
20#
21#   (1) tDiary2.3.1以降が対象です。
22#       日記データがUTF-8に変換されている必要があります。
23#   (2) Wiki記法で記述された日記が対象です。
24#
25#
26#   == 移行手順
27#
28#   1. Flickr APIキーの取得
29#
30#   flickr.comのAPIサイトにアクセスし、"Apply for a new API Key"にて
31#   新しいAPIキーを生成します。
32#   http://www.flickr.com/services/api/keys/
33#
34#   Authentication TypeはAuthentication Typeを選択してください。
35#
36#
37#   2. tDiaryデータフォルダのバックアップ
38#
39#   このマイグレーションツールはtDiaryの日記データを書き換えます。
40#   古い日記データを残す仕様ですが、万が一に備えて
41#   事前にtDiaryのデータフォルダをバックアップしてください。
42#
43#
44#   3. rflickrライブラリの取得
45#
46#   このマイグレーションツールはFlickrへの写真のアップロードに
47#   rflickrライブラリを使用します。
48#   以下のサイトからrflickrライブラリを取得して、インストールしてください。
49#   http://rubyforge.org/projects/rflickr/
50#
51#   RubyGemsが利用できる場合は、以下のコマンドでインストールできます。
52#   $ gem install rflickr
53#
54#
55#   4. マイグレーションツールの設定
56#
57#   image2flickr.rbをエディタで開き、以下の4つのパラメータを設定します。
58#
59#   # FlickrのAPIキー
60#   @api_key = '123456789012345678901234567890'
61#   # Flickr APIのシークレットキー
62#   @secret = '1234567890'
63#   # tDiaryのデータフォルダ
64#   @data_path = '/var/tdiary'
65#   # tDiaryのイメージフォルダ
66#   @image_dir = '/var//www/tdiary/images'
67#
68#
69#   5. マイグレーションツールの実行
70#
71#   tDiaryのデータフォルダに書き込む権限を持つアカウントで、
72#   コマンドラインからimage2flickr.rbを実行してください。
73#   $ ./image2flickr
74#
75#   すると、以下のメッセージが表示されます。
76#   ----
77#   Flickrへ写真をアップロードするためのトークンを取得します。
78#   Webブラウザで下記のURLへアクセスしたら、何かキーを押してください。
79#   http://www.flickr.com/services/auth/?api_sig=....
80#   ----
81#
82#   指定されたURLへWebブラウザでアクセスし、トークンの発行を許可してください。
83#   コマンドラインへ戻り何かキーを押すと、マイグレーションが始まります。
84#
85#   なお、ツールを途中で中断し、2回目に実行するときはトークンを取得する
86#   必要はありません。
87#
88#
89#   6. 実行結果の確認
90#
91#   ツールが終了したらtDiaryのデータフォルダを開き、
92#   imageプラグインの呼び出しがflickrプラグインの呼び出しへ
93#   置き換わっていることを確認してください。
94#   古い日記データは .bak.20081024090000 などの拡張子がついて
95#   バックアップされていますので、問題があれば元に戻してください。
96#
97#   ツールを実行すると、以下の2つのファイルが作成されます。
98#   (1) flickr.token
99#       Flickrへ写真をアップロードするためのトークン。
100#   (2) image2flickr.yaml
101#       tDiaryのイメージフォルダに存在するJPEGファイル (ex. 20081025_0.jpg) と
102#       Flickrへアップロードしたphoto_idの対応付けを記録したファイル。
103#
104#   これらのファイルは、マイグレーションツールを途中で中断したときのために
105#   用意されています。
106#   マイグレーションが完了したら、少なくともflickr.tokenは削除してください。
107#   (トークンの不正利用を防ぐためです)
108#
109#
110$KCODE = 'utf8'
111begin
112  require 'rubygems'
113  gem 'rflickr'
114rescue
115end
116require 'flickr'
117require 'yaml/store'
118require 'tempfile'
119require 'fileutils'
120
121# FlickrのAPIキー
122@api_key = '123456789012345678901234567890'
123# Flickr APIのシークレットキー
124@secret = '1234567890'
125# tDiaryのデータフォルダ
126@data_path = '/var/tdiary'
127# tDiaryのイメージフォルダ
128@image_dir = '/var/www/tdiary/images'
129
130
131def main
132  uploader = FlickrUploder.new('image2flickr.yaml', 'flickr.token', @api_key, @secret)
133  parser = TDiaryParser.new(@data_path)
134  i2f = Image2Flickr.new(parser, uploader, @image_dir)
135  # tDiaryのimagesフォルダから対象日記を取得
136  files = Dir.glob("#{@image_dir}/*.{jp{,e}g,png,gif}").map{|file|
137    File.basename(file).match(/^(\d{6})/)
138    $1
139  }.compact.uniq
140  # 対象日記を変換
141  files.each do |file|
142    i2f.convert(file)
143  end
144
145  # cache のクリア
146  Dir["#{@data_path}/cache/*.rb"].each{|f| FileUtils.rm_f( f )}
147  Dir["#{@data_path}/cache/*.parser"].each{|f| FileUtils.rm_f( f )}
148end
149
150# Flickrへ写真をアップロードし、元ファイル名とphoto_idのペアをYAMLに記録する
151class FlickrUploder
152  def initialize(yaml, token, api_key, secret)
153    @flickr = Flickr.new(token, api_key, secret)
154    # トークンが無ければ取得する
155    unless @flickr.auth.token
156      puts "Flickrへ写真をアップロードするためのトークンを取得します。"
157      puts "Webブラウザで下記のURLへアクセスしたら、何かキーを押してください。"
158      puts @flickr.auth.login_link
159      # キー入力待ち
160      gets
161      @flickr.auth.getToken
162      @flickr.auth.cache_token
163      puts "トークンを取得し、#{token} へ保存しました。"
164      puts
165    end
166
167    @db = YAML::Store.new(yaml)
168    @db.transaction {
169      @db['photos'] ||= {}
170    }
171  end
172
173  # Flickrへ写真をアップロードする
174  def upload(file, title)
175    id = 0
176    @db.transaction {
177      basename = File.basename(file)
178      if @db['photos'][basename]
179        # アップロード済みの場合はスキップ
180        STDERR.puts "passed updating #{basename} (#{title}) ..."
181        id = @db['photos'][basename]
182        @db.abort
183      else
184        # 写真をアップロードする
185        STDERR.puts "updating #{basename} (#{title}) ..."
186        id = @flickr.photos.upload.upload_file(file, title)
187        @db['photos'][basename] = id
188      end
189    }
190    id
191  end
192end
193
194class TDiaryParser
195  include FileUtils
196
197  def initialize(data_path)
198    @data_path = data_path
199  end
200
201  # tDiaryの日記を置換する
202  # 拡張子に ".bak.yyyymmddHHMMSS" を付けて日記データをバックアップする
203  def each_diary(yearmonth)
204    yearmonth.match(/(\d{4})(\d{2})/)
205    year = $1
206    month = $2
207    file = "#{@data_path}/#{year}/#{yearmonth}.td2"
208    # ファイルをバックアップ
209    backup = "#{file}.bak.#{Time.now.strftime('%Y%m%d%H%M%S')}"
210    cp(file, backup, :preserve => true)
211    # 一時ファイルを生成
212    tmp = Tempfile.new('tmp')
213    open(file) do |fin|
214      fin.each('') do |headers|
215        date = headers.grep(/^Date:\s*(\d{4}\d{2}\d{2})/){$1}[0]
216        diary = fin.gets("\n.\n")
217        diary = yield(date, diary)
218        tmp.print headers
219        tmp.print diary
220      end
221    end
222    tmp.close
223    cp(tmp.path, file)
224  end
225end
226
227class Image2Flickr
228  def initialize(parser, uploader, image_dir)
229    @parser = parser
230    @uploader = uploader
231    @image_dir = image_dir
232  end
233
234  # imageプラグインをflickrプラグインへ置き換える
235  def convert(yearmonth)
236    @parser.each_diary(yearmonth) do |@date, diary|
237      # 現在はWiki記法のみ対応
238      diary.gsub!(/\{\{(image[^}]+)\}\}/) {|match|
239        begin
240          STDERR.puts "found: #{match}"
241          # image, image_left, image_right のいずれかに対応
242          replace = "{{#{eval($1)}}}"
243          STDERR.puts "replace: #{replace}"
244          STDERR.puts
245          replace
246        rescue => e
247          # 例外が発生したら置換しない
248          STDERR.puts "ERROR: #{e}"
249          STDERR.puts
250          match
251        end
252      }
253      diary
254    end
255  end
256
257  def image( index, title = nil, thumbnail = nil, size = nil, place = 'photo' )
258    replace("flickr", @date, index, title)
259  end
260
261  def image_center( index, title = nil, thumbnail = nil, size = nil, place = 'photo' )
262    replace("flickr", @date, index, title)
263  end
264
265  def image_left( index, title = nil, thumbnail = nil, size = nil, place = 'photo' )
266    replace("flickr_left", @date, index, title)
267  end
268
269  def image_right( index, title = nil, thumbnail = nil, size = nil, place = 'photo' )
270    replace("flickr_right", @date, index, title)
271  end
272
273  def replace(method, date, index, title)
274    file = Dir.glob("#{@image_dir}/#{date}_#{index}.{jp{,e}g,png,gif}").shift
275    # タイトルが未指定の場合はファイル名
276    title ||= File.basename(file)
277    id = @uploader.upload(file, title)
278    "#{method} #{id}"
279  end
280end
281
282main
Note: See TracBrowser for help on using the browser.