Kindle書籍を買ったけどダウンロード・配信できない問題と解決法

ググっても今回起きた問題と同一のものが見つからなかったのでメモしておきます。なおTwitterで検索したら数件見つかったのでごく稀に起きる現象のようです。

今回の現象

  • 12月14日0時頃、1-Clickで購入
  • 購入完了画面が出る
  • Kindle Cloud Readerで読む→試し読み版になる*1
  • 配信ボタンを押してもできませんと出る
    • Android端末はグーレアウト
    • Kindle Cloud Reader, iPod Touchの配信ボタンは押せるが、配信できませんと出る。
  • 注文の詳細・領収書は見れる
  • 注文履歴に入っている
    • 未発送の注文にも入っている*2
  • ご注文の確認メールが来ていない

特徴としては、ご注文の確認メールが来てない所になるかもしれません。

解決法

といっても大したことではなく、お問い合わせしただけです。

  1. 画面下部メニュー、右下「カスタマーサービスに連絡
  2. カスタマーサービスに連絡」ボタン
  3. お問い合わせ方法を選択: 電話、チャット、Eメールの3択
    • 夜中だったのでEメールにした
  4. 適当に埋める
    • 注文番号とかも書いておいた。

翌日

  • 3時頃にご注文の確認メールが来た様子
  • 10時頃にお知らせメールが来た

このたびは、Kindle本のご注文について、ご迷惑をおかけしていることをお詫びいたします。

12月13日から14日にかけてご注文いただいたKindle本について、注文の処理に時間がかかりダウンロードが開始されない件について、問題が修復いたしましたのでお知らせいたします。

なお、この問題が発生している間に、同じKindle本を重複してご注文いただいている場合、一方の注文をキャンセルし、返金処理を行います。返金処理が完了しだい、Eメールでお知らせいたしますので、今しばらくお待ちください。(本メールと入れ違いで、お受け取りいただいている場合はご容赦ください。)

その他、ご不明な点がございましたらご遠慮なくお問い合わせください。

どうせこんなことだろうと思い、重複注文しなくて正解でした。

Kindle配信の仕組みの推測

  1. step
    • ユーザ: 1-Clickで購入ボタンを押す。
  2. step
    • サーバ: 該当商品を購入キューに入れる。
    • ユーザ: 画面が切り替わる。
  3. step
    • サーバ: なるはやでキューが処理される。完了時にご注文の確認メール送信。
    • ユーザ: KindleReaderで書籍をダウンロード。

今までも購入後、Kindel Cloud Readerで読む時にお試し版になる現象は何度も起きていました。この原因は3rdステップのタイミングの問題と推測されます。

今回の問題は、3rdステップのサーバ側処理が何らかの原因でスタックしたことが原因ではないかと推測しています。

*1:Kindle Cloud Readerでは購入後のURLと試し読みとURLは同じ。

*2:一回ダウンロードするまではここに入ってキャンセルできる仕組みらしい。

Perlワンライナーメモ

至るところで語り尽くされているネタですが、使おっかなーと思うときには大抵忘れており毎回調べる羽目になるので、備忘としてメモします。

perl -e

オプションで与えた文字列をそのまま評価。

# はろーわーるど
perl -e 'print "Hello, World!\n"'

# モジュールのバージョン確認
perl -e 'use Term::ANSIColor; print $Term::ANSIColor::VERSION, "\n";'

perl -M

モジュールのロードをオプションで指定。

# モジュールのバージョン確認 v2
perl -MTerm::ANSIColor -e 'print $Term::ANSIColor::VERSION, "\n";'

perl -le

処理後にprint $/してくれる。デフォルトでは$/は改行コードなので、改行されます。

# モジュールのバージョン確認 v3
perl -MTerm::ANSIColor -le 'print $Term::ANSIColor::VERSION;'

# インストール済みCPANモジュール一覧表示
# https://gist.github.com/s-shin/10267831
perl -MExtUtils::Installed -le 'print join "\n" => sort ExtUtils::Installed->new->modules;'

perl -ne

ループ内while (<>) { HERE }のような感じでコードを評価。

# $_には"foo\n"と"bar\n"が渡る。
echo -e "foo\nbar" | perl -ne 'print $_'

perl -pe

ループ内while (<>) { HERE; print $_; }のような感じでコードを評価。

# $_には"foo\n"と"bar\n"が渡る。処理後の$_は自動的にprintされる。
echo -e "foo\nbar" | perl -pe 's/^(.*)$/$1\n/g'

perl -ple

ループ内while (<>) { chomp; HERE; print $_, "\n"; }のような感じでコードを評価。

# $_には"foo"と"bar"が渡る。処理後の$_は自動的にsayされる。
echo -e "foo\nbar" | perl -ple 's/^(.*)$/$1\n/g'

perl -i

ファイルによる入出力。

# "[...]"を"{...}"に置換。ファイルはa.txtに上書き。
perl -i -ple 's/\[(.*)\]/{$1}/g' a.txt

# "[...]"を"{...}"に置換。a.txtに上書きされるが、元ファイルはa.txt.bkとしてコピーされる。
perl -i.bk -ple 's/\[(.*)\]/{$1}/g' a.txt

perl -s

変数を外部から与えられる。ダブルクオートでシェル変数を埋め込むとエスケープ地獄で頭がおかしくなりそうな時に便利。

a=o; echo foo | perl -sple 's/$re/a/g' -- -re="$a"

しーぱんおーさーになってみた

いわゆるCPAN Authorデビューしたのでその記録。

何作ったのか

RNCryptorというAESのベストプラクティス的なファイルフォーマット及びiOSライブラリがあるのですが、

The primary target is Objective-C, but implementations are available in C++, C#, Java, PHP, Python, Javascript, and Ruby.

RNCryptor/RNCryptor · GitHub

Perl版が無い…ということでRNCryptorフォーマットを取り扱うためのPerlモジュールを作りました。その名もCrypt::RNCryptorです。



余談:暗号化の面倒くさいお話

何故にこんなものを作ったのかというと、最近、PerliOSAndroid共通鍵暗号のAESを扱う機会があったのですが、AESもとい暗号化というものは想像以上に面倒ということが分かり、いい感じのライブラリを探していたらRNCryptorに辿り着いたものの、Perlの実装がなかったというわけです。

もっとも、実際の所、Perlだけで暗号化・復号する分にはそれ程面倒ではないです。
AESであれば、Crypt::CBC-cipher => 'Crypt::OpenSSL::AES'を指定すれば後はライブラリがよしなにやってくれます。

ですが、これを別のプラットフォームに送るとなるとこれが結構厄介で、色々取り決めが必要となります。

例えばAESの場合、暗号化を行う際に考慮すべきファクターは、ざっと思いつくだけでも以下のようになります。

  • 暗号利用モードをどうするか
    • 上でCrypt::CBC使えば簡単なんて書きましたが、そもそもCBCというのは所謂「暗号利用モード」の1つでしかなく、他にもECBなど色々あります。
    • 今はCBCが主流っぽい?
  • 鍵の長さをどうするか
    • 今は32文字*1のAES256が主流っぽい?
  • 鍵をどう取り扱うか
    • 最初から32文字で生成し、やりとりするのか。
    • 適当な文字列からハッシュで32文字にするのか。
      • Saltは付けるのか。付けるならどうやって渡すのか。
    • ハッシュ化のアルゴリズムはHexなMD5?SHA256?PBRDF2?Bcrypt?
      • ストレッチング(ハッシュの繰り返し)する場合、その回数は?
  • IVをどうするか
    • 使わない(全部0固定にする)のか、使うならどうやって渡すのか。
    • (そもそもIVとか初耳だった…)
  • paddingをどうするか
  • 等々

いやはや面倒ですね。

てなわけで、RNCryptorはこの辺りをトレンドを踏まえつついい感じに決めてくれています。

実は、OpenSSLも独自の取り決めを作っており、

'Salted__' + Salt(8 byte) + CipherText(16 x n byte)
OpenSSLの暗号文をJava/Perl/Rubyで開く - mixi Engineers' Blog

というヘッダを暗号化データに付けるようですが、それ以外についてはストレッチング1回とか、ある程度決めの部分があるようです。詳しくは以下の記事をば*2

RNCryptorはOpenSSLより汎用的*3で頑強な*4設計になっています。
そしてなによりObjective-CJavaのライブラリが既にあるのが一番大きな強みです。

閑話休題

CPANモジュールの作り方

モジュールの作成には、tokuhirom氏謹製のMinillaを使いました。

この手の支援ツールはExtUtils::MakeMakerやShipItなど色々あるようですが*5、Minillaはその中でも最も新しい統合的なオーサリンツールといえるかと思います。

Minillaの基本はこんな感じです。

# インストール
cpanm Minilla
# 大枠作成
minil new Crypt::RNCryptor
cd Crypt-RNCryptor
# 好みのエディタでコード書く
atom .
# テスト
minil test
# リリース
minil release

Minilla Tips

慣れるまで戸惑う点が結構あったので記録しておきます。

README.mdは直接いじらない

メインモジュール(例えばCrypt::RNCryptor)のPODが自動でREADME.mdとして出力されます。

Travis CIを使う

シンプルなモジュールなら自動生成の.travis.ymlで問題無いです。

README.mdにバッジを表示したい場合は、minil.tomlに

badges = ["travis"]

を追記します。ここを変えればcoverallsのバッジも置けます。

テスト

minil testはgitリポジトリの今の状態をサンドボックス環境へ持ってきて、その中でテストしてくれます。そのためか、新規ファイルはgit addしておく必要があります。

サンドボックスが必要ないのであれば、普通にproveしても問題無いです。

余談ですが、proveする際には、Test::Prettyを入れて、.provercを以下のようにすると幸せになれます。

--lib
--color
--failures
--trap
-P Pretty
--verbose
$VERSIONは触らない。

Minillaが勝手にインクリメントとかするようなので、手動での変更は必要ありません。

gitでバージョンのtagは付けない

minil release時に自動的に付けられるので、必要ありません。

Changesの編集

この辺りの仕組みはよくわかっていないのですが、ChangesというのはCPANのSpecial Filesの1つで、CPANにアップする際には、Changesファイルに変更内容を記述するのが慣例のようです。

この時、タイムスタンプを入れる必要がありますが、これをMinillaが自動的に入れてくれます。
minil relase前に{{$NEXT}}の下に色々書くよう習慣づければ良さそうです。

{{$NEXT}}

    - write something
minil release時の"missing user argument ... UploadToCPAN.pm"エラー

よっしゃ書いた書いた公開しちゃうぜー、というノリでminil releaseしたら出てきたエラーです*6

結論から言えば、~/.pauseファイル(PAUSEに関しては後述)が無いor記述が足りない場合に出ます。

minil releaseするには、以下のような~/.pauseを作成しておく必要があります。

user sshin
password himitsu

しかし、生のパスワードを書くのは抵抗があるのですが、何とかならないのでしょうかね。今のところ対応策が見つけられてないのですが…仕方ないので、releaseの時だけ書いて、終わったら消してます。

PAUSEに登録

gemsとかnpmにはモジュールを公開するのにユーザ登録が必要ですが、CPANにももちろんあります。それがPAUSE(The [Perl programming] Authors Upload Server)*7です。

少し驚きだったのは、歴史が長いからかアクティブユーザ数が少ないからかは分かりませんが、何かと人によるチェックが入るところです。そして登録フローもまたアナログです*8

人が絡む最大のメリットは世界のPerl Mongers達がdisってくれることらしいです。

DISられるということは、それだけドキュメントやコードをを読んでいただいている証拠...だと思うので、DISには感謝しましょう。

何事からも学び、そして感謝するのです。謙虚な姿勢が大事なのです。アザマス!!

「CPAN Author になったよ」のつづき - hayajoのはてなブログ

cpan disられる - Google 検索

Minilla使えば、コード関係ない所でdisられることはなくなるんじゃないかな(汗。

モジュール公開までの流れ

一応、公開までの流れを簡単に書いておきます。

参考:[Perl] 作成したモジュールをCPANで公開する手順

  1. PAUSE登録。人のチェックが入るっぽいが、完了までそんなに時間はかからなかった。
  2. パスワード変えたり、プロフィール変えたり。
  3. tarballのアップ。minil releaseでサクッと。PAUSE上でもできるみたい*9
  4. ネームスペースの申請。 これが通過して初めてCPAN上で閲覧可能になる。待ち時間は半日ほど?

感想

Minilla様々です。
開発・公開のフローもこういったツール使うことで、他の言語と大差無いように思います。

CPAN登録するとハッカー気取りになれるので、2日ぐらいでちゃっちゃと作ってアップしてみると良いんじゃないかと思いました(適当)。

以上。

*1:正確には32バイト。ASCIIである必要ないので。

*2:必読

*3:v3で10000回のストレッチング、v3.1では調整もできる。これらの値はヘッダに入る

*4:HMACでとったハッシュを末尾に付ける等

*5:参考:http://gihyo.jp/dev/serial/01/modern-perl/0026

*6:依存関係のエラーも何度か出ました

*7:何をpauseするの?みたいな感じで最初意味が分かりませんでした

*8:というかサイトが既にアレゲPerlらしいといえばPerlらしいですが。初見うぉっとなります。

*9:というかこっちが正式な方法