
すべての一般的なブラウザに適したプラグインX-Notifierがあります。 これにより、新しいレター、メッセージ、およびさまざまなサービスに関するあらゆるものの通知を1か所で受け取ることができます。 X-Notifier用の多くのスクリプトが作成されています (Gmail、Yandex.Mail、Google +、Facebook、Twitterなど)。 しかし、Habr用のスクリプトを作成した人はいません。この誤解を修正する時です。
エントリー
この投稿で使用されているメソッドによって作成されたスクリプトは、このアドオンが存在するどのブラウザーでも動作する可能性があります。 Habr用に記述されたスクリプトは、FirefoxとGoogle Chromeでのみテストされ、後者では制限付きで動作します 。 また、この段階では、一度に1つのアカウントのみがサポートされます。 記事を読みたくないが、通知デバイスだけが欲しい人のために、結論へのリンク 。
目標研究
プロセスを表面的に説明する場合、次のことを行う必要があります。 認証データを含むリクエストを送信し、Cookieを受信し、認証されたユーザーページを時々受信し、トラッカーとダイアログカウンターを解析します。 すべてが非常に簡単です!
ページhttps://id.tmtm.ru/login/の承認フォームを検討してください (追加の詳細は削除されています)。
形

<form novalidate="" data-remote="true" method="post" id="login_form" class="s-form login_form validateble" action="/ajax/login/"> <input type="hidden" value="180351c318af67fa0ec59ecad9ebae72" name="state"> <input type="hidden" value="habrahabr" name="consumer"> <div class="s-field s-with-error"> <input type="email" data-validate_url="/ajax/validate/email/" id="email_field" tabindex="1" autofocus="" data-required="true" name="email" placeholder="E-mail" value=""> </div> <div class="s-field s-with-error"> <input type="password" tabindex="2" name="password" data-required="true" placeholder="" value=""> </div> <div class="s-field"> <input type="hidden" name="captcha"> <input type="hidden" id="recaptcha_challenge_field" name="recaptcha_challenge_field"> <input type="text" name="recaptcha_response_field" id="recaptcha_response_field" data-required="true" placeholder=" " value="" autocomplete="off" tabindex="3"> <div class="icon_captcha"></div> <script src="//www.google.com/recaptcha/api/challenge?k=6LftHuoSAAAAAORONRXn_6xb2f_QCtXqfbRPfY2e" type="text/javascript"> </script> <input type="hidden" value="recaptcha" name="captcha_type"> </div> </form>
ここには、送信用の3つの表示フィールド(電子メール、パスワード、recaptcha_response_field)がありますが、それらはすべて明確です。 また、5つの非表示のもの(state、consumer、captcha、recaptcha_challenge_field、captcha_type)。
state
フィールドは、ログインごとに生成される一意の識別子です。
consumer
は静的な値であり、
habrahabr
と常に等しく、
captcha
値は常に空です
recaptcha_challenge_field
一意のcaptcha識別子です
captcha_type
常に
captcha_type
同じ
recaptcha
。
フォームのすべてが明確になったので、カウンターのデータに移りましょう。 これはユーザーパネルです。
パネル

<div class="userpanel silver"> <div class="bottom"> <a href="http://habrahabr.ru/tracker/"></a> <a class="count" href="http://habrahabr.ru/tracker/">+2</a> <a href="http://habrahabr.ru/conversations/"></a> <a href="http://habrahabr.ru/users/BloodUnit/favorites/"></a> </div> </div>
ここではすべてが簡単です。レギュラーシーズンに合わせて、トラッカーのカウンターとダイアログがあればそれを取得するだけです。
実装に取りかかりましょう。
API
プラグインにはAPIのようなものがありますが、そのドキュメントは見つかりませんでした。 発見された唯一のことは、アドオン開発者からのログと小さな投稿を有効にする方法に関するメモでしたが、それは単純な承認を持つサイトにのみ適しており、それらの1つではありません。 したがって、 ソースを読んで試してみなければなりませんでした...
使用する方法を検討してください。
合計で、5つ必要です。
- init() -スクリプト初期化メソッド、起動時に1回実行
- getCount(aData) -文字列(通常はHTML)を受け取り、カウンターを返すメソッド。 counter> = 0の場合、検証は成功しました。それ以外の場合、検証は失敗しました
- checkLogin(aData、aHttp) -ログイン状態、aData文字列(通常はHTML)、aHttp XMLHttpRequestオブジェクトを確認します
- プロセス(aData、aHttp) -メソッドはプラグインの操作の各段階(リストは以下)で起動され、aDataはデータ文字列(通常はHTML)、aHttpはXMLHttpRequestオブジェクトです
- dlog(name、data) -ログに書き込むためのメソッド。2つの文字列パラメーターを取ります
ステージのリスト、番号は実行のシーケンスです:
- ST_CHECK = 0-認証チェック
- ST_PRE = 100-ログインの準備
- ST_PRE_RES = 101-前の段階で起動されたリクエストからの応答を受信する
- ST_LOGIN = 200-ログイン
- ST_LOGIN_RES = 201-前の段階で起動されたリクエストからの応答を受信する
- ST_DATA = 300-未読メッセージのカウントなど、処理するデータを要求します
- ST_DATA_RES = 301-前の段階で起動されたリクエストからの応答を受信する
たとえば、ST_LOGINなどの一部のステージはプラグインによって実装され、単純な承認を持つほとんどのサイトに適していますが、それらを再定義できます。
書く
まず、スクリプトを初期化する必要があります。 ここでは、いくつかの静的パラメーターと、スクリプトが実行されるステージを設定します。
非表示のテキスト
function init() { this.initStage = ST_PRE; // , ST_LOGIN, , this.loginData = ["https://id.tmtm.ru/ajax/login/", "email", "password", "consumer=habrahabr&captcha_type=recaptcha&captcha="]; // URL , name e-mail , this.dataURL = "http://habrahabr.ru/"; // URL this.viewURL = "http://habrahabr.ru/tracker/"; // URL this.cookieDomain = "habrahabr.ru"; // }
次のステップは承認です。すべてのステージは時系列に配置されます。
非表示のテキスト
function process(aData, aHttp) { switch (this.stage) { /* , state */ case ST_PRE: this.getHtml("https://auth.habrahabr.ru/login/"); return false; /* , state recaptcha, */ case ST_PRE_RES: var recaptchaScriptLink = aData.match(/(\/\/www.google.com\/recaptcha\/api\/challenge\S+?)"/); var state = aData.match(/state=([\w\n]+)/); if (recaptchaScriptLink && state) { this.originPostData = this.loginData[LOGIN_POST]; this.loginData[LOGIN_POST] += "&state=" + encodeURIComponent(state[1]); this.referer = this.loginData[LOGIN_URL] + "?" + "&state=" + encodeURIComponent(state[1]) + "&consumer=habrahabr"; this.getHtml("https:" + recaptchaScriptLink[1]); return false; } this.onError(); break; /* */ case ST_PRE_RES + 1: var recaptchaUid = aData.match(/challenge\s*:\s*'(\S+?)'/); if (recaptchaUid) { this.loginData[LOGIN_POST] += "&recaptcha_challenge_field=" + encodeURIComponent(recaptchaUid[1]); this.openCaptchaDialog(this.id, this.user, "https://www.google.com/recaptcha/api/image?c=" + recaptchaUid[1]); return false; } this.onError(); break; /* */ case ST_PRE_RES + 2: this.loginData[LOGIN_POST] += "&recaptcha_response_field=" + encodeURIComponent(aData); this.stage = ST_LOGIN; return this.process(aData, aHttp); break; /* */ case ST_LOGIN: this.getHtml(this.loginData[LOGIN_URL], this.loginData[LOGIN_POST], { Referer: this.referer }); return false; /* */ case ST_LOGIN_RES: this.loginData[LOGIN_POST] = this.originPostData; var habrRedirectLink = aData.match(/'(.*?)'/); if (habrRedirectLink) { this.getHtml(habrRedirectLink[1]); } this.stage = ST_DATA; return true; } return this.baseProcess(aData, aHttp); }
いくつかのポイントがあります。
- Javascriptはプラグインのコンテキストでは実行されないため、キャプチャへのリンクを取得するには追加のジェスチャーを行う必要があります
- ステップが
false
返す場合、シーケンス値は増加します。 -
this.getHtml
およびthis.openCaptchaDialog
メソッドが返すデータは、次のステップに渡されます -
ST_LOGIN
では、Refererの値を設定する必要があります。設定しないと、認証が失敗します。 Google Chromeでは、このパラメーターを設定することはできません(作業ドラフトではこれが標準です )。それぞれ、 プラグインによる認証は機能しませんが、サイトにログインしている場合はすべて正常に機能します。 -
ST_LOGIN
ステージで、Habrは、次のようなメインスクリプトへのリダイレクトを含むスクリプトを返します。
非表示のテキストwindow.location.href = 'https://habrahabr.ru/ac/entrance/?token=5a15a5d48c7fdeaed5ab20e852107dc6&state=26593fdea0963d8241aab3f20a6893b4&time=1390388377&sign=bb8f45d63c768ed6aebc5ae2bb22de3b';
ログイン検証メソッドの実装は非常に簡単です。
非表示のテキスト
function checkLogin(aData, aHttp) { switch (this.stage) { /* HTML */ case ST_CHECK: this.getHtml(this.dataURL); return false; /* , , */ case ST_CHECK + 1: var loginLink = aData.match(/<a.+?class="login"/); if (!loginLink) { this.stage = ST_DATA; this.getHtml(this.dataURL); return true; } else { this.stage = this.initStage; return this.process(""); } } this.onError(); return true; }
最後に、カウンターを解析する最後のメソッド:
非表示のテキスト
function getCount(aData) { var userMenu = aData.match(/userpanel[\s\S]*?charge_string/); if (!userMenu) { return -1; } else { var counter = 0; var counterRegex = /class="count"[^>]*>\+?(\d*)/g var counterResult; while ((counterResult = counterRegex.exec(userMenu[0])) !== null) { counter += +counterResult[1] || 0; } return counter; } }
ここで説明することはあまりありません。正規表現で値を選択し、結果を返します。
おわりに
この投稿では、新しいメッセージがないかサイトをチェックする簡単なスクリプトを作成する方法の例を示しました。 これらの規則に従って、ほとんどすべてのサイトのスクリプトを作成できます。 一部のスクリプトは、特にサイトに単純な承認スキームがある場合(たとえば、Yandex.Mailのスクリプトが30行に収まる場合)に、はるかに簡単に記述できます。

Habrの完成したスクリプトは、X-Notifierのスクリプトページからダウンロードするか、GitHubで取得できます 。 フォークおよびプルリクエストは大歓迎です。
アドオンページ