📜 ⬆️ ⬇️

X-Notifier. We write notification for tracker and dialogues on Khabarakhabr


There is a good plugin for all popular browsers, X-Notifier . It allows you to receive notifications about new letters, messages, or about anything from various services in one place. For X-Notifier a lot of scripts are written (Gmail, Yandex. Mail, Google+, Facebook, Twitter and others). But still no one has written a script for Habr, it's time to fix this misunderstanding!

Introduction

The script created by the methods used in this post will most likely work in any browser for which this add-on exists. The script written for Habr, tested only in Firefox and Google Chrome, in the latter it works with restrictions . Also at this stage is supported simultaneous work with only one account. For those who do not want to read the article, but just want an alert, a link to the conclusion .

Study goal

If we describe the process superficially, we need to do the following. Send a request with the data for authorization, get cookies and from time to time get the page of an authorized user and parse the tracker and dialog counters. Everything is extremely simple!
Consider the authorization form on the page https://id.tmtm.ru/login/ (extra details are removed):
The form


<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> 


Here we see 3 visible fields for sending (email, password, recaptcha_response_field), everything is clear with them. As well as 5 hidden (state, consumer, captcha, recaptcha_challenge_field, captcha_type). The state field is a kind of unique identifier that is generated for each login, the consumer for us is a static value and is always equal to habrahabr , the captcha value is always empty, recaptcha_challenge_field unique captcha identifier, captcha_type always recaptcha .
Everything is clear with the form, now let's go to the data for the counter. This is a user panel.
Panel

 <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> 


Everything is simple, we just need to go through the regular line, and grab the tracker and dialog counter if there are any.
We proceed to the implementation.
')
API

The plugin has something like an API, but I could not find documentation for it, and most likely it does not exist. The only thing that was found is a note on how to enable logs and a small post from the add-on developer, but it is only suitable for sites with simple authorization, habr is not one such Therefore, I had to read the source and try, and try ...

Consider the methods to be used.
In total, we need 5 of them:

The list of stages, the number is the sequence of execution:

Some steps, for example, such as ST_LOGIN are implemented by a plugin and are suitable for most sites with simple authorization, but you can override them, which we will do.

We write

First we need to initialize the script. Here we will set some static parameters and the stage from which the script will be executed.
Hidden text
 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"; //       } 


The next step is authorization, all stages are arranged in chronological order:
Hidden text
 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); } 


There are a few points.

The implementation of the login method is very simple:
Hidden text
 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; } 


And finally, the last method, parsing counters:
Hidden text
 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; } } 


There’s nothing much to explain here, just select the values ​​with regular expressions, and return the result.

Conclusion

In this post, an example was shown how to write a simple script to check the site for new messages. Following these rules, you can write a script for almost any site. Some scripts will be much easier to write, especially if the site has a simple authorization scheme (for example, the script for Yandex.Mail works in 30 lines).


The ready script for Habr can be downloaded from the scripts page for X-Notifier or taken on GitHub . Forks and pull requests are welcome.
Add-on page .

Source: https://habr.com/ru/post/210020/


All Articles