Advertisement
stuppid_bot

Untitled

Jan 30th, 2016
318
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // event-emitter.js
  2. // Позволяет создавать свои события типа:
  3. // thisModel.emit('login.fail', obj)
  4. // И отлавливаем:
  5. // thisController.model.on('login.fail', function(error) {
  6. //   *Выводим на экран ошибку*
  7. // })
  8. function EventEmitter() {
  9.   this.__listeners = {};
  10. }
  11.  
  12. function EventListener(fn, scope, once) {
  13.   this.fn = fn;
  14.   this.scope = scope;
  15.   this.once = once;
  16. }
  17.  
  18. EventEmitter.prototype = {
  19.   /* Вызывает fn в контексте scope при возникновении события type. Если
  20.    * once == true, то выполнится всего один раз.
  21.    */
  22.   on: function(type, fn, scope, once) {
  23.     var index = this.__indexOf(type, fn);
  24.     if (index != -1) {
  25.       // Если обработчик уже задан, то обновляем scope и once для слушателя
  26.       var listener = this.__listeners[type][index];
  27.       listener.scope = scope;
  28.       listener.once = once;
  29.     } else {
  30.       var listeners = this.__listeners[type] || (this.__listeners[type] = []);
  31.       // Добавляем нового слушателя
  32.       var listener = new EventListener(fn, scope, once);
  33.       listeners.push(listener);
  34.     }
  35.     return this;
  36.   },
  37.   /* Вызывает fn в контексте scope при возникновении события type один раз. */
  38.   once: function(type, fn, scope) {
  39.     return this.on(type, fn, scope, true);
  40.   },
  41.   /* Удаляет всех слушателей, либо удаляет слушателей для события type, либо
  42.    * удаляет слушателя с обработчиком fn для события type.
  43.    */
  44.   off: function(type, fn) {
  45.     if (!arguments.length) {
  46.       // .off() - удаляем всех слушателей
  47.       this.__listeners = {};
  48.     } else if (arguments.length == 1) {
  49.       // .off(type) - удаляем слушателей для события type
  50.       if (this.__listeners.hasOwnProperty(type)) {
  51.         delete this.__listeners[type];
  52.       }
  53.     } else {
  54.       // .off(type, fn) - удаляем слушателя для события type с обработчиком fn
  55.       var index = this.__indexOf(type, fn);
  56.       if (index != -1) {
  57.         // Удаляем обработчик
  58.         this.__listeners[type].splice(index, 1);
  59.         if (!this.__listeners[type].length) {
  60.           // Если массив слушателей пуст, то удаляем свойство с именем type
  61.           delete this.__listeners[type];
  62.         }
  63.       }
  64.     }
  65.     return this;
  66.   },
  67.   /* Генерирует событие type и вызывает их обработчики. В функцию обработчик
  68.    * передаются аргументы после type.
  69.    */
  70.   emit: function(type, args) {
  71.     if (this.__listeners.hasOwnProperty(type)) {
  72.       args = [].slice.call(arguments, 1);
  73.       var i = 0;
  74.       var listeners = this.__listeners[type];
  75.       while (i < listeners.length) {
  76.         var listener = listeners[i];
  77.         listener.fn.apply(listener.scope || this, args);
  78.         if (listener.once) {
  79.           // Если обработчик должен выполниться лишь один раз, то удаляем
  80.           // слушателя
  81.           listeners.splice(i, 1);
  82.         } else {
  83.           ++i;
  84.         }
  85.       }
  86.       if (!listeners.length) {
  87.         // Если массив слушателей пуст, то удаляем свойство с именем type
  88.         delete this.__listeners[type];
  89.       }
  90.     }
  91.     return this;
  92.   },
  93.   __indexOf: function(type, fn) {
  94.     if (this.__listeners.hasOwnProperty(type)) {
  95.       var listeners = this.__listeners[type];
  96.       var i = listeners.length;
  97.       while (i--) {
  98.         if (listeners[i].fn === fn) {
  99.           return i;
  100.         }
  101.       }
  102.     }
  103.     return -1;
  104.   }
  105. };
  106.  
  107. EventEmitter.mixin = function(obj) {
  108.   if (typeof obj == "function") {
  109.     obj = obj.prototype;
  110.   }
  111.   var proto = new EventEmitter();
  112.   for (var i in proto) {
  113.     obj[i] = proto[i];
  114.   }
  115.   return obj;
  116. };
  117.  
  118. var testEvents = {};
  119. EventEmitter.mixin(testEvents);
  120. // End event-emitter.js
  121. // =============================================================================
  122. // http.js
  123. // Набор функций для работы с сетью
  124. // .import "http.js" as http
  125. function encodeQueryParameters(parameters) {
  126.   var pairs = [];
  127.   for (var i in parameters) {
  128.     if (parameters.hasOwnProperty(i)) {
  129.       var name = encodeURIComponent(i);
  130.       var value = encodeURIComponent(parameters[i]);
  131.       pairs.push(name + '=' + value);
  132.     }
  133.   }
  134.   return pairs.join('&');
  135. }
  136.  
  137. function parseQueryString(str) {
  138.   var pairs = str.split("&");
  139.   var ret = {};
  140.   for (var i = 0; i < pairs.length; ++i) {
  141.     var pair = pairs[i].split('=', 2);
  142.     var name = decodeURIComponent(pair[0]);
  143.     var value = pair.length == 2 ? decodeURIComponent(pair[1]) : '';
  144.     ret[name] = value;
  145.   }
  146.   return ret;
  147. }
  148.  
  149. function request(method, url, callback, headers, data) {
  150.   var xhr = new XMLHttpRequest();
  151.   xhr.open(method, url);
  152.   xhr.onload = function() {
  153.     if (typeof callback == "function") {
  154.       try {
  155.         xhr.responseJSON = JSON.parse(xhr.responseText);
  156.       } catch (e) {}
  157.       var data = xhr.responseJSON || xhr.responseText;
  158.       callback(data, xhr.status, xhr);
  159.     }
  160.   };
  161.   if ({}.toString.call(headers) == "[object Object]") {
  162.     for (var i in headers) {
  163.       if (headers.hasOwnProperty(i)) {
  164.           xhr.setRequestHeader(i, headers[i]);
  165.       }
  166.     }
  167.   }
  168.   xhr.send(data);
  169. }
  170.  
  171. function get(url, callback, parameters, headers) {
  172.   if ({}.toString.call(parameters) == "[object Object]") {
  173.     parameters = encodeQueryParameters(parameters);
  174.     url += (url.indexOf('?') == -1 ? '?' : '&') + parameters;
  175.   }
  176.   request('GET', url, callback, headers);
  177. }
  178.  
  179. function post(url, callback, data, headers) {
  180.   if ({}.toString.call(data) == "[object Object]") {
  181.     data = encodeQueryParameters(data);
  182.     headers = headers || {};
  183.     // Если content-type уже задан, то его значение будет выглядеть как:
  184.     // <someshit>, application/x-www-form-urlencoded
  185.     headers["Content-Type"] = "application/x-www-form-urlencoded";
  186.   }
  187.   request('POST', url, callback, headers, data);
  188. }
  189.  
  190. // tests
  191. // Open link <https://httpbin.org> and run this code in the console
  192. get('/get?foo', function(data) {
  193.   console.log(data.args);
  194. }, {bar: 'quix'});
  195.  
  196. post("/post", function(data, status, xhr) {
  197.   console.log(data.form);
  198. }, {foo: 'bar'});
  199. // End http.js
  200. // =============================================================================
  201. // Минимальная реализация работы с Api Вконтакте. Для примера.
  202. var API_VERSION = 5.44;
  203. var API_URL = "https://api.vk.com/method";
  204. var API_DELAY = 0.34; // около 3-х запросов в секунду
  205. var AUTH_URL = "https://oauth.vk.com/token";
  206. var CLIENT_ID = 2274003;
  207. var CLIENT_SECRET = "hHbZxrka2uZ6jB1inYsH";
  208.  
  209.  
  210. function VkApi(accessToken, userId, apiVersion) {
  211.   this.accessToken = accessToken;
  212.   this.userId = userId;
  213.   this.apiVersion = apiVersion || API_VERSION;
  214. }
  215.  
  216. VkApi.prototype = {
  217.   /* Вызывает метод Api */
  218.   apiCall: function(method, callback, params) {
  219.     // foo/bar -> foo/bar/
  220.     var self = this;
  221.     var endpoint = API_URL.replace(/(\/|)$/, '/') + method;
  222.     // При асинхронных запросах не поможет
  223.     post(endpoint, function(data, status, xhr) {
  224.       console.log(xhr);
  225.       callback(data.response, data.error);
  226.     }, params);
  227.   }, // end apiCall
  228.   // Подразумевается, что через графический интерфейс будем работать
  229.   login: function(username, password, captchaKey, captchaSid) {
  230.     var self = this;
  231.     var params = {
  232.       v: self.apiVersion,
  233.       client_id: CLIENT_ID,
  234.       client_secret: CLIENT_SECRET,
  235.       grant_type: "password",
  236.       username: username,
  237.       password: password
  238.     };
  239.     if (captchaKey && captchaSid) {
  240.       params['captcha_key'] = captchaKey;
  241.       params['captcha_sid'] = captchaSid;
  242.     }
  243.     get(AUTH_URL, function(response) {
  244.       console.log(response);
  245.       if (response.error) {
  246.         self.emit("login.fail", response);
  247.         return;
  248.       }
  249.       self.accessToken = response.access_token;
  250.       self.userId = response.user_id;
  251.       // там еще expires_in остался, но он равен 0 для офиц. приложений
  252.       self.emit("login.success");
  253.     }, params)
  254.   }, // end login
  255. };
  256.  
  257. // Добавляем события
  258. EventEmitter.mixin(VkApi);
  259. var vk = new VkApi();
  260.  
  261. vk.on('login.fail', function(response) {
  262.   // Показываем ошибку
  263.   console.warn("Vk Authentication Error: " + response.error +
  264.     (response.error_description ? ": " + response.error_description : ""));
  265. });
  266.  
  267. vk.on('login.success', function() {
  268.   // Скрываем окно авторизации
  269. });
  270.  
  271. // Вызовет ошибку капчи
  272. vk.login(1, 1);
  273.  
  274. // У Вконтакте существует лимит на отправку запросов в секунду с одного ip,
  275. // поэтому нам нужно чтобы запросы отправлялись строго по очереди с задержками.
  276. // var delay = self.apiDelay + self._lastApiRequest - Date.now();
  277.  
  278. function ApiQueue(api, delay) {
  279.   this.api = api;
  280.   this.delay = delay || API_DELAY;
  281.   // Очередь запросов
  282.   this._queue = [];
  283.   // Объект с которым мы работаем
  284.   this._current = null;
  285.   this._start = function() {};
  286.   this._finish = function() {};
  287.   this._except = function() {};
  288. }
  289.  
  290. ApiQueue.prototype = {
  291.   // Добавляет вызов метода в очередь
  292.   add: function(method, callback, params) {
  293.     this._queue.push({
  294.       method: method,
  295.       callback: callback,
  296.       params: params,
  297.     });
  298.     return this;
  299.   },
  300.   // Извлекает первый элемент очереди и делает его текущим
  301.   next: function() {
  302.     if (this._queue.length) {
  303.       this._current = this._queue.shift();
  304.       this._execute();
  305.       return;
  306.     }
  307.     // Если очередь закончилась
  308.     this._finish.call(this);
  309.   },
  310.   // Вызвать текущий метод еще раз
  311.   repeat: function() {}
  312.   // Очистить очередь
  313.   clear: function() {
  314.     this._queue = [];
  315.     return this;
  316.   },
  317.   // Выполнится, если очередь закончилась
  318.   finish: function(callback) {
  319.     this._finish = callback;
  320.     return this;
  321.   },
  322.   // Вызовет обработчик ошибки
  323.   error: function() {
  324.     this._except.apply(this, arguments);
  325.   },
  326.   // Установить обработчик ошибок
  327.   except: function(callback) {
  328.     this._except = callback;
  329.     return this;
  330.   },
  331.   _execute: function() {
  332.     //
  333.   },
  334. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement