e-typing(イータイピング)で好きな例文を入力できるように改造してみた
- 2019-12-29
e-typingは有名なタイピング練習サイトです。
e-typingでは季節、時期によってタイピング練習の例文が変わるので、飽きはしませんが自分で例文を作ったりすることはできません。
自分で作った例文入力できたら面白そうだなと思っていじってみたのでその記録をここに残しておきます。
結果的には成功に終わったのですが、少し大変な道のりだったので興味のある方は読んでみてくださいね。
e-typingの仕組みを知る
まず改造するにしてもe-typingの仕組みを知る必要がありました。
どれがメインのJSファイルなのか?
タイピングの例文データはどこにあってどういった形式なのか?
これがわからないと改造することはできないので。
iframeが使用されている
お馴染みのタイピング画面がこれですが、実はタイピング画面は別のページにあって、それをiframeで表示しているのです。
なのでタイピング画面をそのまま開くと以下のような画面いっぱいサイズになります。
iframeのままだといろいろと解析するときに色々めんどくさいのでタイピング画面をそのまま開くという作業をしました。
開発者ツールで例文データを調べる
ウェブサイトの解析に大変役立つのがChromeの開発者ツール。
もうこれなしでは生きていけないかもしれませんw
まずタイピング画面のページをロードしたときに設定データを取得していることがわかります。
get_typing_setting.aspにリクエストしてデータをもらっています。設定データなので例文データとは別物です。
設定データはそのまま使えるので特に問題なしです。
例文はいつ取得されるのかというとスタートボタンをクリックしたときです。
スタートボタンを押すと同時にget_text_normal.aspにリクエストが送られ、例文データが返ってきています。
ですが、レスポンスをみても「例文データが全く読めない!!」
もしすぐに読める形式なら楽にいじれたのですが、そうはいかないみたいです。
メインのJavaScriptファイルをみつける
例文データをみただけでは理解できないのでJavaScriptをみつけてどういった処理をしているのか解析しないといけません。
そのためにメインのJavaScriptファイルを探す必要があります。
これ自体はけっこう簡単でタイピングページのhtmlをみれば
<script src="./js/app.min.js?c=2019121801"></script>
app.min.jsがメインファイルだと簡単に特定できます。
JavaScriptを解析する
これが一番大変なところでしたね。
jsファイルはminifyされていて読みにくいので解析するのもそれなりに時間がかかります。難読化されていないのでまだマシですけどね。
で、解析してわかったことを先に書いておきますと
- get_text_normal.aspから取得している例文データは暗号化されている
- 例文データにはダミーコードも含まれている
- 例文データには鍵のようなものも含まれており、デコードの際に使用される
get_text_normal.aspからのレスポンスみたときに予想はしてましたが、やはり例文データは暗号化されていましたね。
しかも、ダミーコードや複合化キーのようなものまであるというなかなか面白い仕組みになっておりました。
興味のある人向けに解説したいと思います。JavaScriptとかプログラミングとか正直わからんという人はとばしてください。
e-typingの例文デコード解説
まず暗号化された例文データがこんなかんじ
m_uc=000&m_getsum=15&s0=.....&s1=....
s0=#0#mmdlfjrxeedlekeglkemumbamlevtmhrkmdvamzzgzevtmybmbdmamzzbidlktuzjbevumxbx#1#jcemumvrytdvtxdwwbfvavlsxmdmumwxawfvambuvxevtmyrxpdvtvzzpnemtmhbfyemuvwwcmfmambkitemalgfpwemavxrl#2#mqdbgnbldbfbgklvufebgqldmodbgnxeihebonbxexerskmutqdbgqlbwvdbsqxvqxebskmekeebsqmtqbfrokvzqnfbonlblvfbgnmwvpdrgnvwesebokxbnfdbsqmwnwfbsqlembfrgkrvmbebowguvudbgnbmdlfbgqlgdhfrsnlmj#3#811
m_getsumが例文の数、s0やs1が例文データです。
例文データの分割
例文データには「#0#」、「#1#」、「#2#」、「#3#」といった文字が含まれており、これはデータを分割するために使用されます。
#0#と#1#の間の文字列が普通の例文 #1#と#2#の間の文字列がひらがなの例文(かな表示用) #2#と#3#の間の文字列がローマ字表記の例文(ローマ字表示用) #3#より後がデコードに使用される鍵(複合化キー)
例文データのデコード
デコードには2つの関数が使用されています。
U.prototype._decode = function (t, e) {
// tが例文, eは多分 208 * Number(複合化キー) + 1793 の計算結果
for (var i, n = this._decode2(t).substring(1), a = n.length / 8, s = "", r = 0; a > r; r++) {
i = Number(n.substring(8 * r + 1, 8 * r + 7)) - e, s += String.fromCharCode(i);
}
return s
}
U.prototype._decode2 = function (t) {
for (var e = "", i = t.length, n = 0; i > n; n++) e += this.ht[t.substring(n, n + 1)];
return e
}
ガチで説明するとややこしくて頭から煙が出そうなので簡単に概要だけ説明。
- 暗号化された例文データと鍵が_decode関数に渡される
- _decode2関数に例文を渡すと1文字ずつ数値に変換され、数字だけの文字列が返される(連想配列this.htが定義されていてそれを使って変換される)
- _decode2の戻り値から先頭の1文字だけを削ってnに代入
- nから数字の文字列を6つ取り出す(ダミーコードが3文字ずつ含まれているのでそれは取り出さないようになっている)
- 取り出したものを数値に変換してe(e=
208 * Number(複合化キー) + 1793
)を引き算する - この結果が文字コードでこれを文字に戻すと例文1文字目の複合が完了する
- あとは4~6を繰り返す
だいたいこんな流れです。ちょっとややこしいですが、「こうなってるんだ!」って理解できて楽しかったです。
しかしこれで満足してはいけません!
目的はなんだったでしょうか?そうです。オリジナルの例文でタイピングできるようにすることです。
オリジナル例文を読み込ませる
今考えれば「解読し終わった文をオリジナル例文に書き換えればいいだけじゃん!」と思います。
しかし当時の私は何を思ったのか
オリジナルの例文を解読と真逆の手順をやって暗号化する関数を作ってしまったのですww
発想としては「e-typingは暗号化された例文を読み込んでるから、オリジナル例文も暗号化された状態で読み込ませなきゃ」といったものですね。
そんなめんどいことしなくてもよかったのにww
例文を暗号化するための関数
せっかくなのでここに暗号化するために作った関数を展示しておきます。
U.prototype.pack = function (string) {
let encode = "00";
for (let i = 0, s = ""; i < string.split("").length; i++) {
s = string.substring(i, i + 1).charCodeAt(0);
encode += s + 48801;
if (i < string.split("").length - 1) encode += "000";
}
encode = "2" + encode;
//encode2
let encode2 = "";
var that = this;
for (let i = encode.length, n = 0; i > n; n++) {
encode2 += Object.keys(this.ht).reduce(function(r, k) {
return that.ht[k] == encode.substring(n, n + 1) ? k : r
}, null);
}
return encode2;
}
ダミーコードはなんでもいいので000とかにしてます。複合化キーは固定で226です。
デコードの関数をみながらそれと真逆の動作をする関数を作っただけですが、かなり時間をとられてしまいました。あぁ・・・やらかした。
オリジナル例文導入!
完成したのがこれです。
例文を1つしか用意していないですが無事オリジナル例文でタイピング練習することができました。
例文はjson形式で保存してあり、$.ajaxでGETリクエストして取得しています。
[
[
"オリジナル例文を入力できるよ",
"おりじなるれいぶんをにゅうりょくできるよ",
"orijinarureibunnwonyuuryokudekiruyo"
]
]
JSONの中身はこんなかんじでそのままデータを置いています。
配布について
ウェブサーバーにアップロードすればすぐ使える状態ですが・・・
さすがにマズイかなと思ったのでファイルそのまま配布するのはやめておきます。
もし欲しい方いたらコメントくださいw
最後まで読んでいただきありがとうございました。