Vimからはてなフォトライフに画像を投稿する
Vimからはてなフォトライフに画像を投稿するvimスクリプトを書いてみました。hatena.vimに追加して使用してください。画像を投稿すると、その画像のfotolife記法がVimの本文に追加されます。「Vimからはてなハイクに投稿する」も合わせてどうぞ。
画像の投稿には、はてなフォトライフAtomAPIを使用しました。WSSE認証ヘッダはシェルスクリプトでは難しそうでしたので、こちらの記事を元にrubyで生成しています。AtomAPIを使っているためcookieが使用できず、画像投稿時には毎回パスワードを要求されます。
動作には、rubyとhatena.vimが使用するcurlコマンドの他に、fileコマンドが必要です。
" WSSE認証ヘッダの生成 function s:WSSECreds(user, pass) let creds = system('ruby -r "digest/sha1" -r "time" -e "' . \'nonce = Array.new(10){ rand(0x100000000) }.pack(%!I*!);' . \'nonce_base64 = [nonce].pack(%!m!).chomp;' . \'now = Time.now.utc.iso8601;' . \'digest = [Digest::SHA1.digest(nonce + now + %!' . a:pass . '!)].pack(%!m!).chomp;' . \'print %!UsernameToken !' . \'+ %!Username=\"%s\", ! % %!' . a:user . '!' . \'+ %!PasswordDigest=\"%s\", ! % digest' . \'+ %!Nonce=\"%s\", ! % nonce_base64' . \'+ %!Created=\"%s\"! % now;' . \'"') if v:shell_error return else return creds endif endfunction " 指定したファイルをはてなフォトライフに投稿する " :Usage " :FotolifePost <filename> command! -nargs=1 -complete=file FotolifePost call <SID>FotolifePost('<args>') function s:FotolifePost(filename) let mimetype = system('file -bi "' . a:filename . '"') if v:shell_error echo "指定したファイルがありません" return endif let tmpfile = tempname() let title = input('タイトル: ') " リクエストXMLの作成 let result_encode = system('ruby -r "base64" -e "' . \'request_xml = %!<entry xmlns=\"http://purl.org/atom/ns#\">\n' . \'<title>' . title . '</title>\n' . \'<content mode=\"base64\" type=\"' . mimetype . '\">\n' . \'%s</content>\n' . \'</entry>!;' . \'open(%!' . tmpfile . '!, %!w!){|io|' . \'io << request_xml % Base64.encode64(open(%!' . a:filename .'!).read)' . \'}' . \'"') if v:shell_error echo "Base64 エンコードに失敗しました" return endif let password = inputsecret('Password: ') let header_wsse = 'X-WSSE: ' . s:WSSECreds(g:hatena_user, password) let endpoint = 'http://f.hatena.ne.jp/atom/post' let header_ac = 'Accept: application/x.atom+xml, application/xml, text/xml, */*' let header_cont = 'Content-Type: application/x.atom+xml; charset="utf-8"' let request = s:curl_cmd . ' -f --header "' . header_cont . \'" --header "' . header_ac . '" --header "' . header_wsse . \'" --data "@' . tmpfile . \'" "' . endpoint . '"' echo "画像のアップロード中です..." " 画像の投稿を実行 let ret = system(request) if v:shell_error echo "画像の投稿に失敗しました" return endif let imgsyntax = matchstr(ret, '<hatena:syntax>\zs[^>]*\ze</hatena:syntax>') " 投稿した画像の記法を本文に追加 let ret = append( line('.'), imgsyntax) if strlen(imgsyntax) != 0 echo imgsyntax . " の投稿に成功しました" else echo "画像の投稿に失敗しました" endif return endfunction
実行方法は次のとおり。
:FotolifePost <filename>