// ==UserScript==
// @name        SaveFrom.net helper
// @namespace   http://savefrom.net/
// @version     7.61.2
// @date        2018-04-17
// @author      Magicbit, Inc
// @description Youtube Downloader: all in one script to get Vimeo, Facebook, Dailymotion videos for free
// @homepage    http://savefrom.net/user.php?helper=userjs
// @icon        http://sf-helper.com/img/icon_16.png
// @icon64      http://sf-helper.com/img/icon_64.png
// @updateURL   https://download.sf-helper.com/chrome/helper.meta.js
// @downloadURL https://download.sf-helper.com/chrome/helper.user.js
// @include     http://*
// @include     https://*
// @run-at      document-end
// @grant       GM_listValues
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_deleteValue
// @grant       GM_xmlhttpRequest
// @grant       GM_info
// @grant       GM_openInTab
// @grant       GM_registerMenuCommand
// @grant       GM_unregisterMenuCommand
// @grant       GM_notification
// @grant       GM_download
// @connect     vk.com
// @connect     vk.me
// @connect     userapi.com
// @connect     vkuseraudio.net
// @connect     vkuservideo.net
// @connect     vk-cdn.net
// @connect     youtube.com
// @connect     youtube-nocookie.com
// @connect     ytimg.com
// @connect     googlevideo.com
// @connect     video.google.com
// @connect     google-analytics.com
// @connect     dailymotion.com
// @connect     vimeo.com
// @connect     vimeocdn.com
// @connect     odnoklassniki.ru
// @connect     ok.ru
// @connect     cdn-ok.com
// @connect     mycdn.me
// @connect     pladform.ru
// @connect     clipyou.ru
// @connect     soundcloud.com
// @connect     sndcdn.com
// @connect     mail.ru
// @connect     cdninstagram.com
// @connect     fbcdn.net
// @connect     facebook.com
// @connect     sf-helper.com
// @connect     savefr.com
// @connect     travelbar.tools
// @connect     savefrom.net
// @connect     self
// @connect     *
// ==/UserScript==

(function() {
  if (typeof JSON === 'undefined') {
    if (window.JSON) {
      JSON = window.JSON;
    } else
    if (document.defaultView && document.defaultView.JSON) {
      JSON = document.defaultView.JSON;
    }
  }

  if (typeof GM_getValue === 'undefined' ||
    typeof GM_setValue === 'undefined' ||
    typeof GM_xmlhttpRequest === 'undefined' ||
    typeof JSON === 'undefined') {
    return console.error('GM API is not ready!');
  }

  var _moduleName = null;

  var _menu;
  var _options;
  var _modules = {};
  var _languageList = {};

  try {
    window.sessionStorage['savefrom-helper-userjs'] = '1';
  } catch (e) {}
  /////////////////////////////////////////////////
  // MENU
  _menu = {
    activeDataAttr: 'data-sfh-active',
    id: 'sfh--ujs-menu',
    tooltipId: 'sfh--ujs-menu-tooltip',
    enabled: true,
    active: false,
    hover: false,
    move: false,
    title: '',
    shakeTimer: 0,
    shakeInterval: 10000,

    menu: null,
    icon: null,

    initMenu: null,

    style: {
      menu: {
        initial: {
          background: '#fff',
          borderStyle: 'solid',
          borderWidth: '2px 0 2px 2px',
          borderRadius: '5px 0 0 5px',
          display: 'none',
          boxSizing: 'content-box',
          font: '13px/18px Arial,Helvetica,sans-serif',
          width: 'auto',
          height: 'auto',
          padding: 0,
          margin: 0,
          overflow: 'visible',
          position: 'fixed',
          top: '50px',
          right: '0',
          textAlign: 'left',
          WebkitTransition: 'all 0.2s',
          transition: 'all 0.2s',
          zIndex: 99999
        },

        enabled: {
          borderColor: '#8dc50b'
        },

        disabled: {
          borderColor: '#d0d0d0'
        },

        tag: {
          display: 'block',
          width: '10px',
          height: '20px',
          overflow: 'hidden',
          opacity: 0.5
        },

        tagHover: {
          width: '20px',
          opacity: 0.8
        },

        active: {
          width: 'auto',
          height: 'auto',
          overflow: 'visible',
          opacity: 0.9
        }
      },

      icon: {
        initial: {
          display: 'inline-block',
          boxSizing: 'content-box',
          backgroundPosition: '50% 50%',
          backgroundRepeat: 'no-repeat',
          width: '16px',
          height: '16px',
          margin: 0,
          padding: '2px',
          overflow: 'hidden',
          verticalAlign: 'middle',
          cursor: 'pointer'
        },

        enabled: {
          backgroundImage: 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABqUlEQVQ4jY2SzStEURiHf2bMl+w0SrHRZKPY+RtkYyeRspPFsEEZItLM3DCRjxofw0wyK0k+ClNGhBiEmIiwsrChZqvj/sZcznDJ4um8532f9+3ccy5isRg0Qre2V67hxyzxnfkHm5AdDcib6SvLC9e5e5v4TujuY4Dm6A4YPc684xq8sb6Fbq1CZkbNyU7aACVqdPhP8usGouZT7qcuLInpuFnITJ6bE6zRocuezwEdS/B2LuO+ewXJY44dmZ795yYhM6LmWKNDlz1pn+D0o6J5FjeMfbvGx9ETg5BhjjU6dHXvQMMdMcZ9BxAy7k1DXM/F0J6tYSxm9wbOHJ65y9Lh4FnJvLKZfa3sQKSh5lijQ5c97EX7GnJ61nHYF4Egni0klG3jk7bXYI41bc8e9iaP0RhArmsR+92rEP+BLnvSL3ESea1h7LoWVOEP6NDVvcTaQRQ4ZxBtCUPowRqdX/9EUtOFwoZxbDTNQsgwx9qPV9B7mqoOFNX3Y61xAoIwZk73GfWSySFtKK7uxSph/Jv3FQAZKgYVk0q2ir2sEuWEcSpnSjkZWt87G7sZgVx6JvgAAAAASUVORK5CYII=)'
        },

        disabled: {
          backgroundImage: 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAiNJREFUeNqMkj+oUlEcx7/nHu/V7lMTxaghqIgoWpIQisCmhjfloDS9QQgMHkpTODc2hS45OQRB6GCLb2hqiAIJpzB6UUhDkqi34/17rtfTonI1ifeDs/zO5/eB8/0dwhjDqjRN+xOLxU4bhiGwVUIIhMNhsmJW/YAfsm1bAIDnedgl8DM7BYZhjAHAdd0FpVTy383n84Wf2RD0er3L8Xj8tq7rDAAcx7EopXtbAgsAdF1ng8HgYDKZfEilUt8CADCbzR7quv5AkqQLAGBZlhUMBjcEjuOsBDcYY0+FEK8BVCQAyGQylel0eqhp2vHynSbnHP5j27a5DPp4Op0eZjKZCgAQ/xZW1e12++Fw+Kq/p+v6l3Q6fW2bDfT7/aKiKBdDoZBQFEX1PC9JCJE45xsgIUQaDoevKKUjzrlp2zbhnP8gnU4nIcvyEaU0vQQNSZJmnued9QsopcPFYhERQuwtV911XXefMMbQbDbPJJPJN7Is38IJynXdj6PR6H4+n/+9zqDdbp9TVbWpKMqd/w1zzt+bppnPZrO//gmx0WicTyQSL0Oh0N1dw7ZtvxuPxweFQuHnOpvtLdTr9UuxWOyFqqr3/H3TNN9qmvaoWCx+3wh31xprtdqVaDT6PBKJ7C8/2hFj7HGpVPq6ze4UAEC1Wr0uy/KzZWhPyuXy513cWhCNRgkAAoACCAI4lcvlbgJAq9X6BMAC4ADwAAjGmACAvwMAXX8khNE72VIAAAAASUVORK5CYII=)'
        },

        tag: {
          padding: '2px'
        },
        active: {
          padding: '5px'
        }
      },

      title: {
        display: 'inline-block',
        font: 'bold 13px/18px Arial,Helvetica,sans-serif',
        lineHeight: '26px',
        margin: 0,
        padding: 0,
        textAlign: 'left',
        verticalAlign: 'middle',
        cursor: 'pointer'
      }
    },

    setTitle: function(title, version) {
      this.title = title;
      if (version)
        this.title += ' ' + version;
    },

    hide: function() {
      if (!this.menu || !document.body)
        return;
      this.menu.parentNode.removeChild(this.menu);
      this.menu = null;
      this.icon = null;
    },

    create: function() {
      if (this.menu || !document.body)
        return;

      this.moduleName = _moduleName;

      var _this = this;

      var menu = document.createElement('div');

      menu.addEventListener('mouseover', function() {
        if (!_this.active) {
          _this.hover = true;
          _this.setElementsStyle('tagHover');
        }
      });

      menu.addEventListener('mouseout', function() {
        if (!_this.active) {
          _this.hover = false;
          _this.setElementsStyle('tag');
        }
      });

      var icon = document.createElement('div');
      icon.title = this.title;

      icon.addEventListener('click', function(event) {
        if (_this.move) {
          return;
        }
        event.preventDefault();
        event.stopPropagation();

        if (event.button === 0) {
          _this.toggleMenuItems();
        } else if (event.button == 2) {
          _this.remove();
        }

        return false;
      }, false);

      icon.addEventListener('contextmenu', function(event) {
        if (_this.move) {
          return;
        }
        event.preventDefault();
        event.stopPropagation();
        _this.remove();
        return false;
      }, false);

      this.icon = menu.appendChild(icon);
      this.menu = document.body.appendChild(menu);

      var iconTopPos = parseInt(_menu.style.menu.initial.top);
      if (iconTopPos < 0) {
        iconTopPos = 0;
      } else
      if (this.moduleName === 'youtube' && iconTopPos < 92) {
        iconTopPos = 92;
      } else
      if (iconTopPos + 24 > parseInt(window.innerHeight)) {
        iconTopPos = parseInt(window.innerHeight) - parseInt(_menu.style.menu.tag.height) - 4;
      }

      _menu.style.menu.initial.top = iconTopPos + 'px';

      this.setElementsStyle('initial');
      this.setEnabled(1);
      this.showTag();
      this.enableMove();
    },

    enableMove: function() {
      var isStart = false;
      var _this = this;
      var icon = _this.icon;
      var menu = _this.menu;
      var startTimer = undefined;
      var sT = (parseInt(menu.style.height) / 2) || 0;
      var noSelectStyle = mono.create('style', {
        text: 'body {-webkit-user-select: none;-moz-user-select: none;-o-user-select: none;user-select: none;}'
      });

      var rbIcon = function() {
        _this.move = false;
        menu.style.position = _this.style.menu.initial.position;
        menu.style.WebkitTransition = _this.style.menu.initial.WebkitTransition;
        menu.style.transition = _this.style.menu.initial.transition;
        menu.style.borderStyle = _this.style.menu.initial.borderStyle;

        if (noSelectStyle.parentNode) {
          noSelectStyle.parentNode.removeChild(noSelectStyle);
        }
      };

      var initIcon = function(e) {
        e.stopPropagation();
        e.preventDefault();

        _menu.hideMenuItems();

        _this.hover = true;
        _this.setElementsStyle('tagHover');

        _this.move = true;
        menu.style.position = 'fixed';
        var eX = e.y || e.clientY;
        menu.style.top = (eX - sT) + 'px';
        menu.style.WebkitTransition = 'initial';
        menu.style.transition = 'initial';
        menu.style.borderStyle = 'dotted';

        document.body.appendChild(noSelectStyle);
      };

      var onMouseMove = function(e) {
        var eX = e.y || e.clientY;
        var topValue = eX - sT;
        if (_this.moduleName === 'youtube' && topValue < 92) {
          topValue = 92;
        } else
        if (topValue < 0) {
          topValue = 0;
        }
        menu.style.top = _this.style.menu.initial.top = topValue + 'px';
      };

      var onStartTimer = function(e) {
        isStart = true;
        initIcon(e);
        document.body.addEventListener('mousemove', onMouseMove);
      };

      menu.addEventListener('dragstart', function(e) {
        e.preventDefault();
      });
      menu.addEventListener('mousedown', function(e) {
        if (e.target !== _this.icon) {
          return;
        }
        isStart = false;
        startTimer = setTimeout(onStartTimer.bind(null, e), 500);
        var ml = function() {
          clearTimeout(startTimer);
          mono.off(menu, 'mouseleave', ml);
        };
        mono.on(menu, 'mouseleave', ml);
        document.body.addEventListener('mouseup', function mu() {
          clearTimeout(startTimer);
          document.body.removeEventListener('mouseup', mu);
          mono.off(menu, 'mouseleave', ml);
          if (isStart) {
            setTimeout(rbIcon, 100);
            document.body.removeEventListener('mousemove', onMouseMove);
            mono.storage.set({
              gmIconTop: parseInt(_this.style.menu.initial.top)
            });
          }
        });
      });
    },

    setStyle: function(element, style) {
      if (this[element] && this.style[element] && this.style[element][style])
        SaveFrom_Utils.setStyle(this[element], this.style[element][style]);
    },

    setElementsStyle: function(style) {
      if (!style)
        return;

      var elements = ['menu', 'icon'];

      for (var i = 0; i < elements.length; i++)
        this.setStyle(elements[i], style);
    },

    setEnabled: function(enabled) {
      this.enabled = enabled;
      this.setElementsStyle(this.enabled ? 'enabled' : 'disabled');
    },

    showTag: function() {
      this.setElementsStyle('tag');
    },

    toggleMenuItems: function() {
      return _menu.active ? _menu.hideMenuItems() : _menu.showMenuItems();
    },

    remove: function() {
      if (_menu.menu)
        _menu.menu.parentNode.removeChild(_menu.menu);

      // _menu.removeTooltip();
    },

    menuHTML: 'PHN0eWxlIHR5cGU9InRleHQvY3NzIj4KLnNmLW1lbnUtY29udGFpbmVyIHsKICAgIHdpZHRoOiA0ODJweDsKICAgIGZvbnQ6IDEycHgvMTdweCBUYWhvbWEsIEhlbHZldGljYSwgT3BlblNhbnMsIHNhbnMtc2VyaWY7CiAgICBjb2xvcjogIzAwMDsKICAgIGJhY2tncm91bmQtY29sb3I6ICNmZmY7CiAgICBtYXJnaW46IDA7CiAgICBib3gtc2l6aW5nOiBpbmhlcml0OwogICAgb3ZlcmZsb3c6IGhpZGRlbjsKICAgIGZsZXgtZGlyZWN0aW9uOiBpbml0aWFsOwp9Ci5zZi1tZW51LWNvbnRhaW5lci5sb2FkaW5nID4gKiB7CiAgICB2aXNpYmlsaXR5OiBoaWRkZW47Cn0KLnNmLW1lbnUtY29udGFpbmVyID4gKiB7CiAgICBib3gtc2l6aW5nOiBpbmhlcml0OwogICAgZmxleC1kaXJlY3Rpb246IGluaXRpYWw7Cn0KLnNmLW1lbnUtY29udGFpbmVyIHAgewogICAgZm9udC1zaXplOiAxMnB4Owp9Ci5zZi1tZW51LWNvbnRhaW5lciBkaXYuc2YtbWVudS1saXN0LAouc2YtbWVudS1jb250YWluZXIgZGl2LnNmLW1lbnUtZGVzYyB7CiAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgICB2ZXJ0aWNhbC1hbGlnbjogdG9wOwogICAgZmxvYXQ6IGxlZnQ7Cn0KLnNmLW1lbnUtY29udGFpbmVyIGRpdi5zZi1tZW51LWRlc2MgewogICAgd2lkdGg6IDE2NnB4OwogICAgcGFkZGluZzogMjBweCAzMHB4OwogICAgcGFkZGluZy1ib3R0b206IDM2cHg7CiAgICBjb2xvcjogIzZhNmE2YTsKfQouc2YtbWVudS1jb250YWluZXIgZGl2LnNmLW1lbnUtZGVzYyBhIHsKICAgIHRleHQtZGVjb3JhdGlvbjogbm9uZTsKICAgIGNvbG9yOiAjNEE5MEUyOwp9Ci5zZi1tZW51LWNvbnRhaW5lciBkaXYuc2YtbWVudS1kZXNjIGE6bm90KC5zb2NpYWwtYnRuKTpob3ZlciB7CiAgICB0ZXh0LWRlY29yYXRpb246IHVuZGVybGluZTsKfQouc2YtbWVudS1jb250YWluZXIgLnNmLW1lbnUtZGVzYyAuaWNvbiB7CiAgICB3aWR0aDogNzRweDsKICAgIGhlaWdodDogNzRweDsKICAgIGRpc3BsYXk6IGlubGluZS1ibG9jazsKICAgIGJhY2tncm91bmQtc2l6ZTogNzRweDsKICAgIGJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7CiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiBjZW50ZXI7CiAgICBwYWRkaW5nOiAwOwogICAgbWFyZ2luOiAwOwp9Ci5zZi1tZW51LWNvbnRhaW5lciAuc2YtbWVudS1kZXNjIC52ZXJzaW9uIHsKICAgIHZlcnRpY2FsLWFsaWduOiB0b3A7CiAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgICBmbG9hdDogcmlnaHQ7CiAgICBtYXJnaW4tcmlnaHQ6IC0zMHB4OwogICAgd2lkdGg6IDExMHB4Owp9Ci5zZi1tZW51LWNvbnRhaW5lciAuc2YtbWVudS1kZXNjIC52ZXJzaW9uID4gc3BhbiwKLnNmLW1lbnUtY29udGFpbmVyIC5zZi1tZW51LWRlc2MgLnZlcnNpb24gPiBhIHsKICAgIGRpc3BsYXk6IGJsb2NrOwp9Ci5zZi1tZW51LWNvbnRhaW5lciAuc2YtbWVudS1kZXNjIC5pY29uIHBhdGggewogICAgZmlsbDogI2NjY2NjYyAhaW1wb3J0YW50Owp9Ci5zZi1tZW51LWNvbnRhaW5lciAuc2YtbWVudS1kZXNjIC50aXRsZSB7CiAgICBmb250LXNpemU6IDIwcHg7CiAgICBsaW5lLWhlaWdodDogMS4yOwogICAgZm9udC13ZWlnaHQ6IG5vcm1hbDsKICAgIG1hcmdpbi10b3A6IDE0cHg7CiAgICBtYXJnaW4tYm90dG9tOiAxNnB4Owp9Ci5zZi1tZW51LWNvbnRhaW5lciAuc2YtbWVudS1kZXNjIC5tb3JlIHsKICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTsKICAgIGJvdHRvbTogNDBweDsKfQouc2YtbWVudS1jb250YWluZXIgLnNmLW1lbnUtbGlzdCB7CiAgICBoZWlnaHQ6IDM0OHB4OwogICAgd2lkdGg6IDI0M3B4OwogICAgZm9udC1zaXplOiAxNHB4OwogICAgcGFkZGluZzogMTRweCA2cHg7CiAgICBib3JkZXItbGVmdDogMXB4IHNvbGlkICNEOEQ4RDg7Cn0KLnNmLW1lbnUtY29udGFpbmVyIC5zZi1tZW51LWxpc3QgLnNlcGFyYXRvciB7CiAgICBib3JkZXItdG9wOiAxcHggc29saWQgI0Q4RDhEODsKICAgIG1hcmdpbi10b3A6IDEwcHg7CiAgICBtYXJnaW4tYm90dG9tOiA5cHg7CiAgICBtYXJnaW4tbGVmdDogNTlweDsKfQouc2YtbWVudS1jb250YWluZXIgLnNmLW1lbnUtbGlzdCAuaXRlbSB7CiAgICBoZWlnaHQ6IDQwcHg7CiAgICBjdXJzb3I6IHBvaW50ZXI7CiAgICBib3JkZXItcmFkaXVzOiA1cHg7CiAgICBtYXJnaW4tdG9wOiAtMnB4OwogICAgbWFyZ2luLWJvdHRvbTogLTJweDsKICAgIG92ZXJmbG93OiBoaWRkZW47CiAgICBkaXNwbGF5OiBibG9jazsKfQoKLnNmLW1lbnUtY29udGFpbmVyIC5zZi1tZW51LWxpc3QgLml0ZW0gLmljb24gewogICAgbWFyZ2luOiAwOwogICAgbWFyZ2luLWxlZnQ6IDE4cHg7CiAgICB3aWR0aDogMjRweDsKICAgIGhlaWdodDogMjRweDsKICAgIG1hcmdpbi1ib3R0b206IDhweDsKICAgIG1hcmdpbi10b3A6IDhweDsKICAgIGZsb2F0OiBsZWZ0OwogICAgZGlzcGxheTogYmxvY2s7CiAgICBwYWRkaW5nOiAwOwp9Ci5zZi1tZW51LWNvbnRhaW5lciAuc2YtbWVudS1saXN0IC5pdGVtIC5sYWJlbCB7CiAgICBwYWRkaW5nLWxlZnQ6IDE4cHg7CiAgICBwYWRkaW5nLXJpZ2h0OiAxOHB4OwogICAgbGluZS1oZWlnaHQ6IDQwcHg7CiAgICBmb250LXNpemU6IDE0cHg7CiAgICB3aGl0ZS1zcGFjZTogbm93cmFwOwogICAgd2lkdGg6IDE2NXB4OwogICAgZGlzcGxheTogaW5saW5lLWJsb2NrOwogICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7CiAgICBvdmVyZmxvdzogaGlkZGVuOwp9Ci5zZi1tZW51LWNvbnRhaW5lciAuc2YtbWVudS1saXN0IC5pdGVtIC5sYWJlbC5kYmwgewogICAgbGluZS1oZWlnaHQ6IG5vcm1hbDsKICAgIHBhZGRpbmctdG9wOiAycHg7CiAgICB3aGl0ZS1zcGFjZTogbm9ybWFsOwogICAgaGVpZ2h0OiA0MHB4Owp9Ci5zZi1tZW51LWNvbnRhaW5lci5uby1wb2xsIC5zZi1tZW51LWxpc3QgZGl2W2RhdGEtYWN0aW9uPSJvcGVuUG9sbCJdIHsKICAgIGRpc3BsYXk6IG5vbmU7Cn0KLnNmLW1lbnUtY29udGFpbmVyLm5vLXBvbGwgLnNmLW1lbnUtbGlzdCAuaXRlbSAuaWNvbiB7CiAgICBtYXJnaW4tYm90dG9tOiAxMHB4OwogICAgbWFyZ2luLXRvcDogMTBweDsKfQouc2YtbWVudS1jb250YWluZXIubm8tcG9sbCAuc2YtbWVudS1saXN0IC5pdGVtIHsKICAgIGhlaWdodDogNDRweDsKfQouc2YtbWVudS1jb250YWluZXIubm8tcG9sbCAuc2YtbWVudS1saXN0IC5pdGVtIC5sYWJlbCB7CiAgICBsaW5lLWhlaWdodDogNDRweDsKfQoKLnNmLW1lbnUtY29udGFpbmVyIC5zZi1tZW51LWxpc3QgLml0ZW06aG92ZXIgewogICAgYmFja2dyb3VuZC1jb2xvcjogIzU5N0E5RTsKICAgIGNvbG9yOiAjZmZmOwp9Cgouc2YtbWVudS1jb250YWluZXIgLnNmLW1lbnUtbGlzdCAuaXRlbS5pbmFjdGl2ZSB7CiAgICBvcGFjaXR5OiAwLjU7CiAgICBjdXJzb3I6IGRlZmF1bHQ7Cn0KLnNmLW1lbnUtY29udGFpbmVyIC5zZi1tZW51LWxpc3QgLml0ZW0uaW5hY3RpdmUgLmljb24gcGF0aCB7CiAgICBmaWxsOiAjYzJjMmMyICFpbXBvcnRhbnQ7Cn0KLnNmLW1lbnUtY29udGFpbmVyIC5zZi1tZW51LWxpc3QgLml0ZW0uaW5hY3RpdmU6aG92ZXIgewogICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZjsKICAgIGNvbG9yOiAjMDAwOwp9Ci5zZi1tZW51LWNvbnRhaW5lciAuc2YtbWVudS1saXN0IC5pY29uW2RhdGEtdHlwZT0ic2hvd0Fib3V0UGFnZSJdIHsKICAgIHZpc2liaWxpdHk6IGhpZGRlbjsKfQoKLnNmLW1lbnUtY29udGFpbmVyIC5zZi1tZW51LWxpc3QgLnNCdG4gewogICAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwp9Ci5zZi1tZW51LWNvbnRhaW5lciAuc2YtbWVudS1saXN0IC5zQnRuOmhvdmVyIHsKICAgIHRleHQtZGVjb3JhdGlvbjogbm9uZTsKfQoKLnNmLW1lbnUtY29udGFpbmVyIC5zb2NpYWwtYmxvY2sgewogICAgcG9zaXRpb246IGFic29sdXRlOwogICAgYm90dG9tOiAyMHB4OwogICAgaGVpZ2h0OiAxNnB4OwogICAgY3Vyc29yOiBkZWZhdWx0OwogICAgZmxleC1kaXJlY3Rpb246IGluaXRpYWw7Cn0KLnNmLW1lbnUtY29udGFpbmVyIC5zb2NpYWwtYnRuIHsKICAgIGRpc3BsYXk6IGlubGluZS1ibG9jazsKICAgIHdpZHRoOiAxNnB4OwogICAgaGVpZ2h0OiAxNnB4OwogICAgYmFja2dyb3VuZC1wb3NpdGlvbjogY2VudGVyOwogICAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDsKICAgIGZsb2F0OiBpbml0aWFsOwogICAgbWFyZ2luOiBpbml0aWFsOwogICAgcGFkZGluZzogaW5pdGlhbDsKICAgIGxpc3Qtc3R5bGU6IGluaXRpYWw7Cn0KLnNmLW1lbnUtY29udGFpbmVyIC5zb2NpYWwtYnRuOmhvdmVyIHsKICAgIG9wYWNpdHk6IDAuODsKfQouc2YtbWVudS1jb250YWluZXIgLnNvY2lhbC1idG4udmsgewogICAgYmFja2dyb3VuZC1pbWFnZTogdXJsKGRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQkFBQUFBUUNBWUFBQUFmOC85aEFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFEc01BQUE3REFjZHZxR1FBQUFBWWRFVllkRk52Wm5SM1lYSmxBSEJoYVc1MExtNWxkQ0EwTGpBdU00em1sMUFBQUFHV1NVUkJWRGhQblpEYks4TmhHTWZmZjBiR1dwSlNTaTJITWt4Q2JvVGsxTWdoaHd0aVkydE5JU0p6YUJlYWFFNjVXRUpJc2h2YWhTS1RjbTdNS1VVT2wxKy81KzJudlc5eXNYM3JVOC96OVBsZXZDOHp1WDM2eG1uL1FiUGJqMGlnRG5WWjVZUXZWREN3ZzJ6SFZrUlFoN29zMTc2QkxOdDZWRkNYWlpxOUVDa2Izb1pyTS9DSHVzazl5ZnVGcFhVc1E2VE50WXYvMGp1M0w3a0UwN2Q1SU5MaTNGUjFZR3pKaDg2SlZieC9mdlBkZjNZbnVRUkxiWEpEcEhsMGpjdVV4bUV2VWt4VENGdzk4SDFsOTFoeUNaWmljaWxTbUlZaEw1Y3BwOWRQT0wxNTVuUHc4UlhwOVU3SkpWaHkxVGhFNnZ0WGVJRVN1THpIL3ZFbDNqNisrTDd0UDVkY2dpV1ZqMERFNUZqa01xWEdPZ05ka1JXdEF3dnFCU2p0OFVnK1N5d1poRWl0M2FPcTREUGRiRlBoZjZtMXowcytTeWp1ZzBpTmRWWlZnWk1MNVFsSFYrb0czSVplb0N1MFNUN1RGZHFWWTVocWkxdlY1YXp2SFNLendpRzVCTlBtV3lFU1oreEdURWJUSDJLejJoR2ZaNUZjZ21seXVvUHhSZ3VpZ2JwTWF6UWJOSWJPa0NhblN6bEVnTkxSR3MyR0h6YWttbW9NdmxxZ0FBQUFBRWxGVGtTdVFtQ0MpOwp9Ci5zZi1tZW51LWNvbnRhaW5lciAuc29jaWFsLWJ0bi5vayB7CiAgICBiYWNrZ3JvdW5kLWltYWdlOiB1cmwoZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFCQUFBQUFRQ0FZQUFBQWY4LzloQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQURzTUFBQTdEQWNkdnFHUUFBQUFZZEVWWWRGTnZablIzWVhKbEFIQmhhVzUwTG01bGRDQTBMakF1TTR6bWwxQUFBQUlMU1VSQlZEaFBsZEZQYU5OUUhBZndkeGRhcXhOQlZLUU84YUlnZUJKbDRHa01CTmx3eUk1ZU54QkJ5UmhUaDRpWEhSUmN4ZGxOSnFOT1VRWkQzY1NwUGFUZ3hsQTJVSnpTMmtNbmJaT3VhYkw4YlpwOHpZdFYzNXVuL2VCRHlJL3Y5NUZIaUpYcGJITVd6eTg2U3ozWWtxQkR1OFFVenhTdDk4ZGh6Ui8reS83UUJVOUt3M2VxOEkwQzNOd29yTGRIdVF6dDBDNnhYaCtCTlJjc211eDNwK0JaRXVqNFhpTjgwbkh6S1M0WENyckVuRGtFbHYxNU9DeG9oUXhXVTIzNDhmSUN2TG9KditIQWVuT2F5MUxFZk40S2xyNDZGUjVRRm9lZ1BqMklTaW9PdTVvTGQvcDhONWVsaVBrNERwYWNGc0t3cStSZ2kzMm9MOSttZDRGcktsQ2VCUGZlbENmR3hINndTdmNQUU11TDRTSHNGRjVkaHZad0g1ZWxpSkhjQzVZNWVRejVCeWV4Tm5jVnRhK3pxSHlhUWpiVkEzbmlCSXp4T0plbGlKN1lBNWFuRnVBWk1yU0ZFWlJtTGtLYUZXQjlld0VFZjhSWnVzdGxLYkp4WnpkWXlzcDA4NlA1Y2ZWMVZLWjd1U3hGTm9aM2daVzkxb0x2aVE3VWE4Vm1GVmovK0F4ZmhscFJ2Tm5DWlNtaTNkcUp6WXlGWkxQNmV4cWFCSDJ5Njc4Y1JiUWJPOEN5TTRtdzVOazZzdmU2VVU2UGh1Kys2OEFZNitDeUZGR3Zid2VybGhtSFUvMko3TWc1bEFaaXlGMkpRaElmd2RWa0tNbXpYSllpeXVDMk5YVXdpait5bHlKWTZZdWlKUEM3NWQ0b3l2My9kaFR0RWxtSXRhdjlrYUk2RU1HV0JCMVppTFgvQXU0QThzbkMvaXp5QUFBQUFFbEZUa1N1UW1DQyk7Cn0KLnNmLW1lbnUtY29udGFpbmVyIC5zb2NpYWwtYnRuLmZiIHsKICAgIGJhY2tncm91bmQtaW1hZ2U6IHVybChkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUJBQUFBQVFDQVlBQUFBZjgvOWhBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRHNNQUFBN0RBY2R2cUdRQUFBQVlkRVZZZEZOdlpuUjNZWEpsQUhCaGFXNTBMbTVsZENBMExqQXVNNHptbDFBQUFBRkpTVVJCVkRoUGxZdkJLNE54R01lZmY4Vm1DVW5UZXR0WXZhV3RKcG1KbW1Kb09BbEhCMXN5UzNJUTBmWW1qRjVwMjhFT2xLeTBtVloyMkdrWE54ZFpVUTdLY2I2OFAvMVc5dmErYi92VTUvSjhuaThGb28vaVhLUmNtbytXMFl6S1J0bVNmN1ZZZFMzazRaeTlhMHBsbzJ4SkRHYlJOMzJyNitCaURqZkZWenc5ZjliMUx1ZWhiTWt4ZVFValM1VTNOT0pieXJKR3d2Z2w5TFJQWkZDcmZiUFIrOGNYdGc0TFdEL0lRWnpKc0U2MnNSVDBGUHhwTmxaSVhsZGdIVDZCMVplQWJUVEpPdldNeURDU2M1UXVxeHAxRHgxRFN6MDh3UlQ3b2E0QkNWcnE0UTdJN0ljNjNmdlEwdEliWW5Ja3VWQy9kYmoyMkErMTkrL0FTSTUwWGtSam96WnhHMFp5NHZLRHFwSEZ1UWtqT2ZHemUxV2pWc2NHak9URVR2T3FSbVloL0dLMnIwRlBUaXlSKzk5K3QyUVN3cDRXVzZocUVrTFFjaVZ5d2ZSTzdkWnZmNXV3NXdkZU4zRHIzMDdSV0FBQUFBQkpSVTVFcmtKZ2dnPT0pOwp9Ci5zZi1tZW51LWNvbnRhaW5lciAuc29jaWFsLWJ0bi50dyB7CiAgICBiYWNrZ3JvdW5kLWltYWdlOiB1cmwoZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFCQUFBQUFRQ0FZQUFBQWY4LzloQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQURzTUFBQTdEQWNkdnFHUUFBQUFZZEVWWWRGTnZablIzWVhKbEFIQmhhVzUwTG01bGRDQTBMakF1TTR6bWwxQUFBQUhLU1VSQlZEaFBuZERQU3hSaEhBYnc5eStaWFRXWE1JbVFoQVRKazJRR0NSNjdDT0dsYnAzczR0bTdxV2lKYm1WSkVrWWVERG9zKzROS3d4UXEvSUhGYnUxdXF6SXo2T3pPdnUvTzdzN1QrMzNkMGNXV1lQM0NCOTZaOTNubUhWNTJaMU4wRFd3N3F3TTdEdW9pTzlSbC9kOTQ1dnFHUVB1WFFsMm9RMTEyN1hNQlYxZlBoN3FzN2FNQTZWNHJvR1BsZUYydFQ1NFVNY3RJY2hlenFSSUd2eGR3Vi9MMjJaVW9CNWxLT05qTWx0SDVRYWhuMGliOXpwZHhkcWJqcHhsMk9jUkJodFl0dFhrZ1hJeklTK3FLQ2R6K0pOUzc2akZGQ2IwaFUzVUlhMzJmQitrTEgrS0FGeXN4d0pFSFovaS9wMi9vSEpmZVdhcERXTXR5SHVUQldyNFMrZis4amRzcTcyRVhsMnlRd0dzZEw3YVBVSExkU3JUMjNJOGFLdTloZ1RjNWVBWkRSaVZXZTNaTWdjQXIvU1JQV1BOQ0RwNExMdzA4ak96alQrNzBMcndwbGwzY1dreWZaRDJzYVQ0TGNtUFp4cjBZeC9oWEd6bTZ3YXBKWngzMEx5YlJPR2VxYkRYV05DY1gwczBsQzgrM09INVpSWmk4aEpUbElKeXdNU3ovcU9WeEhJMUJRK1hPWWczUExCRC9yQUhmWkFyYTJFOW9vN3ZRSHYyQU5wR0EvOGtlR3A0ZXFVd3RUSnM1VFBtRDhnUG5RRjJtQmZVZTM3U1Y4YzFZcUl2c2FFRzk1eS9FQ3lOMFVvVXZjUUFBQUFCSlJVNUVya0pnZ2c9PSk7Cn0KLnNmLW1lbnUtY29udGFpbmVyIC5zb2NpYWwtYnRuLmxqIHsKICAgIGJhY2tncm91bmQtaW1hZ2U6IHVybChkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUJBQUFBQVFDQVlBQUFBZjgvOWhBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRHNNQUFBN0RBY2R2cUdRQUFBQVlkRVZZZEZOdlpuUjNZWEpsQUhCaGFXNTBMbTVsZENBMExqQXVNNHptbDFBQUFBRjRTVVJCVkRoUFkvai8vejhEZzBHWUtJdHUrbEltL2JRL2JBWVovNW4wMDdjemFTUktnT1FJWVFhUVFxREcyeDVleGYvN2ttdi9UMGlwL2Uvc1ZmNmZTU2ZqQmpHR01BQTFiL1FFYWdacExFM3YrMitYdS81L1VNT2UveDdaTTRreUJHVEFINUROWmVtOS95MXpOLzAvZXVVbFVQei8veXQzWC94WEN1d2phQWdEazA3YXp4NmdBUTY1YS85djJILzEvL3NQSC8vWEx6cjMzNzEyLy8vOFJmZisrOVZ1eG1zSUE0dE94bnc3OTlMLzd1V2IvNTg1YytaLzlzU0QvMTBxZC8yZmNlTDMvNWtuLzRJeFBrTVlHRFhEZUlDaGZzdzRyT1gvaktXYi8xc1g3UGh2a2J2NWYwajdJYUlNQVJNd1F4VDlPLzg3bEFGZFVIMFNiRWhveDJHQ2hzQk5naHNTT0JWc0FGNUQ5REwyWWhoQWlpRU9lVXYvcytobEFMV2dHUURDWUVOMDBnK2pHK0pZdXZXL1Nmb2FPTVpwQUFoak13U2s2ZitGS1hDTTF3QVFSamVFWkFOQUdHUUlpM2JHSERtL2lTZ0dUT3hxQWhzQWlnMnNHdEV4U0RFMkRNcTFXRFVRd2lDYm1YUXpkakZxeHFvQUFKVFdkRXFyNStjUUFBQUFBRWxGVGtTdVFtQ0MpOwp9Ci5zZi1tZW51LWNvbnRhaW5lciAuc29jaWFsLWJ0bi5tYWlscnUgewogICAgYmFja2dyb3VuZC1pbWFnZTogdXJsKGRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQkFBQUFBUUNBWUFBQUFmOC85aEFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFEc01BQUE3REFjZHZxR1FBQUFBWWRFVllkRk52Wm5SM1lYSmxBSEJoYVc1MExtNWxkQ0EwTGpBdU00em1sMUFBQUFLSVNVUkJWRGhQbGRKYlNKTmhIQWJ3OS92bVlVVGlSWFFYaGpobjNkaHlibFB4TExtWkU2WW9PemdkVTVmVGVaalp0Q25aWVV2U1padFVXT25JZVNxanNpQUl1aWdMNllCWFhVVFFUVGVXZUZOMHdLaWJwL2Q5WFpKMTVjVVB0di83UFAvMys5aUl3cjlZb0R5ejlFcnBmNDV0b1IzV0pYTHZrOVdFbG9lUU5EellGdFpoWFNKdHVBK0piV0VMalhzRXdXRWpYbzZuNDhXMUF3Z01tWkhaR2Z3dng3cEVZcDNISHp0dDA3Z1ZLc0d2bXdUUHh0SXhlTnFBRVY4RjNvVDM4dGxNc0JRNzZtYzM4d3lSbUtiQnhKc244ZWl5R2l1UlJDanFqaUhWZWdLbUxpZEtYTjJRR2dMUU5yZmcwNHlJaGRFOHhKaW5lSWNoWW5VWVRFTlBNNzlGWnVwRms4ZUI5UnNFYnlmMjhJV3Z4MlZZQ0diRDNtSGhtUXAzTis4d1JEU01nVm0rSWtQa2JBNFU5bjRlS3JZM1FUemtRNXp1Rks3Njh2a3NyYllmZHdNWnVITStpM2NZSXVwRFlOYm5DR3d1RTRaUEhzYmlhQnJFc2lFK0YvVkJKRlY1OEcyV1FHN3BnN2RIajdXcHVPaFppQzdRMFNEMWxRYnNiU1lNOXBWdUxJak9tZVNhNC9oT0w1QWJQZkI1dGZnNEtkMDhJK3d4bWNlaFZOd2V6b0M4c2hVLzZlT1dOVFh5ZVVMNUFPYlBxZmdyN0t0MlkrbWlESFArREg3R0VMRjRBSXlodnBxSDhpeU5LSyt0d2xva0J1OG1kbU0xRW8rbm95bjRjRjJLZXdFRnorUWJyYnpERUxIQUMwYkk3VVo0NENDL3ZjNVJpZjFsVm1oTlZkQVlqTmhWNkVCZlp5SGVoeFBSMVZvRUljL0RPd3dSYyttWEtFSGRDdi9SYlB5Z1ArSG5hZnBub2pjdlgwckNseG1DRkswZFF1WVJDRm50bTNtR0NEbGQyRUxsUkhLUkVZN0dFb1I2VmJqUW8wS05SWXY0M1BhdHVTZ2lxTnRXaEt3T3V2a3ZtamErU0ZBNk5yRFAvMllZMmlXeEdxZE95SFN0Q21vWEhXd0Q3Y1JxbkxyZldFUVBDdzZaK1djQUFBQUFTVVZPUks1Q1lJST0pOwp9Ci5zZi1tZW51LWNvbnRhaW5lciAuc29jaWFsLWJ0bi5ncCB7CiAgICBiYWNrZ3JvdW5kLWltYWdlOiB1cmwoZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFCQUFBQUFRQ0FZQUFBQWY4LzloQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQURzTUFBQTdEQWNkdnFHUUFBQUFZZEVWWWRGTnZablIzWVhKbEFIQmhhVzUwTG01bGRDQTBMakF1TTR6bWwxQUFBQUlmU1VSQlZEaFBsZEwvU3hOaEhBZnc1NCtScVkwY2syQ1U3T1pNMmJtK0xLTmlFU2hOeW9heG9nVEp2b0FXVkFZSkJVWDlFQlJSRW9xbFk0cWExa3JkcFd6T3VWVzJsbHZMVTJ1ck9YVm0yYnU3Qjd4MnlRb2ZlQjNQNS8zdytmRGNjV1R5U3BVdWN0WEdDYkJPbk5oTFFnMEgrWWthRTk3WURPc2k5b2k5NU8zcC9aaCsybzUzVGNmdzhmRWRMSCtOUVZ5cDZVK0llMXlJdE42RXY3cEVrcHJscFgzQVZncnlZeUdKd0kwejhCelNZOWpDWU1DMkM0dXh6NWpubytDT2JzZUlrSTFWRlVuRVBMMG0zNU56ZUZXaGhhZXlrSElMRGVOM3I5RmJ6THpvbHZKVnlhbUlyQ2JMODNNWUVRYWtjMW1OZEVBaS9CNys4NGZwUHRNaTRtUDhnaFd1QTFza25HVXJQWnh5T2ZIU3JFSGJEclVrRVE3SmFqb2c3bk5qMEx3WkEvczBsTCt4RmorWGx1Q3NLWmV5Vllsd1VGYVR3Y1k2cE9KZkVITVBZZlNVQmI3NmFzeHl6OUZ6b2dLOXBudzRkMitTK2ZaaFFsWVR1ekVQOTR1VjZDeG5FYmhlVDY4KzFIQWNYZHRVNk4rcFh1TmhpVkpXazE2akNxS3Uwang0bTg3UkFUSGhsZnJMTkRUL0g5SmpWTU43OWdpQ3R5OWhzcU1adjFaVzZKQms4RFdlN1dYUWJkajRUMlF4R3NhbzhORmEySHpjWXhTNFZhaEVYNTBWS2VGbldvaUUwRmRXZ003aURSa1JSK1VlUE5BcTBLSFBoYU1vRjNaQnN6WWJyV1lEdlkzdjRrbWFaMEllRldSRjdicHMvSzFGR0RyakhZYm5jdTJhc3oreW9zVEJxdGgyUnNFTGtNNnV5NkgvL1JNVEk4dlQ4RzM2SFBZM1dGS2lBZmdSNTg4QUFBQUFTVVZPUks1Q1lJST0pOwp9Cgouc2YtbWVudS1jb250YWluZXIgLnNmLWNoZWNrYm94IHsKICAgIGZsb2F0OiBsZWZ0OwogICAgZGlzcGxheTogYmxvY2s7CgogICAgcGFkZGluZy10b3A6IDEycHg7CiAgICBwYWRkaW5nLWxlZnQ6IDE2cHg7CiAgICBwYWRkaW5nLWJvdHRvbTogMTJweDsKCiAgICAtd2Via2l0LXVzZXItc2VsZWN0OiBub25lOwogICAgLW1vei11c2VyLXNlbGVjdDogbm9uZTsKICAgIHVzZXItc2VsZWN0OiBub25lOwp9Cgouc2YtbWVudS1jb250YWluZXIubm8tcG9sbCAuc2YtY2hlY2tib3ggewogICAgcGFkZGluZy10b3A6IDE0cHg7Cn0KCi5zZi1tZW51LWNvbnRhaW5lciAuc2YtY2hlY2tib3ggPiBpIHsKICAgIHdpZHRoOiAyNHB4OwogICAgaGVpZ2h0OiAxNHB4OwogICAgZGlzcGxheTogYmxvY2s7CiAgICBwYWRkaW5nOiAwOwoKICAgIGJvcmRlci13aWR0aDogMXB4OwogICAgYm9yZGVyLXN0eWxlOiBzb2xpZDsKICAgIGJvcmRlci1yYWRpdXM6IDhweDsKICAgIHBvc2l0aW9uOiByZWxhdGl2ZTsKCiAgICBib3JkZXItY29sb3I6ICM3OEM0MzU7CiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNzhDNDM1Owp9Ci5zZi1tZW51LWNvbnRhaW5lciAuc2YtY2hlY2tib3ggPiBpID4gaSB7CiAgICBkaXNwbGF5OiBibG9jazsKICAgIGJhY2tncm91bmQtY29sb3I6ICNmZmY7CiAgICBib3JkZXItd2lkdGg6IDFweDsKICAgIGJvcmRlci1zdHlsZTogc29saWQ7CiAgICBib3JkZXItcmFkaXVzOiA4cHg7CgogICAgaGVpZ2h0OiAxMnB4OwogICAgd2lkdGg6IDEycHg7CiAgICBib3JkZXItY29sb3I6ICM3OEM0MzU7CiAgICBtYXJnaW4tbGVmdDogMTBweDsKfQouc2YtbWVudS1jb250YWluZXIgLnNmLWNoZWNrYm94LnNmLXRyYW5zaXRpb24gPiBpID4gaSB7CiAgICB0cmFuc2l0aW9uOiBtYXJnaW4tbGVmdCAwLjJzOwogICAgLW8tdHJhbnNpdGlvbjogbm9uZTsKfQouc2YtbWVudS1jb250YWluZXIgLmluYWN0aXZlIC5zZi1jaGVja2JveDpub3QoLmVuYWJsZUZvcmNlKSA+IGksCi5zZi1tZW51LWNvbnRhaW5lciAuc2YtY2hlY2tib3guZGlzYWJsZWQgPiBpIHsKICAgIGJvcmRlci1jb2xvcjogI0JFM0YyRTsKICAgIGJhY2tncm91bmQtY29sb3I6ICNmZmY7Cn0KLnNmLW1lbnUtY29udGFpbmVyIC5pbmFjdGl2ZSAuc2YtY2hlY2tib3g6bm90KC5lbmFibGVGb3JjZSkgPiBpID4gaSwKLnNmLW1lbnUtY29udGFpbmVyIC5zZi1jaGVja2JveC5kaXNhYmxlZCA+IGkgPiBpIHsKICAgIGhlaWdodDogMTRweDsKICAgIHdpZHRoOiAxNHB4OwogICAgYm9yZGVyLWNvbG9yOiAjQkUzRjJFOwogICAgbWFyZ2luOiAtMXB4Owp9Cjwvc3R5bGU+CjxkaXYgY2xhc3M9InNmLW1lbnUtZGVzYyI+CiAgICAgICAgPGRpdiBjbGFzcz0iaWNvbi1ib2R5Ij4KICAgICAgICAgICAgPGRpdiBjbGFzcz0iaWNvbiI+PC9kaXY+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9InZlcnNpb24iPjwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9InRpdGxlIj48L2Rpdj4KICAgICAgICA8ZGl2IGNsYXNzPSJkZXNjIj48L2Rpdj4KICAgICAgICA8YSBocmVmPSIjIiBjbGFzcz0ibW9yZSIgdGFyZ2V0PSJfYmxhbmsiIGRhdGEtaTE4bj0icmVhZE1vcmUiPkxlYXJuIE1vcmU8L2E+CiAgICAgICAgPGRpdiBjbGFzcz0ic29jaWFsLWJsb2NrIj4KICAgICAgICAgICAgPGEgaHJlZj0iIyIgY2xhc3M9InNvY2lhbC1idG4gdmsiIHRhcmdldD0iX2JsYW5rIj48L2E+CiAgICAgICAgICAgIDxhIGhyZWY9IiMiIGNsYXNzPSJzb2NpYWwtYnRuIGZiIiB0YXJnZXQ9Il9ibGFuayI+PC9hPgogICAgICAgICAgICA8YSBocmVmPSIjIiBjbGFzcz0ic29jaWFsLWJ0biBvayIgdGFyZ2V0PSJfYmxhbmsiPjwvYT4KICAgICAgICAgICAgPGEgaHJlZj0iIyIgY2xhc3M9InNvY2lhbC1idG4gdHciIHRhcmdldD0iX2JsYW5rIj48L2E+CiAgICAgICAgICAgIDxhIGhyZWY9IiMiIGNsYXNzPSJzb2NpYWwtYnRuIG1haWxydSIgdGFyZ2V0PSJfYmxhbmsiPjwvYT4KICAgICAgICAgICAgPGEgaHJlZj0iIyIgY2xhc3M9InNvY2lhbC1idG4gbGoiIHRhcmdldD0iX2JsYW5rIj48L2E+CiAgICAgICAgICAgIDxhIGhyZWY9IiMiIGNsYXNzPSJzb2NpYWwtYnRuIGdwIiB0YXJnZXQ9Il9ibGFuayI+PC9hPgogICAgICAgIDwvZGl2PgogICAgPC9kaXY+CiAgICA8ZGl2IGNsYXNzPSJzZi1tZW51LWxpc3QiPgogICAgICAgIDxkaXYgY2xhc3M9Iml0ZW0gYm9va21hcmtsZXQiIGRhdGEtYWN0aW9uPSJkb3dubG9hZEZyb21DdXJyZW50UGFnZSI+CiAgICAgICAgICAgIDxzdmcgY2xhc3M9Imljb24iIGRhdGEtdHlwZT0iZG93bmxvYWRGcm9tQ3VycmVudFBhZ2UiIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjIwcHgiIHZpZXdCb3g9IjAgMCAyNCAyMCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0zLDcuNjk2ODE0MzUgTDMsMTUuMzgwMTA4NyBDMywxNi4yMzIyNjY1IDMuNjgzNDk2NTksMTYuOTIzMDc2OSA0LjQ5MzA5NjM1LDE2LjkyMzA3NjkgTDE2LjUwNjkwMzYsMTYuOTIzMDc2OSBDMTcuMzMwMDk2MiwxNi45MjMwNzY5IDE3Ljk5NzY5NDMsMTYuMjUxNzM0NCAxNy45OTk5OTQsMTUuMzg0NjE1NCBMMTkuNSwxNS4zODQ2MTU0IEwxOS41LDEzLjg0NjE1MzggTDIxLDEzLjg0NjE1MzggTDIxLDE2LjkzNTM1ODQgQzIxLDE4LjYxNTExMzYgMTkuNjUyOTE5NywyMCAxNy45OTEyMTIsMjAgTDMuMDA4Nzg3OTksMjAgQzEuMzQ1NTkwMTksMjAgMCwxOC42Mjc5MTMyIDAsMTYuOTM1MzU4NCBMMCw2LjE0MTU2NDY0IEMwLDQuNDYxODA5NDkgMS4zNDcwODAyNywzLjA3NjkyMzA4IDMuMDA4Nzg3OTksMy4wNzY5MjMwOCBMOSwzLjA3NjkyMzA4IEw5LDQuNjE1Mzg0NjIgTDcuNSw0LjYxNTM4NDYyIEw3LjUsNi4xNTM4NDYxNSBMNC40OTMwOTYzNSw2LjE1Mzg0NjE1IEMzLjY2ODQ4MjAxLDYuMTUzODQ2MTUgMyw2LjgyNzUwOTc3IDMsNy42OTY4MTQzNSBaIE0xNi41LDQuNjMzODg5NzUgTDE2LjUsMCBMMjQsNi45MjMwNzY5MiBMMTYuNSwxMy44NDYxNTM4IEwxNi41LDkuMjQ1OTA5NzkgQzExLjM5NDM4NTMsOS40NTI3MTk4NCA3LjIxOTEzMDgyLDExLjc1NTUzNTYgNi4yMjUwNDA3MywxNC43NjkyMzA4IEM2LjA3NzQ2ODA3LDE0LjIyMjQyOTMgNiwxMy42NTY0ODA3IDYsMTMuMDc2OTIzMSBDNiw4LjU5MzI5NjE2IDEwLjYzNjQ4MTIsNC45MjQxNjQ3OSAxNi41LDQuNjMzODg5NzUgWiIgaWQ9IlNoYXJlIiBmaWxsPSIjMDAwMDAwIj48L3BhdGg+CiAgICAgICAgICAgIDwvc3ZnPgogICAgICAgICAgICA8c3BhbiBjbGFzcz0ibGFiZWwiIGRhdGEtaTE4bj0iZG93bmxvYWRGcm9tQ3VycmVudFBhZ2UiPkdvIHRvIFNhdmVGcm9tLm5ldDwvc3Bhbj4KICAgICAgICA8L2Rpdj4KICAgICAgICA8ZGl2IGNsYXNzPSJib29rbWFya2xldCBzZXBhcmF0b3IiPjwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9Iml0ZW0gbW9kdWxlIHZrIG9kbm9rbGFzc25pa2kgZmFjZWJvb2sgbG0geW91dHViZSBkYWlseW1vdGlvbiBpbnN0YWdyYW0gcnV0dWJlIiBkYXRhLWFjdGlvbj0idXBkYXRlTGlua3MiPgogICAgICAgICAgICA8c3ZnIGNsYXNzPSJpY29uIiBkYXRhLXR5cGU9InVwZGF0ZUxpbmtzIiB3aWR0aD0iMjJweCIgaGVpZ2h0PSIyNHB4IiB2aWV3Qm94PSIwIDAgMjIgMjQiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMjEuMjMwNzY5MiwxMy43MTQyODU3IEMyMS4yMzA3NjkyLDE5LjM5NDkyOTEgMTYuNDc4MDk5OSwyNCAxMC42MTUzODQ2LDI0IEM0Ljc1MjY2OTI5LDI0IDAsMTkuMzk0OTI5MSAwLDEzLjcxNDI4NTcgQzAsOC4wMzM2NDIyOSA0Ljc1MjY2OTI5LDMuNDI4NTcxNDMgMTAuNjE1Mzg0NiwzLjQyODU3MTQzIEwxMC42MTUzODQ2LDYuODU3MTQyODYgQzYuNzA2OTA3NzMsNi44NTcxNDI4NiAzLjUzODQ2MTU0LDkuOTI3MTkwMSAzLjUzODQ2MTU0LDEzLjcxNDI4NTcgQzMuNTM4NDYxNTQsMTcuNTAxMzgxMyA2LjcwNjkwNzczLDIwLjU3MTQyODYgMTAuNjE1Mzg0NiwyMC41NzE0Mjg2IEMxNC41MjM4NjE1LDIwLjU3MTQyODYgMTcuNjkyMzA3NywxNy41MDEzODEzIDE3LjY5MjMwNzcsMTMuNzE0Mjg1NyBMMjEuMjMwNzY5MiwxMy43MTQyODU3IEwyMS4yMzA3NjkyLDEzLjcxNDI4NTcgWiBNMTAuNjE1Mzg0NiwxMC4yODU3MTQzIEwxMC42MTUzODQ2LDAgTDE5LjQ2MTUzODUsNS4xNDI4NTcxNCBMMTAuNjE1Mzg0NiwxMC4yODU3MTQzIFoiIGlkPSJSZWZyZXNoIiBmaWxsPSIjMDAwMDAwIj48L3BhdGg+CiAgICAgICAgICAgIDwvc3ZnPgogICAgICAgICAgICA8c3BhbiBjbGFzcz0ibGFiZWwiIGRhdGEtaTE4bj0idXBkYXRlTGlua3MiPlJlZnJlc2ggbGlua3M8L3NwYW4+CiAgICAgICAgPC9kaXY+CiAgICAgICAgPGRpdiBjbGFzcz0iaXRlbSBtb2R1bGUgdmsgb2Rub2tsYXNzbmlraSBtYWlscnUiIGRhdGEtYWN0aW9uPSJkb3dubG9hZE1QM0ZpbGVzIj4KICAgICAgICAgICAgPHN2ZyBjbGFzcz0iaWNvbiIgZGF0YS10eXBlPSJkb3dubG9hZE1QM0ZpbGVzIiB3aWR0aD0iMjFweCIgaGVpZ2h0PSIyNHB4IiB2aWV3Qm94PSIwIDAgMjEgMjQiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMjEsMi43NjkyMzA3NyBMMjEsMTcuNjQ4NzI4OCBDMjEsMTcuNjQ4NzI4OCAyMSwxNy42NDg3Mjg4IDIxLDE3LjY0ODcyODggTDIxLDE4LjQ2MTUzODUgTDIwLjkwNjg3MjksMTguNDYxNTM4NSBDMjAuNzIzNTk1LDE5LjI3MTIyNDkgMjAuMjcxNjAxMywyMC4wODY1NzkxIDE5LjU2NjkyOTYsMjAuNzY4MDE5OCBDMTcuOTIwMzUzNywyMi4zNjAzMTMgMTUuNTE3Njg5NiwyMi42MTg0NzQ3IDE0LjIwMDQyODksMjEuMzQ0NjQwMiBDMTIuODgzMTY4MiwyMC4wNzA4MDU2IDEzLjE1MDEzMDksMTcuNzQ3MzUwMyAxNC43OTY3MDY4LDE2LjE1NTA1NzEgQzE2LjA2MDI1MTYsMTQuOTMzMTY3NiAxNy43NjkwMzI0LDE0LjQ5NjkwNTEgMTkuMDkwOTA5MSwxNC45MzU2ODE2IEwxOS4wOTA5MDkxLDE0LjkzNTY4MTYgTDE5LjA5MDkwOTEsNC4xNTM4NDYxNSBMNy42MzYzNjM2NCw2LjkyMzA3NjkyIEw3LjYzNjM2MzY0LDE5LjQ5NDg4MjYgQzcuNjM2MzYzNjQsMTkuNDk0ODgyNiA3LjYzNjM2MzY0LDE5LjQ5NDg4MjYgNy42MzYzNjM2NCwxOS40OTQ4ODI2IEw3LjYzNjM2MzY0LDIwLjMwNzY5MjMgTDcuNTQzMjM2NSwyMC4zMDc2OTIzIEM3LjM1OTk1ODU5LDIxLjExNzM3ODggNi45MDc5NjQ5MywyMS45MzI3MzI5IDYuMjAzMjkzMjMsMjIuNjE0MTczNyBDNC41NTY3MTczMiwyNC4yMDY0NjY5IDIuMTU0MDUzMjgsMjQuNDY0NjI4NiAwLjgzNjc5MjU1MiwyMy4xOTA3OTQgQy0wLjQ4MDQ2ODE3MywyMS45MTY5NTk1IC0wLjIxMzUwNTUwMSwxOS41OTM1MDQxIDEuNDMzMDcwNDEsMTguMDAxMjEwOSBDMi42OTY2MTUyMywxNi43NzkzMjE0IDQuNDA1Mzk2MDEsMTYuMzQzMDU5IDUuNzI3MjcyNzMsMTYuNzgxODM1NCBMNS43MjcyNzI3MywxNi43ODE4MzU0IEw1LjcyNzI3MjczLDYuNDYxNTM4NDYgTDUuNzI3MjcyNzMsMy42OTIzMDc2OSBMMjEsMCBMMjEsMi43NjkyMzA3NyBaIiBpZD0iTXVzaWMtMiIgZmlsbD0iIzAwMDAwMCI+PC9wYXRoPgogICAgICAgICAgICA8L3N2Zz4KICAgICAgICAgICAgPHNwYW4gY2xhc3M9ImxhYmVsIiBkYXRhLWkxOG49ImRvd25sb2FkTVAzRmlsZXMiPkRvd25sb2FkIGF1ZGlvIGZpbGVzPC9zcGFuPgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9Iml0ZW0gbW9kdWxlIHZrIG9kbm9rbGFzc25pa2kgcGxZb3V0dWJlIG1haWxydSIgZGF0YS1hY3Rpb249ImRvd25sb2FkUGxheWxpc3QiPgogICAgICAgICAgICA8c3ZnIGNsYXNzPSJpY29uIiBkYXRhLXR5cGU9ImRvd25sb2FkUGxheWxpc3QiIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjE4cHgiIHZpZXdCb3g9IjAgMCAyNCAxOCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0wLDAgTDAsMy42IEwzLjQyODU3MTQzLDMuNiBMMy40Mjg1NzE0MywwIEwwLDAgWiBNMCw3LjIgTDAsMTAuOCBMMy40Mjg1NzE0MywxMC44IEwzLjQyODU3MTQzLDcuMiBMMCw3LjIgWiBNNS4xNDI4NTcxNCwwIEw1LjE0Mjg1NzE0LDMuNiBMMjQsMy42IEwyNCwwIEw1LjE0Mjg1NzE0LDAgWiBNNS4xNDI4NTcxNCw3LjIgTDUuMTQyODU3MTQsMTAuOCBMMjAuNTcxNDI4NiwxMC44IEwyMC41NzE0Mjg2LDcuMiBMNS4xNDI4NTcxNCw3LjIgWiBNMCwxNC40IEwwLDE4IEwzLjQyODU3MTQzLDE4IEwzLjQyODU3MTQzLDE0LjQgTDAsMTQuNCBaIE01LjE0Mjg1NzE0LDE0LjQgTDUuMTQyODU3MTQsMTggTDIyLjI4NTcxNDMsMTggTDIyLjI4NTcxNDMsMTQuNCBMNS4xNDI4NTcxNCwxNC40IFoiIGlkPSJCdWxsZXQtTGlzdCIgZmlsbD0iIzAwMDAwMCI+PC9wYXRoPgogICAgICAgICAgICA8L3N2Zz4KICAgICAgICAgICAgPHNwYW4gY2xhc3M9ImxhYmVsIiBkYXRhLWkxOG49ImRvd25sb2FkUGxheWxpc3QiPkRvd25sb2FkIGEgcGxheWxpc3Q8L3NwYW4+CiAgICAgICAgPC9kaXY+CiAgICAgICAgPGRpdiBjbGFzcz0iaXRlbSBtb2R1bGUgdmsiIGRhdGEtYWN0aW9uPSJkb3dubG9hZFBob3RvcyI+CiAgICAgICAgICAgIDxzdmcgY2xhc3M9Imljb24iIGRhdGEtdHlwZT0iZG93bmxvYWRQaG90b3MiIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjE4cHgiIHZpZXdCb3g9IjAgMCAyNCAxOCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xOS41LDMgTDIxLjAwODkwOTYsMyBDMjIuNjU4MjI5NCwzIDI0LDQuMzQyODg3MTggMjQsNS45OTk0MjI0OCBMMjQsMTUuMDAwNTc3NSBDMjQsMTYuNjU1NjQ5MyAyMi42NjA4NDMyLDE4IDIxLjAwODkwOTYsMTggTDIuOTkxMDkwNDIsMTggQzEuMzQxNzcwNjMsMTggMCwxNi42NTcxMTI4IDAsMTUuMDAwNTc3NSBMMCw1Ljk5OTQyMjQ4IEMwLDQuMzQ0MzUwNzMgMS4zMzkxNTY3OSwzIDIuOTkxMDkwNDIsMyBMNy41LDMgQzcuNSwxLjM0NjUxNzEyIDguODQxODcwNjcsMCAxMC40OTcxNTIsMCBMMTYuNTAyODQ4LDAgQzE4LjE1ODM3NzIsMCAxOS41LDEuMzQzMTQ1NzUgMTkuNSwzIEwxOS41LDMgWiBNMTMuNSwxNi41IEMxNi44MTM3MDg3LDE2LjUgMTkuNSwxMy44MTM3MDg3IDE5LjUsMTAuNSBDMTkuNSw3LjE4NjI5MTM0IDE2LjgxMzcwODcsNC41IDEzLjUsNC41IEMxMC4xODYyOTEzLDQuNSA3LjUsNy4xODYyOTEzNCA3LjUsMTAuNSBDNy41LDEzLjgxMzcwODcgMTAuMTg2MjkxMywxNi41IDEzLjUsMTYuNSBaIE0xMy41LDE1IEMxNS45ODUyODE1LDE1IDE4LDEyLjk4NTI4MTUgMTgsMTAuNSBDMTgsOC4wMTQ3MTg1IDE1Ljk4NTI4MTUsNiAxMy41LDYgQzExLjAxNDcxODUsNiA5LDguMDE0NzE4NSA5LDEwLjUgQzksMTIuOTg1MjgxNSAxMS4wMTQ3MTg1LDE1IDEzLjUsMTUgWiIgaWQ9IkNhbWVyYS0yIiBmaWxsPSIjMDAwMDAwIj48L3BhdGg+CiAgICAgICAgICAgIDwvc3ZnPgogICAgICAgICAgICA8c3BhbiBjbGFzcz0ibGFiZWwiIGRhdGEtaTE4bj0iZG93bmxvYWRQaG90b3MiPkRvd25sb2FkIHBpY3R1cmVzPC9zcGFuPgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9Im1vZHVsZSB2ayBvZG5va2xhc3NuaWtpIGZhY2Vib29rIGxtIHNlcGFyYXRvciI+PC9kaXY+CiAgICAgICAgPGRpdiBjbGFzcz0iaXRlbSIgZGF0YS1hY3Rpb249InJlcG9ydEJ1ZyI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9Imljb24iPjwvZGl2PjxzcGFuIGNsYXNzPSJsYWJlbCIgZGF0YS1pMThuPSJyZXBvcnRCdWciPlJlcG9ydCBhIGJ1Zzwvc3Bhbj4KICAgICAgICA8L2Rpdj4KICAgICAgICA8ZGl2IGNsYXNzPSJpdGVtIiBkYXRhLWFjdGlvbj0ic2hvd09wdGlvbnMiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJpY29uIj48L2Rpdj48c3BhbiBjbGFzcz0ibGFiZWwiIGRhdGEtaTE4bj0ic2hvd09wdGlvbnMiPk9wdGlvbnM8L3NwYW4+CiAgICAgICAgPC9kaXY+CiAgICAgICAgPGRpdiBjbGFzcz0iaXRlbSIgZGF0YS1hY3Rpb249Im9wZW5Qb2xsIj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0iaWNvbiI+PC9kaXY+PHNwYW4gY2xhc3M9ImxhYmVsIiBkYXRhLWkxOG49Im9wZW5Qb2xsIj5CZWNvbWUgYmV0dGVyPC9zcGFuPgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9Iml0ZW0gZW5hYmxlTW9kdWxlIiBkYXRhLWFjdGlvbj0iZW5hYmxlTW9kdWxlIj4KICAgICAgICAgICAgPGkgY2xhc3M9InNmLWNoZWNrYm94Ij48aT48aT48L2k+PC9pPjwvaT4KICAgICAgICAgICAgPHNwYW4gaWQ9ImRpc2FibGVNb2R1bGUiIGNsYXNzPSJsYWJlbCIgZGF0YS1pMThuPSJkaXNhYmxlTW9kdWxlIj5EaXNhYmxlIG1vZHVsZTwvc3Bhbj4KICAgICAgICA8L2Rpdj4KICAgICAgICA8ZGl2IHN0eWxlPSJkaXNwbGF5OiBub25lOyIgZGF0YS1hY3Rpb249InNob3dBYm91dFBhZ2UiPgogICAgICAgICAgICA8c3ZnIGNsYXNzPSJpY29uIiBkYXRhLXR5cGU9InNob3dBYm91dFBhZ2UiIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCAxNiAxNiIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48cGF0aCBkPSJtMy4wOSwuNzE5YzAsLjg1MSAwLDEuNzExIDAsMi41NjEtLjY3LDAtMS4zNCwwLTIuMDEsMCAxLjA3LDEuMDcgMi4xNSwyLjE1IDMuMjIsMy4yMiAwLTEuOTMgMC0zLjg1IDAtNS43ODEtLjQyLDAtLjgzLDAtMS4yNSwwem0xLjkxLDBjLjA0LDIuMDkxIC4wNCw0LjE5MSAuMDQsNi4yODEtMS42NywwLTMuMzMsMC01LDAgMi42NywyLjc3IDUuMzMsNS41IDgsOC4zIDIuNy0yLjggNS4zLTUuNTMgOC04LjMtMS43LDAtMy4zLDAtNSwwIDAtMi4wOSAwLTQuMTkgMC02LjI4MS0yLDAtNCwwLTYsMHptNi43LDBjMCwxLjkzMSAwLDMuODUxIDAsNS43ODEgMS4xLTEuMDcgMi4xLTIuMTUgMy4yLTMuMjItLjcsMC0xLjMsMC0yLDAgMC0uODUgMC0xLjcxIDAtMi41NjEtLjQsMC0uOCwwLTEuMiwweiIvPjwvc3ZnPgogICAgICAgIDwvZGl2PgogICAgPC9kaXY+',

    getMenu: function() {
      var code = atob(this.menuHTML);
      var menu = document.createElement('div');
      menu.classList.add('sf-menu-container');
      menu.setAttribute(this.activeDataAttr, '1');
      menu.style.marginTop = '-24px';
      menu.style.width = 'auto';
      menu.style.minWidth = '482px';
      menu.innerHTML = code;
      return menu;
    },

    showMenuItems: function() {
      if (this.active)
        return;

      this.menu.style.top = this.style.menu.initial.top;

      this.removeActiveItems();

      var menu = this.getMenu();
      if (menu) {
        this.menu.appendChild(menu);
        _menu.initMenu(this.menu);
      }

      this.active = true;
      this.setElementsStyle('active');

      document.addEventListener('click', this.onDocumentClick, false);
      document.addEventListener('keydown', this.onDocumentKeyDown, false);

      var menuHeight = this.menu.clientHeight;
      var menuTop = parseInt(this.menu.style.top);
      var winHeight = window.innerHeight;
      if (menuTop + menuHeight > winHeight) {
        this.menu.style.top = (winHeight - menuHeight - 4) + 'px'
      } else
      if (menuTop < 0) {
        this.menu.style.top = '0px';
      }
    },

    hideMenuItems: function() {
      this.menu.style.top = this.style.menu.initial.top;

      // this.removeTooltip();
      this.removeActiveItems();
      document.removeEventListener('click', this.onDocumentClick, false);
      document.removeEventListener('keydown', this.onDocumentKeyDown, false);

      this.active = false;
      this.showTag();
    },

    onDocumentClick: function(event) {
      var node = event.target;
      if (node != _menu.menu && !SaveFrom_Utils.isParent(node, _menu.menu)) {
        _menu.hideMenuItems();
      }
    },

    onDocumentKeyDown: function(event) {
      if (event.keyCode == 27) {
        _menu.hideMenuItems();
      }
    },

    removeActiveItems: function() {
      var e = null;
      while (e = this.menu.querySelector('div[' + this.activeDataAttr + ']')) {
        e.parentNode.removeChild(e);
      }
    }
  };
  /////////////////////////////////////////////////
  // OPTIONS
  _options = {
    classPrefix: 'sfh--',
    dataAttr: 'data-sfh-option',
    html: 'PHN0eWxlIHR5cGU9InRleHQvY3NzIj4KLnNmaC0tb3B0aW9ucyB7CiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmOwogICAgYm9yZGVyOiBub25lOwogICAgZm9udDogMTNweC8xIEFyaWFsLCBIZWx2ZXRpY2EsIHNhbnMtc2VyaWY7CiAgICB3aWR0aDogNTgwcHg7CiAgICBtYXJnaW46IDA7CiAgICBwYWRkaW5nOiA5cHg7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Cn0KCi5zZmgtLW9wdGlvbnMgLnNmaC0tdGl0bGUgewogICAgZm9udC1zaXplOiAxLjNlbTsKICAgIG1hcmdpbjogMCAwIDEuM2VtIDAKfQoKLnNmaC0tb3B0aW9ucyBmb3JtIHsKICAgIG1hcmdpbjogMDsKICAgIHBhZGRpbmc6IDAKfQoKLnNmaC0tb3B0aW9ucyBpbnB1dFt0eXBlPSJjaGVja2JveCJdIHsKICAgIG1pbi13aWR0aDogMTJweDsKICAgIG1pbi1oZWlnaHQ6IDEycHgKfQoKLnNmaC0tb3B0aW9ucyBsYWJlbCB7CiAgICBkaXNwbGF5OiBibG9jazsKICAgIG1hcmdpbjogLjJlbSAwOwogICAgcGFkZGluZzogMDsKICAgIHRleHQtYWxpZ246IGxlZnQ7CiAgICBmb250LXNpemU6IDEzcHg7CiAgICBmbG9hdDogbm9uZTsKfQoKLnNmaC0tb3B0aW9ucyAuc2ZoLS1pbmxpbmUtY29udGVudCBsYWJlbCB7CiAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgICBtYXJnaW4tbGVmdDogMTBweAp9Cgouc2ZoLS1vcHRpb25zIC5zZmgtLWZsZWZ0IHsKICAgIGZsb2F0OiBsZWZ0Cn0KCi5zZmgtLW9wdGlvbnMgLnNmaC0tZmwtY29sdW1uIHsKICAgIGZsb2F0OiBsZWZ0OwogICAgbWFyZ2luLXJpZ2h0OiAyMHB4Cn0KCi5zZmgtLW9wdGlvbnMgLnNmaC0tY2xlYXIgewogICAgY2xlYXI6IGJvdGg7CiAgICBoZWlnaHQ6IDA7CiAgICBmb250LXNpemU6IDA7CiAgICBsaW5lLWhlaWdodDogMAp9Cgouc2ZoLS1vcHRpb25zIC5zZmgtLWJsb2NrIHsKICAgIGJvcmRlci10b3A6IDFweCBzb2xpZCAjZGZlMWU4OwogICAgcGFkZGluZzogMS41ZW0gMCAwIDA7CiAgICBtYXJnaW46IDEuNWVtIDAgMCAwOwogICAgbWluLXdpZHRoOiAxNjBweAp9Cgouc2ZoLS1vcHRpb25zIC5zZmgtLWJsb2NrLXRpdGxlIHsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgbWFyZ2luLWJvdHRvbTogLjVlbQp9Cgouc2ZoLS1vcHRpb25zIC5zZmgtLW1vZHVsZSB7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIG1hcmdpbi10b3A6IDFlbQp9Cgouc2ZoLS1vcHRpb25zIC5zZmgtLW1vZHVsZTpmaXJzdC1jaGlsZCB7CiAgICBtYXJnaW4tdG9wOiAwCn0KCi5zZmgtLW9wdGlvbnMgLnNmaC0tbW9kdWxlX29wdGlvbnMgewogICAgZm9udC1zaXplOiAuOWVtOwogICAgZm9udC13ZWlnaHQ6IG5vcm1hbDsKICAgIG1hcmdpbi1sZWZ0OiAyZW0KfQoKPC9zdHlsZT4KPGRpdiBjbGFzcz0ic2ZoLS1vcHRpb25zIj4KICA8ZGl2IGNsYXNzPSJzZmgtLXRpdGxlIiBkYXRhLWkxOG49Im9wdGlvbnNUaXRsZSI+U2F2ZUZyb20ubmV0IEhlbHBlciAtIFByZWZlcmVuY2VzPC9kaXY+CgogIDxmb3JtPgogICAgPGRpdiBjbGFzcz0ic2ZoLS1ibG9jayI+CiAgICAgIDxsYWJlbD48aW5wdXQgdHlwZT0iY2hlY2tib3giIGRhdGEtc2ZoLW9wdGlvbj0iYnV0dG9uIiBjaGVja2VkPSIxIj4mbmJzcDs8c3BhbiBkYXRhLWkxOG49InNob3dCdXR0b24iPlNob3cgZXh0ZW5zaW9uIGJ1dHRvbjwvc3Bhbj48L2xhYmVsPgogICAgPC9kaXY+CgogICAgPGRpdiBjbGFzcz0ic2ZoLS1ibG9jayI+CiAgICAgIDxkaXYgZGF0YS1pMThuPSJvcHRpb25zSGFuZGxlTGlua3MiIGNsYXNzPSJzZmgtLWJsb2NrLXRpdGxlIj5IYW5kbGUgbGlua3M8L2Rpdj4KICAgICAgPGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJsbU1lZGlhSG9zdGluZyIgY2hlY2tlZD0iMSI+Jm5ic3A7PHNwYW4gZGF0YS1pMThuPSJvcHRpb25zTWVkaWFIb3N0aW5ncyI+VG8gbWVkaWFob3N0aW5nczwvc3Bhbj48L2xhYmVsPgogICAgPC9kaXY+CgogICAgPGRpdiBjbGFzcz0ic2ZoLS1ibG9jayI+CiAgICAgIDxkaXYgZGF0YS1pMThuPSJvcHRpb25zTW9kdWxlcyIgY2xhc3M9InNmaC0tYmxvY2stdGl0bGUiPk1vZHVsZXM8L2Rpdj4KICAgICAgPGRpdiBjbGFzcz0ic2ZoLS15b3V0dWJlX2JveCIgY2xhc3M9InNmaC0tbW9kdWxlIj48bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249Im1vZHVsZVlvdXR1YmUiIGNoZWNrZWQ9IjEiPiZuYnNwOzxzcGFuIGRhdGEtaTE4bj0ib3B0aW9uc1lvdXR1YmUiPllvdVR1YmU8L3NwYW4+PC9sYWJlbD4KICAgICAgICA8ZGl2IGNsYXNzPSJzZmgtLW1vZHVsZV9vcHRpb25zIj4KICAgICAgICAgIDxkaXYgY2xhc3M9InNmaC0tZmwtY29sdW1uIj48c3BhbiBkYXRhLWkxOG49Im9wdGlvbnNZVEhpZGVMaW5rcyI+SGlkZSBsaW5rczwvc3Bhbj46PC9kaXY+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJzZmgtLWZsZWZ0IHNmaC0taW5saW5lLWNvbnRlbnQiPgogICAgICAgICAgICA8bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249Inl0SGlkZUZMViIgY2hlY2tlZD0iMCI+Jm5ic3A7RkxWPC9sYWJlbD4KICAgICAgICAgICAgPGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJ5dEhpZGVNUDQiIGNoZWNrZWQ9IjAiPiZuYnNwO01QNDwvbGFiZWw+CiAgICAgICAgICAgIDxsYWJlbD48aW5wdXQgdHlwZT0iY2hlY2tib3giIGRhdGEtc2ZoLW9wdGlvbj0ieXRIaWRlV2ViTSIgY2hlY2tlZD0iMSI+Jm5ic3A7V2ViTTwvbGFiZWw+CiAgICAgICAgICAgIDxicj4KICAgICAgICAgICAgPGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJ5dEhpZGUzR1AiIGNoZWNrZWQ9IjEiPiZuYnNwOzNHUDwvbGFiZWw+CiAgICAgICAgICAgIDxsYWJlbD48aW5wdXQgdHlwZT0iY2hlY2tib3giIGRhdGEtc2ZoLW9wdGlvbj0ieXRIaWRlM0QiIGNoZWNrZWQ9IjEiPiZuYnNwOzNEPC9sYWJlbD4KICAgICAgICAgICAgPGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJ5dEhpZGVNUDROb0F1ZGlvIiBjaGVja2VkPSIxIj4mbmJzcDtNUDQmbmJzcDsobm8mbmJzcDthdWRpbyk8L2xhYmVsPgogICAgICAgICAgICA8bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249Inl0SGlkZUF1ZGlvX01QNCIgY2hlY2tlZD0iMSI+Jm5ic3A7QXVkaW88L2xhYmVsPgogICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJzZmgtLWNsZWFyIj48L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgPC9kaXY+CgogICAgICA8ZGl2IGNsYXNzPSJzZmgtLW1vZHVsZSI+PGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJtb2R1bGVEYWlseW1vdGlvbiIgY2hlY2tlZD0iMSI+Jm5ic3A7PHNwYW4gZGF0YS1pMThuPSJvcHRpb25zRGFpbHltb3Rpb24iPkRhaWx5bW90aW9uPC9zcGFuPjwvbGFiZWw+PC9kaXY+CgogICAgICA8ZGl2IGNsYXNzPSJzZmgtLW1vZHVsZSI+PGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJtb2R1bGVWaW1lbyIgY2hlY2tlZD0iMSI+Jm5ic3A7PHNwYW4gZGF0YS1pMThuPSJvcHRpb25zVmltZW8iPlZpbWVvPC9zcGFuPjwvbGFiZWw+PC9kaXY+CgogICAgICA8ZGl2IGNsYXNzPSJzZmgtLW1vZHVsZSI+PGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJtb2R1bGVGYWNlYm9vayIgY2hlY2tlZD0iMSI+Jm5ic3A7PHNwYW4gZGF0YS1pMThuPSJvcHRpb25zRmFjZWJvb2siPkZhY2Vib29rPC9zcGFuPjwvbGFiZWw+PC9kaXY+CgogICAgICA8ZGl2IGNsYXNzPSJzZmgtLW1vZHVsZSI+PGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJtb2R1bGVTb3VuZGNsb3VkIiBjaGVja2VkPSIxIj4mbmJzcDs8c3BhbiBkYXRhLWkxOG49Im9wdGlvbnNTb3VuZGNsb3VkIj5Tb3VuZENsb3VkPC9zcGFuPjwvbGFiZWw+PC9kaXY+CgogICAgICA8ZGl2IGNsYXNzPSJzZmgtLW1vZHVsZSI+PGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJtb2R1bGVWa29udGFrdGUiIGNoZWNrZWQ9IjEiPiZuYnNwOzxzcGFuIGRhdGEtaTE4bj0ib3B0aW9uc1Zrb250YWt0ZSI+Vks8L3NwYW4+PC9sYWJlbD4KICAgICAgICA8ZGl2IGNsYXNzPSJzZmgtLW1vZHVsZV9vcHRpb25zIj48bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249InZrU2hvd0JpdHJhdGUiIGNoZWNrZWQ9IjAiPiZuYnNwOzxzcGFuIGRhdGEtaTE4bj0ib3B0aW9uc0JpdHJhdGUiPlNob3cgYml0cmF0ZSBpbnN0YW50bHk8L3NwYW4+PC9sYWJlbD48L2Rpdj4KICAgICAgPC9kaXY+CgogICAgICA8ZGl2IGNsYXNzPSJzZmgtLW1vZHVsZSI+PGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJtb2R1bGVPZG5va2xhc3NuaWtpIiBjaGVja2VkPSIxIj4mbmJzcDs8c3BhbiBkYXRhLWkxOG49Im9wdGlvbnNPZG5va2xhc3NuaWtpIj5PZG5va2xhc3NuaWtpPC9zcGFuPjwvbGFiZWw+PC9kaXY+CgogICAgICA8ZGl2IGNsYXNzPSJzZmgtLW1vZHVsZSI+PGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJtb2R1bGVNYWlscnUiIGNoZWNrZWQ9IjEiPiZuYnNwOzxzcGFuIGRhdGEtaTE4bj0ib3B0aW9uc01haWxydSI+TWFpbC5ydTwvc3Bhbj48L2xhYmVsPjwvZGl2PgoKICAgICAgPGRpdiBjbGFzcz0ic2ZoLS1tb2R1bGUiPjxsYWJlbD48aW5wdXQgdHlwZT0iY2hlY2tib3giIGRhdGEtc2ZoLW9wdGlvbj0ibW9kdWxlSW5zdGFncmFtIiBjaGVja2VkPSIxIj4mbmJzcDs8c3BhbiBkYXRhLWkxOG49Im9wdGlvbnNJbnN0YWdyYW0iPkluc3RhZ3JhbTwvc3Bhbj48L2xhYmVsPjwvZGl2PgoKICAgICAgPGRpdiBjbGFzcz0ic2ZoLS1tb2R1bGUiPjxsYWJlbD48aW5wdXQgdHlwZT0iY2hlY2tib3giIGRhdGEtc2ZoLW9wdGlvbj0ibW9kdWxlUnV0dWJlIiBjaGVja2VkPSIxIj4mbmJzcDs8c3BhbiBkYXRhLWkxOG49Im9wdGlvbnNSdXR1YmUiPlJ1dHViZTwvc3Bhbj48L2xhYmVsPjwvZGl2PgogICAgPC9kaXY+CiAgICA8ZGl2IGNsYXNzPSJzZmgtLWJsb2NrIGJsb2NrVW1teUluZm8iPgogICAgICA8bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249InNob3dVbW15SW5mbyIgY2hlY2tlZD0iMSI+Jm5ic3A7PHNwYW4gZGF0YS1pMThuPSJvcHRpb25zU2hvd1VtbXlJbmZvIj5TaG93IFVtbXkgaW5mbyBwb3B1cDwvc3Bhbj48L2xhYmVsPgogICAgICA8bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249InNob3dVbW15QnRuIiBjaGVja2VkPSIxIj4mbmJzcDs8c3BhbiBkYXRhLWkxOG49Im9wdGlvbnNTaG93VW1teUJ0biI+U2hvdyB0aGUgVW1teSBidXR0b248L3NwYW4+PC9sYWJlbD4KICAgIDwvZGl2PgogICAgPGRpdiBjbGFzcz0ic2ZoLS1ibG9jayBibG9ja0dtTmF0aXZlRG93bmxvYWQiIHN0eWxlPSJkaXNwbGF5OiBub25lOyI+CiAgICAgIDxsYWJlbD48aW5wdXQgdHlwZT0iY2hlY2tib3giIGRhdGEtc2ZoLW9wdGlvbj0iZ21OYXRpdmVEb3dubG9hZCIgY2hlY2tlZD0iMCI+Jm5ic3A7PHNwYW4gZGF0YS1pMThuPSJvcHRpb25zR21OYXRpdmVEb3dubG9hZCI+QWR2YW5jZWQgZG93bmxvYWQgbW9kZTwvc3Bhbj48L2xhYmVsPgogICAgPC9kaXY+CiAgICA8ZGl2IGNsYXNzPSJzZmgtLWJsb2NrIGJsb2NrU292ZXRuaWtFbmFibGVkIj4KICAgICAgPGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJzb3ZldG5pa0VuYWJsZWQiIGNoZWNrZWQ9IjEiPiZuYnNwOzxzcGFuIGRhdGEtaTE4bj0ib3B0aW9uc1NvdmV0bmlrRW5hYmxlZCI+RW5hYmxlIHNvdmV0bmlrPC9zcGFuPjwvbGFiZWw+CiAgICA8L2Rpdj4KICAgIDxkaXYgY2xhc3M9InNmaC0tYmxvY2sgYmxvY2tBdmlhQmFyRW5hYmxlZCI+CiAgICAgIDxsYWJlbD48aW5wdXQgdHlwZT0iY2hlY2tib3giIGRhdGEtc2ZoLW9wdGlvbj0iYXZpYUJhckVuYWJsZWQiIGNoZWNrZWQ9IjEiPiZuYnNwOzxzcGFuIGRhdGEtaTE4bj0ib3B0aW9uc0F2aWFCYXJFbmFibGVkIj5FbmFibGUgYXZpYUJhcjwvc3Bhbj48L2xhYmVsPgogICAgPC9kaXY+CiAgICA8ZGl2IGNsYXNzPSJzZmgtLWNsZWFyIj48L2Rpdj4KICA8L2Zvcm0+CjwvZGl2Pg==',

    translate: function(parent) {
      parent = parent || document;
      var e_list = parent.querySelectorAll('*[data-i18n]');
      for (var i = 0, len = e_list.length; i < len; i++) {
        var el = e_list[i];
        el.textContent = engine.language[el.dataset.i18n];
      }
    },

    onCbChange: function(event) {
      var el = event.target;
      var key = el.getAttribute(_options.dataAttr);
      mono.sendMessage({
        action: 'updateOption',
        key: key,
        value: el.checked ? 1 : 0
      });
    },

    createStatBlock: function(parent) {
      var id = 'blockStatEnabled';
      var node = parent.querySelector(id);
      if (!node) {
        var block = mono.create('div', {
          class: ['sfh--block', id],
          append: [
            mono.create('label', {
              append: [
                mono.create('input', {
                  type: 'checkbox',
                  data: {
                    sfhOption: 'statEnabled'
                  },
                  checked: true
                }),
                String.fromCharCode(160),
                mono.create('span', {
                  text: 'Web Statistic Tracker'
                })
              ]
            })
          ]
        });
        var clearBlock = parent.querySelector('form > .sfh--clear');
        clearBlock.parentNode.insertBefore(block, clearBlock);
      }
    },

    init: function(preference) {
      var parent = document.querySelector('.sfh--options');

      if (!parent) {
        return;
      }

      if (!preference.hasSovetnik) {
        var sovBlock = parent.querySelector('.blockSovetnikEnabled');
        if (sovBlock) {
          sovBlock.style.display = 'none';
        }
      }

      if (!preference.hasAviaBar) {
        var aviaBlock = parent.querySelector('.blockAviaBarEnabled');
        if (aviaBlock) {
          aviaBlock.style.display = 'none';
        }
      }

      if (!preference.showUmmyItem) {
        var ummyBlock = parent.querySelector('.blockUmmyInfo');
        if (ummyBlock) {
          ummyBlock.style.display = 'none';
        }
      }

      if (preference.hasSwStat || preference.hasFsStat) {
        _options.createStatBlock(parent);
      }

      _options.translate(parent);

      var c = parent.querySelectorAll('form input[type="checkbox"]');
      for (var i = 0; i < c.length; i++) {
        var el = c[i];
        var name = el.getAttribute(_options.dataAttr);
        if (name && preference[name] !== undefined) {
          el.checked = preference[name] !== 0;
          el.addEventListener('change', _options.onCbChange, false);
        }
      }

      if (typeof GM_download !== 'undefined') {
        var blockGmNativeDownload = parent.querySelector('.blockGmNativeDownload');
        if (blockGmNativeDownload) {
          blockGmNativeDownload.style.display = 'block';
        }
      }
    },

    hideBlock: function(name, hide) {
      var node = document.querySelector('.' + _options.classPrefix + name);
      if (node)
        node.style.display = hide ? 'none' : '';
    },

    show: function() {
      var height = document.body.clientHeight || 0;
      if (height > 600) {
        height = 600;
      }
      SaveFrom_Utils.popupDiv(function(cnt) {
        cnt.innerHTML = atob(_options.html);
      }, null, 640, height);

      mono.initGlobal(function(resp) {
        _options.init(mono.global.preference);
      });
    }
  };

  _languageList.de = "%7B%0A%20%20%20%20%22extName%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helfer%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Laden%20Sie%20von%20YouTube,%20Facebook,%20VK.com%20und%20mehr%20als%2040%20anderen%20Seiten%20mit%20einem%20Klick%20herunter.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extNameLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helfer%20Lite%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Herunterladen%20von%20Facebook,%20VK.com%20und%20mehr%20als%2040%20weiteren%20Seiten%20mit%20einem%20Klick%20herunter.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lang%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22de%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDefault%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helfer%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDesabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helfer%20deaktiviert%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Aktivieren%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDisable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Deaktivieren%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Erweiterungs%20Knopf%20anzeigen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22copy%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Kopie%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22download%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Herunterladen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Klicken%20Sie%20den%20Link%20w%C3%A4hrend%20Sie%20die%20Alt/Einstellung%20oder%20Ctrl/Strg%20Taste%20dr%C3%BCcken%20zum%20Herunterladen%20der%20Dateien.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noLinksFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Keine%20Links%20wurden%20gefunden%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22more%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Mehr%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22close%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Schlie%C3%9Fen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22kbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kbps%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22withoutAudio%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22without%20audio%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22size%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22gr%C3%B6%C3%9Fe%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22subtitles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Untertitel%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Wiedergabliste%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22List%20of%20files%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadWholePlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Die%20komplette%20Wiedergabliste%20herunterladen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dateigr%C3%B6%C3%9Fe%20bestimmen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeFailTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Fehler%20bei%20bestimmung%20der%20Dateigr%C3%B6%C3%9Fe.%20Bitte%20versuchen%20Sie%20es%20erneut.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lmButtonTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Holen%20Sie%20sich%20einen%20direkten%20Link.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Zu%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Links%20aktualisieren%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinksNotification%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Links%20aktualisiert%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20Audiodateien%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20Playlist%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20Bilder%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22installFullVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Install%20full%20version%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Deaktivieren%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Einstellungen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22reportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Fehler%20melden%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22openPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Become%20better%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Auf%20dieser%20Webseite%20deaktivieren%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Auf%20dieser%20Webseite%20aktivieren%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableDisableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ein/Aus%20auf%20dieser%20Webseite%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showHideButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Erweitern%20Ein-/Ausblenden%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateTo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Update%20auf%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%C3%9Cber%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helfer%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Version%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Hilft%20den%20Nutzern%20direkte%20Links%20zu%20Herunterladen%20von%20mehr%20als%2040%20Webseiten,%20inklusive%20Dailymotion.com,%20YouTube.com,%20VK.com%20und%20weiteren%20zu%20bekommen.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Hilft%20den%20Nutzern%20direkte%20Links%20zu%20Herunterladen%20von%20mehr%20als%2040%20Webseiten,%20inklusive%20Dailymotion.com,%20VK.com%20und%20weiteren%20zu%20bekommen.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutSupported%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Unterst%C3%BCtzte%20Ressourcen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22homePage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Homepage%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helfer%20-%20Einstellungen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsHandleLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Links%20handhaben%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMediaHostings%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Zu%20Medienhoster%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsModules%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Module%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22YouTube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYTHideLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Links%20ausblenden%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsDailymotion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dailymotion%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVimeo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Vimeo%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsFacebook%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Facebook%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSoundcloud%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SoundCloud%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVkontakte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22VK%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsOdnoklassniki%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Odnoklassniki%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMailru%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Moy%20Mir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsInstagram%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Instagram%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsRutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Rutube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsBitrate%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bitrate%20sofort%20zeigen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSovetnikEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Advisor%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tipps%20f%C3%BCr%20UVD%20einblenden%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsGmNativeDownload%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Erweiterter%20Download-Modus%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyBtn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Schaltfl%C3%A4che%20Ummy%20anzeigen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsAviaBarEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Cheap%20Flights%20Advisor%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSaveAsDialog%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Jedes%20Mal%20nachfragen,%20wo%20eine%20Datei%20gespeichert%20werden%20soll%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Laden%20Sie%20die%20Dateien%20mit%20SaveFrom.net%20von%20der%20aktuellen%20Seite%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuUpdateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Hier%20klicken,%20wenn%20die%20Download-Taste%20nicht%20erscheint%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Alle%20auf%20dieser%20Seite%20gefundenen%20Audiodateien%20herunterladen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Playliste%20mit%20den%20Links%20zu%20den%20Audiodateien%20generieren%20und%20downloaden%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Alle%20auf%20der%20aktuellen%20Seite%20gefundenen%20Bilder%20herunterladen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuReportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Schreiben%20Sie%20uns,%20wenn%20Probleme%20auftreten%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuShowOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22AN/AUS%20unterst%C3%BCtzte%20Ressourcen%20und%20Helperoptionen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnableExtension%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuOpenPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22quality%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Qualit%C3%A4t%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22qualityNote%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Wenn%20es%20nicht%20um%20Qualit%C3%A4t%20geht,%20wird%20das%20n%C3%A4chste%20verf%C3%BCgbare%20Video%20heruntergeladen.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Die%20Liste%20der%20gefundenen%20dateien%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Zum%20Herunterladen%20aller%20datien%20kopieren%20Sie%20die%20liste%20der%20Links%20in%20Ihren%20',%7Ba:%7Bhref:'http://en.wikipedia.org/wiki/Download_manager',text:'Download%20Manager'%7D%7D,'.%20Wenn%20Sie%20noch%20keinen%20Download%20Manager%20haben%20we%20empfehlen%20wir%20Ihnen%20die%20Installation%20des%20',%7Ba:%7Bhref:'http://www.freedownloadmanager.org/',text:'Free%20Download%20Manager'%7D%7D,'.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Wiedergabliste%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Zur%20Wiedergabe%20Ihrer%20gespeicherten%20Wiedergabliste%20kann%20es%20nun%20mit%20einem%20Musik-Player%20ge%C3%B6ffnet%20werden.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummySfTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22HD%20oder%20MP3%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuItem%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bspan:%7B%7D%7D,'%20mithilfe%20von%20Ummy%20herunterladen'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bp:%7Btext:'Schnell%20und%20einfach%20HD%20Videos%20und%20MP3%20%C3%BCber%20Ummy%20Video%20Downloader%20herunterladen!'%7D%7D,%7Bp:%7Bclass:'center',append:%5B%7Ba:%7Bclass:'green-btn-2%20arrow',href:'%7Burl%7D',target:'_blank',text:'Jetzt%20installieren'%7D%7D%5D%7D%7D,%7Bp:%7Bappend:%5B'Nach%20der%20Installation%20startet%20jederzeit%20ein%20Download,%20wenn%20Sie%20auf%20',%7Bimg:%7Bsrc:'#'%7D%7D,'%20klicken'%5D%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%C3%9Cberpr%C3%BCfen%20Sie%20die%20Browsereinstellungen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Die%20Option%20%5C%22Jedes%20Mal%20nachfragen,%20wo%20eine%20Datei%20gespeichert%20werden%20soll%5C%22%20muss%20deaktiviert%20sein.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22readMore%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Mehr%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noWarning%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Nicht%20benachrichtigen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22cancel%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Abbrechen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22continue%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Fortsetzen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22beforeDownloadPopupWarn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Achtung!%20Der%20Download%20kann%20nicht%20abgebrochen%20oder%20angehalten%20werden.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Info%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfoTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dateigr%C3%B6%C3%9Fe%20und%20Bitrate%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkMp3LinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Links%20zu%20MP3%20Dateien%20wurden%20nicht%20gefunden%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkPhotoLinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Photos%20are%20not%20found%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadPhotoAlbum%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Album%20herunterladen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadAllPhotoAlbums%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Alle%20Alben%20herunterladen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Gefundene%20Fotos%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkNotAvailablePhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%25d%20Foto(s)%20vor%C3%BCbergehend%20nicht%20verf%C3%BCgbar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Gefundene%20Links%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundOf%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22von%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkShowAs%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Zeigen%20als%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Liste%20der%20Links%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinksInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Um%20alle%20Fotos%20herunterzuladen,%20kopieren%20Sie%20die%20Links%20aus%20der%20Liste%20und%20f%C3%BCgen%20Sie%20diese%20in%20Ihren%20',%7Ba:%7Bhref:'http://en.wikipedia.org/wiki/Download_manager',text:'Download%20Manager'%7D%7D,'%20ein.%20Wenn%20Sie%20noch%20keinen%20Download%20Manager%20haben%20we%20empfehlen%20wir%20Ihnen%20die%20Installation%20des%20',%7Ba:%7Bhref:'http://www.freedownloadmanager.org/',text:'Free%20Download%20Manager'%7D%7D,'.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkTableOfThumbnails%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tabelle%20der%20Thumbnails%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Liste%20der%20Fotos%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotosInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Klicken%20Sie%20auf%20ein%20Foto%20um%20es%20herunterzuladen.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkKbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kbps%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeKByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeMByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22MB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeGByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22GB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeTByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22TB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadFromYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Herunterladen:%20%C3%96ffnen%20Sie%20',%7Ba:%7Bhref:'%7Burl%7D',text:'die%20Video%20Seite'%7D%7D,'%20und%20dr%C3%BCcken%20Sie%20den%20%5C%22Herunterladen%5C%22%20Knopf%20%C3%BCber%20dem%20Video-Spieler'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundFiles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dateien%20gefunden:%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22shareIn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22In%20%25w%20teilen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22socialDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Der%20SaveFrom.net%20Helper%20erm%C3%B6glicht%20es%20Ihnen%20Dateien%20YouTube.com,%20Facebook.com,%20VK.com%20und%20mehr%20als%2040%20andere%20Seiten%20mit%20einem%20Klick%20herunterzuladen%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Gute%20Nachrichten!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'SaveFrom.net%20Helper%20',%7Bimg:%20%7Bsrc:%20'#logo'%7D%7D,'%20wurde%20erfolgreich%20installiert.%20Jetzt%20kannst%20due%20jedes%20Video%20mit%20einem%20Klick%20von%20YouTube%20herunterladen'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Arrow%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Wie%20das%20geht?',%7Bbr:%7B%7D%7D,'Hier%20erf%C3%A4hrst%20du%20es'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS2Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22W%C3%A4hle%20das%20Format%20des%20Videos,%20das%20du%20herunterladen%20m%C3%B6chtest%20und%20klicken%20auf%20%5C%22Herunterladen%5C%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3History%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Historie%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Du%20m%C3%B6chtest%20ein%20Video%20aus%20Historie%20herunterladen?%20Klicken%20einfach%20in%20der%20Vorschau%20des%20zuletzt%20gesehenen%20Videos%20auf%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS4Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Du%20musst%20dir%20das%20Video%20nicht%20ansehen%20%E2%80%94%20klicke%20einfach%20auf%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,%20',%20w%C3%A4hle%20die%20Qualit%C3%A4t%20und%20lade%20es%20herunter.%20Ganz%20einfach,%20oder?'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Viel%20Spa%C3%9F%20mit%20SaveFrom.net%20Helper!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Noch%20Fragen?%20Vorschl%C3%A4ge?%20Willkommen%20auf%20unserer%20',%20%7Ba:%20%7Btext:%20'Support-Seite',%20href:%20'#support'%7D%7D%20,'.%20Schlie%C3%9Fe%20dich%20uns%20bei%20',%20%7Ba:%20%7Btext:%20'Facebook',%20href:%20'#fb'%7D%7D%20,'%20an'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialTooltipText%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Klicken%20Sie%20zum%20',%7Bb:%20%7Btext:%20'Download'%7D%7D,',%20einfach%20auf%20die%20Schaltfl%C3%A4che'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyTooltipConfirm%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Hatten%20Sie%20',%7Bimg:%7B%7D%7D,'%20Ummy%20Video%20Downloader%20bereits%20zuvor%20installiert?'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22yes%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ja%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22no%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Nein%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tooltipHide%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Diese%20Meldung%20nicht%20wieder%20anzeigen%22%0A%20%20%20%20%7D%0A%7D";
  _languageList.en = "%7B%0A%20%20%20%20%22extName%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20helper%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20YouTube,%20Facebook,%20VK.com%20and%2040+%20sites%20in%20one%20click.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extNameLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20helper%20lite%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20Facebook,%20VK.com%20and%2040+%20sites%20in%20one%20click.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lang%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22en%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDefault%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20helper%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDesabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20helper%20disabled%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Enable%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDisable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Disable%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Show%20extension%20button%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22copy%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Copy%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22download%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Click%20the%20link%20while%20holding%20Alt/Option%20or%20Ctrl%20key%20to%20download%20the%20file.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noLinksFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22No%20links%20were%20found%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22more%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22More%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22close%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Close%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22kbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kbps%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22withoutAudio%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22without%20audio%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22size%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22size%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22subtitles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Subtitles%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Playlist%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22List%20of%20files%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadWholePlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20the%20whole%20playlist%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Get%20file%20size%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeFailTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Unable%20to%20get%20the%20file%20size.%20Please%20try%20again.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lmButtonTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Get%20a%20direct%20link%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Go%20to%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Refresh%20links%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinksNotification%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Links%20updated%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20audio%20files%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20a%20playlist%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20pictures%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22installFullVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Install%20full%20version%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Disable%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Settings%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22reportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Report%20a%20bug%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22openPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Become%20better%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Disable%20on%20this%20website%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Enable%20on%20this%20website%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableDisableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Turn%20On/Off%20on%20this%20website%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showHideButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Show/hide%20extension%20button%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateTo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Update%20to%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22About%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helper%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Version%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Helps%20users%20to%20get%20direct%20links%20to%20download%20from%20more%20than%2040%20websites,%20including%20Dailymotion.com,%20YouTube.com,%20VK.com%20and%20others.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Helps%20users%20to%20get%20direct%20links%20to%20download%20from%20more%20than%2040%20websites,%20including%20Dailymotion.com,%20VK.com%20and%20others.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutSupported%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Supported%20resources%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22homePage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Home%20page%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helper%20-%20Preferences%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsHandleLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Handle%20links%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMediaHostings%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22To%20mediahostings%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsModules%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Modules%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22YouTube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYTHideLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Hide%20links%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsDailymotion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dailymotion%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVimeo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Vimeo%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsFacebook%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Facebook%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSoundcloud%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SoundCloud%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVkontakte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22VK%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsOdnoklassniki%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Odnoklassniki%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMailru%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Moy%20Mir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsInstagram%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Instagram%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsRutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Rutube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsBitrate%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Show%20bitrate%20instantly%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSovetnikEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Advisor%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Show%20tips%20for%20Ummy%20Video%20Downloader%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsGmNativeDownload%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Advanced%20download%20mode%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyBtn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Show%20the%20Ummy%20button%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsAviaBarEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Cheap%20Flights%20Advisor%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSaveAsDialog%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Always%20ask%20me%20where%20to%20save%20files%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20files%20from%20the%20current%20page%20using%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuUpdateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Press%20if%20Download%20button%20doesn't%20appear%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20all%20audio%20files%20found%20on%20the%20current%20page%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Generates%20and%20downloads%20the%20playlist%20consisting%20of%20links%20to%20audio%20files%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20all%20pictures%20found%20on%20the%20current%20page%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuReportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Let%20us%20know%20if%20you%20have%20any%20problems%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuShowOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22ON/OFF%20supported%20resources%20and%20Helper%20options%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnableExtension%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuOpenPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22We%20work%20hard%20to%20become%20better.%20Please,%20give%20us%20a%20hand!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22quality%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Quality%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22qualityNote%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22The%20best%20available%20video%20will%20be%20downloaded%20If%20there%20is%20no%20chosen%20quality.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22The%20list%20of%20the%20found%20files%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'To%20download%20all%20files%20copy%20the%20list%20of%20links%20and%20paste%20it%20into%20the%20',%7Ba:%7Bhref:'http://en.wikipedia.org/wiki/Download_manager',text:'download%20manager'%7D%7D,'.%20If%20you%20do%20not%20have%20a%20download%20manager%20installed%20we%20recommend%20installing%20',%7Ba:%7Bhref:'http://www.freedownloadmanager.org/',text:'Free%20Download%20Manager'%7D%7D,'.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Playlist%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22To%20playback%20the%20saved%20playlist%20it%20may%20be%20now%20opened%20in%20the%20music%20player.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummySfTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22HD%20or%20MP3%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuItem%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bspan:%7B%7D%7D,'%20via%20Ummy'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bp:%7Btext:'Fast%20and%20easy%20download%20HD%20videos%20and%20MP3%20via%20Ummy%20Video%20Downloader!'%7D%7D,%7Bp:%7Bclass:'center',append:%5B%7Ba:%7Bclass:'green-btn-2%20arrow',href:'%7Burl%7D',target:'_blank',text:'Install%20Now'%7D%7D%5D%7D%7D,%7Bp:%7Bappend:%5B'When%20installed,%20a%20download%20will%20start%20anytime%20you%20click%20on%20',%7Bimg:%7Bsrc:'#'%7D%7D%5D%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Check%20browser%20settings%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22The%20option%20%5C%22Always%20ask%20me%20where%20to%20save%20files%5C%22%20must%20be%20turned%20off.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22readMore%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22More%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noWarning%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Don't%20notify%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22cancel%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Cancel%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22continue%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Continue%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22beforeDownloadPopupWarn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Warning!%20Downloading%20cannot%20be%20canceled%20or%20suspended.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Info%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfoTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22File%20size%20and%20bitrate%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkMp3LinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Links%20to%20MP3%20files%20are%20not%20found%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkPhotoLinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Photos%20are%20not%20found%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadPhotoAlbum%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20album%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadAllPhotoAlbums%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20all%20albums%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Found%20photos%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkNotAvailablePhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%25d%20photos%20are%20temporarily%20unavailable%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Found%20links%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundOf%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22of%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkShowAs%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Show%20as%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22List%20of%20links%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinksInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'To%20download%20all%20photos%20copy%20the%20list%20of%20links%20and%20paste%20it%20into%20the%20',%7Ba:%7Bhref:'http://en.wikipedia.org/wiki/Download_manager',text:'download%20manager'%7D%7D,'.%20If%20you%20do%20not%20have%20a%20download%20manager%20installed%20we%20recommend%20installing%20',%7Ba:%7Bhref:'http://www.freedownloadmanager.org/',text:'Free%20Download%20Manager'%7D%7D,'.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkTableOfThumbnails%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Table%20of%20thumbnails%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22List%20of%20photos%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotosInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Click%20on%20the%20photo%20to%20download%20it.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkKbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kbps%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeKByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeMByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22MB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeGByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22GB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeTByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22TB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadFromYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Download:%20open%20',%7Ba:%7Bhref:'%7Burl%7D',text:'the%20video%20page'%7D%7D,'%20and%20press%20the%20%5C%22Download%5C%22%20button%20above%20the%20player'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundFiles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Files%20found:%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22shareIn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Share%20on%20%25w%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22socialDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20helper%20enables%20you%20to%20download%20files%20from%20YouTube.com,%20Facebook.com,%20VK.com%20and%20more%20than%2040%20other%20just%20in%20one%20click%20for%20free%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Good%20news!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'SaveFrom.net%20Helper%20',%7Bimg:%20%7Bsrc:%20'#logo'%7D%7D,'%20has%20been%20successfully%20installed%20and%20now%20you%20can%20download%20any%20video%20from%20YouTube%20in%20one%20click'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Arrow%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Want%20to%20know%20how?',%7Bbr:%7B%7D%7D,'Click%20here'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS2Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22To%20download%20a%20video%20choose%20a%20format%20and%20click%20the%20%5C%22Download%5C%22%20button%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3History%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22History%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Do%20you%20want%20to%20download%20a%20video%20from%20History?',%7Bbr:%7B%7D%7D,'Just%20click%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,'%20on%20the%20preview%20of%20the%20previously%20watched%20video'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS4Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'No%20need%20to%20watch%20a%20video%20%E2%80%94%20just%20click%20on%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,',%20choose%20the%20quality,%20and%20download.%20Quite%20easy,%20isn%E2%80%99t%20it?'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Enjoy%20SaveFrom.net%20Helper!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Still%20have%20questions?%20Want%20to%20share%20your%20ideas?%20Welcome%20to%20',%7Ba:%20%7Btext:%20'our%20support%20page',%20href:%20'#support'%7D%7D,'%20or%20join%20us%20on%20',%20%7Ba:%20%7Btext:%20'Facebook',%20href:%20'#fb'%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialTooltipText%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Just%20click%20the%20button%20to%20',%7Bb:%20%7Btext:%20'download'%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyTooltipConfirm%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Have%20you%20already%20installed',%7Bbr:%7B%7D%7D,%7Bimg:%7B%7D%7D,'%20Ummy%20Video%20Downloader%20earlier?'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22yes%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Yes%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22no%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22No%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tooltipHide%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Do%20not%20show%20this%20message%20again%22%0A%20%20%20%20%7D%0A%7D";
  _languageList.es = "%7B%0A%20%20%20%20%22extName%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20helper%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Descargas%20desde%20YouTube,%20Facebook,%20VK.com%20y%2040+%20sitios%20en%20un%20s%C3%B3lo%20clic.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extNameLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20helper%20lite%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Descargas%20desde%20Facebook,%20VK.com%20y%2040+%20sitios%20en%20un%20s%C3%B3lo%20clic.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lang%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22es%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDefault%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20helper%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDesabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20helper%20deshabilitado%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Habilitar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDisable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Deshabilitar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Mostrar%20bot%C3%B3n%20de%20extensi%C3%B3n%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22copy%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Copiar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22download%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Descargar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Haga%20clic%20en%20el%20enlace%20mientras%20presiona%20la%20tecla%20Alt/Opci%C3%B3n%20o%20Ctrl%20para%20descargar%20el%20archivo.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noLinksFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22No%20se%20han%20encontrado%20enlaces%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22more%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22M%C3%A1s%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22close%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Cerrar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22kbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kbps%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22withoutAudio%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22sin%20audio%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22size%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22tama%C3%B1o%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22subtitles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Subt%C3%ADtulos%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Lista%20de%20reproducci%C3%B3n%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Lista%20de%20archivos%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadWholePlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Descargar%20toda%20la%20lista%20de%20reproducci%C3%B3n%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Obtener%20tama%C3%B1o%20de%20archivo%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeFailTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22No%20se%20pudo%20obtener%20el%20tama%C3%B1o%20del%20archivo.%20Por%20favor,%20int%C3%A9ntelo%20de%20nuevo.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lmButtonTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Obtener%20un%20enlace%20directo%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ir%20a%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Actualizar%20enlaces%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinksNotification%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Enlaces%20actualizados%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Descargar%20archivos%20de%20audio%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Descargar%20una%20lista%20de%20reproducci%C3%B3n%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Descargar%20im%C3%A1genes%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22installFullVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Instalar%20la%20versi%C3%B3n%20completa%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Deshabilitar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ajustes%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22reportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Informar%20sobre%20un%20problema%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22openPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Mejorar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Desactivar%20en%20este%20sitio%20web%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Activar%20en%20este%20sitio%20web%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableDisableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Activ./Desactiv.%20en%20esta%20web%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showHideButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Mostrar/ocultar%20bot%C3%B3n%20extens%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateTo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Actualizar%20a%20la%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Acerca%20de%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helper%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Versi%C3%B3n%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ayuda%20a%20los%20usuarios%20a%20obtener%20enlaces%20directos%20para%20descargar%20desde%20m%C3%A1s%20de%2040%20sitios%20web,%20incluidos%20Dailymotion.com,%20YouTube.com,%20VK.com%20y%20otros.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ayuda%20a%20los%20usuarios%20a%20obtener%20enlaces%20directos%20para%20descargar%20desde%20m%C3%A1s%20de%2040%20sitios%20web,%20incluidos%20Dailymotion.com,%20VK.com%20y%20otros.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutSupported%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Recursos%20admitidos%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22homePage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22P%C3%A1gina%20de%20inicio%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helper%20-%20Preferencias%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsHandleLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Manejar%20enlaces%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMediaHostings%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22A%20servidores%20multimedia%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsModules%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22M%C3%B3dulos%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22YouTube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYTHideLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ocultar%20enlaces%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsDailymotion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dailymotion%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVimeo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Vimeo%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsFacebook%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Facebook%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSoundcloud%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SoundCloud%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVkontakte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22VK%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsOdnoklassniki%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Odnoklassniki%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMailru%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Moy%20Mir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsInstagram%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Instagram%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsRutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Rutube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsBitrate%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Mostrar%20velocidad%20de%20bits%20instant%C3%A1neamente%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSovetnikEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Consejero%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Muestra%20consejos%20para%20Ummy%20Video%20Downloader%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsGmNativeDownload%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22M%C3%B3udlo%20de%20descarga%20avanzada%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyBtn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Mostrar%20el%20bot%C3%B3n%20Ummy%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsAviaBarEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Cheap%20Flights%20Advisor%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSaveAsDialog%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Preguntarme%20siempre%20d%C3%B3nde%20guardar%20los%20archivos%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Descargar%20archivos%20de%20la%20p%C3%A1gina%20actual%20usando%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuUpdateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Pulse%20si%20no%20aparece%20el%20bot%C3%B3n%20Descargar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Descargar%20todos%20los%20archivos%20de%20audio%20de%20la%20p%C3%A1gina%20actual%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Genera%20y%20descarga%20la%20lista%20de%20reproducci%C3%B3n%20que%20consiste%20en%20enlaces%20a%20archivos%20de%20audio%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Descargar%20todas%20las%20im%C3%A1genes%20encontradas%20en%20la%20p%C3%A1gina%20actual%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuReportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22H%C3%A1ganos%20saber%20si%20tiene%20alg%C3%BAn%20problema%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuShowOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22ACTIVAR/DESACTIVAR%20recursos%20admitidos%20y%20opciones%20del%20Helper%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnableExtension%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuOpenPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Trabajamos%20duro%20para%20mejorar.%20%C2%A1%C3%89chenos%20una%20mano!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22quality%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Calidad%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22qualityNote%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Si%20no%20se%20elige%20ninguna%20calidad,%20se%20descargar%C3%A1%20el%20mejor%20v%C3%ADdeo%20disponible.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22La%20lista%20de%20los%20archivos%20encontrados%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Para%20descargar%20todos%20los%20archivos,%20copie%20la%20lista%20de%20enlaces%20y%20p%C3%A9guela%20en%20el%20',%7Ba:%7Bhref:'http://en.wikipedia.org/wiki/Download_manager',text:'gestor%20de%20descargas'%7D%7D,'.%20Si%20no%20tiene%20instalado%20un%20gestor%20de%20descargas,%20le%20recomendamos%20que%20instale%20',%7Ba:%7Bhref:'http://www.freedownloadmanager.org/',text:'Free%20Download%20Manager'%7D%7D,'.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Lista%20de%20reproducci%C3%B3n%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Para%20reproducir%20la%20lista%20de%20reproducci%C3%B3n%20guardada,%20puede%20abrirla%20ahora%20en%20el%20reproductor%20de%20m%C3%BAsica.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummySfTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22HD%20o%20MP3%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuItem%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bspan:%7B%7D%7D,'%20via%20Ummy'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bp:%7Btext:'Instale%20Ummy%20Video%20Downloader%20y%20descargue%20sus%20v%C3%ADdeos%20favoritos%20en%20HD%20o%20MP3.'%7D%7D,%7Bp:%7Bclass:'center',append:%5B%7Ba:%7Bclass:'green-btn-2%20arrow',href:'%7Burl%7D',target:'_blank',text:'Descargar'%7D%7D%5D%7D%7D,%7Bp:%7Bappend:%5B'Despu%C3%A9s%20de%20la%20instalaci%C3%B3n,%20se%20iniciar%C3%A1%20una%20descarga%20autom%C3%A1ticamente%20siempre%20que%20haga%20clic%20en%20',%7Bimg:%7Bsrc:'#'%7D%7D%5D%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Compruebe%20la%20configuraci%C3%B3n%20de%20su%20navegador%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22La%20opci%C3%B3n%20%5C%22Preguntarme%20siempre%20d%C3%B3nde%20guardar%20los%20archivos%5C%22%20debe%20estar%20desactivada.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22readMore%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22M%C3%A1s%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noWarning%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22No%20notificar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22cancel%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Cancelar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22continue%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Continuar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22beforeDownloadPopupWarn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%C2%A1Advertencia!%20La%20descarga%20no%20se%20puede%20cancelar%20o%20suspender.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Informaci%C3%B3n%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfoTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tama%C3%B1o%20de%20archivo%20y%20velocidad%20de%20bits%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkMp3LinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22No%20se%20han%20encontrado%20enlaces%20a%20archivos%20MP3%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkPhotoLinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22No%20se%20han%20encontrado%20im%C3%A1genes%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadPhotoAlbum%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Descargar%20%C3%A1lbum%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadAllPhotoAlbums%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Descargar%20todos%20los%20%C3%A1lbums%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Im%C3%A1genes%20encontradas%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkNotAvailablePhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%25d%20im%C3%A1genes%20est%C3%A1n%20temporalmente%20no%20disponibles%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Enlaces%20encontrados%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundOf%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22de%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkShowAs%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Mostrar%20como%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Lista%20de%20enlaces%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinksInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Para%20descargar%20todas%20las%20im%C3%A1genes,%20copie%20la%20lista%20de%20enlaces%20y%20p%C3%A9guela%20en%20el%20',%7Ba:%7Bhref:'http://en.wikipedia.org/wiki/Download_manager',text:'gestor%20de%20descargas'%7D%7D,'.%20Si%20no%20tiene%20instalado%20un%20gestor%20de%20descargas,%20le%20recomendamos%20que%20instale%20',%7Ba:%7Bhref:'http://www.freedownloadmanager.org/',text:'Free%20Download%20Manager'%7D%7D,'.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkTableOfThumbnails%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tabla%20de%20miniaturas%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Lista%20de%20im%C3%A1genes%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotosInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Haga%20clic%20en%20la%20imagen%20para%20descargarla.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkKbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kbps%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeKByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeMByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22MB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeGByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22GB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeTByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22TB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadFromYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Descargar:%20abra%20',%7Ba:%7Bhref:'%7Burl%7D',text:'la%20p%C3%A1gina%20del%20v%C3%ADdeo'%7D%7D,'%20y%20pulse%20el%20bot%C3%B3n%20%5C%22Descargar%5C%22%20sobre%20el%20reproductor'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundFiles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Archivos%20encontrados:%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22shareIn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Compartir%20en%20%25w%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22socialDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20helper%20le%20permite%20descargar%20archivos%20desde%20YouTube.com,%20Facebook.com,%20VK.com%20y%20m%C3%A1s%20de%2040%20sitios%20distintos%20con%20tan%20s%C3%B3lo%20un%20clic%20y%20gratis%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%C2%A1Excelentes%20noticias!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'SaveFrom.net%20Helper%20',%7Bimg:%20%7Bsrc:%20'#logo'%7D%7D,%20'%20se%20instal%C3%B3%20con%20%C3%A9xito%20y%20ahora%20puedes%20descargar%20cualquier%20video%20de%20YouTube%20con%20un%20solo%20clic'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Arrow%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%C2%BFQuieres%20saber%20c%C3%B3mo?',%20%7Bbr:%7B%7D%7D,%20'Haz%20clic%20aqu%C3%AD'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS2Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Para%20descargar%20un%20video,%20elige%20el%20formato%20y%20haz%20clic%20en%20el%20bot%C3%B3n%20%5C%22Descargar%5C%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3History%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Historial%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%C2%BFDeseas%20descargar%20un%20video%20del%20Historial?',%20%7Bbr:%7B%7D%7D,%20'Simplemente%20haz%20clic%20en%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,%20'%20en%20la%20vista%20previa%20del%20video%20visto%20anteriormente.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS4Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'No%20es%20necesario%20mirar%20un%20video:%20simplemente%20haz%20clic%20en%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,%20',%20elige%20la%20calidad%20y%20desc%C3%A1rgalo.%20F%C3%A1cil,%20%C2%BFverdad?'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%C2%A1Disfruta%20de%20SaveForm.net%20Helper!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%C2%BFTodav%C3%ADa%20tienes%20preguntas?%20%C2%BFQuieres%20compartir%20tus%20ideas?%20Puedes%20ir%20a%20nuestra%20',%7Ba:%20%7Btext:%20'p%C3%A1gina%20de%20soporte',%20href:%20'#support'%7D%7D,'%20o%20unirte%20a%20nosotros%20en%20',%20%7Ba:%20%7Btext:%20'Facebook',%20href:%20'#fb'%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialTooltipText%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Simplemente%20haz%20clic%20en%20el%20bot%C3%B3n%20para%20',%7Bb:%20%7Btext:%20'descargar'%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyTooltipConfirm%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%C2%BFYa%20has%20instalado',%7Bbr:%7B%7D%7D,%7Bimg:%7B%7D%7D,'%20Ummy%20Video%20Downloader%20antes?'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22yes%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22S%C3%AD%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22no%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22No%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tooltipHide%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22No%20mostrar%20de%20nuevo%20este%20mensaje%22%0A%20%20%20%20%7D%0A%7D";
  _languageList.fr = "%7B%0A%20%20%20%20%22extName%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helper%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22T%C3%A9l%C3%A9chargez%20YouTube,%20Facebook,%20VK.com%20et%2040+%20sites%20en%20un%20seul%20clic.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extNameLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helper%20lite%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22T%C3%A9l%C3%A9chargez%20Facebook,%20VK.com%20et%2040+%20sites%20en%20un%20seul%20clic.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lang%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22fr%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDefault%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helper%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDesabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Assistant%20SaveFrom.net%20d%C3%A9sactiv%C3%A9%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Activer%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDisable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22D%C3%A9sactiver%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Afficher%20le%20bouton%20d'extension%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22copy%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Copier%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22download%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22T%C3%A9l%C3%A9charger%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Cliquer%20sur%20le%20lien%20tout%20en%20maintenant%20la%20touche%20Alt/Option%20ou%20Ctrl%20pour%20t%C3%A9l%C3%A9charger%20le%20fichier.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noLinksFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Aucun%20lien%20n'a%20%C3%A9t%C3%A9%20trouv%C3%A9%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22more%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Plus%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22close%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Fermer%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22kbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kbps%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22withoutAudio%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22sans%20audio%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22size%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22taille%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22subtitles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Sous-titres%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Playlist%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Liste%20de%20fichiers%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadWholePlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22T%C3%A9l%C3%A9charger%20toute%20la%20playlist%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Obtenir%20la%20taille%20du%20fichier%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeFailTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Impossible%20d'obtenir%20la%20taille%20du%20fichier.%20Veuillez%20r%C3%A9essayer.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lmButtonTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Obtenir%20un%20lien%20direct%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Aller%20%C3%A0%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Rafra%C3%AEchir%20les%20liens%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinksNotification%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Liens%20mis%20%C3%A0%20jour%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22T%C3%A9l%C3%A9charger%20les%20fichiers%20audio%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22T%C3%A9l%C3%A9charger%20une%20playlist%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22T%C3%A9l%C3%A9charger%20les%20images%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22installFullVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Installer%20la%20version%20compl%C3%A8te%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22D%C3%A9sactiver%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Param%C3%A8tres%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22reportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Signaler%20un%20bug%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22openPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Am%C3%A9liorer%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22D%C3%A9sactiver%20sur%20ce%20site%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Activer%20sur%20ce%20site%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableDisableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Activer%20On/Off%20sur%20ce%20site%20web%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showHideButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Afficher/masquer%20le%20bouton%20d'extension%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateTo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Passer%20%C3%A0%20la%20version%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%C3%80%20propos%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helper%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Version%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Aide%20les%20utilisateurs%20%C3%A0%20obtenir%20des%20liens%20directs%20pour%20t%C3%A9l%C3%A9charger%20depuis%20plus%20de%2040%20sites%20web,%20y%20compris%20Dailymotion.com,%20YouTube.com,%20VK.com%20et%20d'autres.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Aide%20les%20utilisateurs%20%C3%A0%20obtenir%20des%20liens%20directs%20pour%20t%C3%A9l%C3%A9charger%20depuis%20plus%20de%2040%20sites%20web,%20y%20compris%20Dailymotion.com,%20VK.com%20et%20d'autres.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutSupported%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ressources%20prises%20en%20charge%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22homePage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Page%20d'accueil%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helper%20-%20Pr%C3%A9f%C3%A9rences%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsHandleLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22manipuler%20les%20liens%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMediaHostings%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Vers%20l'h%C3%A9bergement%20de%20m%C3%A9dias%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsModules%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Modules%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22YouTube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYTHideLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Masquer%20les%20liens%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsDailymotion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dailymotion%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVimeo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Vimeo%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsFacebook%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Facebook%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSoundcloud%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SoundCloud%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVkontakte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22VK%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsOdnoklassniki%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Odnoklassniki%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMailru%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Moy%20Mir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsInstagram%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Instagram%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsRutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Rutube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsBitrate%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Afficher%20instantan%C3%A9ment%20le%20bitrate%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSovetnikEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Advisor%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Afficher%20les%20astuces%20pour%20Ummy%20Video%20Downloader%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsGmNativeDownload%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Mode%20de%20t%C3%A9l%C3%A9chargement%20avanc%C3%A9%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyBtn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Montrer%20le%20bouton%20Ummy%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsAviaBarEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Cheap%20Flights%20Advisor%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSaveAsDialog%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Toujours%20demander%20o%C3%B9%20enregistrer%20les%20fichiers%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22T%C3%A9l%C3%A9chargement%20des%20fichiers%20depuis%20la%20page%20actuelle%20en%20utilisant%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuUpdateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Appuyez%20si%20le%20bouton%20T%C3%A9l%C3%A9charger%20n'appara%C3%AEt%20pas%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22T%C3%A9l%C3%A9charger%20tous%20les%20fichiers%20audio%20trouv%C3%A9s%20sur%20la%20page%20actuelle%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22G%C3%A9n%C3%A8re%20et%20t%C3%A9l%C3%A9charge%20la%20playlist%20consistant%20en%20liens%20vers%20les%20fichiers%20audio%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22T%C3%A9l%C3%A9charger%20toutes%20les%20images%20trouv%C3%A9es%20sur%20la%20page%20actuelle%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuReportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Pr%C3%A9venez-nous%20si%20vous%20avez%20des%20probl%C3%A8mes%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuShowOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22ON/OFF%20ressources%20prises%20en%20charge%20et%20options%20Helper%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnableExtension%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuOpenPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Nous%20faisons%20tout%20pour%20nous%20am%C3%A9liorer.%20N'h%C3%A9sitez%20pas%20%C3%A0%20nous%20aider%20!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22quality%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Qualit%C3%A9%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22qualityNote%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22La%20meilleure%20vid%C3%A9o%20disponible%20sera%20t%C3%A9l%C3%A9charg%C3%A9e%20s'il%20n'y%20a%20pas%20de%20qualit%C3%A9%20choisie.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22La%20liste%20des%20fichiers%20trouv%C3%A9s%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Pour%20t%C3%A9l%C3%A9charger%20tous%20les%20fichiers%20copiez%20la%20liste%20des%20liens%20et%20collez-la%20dans%20',%7Ba:%7Bhref:'http://en.wikipedia.org/wiki/Download_manager',text:'download%20manager'%7D%7D,'.%20Si%20vous%20n%5C%5C'avez%20pas%20install%C3%A9%20de%20gestionnaire%20de%20t%C3%A9l%C3%A9chargement,%20nous%20vous%20recommandons%20d%5C%5C'installer%20',%7Ba:%7Bhref:'http://www.freedownloadmanager.org/',text:'Free%20Download%20Manager'%7D%7D,'.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Playlist%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Pour%20lire%20la%20playlist%20sauvegard%C3%A9e,%20ouvrez-la%20dans%20le%20lecteur%20musical.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummySfTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22HD%20ou%20MP3%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuItem%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bspan:%7B%7D%7D,'%20via%20Ummy'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bp:%7Btext:'Installez%20Ummy%20Video%20Downloader%20et%20t%C3%A9l%C3%A9chargez%20vos%20vid%C3%A9os%20favorites%20en%20HD%20ou%20MP3.'%7D%7D,%7Bp:%7Bclass:'center',append:%5B%7Ba:%7Bclass:'green-btn-2%20arrow',href:'%7Burl%7D',target:'_blank',text:'Download'%7D%7D%5D%7D%7D,%7Bp:%7Bappend:%5B'Apr%C3%A8s%20l%5C%5C'installation,%20un%20t%C3%A9l%C3%A9chargement%20d%C3%A9marrera%20automatiquement%20d%C3%A8s%20que%20vous%20cliquez%20sur%20',%7Bimg:%7Bsrc:'#'%7D%7D%5D%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22V%C3%A9rifier%20les%20param%C3%A8tres%20du%20navigateur%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22L'option%20%5C%22Toujours%20me%20demander%20o%C3%B9%20sauvegarder%20les%20fichiers%5C%22%20doit%20%C3%AAtre%20d%C3%A9sactiv%C3%A9e.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22readMore%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Plus%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noWarning%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22ne%20pas%20notifier'%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22cancel%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Annuler%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22continue%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Continuer%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22beforeDownloadPopupWarn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Attention!%20Le%20t%C3%A9l%C3%A9chargement%20ne%20peut%20pas%20%C3%AAtre%20annul%C3%A9%20ou%20suspendu.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Info%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfoTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Taille%20de%20fichier%20et%20bitrate%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkMp3LinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Les%20liens%20vers%20les%20fichiers%20MP3%20sont%20introuvables%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkPhotoLinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Photos%20introuvables%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadPhotoAlbum%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22T%C3%A9l%C3%A9charger%20l'album%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadAllPhotoAlbums%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22T%C3%A9l%C3%A9charger%20tous%20les%20albums%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Photos%20trouv%C3%A9es%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkNotAvailablePhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%25d%20photos%20sont%20temporairement%20indisponibles%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Liens%20trouv%C3%A9s%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundOf%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22de%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkShowAs%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Afficher%20comme%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Liste%20des%20liens%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinksInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Pour%20t%C3%A9l%C3%A9charger%20toutes%20les%20photos%20copiez%20la%20liste%20des%20liens%20et%20collez-la%20dans%20',%7Ba:%7Bhref:'http://en.wikipedia.org/wiki/Download_manager',text:'download%20manager'%7D%7D,'.%20Si%20vous%20n%5C%5C'avez%20pas%20install%C3%A9%20de%20gestionnaire%20de%20t%C3%A9l%C3%A9chargement%20nous%20vous%20recommandons%20d%5C%5C'installer%20',%7Ba:%7Bhref:'http://www.freedownloadmanager.org/',text:'Free%20Download%20Manager'%7D%7D,'.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkTableOfThumbnails%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tableau%20des%20vignettes%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Liste%20des%20photos%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotosInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Cliquez%20sur%20la%20photo%20pour%20la%20t%C3%A9l%C3%A9charger.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkKbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kbps%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22O%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeKByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22ko%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeMByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Mo%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeGByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Go%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeTByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22To%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadFromYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Download:%20open%20',%7Ba:%7Bhref:'%7Burl%7D',text:'the%20video%20page'%7D%7D,'%20et%20appuyez%20sur%20le%20bouton%20%5C%22T%C3%A9l%C3%A9charger%5C%22%20au-dessus%20du%20lecteur'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundFiles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Fichiers%20trouv%C3%A9s%20:%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22shareIn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Partager%20sur%20%25w%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22socialDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20helper%20vous%20permet%20de%20t%C3%A9l%C3%A9charger%20des%20fichiers%20de%20YouTube.com,%20Facebook.com,%20VK.com%20et%20plus%20de%2040%20autres%20gratuitement%20et%20en%20un%20seul%20clic%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bonnes%20nouvelles%20!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'SaveFrom.net%20Helper%20',%7Bimg:%20%7Bsrc:%20'#logo'%7D%7D,%20'%20a%20%C3%A9t%C3%A9%20install%C3%A9%20avec%20succ%C3%A8s%20et%20maintenant%20vous%20pouvez%20t%C3%A9l%C3%A9charger%20les%20vid%C3%A9os%20de%20YouTube%20en%20un%20clic'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Arrow%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Vous%20voulez%20savoir%20comment%20?%20Cliquez%20ici'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS2Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Pour%20t%C3%A9l%C3%A9charger%20une%20vid%C3%A9o,%20choisissez%20un%20format%20et%20cliquez%20sur%20le%20bouton%20%5C%22T%C3%A9l%C3%A9charger%5C%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3History%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Historique%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Voulez-vous%20t%C3%A9l%C3%A9charger%20une%20vid%C3%A9o%20depuis%20l%E2%80%99historique%20?',%20%7Bbr:%7B%7D%7D,%20'Il%20suffit%20de%20cliquer%20sur%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,%20'%20situ%C3%A9e%20sur%20l%5C%5C'aper%C3%A7u%20de%20la%20vid%C3%A9o%20pr%C3%A9c%C3%A9demment%20regard%C3%A9e'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS4Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Pas%20besoin%20de%20regarder%20une%20vid%C3%A9o%20%E2%80%94%20il%20suffit%20de%20cliquer%20sur%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,%20',%20faites%20le%20choix%20de%20la%20qualit%C3%A9,%20et%20t%C3%A9l%C3%A9charger.%20Facile,%20est-ce%20pas%20?'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Profitez%20de%20SaveFrom.net%20Helper%20!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Vous%20avez%20encore%20des%20questions%20?%20Vous%20voulez%20partager%20vos%20id%C3%A9es%20?%20Bienvenue%20sur%20notre%20page%20',%7Ba:%20%7Btext:%20'de%20d%E2%80%99Aide',%20href:%20'#support'%7D%7D,'%20ou%20rejoignez-nous%20sur%20',%20%7Ba:%20%7Btext:%20'Facebook',%20href:%20'#fb'%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialTooltipText%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Il%20suffit%20de%20cliquer%20sur%20le%20bouton%20pour%20',%7Bb:%20%7Btext:%20't%C3%A9l%C3%A9charger'%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyTooltipConfirm%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Avez-vous%20d%C3%A9j%C3%A0%20install%C3%A9',%7Bbr:%7B%7D%7D,%7Bimg:%7B%7D%7D,'%20Ummy%20Video%20Downloader%20avant%20?'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22yes%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Oui%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22no%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Non%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tooltipHide%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ne%20plus%20afficher%20ce%20message%22%0A%20%20%20%20%7D%0A%7D";
  _languageList.id = "%7B%0A%20%20%20%20%22extName%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bantuan%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Unduh%20YouTube,%20Facebook,%20VK.com,%20dan%2040+%20situs%20dengan%20satu%20klik.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extNameLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bantuan%20SaveFrom.net%20lite%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Unduh%20Facebook,%20VK.com,%20dan%2040+%20situs%20dengan%20satu%20klik.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lang%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22id%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDefault%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bantuan%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDesabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bantuan%20SaveFrom.net%20nonaktif%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Aktifkan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDisable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Nonaktifkan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tampilkan%20tombol%20ekstensi%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22copy%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Salin%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22download%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Unduh%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Klik%20tautan%20sambil%20menahan%20tombol%20Alt/Option%20atau%20Ctrl%20untuk%20mengunduh%20file.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noLinksFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tautan%20tidak%20ditemukan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22more%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Lainnya%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22close%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tutup%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22kbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kbps%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22withoutAudio%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22tanpa%20audio%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22size%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22ukuran%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22subtitles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Subtitel%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Daftar%20putar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Daftar%20file%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadWholePlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Unduh%20seluruh%20daftar%20putar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dapatkan%20ukuran%20file%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeFailTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Gagal%20mendapatkan%20ukuran%20file.%20Mohon%20coba%20lagi.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lmButtonTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dapatkan%20tautan%20langsung%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Buka%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Segarkan%20tautan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinksNotification%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tautan%20diperbarui%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Unduh%20file%20audio%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Unduh%20daftar%20putar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Unduh%20gambar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22installFullVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Pasang%20versi%20lengkap%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Nonaktifkan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Setelan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22reportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Laporkan%20bug%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22openPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Jadikan%20lebih%20baik%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Nonaktifkan%20di%20situs%20web%20ini%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Aktifkan%20di%20situs%20web%20ini%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableDisableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Nyalakan/Matikan%20di%20situs%20ini%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showHideButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tampilkan/tutup%20tbl%20ekstensi%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateTo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Perbarui%20ke%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tentang%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bantuan%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Versi%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Membantu%20pengguna%20mendapatkan%20tautan%20langsung%20dari%2040+%20situs%20web,%20termasuk%20Dailymotion.com,%20YouTube.com,%20VK.com%20dan%20lain-lain.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Membantu%20pengguna%20mendapatkan%20tautan%20langsung%20untuk%20mengunduh%20dari%2040+%20situs%20web,%20termasuk%20Dailymotion.com,%20VK.com%20dan%20lain-lain.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutSupported%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Sumber%20daya%20yang%20didukung%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22homePage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Laman%20beranda%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bantuan%20SaveFrom.net%20-%20Preferensi%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsHandleLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tangani%20tautan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMediaHostings%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ke%20mediahosting%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsModules%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Modul%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22YouTube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYTHideLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Sembunyikan%20tautan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsDailymotion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dailymotion%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVimeo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Vimeo%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsFacebook%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Facebook%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSoundcloud%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SoundCloud%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVkontakte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22VK%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsOdnoklassniki%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Odnoklassniki%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMailru%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Moy%20Mir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsInstagram%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Instagram%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsRutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Rutube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsBitrate%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Langsung%20tampilkan%20bitrate%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSovetnikEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Penasihat%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tampilkan%20tips%20untuk%20Ummy%20Video%20Downloader%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsGmNativeDownload%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Mode%20unduh%20lanjutan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyBtn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Perlihatkan%20tombol%20Ummy%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsAviaBarEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Cheap%20Flights%20Advisor%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSaveAsDialog%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Selalu%20tanyakan%20lokasi%20penyimpanan%20berkas%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Unduh%20file%20dari%20laman%20saat%20ini%20dengan%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuUpdateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tekan%20jika%20tombol%20Unduh%20tidak%20muncul%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Unduh%20semua%20file%20audio%20yang%20ada%20di%20laman%20saat%20ini%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Buat%20dan%20unduh%20daftar%20putar%20berisi%20tautan%20ke%20file%20audio%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Unduh%20semua%20gambar%20yang%20ada%20di%20laman%20saat%20ini%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuReportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Beri%20tahu%20kami%20jika%20Anda%20mengalami%20masalah%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuShowOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22AKTIFKAN/NONAKTIFKAN%20sumber%20daya%20yang%20didukung%20dan%20opsi%20Bantuan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnableExtension%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuOpenPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Kami%20bekerja%20keras%20untuk%20jadi%20lebih%20baik.%20Tolong,%20bantu%20kami!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22quality%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Kualitas%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22qualityNote%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Video%20terbaik%20yang%20tersedia%20akan%20diunduh%20jika%20tidak%20ada%20kualitas%20yang%20dipilih.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Daftar%20file%20yang%20ditemukan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Untuk%20mengunduh%20semua%20file,%20salin%20daftar%20tautan%20dan%20tempelkan%20ke%20',%7Ba:%7Bhref:'http://en.wikipedia.org/wiki/Download_manager',text:'pengelola%20unduhan'%7D%7D,'.%20Jika%20Anda%20tidak%20memiliki%20pengelola%20unduhan,%20kami%20menyarankan%20',%7Ba:%7Bhref:'http://www.freedownloadmanager.org/',text:'Free%20Download%20Manager'%7D%7D,'.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Daftar%20putar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Untuk%20memutar%20daftar%20putar%20yang%20disimpan,%20sekarang%20bisa%20dibuka%20di%20pemutar%20musik.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummySfTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22HD%20atau%20MP3%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuItem%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bspan:%7B%7D%7D,'%20via%20Ummy'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bp:%7Btext:'Pasang%20Ummy%20Video%20Downloader%20%20dan%20unduh%20video%20favorit%20Anda%20dalam%20format%20HD%20atau%20MP3.'%7D%7D,%7Bp:%7Bclass:'center',append:%5B%7Ba:%7Bclass:'green-btn-2%20arrow',href:'%7Burl%7D',target:'_blank',text:'Unduh'%7D%7D%5D%7D%7D,%7Bp:%7Bappend:%5B'Setelah%20pemasangan,%20unduhan%20akan%20otomatis%20dimulai%20setiap%20kali%20Anda%20mengeklik%20',%7Bimg:%7Bsrc:'#'%7D%7D%5D%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Periksa%20setelan%20browser%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Opsi%20%5C%22Selalu%20tanya%20saya%20di%20mana%20menyimpan%20file%5C%22%20harus%20dinonaktifkan.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22readMore%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Lainnya%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noWarning%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Jangan%20beri%20tahu%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22cancel%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Batal%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22continue%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Lanjutkan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22beforeDownloadPopupWarn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Perhatian!%20Pengunduhan%20tidak%20dapat%20dibatalkan%20atau%20ditunda.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Info%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfoTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ukuran%20file%20dan%20bitrate%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkMp3LinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tautan%20atau%20file%20MP3%20tidak%20ditemukan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkPhotoLinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Foto%20tidak%20ditemukan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadPhotoAlbum%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Unduh%20album%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadAllPhotoAlbums%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Unduh%20semua%20album%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Foto%20ditemukan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkNotAvailablePhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%25d%20foto%20sementara%20ini%20tidak%20tersedia%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tautan%20ditemukan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundOf%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22dari%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkShowAs%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tampilkan%20sebagai%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Daftar%20tautan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinksInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Untuk%20mengunduh%20semua%20foto,%20salin%20daftar%20tautan%20dan%20tempelkan%20ke%20',%7Ba:%7Bhref:'http://en.wikipedia.org/wiki/Download_manager',text:'pengelola%20unduhan'%7D%7D,'.%20Jika%20Anda%20tidak%20memiliki%20pengelola%20unduhan,%20kami%20menyarankan%20',%7Ba:%7Bhref:'http://www.freedownloadmanager.org/',text:'Free%20Download%20Manager'%7D%7D,'.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkTableOfThumbnails%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tabel%20gambar%20mini%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Daftar%20foto%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotosInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Klik%20foto%20untuk%20mengunduhnya.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkKbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kbps%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeKByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeMByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22MB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeGByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22GB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeTByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22TB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadFromYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Mengunduh:%20buka%20',%7Ba:%7Bhref:'%7Burl%7D',text:'laman%20video'%7D%7D,'%20dan%20tekan%20tombol%20%5C%22Unduh%5C%22%20di%20atas%20pemutar'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundFiles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22File%20ditemukan:%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22shareIn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bagikan%20di%20%25w%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22socialDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dengan%20bantuan%20SaveFrom.net,%20Anda%20dapat%20mengunduh%20file%20dari%20YouTube.com,%20Facebook.com,%20VK.com,%20dan%20lebih%20dari%2040%20lainnya%20hanya%20dengan%20satu%20klik%20gratis%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Berita%20bagus!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'SaveFrom.net%20Helper%20',%7Bimg:%20%7Bsrc:%20'#logo'%7D%7D,'%20telah%20berhasil%20diinstal%20dan%20kini%20Anda%20dapat%20mengunduh%20video%20apa%20pun%20dari%20YouTube%20dengan%20satu%20klik'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Arrow%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Anda%20ingin%20tahu%20caranya?',%20%7Bbr:%7B%7D%7D,%20'Klik%20di%20sini'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS2Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Untuk%20mengunduh%20video,%20pilih%20suatu%20format%20dan%20klik%20tombol%20%5C%22Unduh%5C%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3History%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Riwayat%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Apakah%20Anda%20ingin%20mengunduh%20video%20dari%20Riwayat?',%20%7Bbr:%7B%7D%7D,%20'Cukup%20klik%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,%20'%20pada%20pratinjau%20video%20yang%20telah%20ditonton%20sebelumnya'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS4Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Tidak%20perlu%20menonton%20video%20%E2%80%94%20cukup%20klik%20pada%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,%20',%20pilih%20mutunya,%20dan%20unduh.%20Cukup%20mudah,%20ya?'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Nikmati%20SaveFrom.net%20Helper!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Masih%20punya%20pertanyaan?%20Ingin%20berbagi%20ide?%20Selamat%20datang%20di%20',%20%7Ba:%20%7Btext:%20'halaman%20dukungan',%20href:%20'#support'%7D%7D,'%20kami%20atau%20bergabunglah%20dengan%20kami%20di%20',%20%7Ba:%20%7Btext:%20'Facebook',%20href:%20'#fb'%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialTooltipText%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Cukup%20klik%20tombol%20untuk%20',%7Bb:%20%7Btext:%20'mengunduh'%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyTooltipConfirm%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Apakah%20Anda%20sudah%20menginstal',%7Bbr:%7B%7D%7D,%7Bimg:%7B%7D%7D,'%20Ummy%20Video%20Downloader%20sebelumnya?'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22yes%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ya%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22no%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tidak%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tooltipHide%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Jangan%20perlihatkan%20pesan%20ini%20lagi%22%0A%20%20%20%20%7D%0A%7D";
  _languageList.ru = "%7B%0A%20%20%20%20%22extName%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D0%BD%D0%B8%D0%BA%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B8%D0%B2%D0%B0%D0%B9%D1%82%D0%B5%20%D1%81%20%D0%92%D0%BA%D0%BE%D0%BD%D1%82%D0%B0%D0%BA%D1%82%D0%B5,%20YouTube,%20%D0%9E%D0%B4%D0%BD%D0%BE%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D0%BD%D0%B8%D0%BA%D0%B8%20%D0%B8%20%D0%B5%D1%89%D0%B5%2040%20%D1%81%D0%B0%D0%B9%D1%82%D0%BE%D0%B2%20%D0%B7%D0%B0%201%20%D0%BA%D0%BB%D0%B8%D0%BA.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extNameLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D0%BD%D0%B8%D0%BA%20lite%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B8%D0%B2%D0%B0%D0%B9%D1%82%D0%B5%20%D1%81%20%D0%92%D0%BA%D0%BE%D0%BD%D1%82%D0%B0%D0%BA%D1%82%D0%B5,%20%D0%9E%D0%B4%D0%BD%D0%BE%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D0%BD%D0%B8%D0%BA%D0%B8%20%D0%B8%20%D0%B5%D1%89%D0%B5%2040%20%D1%81%D0%B0%D0%B9%D1%82%D0%BE%D0%B2%20%D0%B7%D0%B0%201%20%D0%BA%D0%BB%D0%B8%D0%BA.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lang%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22ru%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDefault%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D0%BD%D0%B8%D0%BA%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDesabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D0%BD%D0%B8%D0%BA%20%D0%B2%D1%8B%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%BA%D0%BB%D1%8E%D1%87%D0%B8%D1%82%D1%8C%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDisable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D1%8B%D0%BA%D0%BB%D1%8E%D1%87%D0%B8%D1%82%D1%8C%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%BA%D0%B0%D0%B7%D1%8B%D0%B2%D0%B0%D1%82%D1%8C%20%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D1%83%20%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22copy%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9A%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22download%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B0%D0%B6%D0%BC%D0%B8%D1%82%D0%B5%20%D0%BD%D0%B0%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D1%83,%20%D1%83%D0%B4%D0%B5%D1%80%D0%B6%D0%B8%D0%B2%D0%B0%D1%8F%20%D0%BA%D0%BB%D0%B0%D0%B2%D0%B8%D1%88%D1%83%20Alt%20%D0%B8%D0%BB%D0%B8%20Ctrl,%20%D1%87%D1%82%D0%BE%D0%B1%D1%8B%20%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D1%8C%20%D1%84%D0%B0%D0%B9%D0%BB.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noLinksFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B5%20%D1%83%D0%B4%D0%B0%D0%BB%D0%BE%D1%81%D1%8C%20%D0%BD%D0%B0%D0%B9%D1%82%D0%B8%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22more%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%95%D1%89%D1%91%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22close%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%B0%D0%BA%D1%80%D1%8B%D1%82%D1%8C%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22kbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%BA%D0%B1/%D1%81%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22withoutAudio%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%B1%D0%B5%D0%B7%20%D0%B0%D1%83%D0%B4%D0%B8%D0%BE%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22size%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22subtitles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D1%83%D0%B1%D1%82%D0%B8%D1%82%D1%80%D1%8B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BB%D0%B5%D0%B9%D0%BB%D0%B8%D1%81%D1%82%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadWholePlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D0%B2%D0%B5%D1%81%D1%8C%20%D0%BF%D0%BB%D0%B5%D0%B9%D0%BB%D0%B8%D1%81%D1%82%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9E%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B8%D1%82%D1%8C%20%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B0%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeFailTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B5%20%D1%83%D0%B4%D0%B0%D0%BB%D0%BE%D1%81%D1%8C%20%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B8%D1%82%D1%8C%20%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B0.%20%D0%9F%D0%BE%D0%BF%D1%80%D0%BE%D0%B1%D1%83%D0%B9%D1%82%D0%B5%20%D0%BF%D0%BE%D0%B2%D1%82%D0%BE%D1%80%D0%B8%D1%82%D1%8C%20%D0%BF%D0%BE%D0%BF%D1%8B%D1%82%D0%BA%D1%83.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lmButtonTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%BB%D1%83%D1%87%D0%B8%20%D0%BF%D1%80%D1%8F%D0%BC%D1%83%D1%8E%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D1%83%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%B5%D1%80%D0%B5%D0%B9%D1%82%D0%B8%20%D0%BD%D0%B0%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9E%D0%B1%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D1%8C%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinksNotification%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D1%81%D1%8B%D0%BB%D0%BA%D0%B8%20%D0%BE%D0%B1%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D1%8B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D0%B0%D1%83%D0%B4%D0%B8%D0%BE%20%D1%84%D0%B0%D0%B9%D0%BB%D1%8B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D0%BF%D0%BB%D0%B5%D0%B9%D0%BB%D0%B8%D1%81%D1%82%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22installFullVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D1%8C%20%D0%BF%D0%BE%D0%BB%D0%BD%D1%83%D1%8E%20%D0%B2%D0%B5%D1%80%D1%81%D0%B8%D1%8E%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D1%8B%D0%BA%D0%BB%D1%8E%D1%87%D0%B8%D1%82%D1%8C%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22reportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BE%D0%BE%D0%B1%D1%89%D0%B8%D1%82%D1%8C%20%D0%BE%D0%B1%20%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B5%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22openPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D1%82%D0%B0%D1%82%D1%8C%20%D0%BB%D1%83%D1%87%D1%88%D0%B5%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9E%D1%82%D0%BA%D0%BB%D1%8E%D1%87%D0%B8%D1%82%D1%8C%20%D0%BD%D0%B0%20%D1%8D%D1%82%D0%BE%D0%BC%20%D1%81%D0%B0%D0%B9%D1%82%D0%B5%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%BA%D0%BB%D1%8E%D1%87%D0%B8%D1%82%D1%8C%20%D0%BD%D0%B0%20%D1%8D%D1%82%D0%BE%D0%BC%20%D1%81%D0%B0%D0%B9%D1%82%D0%B5%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableDisableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%BA%D0%BB/%D0%92%D1%8B%D0%BA%D0%BB%20%D0%BD%D0%B0%20%D1%8D%D1%82%D0%BE%D0%BC%20%D1%81%D0%B0%D0%B9%D1%82%D0%B5%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showHideButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%BA%D0%B0%D0%B7./%D1%81%D0%BA%D1%80.%20%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D1%83%20%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateTo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9E%D0%B1%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D1%8C%20%D0%B4%D0%BE%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9E%20%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D0%BD%D0%B8%D0%BA%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%B5%D1%80%D1%81%D0%B8%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%B7%D0%B2%D0%BE%D0%BB%D1%8F%D0%B5%D1%82%20%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B0%D1%82%D1%8C%20%D0%BF%D1%80%D1%8F%D0%BC%D1%8B%D0%B5%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8%20%D0%B4%D0%BB%D1%8F%20%D1%81%D0%BA%D0%B0%D1%87%D0%B8%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%20%D1%81%20%D0%B1%D0%BE%D0%BB%D0%B5%D0%B5%20%D1%87%D0%B5%D0%BC%2040%20%D1%81%D0%B0%D0%B9%D1%82%D0%BE%D0%B2,%20%D1%81%D1%80%D0%B5%D0%B4%D0%B8%20%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D1%85%20%20VK.com,%20YouTube.com%20%D0%B8%20%D0%B4%D1%80%D1%83%D0%B3%D0%B8%D0%B5.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%B7%D0%B2%D0%BE%D0%BB%D1%8F%D0%B5%D1%82%20%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B0%D1%82%D1%8C%20%D0%BF%D1%80%D1%8F%D0%BC%D1%8B%D0%B5%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8%20%D0%B4%D0%BB%D1%8F%20%D1%81%D0%BA%D0%B0%D1%87%D0%B8%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%20%D1%81%20%D0%B1%D0%BE%D0%BB%D0%B5%D0%B5%20%D1%87%D0%B5%D0%BC%2040%20%D1%81%D0%B0%D0%B9%D1%82%D0%BE%D0%B2,%20%D1%81%D1%80%D0%B5%D0%B4%D0%B8%20%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D1%85%20%20VK.com,%20Vimeo%20%D0%B8%20%D0%B4%D1%80%D1%83%D0%B3%D0%B8%D0%B5.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutSupported%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%B8%D0%B2%D0%B0%D0%B5%D0%BC%D1%8B%D0%B5%20%D1%80%D0%B5%D1%81%D1%83%D1%80%D1%81%D1%8B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22homePage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%94%D0%BE%D0%BC%D0%B0%D1%88%D0%BD%D1%8F%D1%8F%20%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D0%BD%D0%B8%D0%BA%20-%20%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsHandleLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%B0%D1%82%D1%8B%D0%B2%D0%B0%D1%82%D1%8C%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMediaHostings%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B0%20%D0%BC%D0%B5%D0%B4%D0%B8%D0%B0%D1%85%D0%BE%D1%81%D1%82%D0%B8%D0%BD%D0%B3%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsModules%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22YouTube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYTHideLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D1%80%D1%8B%D0%B2%D0%B0%D1%82%D1%8C%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsDailymotion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dailymotion%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVimeo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Vimeo%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsFacebook%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Facebook%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSoundcloud%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SoundCloud%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVkontakte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%BA%D0%BE%D0%BD%D1%82%D0%B0%D0%BA%D1%82%D0%B5%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsOdnoklassniki%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9E%D0%B4%D0%BD%D0%BE%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D0%BD%D0%B8%D0%BA%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMailru%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9C%D0%BE%D0%B9%20%D0%BC%D0%B8%D1%80%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsInstagram%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Instagram%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsRutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Rutube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsBitrate%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%BA%D0%B0%D0%B7%D1%8B%D0%B2%D0%B0%D1%82%D1%8C%20%D0%B1%D0%B8%D1%82%D1%80%D0%B5%D0%B9%D1%82%20%D1%81%D1%80%D0%B0%D0%B7%D1%83%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSovetnikEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BE%D0%B2%D0%B5%D1%82%D0%BD%D0%B8%D0%BA%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%BA%D0%B0%D0%B7%D1%8B%D0%B2%D0%B0%D1%82%D1%8C%20%D0%BF%D0%BE%D0%B4%D1%81%D0%BA%D0%B0%D0%B7%D0%BA%D0%B8%20%D0%B4%D0%BB%D1%8F%20Ummy%20Video%20Downloader%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsGmNativeDownload%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A0%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9%20%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%20%D0%B7%D0%B0%D0%BA%D0%B0%D1%87%D0%BA%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyBtn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9E%D1%82%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B0%D1%82%D1%8C%20%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D1%83%20Ummy%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsAviaBarEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BE%D0%B2%D0%B5%D1%82%D0%BD%D0%B8%D0%BA%20%D0%94%D0%B5%D1%88%D0%B5%D0%B2%D1%8B%D1%85%20%D0%90%D0%B2%D0%B8%D0%B0%D0%B1%D0%B8%D0%BB%D0%B5%D1%82%D0%BE%D0%B2%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSaveAsDialog%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D1%81%D0%B5%D0%B3%D0%B4%D0%B0%20%D0%B2%D1%8B%D0%B4%D0%B0%D0%B2%D0%B0%D1%82%D1%8C%20%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%20%D0%BD%D0%B0%20%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5%20%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D1%84%D0%B0%D0%B9%D0%BB%D1%8B%20%D1%81%20%D1%82%D0%B5%D0%BA%D1%83%D1%89%D0%B5%D0%B9%20%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D1%8B%20%D1%81%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E%20%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuUpdateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B0%D0%B6%D0%BC%D0%B8%D1%82%D0%B5,%20%D0%B5%D1%81%D0%BB%D0%B8%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B0%20%D0%B4%D0%BB%D1%8F%20%D1%81%D0%BA%D0%B0%D1%87%D0%B8%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%20%D0%BD%D0%B5%20%D0%BF%D0%BE%D1%8F%D0%B2%D0%BB%D1%8F%D0%B5%D1%82%D1%81%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D0%B2%D1%81%D0%B5%20%D0%BD%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5%20%D0%BD%D0%B0%20%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B5%20%D0%B0%D1%83%D0%B4%D0%B8%D0%BE%D1%84%D0%B0%D0%B9%D0%BB%D1%8B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A4%D0%BE%D1%80%D0%BC%D0%B8%D1%80%D1%83%D0%B5%D1%82%20%D0%B8%20%D1%81%D0%BA%D0%B0%D1%87%D0%B8%D0%B2%D0%B0%D0%B5%D1%82%20%D0%BF%D0%BB%D0%B5%D0%B9%D0%BB%D0%B8%D1%81%D1%82%20%D1%81%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B0%D0%BC%D0%B8%20%D0%BD%D0%B0%20%D0%B0%D1%83%D0%B4%D0%B8%D0%BE%D1%84%D0%B0%D0%B9%D0%BB%D1%8B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D0%B2%D1%81%D0%B5%20%D0%BD%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5%20%D0%BD%D0%B0%20%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B5%20%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuReportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%94%D0%B0%D0%B9%D1%82%D0%B5%20%D0%BD%D0%B0%D0%BC%20%D0%B7%D0%BD%D0%B0%D1%82%D1%8C,%20%D0%B5%D1%81%D0%BB%D0%B8%20%D0%B2%D0%BE%D0%B7%D0%BD%D0%B8%D0%BA%D0%BB%D0%B8%20%D0%BF%D1%80%D0%BE%D0%B1%D0%BB%D0%B5%D0%BC%D1%8B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuShowOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%BA%D0%BB./%D0%BE%D1%82%D0%BA%D0%BB.%20%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%B8%D0%B2%D0%B0%D0%B5%D0%BC%D1%8B%D0%B5%20%D1%80%D0%B5%D1%81%D1%83%D1%80%D1%81%D1%8B%20%D0%B8%20%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D0%BD%D0%B8%D0%BA%D0%B0%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnableExtension%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuOpenPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%B6%D0%B0%D0%BB%D1%83%D0%B9%D1%81%D1%82%D0%B0,%20%D0%BE%D1%86%D0%B5%D0%BD%D0%B8%D1%82%D0%B5%20%D0%BA%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D1%8F%20%5C%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D0%BD%D0%B8%D0%BA%5C%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22quality%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22qualityNote%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%95%D1%81%D0%BB%D0%B8%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%20%D0%B2%20%D0%BD%D1%83%D0%B6%D0%BD%D0%BE%D0%BC%20%D0%BA%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%B5%20%D0%BD%D0%B5%D1%82,%20%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D0%B5%D1%82%D1%81%D1%8F%20%D0%BB%D1%83%D1%87%D1%88%D0%B5%D0%B5%20%D0%B8%D0%B7%20%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D0%B3%D0%BE.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D0%BD%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D0%BD%D1%8B%D1%85%20%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%A7%D1%82%D0%BE%D0%B1%D1%8B%20%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D0%B2%D1%81%D0%B5%20%D1%84%D0%B0%D0%B9%D0%BB%D1%8B,%20%D1%81%D0%BA%D0%BE%D0%BF%D0%B8%D1%80%D1%83%D0%B9%D1%82%D0%B5%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D1%81%D1%81%D1%8B%D0%BB%D0%BE%D0%BA%20%D0%B8%20%D0%B2%D1%81%D1%82%D0%B0%D0%B2%D1%8C%D1%82%D0%B5%20%D0%B5%D0%B3%D0%BE%20%D0%B2%20',%7Ba:%7Bhref:'http://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%B5%D1%80_%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BE%D0%BA',text:'%D0%BC%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%B5%D1%80%20%D0%B7%D0%B0%D0%BA%D0%B0%D1%87%D0%B5%D0%BA'%7D%7D,'.%20%D0%95%D1%81%D0%BB%D0%B8%20%D1%83%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%20%D0%BC%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%B5%D1%80%20%D0%B7%D0%B0%D0%BA%D0%B0%D1%87%D0%B5%D0%BA,%20%D1%80%D0%B5%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D0%B4%D1%83%D0%B5%D0%BC%20%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D1%8C%20',%7Ba:%7Bhref:'http://www.westbyte.com/dm/',text:'Download%20Master'%7D%7D,'.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BB%D0%B5%D0%B9%D0%BB%D0%B8%D1%81%D1%82%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9%20%D0%BF%D0%BB%D0%B5%D0%B9%D0%BB%D0%B8%D1%81%D1%82%20%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%20%D0%BE%D1%82%D0%BA%D1%80%D1%8B%D1%82%D1%8C%20%D0%B2%20%D0%BF%D0%BB%D0%B5%D0%B5%D1%80%D0%B5%20%D0%B4%D0%BB%D1%8F%20%20%D0%B2%D0%BE%D1%81%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummySfTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22HD%20%D0%B8%D0%BB%D0%B8%20MP3%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuItem%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bspan:%7B%7D%7D,'%20%D1%81%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E%20Ummy'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bp:%7Bappend:%5B'%D0%A1%D0%BA%D0%B0%D1%87%D0%B8%D0%B2%D0%B0%D0%B9%D1%82%D0%B5%20HD%20%D0%B8%20MP3%20%D1%81%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E%20%D0%B1%D0%B5%D1%81%D0%BF%D0%BB%D0%B0%D1%82%D0%BD%D0%BE%D0%B9%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D1%8B',%20%7Bbr:%7B%7D%7D,%20'Ummy%20Video%20Downloader!'%5D%7D%7D,%7Bp:%7Bclass:'center',append:%5B%7Ba:%7Bclass:'green-btn-2%20arrow',href:'%7Burl%7D',target:'_blank',text:'%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D1%8C'%7D%7D%5D%7D%7D,%7Bp:%7Bappend:%5B'%D0%9F%D0%BE%D1%81%D0%BB%D0%B5%20%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B8%20%D1%81%D0%BA%D0%B0%D1%87%D0%B8%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%B1%D1%83%D0%B4%D0%B5%D1%82%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%82%D1%8C%D1%81%D1%8F%20%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8',%20%7Bbr:%7B%7D%7D,%20'%D0%BF%D1%80%D0%B8%20%D0%BA%D0%BB%D0%B8%D0%BA%D0%B5%20%D0%BD%D0%B0%20',%7Bimg:%7Bsrc:'#'%7D%7D%5D%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D1%8C%D1%82%D0%B5%20%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B8%20%D0%B1%D1%80%D0%B0%D1%83%D0%B7%D0%B5%D1%80%D0%B0%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D1%8B%D0%B1%D0%BE%D1%80%20%D0%BF%D0%B0%D0%BF%D0%BA%D0%B8%20%D0%BF%D1%80%D0%B8%20%D1%81%D0%BA%D0%B0%D1%87%D0%B8%D0%B2%D0%B0%D0%BD%D0%B8%D0%B8%20%D0%B4%D0%BE%D0%BB%D0%B6%D0%B5%D0%BD%20%D0%B1%D1%8B%D1%82%D1%8C%20%D0%BE%D1%82%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22readMore%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%B4%D1%80%D0%BE%D0%B1%D0%BD%D0%B5%D0%B5...%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noWarning%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B5%20%D0%BF%D1%80%D0%B5%D0%B4%D1%83%D0%BF%D1%80%D0%B5%D0%B6%D0%B4%D0%B0%D1%82%D1%8C%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22cancel%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9E%D1%82%D0%BC%D0%B5%D0%BD%D0%B0%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22continue%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D1%80%D0%BE%D0%B4%D0%BE%D0%BB%D0%B6%D0%B8%D1%82%D1%8C%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22beforeDownloadPopupWarn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%BD%D0%B8%D0%BC%D0%B0%D0%BD%D0%B8%D0%B5:%20%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D0%B8%D1%82%D1%8C%20%D0%B8%D0%BB%D0%B8%20%D0%BF%D1%80%D0%B8%D0%BE%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D1%8C%20%D0%B7%D0%B0%D0%BA%D0%B0%D1%87%D0%BA%D1%83%20%D0%B1%D1%83%D0%B4%D0%B5%D1%82%20%D0%BD%D0%B5%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80%D1%8B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfoTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A0%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B0%20%D0%B8%20%D0%B1%D0%B8%D1%82%D1%80%D0%B5%D0%B9%D1%82%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkMp3LinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B5%20%D0%BD%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D1%8B%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8%20%D0%BD%D0%B0%20MP3%20%D1%84%D0%B0%D0%B9%D0%BB%D1%8B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkPhotoLinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B5%20%D0%BD%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D1%8B%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8%20%D0%BD%D0%B0%20%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadPhotoAlbum%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D0%B0%D0%BB%D1%8C%D0%B1%D0%BE%D0%BC%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadAllPhotoAlbums%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D0%B2%D1%81%D0%B5%20%D0%B0%D0%BB%D1%8C%D0%B1%D0%BE%D0%BC%D1%8B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D0%BE%20%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D0%B9%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkNotAvailablePhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%25d%20%D1%84%D0%BE%D1%82%D0%BE%20%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D0%BE%20%D0%BD%D0%B5%20%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%BD%D0%BE%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D0%BE%20%D1%81%D1%81%D1%8B%D0%BB%D0%BE%D0%BA%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundOf%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%B8%D0%B7%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkShowAs%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D1%8C%20%D0%BA%D0%B0%D0%BA%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D1%81%D1%81%D1%8B%D0%BB%D0%BE%D0%BA%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinksInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%A7%D1%82%D0%BE%D0%B1%D1%8B%20%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D0%B2%D1%81%D0%B5%20%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D0%B8,%20%D1%81%D0%BA%D0%BE%D0%BF%D0%B8%D1%80%D1%83%D0%B9%D1%82%D0%B5%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D1%81%D1%81%D1%8B%D0%BB%D0%BE%D0%BA%20%D0%B8%20%D0%B2%D1%81%D1%82%D0%B0%D0%B2%D1%8C%D1%82%D0%B5%20%D0%B5%D0%B3%D0%BE%20%D0%B2%20',%7Ba:%7Bhref:'http://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%B5%D1%80_%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BE%D0%BA',text:'%D0%BC%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%B5%D1%80%20%D0%B7%D0%B0%D0%BA%D0%B0%D1%87%D0%B5%D0%BA'%7D%7D,'.%20%D0%95%D1%81%D0%BB%D0%B8%20%D1%83%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%20%D0%BC%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%B5%D1%80%20%D0%B7%D0%B0%D0%BA%D0%B0%D1%87%D0%B5%D0%BA,%20%D1%80%D0%B5%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D0%B4%D1%83%D0%B5%D0%BC%20%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D1%8C%20',%7Ba:%7Bhref:'http://www.westbyte.com/dm/',text:'Download%20Master'%7D%7D,'.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkTableOfThumbnails%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A2%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83%20%D1%8D%D1%81%D0%BA%D0%B8%D0%B7%D0%BE%D0%B2%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D0%B9%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotosInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A7%D1%82%D0%BE%D0%B1%D1%8B%20%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D1%8E,%20%D1%89%D0%B5%D0%BB%D0%BA%D0%BD%D0%B8%D1%82%D0%B5%20%D0%BD%D0%B0%20%D0%BD%D0%B5%D0%B9%20%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9%20%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D0%BE%D0%B9%20%D0%BC%D1%8B%D1%88%D0%B8.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkKbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%BA%D0%B1/%D1%81%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%91%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeKByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%BA%D0%91%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeMByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9C%D0%91%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeGByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%93%D0%91%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeTByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A2%D0%91%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadFromYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C:%20%D0%BE%D1%82%D0%BA%D1%80%D0%BE%D0%B9%D1%82%D0%B5%20',%7Ba:%7Bhref:'%7Burl%7D',text:'%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D1%83%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%20%D1%80%D0%BE%D0%BB%D0%B8%D0%BA%D0%B0'%7D%7D,'%20%D0%B8%20%D0%BD%D0%B0%D0%B6%D0%BC%D0%B8%D1%82%D0%B5%20%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D1%83%20%5C%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%5C%22%20%D0%BD%D0%B0%D0%B4%20%D0%BF%D0%BB%D0%B5%D0%B5%D1%80%D0%BE%D0%BC'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundFiles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D0%BE%20%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2:%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22shareIn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%B4%D0%B5%D0%BB%D0%B8%D1%82%D1%8C%D1%81%D1%8F%20%D0%B2%20%25w%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22socialDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D0%BD%D0%B8%D0%BA%20%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D0%B5%D1%82%20%D0%B1%D0%B5%D1%81%D0%BF%D0%BB%D0%B0%D1%82%D0%BD%D0%BE%20%D1%81%D0%BA%D0%B0%D1%87%D0%B8%D0%B2%D0%B0%D1%82%D1%8C%20%D1%81%20VK.com,%20YouTube.com,%20Odnoklassniki.ru%20%D0%B8%20%D0%B1%D0%BE%D0%BB%D0%B5%D0%B5%2040%20%D0%B4%D1%80%D1%83%D0%B3%D0%B8%D1%85%20%D1%81%D0%B0%D0%B9%D1%82%D0%BE%D0%B2%20%D0%B2%201%20%D0%BA%D0%BB%D0%B8%D0%BA%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A5%D0%BE%D1%80%D0%BE%D1%88%D0%B8%D0%B5%20%D0%BD%D0%BE%D0%B2%D0%BE%D1%81%D1%82%D0%B8!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%A3%20%D1%82%D0%B5%D0%B1%D1%8F%20%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%20SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D0%BD%D0%B8%D0%BA%20',%7Bimg:%20%7Bsrc:%20'#logo'%7D%7D,',%20%D0%B8%20%D1%82%D0%B5%D0%BF%D0%B5%D1%80%D1%8C%20%D1%82%D1%8B%20%D0%BC%D0%BE%D0%B6%D0%B5%D1%88%D1%8C%20%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D0%BB%D1%8E%D0%B1%D0%BE%D0%B5%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%20%D1%81%20YouTube%20%D0%B2%20%D0%BE%D0%B4%D0%B8%D0%BD%20%D0%BA%D0%BB%D0%B8%D0%BA'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Arrow%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%A5%D0%BE%D1%87%D0%B5%D1%88%D1%8C%20%D1%83%D0%B7%D0%BD%D0%B0%D1%82%D1%8C%20%D0%BA%D0%B0%D0%BA?',%7Bbr:%7B%7D%7D,'%D0%9D%D0%B0%D0%B6%D0%BC%D0%B8%20%D0%B7%D0%B4%D0%B5%D1%81%D1%8C'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS2Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A7%D1%82%D0%BE%D0%B1%D1%8B%20%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE,%20%D0%B2%D1%8B%D0%B1%D0%B5%D1%80%D0%B8%20%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%20%D0%B8%20%D0%BD%D0%B0%D0%B6%D0%BC%D0%B8%20%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D1%83%20%5C%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%5C%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3History%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%A5%D0%BE%D1%87%D0%B5%D1%88%D1%8C%20%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20%D1%83%D0%B6%D0%B5%20%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%D0%B5%D0%BD%D0%BD%D0%BE%D0%B5%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE?',%7Bbr:%7B%7D%7D,'%D0%9D%D0%B0%D0%B6%D0%B8%D0%BC%D0%B0%D0%B9%20%D0%BD%D0%B0%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,'%20%D0%BD%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B2%D1%8C%D1%8E%20%D0%B2%20%D0%9F%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%D0%B5%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS4Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%92%D0%B8%D0%B4%D0%B5%D0%BE%20%D0%BD%D0%B5%20%D0%BE%D0%B1%D1%8F%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%20%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D0%B2%D0%B0%D1%82%D1%8C%20%E2%80%94',%7Bbr:%7B%7D%7D,'%D0%BD%D0%B0%D0%B6%D0%B8%D0%BC%D0%B0%D0%B9%20%D0%BD%D0%B0%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,',%20%D0%B2%D1%8B%D0%B1%D0%B8%D1%80%D0%B0%D0%B9%20%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%20%D0%B8%20%D1%81%D0%BA%D0%B0%D1%87%D0%B8%D0%B2%D0%B0%D0%B9.%20%D0%AD%D1%82%D0%BE%20%D1%83%D0%B4%D0%BE%D0%B1%D0%BD%D0%BE!'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D1%80%D0%B8%D1%8F%D1%82%D0%BD%D0%BE%D0%B9%20%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%9E%D1%81%D1%82%D0%B0%D0%BB%D0%B8%D1%81%D1%8C%20%D0%B2%D0%BE%D0%BF%D1%80%D0%BE%D1%81%D1%8B?%20%D0%95%D1%81%D1%82%D1%8C%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F?%20%D0%97%D0%B0%D0%B3%D0%BB%D1%8F%D0%BD%D0%B8%D1%82%D0%B5%20%D0%BD%D0%B0%20',%20%7Ba:%20%7Btext:%20'%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D1%83%20%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D0%B8',%20href:%20'#support'%7D%7D,'%20%D0%B8%D0%BB%D0%B8%20%D0%B2%D1%81%D1%82%D1%83%D0%BF%D0%B0%D0%B9%D1%82%D0%B5%20%D0%B2%20%D0%BD%D0%B0%D1%88%D0%B5%20',%20%7Ba:%20%7Btext:%20'%D0%92%D0%9A-%D1%81%D0%BE%D0%B1%D1%89%D0%B5%D1%81%D1%82%D0%B2%D0%BE',%20href:%20'#vk'%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialTooltipText%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%A7%D1%82%D0%BE%D0%B1%D1%8B%20',%7Bb:%20%7Btext:%20'%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C'%7D%7D,',%20%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%20%D0%BA%D0%BB%D0%B8%D0%BA%D0%BD%D0%B8%D1%82%D0%B5%20%D0%BF%D0%BE%20%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D0%B5'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyTooltipConfirm%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%92%D1%8B%20%D1%83%D0%B6%D0%B5%20%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D0%BB%D0%B8',%7Bbr:%7B%7D%7D,%7Bimg:%7B%7D%7D,'%20Ummy%20Video%20Downloader?'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22yes%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%94%D0%B0%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22no%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B5%D1%82%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tooltipHide%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%91%D0%BE%D0%BB%D1%8C%D1%88%D0%B5%20%D0%BD%D0%B5%20%D0%BF%D0%BE%D0%BA%D0%B0%D0%B7%D1%8B%D0%B2%D0%B0%D1%82%D1%8C%20%D1%8D%D1%82%D0%BE%20%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B5%22%0A%20%20%20%20%7D%0A%7D";
  _languageList.tr = "%7B%0A%20%20%20%20%22extName%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20asistan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Sadece%20bir%20t%C4%B1klama%20ile%20YouTube,%20Facebook,%20VK.com%20ve%2040'dan%20fazla%20siteden%20dosya%20indirin.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extNameLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20asistan%20lite%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Sadece%20bir%20t%C4%B1klama%20ile%20Facebook,%20VK.com%20ve%2040'dan%20fazla%20siteden%20dosya%20indirin%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lang%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22tr%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDefault%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20asistan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDesabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20asistan%20devre%20d%C4%B1%C5%9F%C4%B1%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Etkin%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDisable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Devre%20d%C4%B1%C5%9F%C4%B1%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Eklenti%20d%C3%BC%C4%9Fmesini%20g%C3%B6ster%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22copy%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Kopyala%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22download%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%C4%B0ndir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dosyay%C4%B1%20indirmek%20i%C3%A7in%20Alt/Option%20veya%20Ctrl%20tu%C5%9Funa%20bas%C4%B1l%C4%B1%20tutarak%20ba%C4%9Flant%C4%B1y%C4%B1%20t%C4%B1klay%C4%B1n.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noLinksFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Hi%C3%A7bir%20ba%C4%9Flant%C4%B1%20bulunamad%C4%B1%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22more%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Daha%20fazla%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22close%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Kapat%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22kbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kbps%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22withoutAudio%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22without%20audio%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22size%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22boyut%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22subtitles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Alt%20yaz%C4%B1%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%C3%87alma%20listesi%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dosya%20listesi%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadWholePlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22T%C3%BCm%20%C3%A7alma%20listesini%20indir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dosya%20boyutunu%20al%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeFailTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dosya%20boyutu%20al%C4%B1namad%C4%B1.%20L%C3%BCtfen%20tekrar%20deneyiniz.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lmButtonTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Do%C4%9Frudan%20ba%C4%9Flant%C4%B1%20al%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net'e%20git%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ba%C4%9Flant%C4%B1lar%C4%B1%20yenile%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinksNotification%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ba%C4%9Flant%C4%B1lar%20g%C3%BCncellendi%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ses%20dosyalar%C4%B1n%C4%B1%20indir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%C3%87alma%20listesini%20indir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Resimleri%20indir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22installFullVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Tam%20versiyonu%20kur%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Devre%20d%C4%B1%C5%9F%C4%B1%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ayarlar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22reportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Hata%20bildir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22openPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Become%20better%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bu%20web%20sitesinde%20devre%20d%C4%B1%C5%9F%C4%B1%20b%C4%B1rak%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bu%20web%20sitesinde%20etkinle%C5%9Ftir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableDisableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bu%20sitede%20etkin/devre%20d%C4%B1%C5%9F%C4%B1%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showHideButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Eklenti%20butonunu%20g%C3%B6ster/gizle%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateTo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%25d%20s%C3%BCr%C3%BCm%C3%BCne%20g%C3%BCncelle%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Hakk%C4%B1nda%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Asistan%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Versiyon%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Kullan%C4%B1c%C4%B1lar%C4%B1n,%20Dailymotion.com,%20YouTube.com,%20VK.com%20ve%20di%C4%9Ferleri%20de%20dahil%20olmak%20%C3%BCzere%2040'dan%20fazla%20web%20sitesinden%20dosya%20indirmek%20i%C3%A7in%20do%C4%9Frudan%20ba%C4%9Flant%C4%B1lar%20almalar%C4%B1n%C4%B1%20sa%C4%9Flar.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Kullan%C4%B1c%C4%B1lar%C4%B1n,%20Dailymotion.com,%20VK.com%20ve%20di%C4%9Ferleri%20de%20dahil%20olmak%20%C3%BCzere%2040'dan%20fazla%20web%20sitesinden%20dosya%20indirmek%20i%C3%A7in%20do%C4%9Frudan%20ba%C4%9Flant%C4%B1lar%20almalar%C4%B1n%C4%B1%20sa%C4%9Flar.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutSupported%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Desteklenen%20kaynaklar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22homePage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ana%20Sayfa%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Asistan%20-%20Tercihler%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsHandleLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Linkleri%20ta%C5%9F%C4%B1%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMediaHostings%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Medya%20payla%C5%9F%C4%B1ma%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsModules%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Mod%C3%BCller%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22YouTube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYTHideLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ba%C4%9Flant%C4%B1lar%C4%B1%20gizle%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsDailymotion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dailymotion%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVimeo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Vimeo%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsFacebook%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Facebook%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSoundcloud%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SoundCloud%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVkontakte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22VK%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsOdnoklassniki%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Odnoklassniki%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMailru%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Moy%20Mir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsInstagram%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Instagram%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsRutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Rutube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsBitrate%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bit%20h%C4%B1z%C4%B1n%C4%B1%20anl%C4%B1k%20olarak%20g%C3%B6ster%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSovetnikEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Advisor%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22UVD%20i%C3%A7in%20ipu%C3%A7lar%C4%B1n%C4%B1%20g%C3%B6ster%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsGmNativeDownload%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Geli%C5%9Fmi%C5%9F%20indirme%20modu%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyBtn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ummy%20d%C3%BC%C4%9Fmesini%20g%C3%B6ster%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsAviaBarEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Cheap%20Flights%20Advisor%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSaveAsDialog%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dosyalar%C4%B1n%20nereye%20kaydedilece%C4%9Fini%20her%20seferinde%20sor%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net'i%20kullanarak%20ge%C3%A7erli%20sayfadan%20dosya%20indirin%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuUpdateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Download%20d%C3%BC%C4%9Fmesi%20g%C3%B6r%C3%BCnm%C3%BCyorsa%20t%C4%B1klay%C4%B1n%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ge%C3%A7erli%20sayfada%20bulunan%20t%C3%BCm%20ses%20dosyalar%C4%B1n%C4%B1%20indirin%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ses%20dosyalar%C4%B1ndan%20olu%C5%9Fan%20bir%20%C3%A7alma%20listesi%20olu%C5%9Fturur%20ve%20indirir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ge%C3%A7erli%20sayfada%20bulunan%20t%C3%BCm%20resimleri%20indirin%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuReportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Herhangi%20bir%20sorun%20olmas%C4%B1%20durumunda%20bize%20bildirin%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuShowOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Desteklenen%20kaynaklar%C4%B1%20ve%20Helper%20se%C3%A7eneklerini%20A%C3%87/KAPAT%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnableExtension%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuOpenPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22quality%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Kalite%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22qualityNote%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Herhangi%20bir%20se%C3%A7ilebilir%20kalitenin%20olmamas%C4%B1%20durumunda%20mevcut%20olan%20en%20iyi%20video%20indirilecektir.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bulunan%20dosyalar%C4%B1n%C4%B1%20listesi%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'T%C3%BCm%20dosyalar%C4%B1n%C4%B1%20indirmek%20i%C3%A7in%20ba%C4%9Flant%C4%B1%20listesini%20kopyalay%C4%B1n%20ve%20',%7Ba:%7Bhref:'http://en.wikipedia.org/wiki/Download_manager',text:'indirme%20y%C3%B6neticisine'%7D%7D,'%20yap%C4%B1%C5%9Ft%C4%B1r%C4%B1n.%20Kurulu%20bir%20indirme%20y%C3%B6neticiniz%20yoksa%20',%7Ba:%7Bhref:'http://www.freedownloadmanager.org/',text:'Free%20Download%20Manager'%7D%7D,'%20y%C3%BCklemenizi%20tavsiye%20ederiz.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%C3%87alma%20Listesi%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Art%C4%B1k%20kaydedilen%20%C3%A7alma%20listenizi%20y%C3%BCr%C3%BCtmek%20i%C3%A7in%20m%C3%BCzik%20%C3%A7alar%C4%B1n%C4%B1zda%20a%C3%A7abilirsiniz.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummySfTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22HD%20veya%20MP3%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuItem%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Ummy%20ile%20',%7Bspan:%7B%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bp:%7Btext:'Ummy%20Video%20%C4%B0ndirici%5C%5C'yi%20y%C3%BCkleyin%20ve%20en%20sevdi%C4%9Finiz%20HD%20videolar%C4%B1%20ya%20da%20MP3%5C%5C'leri%20hemen%20indirin.'%7D%7D,%7Bp:%7Bclass:'center',append:%5B%7Ba:%7Bclass:'green-btn-2%20arrow',href:'%7Burl%7D',target:'_blank',text:'%C4%B0ndir'%7D%7D%5D%7D%7D,%7Bp:%7Bappend:%5B'Kurulumdan%20sonra%20',%7Bimg:%7Bsrc:'#'%7D%7D,'%20simgesine%20t%C4%B1klayarak%20dosya%20indirme%20i%C5%9Flemini%20otomatik%20olarak%20ba%C5%9Flatabilirsiniz.'%5D%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Taray%C4%B1c%C4%B1%20ayarlar%C4%B1n%C4%B1%20kontrol%20edin%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5C%22Dosyalar%C4%B1n%20nereye%20kaydedilece%C4%9Fini%20her%20seferinde%20sor%5C%22%20se%C3%A7ene%C4%9Fi%20kapal%C4%B1%20olmal%C4%B1d%C4%B1r.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22readMore%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Daha%20fazla%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noWarning%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bildirme%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22cancel%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%C4%B0ptal%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22continue%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Devam%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22beforeDownloadPopupWarn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Uyar%C4%B1!%20%C4%B0ndirme%20i%C5%9Flemi%20iptal%20edilemez%20ya%20da%20ertelenemez.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bilgi%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfoTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dosya%20boyutu%20ve%20bit%20h%C4%B1z%C4%B1%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkMp3LinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22MP3%20dosyalar%C4%B1%20i%C3%A7in%20ba%C4%9Flant%C4%B1lar%20bulunam%C4%B1yor%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkPhotoLinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Foto%C4%9Fraflar%20bulunamad%C4%B1%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadPhotoAlbum%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Alb%C3%BCm%C3%BC%20indir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadAllPhotoAlbums%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22T%C3%BCm%20alb%C3%BCmleri%20indir%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bulunan%20foto%C4%9Fraflar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkNotAvailablePhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%25d%20resim%20ge%C3%A7ici%20olarak%20kullan%C4%B1lam%C4%B1yor%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bulunan%20ba%C4%9Flant%C4%B1lar%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundOf%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22den%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkShowAs%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Olarak%20g%C3%B6ster%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ba%C4%9Flant%C4%B1%20listesi%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinksInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'T%C3%BCm%20foto%C4%9Fraflar%C4%B1%20indirmek%20i%C3%A7in%20ba%C4%9Flant%C4%B1%20listesini%20kopyalay%C4%B1n%20ve%20',%7Ba:%7Bhref:'http://en.wikipedia.org/wiki/Download_manager',text:'indirme%20y%C3%B6neticisine'%7D%7D,'%20yap%C4%B1%C5%9Ft%C4%B1r%C4%B1n.%20Kurulu%20bir%20indirme%20y%C3%B6neticiniz%20yoksa%20',%7Ba:%7Bhref:'http://www.freedownloadmanager.org/',text:'Free%20Download%20Manager'%7D%7D,'%20y%C3%BCklemenizi%20tavsiye%20ederiz.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkTableOfThumbnails%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22K%C3%BC%C3%A7%C3%BCkk%20resimler%20tablosu%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Foto%C4%9Fraf%20listesi%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotosInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%C4%B0ndirmek%20i%C3%A7in%20foto%C4%9Fraf%C4%B1n%20%C3%BCzerine%20t%C4%B1klay%C4%B1n.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkKbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kbps%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22B%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeKByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22kB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeMByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22MB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeGByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22GB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeTByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22TB%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadFromYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%C4%B0ndirme:%20',%7Ba:%7Bhref:'%7Burl%7D',text:'video%20sayfas%C4%B1n%C4%B1'%7D%7D,'%20a%C3%A7%C4%B1n%20ve%20oynat%C4%B1c%C4%B1%20%C3%BCzerindeki%20%5C%22%C4%B0ndir%5C%22%20d%C3%BCmesine%20bas%C4%B1n'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundFiles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bulunan%20dosyalar:%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22shareIn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%25w%20%C3%BCzerinden%20payla%C5%9F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22socialDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20Helper,%20sadece%20bir%20t%C4%B1klama%20ile%20YouTube.com,%20Facebook.com,%20VK.com%20ve%2040'dan%20fazla%20siteden%20%C3%BCcretsiz%20olarak%20dosya%20indirmenizi%20sa%C4%9Flar.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Size%20harika%20bir%20haberimiz%20var!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'SaveFrom.net%20Helper%20',%7Bimg:%20%7Bsrc:%20'#logo'%7D%7D,%20'%20ba%C5%9Far%C4%B1yla%20kuruldu.%20Art%C4%B1k%20tek%20bir%20t%C4%B1klama%20ile%20YouTube%5C%5C'dan%20istedi%C4%9Finiz%20videoyu%20indirebilirsiniz'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Arrow%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Nas%C4%B1l%20oldu%C4%9Funu%20%C3%B6%C4%9Frenmek%20ister%20misiniz?%20Buraya%20t%C4%B1klay%C4%B1n'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS2Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Sadece%20indirmek%20istedi%C4%9Finiz%20videonun%20format%C4%B1n%C4%B1%20se%C3%A7in%20ve%20%5C%22%C4%B0ndir%5C%22%20butonuna%20t%C4%B1klay%C4%B1n%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3History%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Ge%C3%A7mi%C5%9F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Web%20ge%C3%A7mi%C5%9Finizdeki%20videolar%C4%B1%20indirmek%20ister%20misiniz?',%20%7Bbr:%7B%7D%7D,%20'%20Sadece%20daha%20%C3%B6nce%20izledi%C4%9Finiz%20bir%20videonun%20%C3%B6nizlemesi%20%C3%BCzerindeki%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,%20'%20simgesine%20t%C4%B1klay%C4%B1n'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS4Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Videolar%C4%B1%20izlemenize%20gerek%20yok%20%E2%80%94%20sadece%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,%20'%20simgesine%20t%C4%B1klay%C4%B1n,%20kalite%20de%C4%9Ferini%20se%C3%A7in%20ve%20an%C4%B1nda%20indirin.%20Olduk%C3%A7a%20kolay,%20de%C4%9Fil%20mi?'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Hemen%20SaveFrom.net%20Helper'in%20keyfini%20%C3%A7%C4%B1karmaya%20ba%C5%9Flay%C4%B1n!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'Hala%20kafan%C4%B1za%20tak%C4%B1lan%20sorular%20m%C4%B1%20var?%20D%C3%BC%C5%9F%C3%BCncelerinizi%20payla%C5%9Fmak%20m%C4%B1%20istiyorsunuz?%20',%7Ba:%20%7Btext:%20'Destek%20sayfam%C4%B1z%C4%B1',%20href:%20'#support'%7D%7D,'%20ziyaret%20edin%20veya%20',%7Ba:%20%7Btext:%20'Facebook',%20href:%20'#fb'%7D%7D,'%20toplulu%C4%9Fumuza%20kat%C4%B1l%C4%B1n'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialTooltipText%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bb:%20%7Btext:%20'%C4%B0ndirmek'%7D%7D,%20'%20i%C3%A7in%20sadece%20butona%20t%C4%B1klay%C4%B1n'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyTooltipConfirm%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bimg:%7B%7D%7D,'%20Ummy%20Video%20Downloader%20program%C4%B1n%C4%B1%20daha%20%C3%B6nce%20y%C3%BCklediniz%20mi?'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22yes%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Evet%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22no%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Hay%C4%B1r%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tooltipHide%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Bu%20mesaj%C4%B1%20tekrar%20g%C3%B6sterme%22%0A%20%20%20%20%7D%0A%7D";
  _languageList.uk = "%7B%0A%20%20%20%20%22extName%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D1%96%D1%87%D0%BD%D0%B8%D0%BA%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D1%83%D0%B9%D1%82%D0%B5%20%D0%B7%20%C2%AB%D0%92%D0%9A%D0%BE%D0%BD%D1%82%D0%B0%D0%BA%D1%82%D0%B5%C2%BB,%20YouTube,%20Facebook%20%D1%96%20%D1%89%D0%B5%2040%20%D1%81%D0%B0%D0%B9%D1%82%D1%96%D0%B2%20%D0%B7%D0%B0%201%20%D0%BA%D0%BB%D1%96%D0%BA.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extNameLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D1%96%D1%87%D0%BD%D0%B8%D0%BA%20lite%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22extDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D1%83%D0%B9%D1%82%D0%B5%20%D0%B7%20%C2%AB%D0%92%D0%9A%D0%BE%D0%BD%D1%82%D0%B0%D0%BA%D1%82%D0%B5%C2%BB,%20YouTube,%20Facebook%20%D1%96%20%D1%89%D0%B5%2040%20%D1%81%D0%B0%D0%B9%D1%82%D1%96%D0%B2%20%D0%B7%D0%B0%201%20%D0%BA%D0%BB%D1%96%D0%BA.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lang%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22uk%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDefault%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D1%96%D1%87%D0%BD%D0%B8%D0%BA%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22titleDesabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D1%96%D1%87%D0%BD%D0%B8%D0%BA%20%D0%B2%D0%B8%D0%BC%D0%BA%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A3%D0%B2%D1%96%D0%BC%D0%BA%D0%BD%D1%83%D1%82%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDisable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%B8%D0%BC%D0%BA%D0%BD%D1%83%D1%82%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%BA%D0%B0%D0%B7%D1%83%D0%B2%D0%B0%D1%82%D0%B8%20%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D1%83%20%D1%80%D0%BE%D0%B7%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%BD%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22copy%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9A%D0%BE%D0%BF%D1%96%D1%8E%D0%B2%D0%B0%D1%82%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22download%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B0%D1%82%D0%B8%D1%81%D0%BD%D1%96%D1%82%D1%8C%20%D0%BD%D0%B0%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D0%BD%D1%8F,%20%D1%83%D1%82%D1%80%D0%B8%D0%BC%D1%83%D1%8E%D1%87%D0%B8%20%D0%BA%D0%BB%D0%B0%D0%B2%D1%96%D1%88%D1%83%20Alt%20%D1%87%D0%B8%20Ctrl,%20%D1%89%D0%BE%D0%B1%20%D0%B7%D0%B1%D0%B5%D1%80%D0%B5%D0%B3%D1%82%D0%B8%20%D1%84%D0%B0%D0%B9%D0%BB.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noLinksFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B5%20%D0%B2%D0%B4%D0%B0%D0%BB%D0%BE%D1%81%D1%8F%20%D0%B7%D0%BD%D0%B0%D0%B9%D1%82%D0%B8%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D0%BD%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22more%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A9%D0%B5%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22close%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%B0%D0%BA%D1%80%D0%B8%D1%82%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22kbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%BA%D0%B1/%D1%81%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22withoutAudio%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%B1%D0%B5%D0%B7%20%D0%B0%D1%83%D0%B4%D1%96%D0%BE%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22size%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D1%80%D0%BE%D0%B7%D0%BC%D1%96%D1%80%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22subtitles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D1%83%D0%B1%D1%82%D0%B8%D1%82%D1%80%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BB%D0%B5%D0%B9%D0%BB%D1%96%D1%81%D1%82%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D1%84%D0%B0%D0%B9%D0%BB%D1%96%D0%B2%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadWholePlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8%20%D0%B2%D0%B5%D1%81%D1%8C%20%D0%BF%D0%BB%D0%B5%D0%B9%D0%BB%D1%96%D1%81%D1%82%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%B8%D0%B7%D0%BD%D0%B0%D1%87%D0%B8%D1%82%D0%B8%20%D1%80%D0%BE%D0%B7%D0%BC%D1%96%D1%80%20%D1%84%D0%B0%D0%B9%D0%BB%D1%83%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22getFileSizeFailTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B5%20%D0%B2%D0%B4%D0%B0%D0%BB%D0%BE%D1%81%D1%8F%20%D0%B2%D0%B8%D0%B7%D0%BD%D0%B0%D1%87%D0%B8%D1%82%D0%B8%20%D1%80%D0%BE%D0%B7%D0%BC%D1%96%D1%80%20%D1%84%D0%B0%D0%B9%D0%BB%D1%83.%20%D0%A1%D0%BF%D1%80%D0%BE%D0%B1%D1%83%D0%B9%D1%82%D0%B5%20%D1%89%D0%B5%20%D1%80%D0%B0%D0%B7.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22lmButtonTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9E%D1%82%D1%80%D0%B8%D0%BC%D0%B0%D0%B9%20%D0%BF%D1%80%D1%8F%D0%BC%D0%B5%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D0%BD%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%B5%D1%80%D0%B5%D0%B9%D1%82%D0%B8%20%D0%BD%D0%B0%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D1%96%D0%B4%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D0%B8%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D0%BD%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateLinksNotification%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D0%BD%D1%8F%20%D0%BE%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D1%96%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D0%B8%20%D0%B0%D1%83%D0%B4%D1%96%D0%BE%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D0%B8%20%D0%BF%D0%BB%D0%B5%D0%B9%D0%BB%D0%B8%D1%81%D1%82%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22downloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D0%B8%20%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D1%96%D1%97%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22installFullVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D0%B8%20%D0%BF%D0%BE%D0%B2%D0%BD%D1%83%20%D0%B2%D0%B5%D1%80%D1%81%D1%96%D1%8E%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disable%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%B8%D0%BC%D0%BA%D0%BD%D1%83%D1%82%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B0%D0%BB%D0%B0%D1%88%D1%82%D1%83%D0%B2%D0%B0%D0%BD%D0%BD%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22reportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%B2%D1%96%D0%B4%D0%BE%D0%BC%D0%B8%D1%82%D0%B8%20%D0%BF%D1%80%D0%BE%20%D0%BF%D0%BE%D0%BC%D0%B8%D0%BB%D0%BA%D1%83%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22openPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D1%82%D0%B0%D1%82%D0%B8%20%D0%BA%D1%80%D0%B0%D1%89%D0%B5%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22disableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%B8%D0%BC%D0%BA%D0%BD%D1%83%D1%82%D0%B8%20%D0%BD%D0%B0%20%D1%86%D1%8C%D0%BE%D0%BC%D1%83%20%D1%81%D0%B0%D0%B9%D1%82%D1%96%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A3%D0%B2%D1%96%D0%BC%D0%BA%D0%BD%D1%83%D1%82%D0%B8%20%D0%BD%D0%B0%20%D1%86%D1%8C%D0%BE%D0%BC%D1%83%20%D1%81%D0%B0%D0%B9%D1%82%D1%96%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22enableDisableModule%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%BA%D0%BB./%D0%B2%D0%B8%D0%BC%D0%BA.%20%D0%BD%D0%B0%20%D1%86%D1%8C%D0%BE%D0%BC%D1%83%20%D1%81%D0%B0%D0%B9%D1%82%D1%96%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22showHideButton%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%BA%D0%B0%D0%B7./%D1%81%D0%BA%D1%80.%20%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D1%83%20%D1%80%D0%BE%D0%B7%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%BD%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22updateTo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9E%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D0%B8%20%D0%B4%D0%BE%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D1%80%D0%BE%20%D1%80%D0%BE%D0%B7%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%BD%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D1%96%D1%87%D0%BD%D0%B8%D0%BA%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutVersion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%B5%D1%80%D1%81%D1%96%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescription%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%94%D0%BE%D0%B7%D0%B2%D0%BE%D0%BB%D1%8F%D1%94%20%D0%BE%D1%82%D1%80%D0%B8%D0%BC%D1%83%D0%B2%D0%B0%D1%82%D0%B8%20%D0%BF%D1%80%D1%8F%D0%BC%D1%96%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D0%BD%D1%8F%20%D0%B4%D0%BB%D1%8F%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B5%D0%BD%D0%BD%D1%8F%20%D0%B7%20%D0%BF%D0%BE%D0%BD%D0%B0%D0%B4%2040%20%D1%81%D0%B0%D0%B9%D1%82%D1%96%D0%B2,%20%D1%81%D0%B5%D1%80%D0%B5%D0%B4%20%D1%8F%D0%BA%D0%B8%D1%85%20VK.com,%20YouTube.com%20%D1%82%D0%B0%20%D1%96%D0%BD%D1%88%D1%96.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutDescriptionLite%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%94%D0%BE%D0%B7%D0%B2%D0%BE%D0%BB%D1%8F%D1%94%20%D0%BE%D1%82%D1%80%D0%B8%D0%BC%D1%83%D0%B2%D0%B0%D1%82%D0%B8%20%D0%BF%D1%80%D1%8F%D0%BC%D1%96%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D0%BD%D1%8F%20%D0%B4%D0%BB%D1%8F%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B5%D0%BD%D0%BD%D1%8F%20%D0%B7%20%D0%BF%D0%BE%D0%BD%D0%B0%D0%B4%2040%20%D1%81%D0%B0%D0%B9%D1%82%D1%96%D0%B2,%20%D1%81%D0%B5%D1%80%D0%B5%D0%B4%20%D1%8F%D0%BA%D0%B8%D1%85%20VK.com%20%D1%82%D0%B0%20%D1%96%D0%BD%D1%88%D1%96.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22aboutSupported%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A0%D0%B5%D1%81%D1%83%D1%80%D1%81%D0%B8,%20%D1%8F%D0%BA%D1%96%20%D0%BF%D1%96%D0%B4%D1%82%D1%80%D0%B8%D0%BC%D1%83%D1%8E%D1%82%D1%8C%D1%81%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22homePage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%94%D0%BE%D0%BC%D0%B0%D1%88%D0%BD%D1%8F%20%D1%81%D1%82%D0%BE%D1%80%D1%96%D0%BD%D0%BA%D0%B0%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D1%96%D1%87%D0%BD%D0%B8%D0%BA%20-%20%D0%9D%D0%B0%D0%BB%D0%B0%D1%88%D1%82%D1%83%D0%B2%D0%B0%D0%BD%D0%BD%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsHandleLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9E%D0%B1%D1%80%D0%BE%D0%B1%D0%BB%D1%8F%D1%82%D0%B8%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D0%BD%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMediaHostings%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B0%20%D0%BC%D0%B5%D0%B4%D1%96%D0%B0%D1%85%D0%BE%D1%81%D1%82%D0%B8%D0%BD%D0%B3%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsModules%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%96%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22YouTube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsYTHideLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D1%85%D0%BE%D0%B2%D0%B0%D1%82%D0%B8%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D0%BD%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsDailymotion%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Dailymotion%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVimeo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Vimeo%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsFacebook%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Facebook%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSoundcloud%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SoundCloud%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsVkontakte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%9A%D0%BE%D0%BD%D1%82%D0%B0%D0%BA%D1%82%D0%B5%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsOdnoklassniki%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9E%D0%B4%D0%BD%D0%BE%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D0%BD%D0%B8%D0%BA%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsMailru%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9C%D0%BE%D0%B9%20%D0%BC%D0%B8%D1%80%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsInstagram%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Instagram%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsRutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Rutube%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsBitrate%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%BA%D0%B0%D0%B7%D1%83%D0%B2%D0%B0%D1%82%D0%B8%20%D0%B1%D1%96%D1%82%D1%80%D0%B5%D0%B9%D1%82%20%D0%BE%D0%B4%D1%80%D0%B0%D0%B7%D1%83%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSovetnikEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D1%80%D0%B0%D0%B4%D0%BD%D0%B8%D0%BA%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%BA%D0%B0%D0%B7%D1%83%D0%B2%D0%B0%D1%82%D0%B8%20%D0%BF%D1%96%D0%B4%D0%BA%D0%B0%D0%B7%D0%BA%D0%B8%20%D0%B4%D0%BB%D1%8F%20Ummy%20Video%20Downloader%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsGmNativeDownload%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A0%D0%BE%D0%B7%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D0%B9%20%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%20%D0%B7%D0%B0%D0%BA%D0%B0%D1%87%D1%83%D0%B2%D0%B0%D0%BD%D0%BD%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsShowUmmyBtn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D1%96%D0%B4%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B0%D1%82%D0%B8%20%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D1%83%20Ummy%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsAviaBarEnabled%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22Cheap%20Flights%20Advisor%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22optionsSaveAsDialog%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%B0%D0%B2%D0%B6%D0%B4%D0%B8%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%82%D1%83%D0%B2%D0%B0%D1%82%D0%B8%20%D0%B4%D0%B5%20%D0%B7%D0%B1%D0%B5%D1%80%D0%B5%D0%B3%D1%82%D0%B8%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadFromCurrentPage%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B8%20%D0%B7%20%D0%BF%D0%BE%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D1%97%20%D1%81%D1%82%D0%BE%D1%80%D1%96%D0%BD%D0%BA%D0%B8%20%D0%B7%D0%B0%20%D0%B4%D0%BE%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%BE%D1%8E%20%D1%81%D0%B5%D1%80%D0%B2%D1%96%D1%81%D1%83%20SaveFrom.net%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuUpdateLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B0%D1%82%D0%B8%D1%81%D0%BD%D1%96%D1%82%D1%8C,%20%D1%8F%D0%BA%D1%89%D0%BE%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D0%BD%D1%8F%20%D0%B4%D0%BB%D1%8F%20%D1%81%D0%BA%D0%B0%D1%87%D1%83%D0%B2%D0%B0%D0%BD%D0%BD%D1%8F%20%D0%BD%D0%B5%20%D0%B7'%D1%8F%D0%B2%D0%BB%D1%8F%D1%94%D1%82%D1%8C%D1%81%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadMP3Files%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8%20%D0%B2%D1%81%D1%96%20%D0%B7%D0%BD%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D1%96%20%D0%BD%D0%B0%20%D1%81%D1%82%D0%BE%D1%80%D1%96%D0%BD%D1%86%D1%96%20%D0%B0%D1%83%D0%B4%D1%96%D0%BE%D1%84%D0%B0%D0%B9%D0%BB%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPlaylist%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A4%D0%BE%D1%80%D0%BC%D1%83%D1%94%20%D1%82%D0%B0%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D1%83%D1%94%20%D0%BF%D0%BB%D0%B5%D0%B9%D0%BB%D0%B8%D1%81%D1%82%20%D0%B7%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D0%BD%D1%8F%D0%BC%D0%B8%20%D0%BD%D0%B0%20%D0%B0%D1%83%D0%B4%D1%96%D0%BE%D1%84%D0%B0%D0%B9%D0%BB%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuDownloadPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8%20%D0%B2%D1%81%D1%96%20%D0%B7%D0%BD%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D1%96%20%D0%BD%D0%B0%20%D1%81%D1%82%D0%BE%D1%80%D1%96%D0%BD%D1%86%D1%96%20%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D1%96%D1%97%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuReportBug%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%94%D0%B0%D0%B9%D1%82%D0%B5%20%D0%BD%D0%B0%D0%BC%20%D0%B7%D0%BD%D0%B0%D1%82%D0%B8,%20%D1%8F%D0%BA%D1%89%D0%BE%20%D0%B2%D0%B8%D0%BD%D0%B8%D0%BA%D0%BB%D0%B8%20%D0%BF%D1%80%D0%BE%D0%B1%D0%BB%D0%B5%D0%BC%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuShowOptions%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%BA%D0%BB.%20/%20%D0%92%D0%B8%D0%BC%D0%BA.%20%D0%BF%D1%96%D0%B4%D1%82%D1%80%D0%B8%D0%BC%D1%83%D0%B2%D0%B0%D0%BD%D1%96%20%D1%80%D0%B5%D1%81%D1%83%D1%80%D1%81%D0%B8%20%D1%96%20%D0%BC%D0%BE%D0%B6%D0%BB%D0%B8%D0%B2%D0%BE%D1%81%D1%82%D1%96%20%D0%BF%D0%BE%D0%BC%D1%96%D1%87%D0%BD%D0%B8%D0%BA%D0%B0%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuEnableExtension%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22menuOpenPoll%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%91%D1%83%D0%B4%D1%8C%20%D0%BB%D0%B0%D1%81%D0%BA%D0%B0,%20%D0%BE%D1%86%D1%96%D0%BD%D1%96%D1%82%D1%8C%20%D1%8F%D0%BA%D1%96%D1%81%D1%82%D1%8C%20%D1%80%D0%BE%D0%B7%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%BD%D1%8F%20%5C%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D1%96%D1%87%D0%BD%D0%B8%D0%BA%5C%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22quality%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%AF%D0%BA%D1%96%D1%81%D1%82%D1%8C%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22qualityNote%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%AF%D0%BA%D1%89%D0%BE%20%D0%B2%D1%96%D0%B4%D0%B5%D0%BE%20%D0%B2%20%D0%BF%D0%BE%D1%82%D1%80%D1%96%D0%B1%D0%BD%D1%96%D0%B9%20%D1%8F%D0%BA%D0%BE%D1%81%D1%82%D1%96%20%D0%BD%D0%B5%D0%BC%D0%B0%D1%94,%20%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D1%94%D1%82%D1%8C%D1%81%D1%8F%20%D0%BD%D0%B0%D0%B9%D0%BA%D1%80%D0%B0%D1%89%D0%B5%20%D0%B7%20%D0%BC%D0%BE%D0%B6%D0%BB%D0%B8%D0%B2%D0%BE%D0%B3%D0%BE.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D0%B7%D0%BD%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D0%B8%D1%85%20%D1%84%D0%B0%D0%B9%D0%BB%D1%96%D0%B2%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22filelistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%A9%D0%BE%D0%B1%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8%20%D1%83%D1%81%D1%96%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B8,%20%D1%81%D0%BA%D0%BE%D0%BF%D1%96%D1%8E%D0%B9%D1%82%D0%B5%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D1%8C%20%D1%96%20%D0%B2%D1%81%D1%82%D0%B0%D0%B2%D1%82%D0%B5%20%D0%B9%D0%BE%D0%B3%D0%BE%20%D1%83%20',%7Ba:%7Bhref:'http://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%B5%D1%80_%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BE%D0%BA',text:'%D0%BC%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%B5%D1%80%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B5%D0%BD%D1%8C'%7D%7D,'.%20%D0%AF%D0%BA%D1%89%D0%BE%20%D1%83%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D0%B2%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B9%20%D0%BC%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%B5%D1%80%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B5%D0%BD%D1%8C,%20%D1%80%D0%B5%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D0%B4%D1%83%D1%94%D0%BC%D0%BE%20%D0%B2%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D0%B8%20',%7Ba:%7Bhref:'http://www.westbyte.com/dm/',text:'Download%20Master'%7D%7D,'.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BB%D0%B5%D0%B9%D0%BB%D1%96%D1%81%D1%82%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22playlistInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%B1%D0%B5%D1%80%D0%B5%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9%20%D0%BF%D0%BB%D0%B5%D0%B9%D0%BB%D1%96%D1%81%D1%82%20%D0%BC%D0%BE%D0%B6%D0%BD%D0%B0%20%D0%B2%D1%96%D0%B4%D0%BA%D1%80%D0%B8%D1%82%D0%B8%20%D1%83%20%D0%BF%D0%BB%D0%B5%D1%94%D1%80%D1%96%20%D0%B4%D0%BB%D1%8F%20%D0%B2%D1%96%D0%B4%D1%82%D0%B2%D0%BE%D1%80%D0%B5%D0%BD%D0%BD%D1%8F.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummySfTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22HD%20%D0%B0%D0%B1%D0%BE%20MP3%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuItem%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bspan:%7B%7D%7D,'%20%D0%B7%20%D0%B4%D0%BE%D0%BC%D0%BE%D0%BC%D0%BE%D0%B3%D0%BE%D1%8E%20Ummy'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyMenuInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B%7Bp:%7Btext:'%D0%92%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D1%96%D1%82%D1%8C%20%D0%B1%D0%B5%D0%B7%D0%BA%D0%BE%D1%88%D1%82%D0%BE%D0%B2%D0%BD%D0%B8%D0%B9%20Ummy%20Video%20Downloader%20%D1%96%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D1%83%D0%B9%D1%82%D0%B5%20%D1%81%D0%B2%D0%BE%D1%97%20%D1%83%D0%BB%D1%8E%D0%B1%D0%BB%D0%B5%D0%BD%D1%96%20%D0%B2%D1%96%D0%B4%D0%B5%D0%BE%20%D0%B2%20HD%20%D0%B0%D0%B1%D0%BE%20%D0%B2%20MP3.'%7D%7D,%7Bp:%7Bclass:'center',append:%5B%7Ba:%7Bclass:'green-btn-2%20arrow',href:'%7Burl%7D',target:'_blank',text:'%D0%A1%D0%9A%D0%90%D0%A7%D0%90%D0%A2%D0%98'%7D%7D%5D%7D%7D,%7Bp:%7Bappend:%5B'%D0%9F%D1%96%D1%81%D0%BB%D1%8F%20%D0%B2%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D1%8F%20%D0%BF%D1%80%D0%B8%20%D0%BA%D0%BB%D1%96%D1%86%D1%96%20%D0%BD%D0%B0%20',%7Bimg:%7Bsrc:'#'%7D%7D,'%20%D0%B7%D0%B0%D0%BA%D0%B0%D1%87%D0%BA%D0%B0%20%D0%B1%D1%83%D0%B4%D0%B5%20%D0%BF%D0%BE%D1%87%D0%B8%D0%BD%D0%B0%D1%82%D0%B8%D1%81%D1%8F%20%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D0%B8%D1%87%D0%BD%D0%BE.'%5D%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%B5%D1%80%D0%B5%D0%B2%D1%96%D1%80%D1%82%D0%B5%20%D0%BD%D0%B0%D0%BB%D0%B0%D1%88%D1%82%D1%83%D0%B2%D0%B0%D0%BD%D0%BD%D1%8F%20%D0%B1%D1%80%D0%B0%D1%83%D0%B7%D0%B5%D1%80%D0%B0%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22warningPopupDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%92%D0%B8%D0%B1%D1%96%D1%80%20%D0%BF%D0%B0%D0%BF%D0%BA%D0%B8%20%D0%BF%D1%80%D0%B8%20%D1%81%D0%BA%D0%B0%D1%87%D1%83%D0%B2%D0%B0%D0%BD%D0%BD%D1%96%20%D0%BF%D0%BE%D0%B2%D0%B8%D0%BD%D0%B5%D0%BD%20%D0%B1%D1%83%D1%82%D0%B8%20%D0%B2%D1%96%D0%B4%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B9.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22readMore%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%94%D0%B5%D1%82%D0%B0%D0%BB%D1%8C%D0%BD%D1%96%D1%88%D0%B5...%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22noWarning%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B5%20%D0%BF%D0%BE%D0%BF%D0%B5%D1%80%D0%B5%D0%B4%D0%B6%D0%B0%D1%82%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22cancel%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BA%D0%B0%D1%81%D1%83%D0%B2%D0%B0%D0%BD%D0%BD%D1%8F%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22continue%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D1%80%D0%BE%D0%B4%D0%BE%D0%B2%D0%B6%D0%B8%D1%82%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22beforeDownloadPopupWarn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A3%D0%B2%D0%B0%D0%B3%D0%B0:%20%D1%81%D0%BA%D0%B0%D1%81%D1%83%D0%B2%D0%B0%D1%82%D0%B8%20%D0%B0%D0%B1%D0%BE%20%D0%BF%D1%80%D0%B8%D0%B7%D1%83%D0%BF%D0%B8%D0%BD%D0%B8%D1%82%D0%B8%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B5%D0%BD%D0%BD%D1%8F%20%D0%B1%D1%83%D0%B4%D0%B5%20%D0%BD%D0%B5%D0%BC%D0%BE%D0%B6%D0%BB%D0%B8%D0%B2%D0%BE.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfo%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkInfoTitle%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A0%D0%BE%D0%B7%D0%BC%D1%96%D1%80%20%D1%84%D0%B0%D0%B9%D0%BB%D1%83%20%D1%96%20%D0%B1%D1%96%D1%82%D1%80%D0%B5%D0%B9%D1%82%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkMp3LinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B5%20%D0%B7%D0%BD%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D0%BE%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D1%8C%20%D0%BD%D0%B0%20MP3-%D1%84%D0%B0%D0%B9%D0%BB%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkPhotoLinksNotFound%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D0%B5%20%D0%B7%D0%BD%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D0%BE%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D1%8C%20%D0%BD%D0%B0%20%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D1%96%D1%97%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadPhotoAlbum%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8%20%D0%B0%D0%BB%D1%8C%D0%B1%D0%BE%D0%BC%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadAllPhotoAlbums%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8%20%D1%83%D1%81%D1%96%20%D0%B0%D0%BB%D1%8C%D0%B1%D0%BE%D0%BC%D0%B8%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%BD%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D0%BE%20%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D1%96%D0%B9%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkNotAvailablePhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%25d%20%D1%84%D0%BE%D1%82%D0%BE%20%D1%82%D0%B8%D0%BC%D1%87%D0%B0%D1%81%D0%BE%D0%B2%D0%BE%20%D0%BD%D0%B5%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%BD%D0%BE%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%BD%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D0%BE%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D1%8C%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundOf%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%B7%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkShowAs%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B8%20%D1%8F%D0%BA%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinks%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D1%8C%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfLinksInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%A9%D0%BE%D0%B1%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8%20%D1%83%D1%81%D1%96%20%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D1%96%D1%97,%20%D1%81%D0%BA%D0%BE%D0%BF%D1%96%D1%8E%D0%B9%D1%82%D0%B5%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D0%BF%D0%BE%D1%81%D0%B8%D0%BB%D0%B0%D0%BD%D1%8C%20%D1%96%20%D0%B2%D1%81%D1%82%D0%B0%D0%B2%D1%82%D0%B5%20%D0%B9%D0%BE%D0%B3%D0%BE%20%D1%83%20',%7Ba:%7Bhref:'http://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%B5%D1%80_%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BE%D0%BA',text:'%D0%BC%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%B5%D1%80%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B5%D0%BD%D1%8C'%7D%7D,'.%20%D0%AF%D0%BA%D1%89%D0%BE%20%D1%83%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D0%B2%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B9%20%D0%BC%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%B5%D1%80%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B5%D0%BD%D1%8C,%20%D1%80%D0%B5%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D0%B4%D1%83%D1%94%D0%BC%D0%BE%20%D0%B2%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D0%B8%20',%7Ba:%7Bhref:'http://www.westbyte.com/dm/',text:'Download%20Master'%7D%7D,'.'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkTableOfThumbnails%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A2%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%8E%20%D0%B5%D1%81%D0%BA%D1%96%D0%B7%D1%96%D0%B2%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotos%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D1%96%D0%B9%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkListOfPhotosInstruction%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A9%D0%BE%D0%B1%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8%20%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D1%96%D1%8E,%20%D0%BD%D0%B0%D1%82%D0%B8%D1%81%D0%BD%D1%96%D1%82%D1%8C%20%D0%BD%D0%B0%20%D0%BD%D0%B5%D1%97%20%D0%BB%D1%96%D0%B2%D0%BE%D1%8E%20%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D0%BE%D1%8E%20%D0%BC%D0%B8%D1%88%D1%96.%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkKbps%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%BA%D0%B1/%D1%81%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%91%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeKByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%BA%D0%91%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeMByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9C%D0%91%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeGByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%93%D0%91%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFileSizeTByte%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A2%D0%91%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkDownloadFromYoutube%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%97%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8:%20%D0%B2%D1%96%D0%B4%D0%BA%D1%80%D0%B8%D0%B9%D1%82%D0%B5%20',%7Ba:%7Bhref:'%7Burl%7D',text:'%D1%81%D1%82%D0%BE%D1%80%D1%96%D0%BD%D0%BA%D1%83%20%D0%B2%D1%96%D0%B4%D0%B5%D0%BE-%D1%80%D0%BE%D0%BB%D0%B8%D0%BA%D0%B0'%7D%7D,'%20%D1%96%20%D0%BD%D0%B0%D1%82%D0%B8%D1%81%D0%BD%D1%96%D1%82%D1%8C%20%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D1%83%20%5C%22%D0%97%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8%5C%22%20%D0%BD%D0%B0%D0%B4%20%D0%BF%D0%BB%D0%B5%D1%94%D1%80%D0%BE%D0%BC'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22vkFoundFiles%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%97%D0%BD%D0%B0%D0%B9%D0%B4%D0%B5%D0%BD%D0%BE%20%D1%84%D0%B0%D0%B9%D0%BB%D1%96%D0%B2:%20%25d%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22shareIn%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%BE%D0%B4%D1%96%D0%BB%D0%B8%D1%82%D0%B8%D1%81%D1%8F%20%D0%B2%20%25w%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22socialDesc%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D1%96%D1%87%D0%BD%D0%B8%D0%BA%20%D0%B4%D0%B0%D1%94%20%D0%B2%D0%B0%D0%BC%20%D0%BC%D0%BE%D0%B6%D0%BB%D0%B8%D0%B2%D1%96%D1%81%D1%82%D1%8C%20%D0%B1%D0%B5%D0%B7%D0%BA%D0%BE%D1%88%D1%82%D0%BE%D0%B2%D0%BD%D0%BE%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D1%83%D0%B2%D0%B0%D1%82%D0%B8%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B8%20%D0%B7%20YouTube.com,%20Facebook.com,%20VK.com%20%D1%82%D0%B0%20%D0%B1%D1%96%D0%BB%D1%8C%D1%88%D0%B5%2040%20%D1%96%D0%BD%D1%88%D0%B8%D1%85%20%D1%81%D0%B0%D0%B9%D1%82%D1%96%D0%B2%20%D0%BB%D0%B8%D1%88%D0%B5%20%D0%BE%D0%B4%D0%BD%D0%B8%D0%BC%20%D0%BA%D0%BB%D1%96%D0%BA%D0%BE%D0%BC%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%94%D0%BE%D0%B1%D1%80%D1%96%20%D0%BD%D0%BE%D0%B2%D0%B8%D0%BD%D0%B8!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%A3%20%D1%82%D0%B5%D0%B1%D0%B5%20%D0%B2%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B9%20SaveFrom.net%20%D0%BF%D0%BE%D0%BC%D1%96%D1%87%D0%BD%D0%B8%D0%BA%20',%7Bimg:%20%7Bsrc:%20'#logo'%7D%7D,%20',%20%D1%96%20%D1%82%D0%B5%D0%BF%D0%B5%D1%80%20%D1%82%D0%B8%20%D0%BC%D0%BE%D0%B6%D0%B5%D1%88%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8%20%D0%B1%D1%83%D0%B4%D1%8C-%D1%8F%D0%BA%D0%B5%20%D0%B2%D1%96%D0%B4%D0%B5%D0%BE%20%D0%B7%20YouTube%20%D0%B2%20%D0%BE%D0%B4%D0%B8%D0%BD%20%D0%BA%D0%BB%D1%96%D0%BA'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS1Arrow%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%9F%D1%80%D0%B0%D0%B3%D0%BD%D0%B5%D1%88%20%D0%B4%D0%BE%D0%B2%D1%96%D0%B4%D0%B0%D1%82%D0%B8%D1%81%D1%8F%20%D1%8F%D0%BA?',%20%7Bbr:%7B%7D%7D,%20'%D0%9D%D0%B0%D1%82%D0%B8%D1%81%D0%BD%D0%B8%20%D1%82%D1%83%D1%82'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS2Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A9%D0%BE%D0%B1%20%D0%B7%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8%20%D0%B2%D1%96%D0%B4%D0%B5%D0%BE,%20%D0%BE%D0%B1%D0%B5%D1%80%D1%96%D1%82%D1%8C%20%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%20%D1%96%20%D0%BD%D0%B0%D1%82%D0%B8%D1%81%D0%BD%D0%B8%20%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D1%83%20%5C%22%D0%97%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0%D0%B6%D0%B8%D1%82%D0%B8%5C%22%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3History%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D0%B5%D1%80%D0%B5%D0%B3%D0%BB%D1%8F%D0%BD%D1%83%D1%82%D1%96%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS3Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%A5%D0%BE%D1%87%D0%B5%D1%88%20%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D0%B8%20%D0%B2%D0%B6%D0%B5%20%D0%BF%D0%B5%D1%80%D0%B5%D0%B3%D0%BB%D1%8F%D0%BD%D1%83%D1%82%D0%B5%20%D0%B2%D1%96%D0%B4%D0%B5%D0%BE?',%20%7Bbr:%7B%7D%7D,%20'%D0%9D%D0%B0%D1%82%D0%B8%D1%81%D0%BA%D0%B0%D0%B9%20%D0%BD%D0%B0%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,%20'%20%D0%BD%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B2%D1%8C%D1%8E%20%D0%B2%20%D0%BF%D0%B5%D1%80%D0%B5%D0%B3%D0%BB%D1%8F%D0%BD%D1%83%D1%82%D0%B8%D1%85%20%D0%B2%D1%96%D0%B4%D0%B5%D0%BE'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS4Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%92%D1%96%D0%B4%D0%B5%D0%BE%20%D0%BD%D0%B5%20%D0%BE%D0%B1%D0%BE%D0%B2%5C%5C'%D1%8F%D0%B7%D0%BA%D0%BE%D0%B2%D0%BE%20%D0%BF%D0%B5%D1%80%D0%B5%D0%B3%D0%BB%D1%8F%D0%B4%D0%B0%D1%82%D0%B8%20%E2%80%94',%20%7Bbr:%7B%7D%7D,%20'%D0%BD%D0%B0%D1%82%D0%B8%D1%81%D0%BA%D0%B0%D0%B9%20%D0%BD%D0%B0%20',%20%7Bimg:%20%7Bsrc:%20'#arrow'%7D%7D,%20',%20%D0%BE%D0%B1%D0%B8%D1%80%D0%B0%D0%B9%20%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%20%D1%96%20%D1%81%D0%BA%D0%B0%D1%87%D1%83%D0%B9.%20%D0%A6%D0%B5%20%D0%B7%D1%80%D1%83%D1%87%D0%BD%D0%BE!'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Title%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9F%D1%80%D0%B8%D1%94%D0%BC%D0%BD%D0%BE%D1%97%20%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B8!%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialS5Main%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%97%D0%B0%D0%BB%D0%B8%D1%88%D0%B8%D0%BB%D0%B8%D1%81%D1%8F%20%D0%BF%D0%B8%D1%82%D0%B0%D0%BD%D0%BD%D1%8F?%20%D0%84%20%D0%BF%D1%80%D0%BE%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D1%96%D1%97?%20%D0%97%D0%B0%D0%B3%D0%BB%D1%8F%D0%BD%D1%8C%D1%82%D0%B5%20%D0%BD%D0%B0%20',%7Ba:%20%7Btext:%20'%D1%81%D1%82%D0%BE%D1%80%D1%96%D0%BD%D0%BA%D1%83%20%D0%BF%D1%96%D0%B4%D1%82%D1%80%D0%B8%D0%BC%D0%BA%D0%B8',%20href:%20'#support'%7D%7D,'%20%D0%B0%D0%B1%D0%BE%20%D0%B2%D1%81%D1%82%D1%83%D0%BF%D0%B0%D0%B9%D1%82%D0%B5%20%D0%B4%D0%BE%20%D0%BD%D0%B0%D1%88%D0%BE%D1%97%20',%20%7Ba:%20%7Btext:%20'%D0%92%D0%9A-%D1%81%D0%BF%D1%96%D0%BB%D1%8C%D0%BD%D0%BE%D1%82%D0%B8',%20href:%20'#vk'%7D%7D%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tutorialTooltipText%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%A9%D0%BE%D0%B1%20',%7Bb:%20%7Btext:%20'%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D0%B8'%7D%7D,',%20%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%20%D0%BA%D0%BB%D1%96%D0%BA%D0%BD%D1%96%D1%82%D1%8C%20%D0%BF%D0%BE%20%D0%BA%D0%BD%D0%BE%D0%BF%D1%86%D1%96'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22ummyTooltipConfirm%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%5B'%D0%92%D0%B8%20%D0%B2%D0%B6%D0%B5%20%D0%B2%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D0%BB%D0%B8',%7Bbr:%7B%7D%7D,%7Bimg:%7B%7D%7D,'%20Ummy%20Video%20Downloader?'%5D%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22yes%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%A2%D0%B0%D0%BA%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22no%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%9D%D1%96%22%0A%20%20%20%20%7D,%0A%20%20%20%20%22tooltipHide%22:%20%7B%0A%20%20%20%20%20%20%20%20%22message%22:%20%22%D0%91%D1%96%D0%BB%D1%8C%D1%88%D0%B5%20%D0%BD%D0%B5%20%D0%BF%D0%BE%D0%BA%D0%B0%D0%B7%D1%83%D0%B2%D0%B0%D1%82%D0%B8%20%D1%86%D0%B5%20%D0%BF%D0%BE%D0%B2%D1%96%D0%B4%D0%BE%D0%BC%D0%BB%D0%B5%D0%BD%D0%BD%D1%8F%22%0A%20%20%20%20%7D%0A%7D";
  var mono = (typeof mono !== 'undefined') ? mono : undefined;

  (function(base, factory) {
    "use strict";
    if (mono && mono.isLoaded) {
      return;
    }

    var _mono = mono;
    var fn = function(addon) {
      return factory(_mono, addon);
    };

    mono = base(fn);
    return;
  }(
    function base(factory) {
      if (['interactive', 'complete'].indexOf(document.readyState) !== -1) {
        return factory();
      }

      if (typeof GM_getValue !== 'undefined') {
        return factory();
      }

      var base = {
        isLoaded: true,
        onReadyStack: [],
        onReady: function() {
          base.onReadyStack.push([this, arguments]);
        },
        loadModuleStack: [],
        loadModule: function() {
          base.loadModuleStack.push([this, arguments]);
        }
      };

      var onLoad = function() {
        document.removeEventListener('DOMContentLoaded', onLoad, false);
        window.removeEventListener('load', onLoad, false);

        mono = factory();

        var item;
        while (item = base.onReadyStack.shift()) {
          mono.onReady.apply(item[0], item[1]);
        }

        while (item = base.loadModuleStack.shift()) {
          mono.loadModule.apply(item[0], item[1]);
        }
      };

      document.addEventListener('DOMContentLoaded', onLoad, false);
      window.addEventListener('load', onLoad, false);

      return base;
    },
    function initMono(_mono, _addon) {

      var browserApi = function() {
        "use strict";
        var emptyFn = function() {};

        var cloneObj = function(msg) {
          var obj = null;
          try {
            obj = JSON.parse(JSON.stringify({
              w: msg
            })).w;
          } catch (e) {
            console.error('CloneObj error!', e);
          }

          return obj;
        };

        /**
         * @param {Function} fn
         * @returns {Function}
         */
        var onceFn = function(fn) {
          return function(msg) {
            if (fn) {
              fn(msg);
              fn = null;
            }
          };
        };

        /**
         * @param {Function} fn
         * @returns {Function}
         */
        var cloneResponse = function(fn) {
          return function(response) {
            fn(cloneObj(response));
          };
        };

        var msgTools = {
          listenerBgList: [],
          listenerList: []
        };

        var api = {
          isGM: true,
          /**
           * @param {*} msg
           * @param {Function} [responseCallback]
           */
          sendMessageToActiveTab: function(msg, responseCallback) {
            var responseFn = !responseCallback ? emptyFn : onceFn(cloneResponse(responseCallback));

            msgTools.listenerList.forEach(function(fn) {
              setTimeout(function() {
                fn(cloneObj(msg), responseFn);
              }, 0);
            });
          },
          /**
           * @param {*} msg
           * @param {Function} [responseCallback]
           */
          sendMessage: function(msg, responseCallback) {
            var responseFn = !responseCallback ? emptyFn : onceFn(cloneResponse(responseCallback));

            var cloneMsg = cloneObj(msg);
            msgTools.listenerBgList.forEach(function(fn) {
              setTimeout(function() {
                fn(cloneMsg, responseFn);
              }, 0);
            });
          },
          onMessage: {
            /**
             * @param {Function} callback
             * @param {Object} [details]
             * @param {Boolean} [details.isBg]
             */
            addListener: function(callback, details) {
              details = details || {};
              var listenerList = null;
              if (details.isBg) {
                listenerList = msgTools.listenerBgList;
              } else {
                listenerList = msgTools.listenerList;
              }

              if (listenerList.indexOf(callback) === -1) {
                listenerList.push(callback);
              }
            },
            /**
             * @param {Function} callback
             * @param {Object} [details]
             * @param {Boolean} [details.isBg]
             */
            removeListener: function(callback, details) {
              details = details || {};
              var listenerList = null;
              if (details.isBg) {
                listenerList = msgTools.listenerBgList;
              } else {
                listenerList = msgTools.listenerList;
              }

              var pos = listenerList.indexOf(callback);
              if (pos !== -1) {
                listenerList.splice(pos, 1);
              }
            }
          }
        };

        if (window.chrome) {
          api.isTM = true;
        } else
        if (/Maxthon\//.test(navigator.userAgent)) {
          api.isVM = true;
        } else {
          api.isGmOnly = true;
        }

        var initGmStorage = function() {
          var readOldItem = function(value) {
            var result = undefined;
            if (value !== undefined && value !== null && value !== 'undefined' && value !== 'isMonoEmptyValue') {
              if (typeof value !== 'object') {
                result = value;
              } else {
                try {
                  result = JSON.parse(JSON.stringify(value));
                } catch (e) {
                  console.error('GM old storage item read error!', e, value);
                }
              }
            }
            return result;
          };

          var jsonRe = /^{(?:"w":.+|)}$/;
          var readItem = function(value) {
            if (value !== 'MonoEmptyValue' && !jsonRe.test(value)) {
              return readOldItem(value);
            }

            var result = undefined;
            if (typeof value === 'string' && value !== 'MonoEmptyValue') {
              try {
                result = JSON.parse(value).w;
              } catch (e) {
                console.error('GM Storage item read error!', e, value);
              }
            }
            return result;
          };

          var writeItem = function(value) {
            return JSON.stringify({
              w: value
            });
          };

          return {
            /**
             * @param {String|[String]|Object|null|undefined} [keys]
             * @param {Function} callback
             */
            get: function(keys, callback) {
              var items = {};
              var defaultItems = {};

              var _keys = [];
              if (keys === undefined || keys === null) {
                _keys = GM_listValues();
              } else
              if (Array.isArray(keys)) {
                _keys = keys;
              } else
              if (typeof keys === 'object') {
                _keys = Object.keys(keys);
                defaultItems = keys;
              } else {
                _keys = [keys];
              }

              _keys.forEach(function(key) {
                var value = readItem(GM_getValue(key, 'MonoEmptyValue'));
                if (value === undefined) {
                  value = defaultItems[key];
                }
                if (value !== undefined) {
                  items[key] = value;
                }
              });

              setTimeout(function() {
                callback(items);
              }, 0);
            },
            /**
             * @param {Object} items
             * @param {Function} [callback]
             */
            set: function(items, callback) {
              Object.keys(items).forEach(function(key) {
                if (items[key] !== undefined) {
                  GM_setValue(key, writeItem(items[key]));
                }
              });

              callback && setTimeout(function() {
                callback();
              }, 0);
            },
            /**
             * @param {String|[String]} [keys]
             * @param {Function} [callback]
             */
            remove: function(keys, callback) {
              var _keys = [];
              if (Array.isArray(keys)) {
                _keys = keys;
              } else {
                _keys = [keys];
              }

              _keys.forEach(function(key) {
                GM_deleteValue(key);
              });

              callback && setTimeout(function() {
                callback();
              }, 0);
            },
            /**
             * @param {Function} [callback]
             */
            clear: function(callback) {
              this.remove(GM_listValues(), callback);
            }
          };
        };

        api.storage = initGmStorage();

        var _navigator = null;
        /**
         * @returns {{language: String, platform: String, userAgent: String}}
         */
        api.getNavigator = function() {
          if (_navigator) {
            return _navigator;
          }

          _navigator = {};
          ['language', 'platform', 'userAgent'].forEach(function(key) {
            _navigator[key] = navigator[key] || '';
          });

          return _navigator;
        };

        (function checkCompatibility() {
          var ua = api.getNavigator().userAgent;
          var m = /Chrome\/(\d+)/.exec(ua);
          if (m) {
            var version = parseInt(m[1]);
            api.isChromeVersion = version;
            if (version < 31) {
              api.noMouseEnter = true;
            }
          }
        })();

        /**
         * @param {string} url
         * @param {boolean} [active]
         */
        api.openTab = function(url, active) {
          active = (active === undefined) ? true : !!active;
          if (typeof GM_openInTab !== 'undefined') {
            return GM_openInTab(url, {
              active: active,
              insert: true
            });
          }
        };

        /**
         * @param {Function} cb
         */
        api.getActiveTabUrl = function(cb) {
          cb(location.href);
        };

        /**
         * @returns {string}
         */
        api.getVersion = function() {
          var version = 'GM_unknown';
          if (typeof GM_info !== 'undefined' && GM_info.script && GM_info.script.version) {
            version = GM_info.script.version;
          }
          return version;
        };

        /**
         * @param {String} locale
         * @param {Function} cb
         */
        api.getLanguage = function(locale, cb) {
          var convert = function(messages) {
            var language = {};
            for (var key in messages) {
              if (messages.hasOwnProperty(key)) {
                language[key] = messages[key].message;
              }
            }
            return language;
          };

          try {
            cb(null, convert(JSON.parse(decodeURI(_languageList[locale]))));
          } catch (e) {
            cb(e);
          }
        };

        api.getLoadedLocale = function() {
          return '';
        };

        return {
          api: api
        };
      };

      var mono = browserApi(_addon).api;
      mono.isLoaded = true;
      mono.onReady = function(cb) {
        return cb();
      };

      //> utils

      /**
       * @param {string} head
       * @returns {Object}
       */
      mono.parseXhrHeader = function(head) {
        head = head.split(/\r?\n/);
        var headers = {};
        head.forEach(function(line) {
          "use strict";
          var sep = line.indexOf(':');
          if (sep === -1) {
            return;
          }
          var key = line.substr(0, sep).trim().toLowerCase();
          var value = line.substr(sep + 1).trim();
          headers[key] = value;
        });
        return headers;
      };

      var webRequest = (function() {
        var prefix = 'sf-';
        var prefixRe = /^sf-\d+_/;
        var filter = {
          urls: ["<all_urls>"],
          types: ["xmlhttprequest"]
        };
        var isListen = false;
        var waitHeaders = {};
        var requestIdObj = {};

        var isEmpty = function(obj) {
          for (var key in obj) {
            return false;
          }
          return true;
        };
        var any = function(details) {
          delete requestIdObj[details.requestId];
          if (isEmpty(waitHeaders) && isEmpty(requestIdObj)) {
            removeListener();
          }
        };
        var beforeSendHeadersListener = function(details) {
          var requestObj = requestIdObj[details.requestId];
          var requestHeaders = details.requestHeaders || [];
          var filtered = [];
          var changes = [];
          var filterResponseHeaders = [];

          if (requestObj) {
            changes = requestObj.changes;
            filtered = requestObj.filtered;
          } else
          if (!isEmpty(waitHeaders)) {
            var name, item;
            for (var i = 0, header; header = requestHeaders[i]; i++) {
              name = header.name;
              if (prefixRe.test(name)) {
                item = waitHeaders[name];
                if (item) {
                  header.name = item.name;
                  header.value = item.value;
                  changes.push(header);
                  filtered.push(item.name.toLowerCase());
                  filtered.push(name.toLowerCase());
                  if (/cookie/i.test(header.name)) {
                    filterResponseHeaders.push('set-cookie');
                  }
                  clearTimeout(item.timer);
                  delete waitHeaders[name];
                }
              }
            }
          }

          if (changes.length) {
            if (!requestObj) {
              requestIdObj[details.requestId] = {
                changes: changes,
                filtered: filtered,
                filterResponseHeaders: filterResponseHeaders
              };
            }

            var result = requestHeaders.filter(function(header) {
              return filtered.indexOf(header.name.toLowerCase()) === -1;
            }).concat(changes);

            return {
              requestHeaders: result
            };
          }
        };
        var headersReceivedListener = function(details) {
          var requestObj = requestIdObj[details.requestId];
          var responseHeaders = details.responseHeaders;
          if (requestObj && responseHeaders) {
            var filterResponseHeaders = requestObj.filterResponseHeaders;

            var result = responseHeaders.filter(function(header) {
              return filterResponseHeaders.indexOf(header.name.toLowerCase()) === -1;
            });

            return {
              responseHeaders: result
            };
          }
        };
        var removeListener = function() {
          if (isListen) {
            isListen = false;
            chrome.webRequest.onBeforeSendHeaders.removeListener(beforeSendHeadersListener, filter, ["blocking", "requestHeaders"]);
            chrome.webRequest.onHeadersReceived.removeListener(headersReceivedListener, filter, ["blocking", "responseHeaders"]);
            chrome.webRequest.onResponseStarted.removeListener(any, filter);
            chrome.webRequest.onErrorOccurred.removeListener(any, filter);

            mono.debug('webRequest', 'rm listener');
          }
        };
        var addListener = function() {
          if (!isListen) {
            isListen = true;
            chrome.webRequest.onBeforeSendHeaders.addListener(beforeSendHeadersListener, filter, ["blocking", "requestHeaders"]);
            chrome.webRequest.onHeadersReceived.addListener(headersReceivedListener, filter, ["blocking", "responseHeaders"]);
            chrome.webRequest.onResponseStarted.addListener(any, filter);
            chrome.webRequest.onErrorOccurred.addListener(any, filter);

            mono.debug('webRequest', 'add listener');
          }
        };
        var permissionRequestLimit = 10;
        var permissionRequested = false;
        var requestPermission = function(cb) {
          if (isAvailable() || permissionRequested) {
            cb(available);
          } else
          if (chrome.permissions && chrome.permissions.request) {
            chrome.permissions.request({
              permissions: ['webRequest', 'webRequestBlocking']
            }, function(grunted) {
              if (grunted || permissionRequestLimit-- <= 0) {
                permissionRequested = true;
              }
              grunted && isAvailable(true);
              cb(available);
            });
          } else {
            permissionRequested = true;
            cb(available);
          }
        };
        var isSupported = function() {
          return mono.isChrome || mono.isFirefox;
        };
        var available = null;
        var isAvailable = function(force) {
          if (available === null || force) {
            available = !!(isSupported() &&
              chrome.webRequest &&
              chrome.webRequest.onBeforeSendHeaders &&
              chrome.webRequest.onResponseStarted &&
              chrome.webRequest.onErrorOccurred
            );
          }
          return available;
        };
        var wrapHeaderKey = function(key, value) {
          if (isAvailable()) {
            var mKey, limit = 100;
            while (limit-- > 0) {
              mKey = prefix + parseInt(Math.random() * 100000) + '_' + key;
              if (!waitHeaders[mKey]) {
                break;
              }
            }
            waitHeaders[mKey] = {
              name: key,
              value: value,
              timer: setTimeout(function() {
                delete waitHeaders[mKey];
              }, 3 * 1000)
            };

            addListener();

            return mKey;
          } else {
            return key;
          }
        };
        var specialHeaderRe = /^user-agent$|^origin$|^cookie$/i;
        var isSpecialHeader = function(key) {
          return specialHeaderRe.test(key);
        };
        return {
          wrapHeaderKey: wrapHeaderKey,
          isSpecialHeader: isSpecialHeader,
          isSupported: isSupported,
          requestPermission: requestPermission
        };
      })();

      mono.getDesktopUa = function() {
        return 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36';
      };

      /**
       * @typedef {Object|string} requestDetails
       * @property {string} url
       * @property {string} [method] GET|POST
       * @property {string} [type] GET|POST
       * @property {string} [data]
       * @property {boolean} [cache]
       * @property {Object} [headers]
       * @property {string} [contentType]
       * @property {boolean} [json]
       * @property {boolean} [xml]
       * @property {number} [timeout]
       * @property {string} [mimeType]
       * @property {boolean} [withCredentials]
       * @property {boolean} [localXHR]
       */
      /**
       * @callback requestResponse
       * @param {string|null} err
       * @param {Object} res
       * @param {string|Object|Array} data
       */
      /**
       * @param {requestDetails} obj
       * @param {requestResponse} [origCb]
       * @returns {{abort: function}}
       */
      mono.request = function(obj, origCb) {
        "use strict";
        var result = {};
        var cb = function(e, body) {
          cb = null;
          if (request.timeoutTimer) {
            clearTimeout(request.timeoutTimer);
          }

          var err = null;
          if (e) {
            err = String(e.message || e) || 'ERROR';
          }
          origCb && origCb(err, getResponse(body), body);
        };

        var getResponse = function(body) {
          var response = {};

          response.statusCode = xhr.status;
          response.statusText = xhr.statusText;

          var headers = null;
          var allHeaders = xhr.getAllResponseHeaders();
          if (typeof allHeaders === 'string') {
            headers = mono.parseXhrHeader(allHeaders);
          }
          response.headers = headers || {};

          response.body = body;

          return response;
        };

        if (typeof obj !== 'object') {
          obj = {
            url: obj
          };
        }

        var url = obj.url;

        var method = obj.method || obj.type || 'GET';
        method = method.toUpperCase();

        var data = obj.data;
        if (typeof data !== "string") {
          data = mono.param(data);
        }

        if (data && method === 'GET') {
          url += (/\?/.test(url) ? '&' : '?') + data;
          data = undefined;
        }

        if (obj.cache === false && ['GET', 'HEAD'].indexOf(method) !== -1) {
          url += (/\?/.test(url) ? '&' : '?') + '_=' + Date.now();
        }

        if (mono.isFirefox && !/^https?:\/\//.test(url)) {
          var linkNode = document.createElement('a');
          linkNode.href = url;
          url = linkNode.href;
          linkNode = null;
        }

        obj.headers = obj.headers || {};

        if (data) {
          obj.headers["Content-Type"] = obj.contentType || obj.headers["Content-Type"] || 'application/x-www-form-urlencoded; charset=UTF-8';
        }

        var request = {};
        request.url = url;
        request.method = method;

        data && (request.data = data);
        obj.json && (request.json = true);
        obj.xml && (request.xml = true);
        obj.timeout && (request.timeout = obj.timeout);
        obj.mimeType && (request.mimeType = obj.mimeType);
        obj.withCredentials && (request.withCredentials = true);
        Object.keys(obj.headers).length && (request.headers = obj.headers);

        if (request.timeout > 0) {
          request.timeoutTimer = setTimeout(function() {
            cb && cb(new Error('ETIMEDOUT'));
            xhr.abort();
          }, request.timeout);
        }

        var xhrSuccessStatus = {
          0: 200,
          1223: 204
        };

        var xhr = mono.request.getTransport(obj.localXHR);
        xhr.open(request.method, request.url, true);

        if (request.mimeType) {
          xhr.overrideMimeType(request.mimeType);
        }
        if (request.withCredentials) {
          xhr.withCredentials = true;
        }

        var specialHeaders = [];
        for (var key in request.headers) {
          if (webRequest.isSpecialHeader(key)) {
            specialHeaders.push({
              key: key,
              value: request.headers[key]
            });
          }
          xhr.setRequestHeader(key, request.headers[key]);
        }

        var readyCallback = xhr.onload = function() {
          var status = xhrSuccessStatus[xhr.status] || xhr.status;
          try {
            if (status >= 200 && status < 300 || status === 304) {
              var body = xhr.responseText;
              if (request.json) {
                body = JSON.parse(body);
              } else
              if (request.xml) {
                body = (new DOMParser()).parseFromString(body, "text/xml");
              } else
              if (typeof body !== 'string') {
                console.error('Response is not string!', body);
                throw new Error('Response is not string!');
              }
              return cb && cb(null, body);
            }
            throw new Error(xhr.status + ' ' + xhr.statusText);
          } catch (e) {
            return cb && cb(e);
          }
        };

        var errorCallback = xhr.onerror = function() {
          cb && cb(new Error(xhr.status + ' ' + xhr.statusText));
        };

        var stateChange = null;
        if (xhr.onabort !== undefined) {
          xhr.onabort = errorCallback;
        } else {
          stateChange = function() {
            if (xhr.readyState === 4) {
              cb && setTimeout(function() {
                return errorCallback();
              });
            }
          };
        }

        if (mono.isSafari && mono.badXhrHeadRedirect && request.method === 'HEAD') {
          stateChange = (function(cb) {
            if (xhr.readyState > 1) {
              // Safari 5 on HEAD 302 redirect fix
              setTimeout(function() {
                xhr.abort();
              });
              return readyCallback();
            }

            return cb && cb();
          }).bind(null, stateChange);
        }

        if (mono.isOpera && mono.badXhrRedirect) {
          stateChange = (function(cb) {
            if (xhr.readyState > 1 && (xhr.status === 302 || xhr.status === 0)) {
              // Opera 12 XHR redirect
              if (!obj._redirectCount) {
                obj._redirectCount = 0;
              }
              var location = xhr.getResponseHeader('Location');
              if (location && obj._redirectCount < 5) {
                obj._redirectCount++;
                var redirectObj = mono.extend({}, obj);
                redirectObj.url = location;

                cb = null;
                xhr.abort();
                var redirectRequest = mono.request(redirectObj, origCb);
                mono.extend(result, redirectRequest);
                return;
              }
            }

            return cb && cb();
          }).bind(null, stateChange);
        }

        if (stateChange) {
          xhr.onreadystatechange = stateChange;
        }

        var next = function() {
          try {
            xhr.send(request.data || null);
          } catch (e) {
            setTimeout(function() {
              cb && cb(e);
            });
          }
        };

        if (specialHeaders.length && webRequest.isSupported()) {
          var setSpecialHeaders = function() {
            for (var i = 0, item; item = specialHeaders[i]; i++) {
              xhr.setRequestHeader(webRequest.wrapHeaderKey(item.key, item.value), item.value);
            }
          };
          webRequest.requestPermission(function(grunted) {
            grunted && setSpecialHeaders();
            cb && next();
          });
        } else {
          next();
        }

        result.abort = function() {
          cb = null;
          xhr.abort();
        };

        return result;
      };

      mono.request.getTransport = function(localXHR) {
        if (mono.isGM && !localXHR) {
          return new mono.request.gmTransport();
        }

        return new XMLHttpRequest();
      };

      mono.request.gmTransport = function() {
        "use strict";
        var _this = this;
        var gmXhr = null;

        var sync = function(type, gmResponse) {
          _this.readyState = gmResponse.readyState;
          _this.status = gmResponse.status;
          _this.statusText = gmResponse.statusText;
          if (typeof gmResponse.response === 'string') {
            _this.responseText = gmResponse.response;
          }
          if (gmResponse.responseText) {
            _this.responseText = gmResponse.responseText;
          }
          _this._responseHeaders = gmResponse.responseHeaders;

          _this.onreadystatechange && _this.onreadystatechange();

          _this[type] && _this[type]();
        };

        var gmDetails = {
          headers: {},
          responseType: 'text',
          onload: sync.bind(null, 'onload'),
          onerror: sync.bind(null, 'onerror'),
          onabort: sync.bind(null, 'onabort'),
          ontimeout: sync.bind(null, 'ontimeout')
        };

        this._responseHeaders = '';
        this.readyState = 0;
        this.status = 0;
        this.statusText = '';
        this.responseText = '';
        this.response = '';
        this.responseType = '';
        this.responseURL = '';
        this.open = function(method, url) {
          gmDetails.method = method;
          gmDetails.url = url;
        };
        this.overrideMimeType = function(mimeType) {
          gmDetails.overrideMimeType = mimeType;
        };
        this.setRequestHeader = function(key, value) {
          if (key.toLowerCase() === 'cookie' && value === '') {
            gmDetails.anonymous = true;
          }
          gmDetails.headers[key] = value;
        };
        this.getResponseHeader = function(name) {
          if (!this._responseHeaders) {
            return null;
          }

          name = name.toLowerCase();
          if (!this.headers) {
            this.headers = mono.parseXhrHeader(this._responseHeaders);
          }
          if (!this.headers.hasOwnProperty(name)) {
            return null;
          }
          return this.headers[name];
        };
        this.getAllResponseHeaders = function() {
          return this._responseHeaders;
        };
        this.abort = function() {
          gmXhr && gmXhr.abort();
        };
        this.send = function(data) {
          gmDetails.data = data;
          gmXhr = GM_xmlhttpRequest(gmDetails);
        };
        this.onabort = null;
        this.onerror = null;
        this.onload = null;
        this.onreadystatechange = null;
        this.ontimeout = null;
      };

      mono.extend = function() {
        var obj = arguments[0];
        for (var i = 1, len = arguments.length; i < len; i++) {
          var item = arguments[i];
          for (var key in item) {
            if (item[key] !== undefined) {
              obj[key] = item[key];
            }
          }
        }
        return obj;
      };

      mono.extendPos = function() {
        var obj = arguments[0];
        for (var i = 1, len = arguments.length; i < len; i++) {
          var item = arguments[i];
          for (var key in item) {
            if (item[key] !== undefined) {
              delete obj[key];
              obj[key] = item[key];
            }
          }
        }
        return obj;
      };

      mono.param = function(obj) {
        if (typeof obj === 'string') {
          return obj;
        }
        var itemsList = [];
        for (var key in obj) {
          if (!obj.hasOwnProperty(key)) {
            continue;
          }
          if (obj[key] === undefined || obj[key] === null) {
            obj[key] = '';
          }
          itemsList.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
        }
        return itemsList.join('&');
      };

      mono.capitalize = function(word) {
        "use strict";
        return word.charAt(0).toUpperCase() + word.substr(1);
      };

      /**
       * @param {string|Element|DocumentFragment} tagName
       * @param {Object} obj
       * @returns {Element|DocumentFragment}
       */
      mono.create = function(tagName, obj) {
        "use strict";
        var el;
        var func;
        if (typeof tagName !== 'object') {
          el = document.createElement(tagName);
        } else {
          el = tagName;
        }
        for (var attr in obj) {
          var value = obj[attr];
          if (func = mono.create.hook[attr]) {
            func(el, value);
            continue;
          }
          el[attr] = value;
        }
        return el;
      };
      mono.create.hook = {
        text: function(el, value) {
          "use strict";
          el.textContent = value;
        },
        data: function(el, value) {
          "use strict";
          for (var item in value) {
            el.dataset[item] = value[item];
          }
        },
        class: function(el, value) {
          "use strict";
          if (Array.isArray(value)) {
            for (var i = 0, len = value.length; i < len; i++) {
              el.classList.add(value[i]);
            }
          } else {
            el.setAttribute('class', value);
          }
        },
        style: function(el, value) {
          "use strict";
          if (typeof value === 'object') {
            for (var item in value) {
              var key = item;
              if (key === 'float') {
                key = 'cssFloat';
              }
              var _value = value[item];
              if (Array.isArray(_value)) {
                for (var i = 0, len = _value.length; i < len; i++) {
                  el.style[key] = _value[i];
                }
              } else {
                el.style[key] = _value;
              }
            }
          } else {
            el.setAttribute('style', value);
          }
        },
        append: function(el, value) {
          "use strict";
          if (!Array.isArray(value)) {
            value = [value];
          }
          for (var i = 0, len = value.length; i < len; i++) {
            var node = value[i];
            if (!node && node !== 0) {
              continue;
            }
            if (typeof node !== 'object') {
              node = document.createTextNode(node);
            }
            el.appendChild(node);
          }
        },
        on: function(el, eventList) {
          "use strict";
          if (typeof eventList[0] !== 'object') {
            eventList = [eventList];
          }
          for (var i = 0, len = eventList.length; i < len; i++) {
            var args = eventList[i];
            if (!Array.isArray(args)) {
              continue;
            }
            mono.on.apply(mono, [el].concat(args));
          }
        },
        one: function(el, eventList) {
          "use strict";
          if (typeof eventList[0] !== 'object') {
            eventList = [eventList];
          }
          for (var i = 0, len = eventList.length; i < len; i++) {
            var args = eventList[i];
            if (!Array.isArray(args)) {
              continue;
            }
            mono.one.apply(mono, [el].concat(args));
          }
        },
        onCreate: function(el, value) {
          "use strict";
          value.call(el, el);
        },
        attr: function(el, attrObj) {
          var prop, value;
          for (prop in attrObj) {
            value = attrObj[prop];
            el.setAttribute(prop, value);
          }
        }
      };

      mono.parseTemplate = function(list, details) {
        details = details || {};

        if (typeof list === "string") {
          if (list[0] !== '[') {
            return document.createTextNode(list);
          }
          try {
            list = list.replace(/"/g, '\\u0022').replace(/\\'/g, '\\u0027').replace(/'/g, '"').replace(/([{,])\s*([a-zA-Z0-9]+):/g, '$1"$2":');
            list = JSON.parse(list);
          } catch (e) {
            return document.createTextNode(list);
          }
        }
        if (!Array.isArray(list)) {
          return document.createTextNode(list);
        }
        var fragment = details.fragment || document.createDocumentFragment();
        for (var i = 0, len = list.length; i < len; i++) {
          var item = list[i];
          if (typeof item === 'object') {
            for (var tagName in item) {
              var el = item[tagName];
              var append = el.append;
              delete el.append;
              var dEl;
              fragment.appendChild(dEl = mono.create(tagName, el));
              if (append !== undefined) {
                mono.parseTemplate(append, {
                  fragment: dEl
                });
              }
            }
          } else {
            fragment.appendChild(document.createTextNode(item));
          }
        }
        return fragment;
      };

      mono.trigger = function(el, type, data) {
        if (data === undefined) {
          data = {};
        }
        if (data.bubbles === undefined) {
          data.bubbles = false;
        }
        if (data.cancelable === undefined) {
          data.cancelable = false;
        }
        var event = null;
        if (typeof MouseEvent === 'function' &&
          ['click'].indexOf(type) !== -1) {
          event = new MouseEvent(type, data);
        } else {
          event = new CustomEvent(type, data);
        }
        el.dispatchEvent(event);
      };

      mono.urlPatternToStrRe = function(value) {
        "use strict";
        if (value === '<all_urls>') {
          return '^https?:\\/\\/.+$';
        }

        var m = value.match(/(\*|http|https|file|ftp):\/\/([^\/]+)(?:\/(.*))?/);
        if (!m) {
          throw new Error("Invalid url-pattern");
        }

        var scheme = m[1];
        if (scheme === '*') {
          scheme = 'https?';
        }

        var host = m[2];
        if (host === '*') {
          host = '.+';
        } else {
          host = mono.escapeRegex(host);
          host = host.replace(/^\\\*\\\./, '(?:[^\/]+\\.)?');
          host = host.replace(/\\\.\\\*$/g, '\\.[a-z\\.]{2,}');
        }

        var pattern = ['^', scheme, ':\\/\\/', host];

        var path = m[3];
        if (!path) {
          pattern.push('$');
        } else
        if (path === '*') {
          path = '(?:|\/.*)';
          pattern.push(path);
          pattern.push('$');
        } else
        if (path) {
          path = '\/' + path;
          path = mono.escapeRegex(path);
          path = path.replace(/\\\*/g, '.*');
          pattern.push(path);
          pattern.push('$');
        }

        return pattern.join('');
      };

      mono.isIframe = function() {
        return window.top !== window.self;
      };

      mono.userJsCheck = function() {
        "use strict";
        if (mono.isGM) {
          return;
        }

        if (!mono.hasPageScript()) {
          return;
        }

        try {
          if (window.sessionStorage['savefrom-helper-userjs'] === '1') {
            mono.sendMessage({
              action: 'userjsDetected'
            });
          }
        } catch (e) {}
      };

      mono.hasPageScript = function() {
        "use strict";
        var moduleLoadedList = mono.loadModule.moduleLoadedList;
        return moduleLoadedList.some(function(moduleName) {
          if (['sovetnik', 'aviaBar', 'fsStat', 'swStat'].indexOf(moduleName) === -1) {
            return true;
          }
        });
      };

      mono.setExtensionSession = function() {
        "use strict";
        try {
          if (!mono.hasPageScript()) {
            delete window.sessionStorage['savefrom-helper-extension'];
          } else {
            window.sessionStorage['savefrom-helper-extension'] = '1';
          }
        } catch (e) {}
      };

      mono.loadModule = (function() {
        var moduleNameList = [];
        var moduleList = [];
        var loadedModuleList = [];

        var moduleLoad = function(data) {
          var hasActiveModule = false;

          var item, availFn, isAvailable, moduleName, fn;
          while (item = moduleList.shift()) {
            moduleName = item[0];
            fn = item[1];
            availFn = item[2];

            isAvailable = !availFn;
            try {
              !isAvailable && (isAvailable = availFn(data));
            } catch (e) {
              mono.error('Module available error!', e);
            }

            if (isAvailable) {
              loadedModuleList.push(moduleName);
              hasActiveModule = true;
              try {
                mono.debug('run module', moduleName, data);
                fn(moduleName, data);
              } catch (e) {
                mono.error('Module error!', e);
              }
            } else {
              mono.debug('unavailable', moduleName, data);
            }
          }

          if (hasActiveModule && !mono.isGM) {
            mono.setExtensionSession();
            mono.userJsCheck();
          }
        };

        var requestData = function() {
          "use strict";
          var limit = 20;

          var onceResponse = mono.onceFn(function(data) {
            getData = null;

            mono.global.language = data.getLanguage;
            mono.global.preference = data.getPreference;

            return moduleLoad(data);
          });

          var getData = function() {
            setTimeout(function() {
              limit--;
              if (limit < 0 || mono.isGM) {
                getData = null;
              }
              getData && getData();
            }, 250);

            mono.sendMessage({
              action: 'getLanguageAndPreference'
            }, onceResponse);
          };
          getData();
        };

        var loader = function(moduleName, cb, isAsyncAvailable, syncIsAvailable) {
          if (moduleNameList.indexOf(moduleName) === -1) {
            moduleNameList.push(moduleName);

            var isAvailable = !syncIsAvailable;
            try {
              !isAvailable && (isAvailable = syncIsAvailable());
            } catch (e) {
              mono.error('Module available error!', e);
            }

            if (isAvailable) {
              moduleList.push(arguments);
              if (moduleList.length === 1) {
                requestData();
              }
            } else {
              mono.debug('sync unavailable', moduleName);
            }
          } else {
            mono.debug('Module exists', moduleName);
          }
        };

        loader.moduleLoadedList = loadedModuleList;
        loader.moduleList = moduleList;

        return loader;
      })();

      /**
       * @param {Element} parent
       * @param {Element} target
       * @return {boolean}
       */
      mono.contains = function(parent, target) {
        var rnative = /^[^{]+\{\s*\[native \w/;
        if (rnative.test(document.compareDocumentPosition) || rnative.test(document.contains)) {
          mono.contains = function(a, b) {
            // from Sizzle
            var adown = a.nodeType === 9 ? a.documentElement : a,
              bup = b && b.parentNode;
            return a === bup || !!(bup && bup.nodeType === 1 && (
              adown.contains ?
              adown.contains(bup) :
              a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16
            ));
          };
        } else {
          mono.contains = function(a, b) {
            if (b) {
              while (b = b.parentNode) {
                if (b === a) {
                  return true;
                }
              }
            }
            return false;
          };
        }
        return mono.contains.apply(this, arguments);
      };
      (function() {
        "use strict";
        var getTwoElParent = function(a, b, parentList) {
          parentList.unshift(b);
          while (b = b.parentNode) {
            if (mono.contains(b, a)) {
              return b;
            }
            parentList.unshift(b);
          }
          return null;
        };
        var wrapEvent = function(origType, fixType, origEvent, capture) {
          return !capture ? function(event) {
            var related = event.relatedTarget;
            var target = this;
            if (!related || (related !== target && !mono.contains(target, related))) {
              origEvent.call(this, {
                type: origType,
                target: target,
                preventDefault: event.preventDefault,
                stopPropagation: event.stopPropagation
              });
            }
          } : function(event) {
            var related = event.relatedTarget;
            var target = event.target;
            var parentList = [];
            if (!related || mono.contains(related, target) || (related = getTwoElParent(related, target, parentList))) {
              if (parentList.length === 0) {
                while (target !== related) {
                  parentList.unshift(target);
                  target = target.parentNode;
                }
              }
              while (target = parentList.shift()) {
                origEvent.call(this, {
                  type: origType,
                  target: target,
                  preventDefault: event.preventDefault,
                  stopPropagation: event.stopPropagation
                });
              }
            }
          };
        };

        var functionMap = {
          key: 'fixEvent-',
          eventId: 0,
          replaceList: {},
          bindCount: {}
        };

        /**
         * @param {Node} el
         * @param {String} type
         * @param {Function} onEvent
         * @param {Boolean} [capture]
         */
        mono.on = function(el, type, onEvent, capture) {
          if (mono.noMouseEnter && ['mouseenter', 'mouseleave'].indexOf(type) !== -1) {
            var cacheEventKey = functionMap.key;
            var origEvent = onEvent;
            var origType = type;
            var origCapture = capture;

            if (type === 'mouseenter') {
              type = 'mouseover';
            } else
            if (type === 'mouseleave') {
              type = 'mouseout';
            }
            cacheEventKey += type;
            if (capture) {
              cacheEventKey += '-1';
              capture = false;
            }

            var eventId = origEvent[cacheEventKey];
            if (eventId === undefined) {
              eventId = functionMap.eventId++;
              origEvent[cacheEventKey] = eventId;

              onEvent = wrapEvent(origType, type, origEvent, origCapture);

              functionMap.replaceList[eventId] = onEvent;

              if (functionMap.bindCount[eventId] === undefined) {
                functionMap.bindCount[eventId] = 0;
              }
            } else {
              onEvent = functionMap.replaceList[eventId];
            }

            functionMap.bindCount[eventId]++;
          }

          el.addEventListener(type, onEvent, capture);
        };

        /**
         * @param {Node} el
         * @param {String} type
         * @param {Function} onEvent
         * @param {Boolean} [capture]
         */
        mono.off = function(el, type, onEvent, capture) {
          if (mono.noMouseEnter && ['mouseenter', 'mouseleave'].indexOf(type) !== -1) {
            var cacheEventKey = functionMap.key;
            if (type === 'mouseenter') {
              type = 'mouseover';
            } else
            if (type === 'mouseleave') {
              type = 'mouseout';
            }
            cacheEventKey += type;
            if (capture) {
              cacheEventKey += '-1';
              capture = false;
            }

            var eventId = onEvent[cacheEventKey];
            if (eventId !== undefined) {
              var origEvent = onEvent;
              onEvent = functionMap.replaceList[eventId];
              functionMap.bindCount[eventId]--;

              if (functionMap.bindCount[eventId] === 0) {
                delete origEvent[cacheEventKey];
                delete functionMap.replaceList[eventId];
                delete functionMap.bindCount[eventId];
              }
            }
          }

          el.removeEventListener(type, onEvent, capture);
        };

        /**
         * @param {Node} el
         * @param {String} type
         * @param {Function} onEvent
         * @param {Boolean} [capture]
         */
        mono.one = function(el, type, onEvent, capture) {
          var fnName = ['oneFn', type, !!capture].join('_');
          var fn = onEvent[fnName];
          if (!fn) {
            onEvent[fnName] = fn = function(e) {
              mono.off(this, type, fn, capture);
              onEvent.apply(this, arguments);
            }
          }
          mono.on(el, type, fn, capture);
          fnName = null;
          el = null;
        };
      }());

      mono.global = {};

      mono.initGlobal = function(cb) {
        if (!mono.isGM && mono.global.language && mono.global.preference) {
          return cb({
            getLanguage: mono.global.language,
            getPreference: mono.global.preference
          });
        }
        mono.sendMessage({
          action: 'getLanguageAndPreference'
        }, function(response) {
          mono.global.language = response.getLanguage;
          mono.global.preference = response.getPreference;
          cb(response);
        });
      };

      mono.getParentByClass = function(el, classList) {
        if (!Array.isArray(classList)) {
          classList = [classList];
        }

        for (var parent = el; parent; parent = parent.parentNode) {
          if (parent.nodeType !== 1) {
            return null;
          }
          for (var i = 0, className; className = classList[i]; i++) {
            if (parent.classList.contains(className)) {
              return parent;
            }
          }
        }

        return null;
      };

      /**
       * @param {string} url
       * @param {Object} [details]
       * @param {boolean} [details.params] Input params only [false]
       * @param {string} [details.sep] Separator [&]
       * @param {boolean} [details.noDecode] Disable decode keys [false]
       * @returns {{}}
       */
      mono.parseUrl = function(url, details) {
        details = details || {};
        var query = null;
        if (!details.params && /\?/.test(url)) {
          query = url.match(/[^?]*\?(.*)/)[1];
        } else {
          query = url;
        }
        var separator = details.sep || '&';
        var dblParamList = query.split(separator);
        var params = {};
        for (var i = 0, len = dblParamList.length; i < len; i++) {
          var item = dblParamList[i];
          var keyValue = item.split('=');
          var key = keyValue[0];
          var value = keyValue[1] || '';
          if (!details.noDecode) {
            try {
              key = decodeURIComponent(key);
            } catch (err) {
              key = unescape(key);
            }
            try {
              params[key] = decodeURIComponent(value);
            } catch (err) {
              params[key] = unescape(value);
            }
          } else {
            params[key] = value;
          }
        }
        return params;
      };

      mono.throttle = function(fn, threshhold, scope) {
        threshhold = threshhold || 250;
        var last;
        var deferTimer;
        return function() {
          var context = scope || this;

          var now = Date.now();
          var args = arguments;
          if (last && now < last + threshhold) {
            // hold on to it
            clearTimeout(deferTimer);
            deferTimer = setTimeout(function() {
              last = now;
              fn.apply(context, args);
            }, threshhold);
          } else {
            last = now;
            fn.apply(context, args);
          }
        };
      };

      mono.debounce = function(fn, delay) {
        var timer = null;
        return function() {
          var context = this,
            args = arguments;
          clearTimeout(timer);
          timer = setTimeout(function() {
            fn.apply(context, args);
          }, delay);
        };
      };

      mono.getDomain = function(url, strip) {
        var m = /:\/\/(?:[^\/?#]*@)?([^:\/?#]+)/.exec(url);
        m = m && m[1];
        if (m) {
          if (strip) {
            m = m.replace(/^www\./, '');
          }
        }
        return m;
      };

      // legacy

      mono.getQueryString = function(query, key_prefix, key_suffix) {
        if (!query || typeof(query) != 'object')
          return '';

        if (key_prefix === undefined)
          key_prefix = '';

        if (key_suffix === undefined)
          key_suffix = '';

        var str = '';
        for (var key in query) {
          if (str.length)
            str += '&';

          if (query[key] instanceof Object) {
            if (!key_prefix)
              key_prefix = '';

            if (!key_suffix)
              key_suffix = '';

            str += mono.getQueryString(query[key], key_prefix + key + "[", "]" + key_suffix);
          } else
            str += key_prefix + escape(key) + key_suffix + '=' + escape(query[key]);
        }

        return str;
      };

      /**
       * @param {string} text
       * @returns {string}
       */
      mono.decodeUnicodeEscapeSequence = function(text) {
        try {
          return JSON.parse(JSON.stringify(text)
            .replace(mono.decodeUnicodeEscapeSequence.re, '$1'));
        } catch (e) {
          return text;
        }
      };
      mono.decodeUnicodeEscapeSequence.re = /\\(\\u[0-9a-f]{4})/g;

      mono.fileName = {
        maxLength: 80,

        rtrim: /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,

        illegalRe: /[\/?<>\\:*|"~\u202B]/g,

        controlRe: /[\x00-\x1f\x80-\x9f]/g,

        reservedRe: /^\.+/,

        trim: function(text) {
          return text.replace(this.rtrim, '');
        },

        partsRe: /^(.+)\.([a-z0-9]{1,4})$/i,

        getParts: function(name) {
          return name.match(this.partsRe);
        },

        specialChars: ('nbsp,iexcl,cent,pound,curren,yen,brvbar,sect,uml,copy,ordf,laquo,not,shy,reg,macr,deg,plusmn,sup2' +
          ',sup3,acute,micro,para,middot,cedil,sup1,ordm,raquo,frac14,frac12,frac34,iquest,Agrave,Aacute,Acirc,Atilde,Auml' +
          ',Aring,AElig,Ccedil,Egrave,Eacute,Ecirc,Euml,Igrave,Iacute,Icirc,Iuml,ETH,Ntilde,Ograve,Oacute,Ocirc,Otilde,Ouml' +
          ',times,Oslash,Ugrave,Uacute,Ucirc,Uuml,Yacute,THORN,szlig,agrave,aacute,acirc,atilde,auml,aring,aelig,ccedil' +
          ',egrave,eacute,ecirc,euml,igrave,iacute,icirc,iuml,eth,ntilde,ograve,oacute,ocirc,otilde,ouml,divide,oslash' +
          ',ugrave,uacute,ucirc,uuml,yacute,thorn,yuml').split(','),
        specialCharsList: [
          ['amp', 'quot', 'lt', 'gt'],
          [38, 34, 60, 62]
        ],

        specialCharsRe: /&([^;]{2,6});/g,

        /**
         * @param {string} text
         * @returns {string}
         */
        decodeSpecialChars: function(text) {
          var _this = this;
          return text.replace(this.specialCharsRe, function(text, word) {
            var code = null;
            if (word[0] === '#') {
              code = parseInt(word.substr(1));
              if (isNaN(code)) {
                return '';
              }
              return String.fromCharCode(code);
            }

            var pos = _this.specialCharsList[0].indexOf(word);
            if (pos !== -1) {
              code = _this.specialCharsList[1][pos];
              return String.fromCharCode(code);
            }

            pos = _this.specialChars.indexOf(word);
            if (pos !== -1) {
              code = pos + 160;
              return String.fromCharCode(code);
            }

            return '';
          });
        },

        decodeHexChars: function(text) {
          return text.replace(/(\\x[a-zA-Z0-9]{2})/g, function(text, word) {
            var char = word;
            try {
              char = String.fromCharCode(parseInt('0x' + char.substr(2), 16));
            } catch (e) {}
            return char;
          });
        },

        rnRe: /\r?\n/g,

        re1: /[*?"]/g,

        re2: /</g,

        re3: />/g,

        spaceRe: /[\s\t\uFEFF\xA0]+/g,

        dblRe: /(\.|!|\?|_|,|-|:|\+){2,}/g,

        re4: /[.,:;\/\-_+=']$/g,

        /**
         * @param {string} name
         * @returns {string}
         */
        modify: function(name) {
          if (!name) {
            return '';
          }

          name = mono.decodeUnicodeEscapeSequence(name);

          try {
            name = decodeURIComponent(name);
          } catch (err) {
            name = unescape(name);
          }

          name = this.decodeSpecialChars(name);

          name = name.replace(this.rnRe, ' ');

          name = this.trim(name);

          name = name.replace(this.re1, '')
            .replace(this.re2, '(')
            .replace(this.re3, ')')
            .replace(this.spaceRe, ' ')
            .replace(this.dblRe, '$1')
            .replace(this.illegalRe, '_')
            .replace(this.controlRe, '')
            .replace(this.reservedRe, '')
            .replace(this.re4, '');

          if (name.length > this.maxLength) {
            var parts = this.getParts(name);
            if (parts && parts.length == 3) {
              parts[1] = parts[1].substr(0, this.maxLength);
              name = parts[1] + '.' + parts[2];
            }
          }

          return this.trim(name);
        }
      };
      /**
       * @param {number} min
       * @param {number} max
       * @returns {number}
       */
      mono.getRandomInt = function(min, max) {
        return Math.floor(Math.random() * (max - min)) + min;
      };
      /**
       * @param {string} dataName
       * @returns {string}
       */
      mono.dataAttr2Selector = function(dataName) {
        return 'data-' + dataName.replace(/[A-Z]/g, function(lit) {
          return '-' + lit.toLowerCase();
        });
      };
      /**
       * @param {Object} obj
       * @returns {boolean}
       */
      mono.isEmptyObject = function(obj) {
        for (var item in obj) {
          return false;
        }
        return true;
      };

      /**
       * @param {function} cb
       */
      mono.asyncCall = function(cb) {
        "use strict";
        setTimeout(function() {
          cb();
        }, 0);
      };

      /**
       * @param {Function} cb
       * @param {Object} [scope]
       * @returns {Function}
       */
      mono.asyncFn = function(cb, scope) {
        return function() {
          var context = scope || this;
          var args = arguments;
          setTimeout(function() {
            cb.apply(context, args);
          }, 0);
        };
      };

      /**
       * @param {Function} cb
       * @param {Object} [scope]
       * @returns {Function}
       */
      mono.onceFn = function(cb, scope) {
        return function() {
          if (cb) {
            var context = scope || this;
            cb.apply(context, arguments);
            cb = null;
          }
        };
      };

      /**
       * @param {Function} fn
       * @param {Number} [timeout]
       * @param {Function} alwaysCb
       * @param {Object} [scope]
       * @param {Function} [onTimeout]
       */
      mono.safeFn = function(fn, timeout, alwaysCb, scope, onTimeout) {
        if (typeof timeout === 'function') {
          onTimeout = scope;
          scope = alwaysCb;
          alwaysCb = timeout;
          timeout = 3000;
        }
        if (typeof scope === 'function') {
          onTimeout = scope;
          scope = null;
        }
        var timeoutId = null;
        var onceCb = mono.onceFn(function() {
          clearTimeout(timeoutId);
          alwaysCb.apply(this, arguments);
        });

        return function() {
          var context = scope || this;
          var args = [].slice.call(arguments);

          var pos = args.indexOf(alwaysCb);
          if (pos !== -1) {
            args.splice(pos, 1, onceCb);
          }

          setTimeout(function() {
            timeoutId = setTimeout(function() {
              onceCb();
              onTimeout && onTimeout();
            }, timeout);
            fn.apply(context, args);
          }, 0);
        };
      };

      /**
       * @param {string} html
       * @param {RegExp|RegExp[]} match
       * @returns {string[]}
       */
      mono.getPageScript = function(html, match) {
        "use strict";
        if (match && !Array.isArray(match)) {
          match = [match];
        }
        var scriptList = [];
        html.replace(/<script(?:\s*|\s[^>]+[^\/])>/g, function(text, offset) {
          offset += text.length;
          var endPos = html.indexOf('<\/script>', offset);
          if (endPos !== -1) {
            var content = html.substr(offset, endPos - offset);
            if (match) {
              match.every(function(r) {
                return r.test(content);
              }) && scriptList.push(content);
            } else {
              scriptList.push(content);
            }
          }
        });
        return scriptList;
      };

      mono.findJsObject = function(code) {
        "use strict";
        var readString = function(code) {
          var char = code[0],
            pos = 0;
          while (true) {
            pos = code.indexOf(char, pos + 1);
            if (pos === -1) {
              pos = code.length;
              break;
            }
            if (code[pos - 1] !== '\\') {
              break;
            }
          }
          var str = '';
          try {
            if (char === '"') {
              str = JSON.parse('"' + code.substr(1, pos - 1) + '"');
            } else {
              str = JSON.parse('"' + code.substr(1, pos - 1).replace(/\\'/g, '\'').replace(/"/g, '\\"') + '"');
            }
          } catch (e) {}
          return {
            data: str,
            i: pos
          };
        };
        var readObject = function(code) {
          var items = [],
            item = ['', ''],
            index = 0,
            result, readerFn;
          for (var i = 1, symbol; symbol = code[i]; i++) {
            readerFn = symbolReader[symbol];
            if (readerFn) {
              result = readerFn(code.substr(i));
              item[index] = index === 0 ? result.data : JSON.stringify(result.data);
              i += result.i;
            } else
            if (symbol === '}') {
              break;
            } else
            if (symbol === ':') {
              index = 1;
            } else
            if (symbol === ',') {
              items.push(JSON.stringify(item[0]) + ':' + item[1]);
              item = ['', ''];
              index = 0;
            } else {
              item[index] = (item[index] + symbol).trim();
            }
          }
          if (item[1]) {
            items.push(JSON.stringify(item[0]) + ':' + item[1]);
          }

          try {
            var jsonObject = JSON.parse('{' + items.join(',') + '}');
          } catch (e) {}

          return {
            data: jsonObject || {},
            i: i
          };
        };
        var readArray = function(code) {
          var items = [],
            item = '',
            result, readerFn;
          for (var i = 1, symbol; symbol = code[i]; i++) {
            readerFn = symbolReader[symbol];
            if (readerFn) {
              result = readerFn(code.substr(i));
              item = JSON.stringify(result.data);
              i += result.i;
            } else
            if (symbol === ']') {
              break;
            } else
            if (symbol === ',') {
              item && items.push(item);
              item = '';
            } else {
              item += symbol;
            }
          }
          item && items.push(item);

          try {
            var jsonArray = JSON.parse('[' + items.join(',') + ']');
          } catch (e) {}

          return {
            data: jsonArray || [],
            i: i
          };
        };
        var readCode = function(code, matchFn) {
          var result;
          for (var i = 0, symbol; symbol = code[i]; i++) {
            if (symbol === '[' || symbol === '{') {
              result = symbolReader[symbol](code.substr(i));
              i += result.i;
              if (matchFn(result.data)) {
                return true;
              }
            }
          }
        };
        var symbolReader = {
          '[': readArray,
          '{': readObject,
          '"': readString,
          '\'': readString
        };
        return {
          some: function(matchFn) {
            return readCode(code, matchFn);
          }
        };
      };

      /**
       * @param {string} html
       * @param {RegExp|RegExp[]} match
       * @returns {Object[]}
       */
      mono.findJson = function(html, match) {
        "use strict";
        if (match && !Array.isArray(match)) {
          match = [match];
        }
        var rawJson = [];
        var obj = {
          '{': 0,
          '[': 0
        };
        var map = {
          '}': '{',
          ']': '['
        };
        var jsonSymbols = /[{}\]\[":0-9.,-]/;
        var whiteSpace = /[\r\n\s\t]/;
        var jsonText = '';
        for (var i = 0, symbol; symbol = html[i]; i++) {
          if (symbol === '"') {
            var end = i;
            while (end !== -1 && (end === i || html[end - 1] === '\\')) {
              end = html.indexOf('"', end + 1);
            }
            if (end === -1) {
              end = html.length - 1;
            }
            jsonText += html.substr(i, end - i + 1);
            i = end;
            continue;
          }

          if (!jsonSymbols.test(symbol)) {
            if (symbol === 't' && html.substr(i, 4) === 'true') {
              jsonText += 'true';
              i += 3;
            } else
            if (symbol === 'f' && html.substr(i, 5) === 'false') {
              jsonText += 'false';
              i += 4;
            } else
            if (symbol === 'n' && html.substr(i, 4) === 'null') {
              jsonText += 'null';
              i += 3;
            } else
            if (!whiteSpace.test(symbol)) {
              obj['{'] = 0;
              obj['['] = 0;
              jsonText = '';
            }
            continue;
          }

          jsonText += symbol;

          if (symbol === '{' || symbol === '[') {
            if (!obj['{'] && !obj['[']) {
              jsonText = symbol;
            }
            obj[symbol]++;
          } else
          if (symbol === '}' || symbol === ']') {
            obj[map[symbol]]--;
            if (!obj['{'] && !obj['[']) {
              rawJson.push(jsonText);
            }
          }
        }
        var jsonList = [];
        for (var i = 0, item; item = rawJson[i]; i++) {
          if (item === '{}' || item === '[]') {
            continue;
          }
          try {
            if (match) {
              match.every(function(r) {
                return r.test(item);
              }) && jsonList.push(JSON.parse(item));
            } else {
              jsonList.push(JSON.parse(item));
            }
          } catch (e) {
            // console.log('bad json', item);
          }
        }
        return jsonList;
      };

      mono.findJsonString = function(html, match) {
        "use strict";
        if (match && !Array.isArray(match)) {
          match = [match];
        }

        var rawString = [];
        var lastPos = -1;
        var pos = -1;
        do {
          pos = html.indexOf('"', pos + 1);
          if (pos !== -1) {
            if (html[pos - 1] === '\\') {
              continue;
            }
            if (lastPos !== -1) {
              rawString.push(html.substr(lastPos, pos + 1 - lastPos));
              lastPos = -1;
            } else {
              lastPos = pos;
            }
          } else {
            lastPos = pos;
          }
        } while (pos !== -1);

        var stringList = [];
        for (var i = 0, item; item = rawString[i]; i++) {
          if (item === '""') {
            continue;
          }
          try {
            if (match) {
              match.every(function(r) {
                return r.test(item);
              }) && stringList.push(JSON.parse(item));
            } else {
              stringList.push(JSON.parse(item));
            }
          } catch (e) {
            // console.log('bad json', item);
          }
        }
        return stringList;
      };

      mono.getHtmlTags = function(tagName, str, match) {
        match = match || [];
        if (!Array.isArray(match)) {
          match = [match];
        }
        var result = [];
        var tagOpenRe = new RegExp('(<' + tagName + '[^>]*>)', 'i');
        var tagCloseRe = new RegExp('(</' + tagName + '>)', 'i');

        var m = null;
        var openTag = '';
        var closeTag = '';
        var content = '';
        var pos = -1;
        while (m = tagOpenRe.exec(str)) {
          openTag = m[1];
          pos = str.indexOf(openTag);
          if (pos === -1) {
            break;
          }

          str = str.substr(pos + openTag.length);
          m = tagCloseRe.exec(str);
          if (m) {
            closeTag = m[1];
            content = str.substr(0, str.indexOf(closeTag));
            result.push(openTag + content + closeTag);
          }
        }
        return result.filter(function(str) {
          return match.every(function(re) {
            return re.test(str);
          });
        });
      };

      /**
       * @param {string} str
       * @param {string} location
       * @return {Document}
       */
      mono.parseHtmlFragment = function(str, location) {
        var parser = new DOMParser();
        var doc = parser.parseFromString('<html><body>' + str + '</body></html>', 'text/html');

        if (location) {
          var base = doc.head.querySelector('base');
          if (!base) {
            base = doc.createElement('base');
            base.href = location;
            doc.head.appendChild(base);
          }
        }

        return doc;
      };

      /**
       * @param {Object|Array} cssStyleObj
       * @param {string|Array} [parentSelector]
       * @returns {string}
       */
      mono.style2Text = function(cssStyleObj, parentSelector) {
        "use strict";
        var list = [];

        if (!Array.isArray(cssStyleObj)) {
          cssStyleObj = [cssStyleObj];
        }

        if (parentSelector && !Array.isArray(parentSelector)) {
          parentSelector = [parentSelector];
        }

        var styleToText = function(selectorArr, styleObj) {
          "use strict";
          var content = [];

          for (var item in styleObj) {
            var value = styleObj[item];

            if (item === 'cssFloat') {
              item = 'float';
            }

            var key = item.replace(/([A-Z])/g, function(text, letter) {
              return '-' + letter.toLowerCase();
            });

            content.push(key + ':' + value);
          }

          if (!content.length) {
            return '';
          } else {
            return [selectorArr.join(','), '{', content.join(';'), '}'].join('');
          }
        };

        var inheritSelector = function(section, selector) {
          if (!Array.isArray(selector)) {
            selector = [selector];
          }

          if (parentSelector) {
            var _selector = [];
            var join = (section.join || section.join === '') ? section.join : ' ';
            parentSelector.forEach(function(parentSelector) {
              selector.forEach(function(selector) {
                _selector.push(parentSelector + join + selector);
              });
            });
            selector = _selector;
          }

          return selector;
        };

        cssStyleObj.forEach(function(section) {
          var inhSelector = null;
          var media = section.media;
          var selector = section.selector;
          var style = section.style;
          var append = section.append;

          if (media && append) {
            list.push([media, '{', mono.style2Text(append, parentSelector), '}'].join(''));
          } else
          if (!selector && !style) {
            for (var key in section) {
              if (['append', 'join'].indexOf(key) !== -1) {
                continue;
              }
              selector = key;
              style = section[key];

              append = style.append;
              if (append) {
                delete style.append;
              }

              inhSelector = inheritSelector(section, selector);
              list.push(styleToText(inhSelector, style));

              if (append) {
                list.push(mono.style2Text(append, inhSelector));
              }
            }
          } else {
            inhSelector = inheritSelector(section, selector);
            list.push(styleToText(inhSelector, style));

            if (append) {
              list.push(mono.style2Text(append, inhSelector));
            }
          }
        });

        return list.join('');
      };

      mono.styleReset = {
        animation: "none 0s ease 0s 1 normal none running",
        backfaceVisibility: "visible",
        background: "transparent none repeat 0 0 / auto auto padding-box border-box scroll",
        border: "medium none currentColor",
        borderCollapse: "separate",
        borderImage: "none",
        borderRadius: "0",
        borderSpacing: "0",
        bottom: "auto",
        boxShadow: "none",
        boxSizing: "content-box",
        captionSide: "top",
        clear: "none",
        clip: "auto",
        color: "inherit",
        columns: "auto",
        columnCount: "auto",
        columnFill: "balance",
        columnGap: "normal",
        columnRule: "medium none currentColor",
        columnSpan: "1",
        columnWidth: "auto",
        content: "normal",
        counterIncrement: "none",
        counterReset: "none",
        cursor: "auto",
        direction: "ltr",
        display: "inline",
        emptyCells: "show",
        float: "none",
        font: "normal normal normal normal medium/normal inherit",
        height: "auto",
        hyphens: "none",
        left: "auto",
        letterSpacing: "normal",
        listStyle: "disc outside none",
        margin: "0",
        maxHeight: "none",
        maxWidth: "none",
        minHeight: "0",
        minWidth: "0",
        opacity: "1",
        orphans: "0",
        outline: "medium none invert",
        overflow: "visible",
        overflowX: "visible",
        overflowY: "visible",
        padding: "0",
        pageBreakAfter: "auto",
        pageBreakBefore: "auto",
        pageBreakInside: "auto",
        perspective: "none",
        perspectiveOrigin: "50% 50%",
        position: "static",
        right: "auto",
        tabSize: "8",
        tableLayout: "auto",
        textAlign: "inherit",
        textAlignLast: "auto",
        textDecoration: "none solid currentColor",
        textIndent: "0",
        textShadow: "none",
        textTransform: "none",
        top: "auto",
        transform: "none",
        transformOrigin: "50% 50% 0",
        transformStyle: "flat",
        transition: "none 0s ease 0s",
        unicodeBidi: "normal",
        verticalAlign: "baseline",
        visibility: "visible",
        whiteSpace: "normal",
        widows: "0",
        width: "auto",
        wordSpacing: "normal",
        zIndex: "auto",
        all: "initial"
      };

      /**
       * @param {string} host
       * @param {Array} hostList
       * @returns {boolean}
       */
      mono.matchHost = function(host, hostList) {
        "use strict";
        var dotPos;
        while ((dotPos = host.indexOf('.')) !== -1) {
          if (hostList.indexOf(host) !== -1) {
            return true;
          }
          host = host.substr(dotPos + 1);
        }

        return false;
      };

      /**
       * @param {string} key
       * @param {Function} callback
       */
      mono.storage.getExpire = function(key, callback) {
        "use strict";
        var prefix = mono.storage.getExpire.prefix;
        var now = parseInt(Date.now() / 1000);
        var expireKey = key + prefix;
        return mono.storage.get([key, expireKey], function(storage) {
          var isExpire = storage[expireKey] === undefined || storage[expireKey] < now;
          var _storage = {};
          _storage[key] = storage[key];
          return callback(_storage, isExpire);
        });
      };

      mono.storage.getExpire.prefix = '_expire_';

      /**
       * @param {Object} storage
       * @param {number} time
       * @param {function} [callback]
       */
      mono.storage.setExpire = function(storage, time, callback) {
        "use strict";
        var prefix = mono.storage.getExpire.prefix;
        var now = parseInt(Date.now() / 1000);
        var setObj = {};
        for (var key in storage) {
          setObj[key] = storage[key];
          setObj[key + prefix] = now + time;
        }
        return mono.storage.set(setObj, function() {
          return callback && callback();
        });
      };

      mono.onRemoveEventName = 'sf-removed-' + Math.floor(Math.random() * 1000000);
      mono.onRemoveClassName = 'sf-notify-on-remove-' + Math.floor(Math.random() * 1000000);

      /**
       * @param {Element} node
       * @param {Function} event
       */
      mono.onRemoveEvent = function(node, event) {
        "use strict";
        node.classList.add(mono.onRemoveClassName);
        node.addEventListener(mono.onRemoveEventName, event);
      };
      /**
       * @param {Element} node
       */
      mono.onRemoveListener = function(node) {
        "use strict";
        mono.trigger(node, mono.onRemoveEventName);
      };
      /**
       * @param {Element} node
       * @param {Function} event
       */
      mono.offRemoveEvent = function(node, event) {
        "use strict";
        node.removeEventListener(mono.onRemoveEventName, event);
      };

      /**
       * @param {Node|Element} node
       * @param {string} selector
       * @returns {boolean}
       */
      mono.matches = function(node, selector) {
        "use strict";
        var el = document.createElement('div');
        if (typeof el.matches === 'function') {
          mono.matches = function(node, selector) {
            return node.matches(selector);
          };
        } else
        if (typeof el.matchesSelector === 'function') {
          mono.matches = function(node, selector) {
            return node.matchesSelector(selector);
          };
        } else
        if (typeof el.webkitMatchesSelector === 'function') {
          mono.matches = function(node, selector) {
            return node.webkitMatchesSelector(selector);
          };
        } else
        if (typeof el.mozMatchesSelector === 'function') {
          mono.matches = function(node, selector) {
            return node.mozMatchesSelector(selector);
          };
        } else
        if (typeof el.oMatchesSelector === 'function') {
          mono.matches = function(node, selector) {
            return node.oMatchesSelector(selector);
          };
        } else
        if (typeof el.msMatchesSelector === 'function') {
          mono.matches = function(node, selector) {
            return node.msMatchesSelector(selector);
          };
        } else {
          mono.matches = function(node, selector) {
            return false;
          };
        }
        el = null;

        return mono.matches.call(this, node, selector);
      };

      /**
       * @param {Element} node
       * @param {string} selector
       * @returns {Node|null}
       */
      mono.getParent = function(node, selector) {
        if (!node || node.nodeType !== 1) {
          return null;
        }

        if (mono.matches(node, selector)) {
          return node;
        }

        if (!mono.matches(node, selector + ' ' + node.tagName)) {
          return null;
        }

        node = node.parentNode;
        for (var parent = node; parent; parent = parent.parentNode) {
          if (parent.nodeType !== 1) {
            return null;
          }

          if (mono.matches(parent, selector)) {
            return parent;
          }
        }

        return null;
      };

      /**
       * @param {string} value
       * @returns {string}
       */
      mono.escapeRegex = function(value) {
        "use strict";
        return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
      };

      /**
       * @param {function} callback
       * @constructor
       */
      mono.AsyncList = function(callback) {
        var wait = 0;
        var ready = 0;
        var fired = false;
        this.ready = function(err) {
          if (fired) {
            return;
          }

          if (err) {
            fired = true;
            return callback(err);
          }

          ready++;
          if (wait === ready) {
            fired = true;
            return callback();
          }
        };
        this.wait = function() {
          wait++;
        };
      };

      /**
       * @param {*} msg
       * @param {string} [hook]
       * @returns {Promise}
       */
      mono.sendMessagePromise = function(msg) {
        "use strict";
        return new mono.Promise(function(resolve) {
          mono.sendMessage(msg, resolve);
        });
      };

      /**
       * @param {String|[String]|Object|null|undefined} keys
       * @returns {Promise}
       */
      mono.storage.getPromise = function(keys) {
        "use strict";
        return new mono.Promise(function(resolve) {
          mono.storage.get(keys, resolve);
        });
      };

      /**
       * @param {Object} items
       * @returns {Promise}
       */
      mono.storage.setPromise = function(items) {
        "use strict";
        return new mono.Promise(function(resolve) {
          mono.storage.set(items, resolve);
        });
      };

      /**
       * @param {String|[String]} keys
       * @returns {Promise}
       */
      mono.storage.removePromise = function(keys) {
        "use strict";
        return new mono.Promise(function(resolve) {
          mono.storage.remove(keys, resolve);
        });
      };

      /**
       * @returns {Promise}
       */
      mono.storage.clearPromise = function() {
        "use strict";
        return new mono.Promise(function(resolve) {
          mono.storage.clear(resolve);
        });
      };

      /**
       * @param {requestDetails} obj
       * @returns {Promise}
       */
      mono.requestPromise = function(obj) {
        "use strict";
        return new mono.Promise(function(resolve, reject) {
          mono.request(obj, function(err, resp) {
            if (err) {
              reject(err);
            } else {
              resolve(resp);
            }
          });
        });
      };

      /**
       * @returns {Number}
       */
      mono.getTime = function() {
        return parseInt(Date.now() / 1000);
      };

      mono.debug = function() {
        if (mono.debugMode) {
          var args = [].slice.call(arguments);
          args.unshift('sf');
          console.log.apply(console, args);
        }
      };

      mono.error = function() {
        var args = [].slice.call(arguments);
        args.unshift('sf');
        console.error.apply(console, arguments);
      };

      mono.isNewVersion = function(oldVersion, newVersion) {
        var validate = /^[\d.]+$/;
        if (!validate.test(oldVersion) || !validate.test(newVersion)) {
          throw new Error('Incorrect version');
        }
        var normalize = function(value, len) {
          while (value.length < len) {
            value = '0' + value;
          }
          return value;
        };
        var oldParts = oldVersion.split('.');
        var newParts = newVersion.split('.');
        for (var index = 0; index < newParts.length; index++) {
          var oldValue = oldParts[index] || '';
          var newValue = newParts[index] || '';
          var len = Math.max(oldValue.length, newValue.length);
          oldValue = parseInt(normalize(oldValue, len));
          newValue = parseInt(normalize(newValue, len));
          if (newValue === oldValue) {
            continue;
          }
          return newValue > oldValue;
        }
        return false;
      };

      mono.getDataUrl = function(content, type, isForceData) {
        var url = '';
        if (!isForceData && typeof URL !== 'undefined' && typeof Blob !== "undefined" && !mono.isSafari) {
          var blob = new Blob([content], {
            encoding: "UTF-8",
            type: type
          });
          url = URL.createObjectURL(blob);
        } else {
          var contentUtf8 = SaveFrom_Utils.utf8Encode(content);
          url = 'data:' + type + ';charset=utf8;base64,' + encodeURIComponent(btoa(contentUtf8))
        }
        return url;
      };

      _mono && (function(tmpMono) {
        "use strict";
        _mono = null;
        var args, list = tmpMono.loadModuleStack;
        if (list) {
          while (args = list.shift()) {
            // async
            mono.asyncFn(mono.loadModule).apply(mono, args);
          }
        }
      })(_mono);
      //<utils

      if (typeof Promise === 'function' &&
        typeof Promise.resolve === 'function' &&
        typeof Promise.reject === 'function'
      ) {
        mono.Promise = Promise;
      }

      !mono.Promise && (function() {
        // Use polyfill for setImmediate for performance gains
        var asap = (typeof setImmediate === 'function' && setImmediate) ||
          function(fn) {
            setTimeout(fn, 0);
          };

        /**
         @license
         Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
         This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
         The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
         The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
         Code distributed by Google as part of the polymer project is also
         subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
         */
        // @url https://github.com/PolymerLabs/promise-polyfill
        // @version 1.0.0
        function MakePromise(asap) {
          function Promise(fn) {
            if (typeof this !== 'object' || typeof fn !== 'function') throw new TypeError();
            this._state = null;
            this._value = null;
            this._deferreds = []

            doResolve(fn, resolve.bind(this), reject.bind(this));
          }

          function handle(deferred) {
            var me = this;
            if (this._state === null) {
              this._deferreds.push(deferred);
              return
            }
            asap(function() {
              var cb = me._state ? deferred.onFulfilled : deferred.onRejected
              if (typeof cb !== 'function') {
                (me._state ? deferred.resolve : deferred.reject)(me._value);
                return;
              }
              var ret;
              try {
                ret = cb(me._value);
              } catch (e) {
                deferred.reject(e);
                return;
              }
              deferred.resolve(ret);
            })
          }

          function resolve(newValue) {
            try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
              if (newValue === this) throw new TypeError();
              if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
                var then = newValue.then;
                if (typeof then === 'function') {
                  doResolve(then.bind(newValue), resolve.bind(this), reject.bind(this));
                  return;
                }
              }
              this._state = true;
              this._value = newValue;
              finale.call(this);
            } catch (e) {
              reject.call(this, e);
            }
          }

          function reject(newValue) {
            this._state = false;
            this._value = newValue;
            finale.call(this);
          }

          function finale() {
            for (var i = 0, len = this._deferreds.length; i < len; i++) {
              handle.call(this, this._deferreds[i]);
            }
            this._deferreds = null;
          }

          /**
           * Take a potentially misbehaving resolver function and make sure
           * onFulfilled and onRejected are only called once.
           *
           * Makes no guarantees about asynchrony.
           */
          function doResolve(fn, onFulfilled, onRejected) {
            var done = false;
            try {
              fn(function(value) {
                if (done) return;
                done = true;
                onFulfilled(value);
              }, function(reason) {
                if (done) return;
                done = true;
                onRejected(reason);
              })
            } catch (ex) {
              if (done) return;
              done = true;
              onRejected(ex);
            }
          }

          Promise.prototype['catch'] = function(onRejected) {
            return this.then(null, onRejected);
          };

          Promise.prototype.then = function(onFulfilled, onRejected) {
            var me = this;
            return new Promise(function(resolve, reject) {
              handle.call(me, {
                onFulfilled: onFulfilled,
                onRejected: onRejected,
                resolve: resolve,
                reject: reject
              });
            })
          };

          Promise.resolve = function(value) {
            if (value && typeof value === 'object' && value.constructor === Promise) {
              return value;
            }

            return new Promise(function(resolve) {
              resolve(value);
            });
          };

          Promise.reject = function(value) {
            return new Promise(function(resolve, reject) {
              reject(value);
            });
          };


          return Promise;
        }

        mono.Promise = MakePromise(asap);
      })(mono);

      (function(Promise) {
        Promise.all = Promise.all || function() {
          var args = Array.prototype.slice.call(arguments.length === 1 && Array.isArray(arguments[0]) ? arguments[0] : arguments);

          return new Promise(function(resolve, reject) {
            if (args.length === 0) return resolve([]);
            var remaining = args.length;

            function res(i, val) {
              try {
                if (val && (typeof val === 'object' || typeof val === 'function')) {
                  var then = val.then;
                  if (typeof then === 'function') {
                    then.call(val, function(val) {
                      res(i, val)
                    }, reject);
                    return;
                  }
                }
                args[i] = val;
                if (--remaining === 0) {
                  resolve(args);
                }
              } catch (ex) {
                reject(ex);
              }
            }
            for (var i = 0; i < args.length; i++) {
              res(i, args[i]);
            }
          });
        };

        Promise.race = Promise.race || function(values) {
          return new Promise(function(resolve, reject) {
            for (var i = 0, len = values.length; i < len; i++) {
              values[i].then(resolve, reject);
            }
          });
        };
      })(mono.Promise);
      //@insert

      return mono;
    }
  ));

  var engine = {};

  engine.varCache = {
    // helper name
    helperName: '',
    // extension version
    currentVersion: '',
    langList: ['en', 'de', 'ru', 'tr', 'uk', 'es', 'fr', 'id'],
    meta: {},
    isFirstrun: false,
    isUpgrade: false,
    uuid: '',
    aiid: ''
  };

  engine.extra = {};

  engine.defaultPreferences = {
    version: '0',
    button: 1,
    lmMediaHosting: 1,
    moduleYoutube: 1,
    moduleDailymotion: 1,
    moduleVimeo: 1,
    moduleFacebook: 1,
    moduleSoundcloud: 1,
    moduleVkontakte: 1,
    moduleOdnoklassniki: 1,
    moduleMailru: 1,
    moduleInstagram: 1,
    moduleRutube: 1,
    moduleShowDownloadInfo: 1,
    ytHideFLV: 0,
    ytHideMP4: 0,
    ytHideWebM: 1,
    ytHide3GP: 1,
    ytHide3D: 1,
    ytHideMP4NoAudio: 1,
    ytHideAudio_MP4: 1,
    vkShowBitrate: 0,
    sovetnikEnabled: 1,
    showUmmyInfo: 1,
    showUmmyBtn: 1,
    gmNativeDownload: 0,
    expIndex: 0,
    advPreShow: 0,
    aviaBarEnabled: 1,
    statEnabled: 1,

    showUmmyLanding: 0,
    onceShowYtTutorial: 0,
    onceShowYtTooltip: 0,
    saveAsDialog: 0
  };

  engine.preferences = {
    sfHelperName: '',
    country: '',
    hasSovetnik: undefined,
    hasAviaBar: undefined,
    downloads: undefined,
    ummyDetected: undefined,
    showUmmyItem: undefined
  };

  engine.preferenceMap = {
    youtube: 'moduleYoutube',
    dailymotion: 'moduleDailymotion',
    vimeo: 'moduleVimeo',
    facebook: 'moduleFacebook',
    soundcloud: 'moduleSoundcloud',
    vk: 'moduleVkontakte',
    odnoklassniki: 'moduleOdnoklassniki',
    mailru: 'moduleMailru',
    instagram: 'moduleInstagram',
    rutube: 'moduleRutube'
  };

  engine.modules = {};
  engine.utils = {};

  engine.loader = (function() {
    var DEBUG = false;
    var waitList = [];
    var readyList = [];
    var run = function() {
      waitList.slice(0).forEach(function(obj) {
        var isReady = obj.nameList.every(function(name) {
          return readyList.indexOf(name) !== -1;
        });
        if (isReady) {
          var pos = waitList.indexOf(obj);
          if (pos !== -1) {
            waitList.splice(pos, 1);
            try {
              DEBUG && console.debug('Loader run', obj.nameList);
              obj.fn();
            } catch (e) {
              mono.error('Run error!', e);
            }
          }
        }
      });
    };
    /**
     * @param {String} name
     */
    var ready = function(name) {
      DEBUG && console.trace('Loader ready', name);
      readyList.push(name);
      run();
    };
    /**
     * @param {String|String[]} nameList
     * @param {Function} fn
     */
    var when = function(nameList, fn) {
      DEBUG && console.trace('Loader when', nameList);
      if (!Array.isArray(nameList)) {
        nameList = [nameList];
      }
      waitList.push({
        nameList: nameList,
        fn: fn
      });
      run();
    };

    return {
      waitList: waitList,
      readyList: readyList,
      ready: ready,
      when: when
    }
  })();

  engine.events = (function() {
    var DEBUG = false;
    var listeners = {};
    var slice = [].slice;
    /**
     * @param {string} event
     * @param {...*} params
     */
    var emit = function(event, params) {
      var args = slice.call(arguments).slice(1);
      var arr = listeners[event] || [];
      arr.slice(0).forEach(function(callback) {
        try {
          DEBUG && console.debug('Events emit', event);
          callback.apply(null, args);
        } catch (e) {
          mono.error('Emit error!', e);
        }
      });
    };
    /**
     * @param {string} event
     * @param {Function} callback
     */
    var on = function(event, callback) {
      var arr = listeners[event];
      if (!listeners[event]) {
        arr = listeners[event] = [];
      }
      var pos = arr.indexOf(callback);
      if (pos === -1) {
        DEBUG && console.trace('Events on', event);
        arr.push(callback);
      }
    };
    /**
     * @param {string} event
     * @param {Function} callback
     */
    var off = function(event, callback) {
      var arr = listeners[event] || [];
      var pos = arr.indexOf(callback);
      if (pos !== -1) {
        DEBUG && console.trace('Events off', event);
        arr.splice(pos, 1);
      }
    };
    /**
     * @param {string} event
     * @param {Function} callback
     */
    var once = function(event, callback) {
      DEBUG && console.trace('Events once', event);
      var _callback = function() {
        off(event, callback);
        callback.apply(null, arguments);
      };
      on(event, _callback);
    };

    return {
      listeners: listeners,
      emit: emit,
      on: on,
      off: off,
      once: once
    }
  })();

  engine.getHelperName = function() {
    "use strict";
    var getBrowserName = function() {
      var browser = '';
      var userAgent = mono.getNavigator().userAgent;
      if (userAgent.indexOf('YaBrowser\/') !== -1) {
        browser = 'yabrowser';
      } else
      if (userAgent.indexOf('Maxthon\/') !== -1) {
        browser = 'maxthon';
      } else
      if (userAgent.indexOf('OPR\/') !== -1) {
        browser = 'opera-chromium';
      } else
      if (userAgent.indexOf('Opera\/') !== -1) {
        browser = 'opera';
      } else
      if (userAgent.indexOf('Firefox\/') !== -1) {
        browser = 'firefox';
      } else
      if (userAgent.indexOf('Chrome\/') !== -1) {
        browser = 'chrome';
      } else
      if (userAgent.indexOf('Safari\/') !== -1) {
        browser = 'safari';
      }
      return browser;
    };

    var browser = 'unknown';
    if (mono.isChrome) {
      browser = getBrowserName() || 'chrome';
      if (/sandbox.html#bg/.test(location.href)) {
        browser = 'chameleon';
      }
      if (engine.chromeNoStore) {
        browser += '-sf';
      }
    } else
    if (mono.isFirefox) {
      browser = 'firefox';
      if (mono.isFirefoxMobile) {
        browser += '-mobile';
      }
      if (engine.firefoxNoStore) {
        browser += '-sf';
      }
    } else
    if (mono.isSafari) {
      browser = 'safari';
    } else
    if (mono.isOpera) {
      browser = 'opera';
    } else
    if (mono.isGM) {
      browser = getBrowserName() || browser;
      browser = 'userjs-' + browser;
    } else
    if (mono.isEdge) {
      browser = 'edge';
    }

    return browser;
  };

  engine.getSfHelperName = function() {
    var name = engine.varCache.helperName;
    if (/^firefox/.test(name)) {
      name = name.replace('firefox', 'ff');
    }
    return name;
  };

  engine.dblTrackCheck = function(cb) {
    "use strict";
    var DEBUG = false;
    if (!mono.isGM) {
      return cb();
    }

    if (mono.isIframe()) {
      DEBUG && mono.debug('dblTrack inside frame disabled!');
      return;
    }

    mono.storage.get('dblTrack', function(storage) {
      var now = Date.now();
      if (typeof storage.dblTrack !== 'string') {
        storage.dblTrack = '';
      }

      var dataList = storage.dblTrack.split(',');
      if (dataList[1] > now) {
        DEBUG && mono.debug('dblTrack is not expired!');
        return;
      }

      var uuid = engine.generateUuid();
      var expire = now + 60000;
      mono.storage.set({
        dblTrack: uuid + ',' + expire
      });

      setTimeout(function() {
        mono.storage.get('dblTrack', function(storage) {
          if (typeof storage.dblTrack === 'string') {
            var dataList = storage.dblTrack.split(',');
            if (dataList[0] === uuid) {
              DEBUG && mono.debug('dblTrack callback');
              cb();
            } else {
              DEBUG && mono.debug('dblTrack uuid is change');
            }
          }
        });
      }, 5000);
    });
  };

  engine.getUuid = function() {
    "use strict";
    var varCache = engine.varCache;
    if (varCache.uuid) {
      return varCache.uuid;
    }

    var uuid = engine.generateUuid();
    varCache.uuid = uuid;
    mono.storage.set({
      uuid: uuid
    });
    return uuid;
  };

  engine.generateUuid = function() {
    "use strict";
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = Math.random() * 16 | 0,
        v = c == 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  };

  engine.sovetnikIsAvailable = function() {
    "use strict";
    if (!mono.isFirefox && !mono.isChrome && !mono.isGM && !mono.isOpera) {
      return false;
    }
    if (mono.isChrome && mono.isChromeMobile) {
      return false;
    }
    if (mono.isFirefox && mono.isFirefoxMobile) {
      return false;
    }
    return true;
  };

  /**
   * @returns {string}
   */
  engine.getNavLanguage = function() {
    var language = '';
    var navLanguage = mono.getNavigator().language;
    if (/^\w{2}-|^\w{2}$/.test(navLanguage)) {
      language = navLanguage;
    }
    return language;
  };

  engine.loadLanguage = function(cb) {
    "use strict";
    var language = engine.language;
    var varCache = engine.varCache;
    var langList = varCache.langList;
    var defaultLocale = langList[0];
    var locale = mono.getLoadedLocale();
    if (!locale) {
      var navLanguage = engine.getNavLanguage().substr(0, 2).toLowerCase();
      if (langList.indexOf(navLanguage) !== -1) {
        locale = navLanguage;
      } else {
        locale = defaultLocale;
      }
    }

    (function getLanguage(locale, cb) {
      mono.getLanguage(locale, function(err, _language) {
        if (err) {
          if (locale !== defaultLocale) {
            getLanguage(defaultLocale, cb);
          } else {
            cb();
          }
        } else {
          mono.extend(language, _language);
          cb();
        }
      });
    })(locale, cb);
  };

  engine.language = {};
  engine.operaShowButton = (function() {
    var button = null;
    return function(enabled) {
      "use strict";
      if (button !== null) {
        opera.contexts.toolbar.removeItem(button);
        button = null;
      }
      if (enabled) {
        button = opera.contexts.toolbar.createItem({
          title: 'SaveFrom.net helper',
          icon: "img/icon_18.png",
          popup: {
            href: "popup.html",
            width: 482,
            height: 404
          }
        });
        opera.contexts.toolbar.addItem(button);
      }
    };
  })();

  engine.gmShowButton = function(enabled) {
    if (enabled) {
      _menu.setTitle(engine.language.extName, engine.varCache.currentVersion);
      mono.storage.get('gmIconTop', function(storage) {
        if (storage.gmIconTop === 0 || storage.gmIconTop) {
          _menu.style.menu.initial.top = storage.gmIconTop + 'px';
        }
        _menu.create(1);
      });
    } else {
      _menu.hide();
    }
  };

  engine.tabListener = (function() {
    "use strict";
    var isListen = false;
    var preferences = engine.preferences;
    var extendJsList = {};
    var excludeList = [
      "*://*.google.*/*",
      "*://*.acidtests.org/*",

      "*://*.savefrom.net/*",
      "*://*.youtube.com/*",
      "*://*.vimeo.com/*",
      "*://*.dailymotion.*/*",
      "*://*.vk.com/*",
      "*://*.vkontakte.ru/*",
      "*://*.odnoklassniki.ru/*",
      "*://my.mail.ru/*",
      "*://*.ok.ru/*",
      "*://*.soundcloud.com/*",
      "*://*.facebook.com/*",
      "*://*.instagram.com/*",
      "*://*.rutube.ru/*"
    ];
    var matchCache = null;
    var checkBlackList = function(url) {
      return matchCache.test(url);
    };
    var listener = function(tab) {
      var url = tab.url;
      var inBlackList = checkBlackList(url);
      var scripts = [];

      var addLm = preferences.lmMediaHosting;
      var addSovetnik = preferences.hasSovetnik && preferences.sovetnikEnabled;

      if (mono.isChrome || mono.isEdge || mono.isFirefox) {
        addSovetnik = addSovetnik && window.sovetnik;
      }

      if (!inBlackList) {
        if (addLm) {
          scripts.push('includes/components.js');
          scripts.push('includes/link_modifier.js');
        }
        if (addSovetnik) {
          if (mono.isChrome || mono.isEdge || mono.isFirefox) {
            scripts.push('includes/sovetnik-sf.js');
          }
        }
      }

      var empty = true;
      for (var key in extendJsList) {
        empty = false;
        var item = extendJsList[key];
        if (!inBlackList || item.noBlackList) {
          var scriptList = item.getScriptList(url);
          for (var i = 0, path; path = scriptList[i]; i++) {
            if (scripts.indexOf(path) === -1) {
              scripts.push(path);
            }
          }
        }
      }

      if (!addLm && !addSovetnik && empty) {
        removeListener();
      } else
      if (scripts.length) {
        scripts.unshift('js/mono.js');

        mono.debug('Inject', url, scripts);

        mono.executeScripts(tab, {
          files: scripts
        });
      }
    };
    var removeListener = function() {
      mono.tabsRemoveListener(listener);
      isListen = false;
      mono.debug('tabListener', isListen);
    };
    var addListener = function() {
      if (!isListen) {
        mono.tabsAddListener(listener);
        isListen = true;
        mono.debug('tabListener', isListen);
      }
    };
    var buildMatchCache = function() {
      if (!matchCache) {
        matchCache = excludeList.map(function(pattern) {
          return mono.urlPatternToStrRe(pattern);
        }).join('|');
        matchCache = new RegExp(matchCache);
      }
    };
    var enable = function() {
      if (mono.isChrome || (mono.isFirefox && !mono.isFirefoxMobile) || mono.isEdge) {
        buildMatchCache();
        addListener();
      }
    };
    var disable = function() {
      if (mono.isChrome || (mono.isFirefox && !mono.isFirefoxMobile) || mono.isEdge) {
        removeListener();
      }
    };
    var injectLmInActiveTab = function() {
      var scripts = [
        'js/mono.js',
        'includes/components.js',
        'includes/link_modifier.js'
      ];

      mono.getActiveTab(function(tab) {
        if (tab && /^http/.test(tab.url) && !checkBlackList(tab.url)) {
          mono.executeScripts(tab, {
            files: scripts
          });
        }
      });
    };
    return {
      extendJsList: extendJsList,
      excludeList: excludeList,
      enable: enable,
      disable: disable,
      injectLmInActiveTab: injectLmInActiveTab
    }
  })();

  engine.getCountry = function() {
    "use strict";
    var preferences = engine.preferences;
    var varCache = engine.varCache;

    var getCountryFromLanguage = function(callback) {
      var lang2country = {
        be: 'by',
        kk: 'kz',
        ru: 'ru',
        uk: 'ua',
        hy: 'am',
        ro: 'md',
        az: 'az',
        ka: 'ge',
        ky: 'kg',
        uz: 'uz',
        lv: 'lv',
        lt: 'lt',
        et: 'ee',
        tg: 'tj',
        fi: 'fi',
        tk: 'tm'
      };

      var navLanguage = engine.getNavLanguage().substr(0, 2).toLowerCase();
      var country = lang2country[navLanguage];

      mono.asyncFn(callback)(country);
    };

    var requestCountry = function(callback) {
      var xh = preferences.sfHelperName + ' ' + varCache.currentVersion;
      mono.request({
        type: 'POST',
        url: 'http://sf-helper.com/geoip/country.php',
        data: {
          sig: xh.length
        },
        headers: {
          'X-Helper': xh
        }
      }, function(err, resp, data) {
        var country = '';
        if (!err && data) {
          country = data.toLowerCase().substr(0, 2);
        }
        callback(country);
      });
    };

    var onGetLanguage = function(country) {
      mono.debug('Set country', country);
      preferences.country = country;
      mono.storage.set({
        country: country
      });
      engine.liteStorage.setExpire('countryExpire', 259200);

      engine.loader.ready('getCountry');
    };

    var isExpire = engine.liteStorage.isExpire('countryExpire');
    var isTimeout = engine.liteStorage.isTimeout('countryTimeout');
    if (isExpire && !isTimeout) {
      engine.liteStorage.setTimeout('countryTimeout', 86400);

      getCountryFromLanguage(function(country) {
        if (country) {
          mono.debug('Get country via language', country);
          onGetLanguage(country);
        } else {
          requestCountry(function(country) {
            mono.debug('Get country via api', country);
            if (country) {
              onGetLanguage(country);
            } else {
              mono.debug('Api country is empty!');
            }
          });
        }
      });
    }
  };

  engine.forceMetaRequest = false;

  engine.getMeta = (function() {
    "use strict";
    var varCache = engine.varCache;
    var defaultMeta = {};

    var currentDate = function() {
      var _date = new Date();
      var date = _date.getDate();
      var month = _date.getMonth() + 1;
      var cDate = '';

      cDate += date < 10 ? '0' + date : date;
      cDate += month < 10 ? '0' + month : month;
      cDate += _date.getFullYear();

      return cDate;
    };

    var requestMeta = function(callback) {
      engine.liteStorage.setTimeout('metaTimeout', 21600);

      var always = mono.onceFn(function(err, meta) {
        if (err) {
          mono.debug('Meta request error!', err);
        }

        if (varCache.isFirstrun && !meta) {
          meta = defaultMeta;
        }

        if (meta) {
          var _meta = varCache.meta;
          for (var key in _meta) {
            delete _meta[key];
          }

          mono.extend(_meta, meta);

          engine.loader.ready('getMeta');
        }

        callback();
      });

      setTimeout(function() {
        always('TIMEOUT');
      }, 6000);

      return mono.request({
        url: 'http://sf-helper.com/meta/meta.json' + '?_=' + currentDate(),
        json: true
      }, function(err, resp, json) {
        if (err) {
          always(err);
        } else {
          mono.storage.set({
            meta: json
          });
          engine.liteStorage.setExpire('metaExpire', 86400);
          always(null, json);
        }
      });
    };

    var getMeta = function(callback) {
      var onceCb = mono.onceFn(callback);
      var isExpire = engine.liteStorage.isExpire('metaExpire');
      var isTimeout = engine.liteStorage.isTimeout('metaTimeout');
      if (mono.isEmptyObject(engine.expList) && !engine.forceMetaRequest) {
        mono.debug('Meta not require');
        onceCb();
      } else
      if (varCache.isFirstrun || varCache.isUpgrade) {
        mono.debug('Meta force request');
        requestMeta(function() {
          onceCb();
        });
      } else
      if (isTimeout) {
        mono.debug('Meta timeout');
        onceCb();
      } else
      if (isExpire) {
        mono.debug('Meta is expire');
        requestMeta(function() {
          onceCb();
        });
      } else {
        mono.debug('Meta is fresh');
        onceCb();
      }
    };

    return getMeta;
  })();

  engine.loader.when('prepare', function() {
    var promise = mono.Promise.resolve();

    if (engine.liteStorage.get('fromId', 0)) {
      return promise;
    }

    if (mono.isGM && mono.isIframe()) {
      return promise;
    }

    var requestFromId = function() {
      return mono.requestPromise({
        url: 'http://savefrom.net/tools/get_vid.php'
      }).then(function(resp) {
        var data = resp.body;
        var id = -1;
        if (/^\d+$/.test(data)) {
          id = parseInt(data);
        }

        mono.debug('fromId', id);

        engine.liteStorage.set('fromId', id);
      }).catch(function(err) {
        return mono.error("Request fromId error!", err);
      })
    };

    promise = promise.then(function() {
      var isTimeout = engine.liteStorage.isTimeout('fromIdTimeout');
      if (isTimeout) {
        return mono.debug('Request fromId timeout');
      } else {
        engine.liteStorage.setTimeout('fromIdTimeout', 21600);
        return requestFromId();
      }
    }).catch(function(err) {
      mono.error('Request fromId error', err);
    });

    return promise;
  });

  engine.loader.when('init', function() {
    "use strict";
    if (!mono.isSafari) {
      return;
    }

    safari.extension.settings.addEventListener('change', function(event) {
      if (event.key !== 'show_options') {
        return;
      }
      mono.openTab(safari.extension.baseURI + 'options.html', true);
    });

    var checkInterval = null;

    var removePopover = function() {
      if (checkInterval) {
        clearInterval(checkInterval);
        checkInterval = null;
      }

      safari.extension.toolbarItems.forEach(function(btn) {
        if (btn.popover) {
          if (btn.popover.visible) {
            btn.popover.hide();
          }
          btn.popover = null;
        }
      });

      safari.extension.removePopover('popup');
    };

    safari.application.addEventListener('command', function(e) {
      if (e.command === 'openPopup') {
        var currentBtn = null;
        var activeWindow = safari.application.activeBrowserWindow;
        safari.extension.toolbarItems.some(function(btn) {
          if (btn.browserWindow === activeWindow) {
            currentBtn = btn;
            return true;
          }
        });
        if (!currentBtn) {
          return;
        }

        if (currentBtn.popover && currentBtn.popover.visible) {
          currentBtn.popover.hide();
          return;
        }

        removePopover();

        currentBtn.popover = safari.extension.createPopover('popup', safari.extension.baseURI + 'popup.html', 482, 404);
        currentBtn.showPopover();

        checkInterval = setInterval(function() {
          var isShowMenu = safari.extension.toolbarItems.some(function(btn) {
            if (btn.popover && btn.popover.visible) {
              return true;
            }
          });
          if (!isShowMenu) {
            removePopover();
          }
        }, 1000 * 30);
      }
    }, false);
  });

  engine.onOptionChange = {
    button: function(enabled) {
      if (mono.isOpera) {
        engine.operaShowButton(enabled);
      } else
      if (mono.isGM) {
        engine.gmShowButton(enabled);
      }
    },
    sovetnikEnabled: function(value, oldValue) {
      if (value === oldValue) {
        return;
      }

      if (engine.preferences.hasSovetnik) {
        if (value) {
          engine.tabListener.enable();
        }

        if (mono.isOpera || mono.isChrome || mono.isFirefox) {
          if (window.sovetnik && window.sovetnik.setRemovedState) {
            window.sovetnik.setRemovedState(!value)
          }
        }
      }
    },
    statEnabled: function(state) {
      engine.events.emit('statEnabledChange', state);
    },
    lmMediaHosting: function(value) {
      if (value) {
        engine.tabListener.enable();
      }
    },
    gmNativeDownload: function(value) {
      if (!mono.isGM) {
        return;
      }
      engine.preferences.downloads = !!value;
      if (mono.global.preference) {
        // GM only!
        mono.global.preference.downloads = engine.preferences.downloads;
      }
    }
  };

  engine.sendInGa = (function() {
    "use strict";
    var stack = [];
    var lock = false;
    var send = function() {
      if (lock || !stack.length) {
        return;
      }

      lock = true;

      var now = Date.now();
      var items = stack.slice(0, 20);
      var data = items.map(function(item) {
        var time = item.time;
        var params = JSON.parse(JSON.stringify(item.params));
        var qt = now - time;
        if (qt >= 14400000) {
          qt = 14400000 - ((stack.length + 1) * 1000);
        }
        params.qt = qt;
        return mono.param(params);
      });

      return mono.request({
        url: 'https://www.google-analytics.com/batch?z=' + now,
        type: 'POST',
        contentType: 'text/html',
        data: data.join('\n'),
        timeout: 60 * 1000
      }, function(err) {
        lock = false;
        if (!err) {
          items.forEach(function(item) {
            var details = item.details;
            var pos = stack.indexOf(item);
            if (pos !== -1) {
              stack.splice(pos, 1);
            }
            try {
              details.onSuccess && details.onSuccess();
            } catch (e) {
              mono.error('sendInGa', 'onSuccess', e);
            }
          });

          send();
        }
      });
    };

    var pull = function() {
      if (!stack.length) {
        return;
      }

      var isTimeout = engine.liteStorage.isTimeout('sendInGaTimeout');
      if (!isTimeout) {
        engine.liteStorage.setTimeout('sendInGaTimeout', 1 * 60 * 60);
        send();
      }
    };
    /**
     *@param {Object} params
     *@param {Object} [details]
     *@param {String} details.id
     *@param {Function} details.onSuccess
     **/
    var push = function(params, details) {
      var exists = false;
      details = details || {};

      if (details.id) {
        exists = stack.some(function(item) {
          if (item.details.id === details.id) {
            return true;
          }
        });
      }

      if (!exists) {
        stack.unshift({
          time: Date.now(),
          params: params,
          details: details
        });

        stack.splice(100);

        setTimeout(function() {
          send();
        }, 50);
      }
    };

    return {
      stack: stack,
      push: push,
      pull: pull
    };
  })();

  engine.actionList = {
    getMenuDetails: function(msg, response) {
      "use strict";
      var getLastVersion = function() {
        var version = '';

        var currentVersion = engine.varCache.currentVersion;
        var lastVersion = engine.liteStorage.get('lastVersion', '');
        if (!currentVersion || !lastVersion) {
          return version;
        }

        try {
          if (mono.isNewVersion(currentVersion, lastVersion)) {
            version = lastVersion;
          }
        } catch (err) {
          mono.debug('isNewVersion', err);
        }

        return version;
      };

      var details = {
        language: engine.language,
        preferences: engine.preferences,
        version: engine.varCache.currentVersion,
        lastVersion: getLastVersion(),
        helperName: engine.varCache.helperName
      };

      return response(details);
    },
    getLanguageAndPreference: function(message, response) {
      engine.actionList.getLanguage(message, function(language) {
        engine.actionList.getPreference(message, function(preference) {
          response({
            getLanguage: language,
            getPreference: preference
          });
        });
      });
    },
    getLanguage: function(message, cb) {
      cb(engine.language);
    },
    getPreference: function(message, cb) {
      var preferences = engine.preferences;
      if (mono.isSafari || mono.isGM) {
        preferences = mono.extend({}, engine.preferences);
      }

      cb(preferences);

      engine.userTrack();

      engine.sendInGa.pull();
    },
    updateOption: function(message) {
      var key = message.key;
      var value = message.value;
      var oldValue = engine.preferences[key];
      engine.preferences[key] = value;

      var obj = {};
      obj[key] = value;
      mono.storage.set(obj);

      if (engine.onOptionChange[key]) {
        engine.onOptionChange[key](value, oldValue);
      }
    },
    downloadFromCurrentPage: function() {
      var url = 'http://savefrom.net/';
      mono.getActiveTabUrl(function(cUrl) {
        var args = mono.param({
          url: cUrl,
          utm_source: engine.preferences.sfHelperName,
          utm_medium: 'extensions',
          utm_campaign: 'bookmarklet'
        });
        mono.openTab(url + '?' + args, true);
      });
    },
    openPoll: function() {
      if (['en', 'uk', 'ru'].indexOf(engine.language.lang) === -1) {
        return;
      }
      var url = 'http://' + engine.language.lang + '.savefrom.net/helper-form.php';
      mono.getActiveTabUrl(function(cUrl) {
        var domain = mono.getDomain(cUrl) || '';

        var args = '?' + mono.param({
          version: engine.varCache.currentVersion,
          helper: engine.preferences.sfHelperName,
          url: domain
        });
        mono.openTab(url + args, true);
      });
    },
    reportBug: function() {
      var url = 'http://savefrom.userecho.com/forum/20869-/';
      if (engine.language.lang === 'ru') {
        url = 'http://savefrom.userecho.com/forum/19523-/';
      }
      mono.openTab(url);
    },
    viaMenu_updateLinks: function() {
      mono.sendMessageToActiveTab({
        action: 'updateLinks'
      });
    },
    viaMenu_downloadMP3Files: function() {
      mono.sendMessageToActiveTab({
        action: 'downloadMP3Files'
      });
    },
    viaMenu_downloadPlaylist: function() {
      mono.sendMessageToActiveTab({
        action: 'downloadPlaylist'
      });
    },
    viaMenu_downloadPhotos: function() {
      mono.sendMessageToActiveTab({
        action: 'downloadPhotos'
      });
    },
    viaMenu_changeState: function(msg) {
      engine.actionList.updateOption({
        key: msg.prefKey,
        value: msg.state
      });

      if (msg.state && msg.moduleName === 'lm' && msg.needInclude) {
        if (mono.isChrome || mono.isFirefox) {
          return engine.tabListener.injectLmInActiveTab();
        }
      }

      mono.sendMessageToActiveTab({
        action: 'changeState',
        moduleName: msg.moduleName,
        state: msg.state
      });
    },
    showOptions: function() {
      if (mono.isGM) {
        return _options.show();
      }
      var url = 'options.html';
      if (mono.isSafari) {
        url = safari.extension.baseURI + url;
      }
      mono.openTab(url, true);
    },
    getActiveTabModuleInfo: function(msg, cb) {
      mono.sendMessageToActiveTab({
        action: 'getModuleInfo',
        url: msg.url
      }, function(moduleInfo) {
        cb(moduleInfo);
      });
      return true;
    },
    getActiveTabUrl: function(message, cb) {
      mono.getActiveTabUrl(function(url) {
        return cb(url);
      });
      return true;
    },
    getActiveTabInfo: function(msg, cb) {
      var preferences = engine.preferences;
      mono.getActiveTabUrl(function(url) {
        if (url.indexOf('http') !== 0) {
          return cb();
        }

        var hostList = {
          dailymotion: ['*://*.dailymotion.*/*'],
          facebook: ['*://*.facebook.com/*'],
          mailru: ['*://my.mail.ru/*'],
          odnoklassniki: ['*://*.ok.ru/*', '*://*.odnoklassniki.ru/*'],
          savefrom: ['*://*.savefrom.net/*'],
          soundcloud: ['*://*.soundcloud.com/*'],
          vimeo: ['*://*.vimeo.com/*'],
          vk: ['*://*.vk.com/*', '*://*.vkontakte.ru/*'],
          youtube: ['*://*.youtube.com/*'],
          instagram: ['*://*.instagram.com/*'],
          rutube: ['*://*.rutube.ru/*']
        };

        var moduleName = 'lm';
        var prefKey = 'lmMediaHosting';
        var state = preferences.lmMediaHosting;

        for (var key in hostList) {
          var regList = hostList[key];
          var re = regList.map(function(pattern) {
            return mono.urlPatternToStrRe(pattern);
          }).join('|');
          re = new RegExp(re);

          if (re.test(url)) {
            moduleName = key;
            prefKey = engine.preferenceMap[moduleName];
            state = preferences[prefKey];
            break;
          }
        }

        return cb({
          moduleName: moduleName,
          prefKey: prefKey,
          url: url,
          state: state
        });
      });
      return true;
    },
    userjsDetected: function() {
      if (!engine.liteStorage.get('userjsDetected', false)) {
        engine.liteStorage.set('userjsDetected', true);

        var uuid = engine.getUuid();
        return mono.request({
          url: 'https://www.google-analytics.com/collect',
          type: 'POST',
          data: 'v=1&tid=UA-7055055-1&cid=' + uuid + '&t=pageview&dh=savefrom.net&dp=%2Fextension%2Fuserjs_installed.ext'
        });
      }
    },
    hideDownloadWarning: function(message, cb) {
      if (message.set !== undefined) {
        return mono.storage.set({
          hideDownloadWarning: message.set
        });
      }
      mono.storage.get('hideDownloadWarning', function(storage) {
        cb(storage.hideDownloadWarning);
      });
      return true;
    },
    track: function(message) {
      delete message.action;
      engine.track(message);
    },
    addToClipboard: function(message) {
      if (mono.isChrome || mono.isFirefox) {
        var text = message.text;
        var textArea;
        document.body.appendChild(textArea = mono.create('textarea', {
          text: text
        }));
        textArea.select();
        mono.asyncCall(function() {
          document.execCommand("copy", false, null);
          textArea.parentNode.removeChild(textArea);
        });
      }
    },
    setIconBadge: function(msg) {
      "use strict";
      var text = String(msg.text);

      if (mono.isChrome || mono.isFirefox) {
        chrome.browserAction && chrome.browserAction.setBadgeText({
          text: text
        });
      }
    },
    trackError: function(msg) {
      "use strict";
      try {
        var trackError = engine.actionList.trackError;
        if (!trackError.dDbl) {
          trackError.dDbl = {};
        }

        var desc = msg.desc;

        if (msg.error) {
          var error = msg.error;
          desc = desc ? desc + ' ' : '';
          if (error instanceof Error) {
            desc += String(error.message || error) || 'ERROR';
            if (error.stack) {
              desc += ' ' + msg.error.stack;
            }
          } else {
            desc += error;
          }
        }

        var exd = desc.substr(0, 150);

        if (trackError.dDbl[exd]) {
          return;
        }
        trackError.dDbl[exd] = true;

        var params = {
          t: 'exception',
          exd: exd,
          tid: 'UA-7055055-9'
        };

        engine.sendStatsInfo(params);
      } catch (e) {}
    },
    openTab: function(msg) {
      mono.openTab(msg.url);
    }
  };

  engine.onMessage = function(message, cb) {
    if (!message || typeof message !== 'object') {
      mono.debug('Skip message', message);
      return;
    }

    if (!engine.onMessage.ready) {
      engine.onMessage.stack.push(arguments);
      return;
    }

    var action = message.action;
    var func = engine.actionList[action];
    if (func) {
      return func.call(engine.actionList, message, cb);
    }

    for (var moduleName in engine.modules) {
      var module = engine.modules[moduleName];
      func = module[action];
      if (func) {
        return func.call(module, message, cb);
      }
    }

    func = engine.utils[action];
    if (func) {
      return func.call(engine.utils, message, cb);
    }

    mono.debug('Action is not found', message);
  };
  engine.onMessage.stack = [];
  engine.onMessage.ready = false;

  engine.loadSettings = function(cb) {
    var varCache = engine.varCache;
    var preferences = engine.preferences;
    var defaultPreferences = engine.defaultPreferences;

    if (mono.isGM) {
      defaultPreferences.button = 0;
      defaultPreferences.showUmmyBtn = 0;
    }

    var preload = {
      ummyDetected: function(value) {
        if (!value && value !== 0) {
          value = preferences.showUmmyInfo ? 0 : 1;
          mono.storage.set({
            ummyDetected: value
          });
        }
        preferences.ummyDetected = value;
      }
    };

    var defPreferencesKeys = Object.keys(defaultPreferences);
    var preloadKeys = Object.keys(preload);
    return mono.storage.get(defPreferencesKeys.concat(preloadKeys), function(storage) {
      defPreferencesKeys.forEach(function(key) {
        var defaultValue = defaultPreferences[key];
        var value = storage[key];
        if (value === undefined) {
          value = defaultValue;
        }
        preferences[key] = value;
      });

      preloadKeys.forEach(function(key) {
        preload[key](storage[key]);
      });

      if (varCache.isFirstrun) {
        var tutorialStorage = {
          showUmmyLanding: preferences.showUmmyLanding = 1,
          onceShowYtTooltip: preferences.onceShowYtTooltip = 1,
          onceShowYtTutorial: preferences.onceShowYtTutorial = 1
        };
        mono.storage.set(tutorialStorage);
      }

      if (preferences.onceShowYtTutorial && !engine.hasMenuTutorial) {
        preferences.onceShowYtTutorial = 0;
      }

      if (mono.isChrome) {
        if (mono.isChromeVersion < 31) {
          preferences.downloads = false;
        } else
        if (
          (chrome.downloads && chrome.downloads.download) ||
          (chrome.permissions && chrome.permissions.request)
        ) {
          preferences.downloads = true;
        }
      }

      if (mono.isGM) {
        preferences.downloads = false;
        var hasDownloadApi = typeof GM_download !== 'undefined';
        var browserApiDownloadMode = false;
        if (hasDownloadApi) {
          browserApiDownloadMode = typeof GM_info !== 'undefined' && GM_info.downloadMode === 'browser';
        }
        if (hasDownloadApi && (preferences.gmNativeDownload || browserApiDownloadMode)) {
          preferences.gmNativeDownload = 1;
          preferences.downloads = true;
        }
      }

      if (mono.isFirefox) {
        preferences.downloads = true;
      }

      if (preferences.downloads) {
        preferences.moduleShowDownloadInfo = 0;
      }

      return cb();
    });
  };

  engine.exp = (function() {
    var varCache = engine.varCache;
    var preferences = engine.preferences;
    var meta = varCache.meta;
    var list = engine.expList = {};
    /**
     * @param {string} type
     * @returns {number}
     */
    var getExpIndex = function(type) {
      var result = 0;
      var value = 0;

      if (type === 'firstrun') {
        value = mono.getRandomInt(0, 100);

        for (var index in list) {
          var percent = list[index].percent;
          if (value < percent) {
            result = parseInt(index);
            break;
          } else {
            value -= percent;
          }
        }

      } else
      if (type === 'upgrade') {

      }

      return result;
    };
    var selectExp = function() {
      var metaExp = meta.exp || {};
      Object.keys(list).forEach(function(index) {
        var expItem = metaExp[index];
        if (!expItem || !expItem.enable) {
          delete list[index];
        } else {
          var item = list[index];
          if (item.isAvailable && !item.isAvailable(preferences, varCache)) {
            delete list[index];
          } else {
            list[index].percent = expItem.percent || 0;
          }
        }
      });

      var expIndex = preferences.expIndex;
      if (expIndex > 0 && !list[expIndex]) {
        expIndex = 0;
      }

      if (varCache.isFirstrun) {
        expIndex = getExpIndex('firstrun');
      } else
      if (varCache.isUpgrade && expIndex === 0) {
        expIndex = getExpIndex('upgrade');
      }

      setExpIndex(expIndex);
    };
    /**
     * @param {number} index
     */
    var setExpIndex = function(index) {
      if (preferences.expIndex !== index) {
        mono.debug('Set exp index', index);
        engine.actionList.updateOption({
          key: 'expIndex',
          value: index
        });
      }
    };
    var disable = function() {
      setExpIndex(0);
    };
    var cancel = function() {
      mono.debug('Cancel exp', preferences.expIndex);
      preferences.expIndex = 0;
    };
    /**
     * @param {number} expIndex
     */
    var load = function(expIndex) {
      mono.debug('Load exp', expIndex);
      try {
        list[expIndex](preferences, varCache);
      } catch (e) {
        mono.error('Load exp error!', expIndex, e);
      }
    };
    var run = function() {
      var expIndex = preferences.expIndex;
      if (expIndex > 0) {
        if (!list[expIndex]) {
          setExpIndex(0);
        } else
        if (meta.exp && meta.exp[expIndex] && meta.exp[expIndex].cancel) {
          cancel();
        } else {
          load(expIndex);
        }
      }
    };
    var init = function() {
      if (typeof EXP_INDEX === 'number') {
        mono.debug('Force exp index', EXP_INDEX);
        preferences.expIndex = EXP_INDEX;
        run();
      } else
      if (!varCache.isFirstrun && !varCache.isUpgrade) {
        run();
      } else
      if (!meta.exp || mono.isEmptyObject(list)) {
        setExpIndex(0);
      } else {
        selectExp();
        run();
      }
    };
    return {
      init: init,
      disable: disable
    }
  })();

  engine.checkSovetnik = function() {
    "use strict";
    var preferences = engine.preferences;

    var langList = [
      'be', 'kk', 'ru', 'uk',
      'hy', 'ro', 'az', 'ka',
      'ky', 'uz', 'lv', 'lt',
      'et', 'tg', 'fi', 'tk'
    ];

    var countryList = [
      'by', 'kz', 'ru', 'ua',
      'am', 'md', 'az', 'ge',
      'kg', 'uz', 'lv', 'lt',
      'ee', 'tj', 'fi', 'tm'
    ];

    preferences.hasSovetnik = countryList.indexOf(preferences.country) !== -1;
    if (!preferences.hasSovetnik) {
      var navLanguage = engine.getNavLanguage().substr(0, 2).toLowerCase();
      preferences.hasSovetnik = langList.indexOf(navLanguage) !== -1;
    }

    if (preferences.hasSovetnik) {
      if (mono.isOpera || mono.isChrome || mono.isFirefox) {
        if (engine.sovetnikInit) {
          mono.asyncCall(function() {
            engine.sovetnikInit && engine.sovetnikInit();
          });
        }
      }
    }

    engine.tabListener.enable();
  };

  engine.prepare = function(cb) {
    "use strict";
    var varCache = engine.varCache;

    engine.loader.when('getHelperVersion', function() {
      engine.getCountry();
    });

    engine.loader.when('loadSettings', function() {
      if (engine.sovetnikIsAvailable()) {
        engine.checkSovetnik();
        engine.loader.when('getCountry', function() {
          engine.checkSovetnik();
        });
      }
    });

    engine.loader.when(['loadLanguage', 'loadSettings', 'getHelperVersion'], function() {
      varCache.isUpgrade = !varCache.isFirstrun && engine.preferences.version !== varCache.currentVersion;

      engine.getMeta(function() {
        engine.exp.init();

        cb();
      });
    });

    engine.loadLanguage(function() {
      engine.loader.ready('loadLanguage');
    });

    engine.loadSettings(function() {
      engine.loader.ready('loadSettings');
    });

    var onGetVersion = function(version) {
      varCache.currentVersion = version || 'unknown';
      engine.loader.ready('getHelperVersion');
    };

    mono.safeFn(function(cb) {
      cb(mono.getVersion());
    }, onGetVersion, engine)(onGetVersion);
  };

  engine.initMessageListener = function() {
    if (!engine.initMessageListener.fired) {
      engine.initMessageListener.fired = true;
      mono.onMessage.addListener(function(message, response) {
        return engine.onMessage(message, response);
      }, {
        isBg: true
      });
    }
  };

  engine.init = function() {
    engine.initMessageListener();

    var varCache = engine.varCache;
    var preferences = engine.preferences;

    var load = function() {
      var _navigator = mono.getNavigator();

      varCache.helperName = engine.getHelperName();

      preferences.showUmmyItem = /^Win|^Mac/.test(_navigator.platform) ? 1 : 0;

      preferences.sfHelperName = engine.getSfHelperName();

      engine.loader.ready('init');

      engine.loader.when('beforePrepare', function() {
        engine.checkVersion();
      });

      engine.prepare(function() {
        engine.loader.ready('beforePrepare');

        engine.onMessage.ready = true;
        while (engine.onMessage.stack.length > 0) {
          mono.asyncFn(engine.onMessage).apply(null, engine.onMessage.stack.shift());
        }

        engine.loader.ready('prepare');
      });
    };

    var keys = ['uuid', 'version', 'meta', 'country', 'aiid'];
    keys.push(engine.liteStorage.getStorageKey());

    return mono.storage.get(keys, function(storage) {
      engine.liteStorage.setStorage(storage);

      if (typeof storage.uuid === 'string' && storage.uuid.length === 36) {
        varCache.uuid = storage.uuid;
      }
      if (typeof storage.aiid === 'string') {
        varCache.aiid = storage.aiid.replace(/aiid/, '').replace(/#/g, '');
      }
      if (!storage.version) {
        varCache.isFirstrun = true;
      }
      if (storage.meta) {
        mono.extend(varCache.meta, storage.meta);
      }
      if (storage.country) {
        preferences.country = storage.country;
      }

      return load();
    });
  };

  engine.userTrack = function() {
    if (engine.liteStorage.isTimeout('trackTimeout')) {
      return;
    }
    engine.liteStorage.setTimeout('trackTimeout', 5 * 60);

    var next = function() {
      engine.track({
        t: 'screenview',
        cd: 'init',
        tid: 'UA-7055055-5'
      }, {
        id: 'init',
        onSuccess: function() {
          "use strict";
          engine.liteStorage.setTimeout('trackTimeout', 12 * 60 * 60);

          if (engine.preferences.expIndex) {
            engine.track({
              t: 'screenview',
              cd: 'init',
              tid: 'UA-7055055-11'
            });
          }

          engine.events.emit('sendScreenView');
        }
      });
    };

    return engine.dblTrackCheck(next);
  };

  engine.trackValidate = function(params) {
    var isValidValue = function(value) {
      if (!value && value !== 0 && value !== false) {
        return false;
      }
      if (['object', 'function'].indexOf(typeof value) !== -1) {
        return false;
      }
      return true;
    };

    if (!params.tid) {
      return false;
    }

    if (!params.cid) {
      return false;
    }

    if (parseInt(params.v) !== 1) {
      return false;
    }

    if (!isValidValue(params.an)) {
      return false;
    }

    if (!params.t) {
      return false;
    } else
    if (params.t === 'event') {
      if (!isValidValue(params.ec) || !isValidValue(params.ea) || !isValidValue(params.el)) {
        return false;
      }
    } else
    if (params.t === 'screenview') {
      if (!isValidValue(params.cd)) {
        return false;
      }
    } else
    if (params.t === 'social') {
      if (!isValidValue(params.st) || !isValidValue(params.sa) || !isValidValue(params.sn)) {
        return false;
      }
    }

    return true;
  };

  engine.track = function(params, details) {
    return engine.sendStatsInfo(params, details);
  };

  /**
   * @param {Object} params
   * @param {Object} [details]
   * @param {String} [details.id]
   * @param {Function} [details.onSuccess]
   */
  engine.quickTrack = function(params, details) {
    if (!engine.trackValidate(params)) {
      mono.error('Invalid track params!', params);
    } else {
      mono.debug('Track', params);
      engine.sendInGa.push(params, details);
    }
  };

  engine.wrapBaseStatInfo = function(params) {
    var varCache = engine.varCache;

    var defaultParams = {
      v: 1,
      ul: mono.getNavigator().language,
      tid: 'UA-67738130-2',
      cid: engine.getUuid(),

      an: 'helper',
      aid: varCache.helperName,
      av: varCache.currentVersion
    };

    for (var key in defaultParams) {
      if (!params.hasOwnProperty(key)) {
        params[key] = defaultParams[key];
      }
    }

    return params;
  };

  engine.sendStatsInfo = function(params, details) {
    var preferences = engine.preferences;

    engine.wrapBaseStatInfo(params);

    if (engine.varCache.aiid) {
      params.aiid = engine.varCache.aiid;
    }

    if (!params.hasOwnProperty('cd3')) {
      params.cd3 = engine.language.lang;
    }

    if (preferences.expIndex) {
      params.cd1 = 'test_' + preferences.expIndex;
    }

    var fromId = engine.liteStorage.get('fromId', 0);
    if (fromId > 0) {
      params.cd2 = fromId;
    }

    if (preferences.hasSovetnik) {
      params.cd4 = preferences.sovetnikEnabled ? 'true' : 'false';
    }

    params.cd6 = preferences.ummyDetected ? 'true' : preferences.showUmmyItem ? 'false' : 'none';

    if (preferences.hasAviaBar) {
      params.cd7 = preferences.aviaBarEnabled ? 'true' : 'false';
    }

    engine.quickTrack(params, details);
  };

  engine.checkVersion = function() {
    var varCache = engine.varCache;
    var needSaveVersion = false;
    if (varCache.isFirstrun) {
      engine.loader.ready('firstrun');

      needSaveVersion = true;
    } else
    if (varCache.isUpgrade) {
      engine.loader.ready('upgrade');

      needSaveVersion = true;
    }

    if (needSaveVersion) {
      engine.actionList.updateOption({
        key: 'version',
        value: varCache.currentVersion
      });
    }
  };

  engine.loader.when('firstrun', function() {
    "use strict";
    if (mono.isGM) {
      return;
    }

    var url = 'http://savefrom.net/user.php?helper=' + engine.preferences.sfHelperName + ';firstrun';

    engine.utils.checkUrlsOfOpenTabs([
      /https?:\/\/([\w\-]+\.)?savefrom\.net\/(update-helper|userjs-setup)\.php/i
    ], function(foundUrls) {
      if (foundUrls.length > 0) {
        return;
      }

      engine.utils.checkUrlsOfOpenTabs([
        /https?:\/\/legal\.yandex\.(ru|com\.tr)\//i
      ], function(foundUrls) {
        var active = foundUrls.length === 0;
        return mono.openTab(url, active);
      });
    });
  });

  engine.loader.when('prepare', function() {
    "use strict";
    var preferences = engine.preferences;

    if (preferences.onceShowYtTutorial) {
      engine.actionList.setIconBadge({
        text: '?'
      });
    }

    if (preferences.showUmmyLanding) {
      mono.storage.get(['onceUmmyLandingHide'], function(storage) {
        if (storage.onceUmmyLandingHide > 2) {
          mono.storage.set({
            showUmmyLanding: preferences.showUmmyLanding = 0
          });
        }
      });
    }
  });

  engine.loader.when('prepare', function() {
    "use strict";
    if (!mono.isChrome && !mono.isFirefox) {
      return;
    }

    engine.tabListener.enable();
  });

  engine.loader.when('init', function() {
    "use strict";
    if ((!mono.isChrome && !mono.isFirefox) || !chrome.runtime.setUninstallURL) {
      return;
    }

    var varCache = engine.varCache;
    var preferences = engine.preferences;

    var updateUrl = function() {
      var uninstallUrl = 'http://savefrom.net/goodbye.php';

      var params = {
        version: varCache.currentVersion,
        language: engine.language.lang,
        appid: varCache.helperName,
        country: preferences.country
      };

      var url = (uninstallUrl + '?' + mono.param(params)).substr(0, 255);
      chrome.runtime.setUninstallURL(url);
    };

    updateUrl();

    engine.loader.when('prepare', function() {
      updateUrl();
    });

    engine.loader.when('getCountry', function() {
      updateUrl();
    });
  });

  engine.loader.when('prepare', function() {
    "use strict";
    if (!mono.isOpera) {
      return;
    }

    engine.operaShowButton(engine.preferences.button);
  });

  engine.liteStorage = (function() {
    var storageKey = 'liteStorage';
    var store = {};
    /**
     * @param {*} value
     */
    var cloneObj = function(value) {
      return JSON.parse(JSON.stringify({
        w: value
      })).w;
    };
    /**
     * @param {Function} cb
     */
    var save = function(cb) {
      var obj = {};
      obj[storageKey] = store;
      return mono.storage.set(obj, cb);
    };
    var debounceSave = function() {
      mono.error('liteStorage is not set!');
    };
    /**
     * @param {String} key
     * @param {*} value
     */
    var setValue = function(key, value) {
      if (store[key] !== value) {
        store[key] = value;
        debounceSave();
      }
    };
    /**
     * @param {string} key
     * @param {*} defaultValue
     * @returns {*}
     */
    var getValue = function(key, defaultValue) {
      var value = store[key];
      if (value === undefined) {
        value = defaultValue;
      }
      return cloneObj(value);
    };
    /**
     * @returns {string}
     */
    var getStorageKey = function() {
      return storageKey;
    };
    /**
     * @param {Object} storage
     */
    var setStorage = function(storage) {
      store = storage[storageKey] || {};
      debounceSave = mono.debounce(save, 100);
    };
    /**
     * @param {string} key
     * @param {number} time
     */
    var setExpire = function(key, time) {
      return setValue(key, mono.getTime() + time);
    };
    /**
     * @param {string} key
     * @returns {boolean}
     */
    var isTimeout = function(key) {
      return getValue(key, 0) > mono.getTime();
    };
    /**
     * @param {string} key
     * @returns {boolean}
     */
    var isExpire = function(key) {
      return getValue(key, 0) < mono.getTime();
    };
    return {
      getStorageKey: getStorageKey,
      setStorage: setStorage,
      set: setValue,
      get: getValue,
      isTimeout: isTimeout,
      setTimeout: setExpire,
      isExpire: isExpire,
      setExpire: setExpire
    };
  })();

  engine.menuCommands = {
    commands: [{
      id: 'downloadFromCurrentPage',
      command: function() {
        engine.actionList.downloadFromCurrentPage();
      }
    }, {
      id: 'updateLinks',
      notify: 'updateLinksNotification',
      modules: ['vk', 'odnoklassniki', 'facebook', 'lm',
        'youtube',
        'dailymotion', 'instagram', 'rutube'
      ]
    }, {
      id: 'downloadMP3Files',
      modules: ['vk', 'odnoklassniki', 'mailru']
    }, {
      id: 'downloadPlaylist',
      modules: ['vk', 'odnoklassniki', 'mailru']
    }, {
      id: 'downloadPhotos',
      modules: ['vk']
    }, {
      id: 'showOptions',
      command: function() {
        _options.show();
      }
    }, {
      id: 'reportBug',
      command: function() {
        engine.actionList.reportBug();
      }
    }, {
      id: 'enableDisableModule',
      command: function() {
        engine.actionList.getActiveTabInfo(null, function(tabInfo) {
          tabInfo = tabInfo || {};
          var state = tabInfo.state ? 0 : 1;
          engine.actionList.viaMenu_changeState({
            state: state,
            prefKey: tabInfo.prefKey,
            moduleName: tabInfo.moduleName
          });
          if (state) {
            if (engine.preferences.button === 1) {
              engine.gmShowButton(1);
            } else {
              engine.gmShowButton(0);
            }
          } else {
            engine.gmShowButton(0);
          }
        });
      }
    }, {
      id: 'showHideButton',
      command: function() {
        var hiddenBtn = _menu.menu === null;
        engine.actionList.updateOption({
          action: 'updateOption',
          key: 'button',
          value: hiddenBtn ? 1 : 0
        });
      }
    }],
    registerModule: function(params) {
      if (typeof GM_registerMenuCommand === 'undefined') {
        return;
      }

      var strId = params.id;

      var name = engine.language[strId];

      if (params.command) {
        return GM_registerMenuCommand(name, params.command);
      }

      var fn = function() {
        engine.onMessage({
          action: (params.modules !== undefined ? 'viaMenu_' : '') + params.id
        });

        if (params.notify && typeof GM_notification !== 'undefined') {
          GM_notification(engine.language[params.notify], null, null, null, 3000);
        }
      };

      return GM_registerMenuCommand(name, fn);
    },
    register: function(moduleName) {
      var hasRmFunc = typeof GM_unregisterMenuCommand !== "undefined";
      for (var i = 0, item; item = this.commands[i]; i++) {
        if (hasRmFunc) {
          if (item.gmId) {
            GM_unregisterMenuCommand(item.gmId);
          }
        } else
        if (item.hasOwnProperty("gmId")) {
          continue;
        }

        if (!item.modules || item.modules.indexOf(moduleName) > -1) {
          item.gmId = this.registerModule(item);
        }
      }
    }
  };

  engine.loader.when('prepare', function() {
    "use strict";
    if (!mono.isIframe()) {
      engine.menuCommands.register(_moduleName);

      if (engine.preferences.button && engine.preferences[engine.preferenceMap[_moduleName]] || _moduleName === 'savefrom') {
        engine.gmShowButton(1);
      }
    }
  });
  engine.checkUpdate = function() {
    "use strict";
    var varCache = engine.varCache;
    var typeList = engine.checkUpdate.typeList;
    var type = (mono.isChrome && !engine.isOperaNext) ? 'chrome' : (mono.isFirefox && engine.firefoxNoStore) ? 'firefox' : mono.isGM ? 'gm' : mono.isSafari ? 'safari' : undefined;
    if (!typeList[type]) {
      return;
    }

    var requestVersion = function() {
      mono.request({
        type: 'GET',
        url: typeList[type].url,
        cache: false
      }, function(err, resp) {
        if (err) {
          return;
        }

        var version = typeList[type].getVersion(resp.body);
        if (version) {
          engine.liteStorage.set('lastVersion', version);
          engine.liteStorage.setExpire('lastVersionExpire', 604800);
        }
      });
    };

    var isExpire = engine.liteStorage.isExpire('lastVersionExpire');
    if (varCache.isUpgrade) {
      isExpire = true;
    }

    if (isExpire) {
      engine.liteStorage.set('lastVersion', '');
      engine.liteStorage.setExpire('lastVersionExpire', 86400);

      requestVersion();
    }
  };

  engine.checkUpdate.typeList = {
    chrome: {
      url: 'http://download.sf-helper.com/chrome/updates-3.xml',
      getVersion: function(data) {
        var version = /updatecheck.+version=['"](.+)['"]/.exec(data);
        version = version && version[1];
        return version;
      }
    },
    firefox: {
      url: 'https://download.sf-helper.com/mozilla/updates.json',
      getVersion: function(data) {
        var updates = null;
        try {
          var obj = JSON.parse(data);
          updates = obj.addons[Object.keys(obj.addons)[0]].updates;
        } catch (e) {}
        if (!updates) return;

        var version = null;
        updates.some(function(item) {
          return version = item.version;
        });

        return version;
      }
    },
    safari: {
      url: 'https://download.sf-helper.com/safari/update.plist',
      getVersion: function(data) {
        if (typeof data !== 'string') {
          return;
        }

        var pos = data.indexOf('<key>CFBundleVersion</key>');
        if (pos === -1) {
          return;
        }

        data = data.substr(pos);
        var version = /<string>(.+)<\/string>/.exec(data);
        version = version && version[1];
        return version;
      }
    },
    gm: {
      url: 'https://download.sf-helper.com/chrome/helper.meta.js',
      getVersion: function(data) {
        var version = /@version\s+(.+)\s*\r?\n/.exec(data);
        version = version && version[1];
        return version;
      }
    }
  };

  engine.loader.when('prepare', function() {
    "use strict";
    engine.checkUpdate();
  });
  engine.loader.when('init', function() {
    "use strict";
    if (mono.isFirefox && mono.isFirefoxMobile) {
      return;
    }
    if (mono.isChrome && mono.isChromeMobile) {
      return;
    }

    var preferences = engine.preferences;

    var isDeny = function() {
      if (!preferences.hasAviaBar || !preferences.aviaBarEnabled) {
        return true;
      }

      return false;
    };

    var updateState = function() {
      delete engine.tabListener.extendJsList.aviaBar;

      if (isDeny()) {
        return;
      }

      engine.tabListener.extendJsList.aviaBar = aviaBar;

      engine.tabListener.enable();

      travelBarInit && travelBarInit();
    };

    var aviaBar = {
      matchCache: /null/,
      includeList: [
        '*://*.ozon.travel/*',
        '*://*.onetwotrip.com/*',

        '*://*.skyscanner.*/*',

        '*://*.aeroflot.ru/*',
        '*://*.momondo.*/*',
        '*://*.anywayanyday.com/*',
        '*://*.svyaznoy.travel/*',
        '*://avia.tickets.ru/*',
        '*://*.s7.ru/*',
        '*://*.kupibilet.ru/*',
        '*://*.trip.ru/*',
        '*://*.sindbad.ru/*',
        '*://*.aviakassa.ru/*',
        '*://*.aviakassa.com/*',
        '*://*.biletix.ru/*',
        '*://*.utair.ru/*',

        '*://*.kayak.*/*',
        '*://*.orbitz.com/*',
        '*://*.travelocity.com/*',
        '*://*.travelocity.ca/*',
        '*://*.expedia.*/*',
        '*://*.expedia-cn.com/*',
        '*://*.priceline.com/*',

        '*://booking.airasia.com/*',
        '*://*.ryanair.com/*',

        '*://*.booking.*/*',
        '*://*.agoda.*/*',
        '*://*.hotels.com/*',
        '*://*.ostrovok.ru/*',
        '*://*.travel.ru/*',
        '*://*.oktogo.ru/*',
        '*://*.roomguru.ru/*',
        '*://*.tripadvisor.ru/*',
        '*://*.hilton.ru/*',
        '*://*.hilton.com/*',
        '*://*.marriott.com/*',
        '*://*.hostelworld.com/*',
        '*://*.tiket.com/*',
        '*://*.hotelsclick.com/*',
        '*://*.hotelscombined.com/*',

        '*://*.avis.*/*',
        '*://*.budget.com/*',
        '*://*.wizzair.com/*',
        '*://*.emirates.com/*',
        '*://*.delta.com/*',
        "*://*.hertz.com/*",
        "*://*.europcar.com/*"
      ],
      getScriptList: function(url) {
        var list = [];

        if (isDeny()) {
          updateState();
          return list;
        }

        if (this.matchCache.test(url)) {
          list.push('includes/components.js');
          list.push('includes/aviaBar.js');
        }
        return list;
      }
    };

    aviaBar.matchCache = aviaBar.includeList.map(function(pattern) {
      return mono.urlPatternToStrRe(pattern);
    }).join('|');
    aviaBar.matchCache = new RegExp(aviaBar.matchCache);

    engine.onOptionChange.aviaBarEnabled = function() {
      updateState();
    };

    var onLoadSettings = function() {
      var onceTrackAviaBar;

      preferences.hasAviaBar = 1;

      mono.storage.get('onceTrackAviaBar', function(storage) {
        var value = storage.onceTrackAviaBar;
        if (!value && value !== 0) {
          if (mono.getRandomInt(0, 100) < 10) {
            value = 1;
          } else {
            value = 0;
          }
          mono.storage.set({
            onceTrackAviaBar: value
          });
        }
        onceTrackAviaBar = value;
      });

      updateState();

      engine.events.on('sendScreenView', function() {
        if (onceTrackAviaBar) {
          var params = {
            t: 'screenview',
            cd: 'init',
            tid: 'UA-70432435-1'
          };

          engine.wrapBaseStatInfo(params);
          engine.quickTrack(params);
        }
      });
    };

    engine.loader.when('loadSettings', onLoadSettings);

    var travelBarInit = function() {
      travelBarInit = null;

      var browser = {
        onMessage: function(cb) {
          return mono.onMessage.addListener(cb, {
            isBg: true
          });
        },
        storage: {
          get: function(data, cb) {
            return mono.storage.get(data, cb);
          },
          set: function(data, cb) {
            return mono.storage.set(data, cb);
          }
        }
      };

      var travelBar = {};

      travelBar.appInfo = {
        id: 'sf.sfHelper',
        track: true,
        directTrack: true,
        useTemplates: true
      };

      travelBar.API = {
        setRemovedState: function(state) {
          browser.storage.get('aviaBar', function(storage) {
            storage.aviaBar = storage.aviaBar || {};
            storage.aviaBar.removed = !!state;
            return browser.storage.set(storage);
          });
        }
      };

      var track = function(details) {
        var tid = 'UA-70432435-1';
        var isError = ['cheapflightError', 'hotelError'].indexOf(details.ec) !== -1;
        if (isError) {
          tid = 'UA-7055055-10';
        }

        details.tid = tid;
        engine.wrapBaseStatInfo(details);

        if (!isError) {
          var detailsMirror = JSON.parse(JSON.stringify(details));
          detailsMirror.tid = 'UA-70432435-6';

          engine.quickTrack(details);
          engine.quickTrack(detailsMirror);
        } else
        if (mono.isGM) {
          engine.quickTrack(details);
        }
      };

      var directTrack = function(details) {
        if (details.tid) {
          engine.wrapBaseStatInfo(details);
          engine.quickTrack(details);
        }
      };

      var prepareStorage = function(storage) {
        var travelBar = storage.aviaBar;
        if (!travelBar || typeof travelBar !== 'object') {
          travelBar = storage.aviaBar = {};
        }
        if (!Array.isArray(travelBar.blackList)) {
          travelBar.blackList = [];
        }
        if (!travelBar.templates || typeof travelBar.templates !== 'object') {
          travelBar.templates = {};
        }
      };

      browser.onMessage(function(msg, response) {
        if (msg && msg.action) {
          switch (msg.action) {
            case "tbrGetInfo":
              response(travelBar.appInfo);
              break;
            case "tbrIsAllow":
              browser.storage.get('aviaBar', function(storage) {
                prepareStorage(storage);

                var removed = storage.aviaBar.removed;
                if (removed) {
                  return response(false);
                }

                var allow = true;

                var blackList = storage.aviaBar.blackList;

                var item = null;
                blackList.some(function(_item) {
                  if (_item.hostname === msg.hostname) {
                    item = _item;
                    return true;
                  }
                });

                if (item) {
                  var now = parseInt(Date.now() / 1000);
                  if (item.expire > now) {
                    allow = false;
                  } else {
                    var pos = blackList.indexOf(item);
                    blackList.splice(pos, 1);

                    browser.storage.set(storage);
                  }
                }

                return response(allow);
              });
              break;
            case "tbrCloseBar":
              browser.storage.get('aviaBar', function(storage) {
                prepareStorage(storage);

                var blackList = storage.aviaBar.blackList;

                var item = null;
                blackList.some(function(_item) {
                  if (_item.hostname === msg.hostname) {
                    item = _item;
                    return true;
                  }
                });

                if (!item) {
                  var now = parseInt(Date.now() / 1000);
                  blackList.push({
                    hostname: msg.hostname,
                    expire: now + 5 * 60 * 60
                  });

                  browser.storage.set(storage);
                }
              });
              break;
            case "tbrGetTemplate":
              browser.storage.get('aviaBar', function(storage) {
                prepareStorage(storage);

                var templates = storage.aviaBar.templates;
                var template = templates[msg.id];
                if (!template) {
                  templates[msg.id] = template = {};
                }

                var now = parseInt(Date.now() / 1000);
                if (template.expire > now) {
                  response(template.data);
                } else {
                  template.expire = now + 21600;

                  mono.request({
                    url: 'https://travelbar.tools/static/scheme/' + msg.id + '.json',
                    timeout: 60 * 1000,
                    json: true
                  }, function(err, _response) {
                    if (!err) {
                      var data = _response.body;
                      template.expire = now + 43200;
                      template.data = data;

                      Object.keys(templates).sort(function(a, b) {
                        return templates[a].expire > templates[b].expire ? -1 : 1;
                      }).slice(5).forEach(function(key) {
                        delete templates[key];
                      });
                    }

                    response(data);
                    browser.storage.set(storage);
                  });
                }
              });
              break;
            case "tbrEvent":
              if (msg.type === 'track') {
                track(msg.data[0]);
              } else
              if (msg.type === 'directTrack') {
                directTrack(msg.data[0]);
              }
              break;
          }
        }
      });
    };
  });
  engine.loader.when('init', function() {
    "use strict";
    if (mono.isFirefox && mono.isFirefoxMobile) {
      return;
    }

    if (mono.isChrome && mono.isChromeMobile) {
      return;
    }

    var preferences = engine.preferences;
    var meta = engine.varCache.meta;

    var isDeny = function() {
      if (!preferences.hasFsStat || !preferences.statEnabled) {
        return true;
      } else {
        return false;
      }
    };

    var updateState = function() {
      if (isDeny()) {
        delete engine.tabListener.extendJsList.stat;
      } else {
        engine.tabListener.extendJsList.stat = stat;
        engine.tabListener.enable();
      }
    };

    var stat = {
      noBlackList: true,
      getScriptList: function() {
        var list = [];

        if (isDeny()) {
          updateState();
        } else {
          list.push('includes/fsStat.js');
        }

        return list;
      }
    };

    var isAvailable = function() {
      if (meta.fsStat && (!meta.fsStat.enable || meta.fsStat.cancel)) {
        preferences.hasFsStat = 0;
      } else {
        preferences.hasFsStat = 1;
      }
    };

    engine.events.on('statEnabledChange', function() {
      updateState();
    });

    engine.loader.when('getMeta', function() {
      isAvailable();

      updateState();
    });

    engine.loader.when('prepare', function() {
      isAvailable();

      updateState();
    });
  });
  engine.loader.when('init', function() {
    "use strict";
    if (mono.isFirefox && mono.isFirefoxMobile) {
      return;
    }

    if (mono.isChrome && mono.isChromeMobile || /yabrowser|chameleon/.test(engine.varCache.helperName)) {
      return;
    }

    var preferences = engine.preferences;
    var meta = engine.varCache.meta;

    var isDeny = function() {
      if (!preferences.hasSwStat || !preferences.statEnabled) {
        return true;
      } else {
        return false;
      }
    };

    var updateState = function() {
      if (engine.extra.sw) {
        if (isDeny()) {
          engine.extra.sw.disable();
        } else {
          engine.extra.sw.enable();
        }
      }
    };

    var isAvailable = function() {
      if (meta.swStat && (!meta.swStat.enable || meta.swStat.cancel)) {
        preferences.hasSwStat = 0;
      } else {
        preferences.hasSwStat = 1;
      }
    };

    engine.events.on('statEnabledChange', function() {
      updateState();
    });

    engine.loader.when('getMeta', function() {
      isAvailable();

      updateState();
    });

    engine.loader.when('beforePrepare', function() {
      isAvailable();

      updateState();
    });
  });
  engine.loader.when('init', function() {
    var onceTrackStat = null;

    engine.events.on('sendScreenView', function() {
      if (!onceTrackStat) return;

      var preferences = engine.preferences;
      var varCache = engine.varCache;

      if (preferences.hasFsStat || preferences.hasSwStat) {
        var params = {
          v: 1,
          ul: mono.getNavigator().language,
          tid: 'UA-67738130-7',
          cid: engine.getUuid(),
          an: 'helper',
          aid: varCache.helperName,
          av: varCache.currentVersion,
          t: 'screenview',
          cd: 'init',
          cd1: preferences.hasFsStat ? preferences.statEnabled ? 'true' : 'false' : 'none',
          cd2: preferences.hasSwStat ? preferences.statEnabled ? 'true' : 'false' : 'none'
        };

        engine.sendInGa.push(params);
      }
    });

    mono.storage.get({
      onceTrackStat: null
    }, function(storage) {
      onceTrackStat = storage.onceTrackStat;
      if (onceTrackStat === null) {
        if (mono.getRandomInt(0, 100) < 10) {
          onceTrackStat = 1;
        } else {
          onceTrackStat = 0;
        }
        mono.storage.set({
          onceTrackStat: onceTrackStat
        });
      }
    });
  });
  engine.loader.when(['init', 'getHelperVersion'], function() {
    "use strict";

    var dblTrackCheck = function(cb) {
      "use strict";
      if (!mono.isGM) {
        return cb();
      }

      if (mono.isIframe()) {
        return;
      }

      var key = 'userjsDblTrack';
      var getObj = {};
      getObj[key] = '';
      return mono.storage.get(getObj, function(storage) {
        var now = Date.now();

        var dataList = storage[key].split(',');
        if (dataList[1] > now) {
          return;
        }

        var uuid = engine.generateUuid();
        var expire = now + 60000;
        storage[key] = uuid + ',' + expire;
        mono.storage.set(storage);

        return setTimeout(function() {
          return mono.storage.get(getObj, function(storage) {
            var dataList = storage[key].split(',');
            if (dataList[0] === uuid) {
              cb();
            }
          });
        }, 5 * 1000);
      });
    };

    return mono.storage.getPromise({
      userjsIsInstaller: 0,
      userjsVideoId: '',
      userjsIsOpenVideo: 0
    }).then(function(options) {
      if (!options.userjsIsInstaller) {
        mono.debug('Skip', 'userjsIsInstaller', JSON.stringify(options));
        return;
      }

      if (!options.userjsIsOpenVideo && typeof options.userjsVideoId === 'string' && options.userjsVideoId) {
        dblTrackCheck(function() {
          options.userjsIsOpenVideo = 1;
          mono.storage.set(options, function() {
            var videoId = options.userjsVideoId.replace(/#/g, '');
            if (videoId !== 'videoId') {
              mono.openTab('https://www.youtube.com/watch?v=' + videoId);
            }
          });
        });
      }
    });
  });
  engine.loader.when('prepare', function() {
    "use strict";
    if (typeof engine.modules.youtube !== 'object') {
      return;
    }

    var titleRe = /&title=[^&]*$/;
    var collectLinks = function(response, vid) {
      if (!response || !response.links || !response.title || !vid) {
        return;
      }

      var obj = {
        vid: vid,
        links: {},
        title: response.title
      };

      var itagList = [5, 17, 18, 22, 36, 43, 135, 137, 138, 140, 264];
      itagList.forEach(function(itag) {
        var link = response.links[itag];
        if (link) {
          obj.links[itag] = link.replace(titleRe, '');
        }
      });

      if (!Object.keys(obj.links).length) {
        return;
      }

      return mono.request({
        type: 'POST',
        url: 'http://savefrom.net/tools/yt_helper.php',
        data: mono.param({
          video_id: obj.vid,
          data: JSON.stringify(obj)
        })
      });
    };

    var _this = engine.modules.youtube;
    var _origGetYoutubeLinks = _this.getYoutubeLinks;
    _this.getYoutubeLinks = function(msg, cb) {
      return _origGetYoutubeLinks.call(_this, msg, function(response) {
        collectLinks(response, msg.extVideoId);
        return cb.apply(this, arguments);
      });
    };
  });
  //@insert

  mono.onReady(function() {
    if (mono.isGM) {
      engine.initMessageListener();
    } else {
      engine.init();
    }
  });
  var bg_utils = {
    getFileSize: function(message, cb) {
      "use strict";
      var url = message.url;
      var response = {
        fileSize: 0,
        fileType: '',
        status: 0,
        error: false
      };
      mono.request({
        url: url,
        type: 'HEAD'
      }, function(err, resp) {
        if (err) {
          response.error = true;
          return cb(response);
        }

        response.status = resp.statusCode;

        response.fileSize = parseInt(resp.headers['content-length']) || 0;

        var contentType = resp.headers['content-type'];
        if (contentType) {
          response.fileType = contentType;
        }

        cb(response);
      });
      return true;
    },
    ChromeDl: function() {
      var inProgress = {};
      var isListen = false;
      var addListener = function() {
        if (isListen) return;
        isListen = true;
        chrome.downloads.onChanged.addListener(onChange);
      };
      var removeListener = function() {
        isListen = false;
        chrome.downloads.onChanged.removeListener(onChange);
      };
      var addDownloadId = function(id, details) {
        if (!inProgress[id]) {
          inProgress[id] = details;
        }
      };
      var removeDownloadId = function(id) {
        if (inProgress[id]) {
          delete inProgress[id];
        }
        if (Object.keys(inProgress).length === 0) {
          removeListener();
        }
      };
      var canFixNetworkFiled = function(details, downloadDelta) {
        var time = parseInt(Date.now() / 1000);

        var resumeDownload = false;

        if (!details.lastFix) {
          details.lastFix = 0;
        }

        if (details.lastFix + 5 < time) {
          details.lastFix = time;
          resumeDownload = true;
        }

        var isInterrupted = downloadDelta.state && downloadDelta.state.current === 'interrupted';
        var networkFailed = downloadDelta.error && downloadDelta.error.current === 'NETWORK_FAILED';
        var canResume = downloadDelta.canResume && downloadDelta.canResume.current;
        if (!isInterrupted || !networkFailed || !canResume) {
          resumeDownload = false;
        }

        return resumeDownload;
      };
      var onChange = function(downloadDelta) {
        var details = inProgress[downloadDelta.id];
        if (!details) {
          return;
        }

        var resumeDownload = false;
        if (details.fixNetworkFiled) {
          resumeDownload = canFixNetworkFiled(details, downloadDelta);
        }
        if (resumeDownload) {
          chrome.downloads.resume(downloadDelta.id);
        } else
        if (downloadDelta.state && ['interrupted', 'complete'].indexOf(downloadDelta.state.current) !== -1) {
          removeDownloadId(downloadDelta.id);
        }
      };

      this.download = function(details) {
        var url = details.url;
        var filename = details.filename;

        details.fixNetworkFiled = /(vk\.me|userapi\.com)\/.+\.mp4/i.test(url);

        var options = {
          url: url,
          filename: filename
        };
        if (mono.isFirefox && engine.preferences.saveAsDialog) {
          options.saveAs = true;
        }
        chrome.downloads.download(options, function(downloadId) {
          if (details.fixNetworkFiled) {
            addDownloadId(downloadId, details);
            addListener();
          }
        });
      };
    },
    chromeDownload: null,
    downloadFile: function(message) {
      "use strict";
      var _this = bg_utils;
      if (mono.isChrome || mono.isFirefox) {
        if (!_this.chromeDownload) {
          _this.chromeDownload = new _this.ChromeDl();
        }
        var onHasPermission = function() {
          return _this.chromeDownload.download(message.options);
        };
        if (chrome.downloads && chrome.downloads.download) {
          return onHasPermission();
        } else
        if (chrome.permissions && chrome.permissions.request) {
          chrome.permissions.request({
            permissions: ['downloads']
          }, function(granted) {
            if (granted) {
              return onHasPermission();
            } else {
              mono.error('Permissions not granted!');
            }
          });
        } else {
          mono.error('Method in not supported!');
        }
      } else
      if (mono.isGM) {
        GM_download(message.options.url, message.options.filename);
      }
    },
    chromeListDownload: function(list, folder) {
      var waitDownloadId = null;

      list = list.map(function(item) {
        return {
          url: item.url,
          filename: folder + item.filename
        };
      });

      var addListener = function() {
        chrome.downloads.onChanged.addListener(onChange);
      };

      var removeListener = function() {
        chrome.downloads.onChanged.removeListener(onChange);
      };

      var onChange = function(downloadDelta) {
        if (downloadDelta.id !== waitDownloadId || !downloadDelta.state) {
          return;
        }

        if (['interrupted', 'complete'].indexOf(downloadDelta.state.current) !== -1) {
          waitDownloadId = null;
          return onSuccess();
        }
      };

      addListener();

      var index = -1;
      var onSuccess = function() {
        index++;
        var item = list[index];
        if (!item) {
          removeListener();
          return;
        }

        return chrome.downloads.download({
          url: item.url,
          filename: item.filename
        }, function(downloadId) {
          waitDownloadId = downloadId;
        });
      };

      return onSuccess();
    },
    downloadList: function(message) {
      "use strict";
      var _this = this;
      var list = message.fileList;
      var folder = message.folder;

      if ((mono.isChrome || mono.isFirefox) && chrome.downloads && chrome.downloads.download) {
        _this.chromeListDownload(list, folder);
      } else {
        list.forEach(function(item) {
          _this.downloadFile({
            options: {
              url: item.url,
              filename: folder + item.filename
            }
          });
        });
      }
    },
    getUmmyIcon: function(message, cb) {
      "use strict";
      var icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAB90lEQVQ4EcVSy2oUURCtqm7HcYgmYDTiYxEEERdZGP0B0UVwEcSv8LHIb4gbQcjGlVtB40YhfkAWuhs0uFOIgjJomiEzztzue4+n7rTgH6SaoqpPnao6fW+LHLapC9hdPHMbKT1UTcsQWxDBnAAdFkuvQ6QR1cD0QAUVoF+0kKdXBoO32j959maK8V1LVDaBDXkwm9q32atz/hmRpIZb5STqPaDIjP/oFAS5Xu1l/MPCBZhxt09uSRykCn1QhmQr1MiSQ3TPGYdIMtwfZPh3MjkhlvOWOcuTrJQB5VJeR0g5HlzjMSSVpp7mtQGFBJjXwJp69AlqtlTW0bpQ6nNLbTdjSCIxNhkOqUBwBconZYWZr1G6RgXcRoI782k0rO681vVq15o6SGyCrFefbHVnS6eNkmcSyMlOvr48ernimjlf5WcUuP1zr7C7W090/twiMcjw+y95dWcjXRr7Sn6Ba8mmB1RQ/MwqOK2mg356FPFi4xGm4z8I40nOT434OanElDdWM2aH/eAtHOlz98XZRBch0uPnHPu4J9uPn+dNzNGTLho/Kj+D1gza12fl1RuEtlmaaWPiGkOK8k0mecB5Nnes8DZvdiwPgRVrmbAp19aI8Fe2ZSDN86aOk9OpkfiHqfKoap9JfMTWfcavvNXN+/H9G596uPYX83AWUVC6/FsAAAAASUVORK5CYII=';
      cb(icon);
    },
    getWarningIcon: function(message, cb) {
      "use strict";
      var icon;
      var color = message.color || '#c2c2c2';
      if (message.type === 'audio') {
        icon = '<svg width="21px" height="24px" viewBox="0 0 21 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M21,2.76923077 L21,17.6487288 C21,17.6487288 21,17.6487288 21,17.6487288 L21,18.4615385 L20.9068729,18.4615385 C20.723595,19.2712249 20.2716013,20.0865791 19.5669296,20.7680198 C17.9203537,22.360313 15.5176896,22.6184747 14.2004289,21.3446402 C12.8831682,20.0708056 13.1501309,17.7473503 14.7967068,16.1550571 C16.0602516,14.9331676 17.7690324,14.4969051 19.0909091,14.9356816 L19.0909091,14.9356816 L19.0909091,4.15384615 L7.63636364,6.92307692 L7.63636364,19.4948826 C7.63636364,19.4948826 7.63636364,19.4948826 7.63636364,19.4948826 L7.63636364,20.3076923 L7.5432365,20.3076923 C7.35995859,21.1173788 6.90796493,21.9327329 6.20329323,22.6141737 C4.55671732,24.2064669 2.15405328,24.4646286 0.836792552,23.190794 C-0.480468173,21.9169595 -0.213505501,19.5935041 1.43307041,18.0012109 C2.69661523,16.7793214 4.40539601,16.343059 5.72727273,16.7818354 L5.72727273,16.7818354 L5.72727273,6.46153846 L5.72727273,3.69230769 L21,0 L21,2.76923077 Z" fill="' + color + '"></path></svg>';
      } else
      if (message.type === 'playlist') {
        icon = '<svg width="24px" height="18px" viewBox="0 0 24 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M0,0 L0,3.6 L3.42857143,3.6 L3.42857143,0 L0,0 Z M0,7.2 L0,10.8 L3.42857143,10.8 L3.42857143,7.2 L0,7.2 Z M5.14285714,0 L5.14285714,3.6 L24,3.6 L24,0 L5.14285714,0 Z M5.14285714,7.2 L5.14285714,10.8 L20.5714286,10.8 L20.5714286,7.2 L5.14285714,7.2 Z M0,14.4 L0,18 L3.42857143,18 L3.42857143,14.4 L0,14.4 Z M5.14285714,14.4 L5.14285714,18 L22.2857143,18 L22.2857143,14.4 L5.14285714,14.4 Z" fill="' + color + '"></path></svg>';
      } else {
        // photo
        icon = '<svg width="24px" height="18px" viewBox="0 0 24 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M19.5,3 L21.0089096,3 C22.6582294,3 24,4.34288718 24,5.99942248 L24,15.0005775 C24,16.6556493 22.6608432,18 21.0089096,18 L2.99109042,18 C1.34177063,18 0,16.6571128 0,15.0005775 L0,5.99942248 C0,4.34435073 1.33915679,3 2.99109042,3 L7.5,3 C7.5,1.34651712 8.84187067,0 10.497152,0 L16.502848,0 C18.1583772,0 19.5,1.34314575 19.5,3 L19.5,3 Z M13.5,16.5 C16.8137087,16.5 19.5,13.8137087 19.5,10.5 C19.5,7.18629134 16.8137087,4.5 13.5,4.5 C10.1862913,4.5 7.5,7.18629134 7.5,10.5 C7.5,13.8137087 10.1862913,16.5 13.5,16.5 Z M13.5,15 C15.9852815,15 18,12.9852815 18,10.5 C18,8.0147185 15.9852815,6 13.5,6 C11.0147185,6 9,8.0147185 9,10.5 C9,12.9852815 11.0147185,15 13.5,15 Z" fill="' + color + '"></path></svg>';
      }
      cb('data:image/svg+xml;utf8,' + encodeURIComponent(icon));
    },
    checkUrlsOfOpenTabs: function(regExpList, callback) {
      "use strict";
      var getUrlList = mono.isGM ? function(cb) {
        cb([location.href]);
      } : mono.isChrome ? function(cb) {
        var urlList = [];
        chrome.tabs.query({}, function(tabs) {
          tabs.forEach(function(tab) {
            urlList.push(tab.url);
          });
          cb(urlList);
        });
      } : mono.isFirefox ? function(cb) {
        var urlList = [];
        if (mono.isFirefoxMobile) {
          return cb(urlList);
        }

        chrome.tabs.query({}, function(tabs) {
          tabs.forEach(function(tab) {
            urlList.push(tab.url);
          });
          cb(urlList);
        });
      } : mono.isOpera ? function(cb) {
        var urlList = [];
        var oTabs = opera.extension.tabs.getAll();
        oTabs.forEach(function(tab) {
          urlList.push(tab.url);
        });
        cb(urlList);
      } : mono.isSafari ? function(cb) {
        var urlList = [];

        safari.application &&
          safari.application.activeBrowserWindow &&
          safari.application.activeBrowserWindow.tabs &&
          safari.application.activeBrowserWindow.tabs.forEach(function(tab) {
            if (!tab.url) {
              return 1;
            }
            urlList.push(tab.url);
          });

        cb(urlList);
      } : function(cb) {
        cb([]);
      };

      getUrlList(function(urlList) {
        var foundUrlList = [];
        urlList.forEach(function(url) {
          regExpList.forEach(function(regexp) {
            if (url.search(regexp) !== -1) {
              foundUrlList.push(url);
            }
          });
        });
        callback(foundUrlList);
      });
    },
    getData: function(message, cb) {
      "use strict";
      var url = message.url;
      if (!url) {
        return cb();
      }

      mono.request({
        url: url
      }, function(err, resp, data) {
        if (err) {
          return cb();
        }
        cb(data);
      });
      return true;
    }
  };

  engine.utils = bg_utils;
  (function() {
    var language = {};
    var preference = {};
    var varCache = {
      icons: {},
      activeTabInfo: {},
      helperName: ''
    };
    var menuContainer = undefined;

    var translatePage = function() {
      var elList = menuContainer.querySelectorAll('*[data-i18n]');
      for (var i = 0, len = elList.length; i < len; i++) {
        var el = elList[i];
        var key = el.dataset.i18n;
        el.textContent = language[key];
        if (el.classList.contains('label')) {
          el.title = language[key];
        }
      }
    };

    var onModuleToggle = function() {
      var tabInfo = varCache.activeTabInfo;

      var state = varCache.moduleTrigger.classList.contains('disabled') ? 1 : 0;
      tabInfo.state = state;

      setCheckboxState(state, 1);

      preference[tabInfo.prefKey] = state;

      mono.sendMessage({
        action: 'viaMenu_' + 'changeState',
        state: state ? 1 : 0,
        prefKey: tabInfo.prefKey,
        moduleName: tabInfo.moduleName,
        needInclude: tabInfo.isNotResponse
      });

      tabInfo.isNotResponse = false;

      updateMenuItem(tabInfo);
    };

    var menuItemAction = function(event) {
      event.preventDefault();
      event.stopPropagation();
      var node = this;

      if (node.classList.contains('inactive')) {
        return;
      }

      var action = node.dataset.action;

      var isModule = node.classList.contains('module');

      if (action === 'enableModule') {
        return onModuleToggle();
      } else {
        mono.sendMessage({
          action: (isModule ? 'viaMenu_' : '') + action
        });
      }

      if (mono.isGM) {
        _menu.hideMenuItems();
        return;
      }
      if (mono.isSafari) {
        safari.extension.popovers[0].hide();
        return;
      }
      window.close();
    };

    var setItemState = function(className, show) {
      var li = menuContainer.querySelectorAll('div.' + className);
      for (var i = 0; i < li.length; i++) {
        if (show) {
          li[i].classList.remove('inactive');
        } else {
          li[i].classList.add('inactive');
        }
      }
    };

    var setModuleItemState = function(moduleName, show) {
      if (!show) {
        return setItemState('module', false);
      }

      var li = menuContainer.querySelectorAll('div.module');
      for (var i = 0; i < li.length; i++) {
        if (li[i].classList.contains(moduleName)) {
          li[i].classList.remove('inactive');
        } else {
          li[i].classList.add('inactive');
        }
      }
    };

    var safariBlankLink = function(e) {
      e.preventDefault();

      mono.openTab(this.href, true);
    };

    var updateSafariLinks = function() {
      var links = menuContainer.querySelectorAll('a[href][target="_blank"]');
      for (var i = 0, len = links.length; i < len; i++) {
        links[i].removeEventListener('click', safariBlankLink);
        links[i].addEventListener('click', safariBlankLink);
      }
    };

    var bindSocialBtn = function() {
      var targetUrl = 'http://savefrom.net/user.php';
      var url = encodeURIComponent(targetUrl);
      var image = encodeURIComponent('http://savefrom.net/img/icon_100.png');
      var title = encodeURIComponent(language.extName);
      var desc = encodeURIComponent(language.socialDesc);
      var btnList = {
        vk: {
          network: 'vkontakte',
          title: language.shareIn.replace('%w', 'VK'),
          href: 'http://vk.com/share.php?url=' + url + '&image=' + image + '&title=' + title + '&description=' + desc
        },
        ok: {
          network: 'odnoklassniki',
          title: language.shareIn.replace('%w', 'OK.ru'),
          href: 'http://www.odnoklassniki.ru/dk?st.cmd=addShare&st.s=1&st._surl=' + url + '&st.comments=' + desc
        },
        mailru: {
          network: 'mail.ru',
          title: language.shareIn.replace('%w', 'Mail.ru'),
          href: 'http://connect.mail.ru/share?url=' + url + '&title=' + title + '&description=' + desc + '&imageurl=' + image
        },
        tw: {
          network: 'twitter',
          title: language.shareIn.replace('%w', 'Twitter'),
          href: 'https://twitter.com/intent/tweet?text=' + title + '&url=' + url
        },
        fb: {
          network: 'facebook',
          title: language.shareIn.replace('%w', 'Facebook'),
          href: 'http://www.facebook.com/sharer.php?s=100&p[url]=' + url + '&p[title]=' + title + '&p[summary]=' + desc + '&p[images][0]=' + image
        },
        gp: {
          network: 'google+',
          title: language.shareIn.replace('%w', 'Google+'),
          href: 'https://plus.google.com/share?url=' + url
        },
        lj: {
          network: 'livejournal',
          title: language.shareIn.replace('%w', 'Livejournal'),
          href: 'http://www.livejournal.com/update.bml?subject=' + title + '&event=' + desc + ' ' + url
        }
      };
      for (var item in btnList) {
        var link = menuContainer.querySelector('.social-btn.' + item);
        if (!link) {
          continue;
        }
        link.title = btnList[item].title;
        link.href = btnList[item].href;
        link.dataset.network = btnList[item].network;
      }
      link.parentNode.addEventListener('click', function(e) {
        var btn = e.target;
        if (!btn.classList.contains('social-btn')) {
          return;
        }
        var network = btn.dataset.network;
        mono.sendMessage({
          action: 'track',
          t: 'social',
          st: targetUrl,
          sa: 'share',
          sn: network
        });
      });
    };

    var setModuleBtnState = function(tabInfo) {
      if (['odnoklassniki'].indexOf(tabInfo.moduleName) !== -1) {
        setItemState('bookmarklet', false);
      } else {
        setItemState('bookmarklet', true);
      }

      setModuleItemState(tabInfo.moduleName, tabInfo.state);

      if (tabInfo.state && tabInfo.moduleName === 'youtube') {
        var url = tabInfo.url;

        var isPlaylist = /\/playlist\?|[?&]list=/.test(url);
        if (!isPlaylist) {
          isPlaylist = /(user|channel|c|show)\/[^\/]+(\/feed|\/featured|\/videos|$)/i.test(url);
        }
        if (!isPlaylist) {
          isPlaylist = /\/(feed)\/(trending|subscriptions|history)/i.test(url);
        }

        setItemState('plYoutube', !!isPlaylist);
      }
    };

    var setCheckBoxModuleState = function(tabInfo) {
      "use strict";
      var checkBoxIsEnable = false;
      var checkBoxState = false;
      if (['savefrom'].indexOf(tabInfo.moduleName) !== -1) {
        checkBoxState = 'force';
      } else
      if (tabInfo.moduleName) {
        checkBoxState = !!tabInfo.state;
        checkBoxIsEnable = true;
      }
      setItemState('enableModule', checkBoxIsEnable);
      setCheckboxState(checkBoxState);
    };

    var onGetTabInfo = function(tabInfo, force) {
      varCache.activeTabInfo = tabInfo = tabInfo || {};

      setCheckBoxModuleState(tabInfo);
      setModuleBtnState(tabInfo);

      if (!force) {
        var onResponse = function(moduleInfo) {
          "use strict";
          clearTimeout(timeout);
          tabInfo.isNotResponse = !moduleInfo;

          for (var key in moduleInfo) {
            tabInfo[key] = moduleInfo[key];
          }

          setCheckBoxModuleState(tabInfo);
          setModuleBtnState(tabInfo);
        };
        var timeout = setTimeout(onResponse, 250);
        mono.sendMessage({
          action: 'getActiveTabModuleInfo',
          url: tabInfo.url
        }, onResponse);
      }
    };

    var updateMenuItem = function(tabInfo) {
      varCache.activeTabInfo = {};

      if (tabInfo) {
        onGetTabInfo(tabInfo, 1);
      } else {
        mono.sendMessage({
          action: 'getActiveTabInfo'
        }, onGetTabInfo);
      }
    };

    var setIconState = function(el, state) {
      var path = el.querySelector('path');
      if (state === 'hover') {
        path.setAttribute('fill', '#ffffff');
      } else
      if (state === 'active') {
        path.setAttribute('fill', '#AAAAAA');
      } else {
        var type = el.getAttribute('data-type');
        if (type === 'downloadMP3Files') {
          path.setAttribute('fill', '#00CCFF');
        } else
        if (type === 'downloadPlaylist') {
          path.setAttribute('fill', '#77D1FA');
        } else
        if (type === 'downloadPhotos') {
          path.setAttribute('fill', '#88cb66');
        } else
        if (type === 'showAboutPage') {
          path.setAttribute('fill', '#ADE61B');
        } else
        if (type === 'updateLinks') {
          path.setAttribute('fill', '#CB7FBD');
        } else
        if (type === 'downloadFromCurrentPage') {
          path.setAttribute('fill', '#CB7FBD');
        }
      }
    };

    var getAboutPage = function() {
      "use strict";
      return mono.create(document.createDocumentFragment(), {
        append: [
          mono.create('p', {
            text: language.aboutDescription
          }),
          mono.create('a', {
            href: 'http://savefrom.net/faq.php#supported_resourses',
            target: '_blank',
            text: language.aboutSupported,
            style: {
              display: 'block'
            }
          }),
          mono.create('a', {
            href: 'http://savefrom.net/user.php?helper=' + varCache.helperName,
            target: '_blank',
            text: language.homePage,
            style: {
              display: 'block'
            }
          })
        ]
      });
    };

    var updateDescription = function(action, label) {
      var desc = varCache.desc;
      var text = varCache.deskText;
      var title = varCache.descTitel;
      var more = varCache.descMore;
      desc.dataset.page = action;

      var icon = varCache.icons[action];
      var subIcon = desc.querySelector('.icon');
      if (icon) {
        var _icon = icon.cloneNode(true);
        setIconState(_icon, 'active');
        if (subIcon) {
          subIcon.parentNode.replaceChild(_icon, subIcon);
        }
        subIcon.style.visibility = 'visible';
      } else {
        subIcon.style.visibility = 'hidden';
      }

      if (action === 'showAboutPage') {
        title.textContent = language.aboutTitle;
        text.textContent = '';
        text.appendChild(getAboutPage());
        more.style.display = 'none';
      } else {
        title.textContent = label;
        text.textContent = language['menu' + mono.capitalize(action)] || '';
        more.style.display = 'block';
      }

      if (mono.isSafari) {
        updateSafariLinks();
      }
    };

    var onReady = function() {
      translatePage();

      varCache.descMore.href = 'http://savefrom.net/user.php?helper=' + varCache.helperName;

      var btnList = menuContainer.querySelectorAll('div[data-action]');
      for (var i = 0; i < btnList.length; i++) {
        var icon = btnList[i].querySelector('svg');
        if (icon) {
          varCache.icons[btnList[i].dataset.action] = icon;
          setIconState(icon);
        }

        if (btnList[i].style.display === 'none') {
          continue;
        }

        mono.create(btnList[i], {
          on: [
            ['click', menuItemAction],
            ['mouseenter', function() {
              "use strict";
              var action = this.dataset.action;

              var icon = varCache.icons[action];
              icon && setIconState(icon, 'hover');

              var span = this.querySelector('span');
              var title = span && span.textContent || '';

              updateDescription(action, title);
            }],
            ['mouseleave', function() {
              "use strict";
              var action = this.dataset.action;

              var icon = varCache.icons[action];
              icon && setIconState(icon);
            }]
          ]
        });
      }

      bindSocialBtn();

      if (mono.isSafari) {
        updateSafariLinks();
      }

      updateDescription('showAboutPage');

      updateMenuItem();

      menuContainer.classList.remove('loading');
    };

    var setCheckboxState = function(state, byUser) {
      if (byUser) {
        varCache.moduleTrigger.classList.add('sf-transition');
      }
      if (state === 'force') {
        varCache.moduleTrigger.classList.add('enableForce');
      } else {
        varCache.moduleTrigger.classList.remove('enableForce');
      }
      if (state) {
        varCache.moduleTrigger.classList.remove('disabled');
        varCache.moduleTrigger.nextElementSibling.textContent = language.disableModule;
      } else {
        varCache.moduleTrigger.classList.add('disabled');
        varCache.moduleTrigger.nextElementSibling.textContent = language.enableModule;
      }
      if (varCache.desc.dataset.page !== 'showAboutPage') {
        updateDescription('enableModule', state ? language.disableModule : language.enableModule);
      }
    };

    var tutorial = {
      tutorialSlides: null,
      show: function() {
        "use strict";
        if (!preference.onceShowYtTutorial) {
          return;
        }

        var onClose = function() {
          mono.sendMessage({
            action: 'updateOption',
            key: 'onceShowYtTutorial',
            value: preference.onceShowYtTutorial = 0
          });
          mono.sendMessage({
            action: 'setIconBadge',
            text: ''
          });
        };

        if (!tutorial.tutorialSlides) {
          return onClose();
        }

        return tutorial.tutorialSlides.show({
          container: menuContainer,
          width: 482,
          height: 404 + (mono.isGM ? 2 : 0),
          padding: 4,
          slideList: tutorial.tutorialSlides.getYtSlideList('black'),
          onClose: onClose,
          trackId: 'Menu',
          boxStyle: {
            backgroundColor: 'transparent'
          },
          containerStyle: {
            borderRadius: '3px',
            backgroundColor: 'rgba(0, 104, 255, 0.9)',
            padding: 0,
            margin: '4px',
            boxShadow: 'none'
          },
          slideStyle: {
            backgroundColor: 'transparent',
            borderRadius: 0
          },
          leftBtnStyle: {
            top: '4px',
            left: '4px'
          },
          rightBtnStyle: {
            top: '4px',
            right: '4px'
          },
          closeBtnStyle: {
            backgroundColor: '#fff',
            color: 'rgba(0, 104, 255, 0.9)'
          },
          cssStyle: {
            ' .sf-dots': {
              paddingTop: '2px'
            },
            ' .sf-dot i': {
              backgroundColor: '#fff'
            },
            ' .sf-dot.active i': {
              backgroundColor: 'transparent',
              borderRadius: '6px',
              margin: '-1px',
              width: '6px',
              height: '6px',
              border: '2px solid #fff'
            },
            ' .sf-slider-conteiner span': {
              color: '#fff !important'
            },
            ' .sf-slider-conteiner a': {
              color: '#fff !important'
            }
          },
          arrowColor: '#fff',
          arrowColorActive: '#fff',
          onResize: function(details) {
            details.box.style.position = 'absolute';
          },
          withOpacity: true,
          withDelay: 250,
          onShow: function() {
            mono.isSafari && updateSafariLinks();

            mono.sendMessage({
              action: 'setIconBadge',
              text: '?'
            });
          }
        });
      }
    };

    var setVersion = function(version, lastVersion) {
      "use strict";
      var versionNode = varCache.desc.querySelector('.version');

      versionNode.textContent = '';

      versionNode.appendChild(mono.create('span', {
        text: language.aboutVersion + ' ' + version
      }));

      if (lastVersion && lastVersion !== version) {
        versionNode.appendChild(mono.create('a', {
          text: language.updateTo.replace('%d', lastVersion),
          href: 'http://savefrom.net/user.php?helper=' + varCache.helperName + '&update=' + version,
          target: '_blank'
        }));
      }
    };

    var run = function(parent) {
      menuContainer = (parent || document).querySelector('.sf-menu-container');
      if (!menuContainer) {
        return;
      }

      setTimeout(function() {
        menuContainer.classList.remove('loading');
      }, 1000);

      varCache.list = menuContainer.querySelector('.sf-menu-list');
      varCache.desc = menuContainer.querySelector('.sf-menu-desc');
      varCache.moduleTrigger = menuContainer.querySelector('.sf-checkbox');
      varCache.descTitel = varCache.desc.querySelector('.title');
      varCache.deskText = varCache.desc.querySelector('.desc');
      varCache.descMore = varCache.desc.querySelector('.more');

      varCache.list.style.height = varCache.list.offsetHeight + 'px';

      mono.sendMessage({
        action: 'getMenuDetails'
      }, function(response) {
        language = response.language;
        preference = response.preferences;

        mono.global.language = language;
        mono.global.preference = preference;

        varCache.helperName = response.helperName;

        setVersion(response.version, response.lastVersion);

        if (['en', 'uk', 'ru'].indexOf(language.lang) === -1) {
          menuContainer.classList.add('no-poll');
        }

        tutorial.show();

        onReady();
      });
    };

    mono.onReady(function() {
      if (mono.isGM) {
        _menu.initMenu = run;
      } else {
        run();
      }
    });

    //@insert
  })();
  var dailymotion_com_embed = {
    getDailymotionLinks: function(request, callback) {
      var _this = dailymotion_com_embed;
      var callback_links = function(data) {
        if (!data) {
          data = {};
        }

        _this.addUmmyLinks(data.links, request.extVideoId);

        var response = {
          action: request.action,
          extVideoId: request.extVideoId,
          links: data.links,
          title: data.title,
          duration: data.duration,
          thumb: data.thumb
        };

        callback(response);
      };

      dailymotion_com_embed.getEmbedVideoInfo(request.extVideoId, request.metadata, callback_links);
      return true;
    },

    /**
     * @private
     */
    addUmmyLinks: function(links, videoId) {
      if (engine.preferences.showUmmyItem && links && links.length) {
        links.push({
          url: 'ummy://www.dailymotion.com/video/' + videoId + '?sf_type=audio',
          type: 'ummyAudio',
          extra: 'ummy',
          videoId: 'dm-' + videoId
        });
      }
    },

    readDmMetadata: function(metadata, noRead) {
      "use strict";
      if (!metadata.qualities) {
        return;
      }

      delete metadata.qualities.auto;

      var qualities = metadata.qualities;

      var links = [];
      var info = {
        title: metadata.title,
        duration: metadata.duration,
        thumb: metadata.poster_url,
        links: undefined
      };

      for (var size in qualities) {
        var linkList = qualities[size];
        if (!Array.isArray(linkList)) continue;

        for (var i = 0, item; item = linkList[i]; i++) {
          if (!/mp4|flv/.test(item.type) || !item.url) {
            continue;
          }
          if (!noRead) {
            var linkObj = dailymotion_com_embed.readLink(item.url);
            linkObj && links.push(linkObj);
          } else {
            links.push(item.url);
          }
        }
      }

      if (links.length) {
        if (!noRead) {
          links.sort(function(a, b) {
            return a.height < b.height;
          });
        }
        info.links = links;
      }

      return info;
    },

    getPlayerV5Links: function(text, cb, noRead) {
      "use strict";
      var metadata = null;
      try {
        var scriptList = mono.getPageScript(text, /playerV5/);
        scriptList.some(function(script) {
          "use strict";
          var jsonList = mono.findJson(script);
          return jsonList.some(function(json) {
            if (json && json.metadata) {
              metadata = json.metadata;
              return true;
            }
          });
        });

        if (!metadata) {
          throw 'Metadata is not found!';
        }
      } catch (e) {
        return cb();
      }

      var info = this.readDmMetadata(metadata, noRead);
      cb(info);
    },

    readLink: function(url) {
      url = url.replace(/\\\//g, '/');
      url = url.replace(/\@\@[\w\-]+$/, '');
      var size = '';
      var t = url.match(/\/cdn\/\w+\-(\d+x\d+)\//i);
      if (t && t.length > 1) {
        size = t[1];
      } else {
        t = url.match(/\D(\d+x\d+)\D/i);
        if (t && t.length > 1) {
          size = t[1];
        }
      }

      var ext = 'FLV';
      t = url.match(/\.(\w{1,6})(?:$|\?)/);
      if (t && t.length > 1) {
        ext = t[1].toUpperCase();
      }

      if (size !== '80x60') {
        var height = parseInt(size.split('x').slice(-1)[0]);
        return {
          url: url,
          name: ext + ' ' + height,
          ext: ext,
          info_url: '',
          height: height
        };
      }
    },

    getLinks: function(text, cb, noRead) {
      var about = {};
      var links = [];
      var info = text.match(/(?:var|,)\s*info\s*=\s*\{(.*?)\}\s*(?:;|,\s*\w+\s*=)/i);

      if (!info || info.length < 2) {
        return dailymotion_com_embed.getPlayerV5Links(text, cb, noRead);
      }
      info = info[1];
      try {
        info = JSON.parse('{' + info + '}');
        if (!info) {
          return cb();
        }
        about.title = info.title;
        about.duration = info.duration;
        about.thumb = info.thumbnail_medium_url;
        for (var i in info) {
          if (!info.hasOwnProperty(i)) {
            continue;
          }
          if (typeof info[i] !== 'string') {
            continue;
          }
          if (info[i].search(/^https?:\/\/[^\s\"]+\.(mp4|flv)(\?|$)/) > -1) {
            if (noRead) {
              links.push(info[i]);
            } else {
              var link = dailymotion_com_embed.readLink(info[i]);
              if (link !== undefined) {
                links.push(link);
              }
            }
          }
        }
      } catch (e) {}
      if (links.length > 0) {
        if (!noRead) {
          links.sort(function(a, b) {
            return a.height < b.height;
          });
        }
        about.links = links;
      }
      cb(about);
    },

    getDailymotionEmbedVideoInfoMsg: function(message, cb) {
      mono.request({
        url: message.url
      }, function(err, resp, data) {
        if (err || !data) {
          return cb();
        }

        dailymotion_com_embed.getLinks(data, cb, true);
      });
      return true;
    },

    getEmbed: function(url, cb) {
      mono.request({
        url: url
      }, function(err, resp, data) {
        if (err || !data) {
          return cb();
        }

        dailymotion_com_embed.getLinks(data, cb);
      });
    },

    getEmbedVideoInfo: function(id, metadata, callback) {
      "use strict";
      if (metadata) {
        var info = this.readDmMetadata(metadata);
        if (info && info.links && info.links.length) {
          return callback(info);
        }
      }

      var url = "http://www.dailymotion.com/embed/video/" + id;
      dailymotion_com_embed.getEmbed(url, callback);
    }
  };

  engine.modules.dailymotion = dailymotion_com_embed;
  var odnoklassniki_ru_embed = {
    getOdnoklassnikiLinks: function(request, callback) {
      function callback_links(links) {
        var response = {
          action: request.action,
          extVideoId: request.extVideoId,
          links: links,
          title: request.title
        };

        callback(response);
      }

      odnoklassniki_ru_embed._getOdnoklassnikiLinks(request.extVideoId, callback_links);
      return true;
    },

    getOdnoklassnikiAudioLinks: function(request, callback) {
      function callback_links(data) {
        var response = {
          action: request.action,
          trackId: request.trackId,
          jsessionId: request.jsessionId,
          data: data
        };

        callback(response);
      }

      odnoklassniki_ru_embed._getOdnoklassnikiAudioLinks(request.url, request.trackId, request.jsessionId, callback_links);
      return true;
    },

    _getOdnoklassnikiLinks: function(extVideoId, callback) {
      if (!extVideoId) {
        callback(null);
        return;
      }

      var url = 'http://in.video.mail.ru/cgi-bin/video/oklite?eid=' + extVideoId;

      mono.request({
        url: url
      }, function(err, resp, data) {
        if (err || !data) {
          return callback(null);
        }

        var u = 'http://www.okcontent.video.mail.ru/media/';

        var host = data.match(/\$vcontentHost=([^\s"'<>]+)/i);
        if (host && host.length > 1) {
          u = 'http://' + host[1] + '/media/';
        }

        u += extVideoId;

        var links = [];

        var quality = '';
        var qulityMatch = data.match(/\$height=([0-9]+)/);
        if (qulityMatch && qulityMatch.length > 1) {
          quality = qulityMatch[1];
        }

        links.push({
          url: u + '-v.mp4',
          name: 'SD',
          ext: 'FLV',
          subname: quality
        });

        if (data.search(/\$HDexist=1/i) > -1) {
          quality = '';
          qulityMatch = data.match(/\$HDheight=([0-9]+)/);
          if (qulityMatch && qulityMatch.length > 1) {
            quality = qulityMatch[1];
          }

          links.push({
            url: u + '-hv.mp4',
            name: 'HD',
            ext: 'MP4',
            subname: quality
          });
        }

        if (links) {
          callback(links);
        }
      });
    },

    _getOdnoklassnikiAudioLinks: function(pageUrl, trackId, jSessionId, cb) {
      if (!trackId || !jSessionId) {
        return cb(null);
      }

      mono.request({
        url: 'http://wmf1.ok.ru/play;jsessionid=' + jSessionId + '?tid=' + trackId,
        json: true
      }, function(err, resp, json) {
        if (err || !json) {
          return cb(null);
        }

        cb(json);
      });
    },

    getOkAudioListLinks: function(msg, cb) {
      var responseList = [];
      var trackIdList = msg.trackIdArr;
      var jSessionId = msg.jsessionId;
      if (!Array.isArray(trackIdList) || typeof jSessionId !== 'string' || !trackIdList.length) {
        return cb(responseList);
      }

      var waitCount = trackIdList.length;
      var readyCount = 0;
      var onReady = function() {
        readyCount++;
        if (readyCount !== waitCount) {
          return;
        }
        return cb(responseList);
      };
      var onGetData = function(data) {
        if (data) {
          responseList.push(data);
        }
        onReady();
      };
      for (var i = 0, trackId; trackId = trackIdList[i]; i++) {
        this._getOdnoklassnikiAudioLinks(undefined, trackId, jSessionId, onGetData);
      }
      return true;
    },

    getClipyouLinks: function(id, hash, quality, title, cb) {
      mono.request({
        url: 'http://media.clipyou.ru/api/player/secure_link?record_id=' + id + '&type=mp4&resource_hash=' + hash,
        json: true
      }, function(err, resp, json) {
        if (err || !json || !Array.isArray(json.data) || !json.data.length) {
          return cb();
        }

        var links = [];
        json.data.forEach(function(item) {
          links.push({
            quality: quality,
            url: item,
            title: title
          });
        });
        cb(links);
      });
    },

    getClipyouHash: function(id, cb) {
      mono.request({
        url: 'http://media.clipyou.ru/api/player_data.json?id=' + id
      }, function(err, resp, data) {
        if (err || !data) {
          return cb();
        }

        data = data.match('resource_hash".?:.?"([^"]*)"');
        if (!data || data.length < 2) {
          return cb();
        }
        var hash = data[1];
        cb(hash);
      });
    },

    getPladformVideo: function(message, cb) {
      "use strict";
      var response = {
        action: message.action,
        extVideoId: message.extVideoId,
        links: [],
        title: message.title
      };

      var done = function() {
        cb(response);
      };

      var playerId = message.extVideoId.playerId;
      var videoId = message.extVideoId.videoId;

      mono.request({
        url: 'http://out.pladform.ru/getVideo?pl=' + playerId + '&videoid=' + videoId,
        xml: true
      }, function(err, resp, xml) {
        if (err || !xml) {
          return done();
        }

        var srcList = xml.querySelectorAll('src');
        if (srcList.length === 0) {
          return done();
        }

        var cover = xml.querySelector('cover') || undefined;
        if (cover && (cover = cover.textContent) && cover.substr(0, 2) === '//') {
          cover = 'http:' + cover;
        }

        var time = xml.querySelector('time') || undefined;
        time = time && time.textContent;

        var title = xml.querySelector('title');
        title = title && title.textContent;
        if (title) {
          response.title = title;
        }

        var firstLink = srcList[0];
        var type = firstLink.getAttribute('type');
        var id = firstLink.textContent || '';
        var quality = firstLink.getAttribute('quality');
        if (firstLink) {
          if (type === 'clipyou') {
            return odnoklassniki_ru_embed.getClipyouHash(id, function(hash) {
              if (!hash) {
                return done();
              }

              odnoklassniki_ru_embed.getClipyouLinks(id, hash, quality, title, function(links) {
                response.links = links;

                done();
              });
            });
          } else
          if (type === 'rutube') {
            var externalEmbed = xml.querySelector('external_embed');
            externalEmbed = externalEmbed && externalEmbed.textContent;
            if (externalEmbed) {
              response.action = 'getRutubeLinks';
              response.links = [externalEmbed];
            }

            return done();
          }
        }

        var qualityList = ['ld', 'sd'];
        var sizeList = ['360', '720'];

        for (var i = 0, src; src = srcList[i]; i++) {
          id = src.textContent || '';
          quality = src.getAttribute('quality');

          if (/^\d+p$/.test(quality)) {
            quality = quality.match(/^(\d+)p$/)[1];
          }

          var qIndex = qualityList.indexOf(quality);
          if (qIndex !== -1) {
            quality = sizeList[qIndex];
          }

          type = src.getAttribute('type');

          if (type === 'video') {
            response.links.push({
              url: id,
              quality: quality,
              title: title,
              cover: cover,
              duration: time
            });
          }
        }

        return done();
      });
      return true;
    },

    getOkMetadata: function(message, cb) {
      var url = message.url;
      if (!url) {
        return cb();
      }
      mono.request({
        method: 'POST',
        url: url,
        json: true
      }, function(err, resp, json) {
        if (err || !json) {
          return cb();
        }

        cb(json);
      });
      return true;
    },

    getOkViaMobile: function(message, cb) {
      "use strict";
      var metadata = message.metadata;
      var params = {
        'st.cmd': 'movieLayer',
        'st.mvId': message.mvId
      };
      var url = 'http://m.ok.ru/dk?' + mono.param(params);

      var response = {
        action: message.action,
        links: null,
        title: metadata.movie.title
      };

      mono.request({
        url: url
      }, function(err, resp, data) {
        if (err || !data) {
          return cb();
        }

        var r = new RegExp('href="([^"]+st\\.cmd=moviePlaybackRedirect[^"]+st\\.mvid=' + message.mvId + '[^"]+)"');
        var moviePlaybackRedirect = data.match(r);
        moviePlaybackRedirect = moviePlaybackRedirect && moviePlaybackRedirect[1];
        if (!moviePlaybackRedirect) {
          return cb();
        }

        moviePlaybackRedirect = mono.fileName.decodeSpecialChars(moviePlaybackRedirect);

        response.links = [{
          url: moviePlaybackRedirect
        }];

        if (!/st.mq=\d+/.test(moviePlaybackRedirect)) {
          return cb(response);
        }

        var videos = metadata.videos;
        if (!videos || !videos.length) {
          return cb(response);
        }

        videos.forEach(function(item) {
          if (!item.url) {
            return;
          }

          var params = mono.parseUrl(item.url);
          if (!params.type) {
            return;
          }

          item.url = moviePlaybackRedirect.replace(/(st.mq=)\d+/, '$1' + params.type);
        });

        response.links = videos;

        cb(response);
      });
      return true;
    },

    okDirectOrMobile: function(message, cb) {
      "use strict";
      var metadata = message.metadata;
      var url = null;
      metadata.videos && metadata.videos.some(function(item) {
        if (item.url) {
          url = item.url;
          return true;
        }
      });

      var onAbort = function() {
        message.action = 'getOkViaMobile';
        odnoklassniki_ru_embed.getOkViaMobile(message, cb);
      };

      if (!url) {
        onAbort();
        return true;
      }

      mono.request({
        url: url,
        type: 'HEAD'
      }, function(err) {
        if (err) {
          return onAbort();
        }

        message.action = 'getOkViaMobileNoWrap';
        message.links = metadata.videos;
        return cb(message);
      });
      return true;
    }
  };

  engine.modules.odnoklassniki = odnoklassniki_ru_embed;
  var soundcloud_com_embed = {
    getSoundcloudTrackInfo: function(request, callback) {
      function callback_links(data, isValid) {
        var response = {
          action: request.action,
          trackUrl: request.trackUrl,
          client_id: request.client_id,
          data: data,
          checkLinks: isValid
        };

        callback(response);
      }

      soundcloud_com_embed._getSoundcloudTrackInfo(request.trackUrl, request.client_id, callback_links);
      return true;
    },

    _getSoundcloudTrackInfo: function(trackUrl, client_id, callback) {
      if (!trackUrl || !client_id) {
        callback(null);
        return;
      }

      var url = 'http://api.soundcloud.com/resolve.json?url=' + trackUrl +
        '&client_id=' + encodeURIComponent(client_id);

      mono.request({
        url: url,
        headers: {
          Referer: url
        },
        json: true
      }, function(err, resp) {
        var json = resp.body;
        if (err || !json) {
          return callback();
        }

        soundcloud_com_embed.checkSoundcloudLinks(json, client_id, callback);
      });
    },

    checkSoundcloudLinks: function(data, client_id, cb) {
      if (!data) {
        return cb();
      }
      var info = data;

      if (info.kind !== 'track' && info.tracks && info.tracks.length === 1) {
        info = info.tracks[0];
      }

      if (info.kind === 'track' && info.stream_url) {
        soundcloud_com_embed.validateSoundcloudTrackUrl(info.stream_url, client_id, function(isValid) {
          cb(data, isValid);
        });
        return;
      }

      if (info.tracks && info.tracks[0]) {
        soundcloud_com_embed.validateSoundcloudTrackUrl(info.tracks[0].stream_url, client_id, function(isValid) {
          cb(data, isValid);
        });
        return;
      }

      return cb(data);
    },

    validateSoundcloudTrackUrl: function(url, client_id, cb) {
      url += (url.indexOf('?') === -1) ? '?' : '&';
      url += 'client_id=' + client_id;
      mono.request({
        url: url,
        type: 'HEAD'
      }, function(err) {
        cb(!err);
      });
    }
  };

  engine.modules.soundcloud = soundcloud_com_embed;
  var vimeo_com_embed = {
    getVimeoLinks: function(request, callback) {
      "use strict";

      function callback_links(links, title, thumb) {
        var response = {
          action: request.action,
          extVideoId: request.extVideoId,
          links: links,
          title: title,
          thumb: thumb
        };

        callback(response);
      }

      vimeo_com_embed._getVimeoLinks(request.extVideoId, request.url, callback_links);
      return true;
    },
    _getVimeoLinks: function(videoId, url, callback) {
      "use strict";
      vimeo_com_embed.getVimeoNoEmbedLinks(videoId, url, function(links, title, thumb) {
        if (links) {
          return callback(links, title, thumb);
        }

        vimeo_com_embed.getVimeoEmbedLinks(videoId, callback);
      });
    },
    getVimeoEmbedLinks: function(videoId, callback) {
      "use strict";
      var abort = function() {
        return callback(null, '', '');
      };

      if (!videoId) {
        return abort();
      }

      mono.request({
        url: 'https://player.vimeo.com/video/' + videoId
      }, function(err, resp, data) {
        if (err || !data) {
          return abort();
        }

        var jsonList = mono.findJson(data, [/"files":/]);
        var config = null;
        jsonList.some(function(obj) {
          "use strict";
          if (!obj.video || !obj.request || !obj.request.files) {
            return;
          }

          config = obj;
          return true;
        });

        data = vimeo_com_embed.getLinksFromConfig(config);
        if (data) {
          return callback(data.links, data.title, data.thumb);
        }

        return abort();
      });
    },
    getVimeoConfig: function(url, cb) {
      "use strict";
      var abort = function() {
        return cb(null, '', '');
      };

      mono.request({
        url: url
      }, function(err, resp, data) {
        if (err || !data) {
          return abort();
        }

        data = vimeo_com_embed.getVimeoDataFromConfig(data);
        if (data) {
          return cb(data.links, data.title, data.thumb);
        }

        return abort();
      });
    },
    getClipPageConfig: function(data, cb) {
      "use strict";
      var abort = function() {
        return cb(null, '', '');
      };

      var configUrl = null;
      var scriptList = mono.getPageScript(data, /['"]config_url['"]\s*:\s*/);
      scriptList.some(function(script) {
        var configList = mono.findJson(script, /['"]config_url['"]\s*:\s*/);
        return configList.some(function(config) {
          if (config.player) {
            configUrl = config.player.config_url;
            if (configUrl) {
              return true;
            }
          }
        });
      });

      if (configUrl) {
        return vimeo_com_embed.getVimeoConfig(configUrl, cb);
      }

      return abort();
    },
    getVimeoNoEmbedLinks: function(videoId, url, cb) {
      "use strict";
      var abort = function() {
        return cb(null, '', '');
      };

      if (videoId && url) {
        var isReview = /vimeo\.com\/[^\/]+\/review\/\d+/i.test(url);
        var isPrivate = /vimeo\.com\/\d+\/\w+/i.test(url);
        if (!isReview && !isPrivate) {
          url = null;
        }
      }

      mono.request({
        url: url || 'https://vimeo.com/' + videoId
      }, function(err, resp, data) {
        if (err || !data) {
          return abort();
        }

        var configUrl = data.match(/data-config-url=["']([^\s"'<>]+)/i);
        configUrl = configUrl && configUrl[1].replace(/&amp;/ig, '&');

        if (configUrl) {
          return vimeo_com_embed.getVimeoConfig(configUrl, cb);
        } else {
          return vimeo_com_embed.getClipPageConfig(data, cb);
        }
      });
    },
    getVimeoLinksFromConfig: function(msg, response) {
      "use strict";
      var data = vimeo_com_embed.getLinksFromConfig(msg.config);
      if (data) {
        return response(data);
      }

      return response(null);
    },
    getLinksFromConfig: function(config) {
      "use strict";
      if (!config || !config.video || !config.request || !config.request.files) {
        return null;
      }

      var video = config.video;
      var files = config.request.files;

      var data = {};

      data.title = video.title || '';

      var maxSize = null;
      for (var size in video.thumbs) {
        if (maxSize === null || maxSize < size) {
          maxSize = size;
          data.thumb = video.thumbs[size];
        }
      }

      data.links = [];

      for (var type in files) {
        if (!Array.isArray(files[type])) {
          continue;
        }
        files[type].forEach(function(item) {
          if (!item || !item.url || !item.mime) {
            return;
          }

          var ext = item.mime.split('/')[1];
          if (!ext) {
            ext = item.url.match(/\.(\w{2,4})(?:\?|#|$)/i);
            ext = ext && ext[1] || 'mp4';
          }

          var extUp = ext.toUpperCase();

          var height = item.quality;
          if (/^\d+p$/.test(height)) {
            height = height.replace(/p$/, '');
          }

          var extQuality = extUp + ' ' + height;

          data.links.push({
            url: item.url,
            name: extQuality,
            height: height,
            type: extUp,
            format: extUp,
            ext: ext
          });
        });
      }

      if (!data.links.length) {
        data = null;
      }

      return data;
    },
    getVimeoDataFromConfig: function(config) {
      "use strict";
      config = config.replace(/(\{|,)\s*(\w+)\s*:/ig, '$1"$2":').
      replace(/(:\s+)\'/g, '$1"').replace(/\'([,\]\}])/g, '"$1');

      try {
        config = JSON.parse(config);
      } catch (err) {
        return null;
      }

      return this.getLinksFromConfig(config);
    }
  };

  engine.modules.vimeo = vimeo_com_embed;
  var vkontakte_ru_embed = {
    getVKLinks: function(request, callback) {
      function callback_links(vid, links, title, duration, thumb, data, embed) {
        if (embed) {
          embed.origRequest = request;
          engine.onMessage(embed, callback);
          return;
        }

        var response = {
          action: request.action,
          extVideoId: vid ? vid : request.extVideoId,
          links: links,
          title: title,
          duration: duration,
          thumb: thumb,
          data: data,
          checkLinks: null
        };

        if (request.checkLinks && links && links.length > 0) {
          vkontakte_ru_embed.checkVkLinks(links, function(checkUrl, isValid) {
            response.checkLinks = isValid;
            callback(response);
          });
          return;
        }

        callback(response);
      }

      vkontakte_ru_embed._getVKLinks(request.extVideoId, callback_links);
      return true;
    },

    preparePladformLinks: function(pladformLinks) {
      var links;
      var obj = {
        links: links = []
      };
      pladformLinks.forEach(function(item) {
        obj.title = item.title;
        obj.duration = item.duration;
        obj.thumb = item.cover;

        var ext = item.url.match(/[\w]+\.(mp4|flv)(?:\?|$)/i);
        if (!ext) {
          ext = 'flv';
        } else {
          ext = ext[1];
        }
        links.push({
          url: item.url,
          name: ext.toUpperCase(),
          subname: item.quality.toUpperCase(),
          type: ext.toLowerCase()
        });
      });
      return obj;
    },

    _getVKLinks: function(videoId, callback) {
      var _this = this;
      var links = [],
        title = videoId,
        data = null,
        embed = null,
        thumb = '',
        duration = '';

      var vid = videoId;

      var m = null;
      var oid = null;
      var id = null;

      var re = /^video(-?\d+)_(\d+)/i;

      if (!re.test(vid)) {
        var oidRe = /(?:^|&)oid=(-?\d+)/i;
        var idRe = /(?:^|&)id=(-?\d+)/i;

        m = vid.match(oidRe);
        oid = m && parseInt(m[1]);

        m = vid.match(idRe);
        id = m && parseInt(m[1]);

        vid = '';
        if (oid && id) {
          vid = 'video' + oid + '_' + id;
        }
      } else {
        m = vid.match(re);
        oid = parseInt(m[1]);
        id = parseInt(m[2]);
      }

      if (!vid) {
        return callback(vid, links, title);
      }

      title = vid;

      return mono.request({
        url: 'https://vk.com/' + vid
      }, function(err, resp, response) {
        if (err || !response) {
          return callback(vid, links, title, duration, thumb, data, embed);
        }

        var varsJson = null;

        mono.findJson(response, [/"vid":/, /"oid":/, /"md_title":/]).some(function(arr) {
          var index = 4;
          var obj = arr && arr[index] && arr[index].player && arr[index].player.params && arr[index].player.params[0];
          if (obj && obj.vid === id && obj.oid === oid) {
            varsJson = obj;
            return true;
          }
        });

        if (varsJson) {
          var videoInfo = vkontakte_ru_embed.getVkLinksFromJson(varsJson);

          links = videoInfo.links;
          title = videoInfo.title;
          thumb = videoInfo.thumb;
          duration = videoInfo.duration;

          return callback(vid, links, title, duration, thumb, varsJson, embed);
        }

        var embedPlayerUrl = null;
        mono.findJson(response, [/"player"/]).some(function(arr) {
          var index = 4;
          var embedUrl = arr && arr[4] && arr[4].player && arr[4].player.params && arr[4].player.params[0];
          if (typeof embedUrl === 'string') {
            embedPlayerUrl = embedUrl;
            return true;
          }
        });

        var foundEmbed = false;
        if (embedPlayerUrl) {
          var m;
          m = /dailymotion.com\/(?:swf\/)?video\/([\w\d]+)/i.exec(embedPlayerUrl);
          if (m) {
            embed = {
              action: 'getDailymotionLinks',
              extVideoId: m[1]
            };
            foundEmbed = true;
          }
        }

        if (foundEmbed) {
          return callback(vid, links, title, duration, thumb, data, embed);
        }

        var async = false;
        mono.findJsonString(response, /video_box_wrap/).some(function(str) {
          var m = null;
          var frameBodyM = /<iframe([^>]+)>/i.exec(str);
          if (frameBodyM) {
            var frameBody = frameBodyM[1];
            m = /youtube.com\\?\/embed\\?\/([\w\-]+)/i.exec(frameBody);
            if (m) {
              embed = {
                action: 'getYoutubeLinks',
                extVideoId: m[1]
              };
              return true;
            }
            m = /vimeo.com\\?\/video\\?\/(\d+)/i.exec(frameBody);
            if (m) {
              embed = {
                action: 'getVimeoLinks',
                extVideoId: m[1]
              };
              return true;
            }
            m = /src="([^"]*pladform\.ru[^"]+)"/i.exec(frameBody);
            if (m) {
              async = true;
              var params = mono.parseUrl(m[1]);
              engine.modules.odnoklassniki.getPladformVideo({
                extVideoId: {
                  playerId: params.pl,
                  videoId: params.videoid
                }
              }, function(response) {
                if (response && response.action === 'getRutubeLinks') {
                  response.links = null;
                }

                var pladformLinks = response && response.links;
                if (!Array.isArray(pladformLinks)) {
                  return callback(vid, links, title, duration, thumb, data, embed);
                }

                var videoInfo = vkontakte_ru_embed.preparePladformLinks(pladformLinks);

                return callback(vid, videoInfo.links, videoInfo.title, videoInfo.duration, videoInfo.thumb, data, embed);
              });
              return true;
            }
          }

          var videoSourceFound = mono.getHtmlTags('video', str).some(function(videoTag) {
            var doc = mono.parseHtmlFragment(videoTag, 'https://vk.com/');

            var isFoundLinks = false;
            [].slice.call(doc.querySelectorAll('source')).forEach(function(sourceTag) {
              var isMatchedUrl = false;
              var url = sourceTag.src;
              if (!isMatchedUrl) {
                var isInstagram = /^(.*cdninstagram\.com.+mp4)/i.exec(url);
                if (isInstagram) {
                  isMatchedUrl = true;
                  isFoundLinks = true;
                  links.push({
                    url: url,
                    subname: 'SD',
                    name: 'MP4',
                    type: 'mp4'
                  });
                }
              }
              if (!isMatchedUrl) {
                var isVkVideo = /\.(\d+)\.mp4(?:$|\?)/.exec(url);
                if (isVkVideo) {
                  isMatchedUrl = true;
                  isFoundLinks = true;
                  var vkUrl = url;
                  var quality = isVkVideo[1];
                  var pos = vkUrl.indexOf('?');
                  if (pos !== -1) {
                    vkUrl = vkUrl.substr(0, pos);
                  }
                  mono.findJsonString(response, /mv_title/).some(function(str) {
                    var m = /id="mv_title"[^>]*>([^<]+)/.exec(str);
                    if (m) {
                      title = mono.fileName.decodeSpecialChars(mono.decodeUnicodeEscapeSequence(m[1]));
                      return true;
                    }
                  });
                  links.push({
                    url: vkUrl,
                    subname: quality,
                    name: 'MP4',
                    type: 'mp4'
                  });
                }
              }
            });
            return isFoundLinks;
          });
          if (videoSourceFound) {
            return true;
          }

          if (/var\sopts\s*=\s*/.test(str)) {
            m = /url:\s*'(?:[^']+)dailymotion.com\/(?:swf\/)?video\/([\w\d]+)/.exec(str);
            if (m) {
              embed = {
                action: 'getDailymotionLinks',
                extVideoId: m[1]
              };
              return true;
            }
          }
        });

        return !async && callback(vid, links, title, duration, thumb, data, embed);
      });
    },

    checkVkLinks: function(links, callback) {
      var checkUrl = '';

      if (links && links.length > 0) {
        if (links[0].type == 'mp4')
          checkUrl = links[0].url;
        else if (links.length > 1)
          checkUrl = links[1].url;
        else
          checkUrl = links[0].url;
      }

      if (checkUrl) {
        mono.request({
          url: checkUrl,
          type: 'HEAD'
        }, function(err, resp) {
          callback(checkUrl, !err);
        });
        return;
      }

      callback();
    },

    getVkLinksFromJsonMsg: function(msg, response) {
      var info = this.getVkLinksFromJson(msg.json);
      return response(info);
    },

    getVkLinksFromJson: function(json) {
      var links = [];
      var vid = json.vid;
      var title = json.md_title || json.vid;
      var thumb = '';

      if (json.thumb) {
        thumb = json.thumb;
      } else
      if (json.jpg) {
        thumb = json.jpg;
      }

      var flvRe = /\.flv(\?|$)]/;
      var videoUrlRegExp = /url([0-9]+)/;
      Object.keys(json).forEach(function(key) {
        var url = '';
        var type = 'mp4';
        var quality = null;
        if (key === 'extra_data' && json.extra === "99") {
          url = '';
          if (json.live_mp4) {
            url = json.live_mp4;
          } else
          if (json.postlive_mp4) {
            url = json.postlive_mp4;
          }
          if (url) {
            quality = json.hd ? 'HD' : 'SD';
            links.push({
              url: url,
              subname: quality,
              name: type.toUpperCase(),
              type: type
            });
          }
        } else
        if (key === 'extra_data' && json.extra === "52") {
          quality = json.hd ? 'HD' : 'SD';
          url = json.extra_data;
          if (flvRe.test(url)) {
            type = 'flv';
          }
          links.push({
            url: url,
            subname: quality,
            name: type.toUpperCase(),
            type: type
          });
        } else {
          quality = key.match(videoUrlRegExp);
          quality = quality && quality[1];
          if (quality !== null) {
            url = json[key];
            if (flvRe.test(url)) {
              type = 'flv';
            }

            links.push({
              url: url,
              subname: quality,
              name: type.toUpperCase(),
              type: type
            });
          }
        }
      });

      var duration = json.duration;

      return {
        action: 'getVKLinks',
        extVideoId: vid,
        links: links,
        title: title,
        duration: duration,
        thumb: thumb,
        data: json,
        checkLinks: null
      };
    },

    getVkLinksFromData: function(request, cb) {
      var response = request.data;

      var varsJson = null;
      mono.findJson(response, [/"vid":/, /"oid":/, /"md_title":/]).some(function(obj) {
        var obj = obj.player && obj.player.params && obj.player.params[0];
        if (obj) {
          varsJson = obj;
          return true;
        }
      });

      if (!varsJson) {
        return cb();
      }

      var info = vkontakte_ru_embed.getVkLinksFromJson(varsJson);

      return cb(info);
    }
  };

  engine.modules.vkontakte = vkontakte_ru_embed;
  var youtube_com_embed = {
    /**
     * @private
     */
    lastSts: ["17598", [
      ["reverse", null],
      ["splice", 1],
      ["reverse", null],
      ["swap", 50]
    ]],
    _stsIsLoaded: false,
    _lastSignature: null,
    _dashMpdSigR: /(\/s\/([^\/]+))/,
    getYoutubeLinks: function(request, callback) {
      function callback_links(links, title, subtitles, duration) {
        youtube_com_embed.addUmmyLinks(links, request.extVideoId);

        var response = {
          action: request.action,
          extVideoId: request.extVideoId,
          links: links,
          title: title,
          subtitles: subtitles,
          duration: duration,
          checkLinks: null
        };

        if (request.checkLinks && links) {
          return youtube_com_embed.checkYoutubeLinks(links, function(checkUrl, isValid) {
            response.checkLinks = isValid;
            return callback(response);
          });
        }

        return callback(response);
      }

      youtube_com_embed._prepareLastSts().then(function() {
        return youtube_com_embed._getYoutubeLinks(request.url, request.extVideoId, request.checkSubtitles, request.noDash).then(function(result) {
          callback_links(result.links, result.title, result.subtitles, result.duration);
        }, function(err) {
          mono.error('_getYoutubeLinks error', err);
          callback_links(null, '', null, '');
        });
      });
      return true;
    },
    _getYoutubeLinks: function(eurl, id, checkSubtitles, noDash) {
      var self = this;

      if (!eurl) {
        eurl = 'https://www.youtube.com/watch?v=' + id;
      }

      return self._getVideoInfo(id, eurl).then(function(result) {
        var config = result.config;
        var signature = result.signature;
        return self.onGetConfig(id, checkSubtitles, noDash, config, signature);
      });
    },
    _getVideoInfo: function(id, eurl) {
      var self = this;
      var Promise = mono.Promise;
      var rp = self._rp;
      var getVideoInfo = function(domain, eurl, id, el, signature) {
        var headers = {};
        if (mono.isChromeMobile || mono.isFirefoxMobile) {
          headers['User-Agent'] = mono.getDesktopUa();
        }
        return rp({
          url: 'https://' + domain + '/get_video_info?' + mono.param({
            video_id: id,
            eurl: eurl,
            el: el,
            sts: signature.sts
          }),
          headers: headers
        }).then(function(config) {
          return self._dataStrToObj(config);
        }).then(function(config) {
          if (!config.video_id) {
            throw new Error('Config videoId is empty!');
          }

          return {
            signature: signature,
            config: config
          };
        });
      };
      var getAsJsonPage = function(id) {
        var headers = {};
        if (mono.isChromeMobile || mono.isFirefoxMobile) {
          headers['User-Agent'] = mono.getDesktopUa();
        }
        return rp({
          url: 'https://www.youtube.com/watch?' + mono.param({
            v: id,
            spf: 'navigate'
          }),
          headers: headers
        }).then(function(response) {
          var json = JSON.parse(response);
          var jsonList = null;
          json.some(function(item) {
            if (item.data && item.data.swfcfg) {
              jsonList = item.data.swfcfg;
              return true;
            }
          });
          if (!jsonList) {
            throw new Error('swfcfg is not found');
          }

          if (!jsonList.args || typeof jsonList.args !== 'object') {
            throw new Error('jsonList args is not found!');
          }

          var config = self._decodeParams(jsonList.args);
          if (!config.video_id) {
            throw new Error('Config videoId is empty!');
          }

          var sts = parseInt(jsonList.sts);
          var playerUrl = jsonList.assets && jsonList.assets.js;

          return getSignatureByConfig(config, playerUrl, sts).then(function(signature) {
            return {
              config: config,
              signature: signature
            }
          });
        });
      };
      var getAsVideoPage = function(id) {
        var headers = {};
        if (mono.isChromeMobile || mono.isFirefoxMobile) {
          headers['User-Agent'] = mono.getDesktopUa();
        }
        return rp({
          url: 'https://www.youtube.com/watch?' + mono.param({
            v: id
          }),
          headers: headers
        }).then(function(response) {
          var script = mono.getPageScript(response, /ytplayer\.config\s+=\s+/);
          if (!script.length) {
            throw new Error('Video page script is not found!');
          }
          script = script[0];

          var jsonList = mono.findJson(script, [/"video_id":/])[0];
          if (!jsonList) {
            throw new Error('Video page jsonList is not found!');
          }

          if (!jsonList.args || typeof jsonList.args !== 'object') {
            throw new Error('jsonList args is not found!');
          }

          var config = self._decodeParams(jsonList.args);
          if (!config.video_id) {
            throw new Error('Config videoId is empty!');
          }

          var sts = parseInt(jsonList.sts);
          var playerUrl = jsonList.assets && jsonList.assets.js;

          return getSignatureByConfig(config, playerUrl, sts).then(function(signature) {
            return {
              config: config,
              signature: signature
            }
          });
        });
      };
      var getSignatureByConfig = function(config, playerUrl, sts) {
        var promise = Promise.resolve(null);

        if (self._getChipedItem(config)) {
          promise = promise.then(function() {
            if (!playerUrl) {
              throw new Error('Player url is not found!');
            }
            return self._ytHtml5SigDecipher.dechip(playerUrl, sts);
          });
        }

        return promise;
      };

      return self._getSignature().then(function(signature) {
        return getVideoInfo('www.youtube-nocookie.com', eurl, id, 'detailpage', signature).then(function(config) {
          if (config.requires_purchase === '1' ||
            config.url_encoded_fmt_stream_map === '' ||
            config.fmt_url_map === '' ||
            config.adaptive_fmts === '' ||
            config.errorcode > 0) {
            throw new Error('Some config keys is bad');
          }
          return config;
        }, function(err) {
          mono.debug('try 1', err);
          throw err;
        }).catch(function() {
          return getVideoInfo('www.youtube.com', eurl, id, 'detailpage', signature).catch(function(err) {
            mono.debug('try 2', err);
            throw err;
          });
        }).catch(function() {
          return getVideoInfo('www.youtube-nocookie.com', eurl, id, 'embedded', signature).then(function(config) {
            if (config.requires_purchase === '1' ||
              config.url_encoded_fmt_stream_map === '' ||
              config.fmt_url_map === '' ||
              config.adaptive_fmts === '' ||
              config.errorcode > 0) {
              throw new Error('Some config keys is bad');
            }
            return config;
          }, function(err) {
            mono.debug('try 3', err);
            throw err;
          });
        }).catch(function() {
          return getVideoInfo('www.youtube.com', eurl, id, 'embedded', signature).catch(function(err) {
            mono.debug('try 4', err);
            throw err;
          });
        });
      }).catch(function(err) {
        mono.debug('_getSignature error', err);
        throw err;
      }).catch(function() {
        return getAsJsonPage(id).catch(function(err) {
          mono.debug('try 5', err);
          throw err;
        });
      }).catch(function() {
        return getAsVideoPage(id).catch(function(err) {
          mono.debug('try 6', err);
          throw err;
        });
      }).catch(function() {
        throw new Error('Get config error');
      }).then(function(result) {
        var config = result.config;
        var signature = result.signature;
        return self._testSignature(config, signature).then(function() {
          return {
            config: config,
            signature: signature
          };
        });
      });
    },
    _getSignature: function() {
      var self = this;
      var Promise = mono.Promise;
      var rp = self._rp;

      if (self._lastSignature && self._lastSignature.expire > parseInt(Date.now() / 1000)) {
        return Promise.resolve(self._lastSignature);
      }

      var headers = {};
      if (mono.isChromeMobile || mono.isFirefoxMobile) {
        headers['User-Agent'] = mono.getDesktopUa();
      }

      return rp({
        url: 'https://www.youtube.com/',
        headers: headers
      }).then(function(html) {
        var playerInfo = null;
        try {
          playerInfo = self.getPlayerStsAndUrlFromHtml(html);
        } catch (err) {
          playerInfo = self.getPlayerStsAndUrlFromAuthHtml(html);
        }
        return playerInfo;
      }).then(function(playerInfo) {
        if (!playerInfo.sts) {
          return self._ytHtml5SigDecipher.dechip(playerInfo.playerUrl);
        } else {
          return playerInfo;
        }
      }).then(function(signature) {
        signature.expire = parseInt(Date.now() / 1000) + 6 * 60 * 60;
        return self._lastSignature = signature;
      });
    },
    getPlayerStsAndUrlFromHtml: function(html) {
      var script = mono.getPageScript(html, /window\.ytplayer\s*=\s*/);
      if (!script.length) {
        throw new Error('Player config is not found');
      }
      script = script[0];

      var jsonList = mono.findJson(script, [/"PLAYER_JS_URL":/]);
      if (!jsonList.length) {
        throw new Error('Player url is not found!');
      }
      jsonList = jsonList[0];

      var playerUrl = jsonList.PLAYER_JS_URL;
      if (!playerUrl) {
        throw new Error('playerUrl is not found');
      }

      return {
        sts: null,
        playerUrl: playerUrl
      };
    },
    getPlayerStsAndUrlFromAuthHtml: function(html) {
      var script = mono.getPageScript(html, /ytplayer\.config\s+=\s+/);
      if (!script.length) {
        throw new Error('Player config script is not found');
      }
      script = script[0];

      var jsonList = mono.findJson(script, [/"assets":/, /"sts":\d+/]);
      if (!jsonList.length) {
        throw new Error('Player config json is not found!');
      }
      jsonList = jsonList[0];


      var playerUrl = jsonList.assets && jsonList.assets.js;
      if (!playerUrl) {
        throw new Error('playerUrl is not found');
      }

      var sts = parseInt(jsonList.sts);

      return {
        sts: sts,
        playerUrl: playerUrl
      };
    },
    _dataStrToObj: function(data) {
      return this._decodeParams(mono.parseUrl(data, {
        params: true
      }));
    },
    _decodeParams: function(data) {
      var self = this;
      ['url_encoded_fmt_stream_map', 'adaptive_fmts', 'fmt_url_map'].forEach(function(key) {
        if (data[key]) {
          data[key] = data[key].split(',').map(function(item) {
            return self._dataStrToObj(item);
          });
        }
      });
      return data;
    },
    _testSignature: function(config, signature) {
      var self = this;
      var Promise = mono.Promise;
      var rp = self._rp;

      var chipedItem = self._getChipedItem(config);

      if (!chipedItem) {
        return Promise.resolve();
      }

      return Promise.resolve().then(function() {
        if (!signature.actionList) {
          return self._ytHtml5SigDecipher.dechip(signature.playerUrl, signature.sts).then(function(sig) {
            signature.sts = sig.sts;
            signature.actionList = sig.actionList;
            return signature;
          });
        } else {
          return signature;
        }
      }).then(function(signature) {
        var url = null;
        var decodedSignature = self._ytHtml5SigDecipher.applyActions(signature.actionList, chipedItem.s);
        if (chipedItem.getUrl) {
          url = chipedItem.getUrl(decodedSignature);
        } else {
          url = chipedItem.url + '&signature=' + decodedSignature;
        }

        return rp({
          method: 'HEAD',
          url: url
        }).then(function() {
          return self._ytHtml5SigDecipher.saveSignature(signature);
        }, function(err) {
          if (/403/.test(err.message)) {
            throw err;
          }
        });
      });
    },
    _getChipedItem: function(config) {
      var self = this;
      var chipedItem = null;

      ['url_encoded_fmt_stream_map', 'adaptive_fmts', 'fmt_url_map'].some(function(key) {
        var item = config[key];
        if (!item) {
          return false;
        }

        return item.some(function(subItem) {
          if (subItem.s && subItem.url) {
            chipedItem = subItem;
            return true;
          }
        });
      });

      var dashUrl = config.dashmpd;
      if (!chipedItem && dashUrl) {
        var s = self._dashMpdSigR.exec(dashUrl);
        if (s) {
          chipedItem = {
            s: s[2],
            url: dashUrl.replace(s[1], ''),
            getUrl: function(url, s, signature) {
              return url.replace(s[1], '/signature/' + signature);
            }.bind(null, dashUrl, s)
          };
        }
      }

      return chipedItem;
    },

    /**
     * @private
     */
    readFmt: function(links, fmt, signature, titleParam) {
      var self = this;
      var meta = links.meta;

      fmt.forEach(function(item) {
        if (item.stream) {
          meta.hasStream = 1;
          return;
        }

        var url = item.url;
        if (!url) return;

        if (!/([?&])s(ig(nature)?)?=/i.test(url)) {
          if (item.sig) {
            url += '&signature=' + item.sig;
          } else
          if (item.signature) {
            url += '&signature=' + item.signature;
          } else
          if (item.s) {
            url += '&signature=' + self._ytHtml5SigDecipher.applyActions(signature.actionList, item.s);
          }
        }
        url = url.replace(/([?&])sig=/i, '$1signature=').replace(/\\u0026/ig, '&');

        var itag = item.itag;
        if (!itag) {
          var m = /(?:[?&])itag=(\d+)/i.exec(url);
          if (m) {
            itag = m[1];
          }
        }
        if (!itag) return;

        if (!/[?&]itag=/i.test(url)) {
          url += '&itag=' + itag;
        }

        url = self._addRateByPass(url);

        var metaItem = meta[itag];
        if (!metaItem) {
          metaItem = meta[itag] = {};
        }

        if (item.fps) {
          metaItem.fps = item.fps;
        }

        if (item.size && /^\d+x\d+$/.test(item.size)) {
          var wh = item.size.split('x');
          metaItem.quality = youtube_com_embed.getDashQuality(wh[0], wh[1]);
        }

        if (item.bitrate) {
          metaItem.bitrate = parseInt(item.bitrate);
        }

        if (item.type) {
          metaItem.type = item.type;
          var codecs = item.type.match(/codecs="([^"]+)"/);
          if (codecs) {
            metaItem.codecs = codecs[1];
          }
        }

        if (item.projection_type) {
          metaItem.projectionType = parseInt(item.projection_type);
        }

        if (!links[itag]) {
          links[itag] = url + titleParam;
        }
      });
    },

    /**
     * @private
     */
    onGetConfig: function(videoId, checkSubtitles, noDash, config, signature) {
      "use strict";
      var self = this;
      var Promise = mono.Promise;

      var links = {
          meta: {}
        },
        title = '',
        subtitles = null,
        duration = '',
        dashUrl = null;

      return Promise.resolve().then(function() {
        duration = config.length_seconds || '';

        title = config.title || '';
        var titleParam = '';
        if (title) {
          title = title.replace(/\+/g, ' ');
          titleParam = '&title=' + encodeURIComponent(mono.fileName.modify(title));
        }

        var fmtMap = config.fmt_url_map || config.url_encoded_fmt_stream_map || [];
        var adaptiveFmts = config.adaptive_fmts || [];

        if (config.livestream || config.live_playback) {
          links.meta.hasStream = 1;
        }

        fmtMap && self.readFmt(links, fmtMap, signature, titleParam);
        adaptiveFmts && self.readFmt(links, adaptiveFmts, signature, titleParam);

        dashUrl = config.dashmpd || '';
        if (dashUrl && dashUrl.indexOf('yt_live_broadcast') !== -1) {
          dashUrl = null;
        }
      }).then(function() {
        var promise = Promise.resolve();

        if (checkSubtitles) {
          promise = promise.then(function() {
            return new Promise(function(resolve) {
              self.getYoutubeSubtitles({
                extVideoId: videoId
              }, function(subs) {
                subtitles = subs || null;
                resolve();
              });
            }).catch(function(err) {
              mono.error('Get subtitles error', err);
            });
          });
        }

        if (!noDash && dashUrl) {
          promise = promise.then(function() {
            var dechipedDashUrl = dashUrl;

            var s = self._dashMpdSigR.exec(dashUrl);
            if (s) {
              var sig = self._ytHtml5SigDecipher.applyActions(signature.actionList, s[2]);
              dechipedDashUrl = dashUrl.replace(s[1], '/signature/' + sig);
            }

            dechipedDashUrl = dechipedDashUrl.replace('/sig/', '/signature/');

            return self.getYouTubeDashLinks(links, dechipedDashUrl).catch(function(err) {
              mono.error('Get dash error', err);
            });
          });
        }

        return promise;
      }).then(function() {
        var len = Object.keys(links).length;
        if (links.meta && !links.meta.hasStream) {
          len--;
        }
        if (!len) {
          links = null;
        }

        return {
          links: links,
          title: title,
          subtitles: subtitles,
          duration: duration
        };
      });
    },

    /**
     * @private
     */
    addUmmyLinks: function(links, videoId) {
      if (!links || (links.meta && links.meta.hasStream)) {
        return;
      }

      if (engine.preferences.showUmmyItem) {
        var meta = links.meta;
        if (!meta) {
          meta = links.meta = {};
        }
        meta.videoId = videoId;

        links['ummy'] = 'ummy://www.youtube.com/watch?v=' + videoId;
        links['ummyAudio'] = 'ummy://www.youtube.com/watch?v=' + videoId + '&sf_type=audio';
      }
    },

    /**
     * @private
     */
    checkYoutubeLinks: function(links, callback) {
      var checkItags = ['18', '34', '35'],
        checkUrl = '';
      for (var i = 0; i < checkItags.length; i++) {
        if (links[checkItags[i]]) {
          checkUrl = links[checkItags[i]];
          break;
        }
      }

      if (checkUrl) {
        mono.request({
          type: 'HEAD',
          url: checkUrl
        }, function(err, resp) {
          callback(checkUrl, !err);
        });
      } else {
        callback();
      }
    },

    /**
     * @private
     */
    convertVtt2Srt: function(item, cb) {
      "use strict";
      mono.request({
        url: item.url
      }, function(err, resp, body) {
        if (err || !body) {
          console.error('Request error!', err);
          return cb();
        }

        var re = /(\d{2}:\d{2}:\d{2})\.(\d{3})/g;
        var validateRe = /^\d{2}:\d{2}:\d{2}\.\d{3}/;
        var arr = body.split('\n\n');

        if (!validateRe.test(arr[0])) {
          arr.shift();
        }

        if (!validateRe.test(arr[arr.length - 1])) {
          arr.pop();
        }

        var hasSkip = false;
        var srt = arr.filter(function(item) {
          var r = validateRe.test(item);
          if (!r) {
            hasSkip = true;
          }
          return r;
        }).map(function(item, index) {
          item = item.replace(re, "$1,$2");
          return (index + 1) + '\n' + item;
        });
        srt = srt.join('\n\n');

        if (hasSkip) {
          return cb();
        }

        item.srt = srt;
        item.preprocess = 'srt2url';
        cb();
      });
    },

    /**
     * @private
     */
    getYoutubeSubtitles: function(message, cb) {
      var _this = this;
      var videoId = message.extVideoId;
      var baseUrl = 'http://video.google.com/timedtext';
      mono.request({
        url: baseUrl + '?hl=' + engine.language.lang + '&v=' + videoId + '&type=list&tlangs=1',
        xml: true
      }, function(err, resp, xml) {
        if (err || !xml) {
          return cb();
        }

        var track = xml.querySelectorAll('track');
        var target = xml.querySelectorAll('target');
        var list = [];
        var trackList = {};
        var targetList = {};
        var origTrack = undefined;
        var langCode, param;
        for (var i = 0, item; item = track[i]; i++) {
          langCode = item.getAttribute('lang_code');
          param = {
            lang: langCode,
            v: videoId,
            fmt: 'vtt',
            name: item.getAttribute('name') || undefined
          };
          trackList[langCode] = {
            lang: item.getAttribute('lang_translated'),
            langCode: langCode,
            url: baseUrl + '?' + mono.param(param),
            name: param.name
          };
          list.push(trackList[langCode]);
          if (!origTrack && item.getAttribute('cantran')) {
            origTrack = param;
          }
        }

        if (origTrack) {
          for (i = 0, item; item = target[i]; i++) {
            langCode = item.getAttribute('lang_code');
            param = {
              lang: origTrack.lang,
              v: videoId,
              tlang: langCode,
              fmt: 'vtt',
              name: origTrack.name
            };
            targetList[langCode] = {
              lang: item.getAttribute('lang_translated'),
              langCode: langCode,
              url: baseUrl + '?' + mono.param(param),
              isAuto: true
            };
          }
        }

        langCode = mono.getNavigator().language.toLowerCase();
        if (langCode.indexOf('zh-hant') === 0) {
          langCode = 'zh-Hant';
        } else
        if (langCode.indexOf('zh-hans') === 0) {
          langCode = 'zh-Hans';
        }
        var localeList = [langCode];
        if (localeList[0] === 'uk') {
          localeList.push('ru');
        }
        for (var i = 0, item; item = localeList[i]; i++) {
          if (!trackList[item] && targetList[item]) {
            list.push(targetList[item]);
          }
        }

        var waitCount = 0;
        var readyCount = 0;
        var onReady = function() {
          readyCount++;
          if (waitCount !== readyCount) {
            return;
          }
          return cb(list);
        };
        waitCount++;
        list.forEach(function(item) {
          waitCount++;
          _this.convertVtt2Srt(item, onReady);
        });
        onReady();
      });
    },

    /**
     * @private
     */
    getYouTubeDashLinks: function(links, dashUrl) {
      var self = this;
      var rp = self._rp;

      var headers = {};
      if (mono.isChromeMobile || mono.isFirefoxMobile) {
        headers['User-Agent'] = mono.getDesktopUa();
      }

      return rp({
        url: dashUrl,
        headers: headers,
        xml: true
      }).then(function(xml) {
        self.parseDash(xml, links);
      });
    },

    /**
     * @private
     */
    getDashQuality: function(a, b) {
      var qualityList = {
        144: 144,
        240: 240,
        360: 360,
        480: 480,
        720: 720,
        1080: 1080,
        1440: 1440,
        '4K': 2160,
        '5K': 2880,
        '8K': 4320
      };

      var quality;
      var g = Math.max(a, b);
      a = Math.min(a, b);
      for (var qualityName in qualityList) {
        var value = qualityList[qualityName];
        if (g >= Math.floor(16 * value / 9) || a >= value) {
          quality = qualityName;
        } else {
          return quality;
        }
      }
      return quality;
    },

    /**
     * @private
     */
    parseDash: function(xml, links) {
      var self = this;
      var elList = xml.querySelectorAll('Representation');

      var meta = links.meta = links.meta || {};

      for (var i = 0, el; el = elList[i]; i++) {
        var baseUrlNode = el.querySelector('BaseURL');
        var url = baseUrlNode.textContent;
        if (!url) {
          continue;
        }

        var segmentUrlNode = baseUrlNode.parentNode.querySelector('SegmentURL');
        var segmentUrl = segmentUrlNode && segmentUrlNode.getAttribute('media');
        if (segmentUrl && segmentUrl.indexOf('sq/') === 0) {
          continue;
        }

        var itag = el.getAttribute('id');
        var metaItem = meta[itag];
        if (!metaItem) {
          metaItem = meta[itag] = {};
        }

        url = self._addRateByPass(url);

        var frameRate = el.getAttribute('frameRate');
        if (frameRate) {
          metaItem.fps = frameRate;
        }

        var width = el.getAttribute('width');
        var height = el.getAttribute('height');

        if (width && height) {
          metaItem.quality = youtube_com_embed.getDashQuality(width, height);
        }

        var codecs = el.getAttribute('codecs');
        if (codecs) {
          metaItem.codecs = codecs;
          var type = url.match(/mime=([^&]+)/);
          type = type && type[1];
          if (type) {
            metaItem.type = type;
          }
        }

        if (!links[itag]) {
          links[itag] = url;
        }
      }
    },

    getYoutubeIdListFromPlaylist: function(request, cb) {
      youtube_com_embed.getIdListFromList(request.baseUrl || 'https://www.youtube.com', request.listId, cb);
      return true;
    },

    /**
     * @private
     */
    getIdListFromList: (function() {
      var getNextPage = function(baseUrl, url, pageList, cb) {
        if (!pageList) {
          pageList = [];
        }
        mono.request({
          url: baseUrl + url,
          json: true
        }, function(err, resp, data) {
          if (err || !data) {
            return cb(pageList);
          }

          pageList.push(data.content_html);
          var nextPageUrl = getNextPageUrl(data.load_more_widget_html);
          if (nextPageUrl === undefined) {
            return cb(pageList);
          }
          getNextPage(baseUrl, nextPageUrl, pageList, cb);
        });
      };
      var getTitleFromPage = function(data) {
        var title = data.match(/<h1[^>]+>([^<]+)<\/h1>/);
        if (!title) {
          return undefined;
        }
        return title[1].replace(/\r?\n/g, " ").trim();
      };
      var getNextPageUrl = function(data) {
        if (!data) {
          return undefined;
        }
        var nextUrl = data.match(/data-uix-load-more-href="([^"]+)"/);
        if (nextUrl) {
          nextUrl = nextUrl[1];
        }
        return nextUrl || undefined;
      };
      var readLinksFromPages = function(listId, pageList, cb) {
        var title = getTitleFromPage(pageList[0]);
        var idObj = {};
        var idList = [];
        var pattern = /href="\/watch\?([^"]+)"/g;
        var maxIndex = 0;
        for (var i = 0, len = pageList.length; i < len; i++) {
          var content = pageList[i];
          content.replace(pattern, function(string, args) {
            var url = mono.parseUrl(args, {
              params: true,
              sep: '&amp;'
            });
            if (url.list !== listId) {
              return;
            }
            url.index = parseInt(url.index);
            idObj[url.index] = url.v;
            if (url.index > maxIndex) {
              maxIndex = url.index;
            }
          });
        }
        for (i = 0; i <= maxIndex; i++) {
          if (idObj[i] === undefined) {
            continue;
          }
          if (idList.indexOf(idObj[i]) === -1) {
            idList.push(idObj[i]);
          }
        }
        cb({
          idList: idList,
          title: title
        });
      };
      var getNewClientHeaders = function(data) {
        var headers = {};
        var params = null;
        var m = /ytcfg\.set\(({.+)/.exec(data);
        if (m) {
          mono.findJsObject(m[1]).some(function(obj) {
            if (obj.INNERTUBE_CONTEXT_CLIENT_NAME) {
              params = obj;
              return true;
            }
          });
        }
        if (params) {
          headers['x-youtube-client-name'] = params.INNERTUBE_CONTEXT_CLIENT_NAME;
          headers['x-youtube-client-version'] = params.INNERTUBE_CONTEXT_CLIENT_VERSION;
          if (params.ID_TOKEN) {
            headers['x-youtube-identity-token'] = params.ID_TOKEN;
          }
          /*headers['x-youtube-page-cl'] = params.PAGE_CL;
          headers['x-youtube-page-label'] = params.PAGE_BUILD_LABEL;
          headers['x-youtube-variants-checksum'] = params.VARIANTS_CHECKSUM;*/
        }
        return headers;
      };
      var getNewTitle = function(data) {
        var title = 'unknown';
        var params = null;
        var m = data.match(/"playlistSidebarPrimaryInfoRenderer":({.+)/);
        if (m) {
          mono.findJsObject(m[1]).some(function(obj) {
            if (obj.title && obj.title.runs) {
              params = obj;
              return true;
            }
          });
        }
        if (params) {
          try {
            params.title.runs.some(function(obj) {
              if (obj.text) {
                return title = obj.text;
              }
            });
          } catch (err) {
            mono.debug('getNewTitle error', err);
          }
        }
        return title;
      };
      var getNewNextPageUrl = function(data) {
        var path = null;
        var m = data.match(/"nextContinuationData":({[^}]+})/);
        if (m) {
          try {
            var nextContinuationData = JSON.parse(m[1]);
            path = '/browse_ajax?' + mono.param({
              ctoken: nextContinuationData.continuation,
              itct: nextContinuationData.clickTrackingParams
            });
          } catch (e) {
            mono.debug('getNewNextPageUrl error', e);
          }
        }
        return path;
      };
      var getNewVideoList = function(data, idList) {
        var onGetContents = function(contents) {
          if (Array.isArray(contents)) {
            contents.forEach(function(item) {
              var playlistVideoRenderer = item.playlistVideoRenderer;
              var videoId = playlistVideoRenderer && playlistVideoRenderer.videoId;
              if (videoId) {
                idList.push(videoId);
              }
            });
          }
        };

        var pos = data.indexOf('{"playlistVideoListRenderer":{');
        if (pos !== -1) {
          data = data.substr(pos);
          mono.findJson(data).forEach(function(obj) {
            var playlistVideoListRenderer = obj.playlistVideoListRenderer;
            var contents = playlistVideoListRenderer && playlistVideoListRenderer.contents;
            onGetContents(contents);
          });
        } else {
          pos = data.indexOf('{"playlistVideoListContinuation":{');
          if (pos !== -1) {
            data = data.substr(pos);
            mono.findJson(data).forEach(function(obj) {
              var playlistVideoListContinuation = obj.playlistVideoListContinuation;
              var contents = playlistVideoListContinuation && playlistVideoListContinuation.contents;
              onGetContents(contents);
            });
          }
        }
      };
      var getNewNextPage = function(baseUrl, path, clientHeaders, dataList, cb) {
        mono.request({
          url: baseUrl + path,
          headers: clientHeaders,
          json: true
        }, function(err, resp, data) {
          if (err) {
            mono.error('YT next page request error!', err);
            return cb();
          }

          var dataStr = JSON.stringify(data);
          var nextPageUrl = getNewNextPageUrl(dataStr);
          getNewVideoList(dataStr, dataList);

          if (nextPageUrl) {
            getNewNextPage(baseUrl, nextPageUrl, clientHeaders, dataList, cb);
          } else {
            cb();
          }
        });
      };
      return function getLinksFromList(baseUrl, listId, cb) {
        mono.request({
          url: baseUrl + '/playlist?list=' + listId
        }, function(err, resp, data) {
          if (err) {
            return cb();
          }

          var nextPageUrl = null;
          if (/"playlistVideoListRenderer"/.test(data)) {
            var clientHeaders = getNewClientHeaders(data);
            var title = getNewTitle(data);
            var idList = [];

            getNewVideoList(data, idList);

            nextPageUrl = getNewNextPageUrl(data);
            if (!nextPageUrl) {
              cb({
                idList: idList,
                title: title
              });
            } else {
              getNewNextPage(baseUrl, nextPageUrl, clientHeaders, idList, function() {
                cb({
                  idList: idList,
                  title: title
                });
              });
            }
          } else {
            nextPageUrl = getNextPageUrl(data);
            if (!nextPageUrl) {
              readLinksFromPages(listId, [data], cb);
            } else {
              getNextPage(baseUrl, nextPageUrl, [data], function(pageList) {
                readLinksFromPages(listId, pageList, cb);
              });
            }
          }
        });
      };
    })(),

    getYoutubeLinksFromConfig: function(message, response) {
      "use strict";
      var self = this;
      var Promise = mono.Promise;
      var fallback = function(err) {
        mono.debug('Skip getYoutubeLinksFromConfig', err);
        youtube_com_embed.getYoutubeLinks(message, response);
      };

      this._prepareLastSts().then(function() {
        var jsonList = message.config;
        if (!jsonList ||
          !jsonList.args ||
          jsonList.args.video_id !== message.extVideoId ||
          !jsonList.assets ||
          !jsonList.assets.js ||
          !(jsonList.args.url_encoded_fmt_stream_map || jsonList.args.adaptive_fmts || jsonList.args.fmt_url_map)
        ) {
          throw new Error('jsonList args is not found!');
        }

        var config = self._decodeParams(jsonList.args, 1);
        var sts = parseInt(jsonList.sts);
        var playerUrl = jsonList.assets && jsonList.assets.js;

        return Promise.resolve().then(function() {
          if (self._getChipedItem(config)) {
            if (!playerUrl) {
              throw new Error('Player url is not found!');
            }
            return self._ytHtml5SigDecipher.dechip(playerUrl, sts);
          } else {
            return null;
          }
        }).then(function(signature) {
          return self._testSignature(config, signature).then(function() {
            return {
              config: config,
              signature: signature
            };
          });
        }).then(function(result) {
          var config = result.config;
          var signature = result.signature;
          return self.onGetConfig(
            message.extVideoId,
            message.checkSubtitles,
            message.noDash,
            config,
            signature
          ).then(function(result) {
            var links = result.links;
            var title = result.title;

            if (links) {
              youtube_com_embed.addUmmyLinks(links, message.extVideoId);
            }

            response({
              links: links,
              title: title,
              isQuick: 1
            });
          });
        });
      }).catch(fallback);
      return true;
    },
    _addRateByPass: function(url) {
      if (!/ratebypass/.test(url)) {
        if (!/\?/.test(url)) {
          if (!/\/$/.test(url)) {
            url += '/';
          }
          url += 'ratebypass/yes/'
        } else {
          url += '&ratebypass=yes'
        }
      }
      return url;
    },

    _ytHtml5SigDecipher: {
      applyActions: function(actionList, sig) {
        var actions = {
          slice: function(a, b) {
            a.slice(b)
          },
          splice: function(a, b) {
            a.splice(0, b)
          },
          reverse: function(a) {
            a.reverse()
          },
          swap: function(a, b) {
            var c = a[0];
            a[0] = a[b % a.length];
            a[b] = c
          }
        };
        var parts = sig.split("");
        for (var i = 0, item; item = actionList[i]; i++) {
          actions[item[0]](parts, item[1]);
        }
        return parts.join("");
      },
      readObfFunc: function(func, data) {
        var vList = func.match(/\[(\w+)\]/g);
        if (!vList) {
          return;
        }
        for (var i = 0, v; v = vList[i]; i++) {
          var vv = data.match(new RegExp('[, ]{1}' + v.slice(1, -1) + '="(\\w+)"'));
          if (vv) {
            func = func.replace(v, '.' + vv[1]);
          }
        }
        var arr = func.split(';');
        var actList = [];
        for (var i = 0, item; item = arr[i]; i++) {
          if (item.indexOf('.split(') !== -1 || item.indexOf('.join(') !== -1) {
            continue;
          }
          if (item.indexOf('reverse') !== -1) {
            actList.push(['reverse', null]);
            continue;
          }
          var m = item.match(/splice\((\d+)\)/);
          if (m) {
            m = parseInt(m[1]);
            if (isNaN(m)) return;
            actList.push(['splice', m]);
            continue;
          }
          var m = item.match(/slice\((\d+)\)/);
          if (m) {
            m = parseInt(m[1]);
            if (isNaN(m)) return;
            actList.push(['slice', m]);
            continue;
          }
          var m = item.match(/\[(\d+)%\w+\.length/);
          if (m) {
            m = parseInt(m[1]);
            if (isNaN(m)) return;
            actList.push(['swap', m]);
          }
        }
        return actList;
      },
      getNewChip: function(data) {
        var getObjPropFn = function(objectName, propName) {
          objectName = objectName.replace(/\$/g, '\\$');
          var placeRe = new RegExp('(?:var |,)?' + objectName + '={');
          var placePos = data.search(placeRe);
          if (placePos === -1) {
            throw new Error('Place is not found');
          }

          var place = data.substr(placePos, 300);
          propName = propName.replace(/\$/g, '\\$');
          var re = new RegExp(propName + ':function\\(([$\\w,]+)\\){([^}]+)}');
          var m = place.match(re);
          if (!m) {
            throw new Error('Place function is not found!');
          }

          var args = m[1];
          var statement = m[2];
          return {
            args: args,
            statement: statement
          };
        };
        var readAction = function(item) {
          var m = /([\w$]+)(?:\.([\w$]+)|\[("[\w$]+")\])\([\w$]+,?([\w$]+)?\)/.exec(item);
          if (!m) {
            throw new Error('readAction');
          }

          var objectName = m[1];
          var propName = m[2] || m[3];
          var arg = m[4];
          var fn = getObjPropFn(objectName, propName);
          if (/\.reverse/.test(fn.statement)) {
            return ['reverse', null];
          } else {
            if (!/^[\d]+$/.test(arg)) {
              throw new Error('Arg is not number');
            }

            if (/\.splice/.test(fn.statement)) {
              return ['splice', parseInt(arg)];
            } else if (/\.slice/.test(fn.statement)) {
              return ['slice', parseInt(arg)];
            } else {
              return ['swap', parseInt(arg)];
            }
          }
        };
        var readStatement = function(arg, statement) {
          arg = arg.replace(/\$/g, '\\$');
          var re = new RegExp('[\\w$]+(?:\\.[\\w$]+|\\["[\\w$]+"\\])\\(' + arg + '[^)]*\\)', 'g');
          var actionList = statement.match(re);
          if (!actionList) {
            throw new Error('readScope');
          }

          return actionList.map(function(item) {
            return readAction(item);
          });
        };
        var findDecodeFn = function(name) {
          name = name.replace(/\$/g, '\\$');
          var re = new RegExp('(?:function ' + name + '|(?:var |,|;\n)' + name + '=function)\\(([\\w$]+)\\){([^}]*)}[;,]');
          var m = re.exec(data);
          if (!m) {
            throw new Error('findConvertFn');
          }

          var variable = m[1];
          var statement = m[2];
          return readStatement(variable, statement);
        };

        var stsM = /,sts:(\d+)/.exec(data);
        if (!stsM) {
          throw new Error('Sts is not found');
        }
        var sts = parseInt(stsM[1]);

        var fnName = /[$_a-zA-Z0-9]+\.set\((?:[$_a-zA-Z0-9]+\.[$_a-zA-Z0-9]+\|\|)?"signature",([$_a-zA-Z0-9]+)\(/.exec(data);
        if (fnName) {
          mono.debug('new chip');
        } else {
          fnName = /(?:function ([$_a-zA-Z0-9]+)|(?:var |,|;\n)([$_a-zA-Z0-9]+)=function)\(([\w$]+)\){\3=\3\.split\([^}]+;return \3\.join\([^}]+}[;,]/.exec(data);
          if (fnName) {
            mono.debug('alt chip');
            fnName = [fnName[0], fnName[1] || fnName[2]];
          }
        }
        if (!fnName) {
          throw new Error('Decode function name is not found!');
        }

        var actionList = findDecodeFn(fnName[1]);

        if (!actionList.length) {
          throw new Error('actionList is empty');
        }

        return {
          actionList: actionList,
          sts: sts
        };
      },
      getChip: function(data) {
        var sts = data.match(/,sts:(\d+)/);
        sts = sts && sts[1];

        var actList = [];
        var funcName = data.match(/\.sig\|\|([$_a-zA-Z0-9]+)\(/);
        if (!funcName) {
          return this.getNewChip(data);
        } else {
          mono.debug('old chip');
        }
        funcName = funcName[1];
        funcName = funcName.replace(/\$/g, '\\$');
        var func = data.match(new RegExp("((?:function " + funcName + "|(?:var |,|;\n)" + funcName + "=function)\\(([\\w$]+)\\){[^}]*})[;,]"));
        if (!func) {
          throw new Error('Func is not found!');
        }
        var vName = func[2];
        func = func[1];
        var regexp = new RegExp("[\\w$]+\\.[\\w$]+\\(" + vName + "[^)]*\\)", 'g');
        var sFuncList = func.match(regexp);
        if (!sFuncList) {
          actList = this.readObfFunc(func, data);
          if (actList && actList.length > 0) {
            return {
              actionList: actList,
              sts: sts
            };
          }
          throw new Error('readObfFunc actions is not found');
        }
        var objName = '';
        var objElList = [];
        for (var i = 0, item; item = sFuncList[i]; i++) {
          var m = item.match(/([\w$]+)\.([\w$]+)\([\w$]+,?([\w$]+)?\)/);
          if (m) {
            objName = m[1];
            objElList.push({
              name: m[2],
              arg: parseInt(m[3])
            });
          }
        }
        var sPos = data.indexOf('var ' + objName + '={');
        if (sPos === -1) {
          sPos = data.indexOf(',' + objName + '={');
        }
        if (sPos === -1) {
          sPos = data.indexOf(objName + '={');
        }
        var place = data.substr(sPos, 300);
        for (i = 0, item; item = objElList[i]; i++) {
          var vName = item.name;
          regexp = new RegExp(vName + ":(function\\([$\\w,]+\\){[^}]+})");
          var sF = place.match(regexp);
          if (!sF) {
            throw new Error('Match fn error');
          }
          sF = sF[1];
          if (sF.indexOf('splice') !== -1) {
            if (isNaN(item.arg)) {
              throw new Error('Match splice error');
            }
            actList.push(['splice', item.arg]);
          } else
          if (sF.indexOf('slice') !== -1) {
            if (isNaN(item.arg)) {
              throw new Error('Match slice error');
            }
            actList.push(['slice', item.arg]);
          } else
          if (sF.indexOf('reverse') !== -1) {
            item.arg = null;
            actList.push(['reverse', item.arg]);
          } else {
            if (isNaN(item.arg)) {
              throw new Error('Match reverse error');
            }
            actList.push(['swap', item.arg]);
          }
        }
        return {
          actionList: actList,
          sts: sts
        };
      },
      getPlayer: function(url) {
        var self = this;

        if (url.substr(0, 2) === '//') {
          url = 'https:' + url;
        } else
        if (url[0] === '/') {
          url = 'https://www.youtube.com' + url;
        }

        var headers = {};
        if (mono.isChromeMobile || mono.isFirefoxMobile) {
          headers['User-Agent'] = mono.getDesktopUa();
        }

        var rp = youtube_com_embed._rp;

        return rp({
          url: url,
          headers: headers
        });
      },
      playerUrlSts: {},
      storage: {},
      saveSignature: function(signature) {
        var self = this;
        var Promise = mono.Promise;

        if (!self.playerUrlSts[signature.playerUrl]) {
          self.playerUrlSts[signature.playerUrl] = signature.sts;
        }

        var existsActionList = self.storage[signature.sts];
        if (!existsActionList || JSON.stringify(existsActionList) !== JSON.stringify(signature.actionList)) {
          Object.keys(self.storage).sort(function(a, b) {
            return a < b ? 1 : -1
          }).slice(3).forEach(function(key) {
            delete self.storage[key];
          });

          if (signature.sts && signature.actionList) {
            self.storage[signature.sts] = signature.actionList;
          }

          return new Promise(function(resolve) {
            mono.storage.set({
              ytDechipList: self.storage
            }, resolve);
          });
        }
      },
      isTrackError: {},
      /**
       * @typedef {{}} YtSignature
       * @property {number} sts
       * @property {string} playerUrl
       * @property {string} [actionList]
       */
      /**
       * @param {string} playerUrl
       * @param {number} [sts]
       * @return {Promise.<YtSignature>}
       */
      dechip: function(playerUrl, sts) {
        var self = this;
        var Promise = mono.Promise;

        if (!sts) {
          sts = self.playerUrlSts[playerUrl];
        }

        var cache = self.storage[sts];
        if (cache) {
          return Promise.resolve({
            sts: sts,
            actionList: cache,
            playerUrl: playerUrl
          });
        }

        return self.getPlayer(playerUrl).then(function(response) {
          return self.getChip(response);
        }).then(function(result) {
          return {
            sts: result.sts,
            actionList: result.actionList,
            playerUrl: playerUrl
          };
        }).catch(function(err) {
          var sigUrl = '';
          var m = /\/(?:[^\/]+)?player-([^\/]+)\//.exec(playerUrl);
          if (m) {
            sigUrl = m[1];
          } else {
            sigUrl = 'unknownPlayerName';
          }
          if (!self.isTrackError[sigUrl]) {
            self.isTrackError[sigUrl] = 1;
            sigUrl && sts && engine.track({
              t: 'event',
              ec: 'youtube',
              ea: 'pError',
              el: sts + ' ' + sigUrl
            });
          }
          throw err;
        });
      }
    },

    /**
     * @private
     */
    _prepareLastSts: function() {
      var _this = this;
      var Promise = mono.Promise;
      if (_this._stsIsLoaded) {
        return Promise.resolve();
      }
      _this._stsIsLoaded = true;

      return new Promise(function(resolve) {
        mono.storage.get('ytDechipList', resolve);
      }).then(function(storage) {
        var stsObj = storage.ytDechipList || {};
        _this._ytHtml5SigDecipher.storage = stsObj;

        var inlineSts = _this.lastSts;
        var inlineStsNum = inlineSts[0];
        var inlineStsActions = inlineSts[1];
        stsObj[inlineStsNum] = inlineStsActions;

        var lastStsNum = Object.keys(stsObj).sort(function(a, b) {
          return a < b ? 1 : -1
        }).shift();
        var lastStsActions = stsObj[lastStsNum];

        if (inlineStsNum < lastStsNum) {
          _this.lastSts[0] = lastStsNum;
          _this.lastSts[1] = lastStsActions;
        }
      });
    },
    _rp: function(options) {
      var Promise = mono.Promise;
      return new Promise(function(resolve, reject) {
        mono.request(options, function(err, resp, data) {
          if (err && typeof err === 'string') {
            err = new Error(err);
          }
          err ? reject(err) : resolve(data);
        });
      });
    }
  };

  engine.modules.youtube = youtube_com_embed;
  var facebook_com_embed = {
    getFacebookLinks: function(request, callback) {
      var callback_links = function(links, title, thumb, duration) {
        var response = {
          action: request.action,
          extVideoId: request.extVideoId,
          links: links || null,
          title: title || '',
          thumb: thumb || '',
          duration: duration || ''
        };

        callback(response);
      };

      facebook_com_embed._getFacebookLinks(request.extVideoId, callback_links);
      return true;
    },

    getFacebookLinksFromData: function(request, cb) {
      var data = request.data;
      var videoId = request.extVideoId;

      return facebook_com_embed.getLinksFromData2(data, videoId, true, function(links, title, thumb, duration) {
        var response = {
          action: 'getFacebookLinksFromData',
          extVideoId: request.extVideoId,
          links: links || null,
          title: title || '',
          thumb: thumb || '',
          duration: duration || ''
        };

        cb(response);
      });
    },

    _getFacebookLinks: function(videoId, cb) {
      mono.request({
        type: 'GET',
        url: 'https://www.facebook.com/video.php?v=' + videoId,
        headers: {
          'Cookie': ''
        }
      }, function(err, resp, data) {
        if (err || !data) {
          return cb();
        }

        facebook_com_embed.getLinksFromData(data, videoId, cb);
      });
    },
    getLinksFromData: function(data, videoId, cb) {
      "use strict";
      var match = data.match(/\["params","([^"]*)"\]/im);
      var title = '';

      if (!match) {
        return this.getLinksFromData2(data, videoId, false, cb);
      }
      var videoData = null;
      try {
        videoData = JSON.parse(decodeURIComponent(JSON.parse('"' + match[1] + '"'))).video_data;
        if (videoData.progressive) {
          videoData = videoData.progressive;
        }
        if (!videoData) {
          return cb();
        }
      } catch (e) {
        return cb();
      }

      var thumb = null;
      var duration = null;

      var links = [];
      var typeMap = {
        sd_src: 'SD',
        hd_src: 'HD'
      };
      if (!Array.isArray(videoData)) {
        videoData = [videoData];
      }
      for (var i = 0, item; item = videoData[i]; i++) {
        ['sd_src', 'hd_src'].forEach(function(type) {
          if (item.thumbnail_src) {
            thumb = item.thumbnail_src;
          }

          if (item.video_duration) {
            duration = item.video_duration;
          }

          if (!item[type]) {
            return;
          }

          var ext = facebook_com_embed.getFileExtension(item[type], 'mp4');
          links.push({
            url: item[type],
            name: typeMap[type],
            type: ext,
            ext: ext.toUpperCase()
          });
        });
      }

      cb(links, title, thumb, duration);
    },

    getLinksFromData2: function(data, videoId, noPage, cb) {
      "use strict";
      var title = '';

      var params = null;

      var onScript = function(data) {
        return data.split(/"?videoData"?:\[/).some(function(data) {
          return mono.findJsObject(data).some(function(_params) {
            if ((_params.sd_src || _params.hd_src) && String(_params.video_id) === String(videoId)) {
              params = _params;
              return true;
            }
          });
        });
      };

      if (noPage) {
        onScript(data);
      } else {
        mono.getPageScript(data, [/"?videoData"?:\[/]).some(onScript);
      }

      if (!params) {
        return cb();
      }

      var links = [];

      var ext;
      if (params.sd_src) {
        ext = facebook_com_embed.getFileExtension(params.sd_src, 'mp4');
        links.push({
          url: params.sd_src,
          name: 'SD',
          type: ext,
          ext: ext.toUpperCase()
        });
      }
      if (params.hd_src) {
        ext = facebook_com_embed.getFileExtension(params.hd_src, 'mp4');
        links.push({
          url: params.hd_src,
          name: 'HD',
          type: ext,
          ext: ext.toUpperCase()
        });
      }

      return cb(links, title, params.thumbnail_src, params.video_duration);
    },

    getFileExtension: function(str, def) {
      var ext = str.match(/\.([a-z0-9]{3,4})(\?|$)/i);
      if (ext) {
        ext = ext[1];
        return ext.toLowerCase();
      }

      return (def ? def : '');
    },

    getFacebookPhotoUrl: function(message, cb) {
      if (!message.fbid) {
        return cb();
      }
      mono.request({
        url: 'https://www.facebook.com/photo.php?fbid=' + message.fbid
      }, function(err, resp, data) {
        if (err || !data) {
          return cb();
        }

        var m = data.match(/<a[^>]+fbPhotosPhotoActionsItem[^>]+href="([^">]+dl=1)"[^>]+>/i);
        if (m) {
          var url = m[1].replace(/&amp;/g, '&');
          return cb([url]);
        }

        var links = [];
        var sizeLinkMap = {};
        var m = data.match(/(<a[^>]+rel="theater"[^>]+>)/ig);
        m && m.forEach(function(linkHtml) {
          var m = linkHtml.match(/data-pl[os]i="[^"]+"/ig);
          m && m.forEach(function(item) {
            var pos = item.indexOf('=');
            if (pos !== -1) {
              var key = item.substr(0, pos);
              var value = item.substr(pos + 1);
              value = value.substr(1, value.length - 2).replace(/&amp;/g, '&');
              sizeLinkMap[key] = value;
              links.push(value);
            }
          });
        });

        if (sizeLinkMap['data-ploi']) {
          return cb([sizeLinkMap['data-ploi']]);
        }
        return cb(links);
      });
      return true;
    }
  };

  engine.modules.facebook = facebook_com_embed;
  var mail_ru_embed = {
    getMailruLinks: function(request, callback) {
      function callback_links(links, title, thumb, vid, duration) {
        var response = {
          action: request.action,
          extVideoId: vid || request.extVideoId,
          links: links,
          title: title,
          thumb: thumb,
          duration: duration
        };

        callback(response);
      }

      mail_ru_embed._getMailruLinks(request.extVideoId, callback_links);
      return true;
    },
    _getMailruLinks: function(pathname, callback) {
      "use strict";
      var metadataUrl, vPath = pathname;
      var videoId = pathname.match(/\/([^\/]+)\/([^\/]+)\/video\/(.+).html/);
      if (!videoId) {
        videoId = pathname.match(/embed\/([^\/]+)\/([^\/]+)\/(.+).html/);
      }
      if (videoId) {
        metadataUrl = 'http://api.video.mail.ru/videos/' + videoId[1] + '/' + videoId[2] + '/' + videoId[3] + '.json';
        vPath = videoId[1] + '/' + videoId[2] + '/video/' + videoId[3] + '.html';
      }
      if (metadataUrl) {
        return mail_ru_embed.onGetMailruMetadataUrl(metadataUrl, vPath, callback);
      }
      mono.request({
        url: 'http://my.mail.ru/' + pathname
      }, function(err, resp, data) {
        if (err || !data) {
          return callback();
        }

        var jsonRe = /"metaUrl":/;
        var pageConfig = null;
        mono.getPageScript(data, jsonRe).some(function(script) {
          return mono.findJson(script, jsonRe).some(function(json) {
            if (json.metaUrl) {
              pageConfig = json;
              return true;
            }
          });
        });

        if (pageConfig) {
          metadataUrl = pageConfig.metaUrl;
          mail_ru_embed.onGetMailruMetadataUrl(metadataUrl, vPath, callback);
          return;
        }

        data = data.match(/<meta\s+content="[^"]+(videoapi\.my\.mail[^&]+)&[^"]+"[^>]+\/>/);
        if (!data) {
          return callback();
        }
        data = decodeURIComponent(data[1]);
        var vid = data.substr(data.lastIndexOf('/') + 1);
        metadataUrl = 'http://videoapi.my.mail.ru/videos/' + vid + '.json';
        mail_ru_embed.onGetMailruMetadataUrl(metadataUrl, vPath, callback);
      });
    },
    onGetMailruMetadataUrl: function(metadataUrl, vPath, callback) {
      mail_ru_embed.getMailruMetadata(metadataUrl, function(data) {
        if (!data || typeof data === 'string') {
          return callback();
        }
        mail_ru_embed.readMailruMetadata(data, function(_links, title, thumb, duration) {
          callback(mail_ru_embed.prepMailruLinks(_links), title, thumb, vPath, duration);
        });
      });
    },
    prepMailruLinks: function(_links) {
      if (!_links) {
        return;
      }
      var links = [];
      for (var i = 0, link; link = _links[i]; i++) {
        var url = link.url;
        var format = 'FLV';
        if (url.indexOf('.mp4') !== -1) {
          format = 'MP4';
        }
        if (url.indexOf('.mov') !== -1) {
          format = 'MOV';
        }
        if (url.indexOf('.mpg') !== -1) {
          format = 'MPG';
        }
        if (!link.quality) {
          link.quality = '-?-';
        }
        var quality = link.quality.toUpperCase();

        var qList = ['1080P', '720P', '480P', '360P', '272P'];
        var tList = ['1080', '720', '480', '360', '272'];

        var qPos = qList.indexOf(quality);
        if (qPos !== -1) {
          quality = tList[qPos];
        }

        var ext = format.toLowerCase();
        links.push({
          url: url,
          subname: quality,
          name: format,
          ext: ext
        });
      }
      links.sort(function(a, b) {
        if (a.subname === 'HD') {
          return 1;
        }
        return a.subname > b.subname;
      });
      return links;
    },
    getMailruMetadata: function(url, cb) {
      if (!url) {
        return cb();
      }
      mono.request({
        url: url,
        json: true
      }, function(err, resp, json) {
        if (err || !json) {
          return cb();
        }

        cb(json);
      });
    },
    readMailruMetadata: function(metadata, cb) {
      var links = [],
        title;
      /**
       * @namespace metadata.provider Object
       * @namespace metadata.movie Object
       * @namespace metadata.videos Object
       * @namespace metadata.meta Object
       * @namespace metadata.meta.poster Object
       */
      var duration = undefined;
      var thumb = undefined;
      if (metadata.meta) {
        thumb = metadata.meta.poster;
        duration = metadata.meta.duration;
      }
      if (metadata.provider === 'UPLOADED') {
        title = metadata.movie ? metadata.movie.title : undefined;
        if (!metadata.videos) {
          return cb();
        }
        metadata.videos.forEach(function(item) {
          links.push({
            quality: item.name,
            url: item.url,
            title: title
          });
        });
      } else
      if (metadata.provider === 'ugc') {
        title = metadata.meta ? metadata.meta.title : undefined;
        if (!metadata.videos) {
          return cb();
        }
        metadata.videos.forEach(function(item) {
          links.push({
            quality: item.key,
            url: item.url,
            title: title
          });
        });
      } else
      if (metadata.provider === 'pladform') {
        title = metadata.meta ? metadata.meta.title : undefined;
        var okEmbed = engine.modules.odnoklassniki;
        okEmbed.getPladformVideo({
          extVideoId: {
            playerId: metadata.meta.playerId,
            videoId: metadata.meta.videoId
          }
        }, function(response) {
          if (!response) {
            return cb();
          }

          if (response.action === 'getRutubeLinks') {
            response.links = null;
          }

          var links = response.links;
          if (!links) {
            return cb();
          }
          links.forEach(function(item) {
            if (item.title === undefined) {
              item.title = title
            }
          });
          cb(links, title, thumb, duration);
        });
        return;
      }
      if (links.length === 0) {
        return cb();
      }
      return cb(links, title, thumb, duration);
    }
  };

  engine.modules.mail_ru = mail_ru_embed;
  var SaveFrom_Utils = {
    downloadParam: 'sfh--download',

    setStyle: function(node, style) {
      if (!node || !style)
        return;

      for (var i in style)
        node.style[i] = style[i];
    },


    getStyle: function(node, property) {
      return node && window.getComputedStyle && window.getComputedStyle(node, null).getPropertyValue(property);
    },

    addStyleRules: function(selector, rules, className) {
      var style = className ? document.querySelector('#savefrom-styles.' + className) : document.getElementById('savefrom-styles');
      if (!style) {
        style = document.createElement('style');
        style.id = 'savefrom-styles';
        if (className) {
          style.classList.add(className);
        }
        // maybe need for safari
        //style.appendChild(document.createTextNode(""));
        var s = document.querySelector('head style');
        if (s)
          // allow to override our styles
          s.parentNode.insertBefore(style, s);
        else
          document.querySelector('head').appendChild(style);
      }

      if (typeof(rules) == 'object') {
        var r = [];
        for (var i in rules)
          r.push(i + ':' + rules[i]);

        rules = r.join(';');
      }

      style.textContent += selector + '{' + rules + '}';
    },

    getPosition: function(node, parent) {
      var box = node.getBoundingClientRect();

      if (parent) {
        var parent_pos = parent.getBoundingClientRect();
        return {
          top: Math.round(box.top - parent_pos.top),
          left: Math.round(box.left - parent_pos.left),
          width: box.width,
          height: box.height
        }
      }
      return {
        top: Math.round(box.top + window.pageYOffset),
        left: Math.round(box.left + window.pageXOffset),
        width: box.width,
        height: box.height
      }
    },

    getSize: function(node) {
      return {
        width: node.offsetWidth,
        height: node.offsetHeight
      };
    },

    getMatchFirst: function(str, re) {
      var m = str.match(re);
      if (m && m.length > 1)
        return m[1];

      return '';
    },

    getElementByIds: function(ids) {
      for (var i = 0; i < ids.length; i++) {
        var node = document.getElementById(ids[i]);
        if (node)
          return node;
      }

      return null;
    },

    getParentByClass: function(node, name) {
      if (!node || name == '') {
        return false;
      }

      var parent;
      if (typeof name === 'object' && name.length > 0) {
        for (parent = node; parent; parent = parent.parentNode) {
          if (parent.nodeType !== 1) {
            return null;
          }
          for (var i = 0; i < name.length; i++) {
            if (parent.classList.contains(name[i])) {
              return parent;
            }
          }
        }
      } else {
        for (parent = node; parent; parent = parent.parentNode) {
          if (parent.nodeType !== 1) {
            return null;
          }
          if (parent.classList.contains(name)) {
            return parent;
          }
        }
      }

      return null;
    },

    getParentByTagName: function(node, tagName) {
      if (!node || !tagName) {
        return false;
      }

      for (var parent = node; parent; parent = parent.parentNode) {
        if (parent.nodeType !== 1) {
          return null;
        }

        if (parent.tagName === tagName) {
          return parent;
        }
      }

      return null;
    },

    getParentById: function(node, id) {
      for (var parent = node; parent; parent = parent.parentNode) {
        if (parent.nodeType !== 1) {
          return null;
        }

        if (parent.id === id) {
          return parent;
        }
      }

      return null;
    },

    hasChildrenTagName: function(node, tagName) {
      for (var i = 0, item; item = node.childNodes[i]; i++) {
        if (item.nodeType !== 1) {
          continue;
        }
        if (item.tagName === tagName) {
          return true;
        }
      }
      return false;
    },

    isParent: function(node, testParent) {
      if (!testParent || [1, 9, 11].indexOf(testParent.nodeType) === -1) {
        return false;
      }

      return testParent.contains(node);
    },


    emptyNode: function(node) {
      while (node.firstChild)
        node.removeChild(node.firstChild);
    },

    download: function(filename, url, requestOptions, callback) {
      if (!url)
        return false;

      filename = filename || this.getFileName(url);
      if (!filename)
        return false;

      if (!mono.global.preference.downloads) {
        return false;
      }

      var params = requestOptions || {};
      params.url = url;
      params.filename = filename;

      callback = callback || undefined;

      mono.sendMessage({
        action: 'downloadFile',
        options: params
      }, callback);

      return true;
    },

    downloadList: {
      showDownloadWarningPopup: function(onContinue, type) {
        var template = SaveFrom_Utils.playlist.getInfoPopupTemplate();

        mono.sendMessage({
          action: 'getWarningIcon',
          type: type
        }, function(icon) {
          template.icon.style.backgroundImage = 'url(' + icon + ')';
        });

        mono.create(template.textContainer, {
          append: [
            mono.create('p', {
              text: mono.global.language.warningPopupTitle,
              style: {
                color: '#0D0D0D',
                fontSize: '20px',
                marginBottom: '11px',
                marginTop: '13px'
              }
            }),
            mono.create('p', {
              text: mono.global.language.warningPopupDesc + ' ',
              style: {
                color: '#868686',
                fontSize: '14px',
                marginBottom: '13px',
                lineHeight: '24px',
                marginTop: '0px'
              },
              append: mono.create('a', {
                href: (mono.global.language.lang === 'ru' || mono.global.language.lang === 'uk') ? 'http://vk.com/page-55689929_49003549' : 'http://vk.com/page-55689929_49004259',
                text: mono.global.language.readMore,
                target: '_blank',
                style: {
                  color: '#4A90E2'
                }
              })
            }),
            mono.create('p', {
              style: {
                marginBottom: '13px'
              },
              append: [
                mono.create('label', {
                  style: {
                    color: '#868686',
                    cursor: 'pointer',
                    fontSize: '14px',
                    lineHeight: '19px'
                  },
                  append: [
                    mono.create('input', {
                      type: 'checkbox',
                      style: {
                        cssFloat: 'left',
                        marginLeft: '0px'
                      },
                      on: ['click', function() {
                        mono.sendMessage({
                          action: 'hideDownloadWarning',
                          set: this.checked ? 1 : 0
                        });
                      }]
                    }),
                    mono.global.language.noWarning
                  ]
                })
              ]
            })
          ]
        });

        var cancelBtn = undefined;
        var continueBtn = undefined;
        mono.create(template.buttonContainer, {
          append: [
            cancelBtn = mono.create('button', {
              text: mono.global.language.cancel,
              style: {
                height: '27px',
                width: '118px',
                backgroundColor: '#ffffff',
                border: '1px solid #9e9e9e',
                margin: '12px',
                marginBottom: '11px',
                marginRight: '4px',
                borderRadius: '5px',
                fontSize: '14px',
                cursor: 'pointer'
              }
            }),
            continueBtn = mono.create('button', {
              text: mono.global.language.continue,
              style: {
                height: '27px',
                width: '118px',
                backgroundColor: '#ffffff',
                border: '1px solid #9e9e9e',
                margin: '12px',
                marginBottom: '11px',
                marginRight: '8px',
                borderRadius: '5px',
                fontSize: '14px',
                cursor: 'pointer'
              }
            })
          ]
        });

        cancelBtn.addEventListener('click', function(e) {
          var popup = template.body.parentNode;
          mono.trigger(popup.lastChild, 'click');
        });

        continueBtn.addEventListener('click', function(e) {
          e.preventDefault();
          e.stopPropagation();

          onContinue();
          mono.trigger(cancelBtn, 'click');
        });

        SaveFrom_Utils.popupDiv(template.body, 'dl_warning_box_popup');
      },
      startChromeDownloadList: function(options) {
        var folderName = options.folderName;
        var linkList = options.list;


        if (folderName) {
          folderName += '/';
        }

        return mono.sendMessage({
          action: 'downloadList',
          fileList: linkList,
          folder: folderName
        });
      },
      startOldChromeDownloadList: function(options, hideDialog) {
        var folderName = options.folderName;
        var linkList = options.list;
        var dataType = options.type;

        if (folderName) {
          folderName += '/';
        }

        var itemIndex = 0;
        var pause = false;
        var timeout = 500;

        var focusEl = document.body;

        focusEl.focus();

        if (!hideDialog) {
          focusEl.onblur = function() {
            pause = true;
          };
        }

        var nextOneFile = function() {
          var item = linkList[itemIndex];
          itemIndex++;

          if (item === undefined) {
            return;
          }

          if (mono.global.preference.downloads) {
            SaveFrom_Utils.download(folderName + item.filename, item.url);
          } else {
            mono.trigger(mono.create('a', {
              download: item.filename,
              href: item.url,
              on: ['click', function(e) {
                SaveFrom_Utils.downloadOnClick(e);
              }]
            }), 'click', {
              cancelable: true,
              altKey: true
            });
          }

          if (pause) {
            SaveFrom_Utils.downloadList.showDownloadWarningPopup(function() {
              pause = false;
              focusEl.focus();
              nextOneFile();
            }, dataType);
          } else {
            if (itemIndex > 5 && timeout) {
              timeout = undefined;
              focusEl.onblur = undefined;
              pause = false;
              if (mono.global.preference.downloads) {
                mono.sendMessage({
                  action: 'downloadList',
                  fileList: linkList.slice(itemIndex),
                  folder: folderName
                });
                return;
              }
            }

            setTimeout(function() {
              nextOneFile();
            }, timeout);
          }
        };

        nextOneFile();
      },
      startDownload: function(options) {
        options.list.forEach(function(item) {
          item.filename = mono.fileName.modify(item.filename);
        });

        options.folderName = mono.fileName.modify(options.folderName);

        if ((mono.isChrome && mono.global.preference.downloads) || mono.isFirefox) {
          return SaveFrom_Utils.downloadList.startChromeDownloadList(options);
        } else
        if (mono.isGM || mono.isSafari) {
          return mono.sendMessage({
            action: 'hideDownloadWarning'
          }, function(state) {
            SaveFrom_Utils.downloadList.startOldChromeDownloadList(options, state);
          });
        }
      },
      showBeforeDownloadPopup: function(list, options) {
        options.list = list;
        var type = options.type;
        var folderName = options.folderName;
        var onContinue = options.onContinue || SaveFrom_Utils.downloadList.startDownload;
        var onShowList = options.onShowList || SaveFrom_Utils.playlist.popupFilelist;
        var count = options.count || list.length;
        var template = SaveFrom_Utils.playlist.getInfoPopupTemplate();

        mono.sendMessage({
          action: 'getWarningIcon',
          color: '#00CCFF',
          type: type
        }, function(icon) {
          template.icon.style.backgroundImage = 'url(' + icon + ')';
        });

        var showListLink = [];
        if (onShowList) {
          showListLink = [' (', mono.create('a', {
            href: '#',
            text: mono.global.language.vkListOfLinks.toLowerCase()
          }), ')'];
          showListLink[1].addEventListener('click', function(e) {
            e.preventDefault();
            e.stopPropagation();
            onShowList(options.list);
            mono.trigger(cancelBtn, 'click');
          });
        }

        mono.create(template.textContainer, {
          append: [
            mono.create('p', {
              text: folderName || mono.global.language.playlistTitle,
              style: {
                color: '#0D0D0D',
                fontSize: '20px',
                marginBottom: '11px',
                marginTop: '13px'
              }
            }),
            mono.create('p', {
              text: mono.global.language.vkFoundFiles.replace('%d', count),
              style: {
                color: '#868686',
                fontSize: '14px',
                marginBottom: '13px',
                lineHeight: '24px',
                marginTop: '0px'
              },
              append: showListLink
            }),
            mono.create('p', {
              text: mono.global.language.beforeDownloadPopupWarn,
              style: {
                color: '#868686',
                fontSize: '14px',
                marginBottom: '13px',
                lineHeight: '24px',
                marginTop: '0px'
              }
            })
          ]
        });

        var cancelBtn = undefined;
        var dlBtn = undefined;
        mono.create(template.buttonContainer, {
          append: [
            cancelBtn = mono.create('button', {
              text: mono.global.language.cancel,
              style: {
                height: '27px',
                width: '118px',
                backgroundColor: '#ffffff',
                border: '1px solid #9e9e9e',
                margin: '12px',
                marginBottom: '11px',
                marginRight: '4px',
                borderRadius: '5px',
                fontSize: '14px',
                cursor: 'pointer'
              }
            }),
            dlBtn = mono.create('button', {
              text: mono.global.language.continue,
              style: {
                height: '27px',
                width: '118px',
                backgroundColor: '#ffffff',
                border: '1px solid #9e9e9e',
                margin: '12px',
                marginBottom: '11px',
                marginRight: '8px',
                borderRadius: '5px',
                fontSize: '14px',
                cursor: 'pointer'
              }
            })
          ]
        });

        cancelBtn.addEventListener('click', function(e) {
          var popup = template.body.parentNode;
          mono.trigger(popup.lastChild, 'click');
        });

        dlBtn.addEventListener('click', function(e) {
          e.preventDefault();
          e.stopPropagation();

          onContinue(options);
          mono.trigger(cancelBtn, 'click');
        });

        SaveFrom_Utils.popupDiv(template.body, 'dl_confirm_box_popup');
      }
    },

    downloadLink: function(a, callback) {
      if (!a.href)
        return false;

      var filename = a.getAttribute('download');

      return this.download(filename, a.href, null, callback);
    },

    safariDlLink: function(e) {
      "use strict";
      if (e.button || e.ctrlKey || e.altKey || e.shitfKey) {
        return;
      }

      var me = null;

      var legacy = function(e) {
        var me = document.createEvent('MouseEvents');
        me.initMouseEvent('click', true, e.cancelable, window, 0,
          e.screenX, e.screenY, e.clientX, e.clientY,
          false, true, false, e.metaKey, e.button, e.relatedTarget);
        return me;
      };

      try {
        if (typeof MouseEvent !== 'function') {
          throw 'legacy';
        }
        me = new MouseEvent('click', {
          bubbles: true,
          cancelable: e.cancelable,
          screenX: e.screenX,
          screenY: e.screenY,
          clientX: e.clientX,
          clientY: e.clientY,
          ctrlKey: false,
          altKey: true,
          shiftKey: false,
          metaKey: e.metaKey,
          button: e.button,
          relatedTarget: e.relatedTarget
        });
      } catch (err) {
        me = legacy(e);
      }

      e.preventDefault();
      e.stopPropagation();

      this.dispatchEvent(me);
    },

    downloadOnClick: function(event, callback, options) {
      options = options || {};
      var _this = SaveFrom_Utils;

      var node = options.el || event.target;
      if (node.tagName !== 'A') {
        node = mono.getParent(node, 'A');
      }

      if (!node) {
        return;
      }

      if (mono.isSafari) {
        return _this.safariDlLink.call(node, event);
      }

      if (!mono.global.preference.downloads) {
        return;
      }

      if ((mono.isFirefox || mono.isGM) && /^blob:|^data:/.test(node.href)) {
        return;
      }

      if (event.button === 2) {
        return;
      }

      event.preventDefault();
      event.stopPropagation();

      _this.downloadLink(node, callback);
    },

    getQueryString: function(query, key_prefix, key_suffix) {
      if (!query || typeof(query) != 'object')
        return '';

      if (key_prefix === undefined)
        key_prefix = '';

      if (key_suffix === undefined)
        key_suffix = '';

      var str = '';
      for (var key in query) {
        if (str.length)
          str += '&';

        if (query[key] instanceof Object) {
          if (!key_prefix)
            key_prefix = '';

          if (!key_suffix)
            key_suffix = '';

          str += SaveFrom_Utils.getQueryString(query[key], key_prefix + key + "[", "]" + key_suffix);
        } else
          str += key_prefix + escape(key) + key_suffix + '=' + escape(query[key]);
      }

      return str;
    },

    decodeUnicodeEscapeSequence: function(text) {
      return text.replace(/\\u([0-9a-f]{4})/g, function(s, m) {
        m = parseInt(m, 16);
        if (!isNaN(m)) {
          return String.fromCharCode(m);
        }
      });
    },


    getFileExtension: function(str, def) {
      var ext = this.getMatchFirst(str, /\.([a-z0-9]{3,4})(\?|$)/i);
      if (ext)
        return ext.toLowerCase();

      return (def ? def : '');
    },


    getFileName: function(url) {
      var filename = this.getMatchFirst(url, /\/([^\?#\/]+\.[a-z\d]{2,6})(?:\?|#|$)/i);
      if (!filename)
        return filename;

      return mono.fileName.modify(filename);
    },


    getTopLevelDomain: function(domain) {
      if (!domain)
        return '';

      if (!domain.match(/^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}/))
        return domain;

      var a = domain.split('.');
      var l = a.length;

      if (l == 2)
        return domain;

      return (a[l - 2] + '.' + a[l - 1]);
    },


    dateToObj: function(ts, leadingZero) {
      var d = (ts === null || ts === undefined) ? new Date() : new Date(ts);

      if (leadingZero === undefined)
        leadingZero = true;

      var res = {
        year: d.getFullYear(),
        month: (d.getMonth() + 1),
        day: d.getDate(),
        hour: d.getHours(),
        min: d.getMinutes(),
        sec: d.getSeconds()
      };

      if (leadingZero) {
        for (var i in res) {
          if (res[i].toString().length == 1)
            res[i] = '0' + res[i];
        }
      }

      return res;
    },


    utf8Encode: function(str) {
      str = str.replace(/\r\n/g, "\n");
      var res = "";

      for (var n = 0; n < str.length; n++) {
        var c = str.charCodeAt(n);

        if (c < 128)
          res += String.fromCharCode(c);
        else if ((c > 127) && (c < 2048)) {
          res += String.fromCharCode((c >> 6) | 192);
          res += String.fromCharCode((c & 63) | 128);
        } else {
          res += String.fromCharCode((c >> 12) | 224);
          res += String.fromCharCode(((c >> 6) & 63) | 128);
          res += String.fromCharCode((c & 63) | 128);
        }

      }

      return res;
    },

    sizeHuman: function(size, round) {
      if (round == undefined || round == null)
        round = 2;

      var s = size,
        count = 0,
        sign = '',
        unite_spec = [
          mono.global.language.vkFileSizeByte,
          mono.global.language.vkFileSizeKByte,
          mono.global.language.vkFileSizeMByte,
          mono.global.language.vkFileSizeGByte,
          mono.global.language.vkFileSizeTByte
        ];

      if (s < 0) {
        sign = '-';
        s = Math.abs(s);
      }

      while (s >= 1000) {
        count++;
        s /= 1024;
      }

      if (round >= 0) {
        var m = round * 10;
        s = Math.round(s * m) / m;
      }

      if (count < unite_spec.length)
        return sign + s + ' ' + unite_spec[count];

      return size;
    },

    secondsToDuration: function(seconds) {
      if (!seconds || isNaN(seconds))
        return '';

      function zfill(time) {
        if (time < 10)
          return '0' + time;

        return time.toString();
      }

      var hours = Math.floor(seconds / 3600);
      seconds %= 3600;

      var minutes = Math.floor(seconds / 60);
      seconds %= 60;

      if (hours > 0)
        return hours + ":" + zfill(minutes) + ":" + zfill(seconds);

      return minutes + ":" + zfill(seconds);
    },

    svg: {
      icon: {
        download: 'M 4,0 4,8 0,8 8,16 16,8 12,8 12,0 4,0 z',
        info: 'M 8,1.55 C 11.6,1.55 14.4,4.44 14.4,8 14.4,11.6 11.6,14.4 8,14.4 4.44,14.4 1.55,11.6 1.55,8 1.55,4.44 4.44,1.55 8,1.55 M 8,0 C 3.58,0 0,3.58 0,8 0,12.4 3.58,16 8,16 12.4,16 16,12.4 16,8 16,3.58 12.4,0 8,0 L 8,0 z M 9.16,12.3 H 6.92 V 7.01 H 9.16 V 12.3 z M 8.04,5.91 C 7.36,5.91 6.81,5.36 6.81,4.68 6.81,4 7.36,3.45 8.04,3.45 8.72,3.45 9.27,4 9.27,4.68 9.27,5.36 8.72,5.91 8.04,5.91 z',
        noSound: 'M 11.4,5.05 13,6.65 14.6,5.05 16,6.35 14.4,7.95 16,9.55 14.6,11 13,9.35 11.4,11 10,9.55 11.6,7.95 10,6.35 z M 8,1.75 8,14.3 4,10.5 l -4,0 0,-4.75 4,0 z'
      },

      cache: {},

      getSrc: function(icon, color) {
        if (!this.icon[icon])
          return '';

        if (!this.cache[icon])
          this.cache[icon] = {};

        if (!this.cache[icon][color]) {
          this.cache[icon][color] = btoa(
            '<?xml version="1.0" encoding="UTF-8"?>' +
            '<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="16" height="16" viewBox="0 0 16 16" id="svg2" xml:space="preserve">' +
            '<path d="' + this.icon[icon] + '" fill="' + color + '" /></svg>'
          );
        }

        if (this.cache[icon][color])
          return 'data:image/svg+xml;base64,' + this.cache[icon][color];

        return '';
      },

      getSvg: function(icon, color, width, height) {
        var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
        var svgNS = svg.namespaceURI;
        svg.setAttribute('width', width || '16');
        svg.setAttribute('height', height || width || '16');
        svg.setAttribute('viewBox', '0 0 16 16');

        var path = document.createElementNS(svgNS, 'path');
        svg.appendChild(path);
        path.setAttribute('d', this.icon[icon]);

        if (color) {
          path.setAttribute('fill', color);
        }

        return svg;
      }
    },

    appendDownloadInfo: function(parent, color, boxStyle, btnStyle) {
      if (!color)
        color = '#a0a0a0';

      var info = document.createElement('span');
      info.appendChild(document.createTextNode(mono.global.language.downloadTitle));
      this.setStyle(info, {
        display: 'inline-block',
        position: 'relative',
        border: '1px solid ' + color,
        borderRadius: '5px',
        fontSize: '13px',
        lineHeight: '17px',
        padding: '2px 19px 2px 5px',
        marginTop: '5px',
        opacity: 0.9
      });

      if (boxStyle)
        this.setStyle(info, boxStyle);

      var close = document.createElement('span');
      close.textContent = String.fromCharCode(215);
      this.setStyle(close, {
        color: color,
        width: '14px',
        height: '14px',
        fontSize: '14px',
        fontWeight: 'bold',
        lineHeight: '14px',
        position: 'absolute',
        top: 0,
        right: 0,
        overflow: 'hidden',
        cursor: 'pointer'
      });

      if (btnStyle)
        this.setStyle(close, btnStyle);

      close.addEventListener('click', function() {
        info.parentNode.removeChild(info);
        mono.sendMessage({
          action: 'updateOption',
          key: 'moduleShowDownloadInfo',
          value: 0
        });
      }, false);

      info.appendChild(close);
      parent.appendChild(info);
    },

    /**
     * @param {Object|null} ctrStyle
     * @param {Object|null} btnStyle
     * @param {Object|null} svgStyle
     * @param {Object} details
     * @param {Object} details.url
     * @param {Element} [details.link]
     * @param {Boolean} [details.brackets]
     * @returns {{node: Element}}
     */
    getFileSizeIcon: function(ctrStyle, btnStyle, svgStyle, details) {
      var _this = this;
      var language = mono.global.language;
      details = details || {};
      ctrStyle = ctrStyle || {};
      btnStyle = btnStyle || {};
      svgStyle = svgStyle || {};

      var defaultColor = '#333333';
      var zeroSizeColor = '#ffac00';
      var errorColor = '#ff0000';

      var getIconBtn = function(iconColor) {
        return mono.create('div', {
          style: btnStyle,
          append: [
            mono.create(SaveFrom_Utils.svg.getSvg('info', iconColor), {
              style: svgStyle
            })
          ]
        });
      };

      var onIconClick = function(e) {
        e.stopPropagation();
        e.preventDefault();

        ctr.textContent = '...';
        var url = details.url;
        if (!url) {
          url = details.link && details.link.href;
        }
        mono.sendMessagePromise({
          action: 'getFileSize',
          url: url
        }).then(function(response) {
          if (response.error || !response.fileSize) {
            throw new Error(JSON.stringify(response));
          }

          var fileType = response.fileType || '';
          var size = _this.sizeHuman(response.fileSize, 2);
          var bitRate = '';
          if (details.link && /^audio\//i.test(fileType)) {
            var seconds = parseInt(details.link.dataset.savefromHelperDuration);
            if (seconds > 0) {
              bitRate += Math.floor((response.fileSize / seconds) / 125);
              bitRate += ' ' + mono.global.language.kbps;
            }
          }

          var text = '';
          if (bitRate) {
            text += size + ' ~ ' + bitRate;
          } else {
            text += size;
          }

          if (details.brackets) {
            text = '(' + text + ')';
          }

          ctr.textContent = text;
          ctr.title = fileType;
        }).catch(function(err) {
          mono.error(err);

          var icon;
          if (err.message === 'ZERO') {
            icon = getIconBtn(zeroSizeColor);
            icon.title = language.getFileSizeTitle;
          } else {
            icon = getIconBtn(errorColor);
            icon.title = language.getFileSizeFailTitle;
          }
          icon.addEventListener('click', onIconClick);

          ctr.textContent = '';
          ctr.appendChild(icon);
        });
      };

      var ctr = mono.create('div', {
        style: ctrStyle,
        append: [
          mono.create(getIconBtn(defaultColor), {
            title: language.getFileSizeTitle,
            on: ['click', onIconClick]
          })
        ]
      });

      return {
        node: ctr
      };
    },

    appendFileSizeIcon: function(link, iconStyle, textStyle, error, noBrackets, container) {
      var language = mono.global.language;
      iconStyle = iconStyle || {};
      textStyle = textStyle || {};

      var iconColor = '#333333';
      if (error === '0') {
        iconColor = '#ffac00';
      } else
      if (error) {
        iconColor = '#ff0000';
      } else
      if (iconStyle.color) {
        iconColor = iconStyle.color;
      }

      var defIconStyle = {
        width: '14px',
        height: '14px',
        marginLeft: '3px',
        verticalAlign: 'middle',
        position: 'relative',
        top: '-1px',
        cursor: 'pointer'
      };
      mono.extend(defIconStyle, iconStyle);

      var defTextStyle = {
        fontSize: '75%',
        fontWeight: 'normal',
        marginLeft: '3px',
        whiteSpace: 'nowrap'
      };
      mono.extend(defTextStyle, textStyle);

      var fsBtn = mono.create('img', {
        src: SaveFrom_Utils.svg.getSrc('info', iconColor),
        title: error ? language.getFileSizeFailTitle : language.getFileSizeTitle,
        style: defIconStyle
      });

      var _this = this;

      if (container) {
        container.appendChild(fsBtn);
      } else
      if (link.nextSibling) {
        link.parentNode.insertBefore(fsBtn, link.nextSibling);
      } else {
        link.parentNode.appendChild(fsBtn);
      }

      fsBtn.addEventListener("click", function(event) {
        event.preventDefault();
        event.stopPropagation();

        var node = mono.create('span', {
          text: '...',
          style: defTextStyle
        });

        fsBtn.parentNode.replaceChild(node, fsBtn);

        return mono.sendMessage({
          action: 'getFileSize',
          url: link.href
        }, function(response) {
          if (response.fileSize > 0) {
            var fileType = response.fileType || '';
            var size = _this.sizeHuman(response.fileSize, 2);
            var bitrate = '';
            if (/^audio\//i.test(fileType)) {
              var seconds = link.getAttribute('data-savefrom-helper-duration');
              seconds = seconds && parseInt(seconds);
              if (seconds > 0) {
                bitrate = Math.floor((response.fileSize / seconds) / 125);
                bitrate += ' ' + mono.global.language.kbps;
              }
            }
            var text = '';

            if (bitrate) {
              text = size + ' ~ ' + bitrate;
            } else {
              text = size;
            }

            if (!noBrackets) {
              text = '(' + text + ')';
            }

            node.textContent = text;
            node.title = fileType;
          } else
          if (response.error) {
            var errBtn = _this.appendFileSizeIcon(link, iconStyle, textStyle, true, noBrackets, document.createDocumentFragment());
            node.parentNode.replaceChild(errBtn, node);
          } else {
            var zeroBtn = _this.appendFileSizeIcon(link, iconStyle, textStyle, '0', noBrackets, document.createDocumentFragment());
            node.parentNode.replaceChild(zeroBtn, node);
          }
        });
      }, false);

      return fsBtn;
    },

    appendNoSoundIcon: function(link, iconStyle) {
      iconStyle = iconStyle || {};

      var noSoundIconColor = '#ff0000';
      if (iconStyle.color) {
        noSoundIconColor = iconStyle.color;
      }

      var defIconStyle = {
        width: '14px',
        height: '14px',
        marginLeft: '3px',
        verticalAlign: 'middle',
        position: 'relative',
        top: '-1px',
        cursor: 'pointer'
      };
      mono.extend(defIconStyle, iconStyle);

      var icon = mono.create('img', {
        src: SaveFrom_Utils.svg.getSrc('noSound', noSoundIconColor),
        title: mono.global.language.withoutAudio,
        style: defIconStyle
      });

      if (link.nextSibling) {
        link.parentNode.insertBefore(icon, link.nextSibling);
      } else
      if (link.parentNode) {
        link.parentNode.appendChild(icon);
      } else {
        link.appendChild(icon);
      }
    },

    video: {
      dataAttr: 'data-savefrom-video-visible',
      yt: {
        inited: false,

        show3D: false,
        showMP4NoAudio: false,

        showFormat: {
          'FLV': true,
          'MP4': true,
          'WebM': false,
          '3GP': false,
          'Audio AAC': false,
          'Audio Vorbis': false,
          'Audio Opus': false
        },

        format: {
          'FLV': {
            '5': {
              quality: '240'
            },
            '6': {
              quality: '270'
            },
            '34': {
              quality: '360'
            },
            '35': {
              quality: '480'
            }
          },

          'MP4': {
            '18': {
              quality: '360'
            },
            '22': {
              quality: '720'
            },
            '37': {
              quality: '1080'
            },
            '38': {
              quality: '8K'
            },
            '59': {
              quality: '480'
            },
            '78': {
              quality: '480'
            },
            '82': {
              quality: '360',
              '3d': true
            },
            '83': {
              quality: '240',
              '3d': true
            },
            '84': {
              quality: '720',
              '3d': true
            },
            '85': {
              quality: '1080',
              '3d': true
            },
            '160': {
              quality: '144',
              noAudio: true
            },
            '133': {
              quality: '240',
              noAudio: true
            },
            '134': {
              quality: '360',
              noAudio: true
            },
            '135': {
              quality: '480',
              noAudio: true
            },
            '136': {
              quality: '720',
              noAudio: true
            },
            '137': {
              quality: '1080',
              noAudio: true
            },
            '212': {
              quality: '480',
              noAudio: true
            },
            '213': {
              quality: '480',
              noAudio: true
            },
            '214': {
              quality: '720',
              noAudio: true
            },
            '215': {
              quality: '720',
              noAudio: true
            },
            '264': {
              quality: '1440',
              noAudio: true
            },
            '138': {
              quality: '8K',
              noAudio: true
            },
            '298': {
              quality: '720',
              noAudio: true,
              sFps: true
            },
            '299': {
              quality: '1080',
              noAudio: true,
              sFps: true
            },
            '266': {
              quality: '4K',
              noAudio: true
            }
          },

          'WebM': {
            '43': {
              quality: '360'
            },
            '44': {
              quality: '480'
            },
            '45': {
              quality: '720'
            },
            '46': {
              quality: '1080'
            },
            '167': {
              quality: '360',
              noAudio: true
            },
            '168': {
              quality: '480',
              noAudio: true
            },
            '169': {
              quality: '720',
              noAudio: true
            },
            '170': {
              quality: '1080',
              noAudio: true
            },
            '218': {
              quality: '480',
              noAudio: true
            },
            '219': {
              quality: '480',
              noAudio: true
            },
            '242': {
              quality: '240',
              noAudio: true
            },
            '243': {
              quality: '360',
              noAudio: true
            },
            '244': {
              quality: '480',
              noAudio: true
            },
            '245': {
              quality: '480',
              noAudio: true
            },
            '246': {
              quality: '480',
              noAudio: true
            },
            '247': {
              quality: '720',
              noAudio: true
            },
            '248': {
              quality: '1080',
              noAudio: true
            },
            '271': {
              quality: '1440',
              noAudio: true
            },
            '272': {
              quality: '8K',
              noAudio: true
            },
            '278': {
              quality: '144',
              noAudio: true
            },
            '100': {
              quality: '360',
              '3d': true
            },
            '101': {
              quality: '480',
              '3d': true
            },
            '102': {
              quality: '720',
              '3d': true
            },
            '302': {
              quality: '720',
              noAudio: true,
              sFps: true
            },
            '303': {
              quality: '1080',
              noAudio: true,
              sFps: true
            },
            '308': {
              quality: '1440',
              noAudio: true,
              sFps: true
            },
            '313': {
              quality: '4K',
              noAudio: true
            },
            '315': {
              quality: '4K',
              noAudio: true,
              sFps: true
            },
            '330': {
              quality: '144',
              noAudio: true,
              sFps: true
            },
            '331': {
              quality: '240',
              noAudio: true,
              sFps: true
            },
            '332': {
              quality: '360',
              noAudio: true,
              sFps: true
            },
            '333': {
              quality: '480',
              noAudio: true,
              sFps: true
            },
            '334': {
              quality: '720',
              noAudio: true,
              sFps: true
            },
            '335': {
              quality: '1080',
              noAudio: true,
              sFps: true
            },
            '336': {
              quality: '1440',
              noAudio: true,
              sFps: true
            },
            '337': {
              quality: '2160',
              noAudio: true,
              sFps: true
            }
          },

          '3GP': {
            '17': {
              quality: '144'
            },
            '36': {
              quality: '240'
            }
          },

          'Audio AAC': {
            '139': {
              quality: '48',
              ext: 'aac',
              noVideo: true
            },
            '140': {
              quality: '128',
              ext: 'aac',
              noVideo: true
            },
            '141': {
              quality: '256',
              ext: 'aac',
              noVideo: true
            },
            '256': {
              quality: '192',
              ext: 'aac',
              noVideo: true
            },
            '258': {
              quality: '384',
              ext: 'aac',
              noVideo: true
            }
          },

          'Audio Vorbis': {
            '171': {
              quality: '128',
              ext: 'webm',
              noVideo: true
            },
            '172': {
              quality: '192',
              ext: 'webm',
              noVideo: true
            }
          },

          'Audio Opus': {
            '249': {
              quality: '48',
              ext: 'opus',
              noVideo: true
            },
            '250': {
              quality: '128',
              ext: 'opus',
              noVideo: true
            },
            '251': {
              quality: '256',
              ext: 'opus',
              noVideo: true
            }
          }
        },


        init: function() {
          if (SaveFrom_Utils.video.yt.inited) {
            return;
          }

          ['Audio AAC', 'Audio Vorbis', 'Audio Opus'].forEach(function(item) {
            var formatType = SaveFrom_Utils.video.yt.format[item];
            for (var qualityValue in formatType) {
              formatType[qualityValue].quality += ' ' + mono.global.language.kbps;
            }
          });

          SaveFrom_Utils.video.yt.show3D = mono.global.preference.ytHide3D == '0';
          SaveFrom_Utils.video.yt.showMP4NoAudio = mono.global.preference.ytHideMP4NoAudio == '0';

          var show = false;
          var showAudio = false;
          for (var i in SaveFrom_Utils.video.yt.showFormat) {
            var prefName = 'ytHide' + i.replace(' ', '_');
            if (prefName === 'ytHideAudio_AAC') {
              prefName = 'ytHideAudio_MP4';
            }
            var value = mono.global.preference[prefName] == '0';
            if (i === 'Audio AAC') {
              showAudio = value;
            }
            SaveFrom_Utils.video.yt.showFormat[i] = value;
            if (value) {
              show = true;
            }
          }

          SaveFrom_Utils.video.yt.showFormat['Audio Vorbis'] = showAudio;
          SaveFrom_Utils.video.yt.showFormat['Audio Opus'] = showAudio;

          if (!show) {
            SaveFrom_Utils.video.yt.showFormat.FLV = true;
          }

          SaveFrom_Utils.video.yt.inited = true;
        },


        show: function(links, parent, showDownloadInfo, style, videoTitle) {
          style = style || {};

          var content = document.createElement('div');
          SaveFrom_Utils.setStyle(content, {
            display: 'inline-block',
            margin: '0 auto'
          });
          parent.appendChild(content);

          var box = document.createElement('div');
          SaveFrom_Utils.setStyle(box, {
            display: 'inline-block',
            padding: '0 90px 0 0',
            position: 'relative'
          });
          content.appendChild(box);

          var tbl = document.createElement('table');
          SaveFrom_Utils.setStyle(tbl, {
            emptyCells: 'show',
            borderCollapse: 'collapse',
            margin: '0 auto',
            padding: '0',
            width: 'auto'
          });
          box.appendChild(tbl);

          var hidden = false;

          for (var i in SaveFrom_Utils.video.yt.format) {
            if (SaveFrom_Utils.video.yt.append(links, i,
                SaveFrom_Utils.video.yt.format[i], tbl, style, videoTitle)) {
              hidden = true;
            }
          }

          for (var i in links) {
            if (i === 'ummy' || i === 'ummyAudio' || i === 'meta') {
              continue;
            }
            if (SaveFrom_Utils.video.yt.append(links, '', null, tbl, style, videoTitle)) {
              hidden = true;
            }

            break;
          }

          if (!tbl.firstChild) {
            parent.textContent = mono.global.language.noLinksFound;
            return;
          }

          if (!hidden)
            return;

          var more = document.createElement('span');
          more.textContent = mono.global.language.more + ' ' + String.fromCharCode(187);
          SaveFrom_Utils.setStyle(more, {
            color: '#555',
            border: '1px solid #a0a0a0',
            borderRadius: '3px',
            display: 'block',
            fontFamily: 'Arial',
            fontSize: '15px',
            lineHeight: '17px',
            padding: '1px 5px',
            position: 'absolute',
            bottom: '3px',
            right: '0',
            cursor: 'pointer'
          });

          if (style.btn && typeof(style.btn) == 'object')
            SaveFrom_Utils.setStyle(more, style.btn);

          box.appendChild(more);

          more.addEventListener('click', function(event) {
            event.preventDefault();
            event.stopPropagation();

            var e = parent.querySelectorAll('*[' + SaveFrom_Utils.video.dataAttr + ']');
            for (var i = 0; i < e.length; i++) {
              var visible = e[i].getAttribute(SaveFrom_Utils.video.dataAttr);
              var display = 'none',
                symbol = String.fromCharCode(187);
              if (visible == '0') {
                visible = '1';
                display = '';
                symbol = String.fromCharCode(171);
              } else
                visible = '0';

              e[i].style.display = display;
              e[i].setAttribute(SaveFrom_Utils.video.dataAttr, visible);
              this.textContent = mono.global.language.more + ' ' + symbol;
            }

            return false;
          }, false);


          if (showDownloadInfo === 1) {
            var color = '#a0a0a0',
              a = tbl.querySelector('td a');

            content.appendChild(document.createElement('br'));
            SaveFrom_Utils.appendDownloadInfo(content, color, null, {
              width: '16px',
              height: '16px',
              fontSize: '16px',
              lineHeight: '16px'
            });
          }
        },


        append: function(links, title, format, parent, style, videoTitle) {
          var hidden = false;

          var aStyle = {
            whiteSpace: 'nowrap'
          };

          var sStyle = {
            fontSize: '75%',
            fontWeight: 'normal',
            marginLeft: '3px',
            whiteSpace: 'nowrap'
          };

          var tr = document.createElement('tr');

          var td = document.createElement('td');
          td.appendChild(document.createTextNode(title ? title : '???'));

          if (!title || !SaveFrom_Utils.video.yt.showFormat[title]) {
            tr.setAttribute(SaveFrom_Utils.video.dataAttr, '0');
            tr.style.display = 'none';
            hidden = true;
          }

          SaveFrom_Utils.setStyle(td, {
            border: 'none',
            padding: '3px 15px 3px 0',
            textAlign: 'left',
            verticalAlign: 'middle'
          });

          tr.appendChild(td);

          td = document.createElement('td');
          SaveFrom_Utils.setStyle(td, {
            border: 'none',
            padding: '3px 0',
            textAlign: 'left',
            verticalAlign: 'middle',
            lineHeight: '17px'
          });
          tr.appendChild(td);

          var meta = links.meta || {};

          var sep = false;
          if (format) {
            for (var i in format) {
              if (links[i]) {
                var quality = format[i].quality;
                if (sep) {
                  td.lastChild.style.marginRight = '15px';
                  td.appendChild(document.createTextNode(' '));
                }

                var span = document.createElement('span');
                span.style.whiteSpace = 'nowrap';

                var a = document.createElement('a');
                a.href = links[i];
                a.title = mono.global.language.downloadTitle;

                if (meta[i]) {
                  if (meta[i].quality) {
                    quality = meta[i].quality;
                  }

                  if (format[i].sFps) {
                    quality += ' ' + (meta[i].fps || 60);
                  }
                }

                if (format[i]['3d']) {
                  a.textContent = '3D';
                } else {
                  a.textContent = quality;
                }
                if (videoTitle) {
                  var ext = format[i]['ext'];
                  if (!ext)
                    ext = title.toLowerCase();

                  a.setAttribute('download', mono.fileName.modify(videoTitle + '.' + ext));

                  a.addEventListener('click', function(event) {
                    SaveFrom_Utils.downloadOnClick(event);
                  }, false);
                }
                SaveFrom_Utils.setStyle(a, aStyle);
                if (style.link && typeof(style.link) == 'object')
                  SaveFrom_Utils.setStyle(a, style.link);

                span.appendChild(a);
                SaveFrom_Utils.appendFileSizeIcon(a, style.fsIcon, style.fsText);

                if (format[i]['3d']) {
                  if (!SaveFrom_Utils.video.yt.show3D) {
                    hidden = true;
                    span.setAttribute(SaveFrom_Utils.video.dataAttr, '0');
                    span.style.display = 'none';
                  }

                  var s = document.createElement('span');
                  s.textContent = quality;
                  SaveFrom_Utils.setStyle(s, sStyle);
                  if (style.text && typeof(style.text) == 'object')
                    SaveFrom_Utils.setStyle(s, style.text);

                  a.appendChild(s);
                }

                if (format[i]['noAudio']) {
                  if (!SaveFrom_Utils.video.yt.showMP4NoAudio) {
                    hidden = true;
                    span.setAttribute(SaveFrom_Utils.video.dataAttr, '0');
                    span.style.display = 'none';
                  }

                  SaveFrom_Utils.appendNoSoundIcon(a, style ? style.noSoundIcon : false);
                }

                td.appendChild(span);

                sep = true;

                delete links[i];
              }
            }
          } else {
            for (var i in links) {
              if (sep) {
                td.lastChild.style.marginRight = '15px';
                td.appendChild(document.createTextNode(' '));
              }

              var span = document.createElement('span');
              span.style.whiteSpace = 'nowrap';

              var a = document.createElement('a');
              a.href = links[i];
              a.title = mono.global.language.downloadTitle;
              a.textContent = i;
              SaveFrom_Utils.setStyle(a, aStyle);
              if (style.link && typeof(style.link) == 'object')
                SaveFrom_Utils.setStyle(a, style.link);

              span.appendChild(a);
              SaveFrom_Utils.appendFileSizeIcon(a, style.fsIcon, style.fsText);
              td.appendChild(span);

              sep = true;

              delete links[i];
            }
          }

          if (sep === false) {
            return;
          }
          parent.appendChild(tr);

          return hidden;
        }
      }
    }, // video


    playlist: {
      btnStyle: {
        display: 'block',
        fontWeight: 'bold',
        border: 'none',
        textDecoration: 'underline'
      },


      getFilelistHtml: function(links) {
        if (!links || links.length == 0)
          return;

        var rows = 0;
        var list = '';

        for (var i = 0; i < links.length; i++) {
          if (links[i].url) {
            list += links[i].url + '\r\n';
            rows++;
          }
        }

        if (list) {
          if (rows < 5) {
            rows = 5;
          } else
          if (rows > 14) {
            rows = 14;
          }

          var textareaNode;
          return mono.create(document.createDocumentFragment(), {
            append: [
              mono.create('p', {
                text: mono.global.language.filelistTitle,
                style: {
                  color: '#0D0D0D',
                  fontSize: '20px',
                  marginBottom: '11px',
                  marginTop: '5px'
                }
              }),
              mono.create('p', {
                style: {
                  marginBottom: '11px'
                },
                append: mono.parseTemplate(mono.global.language.filelistInstruction)
              }),
              mono.create('p', {
                text: mono.global.language.vkFoundFiles.replace('%d', links.length),
                style: {
                  color: '#000',
                  marginBottom: '11px'
                },
                append: mono.create('a', {
                  text: mono.global.language.playlist,
                  href: '#',
                  class: 'sf__playlist',
                  style: {
                    display: 'none',
                    cssFloat: 'right'
                  }
                })
              }),
              textareaNode = mono.create('textarea', {
                text: list,
                rows: rows,
                cols: 60,
                style: {
                  width: '100%',
                  whiteSpace: (mono.isFirefox || mono.isGmOnly) ? 'normal' : 'nowrap'
                }
              }),
              (!mono.isChrome && !mono.isFirefox) ? undefined : mono.create('button', {
                text: mono.global.language.copy,
                style: {
                  height: '27px',
                  backgroundColor: '#ffffff',
                  border: '1px solid #9e9e9e',
                  marginTop: '6px',
                  paddingLeft: '10px',
                  paddingRight: '10px',
                  borderRadius: '5px',
                  fontSize: '14px',
                  cursor: 'pointer',
                  cssFloat: 'right'
                },
                on: ['click', function(e) {
                  var _this = this;
                  _this.disabled = true;
                  if (mono.isFirefox) {
                    textareaNode.select();
                    document.execCommand("copy");
                  } else {
                    mono.sendMessage({
                      action: 'addToClipboard',
                      text: list
                    });
                  }
                  setTimeout(function() {
                    _this.disabled = false;
                  }, 1000);
                }],
                append: mono.create('style', {
                  text: mono.style2Text({
                    '#savefrom_popup_box': {
                      append: {
                        'button:hover:not(:disabled)': {
                          backgroundColor: '#597A9E !important',
                          borderColor: '#597A9E !important',
                          color: '#fff'
                        },
                        'button:active': {
                          opacity: 0.9
                        }
                      }
                    }
                  })
                })
              })
            ]
          });
        }
      },


      popupFilelist: function(links, title, playlist, id) {
        var content = SaveFrom_Utils.playlist.getFilelistHtml(links);
        if (!content)
          return;

        var popup = SaveFrom_Utils.popupDiv(content, id);
        if (playlist) {
          var a = popup.querySelector('a.sf__playlist');
          if (a) {
            a.addEventListener('click', function(event) {
              setTimeout(function() {
                SaveFrom_Utils.playlist.popupPlaylist(links, title, true, id);
              }, 100);
              event.preventDefault();
              return false;
            }, false);

            SaveFrom_Utils.setStyle(a, SaveFrom_Utils.playlist.btnStyle);
          }
        }
      },

      getInfoPopupTemplate: function() {
        var popupContainer = mono.create('div', {
          class: 'sf-infoPopupTemplate',
          style: {
            width: '400px',
            minHeight: '40px'
          }
        });

        var mediaIcon = mono.create('div', {
          style: {
            backgroundSize: '48px',
            backgroundRepeat: 'no-repeat',
            backgroundPosition: 'center top',
            display: 'inline-block',
            width: '60px',
            height: '60px',
            cssFloat: 'left',
            marginTop: '16px',
            marginRight: '10px'
          }
        });

        var textContent = mono.create('div', {
          style: {
            display: 'inline-block',
            width: '330px'
          }
        });

        var buttonWrap = mono.create('div', {
          style: {
            textAlign: 'right'
          },
          append: mono.create('style', {
            text: mono.style2Text({
              '.sf-infoPopupTemplate': {
                append: [{
                  'a.sf-button': {
                    padding: '1px 6px',
                    display: 'inline-block',
                    textAlign: 'center',
                    height: '23px',
                    lineHeight: '23px',
                    textDecoration: 'none'
                  }
                }, {
                  selector: ['button:hover', 'a.sf-button:hover'],
                  style: {
                    backgroundColor: '#597A9E !important',
                    borderColor: '#597A9E !important',
                    color: '#fff'
                  }
                }]
              }
            })
          })
        });

        popupContainer.appendChild(mediaIcon);
        popupContainer.appendChild(textContent);
        popupContainer.appendChild(buttonWrap);
        return {
          icon: mediaIcon,
          buttonContainer: buttonWrap,
          textContainer: textContent,
          body: popupContainer
        }
      },

      getM3U: function(links) {
        var text = '#EXTM3U\r\n';

        for (var i = 0; i < links.length; i++) {
          if (!links[i].duration)
            links[i].duration = '-1';

          if (links[i].title || links[i].duration) {
            text += '#EXTINF:' + links[i].duration + ',' +
              links[i].title + '\r\n';
          }

          text += links[i].url + '\r\n';
        }

        return text;
      },


      getPlaylistHtml: function(links, fileTitle) {
        if (!links || links.length == 0)
          return;

        var links_len = links.length;

        var d = SaveFrom_Utils.dateToObj();
        var dateStr = d.year + '-' + d.month + '-' + d.day + ' ' +
          d.hour + '-' + d.min;

        // M3U
        var m3uList = SaveFrom_Utils.playlist.getM3U(links);
        m3uList = m3uList.replace(/\r\n/g, '\n');

        var m3uUrl = mono.getDataUrl(m3uList, 'audio/x-mpegurl');

        var template = SaveFrom_Utils.playlist.getInfoPopupTemplate();

        mono.sendMessage({
          action: 'getWarningIcon',
          color: '#00CCFF',
          type: 'playlist'
        }, function(icon) {
          template.icon.style.backgroundImage = 'url(' + icon + ')';
        });

        mono.create(template.textContainer, {
          append: [
            mono.create('p', {
              text: fileTitle || mono.global.language.playlistTitle,
              style: {
                color: '#0D0D0D',
                fontSize: '20px',
                marginBottom: '11px',
                marginTop: '13px'
              }
            }),
            mono.create('p', {
              text: mono.global.language.playlistInstruction,
              style: {
                color: '#868686',
                fontSize: '14px',
                marginBottom: '13px',
                lineHeight: '24px',
                marginTop: '0px'
              }
            }),
            mono.create('a', {
              text: mono.global.language.filelist + ' (' + links_len + ')',
              href: '#',
              class: 'sf__playlist',
              style: {
                display: 'none',
                fontSize: '14px',
                marginBottom: '13px',
                lineHeight: '24px',
                marginTop: '0px'
              }
            })
          ]
        });

        if (!fileTitle) {
          fileTitle = 'playlist';
        }
        fileTitle += ' ' + dateStr;

        mono.create(template.buttonContainer, {
          append: [
            mono.create('a', {
              text: mono.global.language.download,
              href: m3uUrl,
              download: mono.fileName.modify(fileTitle + '.m3u'),
              class: 'sf-button',
              style: {
                width: '118px',
                backgroundColor: '#ffffff',
                border: '1px solid #9e9e9e',
                margin: '12px',
                marginBottom: '11px',
                marginRight: '8px',
                borderRadius: '5px',
                fontSize: '14px',
                cursor: 'pointer'
              }
            })
          ]
        });

        return template.body;
      },


      popupPlaylist: function(links, title, filelist, id) {
        var content = SaveFrom_Utils.playlist.getPlaylistHtml(links, title);
        if (!content)
          return;

        var popup = SaveFrom_Utils.popupDiv(content, id);
        if (filelist) {
          var a = popup.querySelector('a.sf__playlist');
          if (a) {
            a.addEventListener('click', function(event) {
              setTimeout(function() {
                SaveFrom_Utils.playlist.popupFilelist(links, title, true, id);
              }, 100);
              event.preventDefault();
              return false;
            }, false);

            a.style.display = 'inline';
            a = null;
          }
        }
        var dl_links = popup.querySelectorAll('a[download]');
        for (var i = 0, el; el = dl_links[i]; i++) {
          el.addEventListener('click', SaveFrom_Utils.downloadOnClick, false);
        }
      }
    },

    popupCloseBtn: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAWUlEQVQ4y2NgGHHAH4j1sYjrQ+WIAvFA/B+I36MZpg8V+w9VQ9Al/5EwzDBkQ2AYr8uwaXiPQ0yfkKuwGUayIYQMI8kQqhlEFa9RLbCpFv1US5BUzSLDBAAARN9OlWGGF8kAAAAASUVORK5CYII=',

    popupDiv: function(content, id, maxWidth, maxHeight, onClose) {
      if (!id) {
        id = 'savefrom_popup_box';
      }

      if (!maxWidth)
        maxWidth = 580;

      if (!maxHeight)
        maxHeight = 520;

      var popupBody = document.getElementById(id);
      if (popupBody) {
        popupBody.parentNode.removeChild(popupBody);
      }

      popupBody = mono.create('div', {
        id: id,
        style: {
          zIndex: '9999',
          display: 'block',
          cssFloat: 'none',
          position: 'fixed',
          margin: '0',
          padding: '0',
          visibility: 'hidden',
          color: '#000',
          background: '#fff',
          border: '3px solid #c0cad5',
          borderRadius: '7px',
          overflow: 'auto'
        }
      });


      var cnt = mono.create('div', {
        style: {
          display: 'block',
          cssFloat: 'none',
          position: 'relative',
          overflow: 'auto',
          margin: '0',
          padding: '10px 15px'
        }
      });

      if (typeof content === 'function') {
        content(cnt);
      } else {
        cnt.appendChild(content);
      }

      var btn = mono.create('img', {
        src: SaveFrom_Utils.popupCloseBtn,
        alt: 'x',
        width: 18,
        height: 18,
        style: {
          position: 'absolute',
          top: '10px',
          right: '15px',
          opacity: '0.5',
          cursor: 'pointer'
        },
        on: [
          ['mouseenter', function() {
            "use strict";
            this.style.opacity = '0.9';
          }],
          ['mouseleave', function() {
            "use strict";
            this.style.opacity = '0.5';
          }],
          ['click', function() {
            "use strict";
            if (popupBody.parentNode) {
              popupBody.parentNode.removeChild(popupBody);
            }
            if (onClose) {
              onClose();
            }
            return false;
          }]
        ]
      });

      cnt.appendChild(btn);
      popupBody.appendChild(cnt);
      document.body.appendChild(popupBody);

      if (popupBody.offsetWidth > maxWidth) {
        popupBody.style.width = maxWidth + 'px';
      }

      if (popupBody.offsetHeight > maxHeight) {
        popupBody.style.height = maxHeight + 'px';
        popupBody.style.width = (maxWidth + 20) + 'px';
      }

      setTimeout(function() {
        var l = Math.floor((window.innerWidth - popupBody.offsetWidth) / 2.0);
        var t = Math.floor((window.innerHeight - popupBody.offsetHeight) / 2.0);
        if (t < 0) {
          t = 0;
        }
        if (location.host.indexOf('youtu') !== -1 && t < 92) {
          t = 92;
          popupBody.style.height = (popupBody.offsetHeight - t - 10) + 'px';
        }
        if (l < 0) {
          l = 0;
        }
        SaveFrom_Utils.setStyle(popupBody, {
          top: t + 'px',
          left: l + 'px',
          visibility: 'visible'
        });
      });

      var onDocClose = function(event) {
        var node = event.target;
        if (node !== popupBody && !SaveFrom_Utils.isParent(node, popupBody)) {
          if (popupBody.parentNode) {
            popupBody.parentNode.removeChild(popupBody);
          }
          document.removeEventListener('click', onDocClose, false);
          if (onClose) {
            onClose();
          }
        }
      };

      setTimeout(function() {
        document.addEventListener('click', onDocClose, false);
      }, 100);

      popupBody.addEventListener('close', function() {
        if (popupBody.parentNode) {
          popupBody.parentNode.removeChild(popupBody);
        }
        document.removeEventListener('click', onDocClose, false);
        if (onClose) {
          onClose();
        }
      });

      popupBody.addEventListener('kill', function() {
        if (popupBody.parentNode) {
          popupBody.parentNode.removeChild(popupBody);
        }
        document.removeEventListener('click', onDocClose, false);
      });

      return popupBody;
    },

    popupDiv2: function(_details) {
      "use strict";
      var details = {
        id: 'savefrom_popup_box',
        containerStyle: null,
        bodyStyle: null,
        content: null,
        container: null,
        body: null
      };

      details._onClose = function() {
        document.removeEventListener('click', details._onClose);

        if (container.parentNode) {
          container.parentNode.removeChild(container);
        }

        details.onClose && details.onClose();
      };

      mono.extend(details, _details);

      var container = details.container = mono.create('div', {
        id: details.id,
        style: {
          zIndex: 9999,
          display: 'block',
          position: 'fixed',
          background: '#fff',
          border: '3px solid #c0cad5',
          borderRadius: '7px'
        },
        append: [
          mono.create('style', {
            text: mono.style2Text({
              selector: '#' + details.id,
              style: mono.styleReset
            })
          })
        ],
        on: [
          ['click', function(e) {
            e.stopPropagation();
          }]
        ]
      });

      var closeBtn = mono.create('img', {
        src: SaveFrom_Utils.popupCloseBtn,
        alt: 'x',
        width: 18,
        height: 18,
        style: {
          position: 'absolute',
          top: '10px',
          right: '15px',
          opacity: '0.5',
          cursor: 'pointer'
        },
        on: [
          ['mouseenter', function() {
            "use strict";
            this.style.opacity = '0.9';
          }],
          ['mouseleave', function() {
            "use strict";
            this.style.opacity = '0.5';
          }],
          ['click', details._onClose]
        ]
      });

      container.appendChild(closeBtn);

      var body = details.body = mono.create('div', {
        style: mono.extendPos({
          display: 'block',
          position: 'relative',
          padding: '10px 15px',
          overflow: 'auto'
        }, details.bodyStyle)
      });

      if (typeof details.content === 'function') {
        details.content(body);
      } else {
        body.appendChild(details.content);
      }

      container.appendChild(body);

      document.body.appendChild(container);
      document.addEventListener('click', details._onClose);

      return details;
    },

    // row - used for hide tooltip on mouseout
    // because node can dissaper from DOM before mouseout raised
    showTooltip: function(node, text, row, style) {
      if (!node)
        return;

      var tooltip = document.querySelector('.savefrom-tooltip');
      if (!tooltip) {
        tooltip = document.createElement('div');
        tooltip.className = 'savefrom-tooltip';
        SaveFrom_Utils.setStyle(tooltip, {
          'position': 'absolute',
          'opacity': 0,
          'zIndex': -1
        });
        if (style) {
          SaveFrom_Utils.setStyle(tooltip, style);
        }
      }

      tooltip.textContent = text;

      if (tooltip.lastNode && tooltip.lastNode === node) {
        fixPosition();
        return;
      }

      if (tooltip.lastNode) {
        mono.off(tooltip.lastNode, 'mouseleave', hide);
        mono.off(tooltip.lastNode, 'mousemove', fixPosition);
        tooltip.lastRow && mono.off(tooltip.lastRow, 'mouseleave', hide);
      }

      tooltip.lastNode = node;
      row && (tooltip.lastRow = row);

      mono.on(node, 'mouseleave', hide);
      mono.on(node, 'mousemove', fixPosition, false);
      row && mono.on(row, 'mouseleave', hide);

      document.body.appendChild(tooltip);
      fixPosition();

      function fixPosition(e) {
        if (e !== undefined) {
          e.stopPropagation();
        }
        var p = SaveFrom_Utils.getPosition(node),
          s = SaveFrom_Utils.getSize(tooltip);

        if (p.top == 0 && p.left == 0)
          return;

        p.top = p.top - s.height - 10;
        p.left = p.left - s.width / 2 + SaveFrom_Utils.getSize(node).width / 2;

        p.left = Math.min(p.left, document.body.clientWidth + document.body.scrollLeft - s.width);
        if (p.top < document.body.scrollTop)
          p.top = p.top + s.height + SaveFrom_Utils.getSize(node).height + 20;

        p.top += 'px';
        p.left += 'px';

        // show
        p.zIndex = 9999;
        p.opacity = 1;

        SaveFrom_Utils.setStyle(tooltip, p);
      }

      function hide() {
        if (tooltip.parentNode)
          document.body.removeChild(tooltip);

        tooltip.lastNode = null;
        tooltip.lastRow = null;
        SaveFrom_Utils.setStyle(tooltip, {
          zIndex: -1,
          opacity: 0
        });
        mono.off(node, 'mouseleave', hide);
        mono.off(node, 'mousemove', fixPosition);
        row && mono.off(row, 'mouseleave', hide);
      }
    },

    embedDownloader: {
      dataAttr: 'data-savefrom-get-links',
      dataIdAttr: 'data-savefrom-container-id',
      containerClass: 'savefrom-links-container',
      linkClass: 'savefrom-link',
      panel: null,
      lastLink: null,
      style: null,

      hostings: {
        'youtube': {
          re: [
            /^https?:\/\/(?:[a-z]+\.)?youtube\.com\/(?:#!?\/)?watch\?.*v=([\w\-]+)/i,
            /^https?:\/\/(?:[a-z0-9]+\.)?youtube\.com\/(?:embed|v)\/([\w\-]+)/i,
            /^https?:\/\/(?:[a-z]+\.)?youtu\.be\/([\w\-]+)/i
          ],
          action: 'getYoutubeLinks',
          prepareLinks: function(links) {
            var ret = [];
            var sfUtilsYt = SaveFrom_Utils.video.yt;
            var format = sfUtilsYt.format;

            var meta = links.meta || {};

            for (var formatName in format) {
              for (var iTag in format[formatName]) {
                var metaTag = meta[iTag] || {};
                if (links[iTag]) {
                  var type = formatName;
                  if (format[formatName][iTag].ext) {
                    type = format[formatName][iTag].ext;
                  }

                  var quality = format[formatName][iTag].quality;
                  if (metaTag.quality) {
                    quality = metaTag.quality;
                  }

                  if (format[formatName][iTag].sFps) {
                    quality += ' ' + (metaTag.fps || 60);
                  }

                  if (format[formatName][iTag]['3d']) {
                    quality += ' (3d)';
                  }

                  ret.push({
                    name: formatName + ' ' + quality,
                    type: type,
                    url: links[iTag],
                    noSound: format[formatName][iTag].noAudio
                  });
                }
              }
            }

            return ret;
          }
        },
        'vimeo': {
          re: [
            /^https?:\/\/(?:[\w\-]+\.)?vimeo\.com\/(?:\w+\#)?(\d+)/i,
            /^https?:\/\/player\.vimeo\.com\/video\/(\d+)/i,
            /^https?:\/\/(?:[\w\-]+\.)?vimeo\.com\/channels\/(?:[^\/]+)\/(\d+)$/i,
            /^https?:\/\/vimeo\.com\/(?:.+)clip_id=(\d+)/i
          ],
          action: 'getVimeoLinks',
          prepareLinks: function(links) {
            return links.map(function(link) {
              var ext = link.ext;
              if (!ext) {
                ext = 'MP4';
                if (link.url.search(/\.flv($|\?)/i) != -1)
                  ext = 'FLV';
              }

              link.name = link.name ? link.name : ext;
              link.type = link.type ? link.type : ext;
              link.ext = ext;

              return link;
            });
          }
        },

        'vk': {
          re: [
            /^https?:\/\/(?:[\w\-]+\.)?(?:vk\.com|vkontakte\.ru)\/(?:[^\/]+\/)*(?:[\w\-\.]+\?.*z=)?(video-?\d+_-?\d+\?list=[0-9a-z]+|video-?\d+_-?\d+)/i,
            /^https?:\/\/(?:[\w\-]+\.)?(?:vk\.com|vkontakte\.ru)\/video_ext\.php\?(.+)/i
          ],
          action: 'getVKLinks'
        },

        'dailymotion': {
          re: [
            /^http:\/\/(?:www\.)?dai\.ly\/([a-z0-9]+)_?/i,
            /^https?:\/\/(?:[\w]+\.)?dailymotion\.com(?:\/embed|\/swf)?\/video\/([a-z0-9]+)_?/i
          ],
          action: 'getDailymotionLinks'
        },

        'facebook': {
          re: [
            /^https?:\/\/(?:[\w]+\.)?facebook\.com(?:\/video)?\/video.php.*[?&]{1}v=([0-9]+).*/i,
            /^https?:\/\/(?:[\w]+\.)?facebook\.com\/.+\/videos(?:\/\w[^\/]+)?\/(\d+)/i
          ],
          action: 'getFacebookLinks'
        }
      },


      init: function(style) {
        this.style = style;

        if (this.panel) {
          SaveFrom_Utils.popupMenu.removePanel();
        }

        this.panel = null;
        this.lastLink = null;

        var links = document.querySelectorAll('a[' + this.dataAttr + ']'),
          i, l = links.length;

        for (i = 0; i < l; i++) {
          if (['savefrom.net', 'sf-addon.com'].indexOf(
              SaveFrom_Utils.getTopLevelDomain(links[i].hostname)) > -1) {
            links[i].removeEventListener('click', this.onClick, false);
            links[i].addEventListener('click', this.onClick, false);
          }
        }

        // hide menu on click outside them
        // process dinamically added links
        if (document.body) {
          document.body.removeEventListener('click', this.onBodyClick, true);
          document.body.addEventListener('click', this.onBodyClick, true);
        }
      },


      checkUrl: function(url) {
        for (var hosting in this.hostings) {
          var params = this.hostings[hosting];

          for (var i = 0, len = params.re.length; i < len; i++) {
            var match = url.match(params.re[i]);
            if (match) {
              return {
                hosting: hosting,
                action: params.action,
                extVideoId: match[1]
              };
            }
          }
        }

        return null;
      },

      reMapHosting: function(action) {
        var map = {
          'getYoutubeLinks': 'youtube',
          'getVimeoLinks': 'vimeo',
          'getDailymotionLinks': 'dailymotion',
          'getFacebookLinks': 'facebook',
          'getVKLinks': 'vk'
        };

        return map[action];
      },


      onClick: function(event, a) {
        var _this = SaveFrom_Utils.embedDownloader;

        if (!a) {
          a = event.target;
          while (a.parentNode) {
            if (a.nodeName === 'A')
              break;
            a = a.parentNode;
          }

          if (!a)
            return;
        }

        var href = a.getAttribute('data-savefrom-get-links');
        if (!href)
          return;

        if (event.button !== 0 || event.ctrlKey || event.shiftKey)
          return;

        if (_this.lastLink === a && _this.panel && _this.panel.style.display != 'none') {
          _this.lastLink = null;
          _this.panel.style.display = 'none';

          event.preventDefault();
          event.stopPropagation();
          return;
        }

        _this.lastLink = a;
        var data = _this.checkUrl(href);
        if (!data)
          return;

        event.preventDefault();
        event.stopPropagation();

        var request = {
          action: data.action,
          extVideoId: data.extVideoId
        };

        _this.showLinks(mono.global.language.download + ' ...', null, a);

        mono.sendMessage(request, function(response) {
          var hosting = data.hosting;

          if (response.action != request.action) {
            hosting = _this.reMapHosting(response.action);
          }

          if (response.links)
            _this.showLinks(response.links, response.title, a, hosting, true);
          else
            _this.showLinks(mono.global.language.noLinksFound, null, a, undefined, true);
        });

        return false;
      },


      onBodyClick: function(event) {
        var _this = SaveFrom_Utils.embedDownloader;

        var node = event.target;

        if (!_this.panel || _this.panel.style.display == 'none') {
          if (node.tagName !== 'A' && mono.matches(node, 'A ' + node.tagName)) {
            while (node.parentNode) {
              if (node.tagName === 'A') {
                break;
              }
              node = node.parentNode;
            }
          }

          if (node.nodeName !== 'A') {
            return;
          }

          // dinamic links
          if (node.hasAttribute(_this.dataAttr) && ['savefrom.net', 'sf-addon.com'].indexOf(SaveFrom_Utils.getTopLevelDomain(node.hostname)) > -1) {
            return _this.onClick(event, node);
          }

          return;
        }

        if (_this.panel === node || _this.panel.contains(node)) {
          return;
        }

        _this.lastLink = null;
        _this.panel.style.display = 'none';

        event.preventDefault();
        event.stopPropagation();
      },

      hidePanel: function() {
        if (this.panel) {
          this.panel.style.display = 'none';
        }
      },

      createMenu: function(links, title, a, hname, update) {
        var menuLinks = mono.global.language.noLinksFound;
        if (typeof links === 'string') {
          menuLinks = links;
        } else
        if (SaveFrom_Utils.popupMenu.prepareLinks[hname] !== undefined && links) {
          menuLinks = SaveFrom_Utils.popupMenu.prepareLinks[hname](links, title);
        }
        var options = {
          links: menuLinks,
          button: a,
          popupId: undefined,
          showFileSize: true,
          containerClass: this.containerClass,
          linkClass: this.linkClass,
          style: {
            popup: (this.style) ? this.style.container : undefined,
            item: (this.style) ? this.style.link : undefined
          },
          isUpdate: update
        };
        if (update && this.panel) {
          SaveFrom_Utils.popupMenu.update(this.panel, options)
        } else {
          this.panel = SaveFrom_Utils.popupMenu.create(options);
        }
      },

      showLinks: function(links, title, a, hname, update) {
        var panel, id = a.getAttribute(this.dataIdAttr);
        if (id)
          panel = document.getElementById(id);

        if (!panel) {
          this.createMenu(links, title, a, hname, update);

          return;
        } else if (this.panel) {
          this.panel.style.display = 'none';
        }

        if (typeof(links) == 'string') {
          panel.textContent = links;
        } else if (!links || links.length == 0) {
          panel.textContent = mono.global.language.noLinksFound;
        } else {
          // append links
          if (hname && this.hostings[hname] && this.hostings[hname].prepareLinks)
            links = this.hostings[hname].prepareLinks(links);

          panel.textContent = '';

          for (var i = 0; i < links.length; i++) {
            if (links[i].url && links[i].name) {
              var a = document.createElement('a');
              a.href = links[i].url;
              a.title = mono.global.language.downloadTitle;
              a.appendChild(document.createTextNode(links[i].name));
              var span = document.createElement('span');
              span.className = this.linkClass;

              span.appendChild(a);
              panel.appendChild(span);

              SaveFrom_Utils.appendFileSizeIcon(a);
              if (links[i].noSound)
                SaveFrom_Utils.appendNoSoundIcon(a);

              if (title && !links[i].noTitle && links[i].type) {
                a.setAttribute('download', mono.fileName.modify(
                  title + '.' + links[i].type.toLowerCase()));

                a.addEventListener('click', SaveFrom_Utils.downloadOnClick, false);
              }
            }
          }
        }
      }
    },
    createUmmyInfo: function(details, targetNode) {
      "use strict";
      details = details || {};

      var params = mono.extend({
        vid: 111,
        utm_source: 'savefrom-helper',
        utm_medium: 'youtube-helper'
      }, details.params);

      if (!params.utm_campaign) {
        if (details.itemType === 'hd') {
          params.utm_campaign = 'youtube-helper-hd';
        } else
        if (details.itemType === 'mp3') {
          params.utm_campaign = 'youtube-helper-mp3';
        }
      }

      var ummyUrl;
      if (/^Mac/.test(navigator.platform) && /^yt-/.test(params.video)) {
        ummyUrl = 'http://videodownloader.ummy.net/save-from-youtube.html?' + mono.param({
          vid: params.vid,
          video: params.video,
          utm_source: 'savefrom-helper',
          utm_medium: 'youtube-helper',
          utm_campaign: 'ummy',
          utm_content: 'ummy_integration_h'
        });
      } else {
        ummyUrl = 'http://videodownloader.ummy.net/?' + mono.param(params);
      }


      var themeShadowArrowDirStyle, themeArrowDirStyle, themeInfoPopup, themeLinkColor;

      var shadowArrowDirStyle, arrowDirStyle, containerDirArrow;
      if (details.posLeft) {
        shadowArrowDirStyle = {
          border: '8px solid transparent',
          borderLeft: '10px solid rgb(192, 187, 187)',
          borderRight: 0,
          top: '8px',
          right: '11px'
        };

        arrowDirStyle = mono.extend({}, shadowArrowDirStyle, {
          right: '12px',
          borderLeft: '10px solid #fff'
        });

        containerDirArrow = {
          right: '21px'
        };

        if (details.darkTheme) {
          themeShadowArrowDirStyle = {
            borderLeftColor: 'rgba(255, 255, 255, 0.4)'
          };

          themeArrowDirStyle = {
            borderLeftColor: 'rgba(28,28,28, 0.6)'
          };
        }
      } else {
        shadowArrowDirStyle = {
          border: '8px solid transparent',
          borderRight: '10px solid rgb(192, 187, 187)',
          borderLeft: 0,
          top: '8px',
          left: '11px'
        };

        arrowDirStyle = mono.extend({}, shadowArrowDirStyle, {
          left: '12px',
          borderRight: '10px solid #fff'
        });

        containerDirArrow = {
          left: '21px'
        };

        if (details.darkTheme) {
          themeShadowArrowDirStyle = {
            borderRightColor: '#fff'
          };

          themeArrowDirStyle = {
            borderRightColor: '#000'
          };
        }
      }

      if (details.darkTheme) {
        themeLinkColor = {
          'a': {
            color: '#eee'
          }
        };
      } else {
        themeLinkColor = {};
      }

      if (details.darkTheme) {
        themeInfoPopup = {
          backgroundColor: 'rgba(28,28,28,0.8)',
          border: '1px solid rgba(255, 255, 255, 0.4)',
          color: '#fff'
        };
      } else {
        themeInfoPopup = {
          backgroundColor: '#fff',
          border: '1px solid #ccc'
        };
      }


      var arrow = mono.create(document.createDocumentFragment(), {
        append: [
          mono.create('span', {
            style: mono.extend({
              display: 'inline-block',
              width: 0,
              position: 'absolute'
            }, shadowArrowDirStyle, themeShadowArrowDirStyle)
          }),
          mono.create('span', {
            style: mono.extend({
              display: 'inline-block',
              width: 0,
              position: 'absolute',
              zIndex: 1
            }, arrowDirStyle, themeArrowDirStyle)
          })
        ]
      });

      var showUmmyInfoNode = null;
      var info = null;
      var infoContainer = mono.create('div', {
        class: 'sf-ummy-info-popup-container',
        style: {
          position: 'absolute',
          zIndex: 9999
        },
        append: [
          arrow,
          info = mono.create('div', {
            class: 'sf-ummy-info-popup',
            style: mono.extend({
              position: 'relative',
              backgroundColor: '#fff',
              border: '1px solid #ccc',
              padding: '6px 5px',
              textAlign: 'center',
              maxWidth: '240px',
              lineHeight: '16px',
              fontSize: '12px',
              fontFamily: 'arial, sans-serif',
              cursor: 'default'
            }, containerDirArrow, themeInfoPopup),
            append: [
              mono.parseTemplate(mono.global.language.ummyMenuInfo.replace(
                '{url}', ummyUrl
              )),
              mono.create('label', {
                style: {
                  verticalAlign: 'middle',
                  display: 'block'
                },
                append: [
                  showUmmyInfoNode = mono.create('input', {
                    type: 'checkbox',
                    name: 'showUmmyInfo',
                    style: {
                      verticalAlign: 'middle'
                    }
                  }),
                  mono.global.language.tooltipHide
                ]
              }),
              mono.create('style', {
                text: mono.style2Text({
                  '.sf-ummy-info-popup': {
                    append: mono.extend({
                      '> p': {
                        margin: '0 0 .8em 0'
                      },
                      '> p.center': {
                        textAlign: 'center'
                      },
                      '> p > .green-btn-2.arrow': {
                        color: '#fff',
                        background: '#84bd07',
                        borderRadius: '5px',
                        display: 'inline-block',
                        position: 'relative',
                        lineHeight: 1,
                        padding: '8px 34px 8px 10px',
                        textDecoration: 'none',
                        fontSize: '12px'
                      },
                      '> p > .green-btn-2.arrow:hover': {
                        color: '#fff',
                        opacity: 0.8
                      },
                      '> p > .green-btn-2.arrow:after': {
                        background: 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAOCAYAAAAmL5yKAAAAjklEQVQoke3RsRGCQBCF4YuJsQDoQMpjKMImtAjth9xMEj4DF4c5QDH3n7lk773b3XsJNzTpR9DglrwYcUG9w1iHdoTpgYkBJ5QrxkPcDXNDQm/JHR2KOF3UcvoUgnZL8KFBi2I+Yrk2YsZjsaIsBVQ4i08KxqhVu1OYBLji+E/hzTKFlV13pfAVGynkPAFtrlNTMRczMgAAAABJRU5ErkJggg==) 0 0 no-repeat',
                        content: '""',
                        display: 'block',
                        position: 'absolute',
                        width: '16px',
                        height: '14px',
                        top: '50%',
                        right: '10px',
                        marginTop: '-7px'
                      },
                      'input': {
                        display: 'inline-block'
                      }
                    }, themeLinkColor)
                  }
                })
              })
            ]
          })
        ],
        on: [
          ['mouseclick', function(e) {
            e.stopPropagation();
          }],
          ['mousedown', function(e) {
            e.stopPropagation();
          }]
        ]
      });

      mono.sendMessage({
        action: 'getUmmyIcon'
      }, function(dataImg) {
        var icon = info.querySelector('img');
        if (!icon) {
          return;
        }
        icon.src = dataImg;
        icon.style.verticalAlign = 'text-bottom';
      });

      showUmmyInfoNode.checked = !mono.global.preference.showUmmyInfo;
      showUmmyInfoNode.addEventListener('change', function(e) {
        e.preventDefault();
        e.stopPropagation();

        if (this.checked) {
          mono.trigger(targetNode, 'sfRmInfoPopup');
          mono.global.preference.showUmmyInfo = 0;
        } else {
          mono.trigger(targetNode, 'sfAddInfoPopup');
          mono.global.preference.showUmmyInfo = 1;
        }

        mono.sendMessage({
          action: 'updateOption',
          key: 'showUmmyInfo',
          value: mono.global.preference.showUmmyInfo
        });
      });

      details.onCreateUmmyInfo && details.onCreateUmmyInfo(infoContainer);

      return infoContainer;
    },
    bindUmmyInfo: function(container, details) {
      "use strict";
      details = details || {};
      // menu
      if (!details.noUmmy && !mono.global.preference.showUmmyInfo) {
        return;
      }
      if (details.widthLimit && document.documentElement.offsetWidth < details.widthLimit) {
        return;
      }

      details.leftOffset = details.leftOffset || 21;

      var infoPopup = null;
      var infoPopupShowTimer = null;
      var positionTop = null;

      var popupArrowTop = 8;
      var popupArrow = null;
      var popupArrowShadow = null;

      var killTimer = null;
      var killTimerUpdate = function() {
        clearTimeout(killTimer);
        killTimer = setTimeout(function() {
          if (infoPopup && infoPopup.parentNode) {
            if (infoPopup.style.display !== 'none') {
              return killTimerUpdate();
            }
            infoPopup.parentNode.removeChild(infoPopup);
          }
        }, 30 * 1000);
      };

      var fixPosition = function() {
        setTimeout(function() {
          var windowHeight = window.innerHeight;
          var infoHeight = infoPopup.clientHeight;
          var scrollY = window.scrollY;
          if (infoHeight + positionTop > windowHeight + scrollY) {
            var newPositionTop = windowHeight - infoHeight + scrollY;
            if (newPositionTop < 0) {
              return;
            }

            if (positionTop === newPositionTop) {
              return;
            }

            infoPopup.style.top = newPositionTop + 'px';

            var raz = 8 - (windowHeight - (infoHeight + positionTop) + scrollY);
            if (popupArrowTop !== raz) {
              popupArrowTop = raz;
              popupArrow.style.top = popupArrowTop + 'px';
              popupArrowShadow.style.top = popupArrowTop + 'px';
            }
          } else {
            if (popupArrowTop !== 8) {
              popupArrowTop = 8;
              popupArrow.style.top = popupArrowTop + 'px';
              popupArrowShadow.style.top = popupArrowTop + 'px';
            }
          }
        });
      };

      var onMouseLeave = function() {
        clearTimeout(infoPopupShowTimer);
        infoPopupShowTimer = setTimeout(function() {
          infoPopup && (infoPopup.style.display = 'none');
        }, 50);
      };

      var updateLeftPos = function(el) {
        var position = SaveFrom_Utils.getPosition(el);
        if (details.posLeft) {
          infoPopup.style.right = (document.documentElement.clientWidth - position.left - details.leftOffset) + 'px';
        } else {
          var size = SaveFrom_Utils.getSize(el);
          infoPopup.style.left = (size.width + position.left - details.leftOffset) + 'px';
        }
      };

      var onMouseEnter = function() {
        if (!details.noUmmy && !mono.global.preference.showUmmyInfo) {
          return;
        }

        clearTimeout(infoPopupShowTimer);

        var position = SaveFrom_Utils.getPosition(container);

        if (!infoPopup) {
          if (details.expUmmyInfo) {
            infoPopup = details.expUmmyInfo(details.createUmmyInfoDetails, container);
          } else {
            infoPopup = SaveFrom_Utils.createUmmyInfo(details.createUmmyInfoDetails, container);
          }

          popupArrow = infoPopup.firstChild;
          popupArrowShadow = popupArrow.nextElementSibling;

          positionTop = position.top - 4;

          mono.on(infoPopup, 'mouseenter', function() {
            clearTimeout(infoPopupShowTimer);
          });

          mono.on(infoPopup, 'mouseleave', onMouseLeave);
        } else {
          positionTop = position.top - 4;
        }

        infoPopup.style.top = positionTop + 'px';

        if (infoPopup.dataset.hide === '1') {
          return;
        }

        updateLeftPos(container);

        if (!infoPopup.parentNode) {
          infoPopup.style.display = 'none';
          (details.container || document.body).appendChild(infoPopup);
        }

        if (infoPopup.style.display !== 'block') {
          infoPopup.style.display = 'block';
          mono.trigger(infoPopup, 'sfShowInfoPopup');
        }

        fixPosition();

        killTimerUpdate();
      };

      mono.on(container, 'mouseenter', onMouseEnter);
      mono.on(container, 'mouseleave', onMouseLeave);

      mono.on(container, 'sfRmInfoPopup', function() {
        mono.off(container, 'mouseenter', onMouseEnter);
      });

      mono.on(container, 'sfAddInfoPopup', function() {
        mono.on(container, 'mouseenter', onMouseEnter);
      });
    },

    popupMenu: {
      popupId: 'sf_popupMenu',
      popup: undefined,
      popupStyle: undefined,
      dataArrtVisible: 'data-isVisible',
      extStyleCache: undefined,
      ummyIcon: null,

      badgeQualityList: ['8K', '4K', '2160', '1440', '1080', '720', 'ummy'],
      createBadge: function(qulity, options) {
        var _this = this;
        options = options || {};
        var style = {
          display: 'inline-block',
          lineHeight: '18px',
          width: '19px',
          height: '17px',
          color: '#fff',
          fontSize: '12px',
          borderRadius: '2px',
          verticalAlign: 'middle',
          textAlign: 'center',
          paddingRight: '2px',
          fontWeight: 'bold',
          marginLeft: '3px'
        };
        for (var key in options.containerStyle) {
          style[key] = options.containerStyle[key];
        }

        var container = mono.create('div', {
          style: style
        });

        if (qulity === '1080' || qulity === '2160' || qulity === '1440' || qulity === '720') {
          container.textContent = 'HD';
          container.style.backgroundColor = '#505050';
          container.style.paddingRight = '1px';
        } else
        if (qulity === '8K' || qulity === '4K') {
          container.textContent = 'HD';
          container.style.paddingRight = '1px';
          container.style.backgroundColor = 'rgb(247, 180, 6)';
        } else
        if (qulity === 'mp3' || qulity === 'MP3') {
          container.textContent = 'MP3';
          container.style.width = '26px';
          container.style.paddingRight = '1px';
          container.style.backgroundColor = '#505050';
        } else
        if (qulity === 'ummy') {
          if (this.ummyIcon) {
            container.style.background = 'url(' + this.ummyIcon + ') center center no-repeat';
          } else {
            mono.sendMessage({
              action: 'getUmmyIcon'
            }, function(dataImg) {
              container.style.background = 'url(' + (_this.ummyIcon = dataImg) + ') center center no-repeat';
            });
          }
        }
        return container;
      },

      getTitleNode: function(link) {
        "use strict";
        var _this = SaveFrom_Utils.popupMenu;

        var titleContainer = mono.create('span', {
          style: {
            cssFloat: 'left'
          }
        });

        if (link.extra === 'converter') {
          var badge = document.createDocumentFragment();
          if (['MP3', '8K', '4K', '1440', '1080', '720'].indexOf(link.format) !== -1) {
            badge.appendChild(_this.createBadge(link.format, {
              containerStyle: {
                marginLeft: 0
              }
            }));
          } else {
            badge.appendChild(document.createTextNode(link.format));
          }
          mono.create(titleContainer, {
            append: [badge, ' ', link.quality]
          });
          badge = null;
        } else
        if (link.quality === 'ummy') {
          // ummy hook
          var badge = document.createDocumentFragment();
          if (link.uQuality !== null) {
            if (['8K', '4K', '1440', '1080', '720'].indexOf(link.uQuality) !== -1) {
              badge.appendChild(document.createTextNode(link.uQuality));
            } else {
              badge.appendChild(_this.createBadge(link.uQuality, {
                containerStyle: {
                  marginLeft: 0
                }
              }));
            }
          }
          mono.create(titleContainer, {
            append: [badge, ' ', 'Ummy']
          });
          badge = null;
        } else
        if (link.itemText) {
          titleContainer.textContent = link.itemText;
        } else {
          var titleQuality = link.quality ? ' ' + link.quality : '';
          var titleFormat = link.format ? link.format : '???';
          var title3D = link['3d'] ? '3D ' : '';
          var titleFps = '';
          if (link.sFps) {
            titleFps += ' ' + (link.fps || 60);
          }
          titleContainer.textContent = title3D + titleFormat + titleQuality + titleFps;
        }

        if (_this.badgeQualityList.indexOf(String(link.quality)) !== -1) {
          titleContainer.appendChild(_this.createBadge(String(link.quality)));
        }

        return titleContainer;
      },

      createPopupItem: function(listItem, options) {
        var _this = SaveFrom_Utils.popupMenu;

        var href;
        if (typeof listItem === 'string') {
          href = listItem;
        } else {
          href = listItem.href;
        }

        if (href === '-') {
          var line = mono.create('div', {
            style: {
              display: 'block',
              margin: '1px 0',
              borderTop: '1px solid rgb(214, 214, 214)'
            }
          });
          return {
            el: line
          };
        }

        var itemContainer = document.createElement((href === '-text-') ? 'div' : 'a');
        if (options.linkClass) {
          itemContainer.classList.add(options.linkClass);
        }
        var itemContainerStyle = {
          display: 'block',
          padding: '0 5px',
          textDecoration: 'none',
          whiteSpace: 'nowrap',
          overflow: 'hidden'
        };
        if (listItem.isHidden) {
          itemContainer.setAttribute(_this.dataArrtVisible, '0');
          itemContainerStyle.display = 'none';
        }
        SaveFrom_Utils.setStyle(itemContainer, itemContainerStyle);

        if (href === '-text-') {
          itemContainer.style.lineHeight = '22px';
          return {
            el: itemContainer
          };
        }

        itemContainer.href = href;

        if (href === '#') {
          return {
            el: itemContainer
          };
        }

        if (mono.isGM || mono.isOpera || mono.isSafari) {
          if (listItem.quality !== 'ummy' && !listItem.extra) {
            itemContainer.title = mono.global.language.downloadTitle;
          }
        }

        if (listItem.forceDownload) {
          var filename = '';
          if (listItem.title) {
            var ext = (listItem.ext || listItem.format || '').toLowerCase();
            if (ext) {
              ext = '.' + ext;
            }
            filename = listItem.title + ext;
          }
          itemContainer.setAttribute('download', mono.fileName.modify(filename));
          itemContainer.addEventListener('click', function(event) {
            SaveFrom_Utils.downloadOnClick(event, null, {
              el: this
            });
          }, false);
        }

        var onItemClickList = [];
        if (listItem.func) {
          if (Array.isArray(listItem.func)) {
            onItemClickList.push.apply(onItemClickList, listItem.func);
          } else {
            onItemClickList.push(listItem.func);
          }
        }
        if (options.onItemClick && onItemClickList.indexOf(options.onItemClick) === -1) {
          onItemClickList.push(options.onItemClick);
        }

        if (onItemClickList.length) {
          itemContainer.addEventListener('click', function(e) {
            var _this = this;
            onItemClickList.forEach(function(cb) {
              "use strict";
              return cb.call(_this, e, listItem);
            });
          }, false);
        }

        if (listItem.isBlank) {
          itemContainer.setAttribute('target', '_blank');
        }

        itemContainer.appendChild(_this.getTitleNode(listItem));

        var infoConteiner = mono.create('span', {
          style: {
            cssFloat: 'right',
            lineHeight: '22px',
            height: '22px'
          }
        });
        var sizeIconStyle = {
          top: '5px',
          verticalAlign: 'top'
        };
        for (var key in options.sizeIconStyle) {
          sizeIconStyle[key] = options.sizeIconStyle[key];
        }
        var sizeIconTextStyle = {
          marginLeft: 0
        };

        if (listItem.noAudio) {
          SaveFrom_Utils.appendNoSoundIcon(infoConteiner, sizeIconStyle);
        }

        var sizeIconNode = null;
        if (!listItem.noSize) {
          infoConteiner.addEventListener('click', function onClick(e) {
            if (infoConteiner.firstChild.tagName === 'IMG') {
              e.preventDefault();
              e.stopPropagation();
              mono.trigger(infoConteiner.firstChild, 'click', {
                cancelable: true
              });
            }
            this.removeEventListener('click', onClick);
          });
          sizeIconNode = SaveFrom_Utils.appendFileSizeIcon(itemContainer, sizeIconStyle, sizeIconTextStyle, undefined, true, infoConteiner, listItem);
        }

        itemContainer.appendChild(infoConteiner);

        if (listItem.quality === 'ummy') {
          var bInfoDetails = mono.extend({}, options.bindUmmyInfoDetails);
          var cInfoDetails = bInfoDetails.createUmmyInfoDetails = mono.extend({
            itemType: listItem.uIsAudio ? 'mp3' : 'hd'
          }, bInfoDetails.createUmmyInfoDetails);
          cInfoDetails.params = mono.extend({
            video: listItem.videoId,
            vid: listItem.vid
          }, cInfoDetails.params);
          SaveFrom_Utils.bindUmmyInfo(itemContainer, bInfoDetails);
        }

        return {
          el: itemContainer,
          sizeIcon: sizeIconNode,
          prop: listItem
        };
      },

      sortMenuItems: function(list, options) {
        if (options === undefined) {
          options = {};
        }
        var formatPriority = ['ummy', 'Audio Opus', 'Audio Vorbis', 'Audio AAC', '3GP', 'WebM', 'FLV', 'MP4'];
        var strQuality = {
          Mobile: 280,
          LD: 280,
          SD: 360,
          HD: 720,
          ummy: 1
        };
        if (options.strQualityExtend) {
          mono.extend(strQuality, options.strQualityExtend);
        }
        var sizePriority = {};
        var bitratePriority = [];
        var defList = [];
        var audioList = [];
        var subtitleList = [];
        var mute60List = [];
        var muteList = [];
        var _3dList = [];
        var unkList = [];

        list.forEach(function(item) {
          var prop = item.prop;
          if (options.noProp) {
            prop = item;
          }
          var sortOptions = prop.sort || {};
          if (!prop.format) {
            unkList.push(item);
            return 1;
          }
          if (prop.isOther) {
            unkList.push(item);
          } else
          if (prop.isSubtitle) {
            subtitleList.push(item);
          } else
          if (prop.noVideo) {
            bitratePriority[prop.quality] = parseInt(prop.quality);
            audioList.push(item);
          } else {
            var size = sortOptions.size || strQuality[prop.quality] || -1;
            if (size === -1) {
              if (String(prop.quality).substr(-1) === 'K') {
                size = parseInt(prop.quality) * 1000;
              } else {
                size = parseInt(prop.quality);
              }
            }
            if (options.maxSize && size > options.maxSize) {
              return 1;
            }
            if (options.minSize && size < options.minSize) {
              return 1;
            }
            sizePriority[prop.quality] = size;
            if (prop.noAudio) {
              if (prop.sFps) {
                mute60List.push(item);
              } else {
                muteList.push(item);
              }
            } else
            if (prop['3d']) {
              _3dList.push(item);
            } else {
              defList.push(item);
            }
          }
        });
        var sizeCompare = function(a, b) {
          return sizePriority[a.quality] > sizePriority[b.quality] ? -1 : sizePriority[a.quality] === sizePriority[b.quality] ? 0 : 1;
        };
        var bitrateCompare = function(a, b) {
          return bitratePriority[a.quality] > bitratePriority[b.quality] ? -1 : (bitratePriority[a.quality] === bitratePriority[b.quality]) ? 0 : 1;
        };
        var formatCompare = function(a, b) {
          if (a.noVideo && b.noVideo) {
            return bitrateCompare(a, b);
          }
          if (a.noVideo) {
            return 1;
          }
          if (b.noVideo) {
            return -1;
          }
          return formatPriority.indexOf(a.format) > formatPriority.indexOf(b.format) ? -1 : formatPriority.indexOf(a.format) === formatPriority.indexOf(b.format) ? 0 : 1;
        };

        var compare = function(aa, bb) {
          var a = aa.prop;
          var b = bb.prop;
          if (options.noProp) {
            a = aa;
            b = bb;
          }

          var size = sizeCompare(a, b);
          if (size !== 0) {
            return size;
          }
          return formatCompare(a, b);
        };
        defList.sort(compare);
        _3dList.sort(compare);
        audioList.sort(compare);
        mute60List.sort(compare);
        muteList.sort(compare);

        var resList = null;
        if (options.typeList) {
          resList = [];
          if (options.typeList.indexOf('video') !== -1) {
            resList = resList.concat(defList);
          }
          if (options.typeList.indexOf('3d') !== -1) {
            resList = resList.concat(_3dList);
          }
          if (options.typeList.indexOf('audio') !== -1) {
            resList = resList.concat(audioList);
          }
          if (options.typeList.indexOf('mute') !== -1) {
            resList = resList.concat(muteList);
          }
          if (options.typeList.indexOf('mute60') !== -1) {
            resList = resList.concat(mute60List);
          }
          if (options.typeList.indexOf('subtitles') !== -1) {
            resList = resList.concat(subtitleList);
          }
          if (options.typeList.indexOf('other') !== -1) {
            resList = resList.concat(unkList);
          }
        } else {
          resList = defList.concat(_3dList, audioList, subtitleList, mute60List, muteList, unkList);
        }
        if (options.groupCompare) {
          resList.sort(compare);
        }
        return resList;
      },

      removePanel: function() {
        if (this.popup.parentNode !== null) {
          this.popup.parentNode.removeChild(this.popup);
        }
        if (this.popupStyle !== undefined && this.popupStyle.parentNode !== null) {
          this.popupStyle.parentNode.removeChild(this.popupStyle);
        }
        this.popup = undefined;
        this.popupStyle = undefined;
      },

      getHiddenList: function(hiddenList, options) {
        "use strict";
        var _this = this;
        var content = document.createDocumentFragment();
        var scrollListItemCount = 8;
        if (hiddenList.length < scrollListItemCount) {
          mono.create(content, {
            append: hiddenList
          });
        } else {
          var scrollContainer = mono.create('div', {
            style: {
              maxHeight: (scrollListItemCount * 24) + 'px',
              overflowY: 'scroll',
              display: 'none'
            },
            on: [
              ['wheel', function(e) {
                if (e.wheelDeltaY > 0 && this.scrollTop === 0) {
                  e.preventDefault();
                } else
                if (e.wheelDeltaY < 0 && this.scrollHeight - (this.offsetHeight + this.scrollTop) <= 0) {
                  e.preventDefault();
                }
              }],
              (function() {
                var hasTopShadow = false;
                return ['scroll', function() {
                  if (this.scrollTop !== 0) {
                    if (hasTopShadow) {
                      return;
                    }
                    hasTopShadow = true;
                    this.style.boxShadow = 'rgba(0, 0, 0, 0.40) -2px 1px 2px 0px inset';
                  } else {
                    if (!hasTopShadow) {
                      return;
                    }
                    hasTopShadow = false;
                    this.style.boxShadow = '';
                  }
                }];
              })()
            ],
            append: hiddenList
          });
          scrollContainer.setAttribute(_this.dataArrtVisible, '0');

          content.appendChild(scrollContainer);
        }

        var separator = _this.createPopupItem('-', options).el;
        content.appendChild(separator);

        var moreItem = _this.createPopupItem('#', options).el;
        mono.create(moreItem, {
          text: mono.global.language.more + ' ' + String.fromCharCode(187), //171 //160 - space
          data: {
            visible: '0'
          },
          on: ['click', function(e) {
            e.preventDefault();
            var state = this.dataset.visible;
            var symbol;
            if (state > 0) {
              state--;
              symbol = 187;
            } else {
              state++;
              symbol = 171;
            }
            this.textContent = mono.global.language.more + ' ' + String.fromCharCode(symbol);
            this.dataset.visible = state;
            var itemList = this.parentNode.querySelectorAll('*[' + _this.dataArrtVisible + ']');
            for (var i = 0, item; item = itemList[i]; i++) {
              if (state === 1) {
                item.style.display = 'block';
              } else {
                item.style.display = 'none';
              }
              item.setAttribute(_this.dataArrtVisible, state);
            }
          }]
        });
        content.appendChild(moreItem);

        if (options.visibleCount === 0) {
          mono.trigger(moreItem, 'click', {
            cancelable: true
          });
        }

        return content;
      },

      getContent: function(options) {
        "use strict";
        var _this = this;
        var links = options.links;

        var content = document.createDocumentFragment();

        var sizeIconList = [];

        if (typeof(links) === 'string') {
          var loadingItem = _this.createPopupItem('-text-', options).el;
          loadingItem.textContent = links;
          content.appendChild(loadingItem);
        } else
        if (links.length === 0) {
          var emptyItem = _this.createPopupItem('-text-', options).el;
          emptyItem.textContent = mono.global.language.noLinksFound;
          content.appendChild(emptyItem);
        } else {
          var items = [];
          links.forEach(function(link) {
            items.push(_this.createPopupItem(link, options));
          });

          items = _this.sortMenuItems(items, options.sortDetails);

          var hiddenList = [];

          items.forEach(function(item) {
            if (item.prop.isHidden) {
              hiddenList.push(item.el);
              return 1;
            }

            content.appendChild(item.el);

            if (options.showFileSize && item.sizeIcon) {
              sizeIconList.push(item.sizeIcon);
            }
          });

          options.visibleCount = items.length - hiddenList.length;

          if (hiddenList.length > 0) {
            if (options.getHiddenListFunc) {
              content.appendChild(options.getHiddenListFunc(hiddenList, options));
            } else {
              content.appendChild(_this.getHiddenList(hiddenList, options));
            }
          }
        }

        return {
          sizeIconList: sizeIconList,
          content: content
        };
      },

      create: function(options) {
        var button = options.button;
        var _this = SaveFrom_Utils.popupMenu;

        options.linkClass = options.linkClass || 'sf-menu-item';

        options.offsetRight = options.offsetRight || 0;
        options.offsetTop = options.offsetTop || 0;

        options.parent = options.parent || document.body;

        if (options.isUpdate && (_this.popup === undefined || _this.popup.style.display === 'none')) {
          return;
        }

        if (_this.popup) {
          _this.removePanel();
        }

        var popupContainer = _this.popup = document.createElement('div');
        var containerSelector = '#' + _this.popupId;
        if (options.popupId) {
          containerSelector = '#' + options.popupId;
          popupContainer.id = options.popupId;
        } else
        if (options.containerClass) {
          containerSelector = '.' + options.containerClass;
          popupContainer.classList.add(options.containerClass);
        } else {
          popupContainer.id = _this.popupId;
        }

        var popupContainerStyle = {
          display: 'block',
          position: 'absolute',
          minHeight: '24px',
          cursor: 'default',
          textAlign: 'left',
          whiteSpace: 'nowrap',
          fontFamily: 'arial, sans-serif'
        };
        if (options.extStyle) {
          delete popupContainerStyle.display;
        }

        var pos = SaveFrom_Utils.getPosition(button, options.parent),
          size = SaveFrom_Utils.getSize(button);

        popupContainerStyle.top = (pos.top + options.offsetTop + size.height) + 'px';
        popupContainerStyle.left = (pos.left + options.offsetRight) + 'px';
        SaveFrom_Utils.setStyle(popupContainer, popupContainerStyle);

        var popupCustomContainerStyle = {
          'background-color': '#fff',
          'z-index': '9999',
          'box-shadow': '0 2px 10px 0 rgba(0,0,0,0.2)',
          border: '1px solid #ccc',
          'border-radius': '3px',
          'font-size': '12px',
          'font-weight': 'bold',
          'min-width': '190px'
        };

        if (options.style && options.style.popup) {
          for (var key in options.style.popup) {
            var value = options.style.popup[key];
            popupCustomContainerStyle[key] = value;
          }
        }

        SaveFrom_Utils.addStyleRules(containerSelector, popupCustomContainerStyle);

        var itemCustomStyle = {
          'line-height': '24px',
          color: '#3D3D3D'
        };

        if (options.style && options.style.item) {
          for (var key in options.style.item) {
            var value = options.style.item[key];
            itemCustomStyle[key] = value;
          }
        }

        SaveFrom_Utils.addStyleRules(containerSelector + ' .' + options.linkClass, itemCustomStyle);

        var stopPropagationFunc = function(e) {
          e.stopPropagation()
        };
        mono.create(popupContainer, {
          on: [
            ['click', stopPropagationFunc],
            ['mouseover', stopPropagationFunc],
            ['mouseup', stopPropagationFunc],
            ['mousedown', stopPropagationFunc],
            ['mouseout', stopPropagationFunc]
          ]
        });

        while (popupContainer.firstChild !== null) {
          popupContainer.removeChild(popupContainer.firstChild);
        }

        var menuContent = _this.getContent.call(_this, options);
        var sizeIconList = menuContent.sizeIconList;
        menuContent = menuContent.content;
        popupContainer.appendChild(menuContent);


        var hoverBgColor = '#2F8AFF';
        var hoverTextColor = '#fff';
        if (options.style && options.style.hover) {
          hoverBgColor = options.style.hover.backgroundColor || hoverBgColor;
          hoverTextColor = options.style.hover.color || hoverTextColor;
        }
        var styleEl = _this.popupStyle = document.createElement('style');
        styleEl.textContent = mono.style2Text({
          selector: containerSelector,
          append: {
            'a:hover': {
              backgroundColor: hoverBgColor,
              color: hoverTextColor
            },
            '> a:first-child': {
              borderTopLeftRadius: '3px',
              borderTopRightRadius: '3px'
            },
            '> a:last-child': {
              borderBottomLeftRadius: '3px',
              borderBottomRightRadius: '3px'
            }
          }
        });

        options.parent.appendChild(styleEl);
        options.parent.appendChild(popupContainer);
        if (options.extStyle) {
          if (SaveFrom_Utils.popupMenu.extStyleCache !== undefined && SaveFrom_Utils.popupMenu.extStyleCache.parentNode !== null) {
            SaveFrom_Utils.popupMenu.extStyleCache.parentNode.removeChild(SaveFrom_Utils.popupMenu.extStyleCache);
          }

          var extElClassName = 'sf-extElStyle_' + containerSelector.substr(1);
          var extBodyClassName = 'sf-extBodyStyle_' + containerSelector.substr(1);
          var extBodyStyle = document.querySelector('style.' + extBodyClassName);
          if (extBodyStyle === null) {
            document.body.appendChild(mono.create('style', {
              class: extBodyClassName,
              text: mono.style2Text({
                selector: containerSelector,
                style: {
                  display: 'none'
                }
              })
            }));
          }
          SaveFrom_Utils.popupMenu.extStyleCache = options.extStyle.appendChild(mono.create('style', {
            class: extElClassName,
            text: mono.style2Text({
              selector: 'body ' + containerSelector,
              style: {
                display: 'block'
              }
            })
          }));
        }

        setTimeout(function() {
          sizeIconList.forEach(function(icon) {
            mono.trigger(icon, 'click', {
              bubbles: false,
              cancelable: true
            });
          });
        });

        return popupContainer;
      },

      update: function(popupContainer, options) {
        var _this = SaveFrom_Utils.popupMenu;

        while (popupContainer.firstChild !== null) {
          popupContainer.removeChild(popupContainer.firstChild);
        }

        var menuContent = _this.getContent.call(_this, options);
        var sizeIconList = menuContent.sizeIconList;
        menuContent = menuContent.content;
        popupContainer.appendChild(menuContent);

        setTimeout(function() {
          sizeIconList.forEach(function(icon) {
            mono.trigger(icon, 'click', {
              bubbles: false,
              cancelable: true
            });
          });
        });
      },

      preprocessItem: {
        srt2url: function(item, popupLink) {
          "use strict";
          var srt = item.srt;
          var blobUrl = mono.getDataUrl(srt, 'text/plain');

          popupLink.ext = 'srt';
          popupLink.format = 'SRT';
          popupLink.href = blobUrl;
          popupLink.noSize = true;
          if (mono.isOpera) {
            popupLink.forceDownload = false;
          }
        }
      },

      prepareLinks: {
        youtube: function(links, title, subtitles, details) {
          details = details || {};
          subtitles = subtitles || [];
          links = mono.extend({}, links);
          var sfUtilsYt = SaveFrom_Utils.video.yt;
          sfUtilsYt.init();

          var menuLinks = [];
          var popupLink = null;
          var meta = links.meta || {};

          Object.keys(sfUtilsYt.format).forEach(function(format) {
            var formatObj = sfUtilsYt.format[format];
            return Object.keys(formatObj).forEach(function(itag) {
              var url = links[itag];
              if (!url) {
                return;
              }

              var isHidden = false;

              if (!sfUtilsYt.showFormat[format]) {
                isHidden = true;
              }

              var prop = formatObj[itag];

              if (prop['3d'] && !sfUtilsYt.show3D) {
                isHidden = true;
              }

              if (prop.noAudio && !sfUtilsYt.showMP4NoAudio) {
                isHidden = true;
              }

              popupLink = {
                href: url,
                isHidden: isHidden,
                title: title,
                format: format,
                itag: itag,
                forceDownload: true
              };

              mono.extend(popupLink, prop);

              var metaTag = meta[itag];
              if (metaTag) {
                if (metaTag.quality) {
                  popupLink.quality = metaTag.quality;
                }

                if (metaTag.fps) {
                  popupLink.fps = metaTag.fps;
                }
              }

              menuLinks.push(popupLink);
              delete links[itag];
            });
          });


          (links.ummy || links.ummyAudio) && (function() {
            var qualityBadge = null;
            var qualityIndex = -1;
            var badgeQualityList = SaveFrom_Utils.popupMenu.badgeQualityList;
            menuLinks.forEach(function(popupLink) {
              var qIndex = badgeQualityList.indexOf(popupLink.quality);
              if (qIndex !== -1 && (qualityIndex === -1 || qIndex < qualityIndex)) {
                qualityIndex = qIndex;
              }
            });
            if (qualityIndex !== -1) {
              qualityBadge = badgeQualityList[qualityIndex];
            }

            var videoId = meta.videoId;
            videoId && ['ummy', 'ummyAudio'].forEach(function(itag) {
              var url = links[itag];
              if (!url) {
                return;
              }

              popupLink = {
                href: url,
                quality: 'ummy',
                noSize: true,
                format: 'ummy',
                videoId: 'yt-' + videoId
              };

              if (itag === 'ummy') {
                popupLink.itag = 'ummy';
                popupLink.uQuality = qualityBadge;
              } else
              if (itag === 'ummyAudio') {
                popupLink.itag = 'ummyAudio';
                popupLink.uQuality = 'mp3';
                popupLink.uIsAudio = true;
              }

              if (details.ummyVid) {
                popupLink.vid = details.ummyVid;
              }

              menuLinks.push(popupLink);
              delete links[itag];
            });
          })();

          Object.keys(links).forEach(function(itag) {
            if (itag === 'meta') {
              return;
            }

            popupLink = {
              href: links[itag],
              isHidden: true,
              title: title,
              quality: itag,
              itag: itag,
              forceDownload: true
            };

            menuLinks.push(popupLink);
            delete links[itag];
          });

          subtitles.forEach(function(item) {
            "use strict";
            popupLink = {
              href: item.url,
              isHidden: true,
              quality: 'SRT' + (item.isAuto ? 'A' : ''),
              itemText: mono.global.language.subtitles + ' (' + item.lang + ')',
              title: title + '-' + item.langCode,
              ext: 'vtt',
              format: 'VTT',
              isSubtitle: true,
              langCode: item.langCode,
              forceDownload: true
            };

            if (item.preprocess === 'srt2url') {
              SaveFrom_Utils.popupMenu.preprocessItem.srt2url(item, popupLink);
            }

            menuLinks.push(popupLink);
          });

          meta.extra && meta.extra.forEach(function(item) {
            popupLink = {
              href: '#' + item.extra,
              noSize: true,
              isHidden: false
            };

            mono.extend(popupLink, item);

            if (item.itag) {
              Object.keys(sfUtilsYt.format).some(function(format) {
                var formatObj = sfUtilsYt.format[format];
                var prop = formatObj[item.itag];
                if (prop) {
                  mono.extend(popupLink, prop);
                  return true;
                }
              });
            }

            if (item.request) {
              popupLink.func = function(e) {
                e.preventDefault();
                return mono.sendMessage(item.request);
              };
            }

            popupLink.noAudio = false;

            menuLinks.push(popupLink);
          });

          return menuLinks;
        },
        vimeo: function(links, title) {
          var menuLinks = [];
          var popupLink;
          links.forEach(function(link) {
            var ext = link.ext;
            if (!ext) {
              ext = 'mp4';
              if (link.url.search(/\.flv($|\?)/i) != -1) {
                ext = 'flv';
              }
            }
            var quality = link.height || '';
            var format = link.type;
            popupLink = {
              href: link.url,
              title: title,
              ext: ext,
              format: format,
              quality: quality,
              forceDownload: true
            };
            menuLinks.push(popupLink);
          });
          return menuLinks;
        },
        vk: function(links, title) {
          var menuLinks = [];
          var popupLink;
          links.forEach(function(link) {
            var ext = link.name || link.ext;
            if (ext) {
              ext = ext.toLowerCase();
            }
            var format = ext && ext.toUpperCase() || '';
            var quality = link.subname || '';
            popupLink = {
              href: link.url,
              title: title,
              ext: ext,
              format: format,
              quality: quality,
              forceDownload: true
            };
            menuLinks.push(popupLink);
          });
          return menuLinks;
        },
        dailymotion: function(links, title) {
          var menuLinks = [];

          links.forEach(function(link) {
            var popupLink = null;
            if (link.extra === 'ummy') {
              popupLink = {
                href: link.url,
                quality: 'ummy',
                noSize: true,
                format: 'ummy',
                videoId: link.videoId,
                sort: {
                  size: 480
                }
              };

              if (link.type === 'ummyAudio') {
                popupLink.uQuality = 'mp3';
                popupLink.uIsAudio = true;
              }
            } else {
              popupLink = {
                href: link.url,
                title: title,
                ext: link.ext,
                format: link.ext,
                quality: link.height || '',
                forceDownload: true
              };

              if (mono.isOpera) {
                popupLink.noSize = true;
              }
            }

            menuLinks.push(popupLink);
          });

          return menuLinks;
        },
        facebook: function(links, title) {
          var menuLinks = [];
          var popupLink;
          links.forEach(function(link) {
            var ext = link.ext;
            var format = (ext) ? ext.toUpperCase() : '';
            var quality = link.name;
            popupLink = {
              href: link.url,
              title: title,
              ext: ext,
              format: format,
              quality: quality,
              forceDownload: true
            };
            menuLinks.push(popupLink);
          });
          return menuLinks;
        },
        rutube: function(href) {
          "use strict";
          if (Array.isArray(href)) {
            href = href[0];
          }
          if (typeof href !== 'string') {
            return;
          }
          var links = [];

          var videoId = href.match(/\/embed\/(\d+)/);
          videoId = videoId && videoId[1] || undefined;

          if (!videoId) {
            videoId = href.match(/\/video\/([0-9a-z]+)/);
            videoId = videoId && videoId[1] || undefined;
          }

          if (/\/\/video\./.test(href)) {
            href = href.replace(/\/\/video\./, '//');
            if (!videoId) {
              videoId = href.match(/\/(\d+)$/);
              videoId = videoId && videoId[1] || undefined;
            }
          }

          if (videoId) {
            videoId = 'rt-' + videoId;
          }

          var ummyUrl = href.replace(/^.*(\/\/.*)$/, 'ummy:$1');

          var videoLink = {
            href: ummyUrl,
            quality: 'ummy',
            noSize: true,
            format: 'ummy',
            itag: 'ummy',
            uQuality: '720',
            vid: 114,
            videoId: videoId
          };

          var sep = '?';
          if (ummyUrl.indexOf(sep) !== -1) {
            sep = '&';
          }
          ummyUrl += sep + 'sf_type=audio';

          var audioLink = {
            href: ummyUrl,
            quality: 'ummy',
            noSize: true,
            format: 'ummy',
            itag: 'ummyAudio',
            uQuality: 'mp3',
            uIsAudio: true,
            vid: 114,
            videoId: videoId
          };

          links.push(videoLink);
          links.push(audioLink);

          return links;
        },
        mailru: function(links, title) {
          var menuLinks = [];
          var popupLink;
          links.forEach(function(link) {
            var ext = link.ext;
            var format = link.name;
            var quality = link.subname;
            popupLink = {
              href: link.url,
              title: title,
              ext: ext,
              format: format,
              quality: quality,
              forceDownload: true
            };
            menuLinks.push(popupLink);
          });
          return menuLinks;
        }
      },

      /**
       * @param {Node|Element} target
       * @param {String|Array} links
       * @param {String} id
       * @param {Object} [_details]
       * @returns {{isShow: boolean, el: Node|Element, hide: Function, update: Function}}
       */
      quickInsert: function(target, links, id, _details) {
        _details = _details || {};
        var result = {};

        var hideMenu = function(e) {
          if (e && (e.target === target || target.contains(e.target))) {
            return;
          }

          if (!result.isShow) {
            return;
          }

          menu.style.display = 'none';
          mono.off(document, 'mousedown', hideMenu);
          result.isShow = false;
          _details.onHide && _details.onHide(menu);
        };

        var options = {
          links: links,
          button: target,
          popupId: id,
          showFileSize: true
          /*
           parent: args.parent,
           extStyle: args.extStyle,
           offsetRight: args.offsetRight,
           offsetTop: args.offsetTop,
           onItemClick: args.onItemClick
           */
        };

        mono.extend(options, _details);

        var menu = SaveFrom_Utils.popupMenu.create(options);

        _details.onShow && _details.onShow(menu);

        mono.off(document, 'mousedown', hideMenu);
        mono.on(document, 'mousedown', hideMenu);

        return mono.extend(result, {
          button: target,
          isShow: true,
          el: menu,
          hide: hideMenu,
          update: function(links) {
            options.links = links;
            SaveFrom_Utils.popupMenu.update(menu, options)
          }
        });
      }
    },

    frameMenu: {
      getBtn: function(details) {
        "use strict";
        var containerStyle = {
          verticalAlign: 'middle',
          position: 'absolute',
          zIndex: 999,
          fontFamily: 'arial, sans-serif'
        };

        for (var key in details.containerStyle) {
          containerStyle[key] = details.containerStyle[key];
        }

        var quickBtnStyle = details.quickBtnStyleObj || {
          display: 'inline-block',
          fontSize: 'inherit',
          height: '22px',
          border: '1px solid rgba(255, 255, 255, 0.4)',
          borderRadius: '3px',
          borderTopRightRadius: 0,
          borderBottomRightRadius: 0,
          paddingRight: 0,
          paddingLeft: '28px',
          cursor: 'pointer',
          verticalAlign: 'middle',
          position: 'relative',
          lineHeight: '22px',
          textDecoration: 'none',
          zIndex: 1,
          color: '#fff'
        };

        if (details.singleBtn && !details.quickBtnStyleObj) {
          delete quickBtnStyle.borderTopRightRadius;
          delete quickBtnStyle.borderBottomRightRadius;
        }

        var selectBtnStyle = {
          position: 'relative',
          display: 'inline-block',
          fontSize: 'inherit',
          height: '24px',
          padding: 0,
          paddingRight: '21px',
          border: '1px solid rgba(255, 255, 255, 0.4)',
          borderLeft: 0,
          borderRadius: '3px',
          borderTopLeftRadius: '0',
          borderBottomLeftRadius: '0',
          cursor: 'pointer',
          color: '#fff',
          zIndex: 0,
          verticalAlign: 'middle',
          marginLeft: 0,
          boxSizing: 'border-box',
          lineHeight: '22px'
        };

        for (var key in details.selectBtnStyle) {
          selectBtnStyle[key] = details.selectBtnStyle[key];
        }

        var quickBtnIcon = details.quickBtnIcon || mono.create('i', {
          style: {
            position: 'absolute',
            display: 'inline-block',
            left: '6px',
            top: '3px',
            backgroundImage: 'url(' + SaveFrom_Utils.svg.getSrc('download', '#ffffff') + ')',
            backgroundSize: '12px',
            backgroundRepeat: 'no-repeat',
            backgroundPosition: 'center',
            width: '16px',
            height: '16px'
          }
        });

        var selectBtnIcon = details.selectBtnIcon || mono.create('i', {
          style: {
            position: 'absolute',
            display: 'inline-block',
            top: '9px',
            right: '6px',
            border: '5px solid #FFF',
            borderBottomColor: 'transparent',
            borderLeftColor: 'transparent',
            borderRightColor: 'transparent'
          }
        });

        var quickBtn;

        var btnContainer = mono.create('div', {
          id: details.btnId,
          style: containerStyle,
          on: details.on,
          append: [
            quickBtn = mono.create('a', {
              class: 'sf-quick-btn',
              style: quickBtnStyle,
              href: '#',
              append: [
                quickBtnIcon
              ]
            }),
            mono.create('style', {
              text: mono.style2Text({
                selector: '#' + details.btnId,
                style: details.nodeCssStyle || {
                  opacity: 0.8,
                  display: 'none'
                },
                append: [{
                  'button::-moz-focus-inner': {
                    padding: 0,
                    margin: 0
                  },
                  '.sf-quick-btn': details.quickBtnCssStyle || {
                    backgroundColor: 'rgba(28,28,28,0.1)'
                  },
                  '.sf-select-btn': {
                    backgroundColor: 'rgba(28,28,28,0.1)'
                  }
                }, {
                  selector: [':hover', '.sf-over'],
                  join: '',
                  style: {
                    opacity: 1
                  },
                  append: {
                    '.sf-quick-btn': details.quickBtnOverCssStyle || {
                      backgroundColor: 'rgba(0, 163, 80, 0.5)'
                    },
                    '.sf-select-btn': {
                      backgroundColor: 'rgba(60, 60, 60, 0.5)'
                    }
                  }
                }, {
                  join: '',
                  '.sf-over': {
                    append: {
                      '.sf-select-btn': {
                        backgroundColor: 'rgba(28,28,28,0.8)'
                      }
                    }
                  },
                  '.sf-show': {
                    display: 'block'
                  }
                }]
              })
            })
          ]
        });

        var selectBtn = null;
        var setQuality = null;
        if (!details.singleBtn) {
          setQuality = function(text) {
            var node = typeof text === 'object' ? text : document.createTextNode(text);
            var first = selectBtn.firstChild;
            if (first === selectBtnIcon) {
              selectBtn.insertBefore(node, first);
            } else {
              selectBtn.replaceChild(node, first);
            }
          };
          selectBtn = mono.create('button', {
            class: 'sf-select-btn',
            style: selectBtnStyle,
            on: details.onSelectBtn,
            append: [
              selectBtnIcon
            ]
          });
          btnContainer.appendChild(selectBtn);
        }

        return {
          node: btnContainer,
          setQuality: setQuality,
          setLoadingState: function() {
            setQuality(mono.create('img', {
              src: SaveFrom_Utils.svg.getSrc('info', '#ffffff'),
              style: {
                width: '14px',
                height: '14px',
                marginLeft: '6px',
                verticalAlign: 'middle',
                top: '-1px',
                position: 'relative'
              }
            }));
          },
          selectBtn: selectBtn,
          quickBtn: quickBtn
        };
      },

      getHiddenList: function(hiddenList, options) {
        "use strict";
        var popupMenu = SaveFrom_Utils.popupMenu;
        var moreBtn = popupMenu.createPopupItem('-text-', options).el;
        mono.create(moreBtn, {
          text: mono.global.language.more + ' ' + String.fromCharCode(187),
          style: {
            cursor: 'pointer'
          },
          on: ['click', function() {
            var content = this.parentNode;
            var itemList = content.querySelectorAll('*[' + popupMenu.dataArrtVisible + ']');
            for (var i = 0, item; item = itemList[i]; i++) {
              item.style.display = 'block';
              item.setAttribute(popupMenu.dataArrtVisible, 1);
            }
            this.parentNode.removeChild(this);
            /*content.replaceChild(mono.create('i', {
              class: 'sf-separator'
            }), this);*/
          }]
        });

        var content = document.createDocumentFragment();
        content.appendChild(moreBtn);

        mono.create(content, {
          append: hiddenList
        });

        if (options.visibleCount === 0) {
          mono.trigger(moreBtn, 'click', {
            cancelable: true
          });
        }

        return content;
      },

      getMenuContainer: function(options) {
        "use strict";
        var popupMenu = SaveFrom_Utils.popupMenu;
        var button = options.button;
        var popupId = options.popupId;

        var container = mono.create('div', {
          style: {
            position: 'absolute',
            minHeight: '24px',
            cursor: 'default',
            textAlign: 'left',
            whiteSpace: 'nowrap',
            overflow: 'auto'
          }
        });

        if (popupId[0] === '#') {
          container.id = popupId.substr(1);
        } else {
          container.classList.add(popupId);
        }

        var menuContent = popupMenu.getContent(options);
        container.appendChild(menuContent.content);

        setTimeout(function() {
          menuContent.sizeIconList.forEach(function(icon) {
            mono.trigger(icon, 'click', {
              bubbles: false,
              cancelable: true
            });
          });
        });

        var pos = SaveFrom_Utils.getPosition(button, options.parent);
        var size = SaveFrom_Utils.getSize(button);

        var stopPropagationFunc = function(e) {
          e.stopPropagation()
        };

        var topOffset = pos.top + size.height;
        var menuStyle = {
          top: topOffset + 'px',
          maxHeight: (document.body.offsetHeight - topOffset - 40) + 'px'
        };

        if (options.leftMenuPos) {
          menuStyle.left = pos.left + 'px';
        } else {
          menuStyle.right = (document.body.offsetWidth - pos.left - size.width) + 'px';
        }

        mono.create(container, {
          style: menuStyle,
          on: [
            ['click', stopPropagationFunc],
            ['mouseover', stopPropagationFunc],
            ['mouseup', stopPropagationFunc],
            ['mousedown', stopPropagationFunc],
            ['mouseout', stopPropagationFunc],
            ['wheel', function(e) {
              if (e.wheelDeltaY > 0 && this.scrollTop === 0) {
                e.preventDefault();
              } else
              if (e.wheelDeltaY < 0 && this.scrollHeight - (this.offsetHeight + this.scrollTop) <= 0) {
                e.preventDefault();
              }
            }]
          ],
          append: [
            mono.create('style', {
              text: mono.style2Text({
                selector: (popupId[0] === '#' ? '' : '.') + popupId,
                style: {
                  display: 'none',
                  fontFamily: 'arial, sans-serif',

                  backgroundColor: 'rgba(28,28,28,0.8)',
                  zIndex: 9999,
                  borderRadius: '4px',
                  fontSize: '12px',
                  fontWeight: 'bold',
                  minWidth: '190px',
                  color: '#fff'
                },
                append: [{
                  join: '',
                  '.sf-show': {
                    display: 'block'
                  },
                  '::-webkit-scrollbar-track': {
                    backgroundColor: '#424242'
                  },
                  '::-webkit-scrollbar': {
                    width: '10px',
                    backgroundColor: '#424242'
                  },
                  '::-webkit-scrollbar-thumb': {
                    backgroundColor: '#8e8e8e'
                  }
                }, {
                  '.sf-menu-item': {
                    lineHeight: '24px',
                    color: '#fff'
                  },
                  '.sf-menu-item:hover': {
                    backgroundColor: '#1c1c1c'
                  }
                }]
              })
            })
          ]
        });

        return container;
      },
      getMenu: function(target, links, id, _options) {
        "use strict";
        var options = {
          links: links,
          button: target,
          popupId: id || '#sf-frame-menu',
          showFileSize: true,
          sizeIconStyle: {
            color: '#fff'
          },
          linkClass: 'sf-menu-item',
          bindUmmyInfoDetails: {
            posLeft: true,
            widthLimit: 480,
            container: _options.container,
            createUmmyInfoDetails: {
              posLeft: true,
              darkTheme: true
            }
          },
          getHiddenListFunc: this.getHiddenList.bind(this)
        };

        for (var key in _options) {
          options[key] = _options[key];
        }

        var menu = this.getMenuContainer(options);

        (options.container || document.body).appendChild(menu);

        var hideMenu = function() {
          if (menu.parentNode) {
            menu.parentNode.removeChild(menu);
          }
          out.isShow = false;
          options.onHide && options.onHide();
        };

        options.onShow && options.onShow(menu);

        mono.off(document, 'mousedown', hideMenu);
        mono.on(document, 'mousedown', hideMenu);

        var out = {
          isShow: true,
          el: menu,
          hide: hideMenu,
          update: function(links) {
            var popupMenu = SaveFrom_Utils.popupMenu;
            var style = menu.lastChild;
            menu.textContent = '';

            options.links = links;
            var menuContent = popupMenu.getContent(options);

            setTimeout(function() {
              menuContent.sizeIconList.forEach(function(icon) {
                mono.trigger(icon, 'click', {
                  bubbles: false,
                  cancelable: true
                });
              });
            });

            menu.appendChild(menuContent.content);
            menu.appendChild(style);
          }
        };

        return out;
      }
    },

    mobileLightBox: {
      id: 'sf-lightbox',
      clear: function() {
        var el = document.getElementById(SaveFrom_Utils.mobileLightBox.id);
        if (el === null) {
          return;
        }
        el.parentNode.removeChild(el);
      },
      getTitle: function(item) {
        var title = [];

        title.push(item.format || '???');
        if (item.quality) {
          var quality = item.quality;

          if (item.sFps) {
            quality += ' ' + (item.fps || 60);
          }

          title.push(quality);
        }
        if (item['3d']) {
          title.push('3D');
        }
        if (item.noAudio) {
          title.push(mono.global.language.withoutAudio);
        }

        return title.join(' ');
      },
      createItem: function(listItem) {
        var mobileLightBox = SaveFrom_Utils.mobileLightBox;

        var button = mono.create('a', {
          style: {
            display: 'block',
            marginBottom: '6px',
            border: 'solid 1px #d3d3d3',
            lineHeight: '36px',
            minHeight: '36px',
            background: '#f8f8f8',
            verticalAlign: 'middle',
            fontSize: '15px',
            textAlign: 'center',
            color: '#333',
            borderRadius: '2px',
            overflow: 'hidden',
            position: 'relative'
          }
        });

        var filename = '';
        if (listItem.title) {
          var ext = (listItem.ext || listItem.format || '').toLowerCase();
          if (ext) {
            ext = '.' + ext;
          }
          filename = mono.fileName.modify(listItem.title + ext);
        }

        if (typeof listItem === 'string') {
          button.textContent = listItem;
          return button;
        } else {
          button.href = listItem.href;
          button.download = filename;
          button.textContent = mobileLightBox.getTitle(listItem);
        }

        if (listItem.forceDownload) {
          button.addEventListener('click', function(e) {
            SaveFrom_Utils.downloadOnClick(e, null, {
              el: this
            });
          });
        }

        if (listItem.isHidden) {
          button.classList.add('isOptional');
          button.style.display = 'none';
        }

        var ctrStyle = {
          cssFloat: 'right',
          lineHeight: '36px',
          fontSize: '75%',
          marginRight: '10px'
        };
        var svgStyle = {
          width: '16px',
          height: '16px'
        };
        var btnStyle = {
          padding: '10px',
          verticalAlign: 'middle',
          lineHeight: 0
        };
        var sizeIcon = SaveFrom_Utils.getFileSizeIcon(ctrStyle, btnStyle, svgStyle, {
          url: listItem.href
        });
        button.appendChild(sizeIcon.node);

        return button;
      },
      getItems: function(itemList) {
        var mobileLightBox = SaveFrom_Utils.mobileLightBox;

        if (typeof itemList === 'string') {
          return {
            list: [mobileLightBox.createItem(itemList)],
            hiddenCount: 0
          };
        }

        var list = [];
        for (var i = 0, item; item = itemList[i]; i++) {
          if (item.quality === 'ummy') {
            continue;
          }
          if (item.extra) {
            continue;
          }
          list.push({
            el: mobileLightBox.createItem(item),
            prop: item
          });
        }
        list = SaveFrom_Utils.popupMenu.sortMenuItems(list);
        var elList = [];
        var hiddenElList = [];
        for (i = 0, item; item = list[i]; i++) {
          if (item.prop.isHidden) {
            hiddenElList.push(item.el);
          } else {
            elList.push(item.el);
          }
        }
        return {
          list: elList.concat(hiddenElList),
          hiddenCount: hiddenElList.length
        };
      },
      show: function(itemList) {
        var mobileLightBox = SaveFrom_Utils.mobileLightBox;

        var topOffset = window.pageYOffset;
        var winHeight = window.innerHeight;
        var mTop = parseInt(winHeight / 100 * 15);
        var btnBox = undefined;
        var moreBtn;

        var getBtnBoxSize = function(hasMore) {
          "use strict";
          var i = hasMore ? 2 : 1;
          return winHeight - 46 * i - mTop * 2;
        };

        var setMoreBtnState = function(itemObj) {
          "use strict";
          if (itemObj.hiddenCount > 0) {
            btnBox.style.height = getBtnBoxSize(1) + 'px';
            moreBtn.style.display = 'block';
          } else {
            moreBtn.style.display = 'none';
            btnBox.style.height = getBtnBoxSize(0) + 'px';
          }

          if (itemObj.hiddenCount === itemObj.list.length) {
            onMoreBtnClick(moreBtn);
          }
        };

        var onMoreBtnClick = function(btnNode) {
          var state = 'none';
          var elList = btnNode.parentNode.querySelectorAll('.isOptional');
          if (btnNode.dataset.state !== 'open') {
            btnNode.dataset.state = 'open';
            btnNode.textContent = mono.global.language.more + ' ' + String.fromCharCode(171);
            state = 'block';
          } else {
            btnNode.dataset.state = 'close';
            btnNode.textContent = mono.global.language.more + ' ' + String.fromCharCode(187);
          }
          for (var i = 0, el; el = elList[i]; i++) {
            el.style.display = state;
          }
        };

        var exLb = document.getElementById(mobileLightBox.id);
        if (exLb !== null) {
          exLb.parentNode.removeChild(exLb);
        }


        var lbWidth = window.innerWidth;
        if (lbWidth <= 250) {
          lbWidth = '90%';
        } else {
          lbWidth = '70%';
        }

        if (!itemList || itemList.length === 0) {
          itemList = mono.global.language.noLinksFound;
        }

        var itemObj = mobileLightBox.getItems(itemList);

        var lightbox = mono.create('div', {
          id: mobileLightBox.id,
          style: {
            position: 'absolute',
            top: 0,
            left: 0,
            width: '100%',
            zIndex: 9000,
            height: document.body.scrollHeight + 'px',
            background: 'rgba(0,0,0,0.85)',
            textAlign: 'center',
            boxSizing: 'content-box'
          },
          on: [
            ['click', function(e) {
              e.preventDefault();
              close();
            }]
          ],
          append: mono.create('div', {
            style: {
              display: 'inline-block',
              width: lbWidth,
              backgroundColor: '#eee',
              height: (winHeight - mTop * 2) + 'px',
              marginTop: (mTop + topOffset) + 'px',
              borderRadius: '4px',
              padding: '8px',
              position: 'relative',
              boxSizing: 'content-box'
            },
            append: [
              btnBox = mono.create('div', {
                style: {
                  overflowY: 'auto',
                  marginBottom: '6px'
                },
                append: itemObj.list,
                on: ['touchmove', function(e) {
                  e.stopPropagation();
                }]
              }),
              moreBtn = mono.create(mobileLightBox.createItem(mono.global.language.more + ' ' + String.fromCharCode(187)), {
                href: '#',
                on: ['click', function(e) {
                  e.preventDefault();
                  onMoreBtnClick(this);
                }]
              }),
              mono.create(mobileLightBox.createItem(mono.global.language.close), {
                style: {
                  marginBottom: 0
                },
                on: ['click', function(e) {
                  e.preventDefault();
                  close();
                }]
              })
            ],
            on: ['click', function(e) {
              e.stopPropagation();
            }]
          })
        });

        setMoreBtnState(itemObj);

        document.body.appendChild(lightbox);

        var topPos = document.body.scrollTop;

        var result = {};

        var close = function() {
          if (!result.isShow) {
            return;
          }

          document.body.scrollTop = topPos;
          result.hide();
        };

        return mono.extend(result, {
          isShow: true,
          el: lightbox,
          hide: function() {
            lightbox.parentNode && lightbox.parentNode.removeChild(lightbox);
            result.isShow = false;
          },
          close: close,
          update: function(itemList) {
            if (lightbox.parentNode === null) {
              return;
            }

            if (!itemList || itemList.length === 0) {
              itemList = mono.global.language.noLinksFound;
            }

            btnBox.textContent = '';
            var itemObj = mobileLightBox.getItems(itemList);

            mono.create(btnBox, {
              append: itemObj.list
            });

            setMoreBtnState(itemObj);
          }
        });
      }
    },

    /**
     * @param {Object} details
     * @param {Array} [details.args]
     * @param {number} [details.timeout]
     * @param {function} details.func
     * @param {function} details.cb
     */
    bridge: function(details) {
      "use strict";
      details.args = details.args || [];
      if (details.timeout === undefined) {
        details.timeout = 300;
      }
      var scriptId = 'sf-bridge-' + parseInt(Math.random() * 1000) + '-' + Date.now();

      var listener = function(e) {
        window.removeEventListener('sf-bridge-' + scriptId, listener);
        var data;
        if (!e.detail) {
          data = undefined;
        } else {
          data = JSON.parse(e.detail);
        }
        details.cb(data);
      };

      window.addEventListener('sf-bridge-' + scriptId, listener);

      var wrapFunc = '(' + (function(func, args, scriptId, timeout) {
        /* fix */
        var node = document.getElementById(scriptId);
        if (node) {
          node.parentNode.removeChild(node);
        }

        var fired = false;
        var done = function(data) {
          if (fired) {
            return;
          }
          fired = true;

          var event = new CustomEvent('sf-bridge-' + scriptId, {
            detail: JSON.stringify(data)
          });
          window.dispatchEvent(event);
        };

        timeout && setTimeout(function() {
          done();
        }, timeout);

        args.push(done);

        func.apply(null, args);
      }).toString() + ')(' + [
        details.func.toString(),
        JSON.stringify(details.args),
        JSON.stringify(scriptId),
        parseInt(details.timeout)
      ].join(',') + ');';

      if (mono.isSafari) {
        var safariFix = function() {
          if (typeof CustomEvent === 'undefined') {
            CustomEvent = function(event, params) {
              params = params || {
                bubbles: false,
                cancelable: false
              };
              var evt = document.createEvent('CustomEvent');
              evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
              return evt;
            };
            CustomEvent.prototype = window.Event.prototype;
          }
        };
        wrapFunc = wrapFunc.replace('/* fix */', '(' + safariFix.toString() + ')();');
      } else
      if (mono.isOpera) {
        wrapFunc = wrapFunc.replace('/* fix */', 'var CustomEvent = window.CustomEvent;');
      }

      var script = mono.create('script', {
        id: scriptId,
        text: wrapFunc
      });
      document.body.appendChild(script);
    }
  };

  SaveFrom_Utils.TutorialTooltip = function(details) {
    "use strict";
    var _this = this;
    this.details = {
      btnTopOffset: -3,
      btnLeftOffset: 0
    };

    mono.extend(this.details, details);

    this.onResize = this.onResize.bind(this);
    this.onResizeDebouce = mono.debounce(this.onResize, 250);
    this.onClose = this.onClose.bind(this);

    this.target = details.target;

    if (this.target.dataset.sfHasTooltip === '1') {
      return;
    }
    this.target.dataset.sfHasTooltip = '1';


    this.tooltipNode = this.getNode();


    this.target.addEventListener('mouseup', this.onClose);

    this.target.addEventListener(mono.onRemoveEventName, function() {
      _this.onClose && _this.onClose(1);
    });

    window.addEventListener('resize', this.onResizeDebouce);

    this.onResize();

    (details.parent || document.body).appendChild(this.tooltipNode);
  };

  SaveFrom_Utils.TutorialTooltip.prototype.getNode = function() {
    "use strict";
    var _this = this;
    var language = mono.global.language;

    var zIndex = (function() {
      var zIndex = 1000;
      var top = document.getElementById('masthead-positioner');
      var styleList = top && window.getComputedStyle(top, null);
      if (styleList) {
        zIndex = parseInt(styleList.getPropertyValue('z-index')) + 1;
      }
      return zIndex;
    })();

    var box = mono.create('div', {
      class: 'sf-tooltip',
      on: ['mouseup', function(e) {
        e.stopPropagation();
      }],
      append: [
        mono.create('span', {
          style: {
            display: 'inline-block',
            border: '8px solid transparent',
            borderRight: '10px solid #4D4D4D',
            borderLeft: 0,
            width: 0,
            top: '8px',
            left: '0px',
            position: 'absolute'
          }
        }),
        mono.create('span', {
          style: {
            display: 'inline-block',
            backgroundColor: '#4D4D4D',
            marginLeft: '10px',
            padding: '10px 10px',
            maxWidth: '220px',
            minWidth: '220px',
            lineHeight: '16px',
            fontSize: '14px',
            fontFamily: 'font-family: arial, sans-serif',
            color: '#fff'
          },
          append: [
            mono.create('p', {
              style: {
                margin: 0
              },
              append: mono.parseTemplate(language.tutorialTooltipText)
            }),
            mono.create('a', {
              class: 'sf-button',
              text: 'OK',
              style: {
                display: 'inline-block',
                textAlign: 'center',
                textDecoration: 'none',
                padding: '0 10px',
                cssFloat: 'right',

                marginTop: '5px',
                lineHeight: '20px',
                borderRadius: '3px',
                fontSize: '12px',
                color: '#fff',
                fontWeight: 'bolder',
                backgroundColor: '#167AC6',
                cursor: 'pointer'
              },
              on: ['click', function(e) {
                e.preventDefault();
                _this.onClose && _this.onClose();
              }]
            }),
            mono.create('style', {
              text: mono.style2Text({
                '.sf-tooltip': {
                  position: 'absolute',
                  zIndex: zIndex + 2,
                  append: {
                    '.sf-button:hover': {
                      backgroundColor: '#126db3 !important'
                    },
                    '.sf-button:active': {
                      opacity: 0.9
                    }
                  }
                }
              })
            })
          ]
        })
      ]
    });

    return box;
  };

  SaveFrom_Utils.TutorialTooltip.prototype.onClose = function(force) {
    "use strict";
    if (force && force.type === 'mouseup') {
      force = null;
    }

    if (this.tooltipNode) {
      this.tooltipNode.parentNode && this.tooltipNode.parentNode.removeChild(this.tooltipNode);
      this.tooltipNode = null;
    }

    window.removeEventListener('resize', this.onResizeDebouce);
    this.target.removeEventListener('mouseup', this.onClose);

    this.onClose = null;
    if (!force) {
      this.details.onClose && this.details.onClose();
    }
  };

  SaveFrom_Utils.TutorialTooltip.prototype.onResize = function() {
    "use strict";
    var btn = this.target;
    if (!btn.offsetParent || !btn.parentNode) {
      return this.onClose && this.onClose(1);
    }

    var btnPos = SaveFrom_Utils.getPosition(btn, this.details.parent);
    var top = btnPos.top + this.details.btnTopOffset;
    var left = btnPos.left + btnPos.width + this.details.btnLeftOffset;
    this.tooltipNode.style.top = top + 'px';
    this.tooltipNode.style.left = left + 'px';
  };

  SaveFrom_Utils.mutationWatcher = {
    /**
     * @return {MutationObserver}
     */
    getMutationObserver: function() {
      "use strict";
      var MutationObserverCtor = null;
      if (typeof MutationObserver !== 'undefined') {
        MutationObserverCtor = MutationObserver;
      } else
      if (typeof WebKitMutationObserver !== 'undefined') {
        MutationObserverCtor = WebKitMutationObserver;
      } else
      if (typeof MozMutationObserver !== 'undefined') {
        MutationObserverCtor = MozMutationObserver;
      } else
      if (typeof JsMutationObserver !== 'undefined') {
        MutationObserverCtor = JsMutationObserver;
      }
      return MutationObserverCtor;
    },
    isAvailable: function() {
      "use strict";
      return !!this.getMutationObserver();
    },
    disconnect: function(details) {
      "use strict";
      details.observer.disconnect();
    },
    connect: function(details) {
      "use strict";
      details.observer.observe(details.target, details.config);
    },
    joinMutations: function(mutations) {
      "use strict";
      var jMutations = [];
      var targetList = [];

      var jObj = {},
        obj, hasNodes;
      var mutation, i, node, tIndex;
      while (mutation = mutations.shift()) {
        tIndex = targetList.indexOf(mutation.target);

        if (tIndex === -1) {
          tIndex = targetList.push(mutation.target) - 1;
          jObj[tIndex] = {
            target: mutation.target,
            added: [],
            removed: []
          };
        }

        obj = jObj[tIndex];
        hasNodes = undefined;

        for (i = 0; node = mutation.addedNodes[i]; i++) {
          if (node.nodeType !== 1) {
            continue;
          }

          obj.added.push(node);
          hasNodes = true;
        }

        for (i = 0; node = mutation.removedNodes[i]; i++) {
          if (node.nodeType !== 1) {
            continue;
          }

          obj.removed.push(node);
          hasNodes = true;
        }

        if (hasNodes !== undefined && obj.inList === undefined) {
          obj.inList = true;
          jMutations.push(obj);
        }
      }

      return jMutations;
    },
    isMatched: null,
    prepareMatched: function() {
      "use strict";
      if (this.isMatched) {
        return;
      }

      var el = document.createElement('div');

      if (typeof el.matches === 'function') {
        this.isMatched = function(node, selector) {
          return node.matches(selector);
        };
      } else
      if (typeof el.matchesSelector === 'function') {
        this.isMatched = function(node, selector) {
          return node.matchesSelector(selector);
        };
      } else
      if (typeof el.webkitMatchesSelector === 'function') {
        this.isMatched = function(node, selector) {
          return node.webkitMatchesSelector(selector);
        };
      } else
      if (typeof el.mozMatchesSelector === 'function') {
        this.isMatched = function(node, selector) {
          return node.mozMatchesSelector(selector);
        };
      } else
      if (typeof el.oMatchesSelector === 'function') {
        this.isMatched = function(node, selector) {
          return node.oMatchesSelector(selector);
        };
      } else
      if (typeof el.msMatchesSelector === 'function') {
        this.isMatched = function(node, selector) {
          return node.msMatchesSelector(selector);
        };
      }

      el = null;
    },
    match: function(details, summaryList, mutation) {
      "use strict";
      var _this = this;
      var node, i, query, n;
      var queries = details.queries;
      var hasChanges = false;
      ['added', 'removed'].forEach(function(type) {
        var nodeList = mutation[type];
        for (n = 0; node = nodeList[n]; n++) {
          for (i = 0; query = queries[i]; i++) {
            if (query.is !== undefined && query.is !== type) {
              continue;
            }
            var nodeArr = summaryList[i][type];
            if (_this.isMatched(node, query.css) === true) {
              nodeArr.push(node);
            } else {
              nodeArr.push.apply(nodeArr, node.querySelectorAll(query.css));
            }

            if (hasChanges === false) {
              hasChanges = nodeArr[0] !== undefined;
            }
          }
        }
      });

      return hasChanges;
    },
    filterTarget: function(queries, node) {
      "use strict";
      var i, query;
      for (i = 0; query = queries[i]; i++) {
        if (this.isMatched(node, query.css) === true) {
          return true;
        }
      }
      return false;
    },
    run: function(_details) {
      "use strict";
      var _this = this;
      var details = {
        config: {
          childList: true,
          subtree: true
        },
        target: document.body,
        filterTarget: []
      };
      mono.extend(details, _details);

      details._disconnect = this.disconnect.bind(this, details);
      details._connect = this.connect.bind(this, details);
      details._match = this.match.bind(this, details);

      var _summaryList = [];
      for (var i = 0; i < details.queries.length; i++) {
        _summaryList.push({
          added: [],
          removed: []
        });
      }
      _summaryList = JSON.stringify(_summaryList);

      this.prepareMatched();

      var mObserver = this.getMutationObserver();
      details.observer = new mObserver(function(mutations) {
        // console.time('o');
        var jMutations = _this.joinMutations(mutations);
        if (jMutations.length === 0) {
          // console.timeEnd('o');
          return;
        }

        var hasChanges = false;
        var mutation;
        var summaryList = JSON.parse(_summaryList);
        while (mutation = jMutations.shift()) {
          // console.log('mutation', mutation);
          /*console.log('mutationClone', {
            target: mutation.target.cloneNode(true),
            added: [].slice.call(mutation.added).map(function (node) {
              return node.cloneNode(true)
            }),
            removed: [].slice.call(mutation.removed).map(function (node) {
              return node.cloneNode(true)
            })
          });*/
          if (_this.filterTarget(details.filterTarget, mutation.target) === false) {
            if (details._match(summaryList, mutation) === true) {
              hasChanges = true;
            }
          }
        }

        hasChanges === true && details.callback(summaryList);
        // console.timeEnd('o');
      });

      details.trigger = function(node) {
        var hasChanges = false;
        var summaryList = JSON.parse(_summaryList);

        var mutation = {
          added: [node],
          removed: []
        };
        if (details._match(summaryList, mutation)) {
          hasChanges = true;
        }

        hasChanges === true && details.callback(summaryList);
      };

      details.start = function() {
        details._disconnect();
        details._connect();
        details.trigger(details.target);
      };

      details.stop = function() {
        details._disconnect();
      };

      details.start();

      return details;
    }
  };

  SaveFrom_Utils.mutationAttrWatcher = {
    isAvailable: function() {
      "use strict";
      return !!SaveFrom_Utils.mutationWatcher.getMutationObserver();
    },
    disconnect: function(details) {
      "use strict";
      details.observer.disconnect();
    },
    connect: function(details) {
      "use strict";
      details.observer.observe(details.target, details.config);
    },
    run: function(_details) {
      "use strict";
      var _this = this;

      var details = {
        config: {
          attributes: true,
          childList: false,
          attributeOldValue: true
        },
        target: document.body
      };

      mono.extend(details, _details);

      if (!Array.isArray(details.attr)) {
        details.attr = [details.attr];
      }

      details.config.attributeFilter = details.attr;

      details._disconnect = this.disconnect.bind(this, details);
      details._connect = this.connect.bind(this, details);

      var _summaryList = [];
      for (var i = 0; i < details.attr.length; i++) {
        _summaryList.push({});
      }
      _summaryList = JSON.stringify(_summaryList);

      var mObserver = SaveFrom_Utils.mutationWatcher.getMutationObserver();
      details.observer = new mObserver(function(mutations) {
        var hasChanges = false;
        var mutation;
        var summaryList = JSON.parse(_summaryList);
        while (mutation = mutations.shift()) {
          // console.log('mutation', mutation);
          var index = details.attr.indexOf(mutation.attributeName);
          if (index === -1) {
            continue;
          }

          var value = mutation.target.getAttribute(mutation.attributeName);
          if (value === mutation.oldValue) {
            continue;
          }

          summaryList[index] = {
            value: value,
            oldValue: mutation.oldValue
          };

          hasChanges = true;
        }

        hasChanges === true && details.callback(summaryList);
      });

      details.start = function() {
        details._disconnect();
        details._connect();

        var hasChanges = false;
        var summaryList = JSON.parse(_summaryList);

        for (var i = 0, attributeName; attributeName = details.attr[i]; i++) {
          var value = details.target.getAttribute(attributeName);
          if (value === null) {
            continue;
          }
          summaryList[i] = {
            value: value,
            oldValue: null
          };

          hasChanges = true;
        }

        hasChanges === true && details.callback(summaryList);
      };

      details.stop = function() {
        details._disconnect();
      };

      setTimeout(function() {
        details.start();
      });

      return details;
    }
  };
  /**
   * @license
   * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
   * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
   * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
   * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
   * Code distributed by Google as part of the polymer project is also
   * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
   */
  // @url https://github.com/webcomponents/webcomponentsjs
  // @version 0.7.15
  var WeakMap = (typeof WeakMap !== 'undefined') ? WeakMap : undefined;
  if (typeof WeakMap === "undefined") {
    (function() {
      var defineProperty = Object.defineProperty;
      var counter = Date.now() % 1e9;
      WeakMap = function() {
        this.name = "__st" + (Math.random() * 1e9 >>> 0) + (counter++ + "__");
      };
      WeakMap.prototype = {
        set: function(key, value) {
          var entry = key[this.name];
          if (entry && entry[0] === key) entry[1] = value;
          else defineProperty(key, this.name, {
            value: [key, value],
            writable: true
          });
          return this;
        },
        get: function(key) {
          var entry;
          return (entry = key[this.name]) && entry[0] === key ? entry[1] : undefined;
        },
        "delete": function(key) {
          var entry = key[this.name];
          if (!entry || entry[0] !== key) return false;
          entry[0] = entry[1] = undefined;
          return true;
        },
        has: function(key) {
          var entry = key[this.name];
          if (!entry) return false;
          return entry[0] === key;
        }
      };
    })();
  }

  var JsMutationObserver = (typeof JsMutationObserver !== 'undefined') ? JsMutationObserver : undefined;
  (function() {
    if (typeof JsMutationObserver !== 'undefined') {
      return;
    }
    var registrationsTable = new WeakMap();
    var setImmediate;
    if (typeof navigator !== 'undefined' && /Trident|Edge/.test(navigator.userAgent)) {
      setImmediate = setTimeout;
    } else if (window.setImmediate) {
      setImmediate = window.setImmediate;
    } else {
      var setImmediateQueue = [];
      var sentinel = String(Math.random());
      window.addEventListener("message", function(e) {
        if (e.data === sentinel) {
          var queue = setImmediateQueue;
          setImmediateQueue = [];
          queue.forEach(function(func) {
            func();
          });
        }
      });
      setImmediate = function(func) {
        setImmediateQueue.push(func);
        window.postMessage(sentinel, "*");
      };
    }
    var isScheduled = false;
    var scheduledObservers = [];

    function scheduleCallback(observer) {
      scheduledObservers.push(observer);
      if (!isScheduled) {
        isScheduled = true;
        setImmediate(dispatchCallbacks);
      }
    }

    function wrapIfNeeded(node) {
      return window.ShadowDOMPolyfill && window.ShadowDOMPolyfill.wrapIfNeeded(node) || node;
    }

    function dispatchCallbacks() {
      isScheduled = false;
      var observers = scheduledObservers;
      scheduledObservers = [];
      observers.sort(function(o1, o2) {
        return o1.uid_ - o2.uid_;
      });
      var anyNonEmpty = false;
      observers.forEach(function(observer) {
        var queue = observer.takeRecords();
        removeTransientObserversFor(observer);
        if (queue.length) {
          observer.callback_(queue, observer);
          anyNonEmpty = true;
        }
      });
      if (anyNonEmpty) dispatchCallbacks();
    }

    function removeTransientObserversFor(observer) {
      observer.nodes_.forEach(function(node) {
        var registrations = registrationsTable.get(node);
        if (!registrations) return;
        registrations.forEach(function(registration) {
          if (registration.observer === observer) registration.removeTransientObservers();
        });
      });
    }

    function forEachAncestorAndObserverEnqueueRecord(target, callback) {
      for (var node = target; node; node = node.parentNode) {
        var registrations = registrationsTable.get(node);
        if (registrations) {
          for (var j = 0; j < registrations.length; j++) {
            var registration = registrations[j];
            var options = registration.options;
            if (node !== target && !options.subtree) continue;
            var record = callback(options);
            if (record) registration.enqueue(record);
          }
        }
      }
    }
    var uidCounter = 0;
    JsMutationObserver = function(callback) {
      this.callback_ = callback;
      this.nodes_ = [];
      this.records_ = [];
      this.uid_ = ++uidCounter;
    };
    JsMutationObserver.prototype = {
      observe: function(target, options) {
        target = wrapIfNeeded(target);
        if (!options.childList && !options.attributes && !options.characterData || options.attributeOldValue && !options.attributes || options.attributeFilter && options.attributeFilter.length && !options.attributes || options.characterDataOldValue && !options.characterData) {
          throw new SyntaxError();
        }
        var registrations = registrationsTable.get(target);
        if (!registrations) registrationsTable.set(target, registrations = []);
        var registration;
        for (var i = 0; i < registrations.length; i++) {
          if (registrations[i].observer === this) {
            registration = registrations[i];
            registration.removeListeners();
            registration.options = options;
            break;
          }
        }
        if (!registration) {
          registration = new Registration(this, target, options);
          registrations.push(registration);
          this.nodes_.push(target);
        }
        registration.addListeners();
      },
      disconnect: function() {
        this.nodes_.forEach(function(node) {
          var registrations = registrationsTable.get(node);
          for (var i = 0; i < registrations.length; i++) {
            var registration = registrations[i];
            if (registration.observer === this) {
              registration.removeListeners();
              registrations.splice(i, 1);
              break;
            }
          }
        }, this);
        this.records_ = [];
      },
      takeRecords: function() {
        var copyOfRecords = this.records_;
        this.records_ = [];
        return copyOfRecords;
      }
    };

    function MutationRecord(type, target) {
      this.type = type;
      this.target = target;
      this.addedNodes = [];
      this.removedNodes = [];
      this.previousSibling = null;
      this.nextSibling = null;
      this.attributeName = null;
      this.attributeNamespace = null;
      this.oldValue = null;
    }

    function copyMutationRecord(original) {
      var record = new MutationRecord(original.type, original.target);
      record.addedNodes = original.addedNodes.slice();
      record.removedNodes = original.removedNodes.slice();
      record.previousSibling = original.previousSibling;
      record.nextSibling = original.nextSibling;
      record.attributeName = original.attributeName;
      record.attributeNamespace = original.attributeNamespace;
      record.oldValue = original.oldValue;
      return record;
    }
    var currentRecord, recordWithOldValue;

    function getRecord(type, target) {
      return currentRecord = new MutationRecord(type, target);
    }

    function getRecordWithOldValue(oldValue) {
      if (recordWithOldValue) return recordWithOldValue;
      recordWithOldValue = copyMutationRecord(currentRecord);
      recordWithOldValue.oldValue = oldValue;
      return recordWithOldValue;
    }

    function clearRecords() {
      currentRecord = recordWithOldValue = undefined;
    }

    function recordRepresentsCurrentMutation(record) {
      return record === recordWithOldValue || record === currentRecord;
    }

    function selectRecord(lastRecord, newRecord) {
      if (lastRecord === newRecord) return lastRecord;
      if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord)) return recordWithOldValue;
      return null;
    }

    function Registration(observer, target, options) {
      this.observer = observer;
      this.target = target;
      this.options = options;
      this.transientObservedNodes = [];
    }
    Registration.prototype = {
      enqueue: function(record) {
        var records = this.observer.records_;
        var length = records.length;
        if (records.length > 0) {
          var lastRecord = records[length - 1];
          var recordToReplaceLast = selectRecord(lastRecord, record);
          if (recordToReplaceLast) {
            records[length - 1] = recordToReplaceLast;
            return;
          }
        } else {
          scheduleCallback(this.observer);
        }
        records[length] = record;
      },
      addListeners: function() {
        this.addListeners_(this.target);
      },
      addListeners_: function(node) {
        var options = this.options;
        if (options.attributes) node.addEventListener("DOMAttrModified", this, true);
        if (options.characterData) node.addEventListener("DOMCharacterDataModified", this, true);
        if (options.childList) node.addEventListener("DOMNodeInserted", this, true);
        if (options.childList || options.subtree) node.addEventListener("DOMNodeRemoved", this, true);
      },
      removeListeners: function() {
        this.removeListeners_(this.target);
      },
      removeListeners_: function(node) {
        var options = this.options;
        if (options.attributes) node.removeEventListener("DOMAttrModified", this, true);
        if (options.characterData) node.removeEventListener("DOMCharacterDataModified", this, true);
        if (options.childList) node.removeEventListener("DOMNodeInserted", this, true);
        if (options.childList || options.subtree) node.removeEventListener("DOMNodeRemoved", this, true);
      },
      addTransientObserver: function(node) {
        if (node === this.target) return;
        this.addListeners_(node);
        this.transientObservedNodes.push(node);
        var registrations = registrationsTable.get(node);
        if (!registrations) registrationsTable.set(node, registrations = []);
        registrations.push(this);
      },
      removeTransientObservers: function() {
        var transientObservedNodes = this.transientObservedNodes;
        this.transientObservedNodes = [];
        transientObservedNodes.forEach(function(node) {
          this.removeListeners_(node);
          var registrations = registrationsTable.get(node);
          for (var i = 0; i < registrations.length; i++) {
            if (registrations[i] === this) {
              registrations.splice(i, 1);
              break;
            }
          }
        }, this);
      },
      handleEvent: function(e) {
        e.stopImmediatePropagation();
        switch (e.type) {
          case "DOMAttrModified":
            var name = e.attrName;
            var namespace = e.relatedNode.namespaceURI;
            var target = e.target;
            var record = new getRecord("attributes", target);
            record.attributeName = name;
            record.attributeNamespace = namespace;
            var oldValue = e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;
            forEachAncestorAndObserverEnqueueRecord(target, function(options) {
              if (!options.attributes) return;
              if (options.attributeFilter && options.attributeFilter.length && options.attributeFilter.indexOf(name) === -1 && options.attributeFilter.indexOf(namespace) === -1) {
                return;
              }
              if (options.attributeOldValue) return getRecordWithOldValue(oldValue);
              return record;
            });
            break;

          case "DOMCharacterDataModified":
            var target = e.target;
            var record = getRecord("characterData", target);
            var oldValue = e.prevValue;
            forEachAncestorAndObserverEnqueueRecord(target, function(options) {
              if (!options.characterData) return;
              if (options.characterDataOldValue) return getRecordWithOldValue(oldValue);
              return record;
            });
            break;

          case "DOMNodeRemoved":
            this.addTransientObserver(e.target);

          case "DOMNodeInserted":
            var changedNode = e.target;
            var addedNodes, removedNodes;
            if (e.type === "DOMNodeInserted") {
              addedNodes = [changedNode];
              removedNodes = [];
            } else {
              addedNodes = [];
              removedNodes = [changedNode];
            }
            var previousSibling = changedNode.previousSibling;
            var nextSibling = changedNode.nextSibling;
            var record = getRecord("childList", e.target.parentNode);
            record.addedNodes = addedNodes;
            record.removedNodes = removedNodes;
            record.previousSibling = previousSibling;
            record.nextSibling = nextSibling;
            forEachAncestorAndObserverEnqueueRecord(e.relatedNode, function(options) {
              if (!options.childList) return;
              return record;
            });
        }
        clearRecords();
      }
    };
  })();
  (typeof mono === 'undefined') && (mono = {
    loadModule: function() {
      this.loadModuleStack.push(arguments);
    },
    loadModuleStack: []
  });

  mono.loadModule('dailymotion', function(moduleName, initData) {
    "use strict";

    var language = initData.getLanguage;
    var preference = initData.getPreference;
    var moduleState = preference.moduleDailymotion ? 1 : 0;
    var Promise = mono.Promise;

    var iframe = mono.isIframe() && /\/embed\/([\w\-]+)/i.test(document.location.href);

    mono.onMessage.addListener(function(message, cb) {
      if (message.action === 'getModuleInfo') {
        if (message.url !== location.href) return;
        return cb({
          state: moduleState,
          moduleName: moduleName
        });
      }
      if (message.action === 'changeState') {
        if (moduleName !== message.moduleName) {
          return;
        }
        return dailymotion.changeState(message.state);
      }
      if (!moduleState) {
        return;
      }
      if (message.action === 'updateLinks') {
        dailymotion.updateLinks();
      }
    });

    if (moduleState) {
      mono.asyncCall(function() {
        dailymotion.run();
      });
    }

    var dailymotion = {
      contextMenu: null,
      linkCache: {},
      embed: null,
      title: '',
      styleIndex: 0,
      btnId: 'sf__download_btn',
      result: null,
      popupIsShow: false,

      run: function() {
        moduleState = 1;
        if (iframe) {
          dailymotion.appendIframeButtons();
          return;
        }

        if (SaveFrom_Utils.mutationWatcher.isAvailable()) {
          return dailymotion.mutationMode.enable();
        }
      },
      changeState: function(state) {
        if (iframe) return;
        moduleState = state;
        dailymotion.rmBtn();
        dailymotion.mutationMode.stop();
        if (state) {
          dailymotion.run();
        }
      },

      hideMenu: function() {
        if (dailymotion.contextMenu && dailymotion.contextMenu.isShow) {
          dailymotion.contextMenu.hide();
          dailymotion.contextMenu = null;
        }
      },

      updateLinks: function() {
        dailymotion.changeState(0);
        dailymotion.changeState(1);
      },

      appendIframeButtons: function() {
        var _this = this;
        var btnObj = SaveFrom_Utils.frameMenu.getBtn({
          quickBtnStyleObj: {
            display: 'inline-block',
            cursor: 'pointer',
            position: 'relative',
            padding: '9px 10px'
          },
          quickBtnCssStyle: {
            backgroundColor: 'rgba(0,0,0,.75)'
          },
          singleBtn: true,
          btnId: _this.btnId,
          containerStyle: {
            right: '50px',
            top: '10px'
          },
          quickBtnIcon: mono.create(SaveFrom_Utils.svg.getSvg('download', '#ffffff'), {
            style: {
              display: 'inline-block',
              width: '16px',
              height: '16px',
              verticalAlign: 'middle'
            }
          }),
          on: [
            ['click', function(e) {
              e.preventDefault();
              e.stopPropagation();

              if (_this.contextMenu && _this.contextMenu.isShow) {
                _this.hideMenu();
                return;
              }

              var id = _this.getIdFromUrl();
              var links = language.download + ' ...';
              var fromCache = _this.linkCache[id];
              if (fromCache) {
                links = SaveFrom_Utils.popupMenu.prepareLinks.dailymotion(fromCache.links, fromCache.title);
              }

              var menu = _this.contextMenu = SaveFrom_Utils.frameMenu.getMenu(this, links, 'sf-frame-menu', {
                container: btnObj.container,
                onShow: function() {
                  btnObj.node.classList.add('sf-over');
                },
                onHide: function() {
                  _this.contextMenu = null;
                  btnObj.node.classList.remove('sf-over');
                }
              });

              if (!fromCache) {
                mono.sendMessage({
                  action: 'getDailymotionLinks',
                  extVideoId: id,
                  metadata: _this.getMetadata(id)
                }, function(response) {
                  var menuLinks = language.noLinksFound;
                  if (response.links) {
                    _this.linkCache[id] = response;
                    menuLinks = SaveFrom_Utils.popupMenu.prepareLinks.dailymotion(response.links, response.title);
                  }
                  menu.update(menuLinks);
                });
              }
            }],
            ['mousedown', function(e) {
              e.stopPropagation();
              if (e.button === 2) {
                mono.off(document.body, 'mousemove', onMouseMove);

                _this.hideMenu();

                if (btnObj.container.parentNode) {
                  btnObj.container.parentNode.removeChild(btnObj.container);
                }
              }
            }]
          ]
        });

        btnObj.quickBtn.title = language.download;

        btnObj.container = mono.create('div', {
          class: 'sf-btn-ctr',
          append: btnObj.node
        });

        mono.on(btnObj.container, 'mouseenter', function() {
          btnObj.lockHide = true;
        });

        mono.on(btnObj.container, 'mouseleave', function() {
          btnObj.lockHide = false;
        });

        var hideTimeout = null;
        var hasClassName = false;
        var timeoutFn = function() {
          if (!btnObj.lockHide) {
            btnObj.container.classList.add('sf-hide-ui');
            hasClassName = true;
          }
        };
        var onMouseMove = function() {
          if (hasClassName) {
            btnObj.container.classList.remove('sf-hide-ui');
            hasClassName = false;
          }

          clearTimeout(hideTimeout);
          hideTimeout = setTimeout(timeoutFn, 3 * 1000);
        };
        mono.on(document.body, 'mousemove', onMouseMove);

        btnObj.node.appendChild(mono.create('style', {
          text: mono.style2Text([{
            selector: [
              'body:hover .sf-btn-ctr:not(.sf-hide-ui) #' + _this.btnId,
              'body:hover .sf-btn-ctr:not(.sf-hide-ui) .sf-frame-menu'
            ],
            style: {
              display: 'block'
            }
          }])
        }));

        document.body.appendChild(btnObj.container);
      },

      getIdFromUrl: function(url) {
        url = url || location.href;
        var videoId = url.match(/\/embed\/video\/([a-z0-9]+)/);
        videoId = videoId && videoId[1];
        return videoId;
      },

      getMetadata: function(id) {
        "use strict";
        var metadata = null;
        var scriptList = mono.getPageScript(document.body.innerHTML, /playerV5/);
        scriptList.some(function(script) {
          var jsonList = mono.findJson(script);
          return jsonList.some(function(json) {
            if (json && json.metadata && json.metadata.id === id) {
              metadata = json.metadata;
              return true;
            }
          });
        });
        return metadata;
      },

      rmBtn: function() {
        var btnList = document.querySelectorAll(['#' + dailymotion.btnId, '.sf-wrapper']);
        for (var i = 0, item; item = btnList[i]; i++) {
          item.parentNode.removeChild(item);
        }
        dailymotion.result = null;
        dailymotion.popupIsShow = false;
      },
      newGetVideoId: function() {
        var id = '';
        var m = /\/video\/([^\/]+)/.exec(location.href);
        if (m) {
          id = m[1];
        }
        return id;
      },
      newGetMetadata: function(id) {
        return new Promise(function(resolve, reject) {
          SaveFrom_Utils.bridge({
            func: function(cb) {
              try {
                cb(window.__PLAYER_CONFIG__.metadata);
              } catch (err) {
                cb(null);
              }
            },
            cb: function(result) {
              if (!result || result.id !== id) {
                reject(new Error('Metadata is not found'));
              } else {
                resolve(result);
              }
            }
          });
        }).catch(function() {
          return null;
        });
      },
      insertBtn: function(node) {
        if (node.querySelector('.sf-dl-btn')) {
          return;
        }

        var btn = mono.create('a', {
          id: dailymotion.btnId,
          class: ['sf-dl-btn'],
          href: '#',
          title: language.download,
          append: [
            mono.create('span', {
              append: [
                SaveFrom_Utils.svg.getSvg('download', '#000')
              ]
            }),
            mono.create('style', {
              text: mono.style2Text({
                selector: '.sf-dl-btn',
                style: {
                  display: 'block',
                  flex: 1,
                  textAlign: 'center',
                  cursor: 'pointer'
                }
              })
            })
          ],
          on: ['click', function(e) {
            e.preventDefault();
            e.stopPropagation();

            if (dailymotion.contextMenu && dailymotion.contextMenu.isShow) {
              dailymotion.hideMenu();
            } else {
              var results = language.download + ' ...';
              var menu = dailymotion.contextMenu = SaveFrom_Utils.popupMenu.quickInsert(this, results, 'sf-popupMenu');

              Promise.resolve().then(function() {
                var id = dailymotion.newGetVideoId();
                if (!id) {
                  throw new Error('Video is not found');
                }

                var cache = dailymotion.linkCache[id];
                if (cache) {
                  return cache;
                }

                return dailymotion.newGetMetadata(id).then(function(metadata) {
                  return mono.sendMessagePromise({
                    action: 'getDailymotionLinks',
                    extVideoId: id,
                    metadata: metadata
                  }).then(function(response) {
                    if (!response || !response.links) {
                      throw new Error('Links is not found');
                    }

                    return dailymotion.linkCache[id] = response;
                  });
                });
              }).then(function(response) {
                var menuLinks = SaveFrom_Utils.popupMenu.prepareLinks.dailymotion(response.links, response.title);
                menu.update(menuLinks);
              }).catch(function(err) {
                mono.debug('Load links error', err);
                menu.update(language.noLinksFound);
              });
            }
          }]
        });
        node.appendChild(btn);
      },
      mutationMode: {
        observer: null,
        stop: function() {
          if (this.observer) {
            this.observer.stop();
          }

          ['sfSkip'].forEach(function(attr) {
            var dataAttr = mono.dataAttr2Selector(attr);
            var dataAttrList = document.querySelectorAll('[' + dataAttr + ']');
            for (var i = 0, item; item = dataAttrList[i]; i++) {
              item.removeAttribute(dataAttr);
            }
          });
        },
        enable: function() {
          if (this.observer) {
            return this.observer.start();
          }

          this.observer = SaveFrom_Utils.mutationWatcher.run({
            callback: function(summaryList) {
              var summary, n, i, node;

              summary = summaryList[0];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                dailymotion.insertBtn(node);
              }
            },
            queries: [{
              css: 'div[class^="QueueActions__content"]',
              is: 'added'
            }]
          });
        }
      }
    };
  }, null, function syncIsActive() {
    "use strict";
    if (mono.isSafari || mono.isGM) {
      var list = [
        '*://*.dailymotion.*/*'
      ];

      var reStr = list.map(function(pattern) {
        return mono.urlPatternToStrRe(pattern);
      }).join('|');
      var re = new RegExp(reStr);

      if (!re.test(location.protocol + '//' + location.hostname)) {
        return false;
      }
    }

    if (mono.isIframe()) {
      if (!/\/embed\/([\w\-]+)/i.test(document.location.href)) {
        return false;
      }

      try {
        if (location.hostname === window.parent.location.hostname) {
          return false;
        }
      } catch (e) {}
    }

    return true;
  });
  (typeof mono === 'undefined') && (mono = {
    loadModule: function() {
      this.loadModuleStack.push(arguments);
    },
    loadModuleStack: []
  });

  mono.loadModule('facebook', function(moduleName, initData) {
    "use strict";

    var language = initData.getLanguage;
    var preference = initData.getPreference;
    var moduleState = preference.moduleFacebook ? 1 : 0;
    var Promise = mono.Promise;

    mono.onMessage.addListener(function(message, cb) {
      if (message.action === 'getModuleInfo') {
        if (message.url !== location.href) return;
        return cb({
          state: moduleState,
          moduleName: moduleName
        });
      }
      if (message.action === 'changeState') {
        if (moduleName !== message.moduleName) {
          return;
        }
        return fb.changeState(message.state);
      }
      if (!moduleState) {
        return;
      }
      if (message.action === 'updateLinks') {
        fb.changeState(0);
        fb.changeState(1);
      }
    });

    if (moduleState) {
      mono.asyncCall(function() {
        fb.run();
      });
    }

    var fb = {
      contextMenu: null,
      className: 'savefrom_fb_download',
      isMutation: false,
      run: function() {
        moduleState = 1;

        videoFeed.addStyle();
        photo.injectStyle();

        if (SaveFrom_Utils.mutationWatcher.isAvailable()) {
          this.isMutation = true;
          this.initEmbedDownloader();
          this.mutationMode.enable();
          return;
        }
      },

      changeState: function(state) {
        fb.hideMenu();
        moduleState = state;
        externalMedia.disable();
        photo.rmCurrentPhotoBtn();
        photo.rmDataAttrs();
        videoFeed.rmBtn();
        video.rmBtn();
        fb.mutationMode.stop();
        if (state) {
          fb.run();
        }
      },

      initEmbedDownloader: function() {
        SaveFrom_Utils.addStyleRules('.' + SaveFrom_Utils.embedDownloader.linkClass + ' img', {
          opacity: '.5'
        });

        SaveFrom_Utils.embedDownloader.init();
      },

      mutationMode: {
        observer: null,
        stop: function() {
          if (this.observer) {
            this.observer.stop();
          }

          ['sfSkip'].forEach(function(attr) {
            var dataAttr = mono.dataAttr2Selector(attr);
            var dataAttrList = document.querySelectorAll('[' + dataAttr + ']');
            for (var i = 0, item; item = dataAttrList[i]; i++) {
              item.removeAttribute(dataAttr);
            }
          });
        },
        wrapVideoGetLinks: function(player) {
          switch (player.tagName) {
            case 'EMBED':
              video.getLinksFromEmbed(player, function(links) {
                video.appendLinks(links);
              });
              break;
            case 'VIDEO':
              video.getLinksFromVideo(player, function(links) {
                video.appendLinks(links);
              });
              break;
          }
        },
        wrapVideoFeedOnLinkHover: function() {
          if (!moduleState) {
            return;
          }
          videoFeed.onLinkHover.apply(this);
        },
        wrapPhotoOnHover: function(context) {
          if (!moduleState) {
            return;
          }
          photo.addCurrentDlBtn(this);
        },
        wrapExternalMediaMouseEnter: function() {
          if (!moduleState) {
            return;
          }
          var link = this;
          var attr = link.dataset[externalMedia.linkDataAttr];

          if (attr) {
            clearTimeout(externalMedia.timer);
            return;
          }

          if (externalMedia.handle(link)) {
            if (externalMedia.lastLink && externalMedia.lastLink !== link) {
              externalMedia.removeBtn(externalMedia.lastLink);
            }

            SaveFrom_Utils.embedDownloader.hidePanel();
            externalMedia.lastLink = link;
          } else {
            mono.off(this, 'mouseenter', fb.mutationMode.wrapExternalMediaMouseEnter);
            mono.off(this, 'mouseleave', fb.mutationMode.wrapExternalMediaMouseLeave);
          }
        },
        wrapExternalMediaMouseLeave: function() {
          if (!moduleState) {
            return;
          }
          var link = this;
          var attr = link.dataset[externalMedia.linkDataAttr];

          if (attr) {
            clearTimeout(externalMedia.timer);
            externalMedia.timer = setTimeout(function() {
              externalMedia.removeBtn(link);
            }, 1500);
          }
        },
        wrapExternalMedia: function(node) {
          mono.on(node, 'mouseenter', fb.mutationMode.wrapExternalMediaMouseEnter);
          mono.on(node, 'mouseleave', fb.mutationMode.wrapExternalMediaMouseLeave);
        },
        enable: function() {
          if (this.observer) {
            return this.observer.start();
          }

          var _this = this;

          this.observer = SaveFrom_Utils.mutationWatcher.run({
            callback: function(summaryList) {
              var summary, n, i, node;

              for (i = 0; i < 2; i++) {
                summary = summaryList[i];
                for (n = 0; node = summary.added[n]; n++) {
                  var isInsert = false;

                  if (mono.matches(node, '#fbxPhotoContentContainer .videoStage ' + node.tagName)) {
                    isInsert = true;
                  }

                  if (isInsert) {
                    _this.wrapVideoGetLinks(node);
                  } else {
                    mono.one(node, 'mouseenter', _this.wrapVideoFeedOnLinkHover);
                  }
                }
              }

              summary = summaryList[2];
              for (n = 0; node = summary.added[n]; n++) {
                fb.hideMenu();

                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                var container = SaveFrom_Utils.getParentByClass(node, 'stageWrapper');
                mono.one(container, 'mouseenter', _this.wrapPhotoOnHover);
              }

              summary = summaryList[3];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.sfSkip > 0) {
                  continue;
                }
                node.sfSkip = '1';

                _this.wrapExternalMedia(node);
              }

              summary = summaryList[4];
              for (n = 0; node = summary.removed[n]; n++) {
                mono.onRemoveListener(node);
              }

            },
            queries: [{
                css: 'embed',
                is: 'added'
              },
              {
                css: 'video',
                is: 'added'
              },
              {
                css: [
                  '.fbPhotoSnowliftContainer .stageWrapper .stage img.spotlight',
                  '.fbPhotoSnowliftContainer .stageWrapper .stage .videoStage video'
                ],
                is: 'added'
              },
              {
                css: 'a',
                is: 'added'
              },
              {
                css: '.' + mono.onRemoveClassName,
                is: 'removed'
              }
            ]
          });
        }
      },
      hideMenu: function() {
        if (fb.contextMenu) {
          fb.contextMenu.hide();
          fb.contextMenu = null;
        }
      }
    };

    var externalMedia = {
      linkDataAttr: 'savefromEd',
      timer: 0,
      lastLink: null,

      re: [
        /https?:\/\/(?:[a-z]+\.)?youtube\.com\/(?:#!?\/)?watch\?[^\s\"\'\<\>]*v=([\w\-]+)/i,
        /https?:\/\/(?:[a-z0-9]+\.)?youtube\.com\/(?:embed|v)\/([\w\-]+)/i,
        /https?:\/\/(?:[a-z]+\.)?youtu\.be\/([\w\-]+)/i,
        /https?:\/\/(?:[\w\-]+\.)?vimeo\.com\/(\d+)(?:\?|$)/i
      ],

      thumbnail: {
        youtube: {
          re: [/ytimg\.com(?:\/|%2F)vi(?:\/|%2F)([\w\-]+)(?:\/|%2F)/i],
          url: 'http://www.youtube.com/watch?v={vid}'
        }
      },

      disable: function() {
        var panel = SaveFrom_Utils.embedDownloader.panel;
        if (panel) {
          panel.style.display = 'none';
        }
      },

      removeBtn: function(link) {
        if (!link || typeof(link) != 'object')
          return;

        var btn = link.querySelector('.' + fb.className);
        if (btn) {
          btn.parentNode.removeAttribute(mono.dataAttr2Selector(externalMedia.linkDataAttr));
          btn.parentNode.removeChild(btn);
        }

        link.removeAttribute(mono.dataAttr2Selector(externalMedia.linkDataAttr));

        if (link == this.lastLink)
          this.lastLink = null;
      },


      checkUrl: function(url, retry) {
        if (!retry && url.search(/https?:\/\/([\w\-]+\.)?facebook\.com\/l\.php/i) > -1) {
          return this.checkUrl(decodeURIComponent(url), true);
        }

        for (var i = 0, l = this.re.length; i < l; i++) {
          var m = url.match(this.re[i]);
          if (m && m.length > 0)
            return m[0];
        }
      },


      handle: function(link) {
        var img = link.querySelector('img');
        if (img) {
          var parent = img.parentNode;
          if (img.src && SaveFrom_Utils.getStyle(parent, 'position') == 'relative') {
            var ajaxify = link.getAttribute('ajaxify');

            if (ajaxify && ajaxify.search(/\/flash\/expand_inline/i) > -1) {
              var url = this.getThumbnailUrl(img.src);
              if (url) {
                return this.createButton(url, parent, link, {
                  display: 'block',
                  position: 'absolute',
                  bottom: '3px',
                  right: '3px',
                  zIndex: 9999,
                  margin: 0,
                  width: '16px',
                  height: '16px'
                }, {
                  display: 'block'
                });
              }
            } else if (this.checkUrl(link.href)) {
              return this.createButton(link.href, parent, link, {
                display: 'block',
                position: 'absolute',
                bottom: '3px',
                right: '3px',
                zIndex: 9999,
                margin: 0,
                width: '16px',
                height: '16px'
              }, {
                display: 'block'
              });
            }
          }

          return false;
        }

        return this.createButton(link.href, link, link);
      },


      getThumbnailUrl: function(url) {
        for (var i in this.thumbnail) {
          for (var j = 0; j < this.thumbnail[i].re.length; j++) {
            var vid = SaveFrom_Utils.getMatchFirst(url, this.thumbnail[i].re[j]);
            if (vid)
              return this.thumbnail[i].url.replace(/\{vid\}/ig, vid);
          }
        }

        return '';
      },


      createButton: function(url, parent, link, styleParent, styleIcon) {
        url = this.checkUrl(url);
        if (!url)
          return false;

        var btn = document.createElement('a');
        btn.className = fb.className;
        btn.href = 'http://savefrom.net/?url=' + encodeURIComponent(url);
        btn.setAttribute(SaveFrom_Utils.embedDownloader.dataAttr, url);
        btn.title = language.download;

        SaveFrom_Utils.setStyle(btn, {
          marginLeft: '7px',
          verticalAlign: 'middle'
        });

        if (styleParent)
          SaveFrom_Utils.setStyle(btn, styleParent);

        var icon = document.createElement('img');
        icon.className = 'icon';
        icon.src = SaveFrom_Utils.svg.getSrc('download', '#a2db16');
        SaveFrom_Utils.setStyle(icon, {
          display: 'inline-block',
          width: '16px',
          height: '16px',
          verticalAlign: 'middle',
          //opacity: '0.9',
          cursor: 'pointer'
        });

        if (styleIcon)
          SaveFrom_Utils.setStyle(icon, styleIcon);

        btn.appendChild(icon);

        link.dataset[this.linkDataAttr] = 1;
        parent.appendChild(btn);

        return true;
      }
    };


    var video = {
      getLinksFromEmbed: function(embed, cb) {
        if (!embed) {
          return cb(null);
        }

        var fv = embed.getAttribute('flashvars');
        if (fv === null) {
          return cb(null);
        }

        var params = mono.parseUrl(fv).params;
        if (!params) {
          return cb(null);
        }

        var videoData = null;
        try {
          videoData = JSON.parse(params).video_data;
        } catch (e) {}

        if (!videoData) {
          return cb(null);
        }

        if (videoData.progressive) {
          videoData = videoData.progressive;
        }

        var links = {};
        var typeMap = {
          sd_src: 'SD',
          hd_src: 'HD'
        };
        if (!Array.isArray(videoData)) {
          videoData = [videoData];
        }
        for (var i = 0, item; item = videoData[i]; i++) {
          ['sd_src', 'hd_src'].forEach(function(type) {
            if (!item[type]) {
              return;
            }

            links[item[type]] = typeMap[type];
          });
        }

        return cb(links);
      },

      requestLocalVideoLinks: function(videoid) {
        return new Promise(function(resolve, reject) {
          SaveFrom_Utils.bridge({
            func: function(cb) {
              var err = null;
              var token = null;
              try {
                token = require('DTSGInitialData').token;
              } catch (_err) {
                err = _err.message;
              }
              cb([err, token]);
            },
            cb: function(args) {
              var err = null;
              var token = null;
              if (!args || args[0]) {
                err = new Error('Get token timeout');
              } else {
                token = args[1];
              }
              err ? reject(err) : resolve(token);
            }
          });
        }).then(function(token) {
          return new Promise(function(resolve, reject) {
            mono.request({
              method: 'POST',
              url: 'https://www.facebook.com/video/tahoe/async/' + videoid + '/?' + mono.param({
                chain: true,
                isvideo: true
              }),
              data: mono.param({
                __a: 1,
                fb_dtsg: token
              })
            }, function(err, resp, data) {
              if (err || !data) {
                reject(new Error('Request data error'));
              } else {
                resolve(data);
              }
            });
          });
        }).then(function(data) {
          return new Promise(function(resolve, reject) {
            mono.sendMessage({
              action: 'getFacebookLinksFromData',
              extVideoId: videoid,
              data: data
            }, function(response) {
              if (!response || !response.links) {
                reject(new Error('Get links from data error'));
              } else {
                resolve(response);
              }
            });
          });
        }).catch(function(err) {
          mono.error('get local links error', err);
          throw err;
        });
      },

      requestBgVideoLinks: function(videoId) {
        return new Promise(function(resolve, reject) {
          mono.sendMessage({
            action: 'getFacebookLinks',
            extVideoId: videoId
          }, function(response) {
            if (!response || !response.links) {
              reject(new Error('Get links error'));
            } else {
              resolve(response);
            }
          });
        }).catch(function(err) {
          mono.error('get links error', err);
          throw err;
        });
      },

      requestVideoLinksById: function(videoId) {
        return Promise.resolve().then(function() {
          return video.requestLocalVideoLinks(videoId);
        }).catch(function() {
          return video.requestBgVideoLinks(videoId);
        });
      },

      requestVideoLinks: function(videoId, cb) {
        return video.requestVideoLinksById(videoId).then(function(response) {
          cb(response.links, response.title);
        }, function(err) {
          cb();
        });
      },

      getLinksFromVideo: function(videoNode, cb) {
        if (!videoNode) {
          return cb(null);
        }

        var links = {};

        var id = null;

        if (!id) {
          // video in popup
          var ctr = mono.getParent(videoNode, '.uiStreamStory[data-story-id]');
          var storyId = /:(\d+)$/.exec(ctr && ctr.dataset.storyId);
          storyId = storyId && storyId[1];
          // mono.debug('uiStreamStory', storyId);
          if (storyId) {
            id = storyId;
          }
        }
        if (!id) {
          // from wall
          var parent = mono.getParentByClass(videoNode, 'fbUserContent');
          // mono.debug('fbUserContent parent', !!parent);
          if (parent) {
            var videoLink = parent.querySelector('a[data-video-id]');
            // mono.debug('fbUserContent videoLink', !!videoLink);
            if (videoLink) {
              var videoId = videoLink && videoLink.dataset.videoId;
              // mono.debug('fbUserContent videoId', videoId);
              if (videoId) {
                id = videoId;
              }
            }
          }
        }
        if (!id) {
          // from stream wall
          var parent = mono.getParent(videoNode, '.userContentWrapper');
          // mono.debug('userContentWrapper parent', !!parent);
          if (parent) {
            var postLinkNode = parent.querySelector('div[id^="feed_subtitle_"] a[data-video-channel-id]');
            // mono.debug('userContentWrapper postLinkNode', !!postLinkNode);
            if (postLinkNode) {
              var m = /\/videos\/(\d+)/.exec(postLinkNode.href);
              var videoId = m && m[1];
              // mono.debug('userContentWrapper videoId', videoId);
              if (videoId) {
                id = videoId;
              }
            } else {
              var aTheater = parent.querySelectorAll('a.profileLink, a[rel="theater"], #fbPhotoSnowliftTimestamp > a[href]');
              // mono.debug('userContentWrapper aTheater', !!aTheater);
              var videoId = null;
              [].slice.call(aTheater).some(function(item) {
                var m = /\/videos\/(\d+)/.exec(item.href);
                return videoId = m && m[1];
              });
              // mono.debug('userContentWrapper videoId', videoId);
              if (videoId) {
                id = videoId;
              }
            }
          }
        }
        if (!id) {
          // facebook.com/username/videos/n/
          var isPageLet = false;
          var isOpenedVideo = false;
          var streamPagelet = document.getElementById('stream_pagelet');
          var prevElement = streamPagelet && streamPagelet.previousElementSibling;
          if (prevElement && prevElement.contains(videoNode)) {
            isPageLet = true;
          }
          if (!isPageLet) {
            var uiStreamStory = document.querySelector('.uiStreamStory');
            var uiStreamStoryWrap = uiStreamStory && uiStreamStory.parentNode;
            uiStreamStoryWrap = uiStreamStoryWrap && uiStreamStoryWrap.parentNode;
            if (uiStreamStoryWrap && uiStreamStoryWrap.contains(videoNode)) {
              // is opened video
              isOpenedVideo = true;
            }
          }
          if (isPageLet || isOpenedVideo) {
            var videoId = video.getVideoIdFromUrl();
            // mono.debug('isPageLet || isOpenedVideo', videoId);
            if (videoId) {
              id = videoId;
            }
          }
        }
        if (!id) {
          var permalink = mono.getParent(videoNode, '#pagelet_group_permalink');
          if (permalink) {
            var m = /video_id:"?([^,"]+)/.exec(document.body.innerHTML);
            var videoId = m && m[1];
            // mono.debug('pagelet_group_permalink videoId', videoId);
            if (videoId) {
              id = videoId;
            }
          }
        }
        id && (links.id = id);

        if (videoNode.src && /^https?:/.test(videoNode.src)) {
          var ext = SaveFrom_Utils.getFileExtension(videoNode.src, 'mp4');
          links[videoNode.src] = ext.toUpperCase();
        }

        var src = videoNode.querySelectorAll('source');
        if (src && src.length > 0) {
          for (var i = 0; i < src.length; i++) {
            var ext = SaveFrom_Utils.getFileExtension(src[i].src, 'mp4');
            links[src[i].src] = ext.toUpperCase();
          }
        }

        // mono.debug('links', links);

        if (Object.keys(links).length) {
          return cb(links);
        } else {
          return cb(null);
        }
      },

      getVideoIdFromUrl: function() {
        var videoId = null;
        SaveFrom_Utils.embedDownloader.hostings.facebook.re.some(function(reg) {
          var m = reg.exec(location.href);
          if (m) {
            videoId = m[1];
            return true;
          }
        });
        return videoId;
      },


      getFileName: function(url) {
        var name = SaveFrom_Utils.getFileName(url);
        if (name)
          return name;

        var d = SaveFrom_Utils.dateToObj();
        var dateStr = d.year + '-' + d.month + '-' + d.day + '_' +
          d.hour + '-' + d.min;

        return 'facebook_' + dateStr + '.' +
          SaveFrom_Utils.getFileExtension(url, 'mp4');
      },

      prepareLinks: function(links, _title) {
        var menuLinks = [];
        for (var url in links) {
          var title = this.getFileName(url);
          var extPos = title.lastIndexOf('.');
          var ext = title.substr(extPos + 1);
          title = _title || title.substr(0, extPos);
          var format = ext.toUpperCase();

          var quality = links[url];
          var popupLink = {
            href: url,
            title: title,
            format: format,
            quality: quality,
            forceDownload: true
          };
          menuLinks.push(popupLink);
        }
        if (menuLinks.length === 0) {
          menuLinks = language.noLinksFound;
        }
        return menuLinks;
      },

      appendLinks: function(links) {
        if (!links) {
          return;
        }

        var box = document.getElementById('fbPhotoPageMediaInfo');

        if (box === null) {
          return;
        }

        var title = document.querySelector('h2.uiHeaderTitle');
        if (title) {
          title = title.textContent;
        }

        if (!box || box.querySelector('.' + fb.className)) {
          return;
        }

        var panel = document.createElement('div');
        panel.className = fb.className;

        var button = mono.create('div', {
          title: language.download,
          style: {
            display: 'inline-block',
            width: '16px',
            height: '16px',
            backgroundImage: 'url(' + SaveFrom_Utils.svg.getSrc('download', '#a2db16') + ')',
            backgroundRepeat: 'no-repeat',
            backgroundPosition: 'center center',
            verticalAlign: 'middle',
            cursor: 'pointer'
          }
        });

        panel.appendChild(button);


        var popupMenuLinks = null;

        button.addEventListener('click', function() {
          if (fb.contextMenu && fb.contextMenu.isShow) {
            fb.hideMenu();
            return;
          }

          var menu = fb.contextMenu = SaveFrom_Utils.popupMenu.quickInsert(this, language.download + ' ...', fb.className + '_popup');

          if (popupMenuLinks) {
            menu.update(popupMenuLinks);
          } else
          if (links.id) {
            var id = links.id;
            delete links.id;
            video.requestVideoLinks(id, function(_links, title) {
              if (_links) {
                popupMenuLinks = SaveFrom_Utils.popupMenu.prepareLinks.facebook(_links, title);
              } else {
                popupMenuLinks = video.prepareLinks(links);
              }
              menu.update(popupMenuLinks);
            });
          } else {
            popupMenuLinks = video.prepareLinks(links, title);
            menu.update(popupMenuLinks);
          }
        });

        box.appendChild(panel);

        box = null;
        panel = null;
        button = null;
      },
      rmBtn: function() {
        var btnList = document.querySelectorAll('.' + fb.className);
        for (var i = 0, item; item = btnList[i]; i++) {
          item.parentNode.removeChild(item);
        }
      }
    };

    var photo = {
      style: null,
      getFilenameFromUrl: function(url) {
        return SaveFrom_Utils.getMatchFirst(url, /\/([^\/]+\.[a-z0-9]{3,4})(?:\?|$)/i);
      },
      getPhotoIdFromUrl: function() {
        var photoId = null;
        var params = mono.parseUrl(location.href);
        if (params.fbid) {
          photoId = params.fbid;
        }
        return photoId;
      },
      prepPhotoUrl: function(url) {
        if (url) {
          if (!/[?&]dl=1/.test(url)) {
            var sep = /\?/.test(url) ? '&' : '?';
            url += sep + 'dl=1'
          }
        }
        return url;
      },
      rmCurrentPhotoBtn: function(insertContainer) {
        var exBtn = undefined;
        var imgList = document.querySelectorAll('.sf-dl-current-photo-btn');
        for (var i = 0, imgItem; imgItem = imgList[i]; i++) {
          if (!insertContainer || !insertContainer.contains(imgItem)) {
            imgItem.parentNode.removeChild(imgItem);
          } else {
            exBtn = imgItem;
          }
        }
        return exBtn;
      },
      injectStyle: function() {
        if (this.style) {
          if (!this.style.parentNode) {
            document.head.appendChild(this.style);
          }
          return;
        }

        this.style = mono.create('style', {
          text: mono.style2Text({
            'div > .sf-dl-current-photo-btn': {
              display: 'none',
              position: 'absolute',
              top: '10px',
              left: '10px',
              width: '28px',
              height: '24px',
              border: 0,
              zIndex: 100,
              cursor: 'pointer',

              backgroundColor: '#000',
              padding: 0,
              borderRadius: '2px',
              opacity: 0.4,
              transition: 'opacity 100ms linear',

              lineHeight: 0
            },
            'div > .sf-dl-current-photo-btn svg': {
              margin: '4px'
            },
            'div > .sf-dl-current-photo-btn:hover': {
              opacity: 0.8
            },
            'div > .sf-dl-current-photo-btn:hover svg path': {
              fill: '#00B75A'
            },
            'body:not(.fullScreen) div:hover > .sf-dl-current-photo-btn': {
              display: 'block'
            }
          })
        });

        document.head.appendChild(this.style);
      },
      getPhotoUrlFromCtr: function(container) {
        var result = [];
        var img = container.querySelector('img.spotlight') || container.querySelector('img.fbPhotoImage');
        if (img) {
          result.push(img.src);
        }
        return result;
      },
      getVideoUrlFromPhotoCtr: function(imgContainer) {
        var videoId = null;
        var videoNode = imgContainer.querySelector('.stage .videoStage video');
        if (videoNode) {
          var parent = mono.getParent(videoNode, '.fbPhotoSnowliftPopup');
          if (parent) {
            var postLinkNode = parent.querySelector('div[id^="feed_subtitle_"] a[data-video-channel-id]');
            if (postLinkNode) {
              var m = /\/videos\/(\d+)/.exec(postLinkNode.href);
              if (m) {
                videoId = m[1];
              }
            }
          }
        }
        return videoId;
      },
      getLinksFromPhotoCtr: function(imgContainer) {
        var isVideo = mono.matches(imgContainer, '.stageWrapper.showVideo');
        if (isVideo) {
          return Promise.resolve().then(function() {
            var videoId = video.getVideoIdFromUrl();
            // mono.debug('getVideoIdFromUrl', videoId);
            if (!videoId) {
              videoId = photo.getVideoUrlFromPhotoCtr(imgContainer);
              // mono.debug('getVideoUrlFromPhotoCtr', videoId);
            }
            if (videoId) {
              return video.requestVideoLinksById(videoId);
            }
          }).then(function( /**{links:string[], title:string}*/ response) {
            // mono.debug('requestVideoLinksById', response);
            return SaveFrom_Utils.popupMenu.prepareLinks.facebook(response.links, response.title);
          });
        } else {
          return Promise.resolve().then(function() {
            var fbid = photo.getPhotoIdFromUrl();
            // mono.debug('getPhotoIdFromUrl', fbid);
            if (fbid) {
              return new Promise(function(resolve, reject) {
                mono.sendMessage({
                  action: 'getFacebookPhotoUrl',
                  fbid: fbid
                }, function(urls) {
                  // mono.debug('getFacebookPhotoUrl', url);
                  if (!urls || !urls.length) {
                    reject(new Error('getFacebookPhotoUrl can\'t get url'))
                  } else {
                    resolve(urls);
                  }
                });
              });
            } else {
              throw new Error('Can\'t get photo id from url');
            }
          }).catch(function(err) {
            var urls = photo.getPhotoUrlFromCtr(imgContainer);
            // mono.debug('getPhotoUrlFromCtr', url);
            return urls;
          }).then(function(urls) {
            // mono.debug('urls', urls);
            if (!urls || !urls.length) {
              throw new Error('Photo url not found');
            }

            return urls.map(function(url) {
              var dlUrl = photo.prepPhotoUrl(url);
              var photoFileName = mono.fileName.modify(photo.getFilenameFromUrl(dlUrl));
              var m = /(.+)\.([^.]+)$/.exec(photoFileName);
              var photoExt = 'jpg';
              var photoTitle = photoFileName;
              if (m) {
                photoExt = m[1];
                photoTitle = m[2];
              }

              return {
                href: dlUrl,
                title: photoTitle,
                quality: language.download,
                format: ' ',
                ext: photoExt,
                isBlank: true
              };
            });
          });
        }
      },
      addDlCurrentPhotoBtn: function(imgContainer) {
        var exBtn = this.rmCurrentPhotoBtn(imgContainer);
        if (exBtn) {
          return;
        }

        var button = mono.create('a', {
          class: 'sf-dl-current-photo-btn',
          href: '#',
          title: language.download,
          append: [
            SaveFrom_Utils.svg.getSvg('download', '#FFF', 16)
          ],
          on: ['click', function(e) {
            e.stopPropagation();
            e.preventDefault();

            if (fb.contextMenu && fb.contextMenu.isShow) {
              fb.hideMenu();
              return;
            }

            var onKeyDown = function(e) {
              if (e.keyCode === 18 || e.keyCode === 17) return;
              menu.hide();
              document.removeEventListener('keydown', onKeyDown);
            };

            var menu = fb.contextMenu = SaveFrom_Utils.popupMenu.quickInsert(this, language.download + ' ...', "photoDlMenu", {
              parent: imgContainer,
              onShow: function() {
                if (fb.isMutation) {
                  return;
                }
                document.addEventListener('keydown', onKeyDown);
              },
              onHide: function() {
                if (fb.isMutation) {
                  return;
                }
                document.removeEventListener('keydown', onKeyDown);
              }
            });

            photo.getLinksFromPhotoCtr(imgContainer).then(function(links) {
              // mono.debug('getLinksFromPhotoCtr', links);
              links.forEach(function(link) {
                link.func = function() {
                  menu.hide();
                };
              });

              menu.update(links);
            }).catch(function(err) {
              mono.debug('Get photo links error', err);
              menu.update(language.noLinksFound);
            });
          }]
        });

        imgContainer.appendChild(button);
      },
      addCurrentDlBtn: function(container) {
        if (container.dataset.sfSkip > 0) {
          return;
        }
        container.dataset.sfSkip = '1';

        this.addDlCurrentPhotoBtn(container);
      },
      rmDataAttrs: function() {
        var dataAttr = mono.dataAttr2Selector('sfSkip');
        var dataAttrList = document.querySelectorAll('*[' + dataAttr + ']');
        for (var i = 0, item; item = dataAttrList[i]; i++) {
          item.removeAttribute(dataAttr);
        }
      }
    };

    var videoFeed = {
      style: null,
      addStyle: function() {
        if (this.style) {
          if (!this.style.parentNode) {
            document.head.appendChild(this.style);
          }
          return;
        }

        this.style = mono.create('style', {
          class: 'sfFeedStyle',
          text: mono.style2Text([{
            selector: '.' + fb.className + '-feed' + '.sf-feed',
            style: {
              display: 'none',
              width: '20px',
              height: '20px',
              padding: 0,
              position: 'absolute',
              background: 'url(' + SaveFrom_Utils.svg.getSrc('download', '#a2db16') + ') center no-repeat transparent',
              backgroundSize: '16px',
              top: '5px',
              left: '5px',
              zIndex: 1,
              cursor: 'pointer'
            }
          }, {
            selector: 'div[role="dialog"] .' + fb.className + '-feed' + '.sf-feed',
            style: {
              top: '40px'
            }
          }, {
            selector: 'body:not(.fullScreen) div:hover > .' + fb.className + '-feed' + '.sf-feed',
            style: {
              display: 'block'
            }
          }, {
            selector: '.' + fb.className + '-feed' + '.sf-feed:active',
            style: {
              outline: 0
            }
          }])
        });

        document.head.appendChild(this.style);
      },
      onDlBtnClick: function(e) {
        e.preventDefault();
        e.stopPropagation();

        if (fb.contextMenu && fb.contextMenu.isShow) {
          fb.hideMenu();
          return;
        }

        try {
          var links = JSON.parse(this.dataset.sfDlLinks);
        } catch (e) {
          return;
        }

        var menu = fb.contextMenu = SaveFrom_Utils.popupMenu.quickInsert(this, language.download + ' ...', fb.className + '_popup');

        if (links.id) {
          var id = links.id;
          delete links.id;
          video.requestVideoLinks(id, function(_links, title) {
            var popupMenuLinks;
            if (_links) {
              popupMenuLinks = SaveFrom_Utils.popupMenu.prepareLinks.facebook(_links, title);
            } else {
              popupMenuLinks = video.prepareLinks(links);
            }
            menu.update(popupMenuLinks);
          });
        } else {
          var popupMenuLinks = video.prepareLinks(links);
          menu.update(popupMenuLinks);
        }
      },
      addDownloadBtn: function(container, links) {
        var prevBtn = container.querySelector('.' + fb.className + '-feed');
        if (prevBtn) {
          prevBtn.parentNode.removeChild(prevBtn);
        }

        container.appendChild(mono.create('a', {
          data: {
            sfDlLinks: JSON.stringify(links)
          },
          title: language.download,
          class: [fb.className + '-feed', 'sf-feed'],
          href: '#',
          on: ['click', videoFeed.onDlBtnClick]
        }));
      },
      onLinkHover: function() {
        var _this = this;
        if (this.dataset.hasSfFeedBtn > 1) {
          return;
        }
        this.dataset.hasSfFeedBtn = '1';

        var onReady = function(links) {
          if (!links) {
            _this.dataset.hasSfFeedBtn = 0;
            return;
          }

          if (mono.matches(_this, '.uiStreamStory ' + _this.tagName) ||
            mono.matches(_this, '.fbPhotoSnowliftContainer ' + _this.tagName)
          ) {
            var videoInPhoto = mono.getParent(_this, '.fbPhotoSnowliftPopup .stageWrapper');
            if (!videoInPhoto) {
              videoFeed.addDownloadBtn(_this.parentNode, links);
            }
            return;
          }

          var timeLineMainColumn = document.getElementById('pagelet_timeline_main_column') ||
            document.getElementById('stream_pagelet') ||
            document.getElementById('mainContainer');


          if (timeLineMainColumn && timeLineMainColumn.contains(_this)) {
            videoFeed.addDownloadBtn(_this.parentNode, links);
            return;
          }

          var streamPagelet = document.getElementById('stream_pagelet');
          var prevElement = streamPagelet && streamPagelet.previousElementSibling;
          if (prevElement && prevElement.contains(_this)) {
            videoFeed.addDownloadBtn(_this.parentNode, links);
            return;
          }

          var uiStreamStory = document.querySelector('.uiStreamStory');
          var uiStreamStoryWrap = uiStreamStory && uiStreamStory.parentNode;
          uiStreamStoryWrap = uiStreamStoryWrap && uiStreamStoryWrap.parentNode;
          if (uiStreamStoryWrap && uiStreamStoryWrap.contains(_this)) {
            // is opened video
            videoFeed.addDownloadBtn(_this.parentNode, links);
            return;
          }
        };

        var videoEl = this;
        if (videoEl.tagName === 'VIDEO') {
          videoEl = videoEl.querySelector('embed') || this;
        }

        if (videoEl.tagName === 'EMBED') {
          video.getLinksFromEmbed(videoEl, onReady);
        } else
        if (videoEl.tagName === 'VIDEO') {
          video.getLinksFromVideo(videoEl, onReady);
        }
      },
      rmBtn: function() {
        var dataAttr = mono.dataAttr2Selector('hasSfFeedBtn');
        var dataAttrList = document.querySelectorAll('*[' + dataAttr + ']');
        for (var i = 0, item; item = dataAttrList[i]; i++) {
          item.removeAttribute(dataAttr);
        }
        var btnList = document.querySelectorAll('.' + fb.className + '-feed');
        for (var i = 0, item; item = btnList[i]; i++) {
          item.parentNode.removeChild(item);
        }
      }
    };
  }, null, function syncIsActive() {
    "use strict";
    if (mono.isSafari || mono.isGM) {
      var list = [
        '*://*.facebook.com/*'
      ];

      var reStr = list.map(function(pattern) {
        return mono.urlPatternToStrRe(pattern);
      }).join('|');
      var re = new RegExp(reStr);

      if (!re.test(location.protocol + '//' + location.hostname)) {
        return false;
      }
    }

    if (mono.isIframe()) {
      return false;
    }

    return true;
  });
  (typeof mono === 'undefined') && (mono = {
    loadModule: function() {
      this.loadModuleStack.push(arguments);
    },
    loadModuleStack: []
  });

  mono.loadModule('lm', function(moduleName, initData) {
    "use strict";
    var language = initData.getLanguage;
    var preference = initData.getPreference;
    var moduleState = preference.lmMediaHosting ? 1 : 0;

    if (preference.showUmmyInfo) {
      mono.asyncCall(function() {
        checkUmmyPage();
      });
    }

    mono.onMessage.addListener(function(message, cb) {
      if (message.action === 'getModuleInfo') {
        if (message.url !== location.href) return;
        return cb({
          state: moduleState,
          moduleName: moduleName
        });
      }
      if (message.action === 'changeState') {
        if (moduleName !== message.moduleName) {
          return;
        }
        return lm.changeState(message.state);
      }
      if (!moduleState) {
        return;
      }
      if (message.action === 'updateLinks') {
        lm.savefromLinkCount = -1;
        lm.run();
      }
    });

    if (moduleState) {
      mono.asyncCall(function() {
        lm.run();
      });
    }

    var checkUmmyPage = function() {
      if (typeof location === 'object' && /videodownloader\.ummy\.net/.test(location.href)) {
        if (/pozdravlyaem|congratulations|tebrikler/.test(location.href)) {
          mono.sendMessage({
            action: 'updateOption',
            key: 'showUmmyInfo',
            value: 0
          });
          mono.sendMessage({
            action: 'updateOption',
            key: 'ummyDetected',
            value: 1
          });
        }
      }
    };

    var lm = {
      htmlAfter: '',

      linkText: '',

      linkStyle: {
        'border': 'none',
        'textDecoration': 'none',
        'padding': '0',
        'position': 'relative'
      },

      imgStyle: {
        'border': 'none',
        'width': 'auto',
        'height': 'auto'
      },

      buttonSrc: 'data:image/gif;base64,R0lGODlhEAAQAOZ3APf39+Xl5fT09OPj4/Hx8evr6/3+/u7u7uDh4OPi497e3t7e3/z8/P79/X3GbuXl5ubl5eHg4WzFUfb39+Pj4lzGOV7LOPz7+/n6+vn5+ZTLj9/e387Ozt7f3/7+/vv7/ISbePn5+m/JV1nRKXmVbkCnKVrSLDqsCuDh4d/e3uDn3/z7/H6TdVeaV1uSW+bn5v39/eXm5eXm5kyHP/f39pzGmVy7J3yRd9/f3mLEKkXCHJbka2TVM5vaZn6Wdfn6+YG/c/r5+ZO/jeLi41aHTIeageLn4f39/vr6+kzNG2PVM5i+lomdf2CXYKHVmtzo2YXNeDqsBebl5uHh4HDKWN3g3kKqEH6WeZHTXIPKdnSPbv79/pfmbE7PHpe1l4O8dTO5DODg4VDLIlKUUtzo2J7SmEWsLlG4NJbFjkrJHP7+/VK5Nfz8+zmnC3KKa+Hg4OHh4Y63j/3+/eDg4Ojo6P///8DAwP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAHcALAAAAAAQABAAAAfWgHd2g4SFhYJzdYqLjIpzgx5bBgYwHg1Hk2oNDXKDFwwfDF5NLmMtcStsn4MhGT8YS04aGmU1QRhIGYMTADQAQlAODlloAMYTgwICRmRfVBISIkBPKsqDBAREZmcVFhYVayUz2IMHB1dWOmImI2lgUVrmgwUFLzdtXTxKSSduMfSD6Aik48MGlx05SAykM0gKhAAPAhTB0oNFABkPHg5KMIBCxzlMQFQZMGBIggSDpsCJgGDOmzkIUCAIM2dOhEEcNijQuQDHgg4KOqRYwMGOIENIB90JBAA7',

      sfref: '&utm_source={sfHelperName}&utm_medium=extensions&utm_campaign=link_modifier',

      pageUrl: 'http://savefrom.net/',
      anchorAttribute: 'savefrom_lm',
      anchorAttributeLink: 'savefrom_lm_is_link',
      anchorIndexAttribute: 'savefrom_lm_index',

      linkRegExp: null,

      savefromLinkCount: 0,

      re: {
        mediahosting: {
          'youtube.com': [
            /^https?:\/\/([a-z]+\.)?youtube\.com\/(#!?\/)?watch\?.*v=/i,
            /^https?:\/\/([a-z0-9]+\.)?youtube\.com\/(embed|v)\/[\w\-]+/i
          ],
          'youtu.be': [/^https?:\/\/([a-z]+\.)?youtu\.be\/[\w\-]+/i],
          'google.com': [/^http:\/\/video\.google\.com\/videoplay\?.*docid=/i],
          'break.com': [/^http:\/\/(www\.)?break\.com\/(index|movies\w*|(\w+\-)+\w+)\/.+\.html$/i, /^http:\/\/view\.break\.com\/\d+/i],
          'vimeo.com': [/^http:\/\/([\w\-]+\.)?vimeo\.com\/\d+$/i],
          'sevenload.com': [/^http:\/\/([\w\-]+\.)?sevenload\.com\/videos\/[-\w\+\/=]+/i, /^http:\/\/([\w\-]+\.)?sevenload\.com\/shows\/.+/i],
          'facebook.com': [/^https?:\/\/(?:www\.)facebook\.com\/([^\/]+\/)*video\.php\?([^&]+&)*v=\d+/i],
          //'rutube.ru': [/^http:\/\/rutube\.ru\/tracks\/\d+\.html\?.*v=[a-f0-9]+/i],
          'mail.ru': [/^http:\/\/([a-z0-9_-]+\.)?video\.mail\.ru\/(.+\/)+\d+\.html/i, /^http:\/\/r\.mail\.ru\/\w+\/video\.mail\.ru\/(.+\/)+\d+\.html/i],
          'yandex.ru': [/^http:\/\/video\.yandex\.ru\/users\/[-\w,!\+]+\/view\/[-\w,!\+]+\/?/i],
          'rambler.ru': [/^http:\/\/vision\.rambler\.ru\/users\/[^\/\s]+\/\d+\/[-\w_\+!]+\/?/i],
          'smotri.com': [/^http:\/\/([a-z0-9_-]+\.)?smotri\.com\/video\/view\/\?.*id=v[0-9a-f]/i],
          'tvigle.ru': [/^http:\/\/(www\.)?tvigle\.ru\/channel\/\d+\?.*vid_id=\d+/i, /^http:\/\/(www\.)tvigle\.ru\/prg\/\d+\/\d+/i],
          '1tv.ru': [/^http:\/\/(www\.)?1tv\.ru(\:\d+)?\/newsvideo\/\d+/i, /^http:\/\/(www\.)?1tv\.ru(\:\d+)?\/news\/\w+\d+/i],
          'ntv.ru': [/^http:\/\/news\.ntv\.ru\/(\w+\/)?\d+\/video\/?/i],
          'vesti.ru': [/^http:\/\/(www\.)?vesti\.ru\/videos\?.*vid=\d+/i],
          'mreporter.ru': [/^http:\/\/(www\.)?mreporter\.ru\/reportermessages\!viewreport\.do[^\?]*\?.*reportid=\d+/i],
          'autoplustv.ru': [/^http:\/\/(www\.)?autoplustv\.ru\/494\/\?id=\d+/i],
          'amik.ru': [/^http:\/\/(www\.)?amik\.ru\/video\/vid\d+\.html/i, /^http:\/\/(www\.)?amik\.ru\/video\/vcid\d+\.html/i],
          'life.ru': [/^http:\/\/([\w+\-]+\.)?life\.ru\/video\/\d+/i]
        }
      },


      parseHref: function(href, search) {
        var res = [];
        res.push(href);

        var i = href.toLowerCase().indexOf('http://', 7);
        if (i > 7) {
          res.push(href.substring(i));
        } else if (search) {
          var h = search.match(/http%3a(%2f%2f|\/\/)[^\s\&\"\<\>]+/i);
          if (h && h.length > 0) {
            res.push(decodeURIComponent(h[0]));
          } else {
            var s = '';
            try {
              s = decodeURIComponent(search);
            } catch (err) {}

            if (s) {
              // facebook
              h = s.match(/((?:aHR0cDovL|aHR0cHM6Ly)[a-z0-9+\/=]+)/i);
              if (h && h.length > 1) {
                try {
                  h = atob(h[1]);
                } catch (e) {
                  h = '';
                }
                if (h.search(/^https?:\/\//i) != -1)
                  res.push(decodeURIComponent(h));
              }
            }
          }
        }

        return res;
      },


      href: function(a) {
        return a.getAttribute('href') || '';
      },


      getElementIndex: function(e) {
        var html = e.innerHTML;
        if (!html || html == ' ')
          return 1;

        var bg = e.style.backgroundImage;
        if (bg && bg != 'none')
          return 1;

        var c = e.getElementsByTagName('*');
        for (var i = 0; i < c.length; i++) {
          if (c[i].tagName == 'IMG')
            return 2;
          else {
            bg = c[i].style.backgroundImage;
            if (bg && bg != 'none')
              return 1;
          }
        }

        return 0;
      },


      run: function() {
        SaveFrom_Utils.embedDownloader.init();

        lm.sfref = lm.sfref.replace('{sfHelperName}', preference.sfHelperName);

        var prefMediaHosting = !!preference.lmMediaHosting;

        moduleState = 1;

        lm.linkRegExp = {};

        if (prefMediaHosting) {
          for (var i in lm.re.mediahosting)
            lm.linkRegExp[i] = lm.re.mediahosting[i];
        }


        var a = document.getElementsByTagName('a');
        if (lm.savefromLinkCount != a.length) {
          lm.savefromLinkCount = a.length;

          var found = {},
            lastHref = '';

          for (var i = 0, len = a.length; i < len; i++) {
            var href = handleAnchor(a[i]);
            if (href) {
              var index = 0;
              var attr = a[i].getAttribute(lm.anchorIndexAttribute);
              if (attr === 0 || attr)
                index = parseInt(attr);
              else {
                index = lm.getElementIndex(a[i]);
                a[i].setAttribute(lm.anchorIndexAttribute, index);
              }

              if (found[href]) {
                if (index < found[href].index) {
                  found[href].elements = [a[i]];
                  found[href].index = index;
                  lastHref = href;
                } else if (index == found[href].index && href != lastHref) {
                  found[href].elements.push(a[i]);
                  lastHref = href;
                }
              } else {
                found[href] = {
                  index: index,
                  elements: [a[i]]
                };

                lastHref = href;
              }
            }
          }

          var count = 0;
          for (var i in found) {
            for (var j = 0, len = found[i].elements.length; j < len; j++) {
              var e = found[i].elements[j];
              count++;
              if (!e.getAttribute(lm.anchorAttribute))
                modifyLink(e, i);
            }
          }
        }



        function checkLink(link, domain) {
          if (!link)
            return false;

          if (link == window.location.href)
            return false;

          domain = SaveFrom_Utils.getTopLevelDomain(domain);
          if (!domain || !lm.linkRegExp[domain])
            return false;

          for (var i = 0; i < lm.linkRegExp[domain].length; i++) {
            if (link.search(lm.linkRegExp[domain][i]) != -1)
              return true;
          }

          return false;
        }


        function handleAnchor(obj) {
          var href = obj.href;
          if (typeof href === 'string' && href.search(/^https?:\/\/([\w\-]+\.)?savefrom\.net\//i) == -1) {
            var hrefArray = lm.parseHref(href, obj.search);

            if (hrefArray.length > 0) {
              if (lm.href(obj).indexOf('#') != 0 && checkLink(hrefArray[0], obj.hostname)) {
                return hrefArray[0];
              } else if (hrefArray.length > 1) {
                for (var j = 1; j < hrefArray.length; j++) {
                  var aTemp = document.createElement('a');
                  aTemp.href = hrefArray[j];
                  if (lm.href(aTemp).indexOf('#') != 0 && checkLink(hrefArray[j], aTemp.hostname)) {
                    return hrefArray[j];
                  }
                }
              }
            }
          }

          return '';
        }

        function modifyLink(obj, link) {
          if (!obj)
            return;

          obj.setAttribute(lm.anchorAttribute, '1');

          var box = document.createElement('span');
          box.setAttribute('style', 'padding: 0; margin: 0; margin-left: 5px;');
          box.addEventListener('click', function(e) {
            e.stopPropagation();
          });

          var parent = obj.parentNode;
          if (!parent)
            return;

          try {
            link = encodeURIComponent(link);
          } catch (err) {
            return;
          }

          var href = lm.pageUrl + '?url=' + link;
          if (lm.sfref)
            href += lm.sfref;

          // add button
          var a = document.createElement('a');
          a.href = href;
          a.target = '_blank';
          a.title = language.lmButtonTitle;

          a.style.backgroundImage = 'url(' + lm.buttonSrc + ')';
          a.style.backgroundRepeat = 'no-repeat';
          a.style.width = '16px';
          a.style.height = '16px';
          a.style.display = 'inline-block';

          for (var i in lm.linkStyle)
            a.style[i] = lm.linkStyle[i];

          if (obj.style.zIndex) {
            a.style.zIndex = obj.style.zIndex;
          }

          a.setAttribute(lm.anchorAttribute, '1');
          a.setAttribute(lm.anchorAttributeLink, '1');
          if (lm.linkText) {
            a.textContent = lm.linkText;
          }

          box.appendChild(a);

          if (lm.htmlAfter)
            box.textContent += lm.htmlAfter;


          if (obj.nextSibling)
            parent.insertBefore(box, obj.nextSibling);
          else
            parent.appendChild(box);
        }
      },
      changeState: function(state) {
        preference.lmMediaHosting = state;
        moduleState = state;
        var btnList = document.querySelectorAll('a[' + lm.anchorAttributeLink + ']');
        for (var i = 0, item; item = btnList[i]; i++) {
          item = item.parentNode;
          item.parentNode.removeChild(item);
        }
        var dataAttrList = document.querySelectorAll(['*[' + lm.anchorAttribute + ']', '*[' + lm.anchorIndexAttribute + ']']);
        for (i = 0, item; item = dataAttrList[i]; i++) {
          item.removeAttribute(lm.anchorAttribute);
          item.removeAttribute(lm.anchorIndexAttribute);
        }
        lm.savefromLinkCount = -1;

        if (state) {
          lm.run();
        }
      }
    };
  }, null, function syncIsActive() {
    "use strict";
    if (document.contentType && document.contentType !== 'text/html') {
      return false;
    }

    if (mono.isIframe()) {
      return false;
    }

    if (mono.isSafari || mono.isFF || mono.isGM) {
      var excludeList = [
        'ftp://*',
        'file://*',
        '*://*.google.*/*',
        '*://*.acidtests.org/*',

        '*://*.savefrom.net/*',
        '*://*.youtube.com/*',
        '*://*.vimeo.com/*',
        '*://*.dailymotion.*/*',
        '*://*.vk.com/*',
        '*://*.vkontakte.ru/*',
        '*://*.odnoklassniki.ru/*',
        '*://*.ok.ru/*',
        '*://my.mail.ru/*',
        '*://*.soundcloud.com/*',
        '*://*.facebook.com/*',
        '*://*.instagram.com/*',
        '*://*.rutube.ru/*'
      ];

      var reStr = excludeList.map(function(pattern) {
        return mono.urlPatternToStrRe(pattern);
      }).join('|');
      var re = new RegExp(reStr);

      if (re.test(location.protocol + '//' + location.hostname)) {
        return false;
      }
    }

    if (/yandex\.com\/launcher/.test(location.href)) {
      return false;
    }

    return true;
  });

  (typeof mono === 'undefined') && (mono = {
    loadModule: function() {
      this.loadModuleStack.push(arguments);
    },
    loadModuleStack: []
  });

  mono.loadModule('odnoklassniki', function(moduleName, initData) {
    "use strict";

    var language = initData.getLanguage;
    var preference = initData.getPreference;
    var moduleState = preference.moduleOdnoklassniki ? 1 : 0;
    var allowDownloadMode = mono.isChrome || mono.isFirefox || (mono.isGM && mono.isTM);
    var Promise = mono.Promise;

    mono.onMessage.addListener(function(message, cb) {
      if (message.action === 'getModuleInfo') {
        if (message.url !== location.href) return;
        return cb({
          state: moduleState,
          moduleName: moduleName
        });
      }
      if (message.action === 'changeState') {
        if (moduleName !== message.moduleName) {
          return;
        }
        return odnoklassniki.changeState(message.state);
      }
      if (!moduleState) {
        return;
      }
      if (message.action === 'updateLinks') {
        updateLinks();
      }
      if (message.action === 'downloadMP3Files') {
        if (allowDownloadMode) {
          audio.downloadMP3Files();
        } else {
          audio.showListOfAudioFiles(false);
        }
      }
      if (message.action === 'downloadPlaylist') {
        audio.showListOfAudioFiles(true);
      }
    });

    if (moduleState) {
      mono.asyncCall(function() {
        odnoklassniki.run();
      });
    }

    var odnoklassniki = {
      linkCache: {},
      contextMenu: null,
      videoToken: null,
      run: function() {
        moduleState = 1;

        audio.getJsSessionId();
        videoFeed.injectStyle();
        photo.injectStyle();

        if (SaveFrom_Utils.mutationWatcher.isAvailable()) {
          return odnoklassniki.mutationMode.enable();
        }
      },
      changeState: function(state) {
        moduleState = state;
        video.rmBtn();
        audio.disable();
        photo.rmCurrentPhotoBtn();
        videoFeed.disable();
        videoFeed.rmBtn();
        odnoklassniki.hideMenu();
        odnoklassniki.mutationMode.stop();
        odnoklassniki.clearCache();
        if (state) {
          odnoklassniki.run();
        }
      },
      hideMenu: function() {
        if (odnoklassniki.contextMenu) {
          odnoklassniki.contextMenu.hide();
          odnoklassniki.contextMenu = null;
        }
      },
      clearCache: function() {
        var linkCache = odnoklassniki.linkCache;
        for (var key in linkCache) {
          delete linkCache[key];
        }
      },
      mutationMode: {
        observer: null,
        stop: function() {
          if (this.observer) {
            this.observer.stop();
          }

          ['sfSkip'].forEach(function(attr) {
            var dataAttr = mono.dataAttr2Selector(attr);
            var dataAttrList = document.querySelectorAll('[' + dataAttr + ']');
            for (var i = 0, item; item = dataAttrList[i]; i++) {
              item.removeAttribute(dataAttr);
            }
          });
        },
        wrapOnPhotoOver: function() {
          if (!moduleState) {
            return;
          }

          photo.addCurrentDlBtn(this);
        },
        wrapVideoFeedOnImgOver: function() {
          if (!moduleState) {
            return;
          }

          videoFeed.onImgOver.call(this);
        },
        wrapAudioOnMouseOver: function() {
          if (!moduleState) {
            return;
          }

          audio.onMouseOver.apply(this, arguments);
        },
        wrapAudioOnMouseOut: function() {
          if (!moduleState) {
            return;
          }

          audio.onMouseOut.apply(this, arguments);
        },
        enable: function() {
          if (this.observer) {
            return this.observer.start();
          }

          var _this = this;

          this.observer = SaveFrom_Utils.mutationWatcher.run({
            callback: function(summaryList) {
              var summary, n, i, node;

              for (i = 0; i < 2; i++) {
                summary = summaryList[i];
                for (n = 0; node = summary.added[n]; n++) {
                  if (node.sfSkip > 0) {
                    continue;
                  }
                  node.sfSkip = '1';

                  mono.on(node, 'mouseenter', _this.wrapAudioOnMouseOver);
                  mono.on(node, 'mouseleave', _this.wrapAudioOnMouseOut);
                }
              }

              if (!mono.isSafari && !mono.isOpera) {
                summary = summaryList[2];
                for (n = 0; node = summary.added[n]; n++) {
                  if (node.dataset.sfSkip > 0) {
                    continue;
                  }
                  node.dataset.sfSkip = '1';

                  mono.one(node, 'mouseenter', _this.wrapOnPhotoOver);
                }
              }

              summary = summaryList[3];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                var parent = mono.getParent(node, '.vp_video');
                if (!parent) {
                  return;
                }

                var info = video.getPlayerOptions(node);
                if (info) {
                  video.appendLinkUnderVideo(parent.parentNode, info);
                }
              }

              summary = summaryList[4];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                node = mono.getParentByClass(node, 'vid-card_cnt');
                if (node.dataset.sfSkip) {
                  return;
                }

                mono.one(node, 'mouseenter', _this.wrapVideoFeedOnImgOver);
              }

              for (i = 5; i < 8; i++) {
                summary = summaryList[i];
                for (n = 0; node = summary.added[n]; n++) {
                  if (node.dataset.sfSkip > 0) {
                    continue;
                  }
                  node.dataset.sfSkip = '1';

                  mono.one(node, 'mouseenter', _this.wrapVideoFeedOnImgOver);
                }
              }

              summary = summaryList[8];
              for (n = 0; node = summary.removed[n]; n++) {
                mono.onRemoveListener(node);
              }

              summary = summaryList[9];
              for (n = 0; node = summary.added[n]; n++) {
                node.addEventListener('click', videoFeed.onBtnClick);
              }
            },
            queries: [{
                css: '.track.js-track',
                is: 'added'
              },
              {
                css: '.mus-tr_i',
                is: 'added'
              },
              {
                css: '#photo-layer_photo',
                is: 'added'
              },
              {
                css: '.vp_video .vid-card_cnt',
                is: 'added'
              },
              {
                css: '.vid-card_cnt .vid-card_cnt_w img',
                is: 'added'
              },
              {
                css: '.d_comment_text_w img',
                is: 'added'
              },
              {
                css: '.video-card .video-card_img-w img',
                is: 'added'
              },
              {
                css: '.vid-card_cnt img',
                is: 'added'
              },
              {
                css: '.' + mono.onRemoveClassName,
                is: 'removed'
              },
              {
                css: '.sf-video-feed-bind-on-insert',
                is: 'added'
              }
            ]
          });
        }
      }
    };

    var downloadLinkClassName = 'savefrom_ok_download';

    var updateLinks = function() {
      odnoklassniki.clearCache();
      removeDownloadLinks();
      audio.getJsSessionId();
      video.catchPopup();
    };

    var createTextLink = function(href, text, blank) {
      if (blank == undefined)
        blank = true;

      var a = document.createElement('a');
      a.href = href;
      a.className = downloadLinkClassName;
      a.textContent = text;

      if (blank)
        a.setAttribute('target', '_blank');

      return a;
    };

    var removeDownloadLinks = function() {
      var selector = '.' + downloadLinkClassName;

      var e = document.querySelectorAll(selector);
      for (var i = e.length - 1; i >= 0; i--)
        e[i].parentNode.removeChild(e[i]);
    };

    ///////////////////////////////////////////////////////////////////
    //  AUDIO

    var audio = {
      downloadIdPrefix: 'savefrom_ok_audio_download_',
      infoIdPrefix: 'savefrom_ok_audio_info_',
      lastRow: null,
      lastRowCandidate: null,
      timer: 0,
      jsessionId: '',
      clientHashV: '',
      scriptNode: null,
      cache: {},
      ajaxTimer: {},


      showRowElements: function(row, show, force) {
        if (!row)
          return;

        var node = row.querySelectorAll('div.' + downloadLinkClassName);

        if (show && !node.length) {
          audio.showRowLinks(row);
        }

        node = row.querySelectorAll('div.' + downloadLinkClassName);
        for (var i = 0; i < node.length; i++) {
          if (show) {
            node[i].style.display = '';
          } else {
            node[i].style.display = 'none';
          }
        }
      },


      getNodeTrackId: function(node) {
        var query = node.getAttribute('data-query');
        if (query) {
          try {
            query = JSON.parse(query);
            if (query && query.trackId) {
              return query.trackId;
            }
          } catch (e) {
            return null;
          }
        }

        var span = node.querySelector('span.track_play[onclick]');
        if (span) {
          var m = /(?:playMediatopic|playFeedTrack)\(['"]?(\d+)['"]?/.exec(span.getAttribute('onclick'));
          return m && m[1];
        }

        return null;
      },


      getTrackId: function(parent) {
        var trackId = audio.getNodeTrackId(parent);
        if (trackId) {
          var links = {};
          links[trackId] = parent;
          return links;
        }

        var id = parent.id;
        if (id) {
          var hashPos = id.indexOf('#');
          if (hashPos !== -1) {
            id = id.substr(hashPos + 1);
          }
          trackId = SaveFrom_Utils.getMatchFirst(id, /^\w+_(\d+)$/i);
          if (!trackId) {
            if (id.indexOf('GROUP_FEED') !== -1) {
              trackId = id.substr(id.lastIndexOf('_') + 1);
            }
          }
          if (trackId) {
            var links = {};
            links[trackId] = parent;
            return links;
          }
        }

        return null;
      },


      showRowLinks: function(row) {
        var links = audio.getTrackId(row);
        for (var i in links) {
          if (audio.handleRow(i, links[i]))
            return true;
        }

        return false;
      },

      disable: function() {
        audio.lastRowCandidate = null;
        audio.lastRow = null;
        var dlBtn = document.querySelectorAll('.' + downloadLinkClassName);
        for (var i = 0, item; item = dlBtn[i]; i++) {
          item.parentNode.removeChild(item);
        }
      },

      getJsSessionId: function() {
        "use strict";
        var getSidViaApi = function() {
          return new Promise(function(resolve, reject) {
            SaveFrom_Utils.bridge({
              func: function(cb) {
                require(['OK/music/sid'], function(sid) {
                  sid.get().then(function(sid) {
                    cb([null, sid]);
                  }, function(err) {
                    cb([err.message]);
                  })
                });
              },
              cb: function(args) {
                if (!args) {
                  reject(new Error('Get sid timeout'))
                } else {
                  var err = args[0];
                  var sid = args[1];
                  err ? reject(new Error('Get sid error')) : resolve(sid);
                }
              }
            });
          });
        };

        var getSigViaReq = function() {
          return new Promise(function(resolve, reject) {
            var url = location.protocol + '//' + location.host + '/web-api/music/conf';
            mono.request({
              type: 'POST',
              url: url,
              data: '_',
              json: true,
              localXHR: true
            }, function(err, resp, data) {
              if (err || !data || !data.sid) {
                reject(new Error('Get jsSessionId error!'));
              } else {
                resolve(data.sid);
              }
            });
          });
        };

        return getSidViaApi().catch(function(err) {
          return getSigViaReq();
        }).then(function(sid) {
          audio.jsessionId = sid;
        }, function(err) {
          mono.debug('getJsSessionId error', err);
        });
      },


      getLink: function(trackId) {
        if (!trackId || !audio.jsessionId)
          return;

        audio.ajaxTimer[trackId] = window.setTimeout(function() {
          delete audio.ajaxTimer[trackId];
          audio.deleteLink(trackId);
        }, 30000);

        mono.sendMessage({
          action: 'getOdnoklassnikiAudioLinks',
          url: location.href,
          trackId: trackId,
          jsessionId: audio.jsessionId
        }, function(response) {
          audio.setLink(response.trackId, response.data);
        });
      },


      onMouseOver: function() {
        if (!audio.jsessionId) {
          return;
        }

        var node = this;
        if (node) {
          audio.lastRowCandidate = node;
          clearTimeout(audio.timer);

          if (audio.lastRow !== node) {
            audio.timer = window.setTimeout(function() {
              audio.showRowElements(audio.lastRow, false);
              audio.lastRow = node;
              audio.lastRowCandidate = null;
              audio.showRowElements(audio.lastRow, true);
            }, 250);
          }
        }
      },


      onMouseOut: function() {
        var node = this;
        if (
          (audio.lastRow && audio.lastRow.contains(node)) ||
          (audio.lastRowCandidate && audio.lastRowCandidate.contains(node))
        ) {
          clearTimeout(audio.timer);
          audio.timer = window.setTimeout(function() {
            audio.showRowElements(audio.lastRow, false);
            audio.lastRow = null;
            audio.lastRowCandidate = null;
          }, 1000);
        }
        node = null;
      },


      handleRow: function(trackId, row) {
        if (!trackId || !row)
          return false;

        var parent = row;
        parent.style.position = 'relative';

        var duration = row.querySelector('.m_c_duration, .m_portal_duration');

        var box = document.createElement('div');
        box.className = downloadLinkClassName;

        var right = 40;
        var mmpcw = document.getElementById('mmpcw');
        if (mmpcw && mmpcw.contains(row)) {
          right = 65;
        }

        SaveFrom_Utils.setStyle(box, {
          color: '#fff',
          background: '#46aa19',
          border: '1px solid #337d12',
          borderRadius: '3px',
          padding: '1px 5px',
          position: 'absolute',
          right: right + 'px',
          top: '50%',
          lineHeight: '15px',
          fontSize: '12px',
          opacity: 0,
          zIndex: 9999,
          cursor: 'pointer'
        });

        box.addEventListener('click', audio.onBoxClick, false);

        box.addEventListener('mousedown', function(e) {
          e.stopPropagation();
        }, false);

        var title = audio.getTitle(trackId, row);

        var link1 = createTextLink('#', '...');
        link1.id = audio.downloadIdPrefix + trackId;
        link1.title = language.downloadTitle;
        if (duration) {
          link1.setAttribute('data-savefrom-helper-duration',
            audio.secondsFromDurationNode(duration));
        }

        if (title) {
          title += '.mp3';
          link1.setAttribute('download', mono.fileName.modify(title));
        }

        SaveFrom_Utils.setStyle(link1, {
          color: '#fff',
          fontWeight: 'normal'
        });

        link1.addEventListener('click', audio.onDownloadLinkClick, false);

        box.appendChild(link1);
        parent.appendChild(box);

        if (audio.cache[trackId])
          audio.setLinkFromCache(trackId, link1);
        else
          audio.getLink(trackId);

        box.style.marginTop = '-' + (box.offsetHeight / 2) + 'px';
        box.style.opacity = '1';

        var close = document.createElement('span');
        close.textContent = String.fromCharCode(215);
        close.title = language.close;
        SaveFrom_Utils.setStyle(close, {
          color: '#fff',
          fontFamily: 'Tahoma,Helvetica,sans-serif',
          fontSize: '15px',
          marginLeft: '7px',
          opacity: '.7',
          cursor: 'pointer'
        });
        close.addEventListener('click', audio.onCloseBtnClick, false);
        box.appendChild(close);

        return true;
      },


      onBoxClick: function(event) {
        event.preventDefault();
        event.stopPropagation();

        var a = this.querySelector('a.' + downloadLinkClassName);
        if (a) {
          mono.trigger(a, 'click', {
            cancelable: true
          });
          return false;
        }

        this.style.display = 'none';
        return false;
      },


      onDownloadLinkClick: function(event) {
        if (event.button == 2)
          return false;

        event.stopPropagation();

        if (this.href == '#') {
          event.preventDefault();
          return false;
        }

        SaveFrom_Utils.downloadOnClick(event);

        return false;
      },


      onCloseBtnClick: function(event) {
        if (event.button == 2)
          return true;

        event.preventDefault();
        event.stopPropagation();

        var parent = mono.getParent(this, '.' + downloadLinkClassName);
        if (parent)
          parent.style.display = 'none';

        return false;
      },


      deleteLink: function(trackId, node) {
        if (!node && trackId)
          node = document.getElementById(audio.downloadIdPrefix + trackId);

        if (!node)
          return;

        var box = node.parentNode;
        if (!box) {
          return;
        }
        box.parentNode.removeChild(box);
      },


      getHash: function(src, magic) {
        if (!magic)
          magic = [4, 3, 5, 6, 1, 2, 8, 7, 2, 9, 3, 5, 7, 1, 4, 8, 8, 3, 4, 3, 1, 7, 3, 5, 9, 8, 1, 4, 3, 7, 2, 8];

        var a = [];
        for (var i = 0; i < src.length; i++) {
          a.push(parseInt('0x0' + src.charAt(i)));
        }

        src = a;

        var res = [];
        src = src.slice(0);
        src[32] = src[31];
        var sum = 0;
        var i = 32;
        while (i-- > 0)
          sum += src[i];

        for (var x = 0; x < 32; x++)
          res[x] = Math.abs(sum - src[x + 1] * src[x] * magic[x]);

        return res.join('');
      },


      setLinkFromCache: function(trackId, node) {
        if (!audio.cache[trackId])
          return false;

        if (!node)
          node = document.getElementById(audio.downloadIdPrefix + trackId);

        if (!node)
          return;

        node.href = audio.cache[trackId].url;
        node.textContent = '';
        if (audio.cache[trackId].downloadAttr)
          node.setAttribute('download', audio.cache[trackId].downloadAttr);

        var icon = mono.create(SaveFrom_Utils.svg.getSvg('download', '#ffffff'), {
          style: {
            display: 'inline-block',
            width: '16px',
            height: '16px',
            verticalAlign: 'middle',
            opacity: '0.9'
          }
        });
        node.appendChild(icon);

        var info = document.createTextNode(audio.cache[trackId].info);

        if (node.nextSibling)
          node.parentNode.insertBefore(info, node.nextSibling);
        else
          node.parentNode.appendChild(info);

        return true;
      },

      getClientHash: function(url) {
        var md5fn = audio.md5;
        var getViaApi = function() {
          if (audio.getClientHash.getViaApiError) {
            return Promise.reject(audio.getClientHash.getViaApiError);
          }

          return new Promise(function(resolve, reject) {
            SaveFrom_Utils.bridge({
              args: [url],
              func: function(url, cb) {
                require(['OK/music/garbage'], function(m) {
                  try {
                    cb([null, /clientHash=([^&]+)/.exec(m.calc(url))[1]]);
                  } catch (err) {
                    cb([err.message]);
                  }
                });
              },
              cb: function(args) {
                if (!args) {
                  reject(new Error('getClientHash timeout'));
                } else {
                  var err = args[0];
                  var result = args[1];
                  err ? reject(new Error('getClientHash error')) : resolve(result);
                }
              }
            });
          }).catch(function(err) {
            audio.getClientHash.getViaApiError = err;
            throw err;
          });
        };

        var getViaConfig = function() {
          var getClientHash = function(n, k, e) {
            var r = /md5=(\w*)/g.exec(n)[1],
              q = k(r + "secret"),
              u = q.length,
              t = 0,
              p, v, s, o = "";
            for (p = 0; p < u; p += 1) {
              t += parseInt(q[p], 16);
            }
            for (p = 0; p < u; p += 1) {
              v = parseInt(q[p], 16);
              if (p === u - 1) {
                s = v;
              } else {
                s = parseInt(q[p + 1], 16);
              }
              o += Math.abs(t - (v * s * e[p]));
            }
            return o;
          };
          var getV = function() {
            if (audio.clientHashV) {
              return Promise.resolve(audio.clientHashV);
            }

            return new Promise(function(resolve, reject) {
              SaveFrom_Utils.bridge({
                func: function(cb) {
                  try {
                    cb([null, require.s.contexts._.config.config['OK/music/garbage'].v]);
                  } catch (err) {
                    cb([err.message]);
                  }
                },
                cb: function(args) {
                  if (!args) {
                    reject(new Error('getClientHash timeout'))
                  } else {
                    var err = args[0];
                    var result = args[1];
                    err ? reject(new Error('getClientHash error')) : resolve(result);
                  }
                }
              });
            }).then(function(v) {
              return audio.clientHashV = v;
            });
          };
          return getV().then(function(v) {
            return getClientHash(url, md5fn, v);
          });
        };

        return getViaApi().catch(function(err) {
          return getViaConfig();
        });
      },

      setLink: function(trackId, data, clientHash) {
        if (!trackId)
          return;

        clearTimeout(audio.ajaxTimer[trackId]);

        var node = document.getElementById(audio.downloadIdPrefix + trackId);
        if (!node)
          return;

        if (audio.setLinkFromCache(trackId, node))
          return;

        if (!data || !data.play) {
          audio.deleteLink(trackId, node);
          node.textContent = '?';
          return;
        }

        if (clientHash === undefined) {
          return this.getClientHash(data.play).then(function(clientHash) {
            audio.setLink(trackId, data, clientHash);
          }, function(err) {
            audio.deleteLink(trackId, node);
          });
        }

        var size = data.track && data.track.size || -1;

        audio.cache[trackId] = {};
        audio.cache[trackId].url = data.play + (clientHash ? '&clientHash=' + clientHash : '');

        var info = ' (' + SaveFrom_Utils.sizeHuman(size, 2);

        var duration = node.getAttribute('data-savefrom-helper-duration');
        if (data.track) {
          if (data.track.duration)
            duration = data.track.duration;

          if (data.track.ensemble && data.track.name) {
            var title = data.track.ensemble + ' - ' + data.track.name;
            audio.cache[trackId].title = title;
            audio.cache[trackId].downloadAttr = mono.fileName.modify(title + '.mp3');
          }
        }

        if (size && size > 0 && duration) {
          duration = parseInt(duration);
          if (isNaN(duration)) {
            delete audio.cache[trackId];
            return;
          }

          var bitrate = Math.floor((size / duration) / 125) + ' ' + language.kbps;
          info += ' ~ ' + bitrate;
        }

        info += ')';
        audio.cache[trackId].info = info;

        audio.setLinkFromCache(trackId, node);
      },


      getTitle: function(id, row) {
        if (!id || !row)
          return '';

        var name = '';

        var performer = row.querySelector('.m_c_artist, .mus-tr_artist, .m_portal_c_artist');
        var title = row.querySelector('.m_track_source, .mus-tr_song, .m_portla_track_name');

        if (performer) {
          performer = performer.textContent;
          if (performer)
            name += performer.trim();
        }

        if (title) {
          title = title.textContent;
          if (title) {
            if (name)
              name += ' - ';

            name += title.trim();
          }
        }

        if (name)
          return name.replace(/\<a\s+[^\>]+\>/ig, '').replace(/\<\/a\>/ig, '');

        return '';
      },


      secondsFromDurationNode: function(node) {
        if (!node)
          return 0;

        var text = node.textContent;
        if (!text)
          return 0;

        var m = text.match(/^(?:\s*(\d+)\s*\:)?\s*(\d+)\s*\:\s*(\d+)/);
        if (m && m.length > 3) {
          if (!m[1])
            m[1] = 0;

          return parseInt(m[1]) * 3600 + parseInt(m[2]) * 60 + parseInt(m[3]);
        }

        return 0;
      },

      getPlaylistName: function(container) {
        if (container === document) return;

        var title = container.querySelector('.mus_h2_tx');
        if (!title) return;
        return mono.fileName.modify(title.textContent) || undefined;
      },

      elIsHidden: function isHidden(el) {
        return (el.offsetParent === null)
      },

      getLayer: function() {
        var layer = document.getElementById('mmpcw');
        if (!layer) {
          return;
        }
        if (layer.classList.contains('__hidden')) {
          return;
        }
        layer = layer.querySelector('div.m_c_s[aria-hidden="false"]');
        if (!layer || audio.elIsHidden(layer)) {
          return;
        }
        return layer;
      },

      getPopup: function(title, type, onClose) {
        var template = SaveFrom_Utils.playlist.getInfoPopupTemplate();

        var progressEl;
        mono.create(template.textContainer, {
          append: [!title ? undefined : mono.create('p', {
              text: title,
              style: {
                color: '#0D0D0D',
                fontSize: '20px',
                marginBottom: '11px',
                marginTop: '13px'
              }
            }),
            progressEl = mono.create('p', {
              text: '',
              style: {
                color: '#868686',
                fontSize: '14px',
                lineHeight: '24px'
              }
            })
          ]
        });

        var popupEl = SaveFrom_Utils.popupDiv(template.body, 'sf_progress_popup', undefined, undefined, onClose);

        var setState = function(state) {
          if (setState.state === state) {
            return;
          }
          setState.state = state;

          template.buttonContainer.style.display = 'none';
          progressEl.style.display = 'none';
          mono.sendMessage({
            action: 'getWarningIcon',
            type: type,
            color: '#77D1FA'
          }, function(icon) {
            template.icon.style.backgroundImage = 'url(' + icon + ')';
          });
          if (state === 'progress') {
            progressEl.style.display = 'block';
          }
          if (state === 'error') {
            mono.sendMessage({
              action: 'getWarningIcon',
              type: type,
              color: '#AAAAAA'
            }, function(icon) {
              template.icon.style.backgroundImage = 'url(' + icon + ')';
            });
            progressEl.style.display = 'block';
          }
        };

        return {
          onPrepare: function(text) {
            setState('progress');
            progressEl.textContent = text;
          },
          onProgress: function(count, max) {
            progressEl.textContent = language.vkFoundFiles.replace('%d', count) + ' ' + language.vkFoundOf + ' ' + max;
          },
          onReady: function() {
            mono.trigger(popupEl, 'kill');
          },
          onError: function(text) {
            setState('error');
            progressEl.textContent = text;
          }
        }
      },

      getAudioLinksViaAPI: function(trackIdList, onProgress, cb) {
        var abort = false;
        var trackList = [];
        var len = trackIdList.length;
        var next = function() {
          if (abort) {
            return;
          }
          var trackIdArr = trackIdList.splice(0, 10);
          if (trackIdArr.length === 0) {
            return cb(trackList);
          }

          mono.sendMessage({
            action: 'getOkAudioListLinks',
            trackIdArr: trackIdArr,
            jsessionId: audio.jsessionId
          }, function(responseList) {
            var promise = Promise.resolve();
            if (Array.isArray(responseList)) {
              responseList.forEach(function(item) {
                promise = promise.then(function() {
                  if (typeof item.play !== 'string' || typeof item.track !== 'object') return;

                  var url = item.play;

                  var title;
                  if (item.track.name) {
                    title = item.track.name;
                  }
                  if (item.track.ensemble) {
                    title = item.track.ensemble + (title ? ' - ' + title : '');
                  }
                  if (!title) {
                    title = 'noname';
                  }

                  return audio.getClientHash(url).then(function(clientHash) {
                    url += '&clientHash=' + clientHash;

                    trackList.push({
                      url: url,
                      duration: item.track.duration || 0,
                      title: title,
                      filename: mono.fileName.modify(title) + '.mp3'
                    });
                  });
                }).catch(function(err) {
                  mono.debug('process item error', item, err);
                });
              });
            }
            promise.then(function() {
              onProgress(len - trackIdList.length, len);
              next();
            });
          });
        };
        next();

        return {
          abort: function() {
            abort = true;
          }
        }
      },

      getAudioListLinksPopup: function(trackIdList, title, cb) {
        var process;
        var popup = this.getPopup(title, 'audio', function onClose() {
          if (process) {
            process.abort();
          }
        });
        var _cb = function(links) {
          if (links.length === 0) {
            popup.onError(language.vkMp3LinksNotFound);
            return;
          }
          popup.onReady();

          cb(links);
        };

        popup.onPrepare(language.download + ' ...');

        process = this.getAudioLinksViaAPI(trackIdList, popup.onProgress, _cb);
      },

      getAudioLinks: function(container, title, cb) {
        var rowList = container.querySelectorAll(['.m_portal_track', '.m_c_tr', '.mus-tr_i']);
        var trackIdList = [];
        for (var i = 0, row; row = rowList[i]; i++) {
          var trackIdObj = audio.getTrackId(row);
          for (var trackId in trackIdObj) {
            trackIdList.push(trackId);
          }
        }
        this.getAudioListLinksPopup(trackIdList, title, cb);
      },

      downloadMP3Files: function() {
        var container = audio.getLayer() || document;
        var title = audio.getPlaylistName(container);
        audio.getAudioLinks(container, title, function(trackList) {
          SaveFrom_Utils.downloadList.showBeforeDownloadPopup(trackList, {
            type: 'audio',
            folderName: title
          });
        });
      },

      showListOfAudioFiles: function(showPlaylist) {
        var container = audio.getLayer() || document;
        var title = audio.getPlaylistName(container);
        audio.getAudioLinks(container, title, function(trackList) {
          if (trackList.length) {
            if (showPlaylist) {
              SaveFrom_Utils.playlist.popupPlaylist(trackList, title, true);
            } else {
              SaveFrom_Utils.playlist.popupFilelist(trackList);
            }
            return;
          }

          alert(language.vkMp3LinksNotFound);
        });
      },

      md5: function(str) {
        // http://kevin.vanzonneveld.net
        // +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
        // + namespaced by: Michael White (http://getsprink.com)
        // +    tweaked by: Jack
        // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
        // +      input by: Brett Zamir (http://brett-zamir.me)
        // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
        // -    depends on: utf8_encode
        // *     example 1: md5('Kevin van Zonneveld');
        // *     returns 1: '6e658d4bfcb59cc13f96c14450ac40b9'
        var xl;

        var rotateLeft = function(lValue, iShiftBits) {
          return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
        };

        var addUnsigned = function(lX, lY) {
          var lX4, lY4, lX8, lY8, lResult;
          lX8 = (lX & 0x80000000);
          lY8 = (lY & 0x80000000);
          lX4 = (lX & 0x40000000);
          lY4 = (lY & 0x40000000);
          lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
          if (lX4 & lY4) {
            return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
          }
          if (lX4 | lY4) {
            if (lResult & 0x40000000) {
              return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
            } else {
              return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
            }
          } else {
            return (lResult ^ lX8 ^ lY8);
          }
        };

        var _F = function(x, y, z) {
          return (x & y) | ((~x) & z);
        };
        var _G = function(x, y, z) {
          return (x & z) | (y & (~z));
        };
        var _H = function(x, y, z) {
          return (x ^ y ^ z);
        };
        var _I = function(x, y, z) {
          return (y ^ (x | (~z)));
        };

        var _FF = function(a, b, c, d, x, s, ac) {
          a = addUnsigned(a, addUnsigned(addUnsigned(_F(b, c, d), x), ac));
          return addUnsigned(rotateLeft(a, s), b);
        };

        var _GG = function(a, b, c, d, x, s, ac) {
          a = addUnsigned(a, addUnsigned(addUnsigned(_G(b, c, d), x), ac));
          return addUnsigned(rotateLeft(a, s), b);
        };

        var _HH = function(a, b, c, d, x, s, ac) {
          a = addUnsigned(a, addUnsigned(addUnsigned(_H(b, c, d), x), ac));
          return addUnsigned(rotateLeft(a, s), b);
        };

        var _II = function(a, b, c, d, x, s, ac) {
          a = addUnsigned(a, addUnsigned(addUnsigned(_I(b, c, d), x), ac));
          return addUnsigned(rotateLeft(a, s), b);
        };

        var convertToWordArray = function(str) {
          var lWordCount;
          var lMessageLength = str.length;
          var lNumberOfWords_temp1 = lMessageLength + 8;
          var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
          var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
          var lWordArray = new Array(lNumberOfWords - 1);
          var lBytePosition = 0;
          var lByteCount = 0;
          while (lByteCount < lMessageLength) {
            lWordCount = (lByteCount - (lByteCount % 4)) / 4;
            lBytePosition = (lByteCount % 4) * 8;
            lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount) << lBytePosition));
            lByteCount++;
          }
          lWordCount = (lByteCount - (lByteCount % 4)) / 4;
          lBytePosition = (lByteCount % 4) * 8;
          lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
          lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
          lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
          return lWordArray;
        };

        var wordToHex = function(lValue) {
          var wordToHexValue = "",
            wordToHexValue_temp = "",
            lByte, lCount;
          for (lCount = 0; lCount <= 3; lCount++) {
            lByte = (lValue >>> (lCount * 8)) & 255;
            wordToHexValue_temp = "0" + lByte.toString(16);
            wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length - 2, 2);
          }
          return wordToHexValue;
        };

        var x = [],
          k, AA, BB, CC, DD, a, b, c, d, S11 = 7,
          S12 = 12,
          S13 = 17,
          S14 = 22,
          S21 = 5,
          S22 = 9,
          S23 = 14,
          S24 = 20,
          S31 = 4,
          S32 = 11,
          S33 = 16,
          S34 = 23,
          S41 = 6,
          S42 = 10,
          S43 = 15,
          S44 = 21;

        //str = this.utf8_encode(str);
        x = convertToWordArray(str);
        a = 0x67452301;
        b = 0xEFCDAB89;
        c = 0x98BADCFE;
        d = 0x10325476;

        xl = x.length;
        for (k = 0; k < xl; k += 16) {
          AA = a;
          BB = b;
          CC = c;
          DD = d;
          a = _FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
          d = _FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
          c = _FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
          b = _FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
          a = _FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
          d = _FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
          c = _FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
          b = _FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
          a = _FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
          d = _FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
          c = _FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
          b = _FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
          a = _FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
          d = _FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
          c = _FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
          b = _FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
          a = _GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
          d = _GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
          c = _GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
          b = _GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
          a = _GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
          d = _GG(d, a, b, c, x[k + 10], S22, 0x2441453);
          c = _GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
          b = _GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
          a = _GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
          d = _GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
          c = _GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
          b = _GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
          a = _GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
          d = _GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
          c = _GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
          b = _GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
          a = _HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
          d = _HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
          c = _HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
          b = _HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
          a = _HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
          d = _HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
          c = _HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
          b = _HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
          a = _HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
          d = _HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
          c = _HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
          b = _HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
          a = _HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
          d = _HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
          c = _HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
          b = _HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
          a = _II(a, b, c, d, x[k + 0], S41, 0xF4292244);
          d = _II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
          c = _II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
          b = _II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
          a = _II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
          d = _II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
          c = _II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
          b = _II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
          a = _II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
          d = _II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
          c = _II(c, d, a, b, x[k + 6], S43, 0xA3014314);
          b = _II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
          a = _II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
          d = _II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
          c = _II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
          b = _II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
          a = addUnsigned(a, AA);
          b = addUnsigned(b, BB);
          c = addUnsigned(c, CC);
          d = addUnsigned(d, DD);
        }

        var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);

        return temp.toLowerCase();
      }
    };

    //  /AUDIO
    ///////////////////////////////////////////////////////////////////



    ///////////////////////////////////////////////////////////////////
    //  VIDEO

    var video = {
      requestMobileToken: function(response, cb) {
        var host = null;
        response.links.some(function(item) {
          var hostname = item.url.match(/\/\/([^/]+)/);
          hostname = hostname && hostname[1];
          if (hostname) {
            host = hostname;
            return true;
          }
        });
        SaveFrom_Utils.bridge({
          timeout: 3000,
          args: [host],
          func: function(host, cb) {
            var cookie = document.cookie;
            var vdsig = cookie && cookie.match(/vdsig=([^;]+);/);
            vdsig = vdsig && vdsig[1];
            if (vdsig) {
              return cb({
                vtkn: vdsig
              });
            }

            host = host || 'vd4.mycdn.me';
            var xhr = new XMLHttpRequest();
            xhr.open('POST', location.protocol + '//' + host + '/usr_login', true);
            xhr.withCredentials = true;
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.onreadystatechange = function() {
              if (xhr.readyState === 4 && xhr.status === 200) {
                var data = null;
                try {
                  data = JSON.parse(xhr.responseText);
                } catch (e) {}

                return cb(data);
              }
            };
            xhr.send();
          },
          cb: function(data) {
            if (!data || !data.vtkn) {
              return cb();
            }

            if (data.ttl) {
              data.expire = Date.now() + data.ttl * 1000;
              odnoklassniki.videoToken = data;
            }

            response.vtkn = data.vtkn;

            cb(response);
          }
        });
      },
      getMobileToken: function(response, cb) {
        if (response.vtkn) {
          return cb(response);
        }

        var videoToken = odnoklassniki.videoToken;
        if (videoToken && videoToken.expire > Date.now()) {
          response.vtkn = videoToken.vtkn;
          return cb(response);
        }

        return video.requestMobileToken(response, cb);
      },
      wrapMobileLinks: function(response, cb) {
        video.getMobileToken(response, function(response) {
          if (!response || !response.vtkn) {
            return cb();
          }

          response.action = 'getOkViaMobileWrapped';
          response.links.forEach(function(link) {
            var sep = !/\?/.test(link.url) ? '?' : '&';
            link.url += sep + 'vdsig=' + response.vtkn;
          });
          cb(response);
        });
      },
      prepareResponse: function(response, cb) {
        var abort = function() {
          cb(language.noLinksFound);
        };
        if (!response || !response.links) {
          return abort();
        }

        if (!preference.showUmmyItem && response.action === 'getRutubeLinks') {
          return abort();
        }

        if (response.action === 'getOkViaMobile') {
          return video.wrapMobileLinks(response, function(response) {
            if (!response) {
              return abort();
            }

            video.prepareResponse(response, cb);
          });
        }

        var prepareLinkType = null;
        if (response.action === 'getYoutubeLinks') {
          prepareLinkType = 'youtube';
        } else
        if (response.action === 'getVimeoLinks') {
          prepareLinkType = 'vimeo';
        } else
        if (response.action === 'getDailymotionLinks') {
          prepareLinkType = 'dailymotion';
        } else
        if (response.action === 'getRutubeLinks') {
          prepareLinkType = 'rutube';
        }

        var menuLinks = null;

        if (prepareLinkType) {
          menuLinks = SaveFrom_Utils.popupMenu.prepareLinks[prepareLinkType](response.links, response.title);
        } else {
          menuLinks = videoFeed.prepareLinks(response.links, response.title);
        }

        return cb(menuLinks);
      },

      matchOpenGraph: function(metadata) {
        if (!metadata || !metadata.movie || !metadata.movie.contentId) {
          return;
        }

        var url = metadata.movie.contentId;

        if (url.indexOf('rutube.') !== -1 && preference.showUmmyItem) {
          return {
            action: 'getRutubeLinks',
            links: [url]
          }
        }

        if (url.indexOf('pladform') !== -1) {
          var urlArgs = mono.parseUrl(url);
          return {
            action: 'getPladformVideo',
            extVideoId: {
              playerId: urlArgs.pl,
              videoId: urlArgs.videoid
            }
          };
        }

        var request = SaveFrom_Utils.embedDownloader.checkUrl(url);
        if (request) {
          return request;
        }

        var poster = metadata.movie.poster;
        if (typeof poster === 'string') {
          var redirectUrl = mono.parseUrl(poster).url || poster;
          var ytId = redirectUrl.match(/ytimg\.com\/vi\/([^\/]+)\//);
          ytId = ytId && ytId[1];
          if (ytId) {
            return {
              action: 'getYoutubeLinks',
              extVideoId: ytId
            }
          }
        }
      },

      switchMetadataProvider: function(metadata) {
        "use strict";
        if (!metadata || !metadata.provider || !metadata.movie) {
          return;
        }

        switch (metadata.provider) {
          case 'USER_YOUTUBE':
            if (metadata.movie.contentId) {
              return {
                request: {
                  action: 'getYoutubeLinks',
                  extVideoId: metadata.movie.contentId
                }
              };
            }
            break;
          case 'OPEN_GRAPH':
            var request = this.matchOpenGraph(metadata);
            if (request) {
              return {
                request: request
              }
            }
            break;
          case 'LIVE_TV_APP':
          case 'LIVE_TV_ODKL':
          case 'UPLOADED_ODKL':
          case 'UPLOADED':
          case 'PARTNER':
          case 'YKL':
            if (metadata.videos && metadata.movie.title) {
              return {
                request: {
                  action: 'wrapMobileLinks',
                  title: metadata.movie.title,
                  links: metadata.videos
                }
              };
            }

            /* via mobile
             return {
             request: {
             action: 'okDirectOrMobile',
             mvId: metadata.movie.id,
             metadata: metadata,
             title: metadata.movie.title,
             links: null
             }
             };
             */

            /* odirect only
             if (metadata.videos && metadata.movie.title) {
             return {
             links: videoFeed.prepareLinks(metadata.videos, metadata.movie.title)
             };
             }*/
            break;
        }
      },

      getPlayerMetadata: function(movieId, sid, cb, withSid) {
        var params = {
          cmd: 'videoPlayerMetadata',
          mid: movieId,
          rnd: Date.now()
        };

        if (withSid) {
          params.mtId = sid;
        }

        mono.request({
          method: 'POST',
          url: location.protocol + '//' + location.host + '/dk?' + mono.param(params),
          json: true,
          localXHR: true
        }, function(err, resp, metadata) {
          if (err) {
            if (!withSid && sid) {
              video.getPlayerMetadata(movieId, sid, cb, 1);
              return;
            }

            return cb();
          }

          return cb(metadata);
        });
      },

      getEmbed: function(contentId, cb) {
        var params = mono.parseUrl(contentId);
        if (!params.id || !params.sig) {
          return cb();
        }

        var url = 'http://cdn-ok.com/video/get/?' + mono.param({
          id: params.id,
          format: 1,
          sig: params.sig,
          sig2: 'oldRotator'
        });

        mono.sendMessage({
          action: 'getData',
          url: url
        }, function(data) {
          if (!data) {
            return cb();
          }

          var jsonList = mono.findJson(data, [/"sourceType":/, /"sourceId":/]);

          var isFound = jsonList.some(function(json) {
            if (json.sourceType === 'youtube' && json.sourceId) {
              cb({
                request: {
                  action: 'getYoutubeLinks',
                  extVideoId: json.sourceId
                }
              });
              return true;
            }
          });

          if (!isFound) {
            return cb();
          }
        });
      },

      readMetadata: function(metadata, cb, skipPlayerMeta) {
        if (metadata.movie) {
          if (/cdn-ok\.com\/embed/.test(metadata.movie.contentId)) {
            return this.getEmbed(metadata.movie.contentId, function(info) {
              if (!info || !info.request) {
                return cb();
              }

              mono.sendMessage(info.request, function(response) {
                video.prepareResponse(response, cb);
              });
            });
          }
        }

        if (!skipPlayerMeta && metadata.movie && metadata.movie.movieId) {
          var sid = metadata.movie.link && mono.parseUrl(metadata.movie.link, {
            sep: '&amp;'
          })['st.vpl.sid'];
          return this.getPlayerMetadata(metadata.movie.movieId, sid, function(_metadata) {
            video.readMetadata(_metadata || metadata, cb, 1);
          });
        }

        var info = this.switchMetadataProvider(metadata);
        if (!info) {
          return cb();
        }

        if (info.links) {
          return cb(info.links);
        }

        if (info.request) {
          if (info.request.action === 'getRutubeLinks') {
            video.prepareResponse(info.request, cb);
          } else
          if (info.request.action === 'wrapMobileLinks') {
            video.wrapMobileLinks(info.request, function(response) {
              video.prepareResponse(response, function(menuLinks) {
                cb(menuLinks, 1);
              });
            });
          } else {
            mono.sendMessage(info.request, function(response) {
              video.prepareResponse(response, cb);
            });
          }
        } else {
          cb();
        }
      },

      loadLinks: function(info, menu) {
        var linkCache = odnoklassniki.linkCache;
        var cacheKey = JSON.stringify(info);
        var cache = linkCache[cacheKey];
        if (cache) {
          return menu.update(cache);
        }

        var onGetMeta = function(metadata, skipPlayerMeta) {
          var onFail = function() {
            menu.update(language.noLinksFound);
          };

          if (!metadata) {
            return onFail();
          }

          video.readMetadata(metadata, function(menuLinks, noCache) {
            if (!menuLinks) {
              return onFail();
            }

            if (Array.isArray(menuLinks) && !menuLinks.length) {
              noCache = 1;
            }

            if (!noCache) {
              linkCache[cacheKey] = menuLinks;
            }

            menu.update(menuLinks);
          }, skipPlayerMeta);
        };

        if (info.metadata) {
          onGetMeta(info.metadata);
        } else
        if (info.request) {
          if (info.request.action === 'getOkMetadata') {
            mono.sendMessage(info.request, onGetMeta);
          } else
          if (info.request.action === 'getPlayerMetadata') {
            this.getPlayerMetadata(info.request.extVideoId, info.request.sid, function(metadata) {
              onGetMeta(metadata, 1);
            });
          } else
          if (info.request.action === 'getRutubeLinks') {
            video.prepareResponse(info.request, function(menuLinks) {
              menu.update(menuLinks);
            });
          } else {
            mono.sendMessage(info.request, function(response) {
              video.prepareResponse(response, function(menuLinks) {
                menu.update(menuLinks);
              });
            });
          }
        } else {
          menu.update(language.noLinksFound);
        }
      },

      appendLinkUnderVideo: function(container, info) {
        "use strict";
        var insertContainer = container.querySelector('.vp-layer-info_cnt');
        if (!insertContainer) {
          return;
        }

        var exButton = insertContainer.querySelector('.' + downloadLinkClassName);

        var button = mono.create('span', {
          className: downloadLinkClassName,
          style: {
            marginLeft: '12px'
          },
          on: [
            ['click', function(e) {
              e.stopPropagation();
            }],
            ['mousedown', function(e) {
              e.stopPropagation();
            }],
            ['keydown', function(e) {
              e.stopPropagation();
            }]
          ],
          append: [
            mono.create('a', {
              href: '#',
              text: language.download,
              on: ['click', function(e) {
                e.preventDefault();

                mono.onRemoveEvent(button, odnoklassniki.hideMenu);

                if (odnoklassniki.contextMenu && odnoklassniki.contextMenu.isShow) {
                  if (odnoklassniki.contextMenu.button !== this) {
                    odnoklassniki.hideMenu();
                  } else {
                    odnoklassniki.hideMenu();
                    return;
                  }
                }

                var menu = odnoklassniki.contextMenu = SaveFrom_Utils.popupMenu.quickInsert(this, language.download + '...', 'sf-single-video-menu', {
                  parent: container
                });

                video.loadLinks(info, menu);
              }]
            })
          ]
        });

        if (exButton && exButton.parentNode) {
          exButton.parentNode.replaceChild(button, exButton);
          exButton = null;
        } else {
          insertContainer.appendChild(button);
        }
      },

      getPlayerOptions: function(node) {
        var optionsNode = mono.getParent(node, '[data-player-element-id][data-options]');

        var options = optionsNode && optionsNode.dataset.options;

        if (!options) {
          return;
        }

        try {
          options = JSON.parse(options);
        } catch (e) {}

        var flashvars = options.flashvars;

        if (!flashvars) {
          return;
        }

        if (flashvars.metadata) {
          var metadata = null;

          try {
            metadata = JSON.parse(flashvars.metadata);
          } catch (e) {}

          if (metadata) {
            return {
              metadata: metadata
            }
          }
        }

        if (flashvars.metadataUrl) {
          return {
            request: {
              action: 'getOkMetadata',
              url: decodeURIComponent(flashvars.metadataUrl)
            }
          }
        }

        var url = options.url;
        if (url) {
          var request = SaveFrom_Utils.embedDownloader.checkUrl(url);
          if (request) {
            return {
              request: request
            }
          }

          if (url.indexOf('rutube.') !== -1) {
            return {
              request: {
                action: 'getRutubeLinks',
                links: [url]
              }
            }
          }
        }
      },

      catchPopup: function() {
        "use strict";
        var videoContainer = null;
        this.lastWaitEl && this.lastWaitEl.abort();

        this.lastWaitEl = this.waitEl(function() {
          videoContainer = document.querySelector('.vp_video .vid-card_cnt');
          if (!videoContainer) {
            return;
          }

          return videoContainer;
        }, function() {
          var parent = mono.getParent(videoContainer, '.vp_video');
          if (!parent) {
            return;
          }

          var info = video.getPlayerOptions(videoContainer);
          if (info) {
            video.appendLinkUnderVideo(parent.parentNode, info);
          }
        });
      },

      rmBtn: function() {
        var dlBtn = document.querySelectorAll('.' + downloadLinkClassName);
        for (var i = 0, item; item = dlBtn[i]; i++) {
          item.parentNode.removeChild(item);
        }
      },

      lastWaitEl: null,
      waitEl: function(func, cb, options) {
        var out;
        var capsule = mono.extend({
          abort: function() {
            clearInterval(capsule.timeout);
            capsule.isAborted = true;
          }
        }, {
          delay: 500,
          repeat: 12,
          isAborted: false,
          timeout: null
        }, options);

        if (out = func()) {
          cb(out);
          return capsule;
        }

        (function wait() {
          capsule.repeat--;
          capsule.timeout = setTimeout(function() {
            if (capsule.isAborted) {
              return;
            }

            if (out = func()) {
              return cb(out);
            }

            if (!capsule.isAborted && capsule.repeat) {
              wait();
            }
          }, capsule.delay);
        })();

        return capsule;
      }
    };

    var videoFeed = {
      btnClassName: 'sf-feed-dl-btn',
      style: undefined,
      thumbClassName: 'vid-card_img',
      prepareLinks: function(links, title) {
        if (!links || !links.length) {
          return language.noLinksFound;
        }

        if (typeof links === 'string') {
          return links;
        }

        title = title || '';

        var menuLinks = [];
        var popupLink;
        var quality;
        var format;
        var url;
        for (var i = 0, len = links.length; i < len; i++) {
          var link = links[i];
          if (typeof(link) === 'object' && link.url) {
            url = link.url;
            var ext = link.ext;

            if (!ext) {
              ext = 'MP4';
              if (link.url.indexOf('.mp4') !== -1) {
                ext = 'MP4';
              }
              if (url.indexOf('.flv') !== -1) {
                ext = 'FLV';
              }
              if (link.url.indexOf('.mov') !== -1) {
                ext = 'MOV';
              }
              if (link.url.indexOf('.mpg') !== -1) {
                ext = 'MPG';
              }
            }

            ext = ext.toLowerCase();
            format = ext.toUpperCase();
            quality = link.subname || link.quality || link.name || ext;
          } else {
            url = link;
            ext = 'MP4';
            if (url.indexOf('.mp4') !== -1) {
              ext = 'MP4';
            }
            if (url.indexOf('.flv') !== -1) {
              ext = 'FLV';
            }
            if (url.indexOf('.mov') !== -1) {
              ext = 'MOV';
            }
            if (url.indexOf('.mpg') !== -1) {
              ext = 'MPG';
            }

            ext = ext.toLowerCase();
            format = ext.toUpperCase();

            quality = ext;
            var qualityMath = SaveFrom_Utils.getMatchFirst(links[i], /\.(\d+)\.mp4/i);
            if (qualityMath) {
              quality = qualityMath;
            }
          }

          var trueName = [144, 240, 360, 480, 720, 1080, 1440, '4K'];
          var origName = ['mobile', 'lowest', 'low', 'sd', 'hd', 'full', 'quad', 'ultra'];
          var pos = origName.indexOf(quality);
          if (pos !== -1) {
            quality = trueName[pos];
          }

          popupLink = {
            href: url,
            title: link.title ? link.title : title,
            ext: ext,
            format: format,
            quality: quality,
            forceDownload: true
          };
          menuLinks.push(popupLink);
        }
        return menuLinks;
      },
      getPosterData: function(node) {
        var infoNode = mono.getParent(node, '[hrefattrs]');

        var info = infoNode && infoNode.getAttribute('hrefattrs');

        if (!info) {
          return;
        }

        var params = mono.parseUrl(info, {
          params: true
        });

        var sid = params['st.vpl.sid'];
        var vid = params['st.vpl.id'];
        if (!vid) {
          var vidNode = mono.getParent(node, '[data-id]');
          vid = vidNode && vidNode.dataset.id;

          if (vid && vid[0] === 'c') {
            return;
          }
        }

        if (vid && vid.substr(0, 3) === 'OK_') {
          vid = SaveFrom_Utils.getMatchFirst(vid, /OK_\d+_(\d+)/);
        }

        if (!vid) {
          return;
        }

        return {
          request: {
            sid: sid,
            action: 'getPlayerMetadata',
            extVideoId: vid
          }
        };
      },
      onBtnClick: function(e) {
        e.preventDefault();
        e.stopPropagation();

        var info = JSON.parse(this.dataset.sfContext);
        mono.onRemoveEvent(this, odnoklassniki.hideMenu);

        if (odnoklassniki.contextMenu && odnoklassniki.contextMenu.isShow) {
          if (odnoklassniki.contextMenu.button !== this) {
            odnoklassniki.hideMenu();
          } else {
            odnoklassniki.hideMenu();
            return;
          }
        }

        // post in popup
        var menuParent = document.querySelector('#mtLayer.__active #mtLayerMain > div');
        if (!menuParent) {
          // video gaallery
          menuParent = document.getElementById('vv_content');
        }
        if (!menuParent) {
          // pm msgs
          menuParent = document.getElementById('__messagesList__');
          if (menuParent && !menuParent.offsetParent) {
            menuParent = null;
          }
        }
        if (!menuParent && mono.matches(this, '#mainContent ' + this.tagName)) {
          menuParent = mono.getParent(this, '#mainContent');
        }
        var menu = odnoklassniki.contextMenu = SaveFrom_Utils.popupMenu.quickInsert(this, language.download + ' ...', 'sf-popupMenu', {
          parent: menuParent || undefined
        });

        video.loadLinks(info, menu);
      },
      onImgOver: function(e) {
        var _this = this;
        var isChat = mono.matches(this, '.mdialog_chat_window .d_comment_text_w ' + this.tagName);

        var container = null;
        if (isChat) {
          container = mono.getParentByClass(this, 'd_comment_text_w');
        } else
        if (mono.matches(this, '.video-card > .video-card_img-w ' + this.tagName)) {
          container = mono.getParentByClass(this, 'video-card_img-w');
        } else
        if (this.classList.contains('vid-card_cnt')) {
          container = this;
        } else
        if (mono.matches(this, '.vid-card_cnt ' + this.tagName)) {
          container = mono.getParentByClass(this, 'vid-card_cnt');
        }

        if (!container) {
          return;
        }

        if (container.getElementsByClassName(videoFeed.btnClassName).length) {
          return;
        }

        var isLive = !!container.querySelector('.vid-card_live.__active');
        if (isLive) {
          return;
        }

        var isVideoVitrina = mono.matches(this, '.vid-card_img__link ' + this.tagName);

        var btnData = video.getPlayerOptions(this);
        if (!btnData) {
          btnData = videoFeed.getPosterData(this);
        }
        if (!btnData) {
          return;
        }

        btnData.isChat = isChat;

        var customStyle = {};

        if (isChat) {
          mono.extend(customStyle, {
            left: '15px',
            top: '15px'
          });
        }

        if (isVideoVitrina) {
          mono.extend(customStyle, {
            backgroundColor: '#454648',
            borderColor: 'rgb(53, 53, 53)'
          });
        }

        var btn = mono.create('i', {
          class: [videoFeed.btnClassName, 'sf-video-feed-bind-on-insert'],
          style: customStyle,
          data: {
            sfContext: JSON.stringify(btnData)
          },
          title: language.download
        });

        btn.appendChild(mono.create(SaveFrom_Utils.svg.getSvg('download'), {
          style: {
            width: '12px',
            height: '12px',
            margin: '4px'
          }
        }));

        container.appendChild(btn);
      },
      injectStyle: function() {
        if (this.style) {
          if (!this.style.parentNode) {
            document.head.appendChild(this.style);
          }
          return;
        }

        this.style = mono.create('style', {
          text: mono.style2Text({
            'div > .sf-feed-dl-btn': {
              display: 'none',
              border: '1px solid #F8F8F8',
              width: '20px',
              height: '20px',
              padding: 0,
              position: 'absolute',
              top: 0,
              left: 0,
              zIndex: 1,
              cursor: 'pointer',
              backgroundColor: '#F8F8F8'
            },
            'div > .sf-feed-dl-btn svg path': {
              fill: '#eb722e'
            },
            'div > .sf-feed-dl-btn:hover svg path': {
              fill: '#00B75A'
            },
            'div > .sf-feed-dl-btn:active': {
              outline: 0,
              boxShadow: 'inset 0 3px 5px rgba(0, 0, 0, 0.125)'
            },
            'div:hover > .sf-feed-dl-btn': {
              display: 'block'
            }
          })
        });

        document.head.appendChild(this.style);
      },
      disable: function() {
        if (this.style) {
          this.style.parentNode && this.style.parentNode.removeChild(this.style);
        }
      },
      rmBtn: function() {
        var btnList = document.querySelectorAll('.sf-feed-dl-btn');
        for (var i = 0, item; item = btnList[i]; i++) {
          item.parentNode.removeChild(item);
        }
        var dataAttr = mono.dataAttr2Selector('sfSkip2');
        var dataAttrList = document.querySelectorAll('[' + dataAttr + ']');
        for (i = 0, item; item = dataAttrList[i]; i++) {
          item.removeAttribute(dataAttr);
        }
      }
    };

    //  /VIDEO
    ///////////////////////////////////////////////////////////////////


    //  PHOTO
    ///////////////////////////////////////////////////////////////////

    var photo = {
      style: null,
      rmCurrentPhotoBtn: function(insertContainer) {
        var exBtn = undefined;
        var imgList = document.querySelectorAll('.sf-dl-current-photo-btn');
        for (var i = 0, imgItem; imgItem = imgList[i]; i++) {
          if (!insertContainer || !insertContainer.contains(imgItem)) {
            imgItem.parentNode.removeChild(imgItem);
          } else {
            exBtn = imgItem;
          }
        }
        return exBtn;
      },
      addDlCurrentPhotoBtn: function(container) {
        var exBtn = this.rmCurrentPhotoBtn(container);
        if (exBtn) {
          return;
        }

        var _this = odnoklassniki;

        container.appendChild(mono.create('a', {
          class: 'sf-dl-current-photo-btn',
          href: '#',
          title: language.download,
          on: ['click', function(e) {
            e.stopPropagation();
            e.preventDefault();

            if (_this.contextMenu && _this.contextMenu.isShow && _this.contextMenu.button === this) {
              if (_this.contextMenu.button !== this) {
                _this.hideMenu();
              } else {
                _this.hideMenu();
                return;
              }
            }

            var onKeyDown = function(e) {
              if (e.keyCode === 18 || e.keyCode === 17) return;
              menu.hide();
              document.removeEventListener('keydown', onKeyDown);
            };

            var menu = _this.contextMenu = SaveFrom_Utils.popupMenu.quickInsert(this, language.download + ' ...', "photoDlMenu", {
              parent: container,
              onShow: function() {
                document.addEventListener('keydown', onKeyDown);
              },
              onHide: function() {
                document.removeEventListener('keydown', onKeyDown);
              }
            });

            var linkList = [];

            var img = container.querySelector('img.photo-layer_img');
            if (img) {
              var url = img.dataset.fsSrc || img.dataset.nfsSrc || img.src;
              if (url) {
                linkList.push({
                  href: url,
                  title: 'photo_' + parseInt(Date.now() / 1000),
                  quality: language.download,
                  format: ' ',
                  ext: 'jpg',
                  forceDownload: true,
                  isBlank: true,
                  func: function() {
                    menu.hide();
                  }
                });
              }
            }

            if (!img) {
              img = container.querySelector('div.gif[data-gifsrc]');
            }

            if (img) {
              var map = {
                webmsrc: 'webm',
                mp4src: 'mp4',
                gifsrc: 'gif'
              };
              Object.keys(map).forEach(function(type) {
                var url = img.dataset[type];
                if (!url) {
                  return;
                }

                var ext = map[type];

                linkList.push({
                  href: url,
                  title: 'gif_' + parseInt(Date.now() / 1000),
                  quality: language.download,
                  format: ext.toUpperCase(),
                  ext: ext,
                  forceDownload: true,
                  isBlank: true,
                  func: function() {
                    menu.hide();
                  }
                });
              });
            }

            if (linkList.length === 0) {
              menu.update(language.noLinksFound);
              return;
            }

            menu.update(linkList);
          }],
          append: [
            mono.create(SaveFrom_Utils.svg.getSvg('download'), {
              style: {
                width: '12px',
                height: '12px',
                margin: '4px'
              }
            })
          ]
        }));
      },
      injectStyle: function() {
        if (photo.style) {
          if (!photo.style.parentNode) {
            document.head.appendChild(photo.style);
          }
          return;
        }

        photo.style = mono.create('style', {
          text: mono.style2Text({
            'div > .sf-dl-current-photo-btn': {
              display: 'none',
              border: '1px solid #F8F8F8',
              width: '20px',
              height: '20px',
              padding: 0,
              position: 'absolute',
              backgroundColor: '#F8F8F8',
              top: '73px',
              left: '90px',
              zIndex: 100,
              cursor: 'pointer'
            },
            'div > .sf-dl-current-photo-btn svg path': {
              fill: '#eb722e'
            },
            'div > .sf-dl-current-photo-btn:hover svg path': {
              fill: '#00B75A'
            },
            'div > .sf-dl-current-photo-btn:active': {
              outline: 0,
              boxShadow: 'inset 0 3px 5px rgba(0, 0, 0, 0.125)'
            },
            'div:hover > .sf-dl-current-photo-btn': {
              display: 'block'
            }
          })
        });

        document.head.appendChild(photo.style);
      },
      addCurrentDlBtn: function(container) {
        if (container.dataset.sfSkip2 === '1') {
          return;
        }
        container.dataset.sfSkip2 = '1';

        var img = container.querySelector('img.photo-layer_img');
        if (img) {
          var url = img.dataset.fsSrc || img.dataset.nfsSrc || img.src;
          if (!url) {
            img = null;
          }
        }

        if (!img) {
          img = container.querySelector('div.gif[data-gifsrc]');
        }

        if (!img) {
          return;
        }

        this.addDlCurrentPhotoBtn(container);
      }
    };

    //  /PHOTO
    //////////////////////////////////////////////////////////////////
  }, null, function syncIsActive() {
    "use strict";
    if (mono.isSafari || mono.isGM) {
      var list = [
        '*://*.ok.ru/*',
        '*://*.odnoklassniki.ru/*'
      ];

      var reStr = list.map(function(pattern) {
        return mono.urlPatternToStrRe(pattern);
      }).join('|');
      var re = new RegExp(reStr);

      if (!re.test(location.protocol + '//' + location.hostname)) {
        return false;
      }
    }

    if (mono.isIframe()) {
      return false;
    }

    return true;
  });
  (typeof mono === 'undefined') && (mono = {
    loadModule: function() {
      this.loadModuleStack.push(arguments);
    },
    loadModuleStack: []
  });

  mono.loadModule('mailru', function(moduleName, initData) {
    "use strict";

    var language = initData.getLanguage;
    var preference = initData.getPreference;
    var moduleState = preference.moduleMailru ? 1 : 0;

    var allowDownloadMode = mono.isChrome || mono.isFirefox || (mono.isGM && mono.isTM);

    var Promise = mono.Promise;

    mono.onMessage.addListener(function(message, cb) {
      if (message.action === 'getModuleInfo') {
        if (message.url !== location.href) return;
        return cb({
          state: moduleState,
          moduleName: moduleName
        });
      }
      if (message.action === 'changeState') {
        if (moduleName !== message.moduleName) {
          return;
        }
        return mailru.changeState(message.state);
      }
      if (!moduleState) {
        return;
      }
      if (message.action === 'downloadMP3Files') {
        if (allowDownloadMode) {
          audio.downloadMP3Files();
        } else {
          audio.showListOfAudioFiles(false);
        }
      }
      if (message.action === 'downloadPlaylist') {
        audio.showListOfAudioFiles(true);
      }
    });

    if (moduleState) {
      mono.asyncCall(function() {
        mailru.run();
      });
    }

    var mailru = {
      contextMenu: null,
      run: function() {
        moduleState = 1;

        audio.injectStyle();
        if (SaveFrom_Utils.mutationWatcher.isAvailable()) {
          this.mutationMode.enable();
        }
      },
      changeState: function(state) {
        moduleState = state;
        audio.rmBtn();
        video.rmBtn();
        this.mutationMode.stop();
        this.hideMenu();
        if (state) {
          this.run();
        }
      },
      hideMenu: function() {
        if (mailru.contextMenu) {
          mailru.contextMenu.hide();
          mailru.contextMenu = null;
        }
      },
      mutationMode: {
        observer: null,
        stop: function() {
          if (this.observer) {
            this.observer.stop();
          }

          ['sfSkip'].forEach(function(attr) {
            var dataAttr = mono.dataAttr2Selector(attr);
            var dataAttrList = document.querySelectorAll('[' + dataAttr + ']');
            for (var i = 0, item; item = dataAttrList[i]; i++) {
              item.removeAttribute(dataAttr);
            }
          });
        },
        wrapAudioOnMouseOver: function() {
          if (!moduleState) {
            return;
          }

          if (this.dataset.sfSkip > 0) {
            return;
          }
          this.dataset.sfSkip = '1';

          var context = JSON.parse(this.dataset.sfContext);
          audio.onTrackOver(this, context.type);
        },
        enable: function() {
          if (this.observer) {
            return this.observer.start();
          }

          this.observer = SaveFrom_Utils.mutationWatcher.run({
            callback: function(summaryList) {
              var summary, n, i, node, context;

              summary = summaryList[0];
              for (n = 0; node = summary.added[n]; n++) {
                context = {};
                context.type = 0;
                node.dataset.sfContext = JSON.stringify(context);
                mono.one(node, 'mouseenter', mailru.mutationMode.wrapAudioOnMouseOver);
              }

              summary = summaryList[1];
              for (n = 0; node = summary.added[n]; n++) {
                context = {};
                context.type = 1;
                node.dataset.sfContext = JSON.stringify(context);
                mono.one(node, 'mouseenter', mailru.mutationMode.wrapAudioOnMouseOver);
              }

              var videoInfo, parent, info;

              for (i = 2; i < 4; i++) {
                summary = summaryList[i];
                for (n = 0; node = summary.added[n]; n++) {
                  if (node.dataset.sfSkip > 0) {
                    continue;
                  }
                  node.dataset.sfSkip = '1';

                  videoInfo = video.getVideoId(node);
                  if (!videoInfo) {
                    continue;
                  }

                  parent = mono.getParentByClass(node, 'b-video__left');
                  if (!parent) {
                    continue;
                  }

                  info = parent.querySelector('.b-video__info-time');
                  if (!info) {
                    continue;
                  }

                  video.insertBtnInPopup(videoInfo, info);
                }
              }

              for (i = 4; i < 6; i++) {
                summary = summaryList[i];
                for (n = 0; node = summary.added[n]; n++) {
                  if (node.dataset.sfSkip > 0) {
                    continue;
                  }
                  node.dataset.sfSkip = '1';

                  videoInfo = video.getVideoId(node);
                  if (!videoInfo) {
                    continue;
                  }

                  parent = mono.getParentByClass(node, 'sp-video__item-page');
                  if (!parent) {
                    continue;
                  }

                  info = parent.querySelector('.sp-video__item-page__info__additional');
                  if (!info) {
                    continue;
                  }

                  video.insertBtnInPage(videoInfo, info, 1);
                }
              }

              for (i = 6; i < 8; i++) {
                summary = summaryList[i];
                for (n = 0; node = summary.added[n]; n++) {
                  if (node.dataset.sfSkip > 0) {
                    continue;
                  }
                  node.dataset.sfSkip = '1';

                  parent = mono.getParentByClass(node, 'sp-video__item-page-new__video-content');
                  info = parent && parent.querySelector('.sp-video__item-page-new__actions');
                  videoInfo = parent && video.getVideoContentVideoId(parent);
                  if (!info || !videoInfo) {
                    continue;
                  }

                  video.insertBtnInPage(videoInfo, info, 2);
                }
              }

              summary = summaryList[0];
              for (n = 0; node = summary.removed[n]; n++) {
                mono.onRemoveListener(node);
              }
            },
            queries: [{
                css: '.jp__track',
                is: 'added'
              },
              {
                css: '.song-item',
                is: 'added'
              },
              {
                css: '.b-video__left .b-video__container object',
                is: 'added'
              },
              {
                css: '.b-video__left .b-video__container video',
                is: 'added'
              },
              {
                css: '.sp-video__item-page .sp-video__item-page__video-wrapper object',
                is: 'added'
              },
              {
                css: '.sp-video__item-page .sp-video__item-page__video-wrapper video',
                is: 'added'
              },
              {
                css: '.sp-video__item-page-new .sp-video__item-page-new__video-content video',
                is: 'added'
              },
              {
                css: '.sp-video__item-page-new .sp-video__item-page-new__video-content object',
                is: 'added'
              },
              {
                css: '.' + mono.onRemoveClassName,
                is: 'removed'
              }
            ]
          });
        }
      }
    };

    var tooltip = {
      tooltip: undefined,
      updatePos: function(button, options) {
        var btnPosition = SaveFrom_Utils.getPosition(button);
        var size = SaveFrom_Utils.getSize(this.tooltip);

        this.tooltip.style.top = (btnPosition.top + options.top - size.height) + 'px';

        var left = btnPosition.left + parseInt(options.width / 2) - parseInt(size.width / 2);
        var pageWidth = document.body.clientWidth + document.body.scrollLeft;
        if (pageWidth < left + size.width) {
          left = pageWidth - size.width;
        }
        this.tooltip.style.left = left + 'px';
      },
      show: function(button, options) {
        var _this = this;
        if (this.tooltip !== undefined) {
          this.hide();
        } else {
          this.tooltip = mono.create('div', {
            class: 'sf-tooltip',
            style: mono.extend({
              position: 'absolute',
              display: 'none',
              zIndex: 9999,
              opacity: 0,
              transition: 'opacity 0.2s',
              whiteSpace: 'nowrap',
              fontSize: '12px',
              color: '#111',
              fontFamily: 'arial, verdana, sans-serif, Lucida Sans'
            }, options.style),
            on: ['mouseenter', function(e) {
              _this.hide();
            }]
          });
          document.body.appendChild(this.tooltip);
        }
        this.tooltip.style.display = 'block';

        setTimeout(function() {
          _this.updatePos(button, options);
          _this.tooltip.style.opacity = 1;
        });

        return this.tooltip;
      },
      hide: function() {
        this.tooltip.style.opacity = 0;
        this.tooltip.style.display = 'none';
      }
    };

    var getFolderName = function() {
      var folderName = document.title;
      var sep = folderName.indexOf('-');
      if (sep !== -1) {
        folderName = folderName.substr(0, sep - 1);
      }

      return mono.fileName.modify(folderName);
    };

    var audio = {
      className: 'sf-audio-panel',
      lastRow: null,
      style: undefined,
      secondsFromDuration: function(time) {
        var minSec = time.split(':').map(function(item) {
          return parseInt(item);
        });
        return minSec[0] * 60 + minSec[1];
      },
      getTitle: function(row) {
        var title = row.querySelector('.jp__track-fullname');
        var artist = row.querySelector('.jp__track-performer');
        if (artist === null) {
          artist = row.querySelector('.jp__track-name-text');
          if (artist !== null) {
            artist = artist.querySelector('a:not(.jp__track-fullname)');
            if (artist !== null) {
              var tmp = title;
              title = artist;
              artist = tmp;
            }
          }
        }
        if (artist !== null) {
          artist = artist.textContent.trim();
          if (!artist) {
            artist = 'noname';
          }
        } else {
          artist = '';
        }
        if (artist) {
          artist = artist + ' - ';
        } else {
          artist = '';
        }
        if (title === null) {
          return;
        }
        title = title.textContent;
        var fullName = artist + title;
        fullName = fullName.replace(/[\r\n\t\s]+/img, ' ').replace(/\s+/g, ' ').trim();
        return fullName;
      },
      getTitle2: function(row) {
        var title = row.querySelector('.title');
        var name = row.querySelector('.name');
        var author = row.querySelector('.author');
        if (name) {
          name = name.textContent;
          if (!name.length) {
            name = 'noname';
          }
        }
        if (author) {
          author = author.textContent;
        }
        var fullName = '';
        if (name && author) {
          fullName = author + ' - ' + name;
        } else {
          fullName = title.textContent;
        }
        fullName = fullName.replace(/[\r\n\t\s]+/img, ' ').replace(/\s+/g, ' ').trim();
        return fullName;
      },
      getMp3UrlList: function(cb) {
        var type = 1;
        var rowList = document.querySelectorAll('.song-item');
        if (rowList.length === 0) {
          rowList = document.querySelectorAll('.jp__track');
          type = 0;
        }

        var urlList = [];
        var dblList = {};

        var next = function(row) {
          promise = promise.then(function() {
            return new Promise(function(resolve) {
              audio.getUrl(row, type, resolve);
            });
          }).then(function(url) {
            if (url && !dblList[url]) {
              dblList[url] = 1;
              var durationNode = '';
              var fullTitle = '';
              if (type === 0) {
                durationNode = row.querySelector('.jp__track-duration-total');
                fullTitle = audio.getTitle(row);
              } else {
                durationNode = row.querySelector('.time');
                fullTitle = audio.getTitle2(row);
              }
              if (fullTitle) {
                var filename = mono.fileName.modify(fullTitle) + '.mp3';
                var duration = durationNode && audio.secondsFromDuration(durationNode.textContent);
                urlList.push({
                  url: url,
                  filename: filename,
                  title: fullTitle,
                  duration: duration
                });
              }
            }
          }).catch(function(err) {
            // console.error(err);
          });
        };

        var promise = Promise.resolve();
        for (var row, i = 0; row = rowList[i]; i++) {
          next(row);
        }
        promise.then(function() {
          cb(urlList);
        });
      },
      showListOfAudioFiles: function(isPlaylist) {
        audio.getMp3UrlList(function(list) {
          if (list.length === 0) {
            return;
          }
          if (isPlaylist) {
            SaveFrom_Utils.playlist.popupPlaylist(list, getFolderName(), true);
          } else {
            SaveFrom_Utils.playlist.popupFilelist(list);
          }
        });
      },
      downloadMP3Files: function() {
        audio.getMp3UrlList(function(list) {
          if (list.length === 0) {
            return;
          }
          SaveFrom_Utils.downloadList.showBeforeDownloadPopup(list, {
            type: 'audio',
            folderName: getFolderName()
          });
        });
      },
      onDlBtnOver: function(e) {
        if (mono.isOpera || mono.isSafari) {
          return;
        }
        var duration = this.dataset.duration;
        if (e.type === 'mouseenter') {
          var _this = this;
          var options = undefined;
          var ttp = tooltip.show(_this, options = {
            top: -14,
            width: 16,
            style: {
              backgroundColor: '#fff',
              border: '1px solid #ccc',
              color: 'rgb(48, 48, 48)'
            }
          });

          if (_this.dataset.bitrate) {
            ttp.style.padding = '2px 5px 3px';
            ttp.textContent = ' (' + _this.dataset.size + ' ~ ' + _this.dataset.bitrate + ')';
            return;
          }

          if (_this.dataset.size) {
            ttp.style.padding = '2px 5px 3px';
            ttp.textContent = ' (' + _this.dataset.size + ')';
            return;
          }

          ttp.style.padding = '2px 2px 0 2px';
          ttp.textContent = '';
          ttp.appendChild(mono.create('img', {
            src: '//my9.imgsmail.ru/r/my/preloader_circle_16.gif',
            height: 16,
            width: 16
          }));

          mono.sendMessage({
            action: 'getFileSize',
            url: _this.href
          }, function(response) {
            ttp.style.padding = '2px 5px 3px';
            if (!response.fileSize) {
              ttp.textContent = language.getFileSizeFailTitle;
              tooltip.updatePos(_this, options);
              return;
            }
            var size = SaveFrom_Utils.sizeHuman(response.fileSize, 2);

            if (duration) {
              var bitrate = Math.floor((response.fileSize / duration) / 125) + ' ' + language.kbps;

              _this.dataset.bitrate = bitrate;
              _this.dataset.size = size;

              ttp.textContent = ' (' + size + ' ~ ' + bitrate + ')';
            } else {
              _this.dataset.size = size;

              ttp.textContent = ' (' + size + ')';
            }

            tooltip.updatePos(_this, options);
          });
          return;
        }
        // mouseleave
        tooltip.hide();
      },
      getUrlViaBridge: function(row, cb) {
        if (audio.getUrlViaBridge.index === undefined) {
          audio.getUrlViaBridge.index = 0;
        }

        var className = 'sf-bridge-item-' + audio.getUrlViaBridge.index;
        audio.getUrlViaBridge.index++;
        row.classList.add(className);

        SaveFrom_Utils.bridge({
          args: [{
            className: className
          }],
          func: function(data, cb) {
            var className = data.className;
            var el = document.getElementsByClassName(className)[0];
            el.classList.remove(className);

            var $data = jQuery(el).data();
            if ($data && $data.item) {
              cb($data.item.url);
            }
          },
          cb: function(data) {
            cb(data);
          },
          timeout: 300
        });
      },
      getUrlById: function(id) {
        var func = function(id, cb) {
          var url = '';
          var findUrl = function(items, id) {
            var url = '';
            items.some(function(item) {
              if (item._attr && item._attr.file === id) {
                url = item._attr.url;
                return true;
              }
            });
            return url;
          };
          try {
            url = findUrl(APP.activePage.collection.items, id);
          } catch (err) {}
          try {
            if (!url) {
              url = findUrl(APP.player.collection.items, id);
            }
          } catch (err) {}
          cb(url);
        };

        return new Promise(function(resolve) {
          SaveFrom_Utils.bridge({
            args: [id],
            func: func,
            cb: resolve
          });
        }).then(function(url) {
          if (!url) {
            throw new Error('Url is not found');
          }
          if (/^\/\//.test(url)) {
            url = 'http:' + url;
          }
          return url;
        });
      },
      getUrl: function(row, rowType, cb) {
        var url = row.dataset.url;
        if (url) {
          return cb(url);
        }
        if (rowType === 0) {
          var urlLink = row.querySelector('a.jp__track-fullname-link');
          if (urlLink === null) {
            return cb();
          }
          urlLink = urlLink.href;
          var params = mono.parseUrl(urlLink);
          if (!params.file || !params.uid) {
            return audio.getUrlViaBridge(row, function(url) {
              if (url) {
                row.dataset.url = url;
              }
              cb(url);
            });
          }
          return cb('http://music.my.mail.ru/file/' + params.file + '.mp3?u=' + encodeURIComponent(params.uid));
        } else
        if (rowType === 1) {
          var id = row.dataset.file;
          return audio.getUrlById(id).then(function(url) {
            cb(url);
          }, function() {
            cb();
          });
        }
      },
      onDlBtnClick: function(e) {
        e.stopPropagation();
        SaveFrom_Utils.downloadOnClick(e);
      },
      getDlLink: function(url, duration, fullTitle) {
        return mono.create('a', {
          data: {
            duration: duration || ''
          },
          href: url,
          style: {
            position: 'relative',
            display: 'inline-block',
            width: '16px',
            height: '16px',
            verticalAlign: 'middle'
          },
          download: mono.fileName.modify(fullTitle + '.mp3'),
          on: [
            ['mouseenter', audio.onDlBtnOver],
            ['mouseleave', audio.onDlBtnOver],
            ['click', this.onDlBtnClick]
          ]
        });
      },
      addDownloadPanelNew: function(row, url) {
        if (!url) {
          return;
        }
        var fullTitle = audio.getTitle2(row);
        if (!fullTitle) {
          return;
        }
        var timeEl = row.querySelector('.time');
        var duration = timeEl && audio.secondsFromDuration(timeEl.textContent);

        var dlPanel = mono.create('div', {
          class: [audio.className, 'type-2'],
          append: [
            this.getDlLink(url, duration, fullTitle)
          ]
        });

        var iconsEl = row.querySelector('.icons');
        if (iconsEl) {
          iconsEl.appendChild(dlPanel);
        }
      },
      addDownloadPanel: function(row, url) {
        var duration = row.querySelector('.jp__track-duration-total');
        if (duration === null || url === undefined) {
          return;
        }
        var fullTitle = audio.getTitle(row);
        if (!fullTitle) {
          return;
        }
        duration = audio.secondsFromDuration(duration.textContent);

        var dlPanel = mono.create('div', {
          class: [audio.className, 'type-0'],
          append: [
            this.getDlLink(url, duration, fullTitle)
          ]
        });

        var container = row.querySelector('.jp__track-management');
        if (!container) {
          return;
        }

        if (container.firstChild) {
          container.insertBefore(dlPanel, container.firstChild);
        } else {
          container.appendChild(dlPanel);
        }
      },
      onTrackOver: function(row, rowType) {
        if (row.getElementsByClassName(audio.className).length !== 0) {
          return;
        }

        audio.getUrl(row, rowType, function(url) {
          if (rowType === 1) {
            audio.addDownloadPanelNew(row, url);
          } else {
            audio.addDownloadPanel(row, url);
          }
        });
      },
      injectStyle: function() {
        if (this.style) {
          if (!this.style.parentNode) {
            document.head.appendChild(this.style);
          }
          return;
        }

        this.style = mono.create('style', {
          text: mono.style2Text([{
            selector: '.' + this.className,
            style: {
              display: 'none',
              left: '22px',
              backgroundImage: 'url(' + SaveFrom_Utils.svg.getSrc('download', '#168DE2') + ')',
              backgroundRepeat: 'no-repeat',
              backgroundPosition: 'center',
              backgroundSize: '16px'
            }
          }, {
            selector: '.jp__track:hover .' + this.className,
            style: {
              display: 'block',
              opacity: 0.5
            }
          }, {
            selector: '.jp__track:hover .' + this.className + '.type-0',
            style: {
              display: 'inline-block',
              marginLeft: '-16px',
              position: 'relative',
              left: '-2px'
            }
          }, {
            selector: '.jp__track.jp__track-plays .' + this.className,
            style: {
              left: '-18px'
            }
          }, {
            selector: '.' + this.className + ':hover',
            style: {
              opacity: '1 !important'
            }
          }, {
            selector: '.' + this.className + '.type-2',
            style: {
              marginRight: '5px',
              marginLeft: '5px'
            }
          }, {
            selector: '.song-item:hover .' + this.className + '.type-2',
            style: {
              display: 'inline-block',
              opacity: 0.5
            }
          }])
        });

        document.head.appendChild(this.style);
      },
      rmBtn: function() {
        if (audio.style) {
          audio.style.parentNode.removeChild(audio.style);
          audio.style = undefined;
        }
        var btnList = document.querySelectorAll('.' + audio.className);
        for (var i = 0, item; item = btnList[i]; i++) {
          item.parentNode.removeChild(item);
        }
      }
    };

    var video = {
      btnIndex: 0,
      domCache: {},
      className: 'sf-video-btn',

      prepareLinks: function(links) {
        var menuLinks = [];
        for (var i = 0, link; link = links[i]; i++) {
          var url = link.url;
          var format = 'FLV';
          if (url.indexOf('.mp4') !== -1) {
            format = 'MP4';
          }
          if (url.indexOf('.mov') !== -1) {
            format = 'MOV';
          }
          if (url.indexOf('.mpg') !== -1) {
            format = 'MPG';
          }
          if (!link.quality) {
            link.quality = '-?-';
          }
          var quality = link.quality.toUpperCase();

          var qList = ['1080P', '720P', '480P', '360P', '272P'];
          var tList = ['1080', '720', '480', '360', '272'];

          var qPos = qList.indexOf(quality);
          if (qPos !== -1) {
            quality = tList[qPos];
          }

          var ext = format.toLowerCase();
          var popupLink = {
            href: url,
            title: link.title,
            ext: ext,
            format: format,
            quality: quality,
            forceDownload: true
          };
          menuLinks.push(popupLink);
        }
        if (menuLinks.length === 0) {
          return;
        }
        return menuLinks;
      },

      showLinkList: function(links, button, isUpdate) {
        if (!links) {
          links = language.noLinksFound;
        }

        if (isUpdate) {
          if (!mailru.contextMenu) {
            return;
          }
          mailru.contextMenu.update(links);
          return;
        }

        if (mailru.contextMenu && mailru.contextMenu.isShow) {
          mailru.hideMenu();
          return;
        }
        mailru.contextMenu = SaveFrom_Utils.popupMenu.quickInsert(button, links, 'video-links-popup', {
          parent: mono.getParentByClass(button, 'b-video__main')
        });
      },

      appendPageBtn: function(container, btnIndex, styleIndex) {
        var exBtn = container.querySelector('.' + video.className);
        if (exBtn !== null) {
          return;
        }

        var link = null;
        var btn = mono.create('span', {
          class: video.className,
          append: [
            link = mono.create('a', {
              data: {
                index: btnIndex
              },
              href: '#',
              on: ['click', function(e) {
                e.preventDefault();

                mono.onRemoveEvent(this, mailru.hideMenu);

                video.readDomCache(this.dataset.index, this);
              }]
            })
          ]
        });

        if (styleIndex === 1) {
          link.style.marginLeft = '15px';
          link.textContent = language.download;
        } else
        if (styleIndex === 2) {
          mono.create(link, {
            style: {
              fontSize: 0,
              lineHeight: 0,
              padding: '6px',
              boxShadow: 'inset 0 0 0 1px #ccc',
              borderRadius: '3px',
              display: 'inline-block'
            }
          });
          link.appendChild(SaveFrom_Utils.svg.getSvg('download', '#666', 18, 18));
        }

        if (styleIndex === 2) {
          container.appendChild(btn);
        } else
        if (styleIndex === 1) {
          var child = container.lastChild;
          container.insertBefore(btn, child);
          child = null;
        }
      },

      appendBtn: function(container, btnIndex) {
        var exBtn = container.querySelector('.' + video.className);
        if (exBtn !== null) {
          return;
        }

        var child = undefined;
        var style = {};
        if (container.childNodes.length > 1) {
          child = container.childNodes[1];
        } else {
          child = container.lastChild;
          style.marginRight = '5px';
        }

        var btn = mono.create('span', {
          class: container.lastChild.getAttribute('class') + ' ' + video.className,
          append: [
            mono.create('a', {
              data: {
                index: btnIndex
              },
              text: language.download,
              href: '#',
              on: ['click', function(e) {
                e.preventDefault();

                mono.onRemoveEvent(this, mailru.hideMenu);

                video.readDomCache(this.dataset.index, this);
              }],
              style: style
            })
          ]
        });

        container.insertBefore(btn, child);
        child = null;
      },

      readDomCache: function(index, button) {
        video.showLinkList(language.download, button);

        var abort = function() {
          video.showLinkList(undefined, button, 1)
        };

        var showLinks = function(response) {
          if (response.action === 'getRutubeLinks') {
            if (!preference.showUmmyItem) {
              return abort();
            }
            video.showLinkList(SaveFrom_Utils.popupMenu.prepareLinks.rutube(response.links), button, 1);
          } else
          if (response.action === 'getMailruLinks') {
            video.showLinkList(SaveFrom_Utils.popupMenu.prepareLinks.mailru(response.links, response.title), button, 1);
          } else {
            video.showLinkList(video.prepareLinks(response.links), button, 1);
          }
        };

        var cacheItem = video.domCache[parseInt(index)];
        if (cacheItem.links) {
          showLinks(cacheItem);
        } else
        if (cacheItem.metadataUrl) {
          var metadataUrl = cacheItem.metadataUrl;
          if (/^\/\//.test(metadataUrl)) {
            metadataUrl = 'http:' + metadataUrl;
          }

          var always = function(data) {
            if (!data || typeof data !== 'object') {
              abort();
            } else
              video.readMeta(data, function(response) {
                if (!response.links) {
                  abort();
                } else {
                  cacheItem.links = response.links;
                  cacheItem.action = response.action;

                  showLinks(cacheItem);
                }
              });
          };

          mono.request({
            url: metadataUrl,
            withCredentials: true,
            json: true,
            localXHR: true
          }, function(err, resp) {
            always(err ? null : resp.body);
          });
        } else
        if (cacheItem.url) {
          mono.sendMessage({
            action: 'getMailruLinks',
            extVideoId: cacheItem.url
          }, function(response) {
            if (!response.links) {
              abort();
            } else {
              cacheItem.title = response.title;
              cacheItem.links = response.links;
              cacheItem.action = response.action;

              showLinks(cacheItem);
            }
          });
        } else {
          abort();
        }
      },

      readMeta: function(metadata, cb) {
        var links = [],
          title;
        if (metadata.provider === 'UPLOADED') {
          title = metadata.movie ? metadata.movie.title : undefined;
          if (!metadata.videos) {
            return cb();
          }
          metadata.videos.forEach(function(item) {
            links.push({
              quality: item.name,
              url: item.url,
              title: title
            });
          });
        }
        if (metadata.provider === 'ugc') {
          title = metadata.meta ? metadata.meta.title : undefined;
          if (!metadata.videos) {
            return cb();
          }
          metadata.videos.forEach(function(item) {
            links.push({
              quality: item.key,
              url: item.url,
              title: title
            });
          });
        }
        if (metadata.provider === 'pladform') {
          title = metadata.meta ? metadata.meta.title : undefined;
          mono.sendMessage({
            action: 'getPladformVideo',
            extVideoId: {
              playerId: metadata.meta.playerId,
              videoId: metadata.meta.videoId
            }
          }, function(response) {
            if (!response) {
              return cb();
            }

            var links = response.links;
            if (!links) {
              return cb();
            }

            links.forEach(function(item) {
              if (typeof item !== 'object') {
                return;
              }

              if (item.title === undefined) {
                item.title = title
              }
            });

            cb(response);
          });
          return;
        }
        if (links.length === 0) {
          return cb();
        }
        return cb({
          links: links
        });
      },

      getFlashVars: function(videoObj) {
        if (!videoObj) {
          return;
        }

        var flashvars = videoObj.querySelector('param[name="flashvars"]');
        if (!flashvars) {
          return;
        }

        var value = flashvars.value;
        var url = mono.parseUrl(value, {
          params: true
        });

        if (url.metadataUrl) {
          return {
            metadataUrl: url.metadataUrl
          };
        }
      },

      matchUrl: function(url) {
        var linkR = /\/([^\/]+)\/([^\/]+)\/video\/(.+).html/;
        var embedR = /embed\/([^\/]+)\/([^\/]+)\/(.+).html/;

        var r = url.match(linkR);
        if (!r) {
          r = url.match(embedR);
        }

        return r;
      },

      getVideoId: function(player) {
        if (player.tagName !== 'OBJECT') {
          player = player.querySelector('object[name="b-video-player"]');
        }

        var videoObj = this.getFlashVars(player);
        if (videoObj) {
          return videoObj;
        }

        var albumJson = document.querySelector('[data-type="album-json"]');
        if (albumJson) {
          try {
            albumJson = JSON.parse(albumJson.textContent);
            if (albumJson.signVideoUrl) {
              return {
                metadataUrl: albumJson.signVideoUrl
              };
            }
          } catch (e) {}
        }

        var videoId = this.matchUrl(location.pathname);

        if (videoId) {
          return {
            metadataUrl: 'http://api.video.mail.ru/videos/' + videoId[1] + '/' + videoId[2] + '/' + videoId[3] + '.json'
          };
        }
      },

      getVideoContentVideoId: function(conteiner) {
        var videoId = null;

        var shareBtn = conteiner.querySelector('.sp-video__item-page-new__share__item[data-share-type][data-location]');
        if (shareBtn) {
          videoId = {
            url: shareBtn.dataset.location
          };
        }

        return videoId;
      },

      insertBtnInPage: function(videoInfo, info, styleIndex) {
        if (videoInfo.metadataUrl) {
          videoInfo.metadataUrl = decodeURIComponent(videoInfo.metadataUrl);
          video.domCache[video.btnIndex] = {
            metadataUrl: videoInfo.metadataUrl
          };
        } else {
          video.domCache[video.btnIndex] = mono.extend({}, videoInfo);
        }


        video.appendPageBtn(info, video.btnIndex, styleIndex);

        video.btnIndex++;
      },
      insertBtnInPopup: function(videoInfo, info) {
        if (videoInfo.metadataUrl) {
          videoInfo.metadataUrl = decodeURIComponent(videoInfo.metadataUrl);
          video.domCache[video.btnIndex] = {
            metadataUrl: videoInfo.metadataUrl
          };
        }

        video.appendBtn(info, video.btnIndex);

        video.btnIndex++;
      },
      rmBtn: function() {
        var btnList = document.querySelectorAll('.' + video.className);
        for (var i = 0, item; item = btnList[i]; i++) {
          item.parentNode.removeChild(item);
        }
      }
    };
  }, null, function syncIsActive() {
    "use strict";
    if (mono.isSafari || mono.isGM) {
      var list = [
        '*://my.mail.ru/*'
      ];

      var reStr = list.map(function(pattern) {
        return mono.urlPatternToStrRe(pattern);
      }).join('|');
      var re = new RegExp(reStr);

      if (!re.test(location.protocol + '//' + location.hostname)) {
        return false;
      }
    }

    if (mono.isIframe()) {
      return false;
    }

    return true;
  });
  (typeof mono === 'undefined') && (mono = {
    loadModule: function() {
      this.loadModuleStack.push(arguments);
    },
    loadModuleStack: []
  });

  mono.loadModule('savefrom', function(moduleName, initData) {
    "use strict";
    var language = initData.getLanguage;
    var preference = initData.getPreference;

    mono.asyncCall(function() {
      savefrom.run();
    });

    var getRandomInt = function() {
      var now = Date.now();
      var rnd = now;
      while (now === rnd) {
        rnd = Date.now();
      }
      return rnd;
    };

    var savefrom = {
      name: moduleName,
      scriptId: 'savefrom__ext_script',
      dataAttr: 'data-extension-disabled',


      run: function() {
        savefrom.setExtParams();

        if (location.href.search(/\/(update-helper|userjs-setup)\.php/i) > -1) {
          var btn = document.getElementById('js-not-remind');
          if (btn) {
            btn.addEventListener('click', function(e) {
              if (e.button === 0) {
                mono.sendMessage({
                  action: 'hideUserjsMigrationInfo'
                });
              }
            });
          }
          return;
        }

        var form = document.getElementById('sf_form');
        if (!form)
          return;

        form.addEventListener('submit', function(event) {
          var url = form.sf_url.value;
          if (!url)
            return;

          if (form.getAttribute(savefrom.dataAttr) == '1')
            return;

          var re = {
            getVKLinks: [
              /^https?:\/\/(?:[a-z]+\.)?(?:vk\.com|vkontakte\.ru)\/(video-?\d+_-?\d+)/i,
              /^https?:\/\/(?:[a-z]+\.)?(?:vk\.com|vkontakte\.ru)\/video_ext.php\?(.*oid=-?\d+.*)$/i,
              /^https?:\/\/(?:[a-z]+\.)?(?:vk\.com|vkontakte\.ru)\/[\w\-\.]+\?.*z=(video-?\d+_-?\d+)/i
            ],
            getYoutubeLinks: [
              /^https?:\/\/(?:[a-z]+\.)?youtube\.com\/(?:#!?\/)?watch\?.*v=([\w\-]+)/i,
              /^https?:\/\/(?:[a-z0-9]+\.)?youtube\.com\/(?:embed|v)\/([\w\-]+)/i,
              /^https?:\/\/(?:[a-z]+\.)?youtu\.be\/([\w\-]+)/i
            ],
            getVimeoLinks: [
              /^https?:\/\/(?:[\w\-]+\.)?vimeo\.com\/(?:\w+\#)?(\d+)/i,
              /^https?:\/\/player\.vimeo\.com\/video\/(\d+)/i,
              /^https?:\/\/(?:[\w\-]+\.)?vimeo\.com\/channels\/(?:[^\/]+)\/(\d+)$/i,
              /^https?:\/\/(?:[\w\-]+\.)?vimeo\.com\/[^\/]+\/review\/(\d+)\/(?:\d+)/i
            ],

            getDailymotionLinks: [
              /^http:\/\/(?:www\.)?dai\.ly\/([a-z0-9]+)_?/i,
              /^https?:\/\/(?:[\w]+\.)?dailymotion\.com(?:\/embed|\/swf)?\/video\/([a-z0-9]+)_?/i
            ],

            getFacebookLinks: [
              /^https?:\/\/(?:[\w]+\.)?facebook\.com(?:\/video)?\/video.php.*[?&]{1}v=([0-9]+).*/i,
              /^https?:\/\/(?:[\w]+\.)?facebook\.com\/.+\/videos(?:\/\w[^\/]+)?\/(\d+)/i
            ],

            getMailruLinks: [
              /^https?:\/\/my\.mail\.ru\/([^\/]+\/[^\/]+\/[^\/]+\/[^\/]+\/[^\/]+\.html).*/i,
              /^https?:\/\/videoapi\.my\.mail\.ru\/videos\/(embed\/[^\/]+\/[^\/]+\/[^\/]+\/[^\/]+\.html).*/i
            ]
          };

          for (var i in re) {
            for (var j = 0; j < re[i].length; j++) {
              var vid = url.match(re[i][j]);
              if (vid && vid.length > 1) {
                vid = vid[1];
                var playlist = SaveFrom_Utils.getMatchFirst(url, /list=([\w\-]+)/i);
                event.preventDefault();
                event.stopPropagation();

                var request = {
                  extVideoId: vid,
                  action: i,
                  checkSubtitles: true,
                  checkLinks: true
                };

                if (i === 'getVimeoLinks') {
                  request.url = url;
                }

                mono.sendMessage(request, function(r) {
                  savefrom.setLinks(r.action, r.extVideoId, r.links, r.title, null,
                    r.subtitles, playlist, r.duration, r.thumb, r.checkLinks);
                });

                return false;
              }
            }
          }
        }, false);


        document.body.addEventListener('click', function(event) {
          var node = event.target;

          if (node.tagName === 'I' && node.classList.contains('file-info-btn')) {
            savefrom.onInfoBtnClick.call(node, event);
            return;
          }

          if (node.tagName != 'A') {
            if (node.parentNode.tagName == 'A')
              node = node.parentNode;
            else
              return;
          }

          if ((mono.isChrome || mono.isFirefox) && node.classList.contains('link-download') && !node.classList.contains('disabled') && node.getAttribute('download')) {
            if (node.classList.contains('ga_track_events') && node.getAttribute('data-ga-event')) {
              mono.trigger(node, 'sendstats', {
                bubbles: true,
                cancelable: false
              });
            }
            return SaveFrom_Utils.downloadOnClick(event, null);
          }

          var vid = node.getAttribute('data-video-id');
          if (!vid) {
            return;
          }

          if (node.getAttribute(savefrom.dataAttr) == '1')
            return;

          var action = {
            vk: 'getVKLinks',
            yt: 'getYoutubeLinks'
          };

          vid = vid.split(':', 2);
          if (vid.length != 2 || !action[vid[0]])
            return;

          event.preventDefault();
          event.stopPropagation();

          node.style.display = 'none';

          if (!node.id) {
            node.id = vid[0] + '_' + vid[1] + '_' + (Math.random() * 1000) +
              '_' + (new Date()).getTime();
          }

          var request = {
            extVideoId: vid[1],
            action: action[vid[0]],
            checkSubtitles: true,
            checkLinks: true
          };

          mono.sendMessage(request, function(r) {
            savefrom.setLinks(r.action, r.extVideoId, r.links, r.title, node,
              r.subtitles, null, r.duration, r.thumb, r.checkLinks);
          });

          return false;
        }, true);
      },

      onInfoBtnClick: function(e) {
        e.preventDefault();
        e.stopPropagation();

        if (this.classList.contains('sf-clicked')) {
          return;
        }
        this.classList.add('sf-clicked');

        var className = 'sf-btn' + getRandomInt();
        this.classList.add(className);

        var rmOldScript = function() {
          var exScript = document.getElementsByClassName('sf-script')[0];
          if (exScript !== undefined) {
            exScript.parentNode.removeChild(exScript);
          }
        };

        rmOldScript();
        document.body.appendChild(mono.create('script', {
          class: 'sf-script',
          text: '(' + function(btnClassName) {
            try {
              var btn = document.getElementsByClassName(btnClassName);
              var $btn = $(btn);

              $btn.unbind('click').removeAttr('onclick').addClass('active');

              if (btn.onclick) {
                btn.onclick = null;
              }

              var parent = $btn.closest('.result-box').find('.meta')[0];

              if (!parent) {
                return;
              }

              var boxId = 'file_info' + btnClassName;

              var box = sf.append(parent, 'div', {
                'id': boxId,
                'class': 'media-info'
              });

              sf.append(box, 'span', {
                id: boxId + '_busy'
              });

              sf.busy(boxId + '_busy', true);
            } catch (err) {}
          }.toString() + ')(' + JSON.stringify(className) + ')'
        }));

        var url = this.nextElementSibling.href;
        var title = this.nextElementSibling.textContent;
        mono.sendMessage({
          action: 'getFileSize',
          url: url
        }, function(response) {
          var size = response.fileSize;
          var data = {
            size: {
              name: {
                trans: language.size
              },
              value: SaveFrom_Utils.sizeHuman(size)
            }
          };
          rmOldScript();
          document.body.appendChild(mono.create('script', {
            class: 'sf-script',
            text: '(' + function(btnClassName, title, json) {
              try {
                var busy = document.getElementById('file_info' + btnClassName + '_busy');

                $(busy).slideUp();

                var btn = document.getElementsByClassName(btnClassName);

                sf.fileInfo.show(json, title, btn, busy.parentNode);
              } catch (err) {}
            }.toString() + ')(' + [
              JSON.stringify(className),
              JSON.stringify(title),
              JSON.stringify(data)
            ].join(',') + ')'
          }));
        });
      },

      setExtParams: function() {
        var script = mono.create('script', {
          id: 'savefrom__ext_params',
          type: 'text/javascript'
        });

        var params = {
          id: preference.sfHelperName,
          version: preference.version,
          enable: 1
        };

        script.textContent = '(' + function(json) {
          try {
            if (window.setBrowserExtension && typeof setBrowserExtension == "function") {
              setBrowserExtension(json);
            }
          } catch (err) {}
        }.toString() + ')(' + JSON.stringify(params) + ')';

        document.body.appendChild(script);
      },


      setLinks: function(action, vid, links, title, btn, subtitles, playlist,
        duration, thumb, valid) {
        if (valid === false) {
          savefrom.handleError(btn);
          return;
        }

        switch (action) {
          case 'getYoutubeLinks':
            savefrom.setYoutubeLinks(vid, links, title, btn, subtitles,
              playlist, duration, thumb);
            break;
          case 'getVKLinks':
            savefrom.setVKLinks(vid, links, title, btn, duration, thumb);
            break;

          case 'getVimeoLinks':
            savefrom.setVimeoLinks(vid, links, title, btn, duration, thumb);
            break;

          case 'getDailymotionLinks':
            savefrom.setDailymotionLinks(vid, links, title, btn, duration, thumb);
            break;

          case 'getFacebookLinks':
            savefrom.setFacebookLinks(vid, links, title, btn, duration, thumb);
            break;

          case 'getMailruLinks':
            savefrom.setMailruLinks(vid, links, title, btn, duration, thumb);
            break;
        }
      },


      handleError: function(btn) {
        if (btn) {
          if (btn) {
            btn.style.display = '';
            btn.setAttribute(savefrom.dataAttr, '1');
            btn.click();
          }
          return;
        }

        var form = document.getElementById('sf_form');
        if (!form)
          return;

        form.setAttribute(savefrom.dataAttr, '1');
        form.submit();
        form.removeAttribute(savefrom.dataAttr);
      },

      showVideoResult: function(result, btn) {
        if (!result || !result.url || !result.url.length) {
          savefrom.handleError(btn);
          return;
        }

        var script = document.getElementById(savefrom.scriptId);
        if (script) {
          script.parentNode.removeChild(script);
        }

        script = mono.create('script', {
          id: savefrom.scriptId,
          type: 'text/javascript'
        });

        var fn;
        if (btn) {
          var btnId = btn.id;
          fn = '(' + function(btnId, json) {
            try {
              var btn = document.getElementById(btnId);
              sf.result.replaceAjaxResult(json, true, true, btn);
            } catch (err) {}
          }.toString() + ')("' + btnId + '",' + JSON.stringify(result) + ')';
        } else {
          fn = '(' + function(json) {
            try {
              sf.finishRequest(true);
              sf.videoResult.show(json);
            } catch (err) {}
          }.toString() + ')(' + JSON.stringify(result) + ')';
        }
        script.textContent = fn;

        document.body.appendChild(script);
      },


      setVKLinks: function(vid, links, title, btn, duration, thumb) {
        if (!vid || !links) {
          savefrom.handleError(btn);
          return;
        }

        var result = {
          id: vid,
          url: links,
          hosting: 'vk.com (h)',
          meta: {
            title: (title ? mono.fileName.modify(title) : 'download'),
            source: "http://vk.com/" + vid,
            duration: SaveFrom_Utils.secondsToDuration(duration)
          }
        };

        if (thumb)
          result.thumb = thumb;

        for (var i = 0; i < result.url.length; i++) {
          result.url[i].info_url = '#';

          if (!result.url[i].ext && result.url[i].type)
            result.url[i].ext = result.url[i].type;

          if (!result.sd && !result.url[i].subname)
            result.sd = {
              url: result.url[i].url
            };
          else if (!result.hd && result.url[i].subname && parseInt(result.url[i].subname) >= 720)
            result.hd = {
              url: result.url[i].url
            };
        }

        savefrom.showVideoResult(result, btn);
      },

      setYoutubeLinks: function(vid, links, title, btn, subtitles, playlist,
        duration, thumb) {
        if (!vid || !links) {
          savefrom.handleError(btn);
          return;
        }

        var result = {
          id: vid,
          url: [],
          hosting: '101 (h)',
          meta: {
            title: (title ? mono.fileName.modify(title) : 'download'),
            source: (vid ? 'http://youtube.com/watch?v=' + vid : ''),
            duration: SaveFrom_Utils.secondsToDuration(duration)
          },
          thumb: (vid ? 'http://i.ytimg.com/vi/' + vid + '/hqdefault.jpg' : '')
        };

        var sig = false;


        SaveFrom_Utils.video.yt.init();

        var meta = links.meta || {};

        for (var formatName in SaveFrom_Utils.video.yt.format) {
          var f = SaveFrom_Utils.video.yt.format[formatName];
          for (var iTag in f) {
            var metaTag = meta[iTag] || {};
            if (links[iTag]) {
              if (!sig && links[iTag].search(/(\?|&)sig(nature)?=/i) > -1) {
                sig = true;
              }

              var quality = f[iTag].quality;

              if (metaTag.quality) {
                quality = metaTag.quality;
              }

              var l = {
                url: links[iTag],
                name: formatName,
                subname: quality,
                info_url: '#',
                type: formatName,
                quality: quality,
                attr: {}
              };


              if (f[iTag].sFps) {
                l.subname += ' ' + (metaTag.fps || 60);
              }

              if (f[iTag]['3d']) {
                l.name = '3D ' + l.name;
                l.group = '3d';
                l['3d'] = true;
              } else if (f[iTag]['noAudio']) {
                l.group = 'MP4 ';
                l.attr['class'] = 'no-audio';
                // l.ext = 'mp4';
              } else if (formatName == 'Audio AAC') {
                l.type = 'AAC';
                l.ext = 'aac';
                l.attr.style = 'white-space: nowrap;';
              } else if (formatName == 'Audio Vorbis') {
                l.type = 'Vorbis';
                l.ext = 'webm';
                l.attr.style = 'white-space: nowrap;';
              } else if (formatName == 'Audio Opus') {
                l.type = 'Opus';
                l.ext = 'opus';
                l.attr.style = 'white-space: nowrap;';
              } else {
                if (formatName.toLowerCase() == 'flv' && !result.sd) {
                  result.sd = {
                    url: links[iTag]
                  };
                }

                if (parseInt(quality) >= 720 && result.sd && !result.hd) {
                  result.hd = {
                    url: links[iTag]
                  };
                }
              }

              if (l.ext === undefined && l.type) {
                l.ext = l.type.toLowerCase();
              }

              if (f[iTag].noVideo === undefined && f[iTag].noAudio === undefined) {
                l.no_download = true;
              }

              result.url.push(l);
              delete links[iTag];
            }
          }
        }

        if (!sig) {
          savefrom.handleError(btn);
          return;
        }

        if (subtitles && subtitles.length > 0) {
          var subsId = vid.replace(/[^\w]/, '_');
          var btnId = 'yt_subs_btn_' + subsId;
          subsId = 'yt_subs_' + subsId;

          var subtToken = 'extension';
          var subsTitle = result.meta.title ? btoa(SaveFrom_Utils.utf8Encode(result.meta.title)) : '';

          result.action = [];
          result.action.push({
            name: language.subtitles,
            attr: {
              id: btnId,
              href: '#'
            },

            bind: {
              click: {
                fn: 'sf.youtubeSubtitles("{vid}","{subsId}","{btnId}","{subtToken}","{subsTitle}")'
                  .replace('{vid}', vid)
                  .replace('{subsId}', subsId)
                  .replace('{btnId}', '#' + btnId)
                  .replace('{subtToken}', subtToken)
                  .replace('{subsTitle}', subsTitle)
              }
            }
          });
        }

        if (playlist && false) {
          playlist = 'http://www.youtube.com/playlist?list=' + playlist;
          if (!result.action)
            result.action = [];
          result.action.push({
            name: language.playlist,
            attr: {
              href: '#',
              class: 'tooltip',
              title: language.downloadWholePlaylist
            },

            bind: {
              click: {
                fn: 'sf.processLink("{playlist}");'
                  .replace('{playlist}', playlist)
              }
            }
          });
        }

        if (preference.showUmmyItem) {
          result.action = result.action || [];

          result.action.push({
            name: 'HD / MP3',
            group: 'ummy',
            'second-btn': true,

            attr: {
              href: 'ummy://www.youtube.com/watch?v=' + vid,
              class: 'ummy-link ga_track_events',
              target: '_blank',
              'data-ga-event': 'send;event;vidacha-helper;youtube;ummy-helper-button-click'
            }
          });

          result.fn = result.fn || [];
          result.fn.push("if(window.ga){ga('send','event','vidacha-helper','youtube','ummy-helper-button-show');}");
        }

        savefrom.showVideoResult(result, btn);
      },

      setVimeoLinks: function(vid, links, title, btn, duration, thumb) {
        if (!vid || !links) {
          savefrom.handleError(btn);
          return;
        }

        var result = {
          id: vid,
          url: links,
          hosting: 'vimeo.com (h)',
          meta: {
            title: (title ? mono.fileName.modify(title) : 'download'),
            source: "http://vimeo.com/" + vid,
            duration: SaveFrom_Utils.secondsToDuration(duration)
          }
        };

        if (thumb)
          result.thumb = thumb;

        for (var i = 0; i < result.url.length; i++) {
          result.url[i].info_url = '#';

          if (!result.url[i].ext && result.url[i].type)
            result.url[i].ext = result.url[i].type;

          if (!result.sd && result.url[i].name == 'SD')
            result.sd = {
              url: result.url[i].url
            };
          else if (!result.hd && result.url[i].name == 'HD')
            result.hd = {
              url: result.url[i].url
            };
        }

        savefrom.showVideoResult(result, btn);
      },

      setDailymotionLinks: function(vid, links, title, btn, duration, thumb) {
        if (!vid || !links) {
          savefrom.handleError(btn);
          return;
        }

        var linkList = links.filter(function(item) {
          if (!item.extra) {
            return true;
          }
        });

        var result = {
          id: vid,
          url: linkList,
          hosting: 'dailymotion.com (h)',
          meta: {
            title: (title ? mono.fileName.modify(title) : 'download'),
            source: "http://dai.ly/" + vid,
            duration: SaveFrom_Utils.secondsToDuration(duration)
          }
        };

        if (thumb)
          result.thumb = thumb;

        var hd_size = 0,
          sd_size = 0;
        for (var i = 0, item; item = linkList[i]; i++) {
          item.info_url = '#';

          if (item.height >= 720) {
            if (hd_size < item.height) {
              result.hd = {
                url: item.url
              };
              hd_size = item.height;
            }
          } else
          if (sd_size < item.height) {
            result.sd = {
              url: item.url
            };
            sd_size = item.height;
          }
          delete item.height;
        }
        savefrom.showVideoResult(result, btn);
      },

      setFacebookLinks: function(vid, links, title, btn, duration, thumb) {
        if (!vid || !links) {
          savefrom.handleError(btn);
          return;
        }

        var result = {
          id: vid,
          url: links,
          hosting: 'facebook.com (h)',
          meta: {
            title: (title ? mono.fileName.modify(title) : 'download'),
            source: "https://facebook.com/video.php?v=" + vid,
            duration: SaveFrom_Utils.secondsToDuration(duration)
          }
        };

        if (thumb) {
          result.thumb = thumb;
        }

        for (var i = 0, item; item = links[i]; i++) {
          item.info_url = '#';

          if (item.name === "SD") {
            result.sd = {
              url: item.url
            };
          } else
          if (item.name === "HD") {
            result.hd = {
              url: item.url
            };
          }

          item.subname = item.name;
          item.name = item.ext;
        }
        savefrom.showVideoResult(result, btn);
      },

      setMailruLinks: function(vid, links, title, btn, duration, thumb) {
        if (!vid || !links) {
          savefrom.handleError(btn);
          return;
        }

        var result = {
          id: vid,
          url: links,
          hosting: 'mail.ru (h)',
          meta: {
            title: (title ? mono.fileName.modify(title) : 'download'),
            source: "http://my.mail.ru/" + vid,
            duration: SaveFrom_Utils.secondsToDuration(duration)
          }
        };

        if (thumb)
          result.thumb = thumb;

        var maxSd = 0;
        for (var i = 0, item; item = result.url[i]; i++) {
          item.info_url = '#';
          if (!isNaN(parseInt(item.subname))) {
            if (maxSd < item.subname && item.subname < 720) {
              result.sd = {
                url: item.url
              };
              maxSd = item.subname;
            }
            if (!result.hd && item.subname >= '720') {
              result.hd = {
                url: item.url
              };
            }
          } else {
            if (item.subname.toLowerCase() === 'sd') {
              result.sd = {
                url: item.url
              };
            } else if (item.subname.toLowerCase() === 'hd') {
              result.hd = {
                url: item.url
              };
            }
          }
        }

        savefrom.showVideoResult(result, btn);
      }
    };
  }, null, function syncIsActive() {
    "use strict";
    if (mono.isSafari || mono.isGM) {
      var list = [
        '*://*.savefrom.net/*'
      ];

      var reStr = list.map(function(pattern) {
        return mono.urlPatternToStrRe(pattern);
      }).join('|');
      var re = new RegExp(reStr);

      if (!re.test(location.protocol + '//' + location.hostname)) {
        return false;
      }
    }

    if (!mono.isIframe()) {
      if (location.href.search(/savefrom\.net\/(index\d?\.php|user\.php|update-helper\.php|userjs-setup\.php|\d+-[^\/]+\/|articles\/.+)?(\?|#|$)/i) === -1) {
        return false;
      }
    } else {
      var allowFrame = false;

      if (mono.isGM) {
        allowFrame = location.href.indexOf('/tools/helper-check.html') !== -1;
      }

      if (!allowFrame) {
        return false;
      }
    }

    return true;
  });
  (typeof mono === 'undefined') && (mono = {
    loadModule: function() {
      this.loadModuleStack.push(arguments);
    },
    loadModuleStack: []
  });

  mono.loadModule('soundcloud', function(moduleName, initData) {
    "use strict";

    var language = initData.getLanguage;
    var preference = initData.getPreference;
    var moduleState = preference.moduleSoundcloud ? 1 : 0;

    mono.onMessage.addListener(function(message, cb) {
      if (message.action === 'getModuleInfo') {
        if (message.url !== location.href) return;
        return cb({
          state: moduleState,
          moduleName: moduleName
        });
      }
      if (message.action === 'changeState') {
        if (moduleName !== message.moduleName) {
          return;
        }
        return sc.changeState(message.state);
      }
    });

    if (moduleState) {
      mono.asyncCall(function() {
        sc.run();
      });
    }

    var sc = {
      client_id: 'fDoItMDbsbZz8dY16ZzARCZmzgHBPotA',

      lastRow: null,
      timer: 0,
      btnClass: 'savefrom-helper--btn',

      nodeId: 0,

      tracks: {},
      audioElClassList: ['soundList__item', 'searchList__item', 'trackList__item', 'compactTrackList__item', 'soundBadgeList__item'],

      refreshClientId: function() {
        SaveFrom_Utils.bridge({
          func: function(cb) {
            if (typeof webpackJsonp === 'undefined') {
              return;
            }
            webpackJsonp([], {
              0: function(e, t, n) {
                "use strict";
                var getObjList = function() {
                  var list = [];
                  for (var key in n) {
                    if (!n.hasOwnProperty(key)) {
                      continue;
                    }
                    var obj = n[key];
                    if (typeof obj !== 'object') {
                      continue;
                    }
                    var hasExports = false;
                    for (var key2 in obj) {
                      if (obj[key2].exports) {
                        hasExports = true;
                      }
                      break;
                    }
                    if (!hasExports) {
                      continue;
                    }
                    list.push(obj);
                  }

                  return list;
                };

                var clientId;
                getObjList().some(function(obj) {
                  for (var index in obj) {
                    var item = obj[index];
                    if (!item) {
                      continue;
                    }
                    var exports = item.exports;
                    if (!exports) {
                      continue;
                    }
                    var _store = exports._store;
                    if (!_store) {
                      continue;
                    }

                    clientId = _store.client_id;
                    if (clientId) {
                      break;
                    }
                  }

                  if (clientId) {
                    return true;
                  }
                });

                cb({
                  client_id: clientId
                });
              }
            });
          },
          cb: function(data) {
            if (!data || !data.client_id) {
              return;
            }

            mono.storage.setExpire({
              scClientId: data.client_id
            }, 21600);

            sc.client_id = data.client_id;
          }
        });
      },

      loadClientId: function(cb) {
        var _this = this;
        mono.storage.getExpire('scClientId', function(storage, isExpire) {
          if (storage.scClientId) {
            _this.client_id = storage.scClientId;
          }

          if (isExpire) {
            _this.refreshClientId();
          }

          return cb();
        });
      },

      run: function() {
        moduleState = 1;
        var _this = this;
        return this.loadClientId(function() {
          if (SaveFrom_Utils.mutationWatcher.isAvailable()) {
            _this.mutationMode.enable();
          }
        });
      },

      changeState: function(state) {
        moduleState = state;
        sc.mutationMode.stop();
        sc.rmBtn();
        if (state) {
          sc.run();
        }
      },

      rmBtn: function() {
        ['sfSkip', 'sfId', 'sfSingle'].forEach(function(attr) {
          var dataAttr = mono.dataAttr2Selector(attr);
          var dataAttrList = document.querySelectorAll('[' + dataAttr + ']');
          for (var i = 0, item; item = dataAttrList[i]; i++) {
            item.removeAttribute(dataAttr);
          }
        });
        var btnList = document.querySelectorAll('.' + sc.btnClass);
        for (var i = 0, item; item = btnList[i]; i++) {
          item.parentNode.removeChild(item);
        }
      },

      handleRow: function(row, single) {
        var parent = row.querySelector('.soundActions .sc-button-group');
        if (!parent) {
          // console.log('no parent!', row);
          return;
        }

        var onGetTackInfo = function(info) {
          if (info) {
            sc.appendButton(parent, row, info);
          }
        };

        if (single) {
          if (parent.getElementsByClassName(sc.btnClass).length === 0) {
            sc.getTrackInfo(window.location.href, row, onGetTackInfo);
          }
        } else {
          var a = row.querySelector('a.sound__coverArt[href], a.soundTitle__title[href], a.trackItemWithEdit__trackTitle[href], a.trackItem__trackTitle[href], .chartTrack__title>a[href]');
          if (a !== null) {
            sc.getTrackInfo(a.href, row, onGetTackInfo);
          }
        }
      },


      getTrackInfo: function(url, row, cb) {
        url = url.replace(/#.*$/i, '');

        if (url.search(/^\/\/(?:[\w-]+\.)?soundcloud\.com(?:\d+)?\//i) > -1) {
          url = window.location.protocol + url;
        } else
        if (url.search(/https?:\/\//i) == -1) {
          if (url.charAt(0) != '/') {
            url = '/' + url;
          }

          url = window.location.protocol + '//' + window.location.host + url;
        }

        var cache = sc.tracks;
        var cacheTrack = cache[url];

        if (cacheTrack) {
          if (cacheTrack.cbList) {
            cacheTrack.cbList.push(cb);
          } else {
            cb(cacheTrack);
          }
        } else {
          cacheTrack = cache[url] = {
            cbList: [cb]
          };

          var request = {
            action: 'getSoundcloudTrackInfo',
            trackUrl: url,
            client_id: sc.client_id
          };

          return mono.sendMessagePromise(request).then(function(response) {
            cache[url] = sc.setTrackInfo(response);
          }, function(err) {
            mono.error('getSoundcloudTrackInfo', err);
            cache[url] = null;
          }).then(function() {
            var cb;
            while (cb = cacheTrack.cbList.shift()) {
              cb(cache[url]);
            }
          });
        }
      },

      setTrackInfo: function(data) {
        var url = data.trackUrl;
        var info = data.data;
        if (!url || !info) {
          return;
        }

        var tInfo = {};

        if (info.kind != 'track' && info.tracks && info.tracks.length == 1) {
          info = info.tracks[0];
        }

        if (info.kind == 'track' && info.stream_url) {
          sc.setSingleTrackParams(tInfo, info);
          tInfo.checkLinks = data.checkLinks;
          return tInfo;
        } else
        if (info.tracks) {
          var playlist = [];
          for (var i = 0, len = info.tracks.length; i < len; i++) {
            var t = {};
            sc.setSingleTrackParams(t, info.tracks[i]);
            playlist.push(t);
          }

          if (playlist.length > 0) {
            if (info.title) {
              tInfo.title = info.title;
            }

            tInfo.playlist = playlist;
            tInfo.checkLinks = data.checkLinks;
            return tInfo;
          }
        }
      },


      setSingleTrackParams: function(track, info) {
        var downloadUrl = info.stream_url;
        downloadUrl += (downloadUrl.indexOf('?') == -1) ? '?' : '&';
        downloadUrl += 'client_id=' + sc.client_id;
        track.url = downloadUrl;

        var param = ['id', 'title', 'duration'];
        for (var i = 0; i < param.length; i++) {
          if (info[param[i]]) {
            track[param[i]] = info[param[i]];
          }
        }

        if (track.title && info.user && info.user.username) {
          track.title = info.user.username + ' - ' + track.title;
        }
      },

      onDlBtnClick: function(e) {
        SaveFrom_Utils.downloadOnClick(e);
      },

      appendButton: function(parent, row, info) {
        var track = info;

        // update parent after latency
        if (!document.body.contains(row)) {
          return;
        } else
        if (!document.body.contains(parent)) {
          parent = row.querySelector('.soundActions .sc-button-group');
          if (!parent) {
            return;
          }
        }

        if (row.dataset.sfSkip > 1) {
          return;
        }
        row.dataset.sfSkip = '2';

        var btnClass = ['sc-button-small', 'sc-button-medium', 'sc-button-large'];
        for (var i = 0; i < btnClass.length; i++) {
          if (parent.querySelector('.' + btnClass[i])) {
            btnClass = [btnClass[i]];
          }
        }

        var a = document.createElement('a');

        var sfId = row.dataset.sfId;
        if (sfId) {
          a.dataset.sfParentId = row.dataset.sfId;
        }

        a.className = sc.btnClass + ' sc-button sc-button-responsive ' + btnClass[0];
        a.style.position = 'relative';

        var icon = document.createElement('img');

        if (track.playlist) {
          a.href = '#';
          a.title = language.playlist;

          var title = track.title ? mono.fileName.modify(track.title) : 'soundcloud';

          a.addEventListener('click', function(event) {
            event.preventDefault();
            setTimeout(function() {
              SaveFrom_Utils.playlist.popupPlaylist(track.playlist, title, true);
            }, 100);
          }, false);

          if (track.checkLinks === false) {
            icon.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAJElEQVQoz2P4//8/A7mYgWqa6+vr/xPCtNE86udRP9PWz6RiANU4hUYGNDpOAAAAAElFTkSuQmCC';
          } else {
            icon.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAMUlEQVR42mL8//8/A7mAiYECwILC82Uk7IzN/xmpYjPjqJ9H/UxTP1OkGQAAAP//AwDcahUV6UvyJwAAAABJRU5ErkJggg==';
          }
          icon.alt = language.playlist;
        } else
        if (track.checkLinks === false) {
          a.href = '#';
          a.title = language.noLinksFound;

          a.addEventListener('click', function(e) {
            e.preventDefault();
            var style = {
              backgroundColor: '#fff',
              border: '1px solid #777',
              padding: '2px 5px 3px'
            };
            SaveFrom_Utils.showTooltip(this, language.noLinksFound, undefined, style);
          });

          icon.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAVklEQVQoz2P4//8/A7mYgSqa0UF9ff1/GEaXG0SagYrmI2vAg+djtZkIA+bjdTYeA+YT5WcsBswnNcDmY9NIlGaoAQnYxHEFGMHQxqe5gRDGqpnuGQMALmDKhkjc9oYAAAAASUVORK5CYII=';
          icon.alt = 'noLinksFound'
        } else {
          a.href = track.url;
          a.title = language.download;

          if (track.title) {
            a.setAttribute('download',
              mono.fileName.modify(track.title.trim() + '.mp3'));

            a.addEventListener('click', this.onDlBtnClick, false);
          }

          icon.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAPklEQVR42mNgGHTgvw/DfxgexJqBiuYja8CD55NrwHxyXTCfWP/OJ0sjFgPmkxvXCWRFDy6MT3MDITw40j8Ak46HYQ4gDfUAAAAASUVORK5CYII=';
          icon.alt = 'download';
        }

        SaveFrom_Utils.setStyle(icon, {
          width: '15px',
          height: '15px',
          position: 'absolute',
          top: '50%',
          left: '50%',
          margin: '-7px 0 0 -7px'
        });
        a.appendChild(icon);

        parent.appendChild(a);

        icon = null;
        a = null;
        parent = null;
      },
      mutationMode: {
        observer: null,
        stop: function() {
          if (sc.mutationMode.observer) {
            sc.mutationMode.observer.stop();
          }
        },
        enable: function() {
          var _this = this;
          if (sc.mutationMode.observer) {
            return sc.mutationMode.observer.start();
          }

          var onTrackOver = (function() {
            var lastTimer = null;
            return function() {
              var _this = this;
              clearTimeout(lastTimer);
              lastTimer = setTimeout(function() {
                mono.off(_this, 'mouseenter', onTrackOver);
                if (moduleState) {
                  sc.handleRow.call(sc, _this);
                }
              }, 250);
            };
          })();

          sc.mutationMode.observer = SaveFrom_Utils.mutationWatcher.run({
            callback: function(summaryList) {
              var summary, n, i, node;
              for (i = 0; i < 6; i++) {
                summary = summaryList[i];
                for (n = 0; node = summary.added[n]; n++) {
                  if (node.dataset.sfSkip > 0) {
                    continue;
                  }
                  node.dataset.sfSkip = '1';
                  node.dataset.sfId = '' + sc.nodeId++;

                  mono.on(node, 'mouseenter', onTrackOver);
                }
              }
              for (i = 6; i < 8; i++) {
                summary = summaryList[i];
                for (n = 0; node = summary.added[n]; n++) {
                  var _node = null;
                  if (i === 6) {
                    _node = mono.getParentByClass(node, 'listenEngagement');
                  } else {
                    _node = mono.getParentByClass(node, 'visualSound');
                  }

                  if (_node.dataset.sfSingle > 0) {
                    continue;
                  }
                  _node.dataset.sfSkip = '1';

                  if (_node.classList.contains('streamContext')) {
                    return;
                  }

                  _node.dataset.sfSingle = '1';

                  sc.handleRow(_node, 1);
                }
              }

              summary = summaryList[8];
              for (n = 0; node = summary.removed[n]; n++) {
                node = document.querySelector('[' + mono.dataAttr2Selector('sfId') + '="' + node.dataset.sfParentId + '"]');

                if (!node) {
                  return;
                }

                if (node.dataset.sfSingle) {
                  return;
                }

                node.dataset.sfSkip = '1';

                if (document.body.contains(node)) {
                  sc.handleRow(node);
                }
              }
            },
            queries: [{
                css: 'li.trackList__item',
                is: 'added'
              },
              {
                css: 'li.compactTrackList__item',
                is: 'added'
              },
              {
                css: 'li.searchList__item',
                is: 'added'
              },
              {
                css: 'li.soundList__item',
                is: 'added'
              },
              {
                css: 'li.soundBadgeList__item',
                is: 'added'
              },
              {
                css: 'li.chartTracks__item',
                is: 'added'
              },
              {
                css: 'div.listenEngagement .soundActions .sc-button-group',
                is: 'added'
              },
              {
                css: 'div.visualSound .soundActions .sc-button-group',
                is: 'added'
              },
              {
                css: '.savefrom-helper--btn',
                is: 'removed'
              }
            ],
            filterTarget: [{
                css: 'div.waveform__layer'
              },
              {
                css: 'a.commentPopover__username'
              },
              {
                css: '.commentPopover'
              },
              {
                css: 'div.playbackTimeline__timePassed'
              },
              {
                css: 'div.commentsList'
              },
              {
                css: 'div.commentsList__item'
              },
              {
                css: 'div.commentsList__body'
              }
            ]
          });
        }
      }
    };

  }, null, function syncIsActive() {
    "use strict";

    if (mono.isSafari || mono.isGM) {
      var list = [
        '*://*.soundcloud.com/*'
      ];

      var reStr = list.map(function(pattern) {
        return mono.urlPatternToStrRe(pattern);
      }).join('|');
      var re = new RegExp(reStr);

      if (!re.test(location.protocol + '//' + location.hostname)) {
        return false;
      }
    }

    if (mono.isIframe()) {
      return false;
    }

    return true;
  });
  (typeof mono === 'undefined') && (mono = {
    loadModule: function() {
      this.loadModuleStack.push(arguments);
    },
    loadModuleStack: []
  });

  mono.loadModule('sovetnik', function(moduleName, initData) {
    "use strict";
    var preference = initData.getPreference;

    var onScriptStart = function() {
      var limit = 30;
      var slice = [].slice;
      var interval = setInterval(function() {
        var id = null;

        var found = slice.call(document.querySelectorAll('body style+div[id^=m]>div[class]:not([id])>img[src]')).some(function(node) {
          if (!/^data:image\/png;/.test(node.src)) {
            return;
          }

          var parent = node.parentNode && node.parentNode.parentNode;
          if (!parent || !/^m/.test(parent.id)) {
            return;
          }

          var btns = parent.querySelector('div>a[title][id^=m]~a[title][id^=m]~a[title][id^=m]');
          if (btns) {
            id = '#' + parent.id;
            return true;
          }
        });

        limit--;
        if (limit < 0 || found) {
          clearInterval(interval);
        }

        found && addListener(id);
      }, 1000);

      var addListener = function(id) {
        var container = document.querySelector(id);
        if (!container) {
          return;
        }

        mono.sendMessage({
          action: 'track',
          t: 'event',
          ec: 'sovetnik',
          ea: 'show',
          el: 'bar',
          tid: 'UA-67738130-3'
        });

        container.addEventListener('mousedown', function(e) {
          if (e.button !== 0) {
            return;
          }

          var link = e.target;
          while (link) {
            if (link.tagName === 'A') {
              break;
            }
            if (link.tagName === 'TR' && link.dataset.typeShop) {
              break;
            }

            link = link.parentNode;
            if (link && link === container) {
              link = null;
            }
          }

          if (!link) {
            return;
          }

          var type = null;
          if (link.tagName === 'TR') {
            type = link.dataset.typeShop;
          }
          if (link.tagName === 'A') {
            var prev = link.previousElementSibling;
            var next = link.nextElementSibling;
            if (!next || next.tagName !== 'A' || !next.querySelector('span')) {
              next = null;
            }
            if (next && next.nextElementSibling) {
              next = null;
            }
            var parent = link.parentNode;
            if (parent && parent.parentNode !== container) {
              parent = null;
            }
            if (parent && parent.childElementCount !== 2) {
              parent = null;
            }
            if (parent && !prev && next) {
              type = 'Show button';
            }
          }

          if (!type) {
            return;
          }

          mono.sendMessage({
            action: 'track',
            t: 'event',
            ec: 'sovetnik',
            ea: 'click',
            el: type,
            tid: 'UA-67738130-3',
            ev: 2
          });
          mono.sendMessage({
            action: 'track',
            t: 'event',
            ec: 'sovetnik',
            ea: 'click',
            el: type,
            tid: 'UA-7055055-5',
            ev: 2
          });
        });
      };
    };

    var domain = document.domain;

    if (/^www./.test(domain)) {
      domain = domain.slice(4);
    }

    var settings = {
      affId: 1020,
      clid: 2210496,
      applicationName: 'SaveFrom',
      aviaEnabled: true,
      offerEnabled: true
    };

    var getUrl = function() {
      var filePath = '//dl.metabar.ru/static/js/sovetnik.min.js';
      return filePath +
        '?mbr=true&settings=' + encodeURIComponent(JSON.stringify(settings));
    };

    var url = getUrl();

    var extStorage = {
      get: function(obj, cb) {
        return mono.storage.get(obj, cb);
      },
      set: function(obj, cb) {
        if (preference.sovetnikEnabled === 1) {
          if (obj.sovetnikRemoved === true) {
            mono.sendMessage({
              action: 'updateOption',
              key: 'sovetnikEnabled',
              value: 0
            });
          } else
          if (obj.sovetnikOfferAccepted === false) {
            mono.sendMessage({
              action: 'updateOption',
              key: 'sovetnikEnabled',
              value: 0
            });
          }
        }
        return mono.storage.set(obj, cb);
      },
      remove: function(obj, cb) {
        return mono.storage.remove(obj, cb);
      }
    };

    var injector = {
      /**
       * inject script to the page
       */
      inject: function() {
        if (!mono.isIframe()) {
          var script = document.createElement('script');
          script.async = 1;
          script.src = url;
          script.setAttribute('charset', 'UTF-8');
          if (document.body) {
            document.body.appendChild(script);
            onScriptStart();
          }
        }
      },

      /**
       * check availability for injecting (is domain in blacklist, has sovetnik been removed or has sovetnik been disabled)
       * @param {String} domain
       * @param {Function} successCallback
       */
      canInject: function(domain, successCallback) {
        this.listenScriptMessages();

        extStorage.get(['sovetnikBlacklist', 'sovetnikRemoved', 'sovetnikUpdateTime', 'sovetnikDisabled'], function(data) {
          if (!((data.sovetnikBlacklist && data.sovetnikBlacklist[domain]) || data.sovetnikRemoved || data.sovetnikDisabled)) {
            successCallback();
          }
          data.sovetnikUpdateTime = data.sovetnikUpdateTime || 0;
          if (Date.now() - data.sovetnikUpdateTime > 604800000) { // one week
            extStorage.set({
              sovetnikUpdateTime: Date.now(),
              sovetnikRemoved: false,
              sovetnikBlacklist: {}
            });
          }
        });
      },

      /**
       * add domain to the blacklist
       * @param domain
       */
      addToBlacklist: function(domain) {
        extStorage.get('sovetnikBlacklist', function(data) {
          data.sovetnikBlacklist = data.sovetnikBlacklist || {};
          data.sovetnikBlacklist[domain] = true;
          extStorage.set(data);
        });
      },

      /**
       *
       * @param {Boolean} value
       */
      setSovetnikRemovedState: function(value) {
        if (typeof value === "undefined") {
          extStorage.remove('sovetnikRemoved');
        } else {
          extStorage.set({
            sovetnikRemoved: value
          });
        }
      },

      /**
       *
       * @param {Boolean} value
       */
      setOfferState: function(value) {
        if (typeof value === "undefined") {
          extStorage.remove('sovetnikOfferAccepted');
        } else {
          extStorage.set({
            sovetnikOfferAccepted: value
          });
        }
      },

      /**
       * window.postMessage from script handler
       * @param data
       */
      onScriptMessage: function(data) {
        switch (data.command) {
          case 'blacklist':
            {
              this.addToBlacklist(data.value);
              break;
            }
          case 'removed':
            {
              this.setSovetnikRemovedState(data.value);
              break;
            }
          case 'offerAccepted':
            this.setOfferState(data.value);
            break;
        }
      },

      /**
       * window.postMessage handler
       */
      listenScriptMessages: function() {
        window.addEventListener('message', function(message) {
          if (message && message.data && message.data.type === 'MBR_ENVIRONMENT') {
            this.onScriptMessage(message.data);
          }
        }.bind(this), false);
      }
    };

    injector.canInject(domain, injector.inject.bind(injector));
  }, function isActive(initData) {
    "use strict";
    if (mono.global.exAviaBar) {
      return false;
    }

    var preference = initData.getPreference;

    if (!preference.hasSovetnik) {
      return false;
    }

    if (!preference.sovetnikEnabled) {
      return false;
    }

    if (mono.global.ddblAdv) {
      return false;
    }
    mono.global.ddblAdv = true;

    return true;
  }, function syncIsAvailable() {
    "use strict";
    if (!document.domain) {
      return false;
    }

    if (mono.isIframe()) {
      return false;
    }

    if (mono.isSafari || mono.isGM) {
      var excludeList = [
        'ftp://*',
        'file://*',
        '*://*.google.*/*',
        '*://*.acidtests.org/*',

        '*://*.savefrom.net/*',
        '*://*.youtube.com/*',
        '*://*.vimeo.com/*',
        '*://*.dailymotion.*/*',
        '*://*.vk.com/*',
        '*://*.vkontakte.ru/*',
        '*://*.odnoklassniki.ru/*',
        '*://*.ok.ru/*',
        '*://my.mail.ru/*',
        '*://*.soundcloud.com/*',
        '*://*.facebook.com/*',
        '*://*.instagram.com/*',
        '*://*.rutube.ru/*'
      ];

      var reStr = excludeList.map(function(pattern) {
        return mono.urlPatternToStrRe(pattern);
      }).join('|');
      var re = new RegExp(reStr);

      if (re.test(location.protocol + '//' + location.hostname)) {
        return false;
      }
    }

    var inBlackList = function() {
      var list = [
        "vk.com",
        "youtube.com",
        "odnoklassniki.ru",
        "ok.ru",
        "privet.ru",
        "facebook.com",
        "news.sportbox.ru",
        "play.google.com",
        "roem.ru",
        "linkedin.com",
        "ex.ua",
        "instagram.com",
        "rutube.ru",
        "e.mail.ru",
        "fotki.yandex.ru",
        "support.kaspersky.ru",
        "vimeo.com",
        "club.foto.ru",
        "garant.ru",
        "webmaster.yandex.ru",
        "support.kaspersky.ru",
        "fotki.yandex.ru",
        "mk.ru",
        "metrika.yandex.ru",
        "images.yandex.ru",
        "disk.yandex.ru",
        "maps.yandex.ru",
        "help.yandex.ru",
        "www.yaplakal.com",
        "www.facebook.com",
        "my.mail.ru",
        "aviasales.ru"
      ];

      return mono.matchHost(location.hostname, list);
    };

    if (inBlackList()) {
      return false;
    }

    return true;
  });
  (typeof mono === 'undefined') && (mono = {
    loadModule: function() {
      this.loadModuleStack.push(arguments);
    },
    loadModuleStack: []
  });

  mono.loadModule('aviaBar', function(moduleName, initData) {
    "use strict";

    (function() {
      "use strict";
      var browser = {
        sendMessage: function(msg, cb) {
          return mono.sendMessage(msg, cb);
        }
      };

      var initMessaging = function() {
        var origin = location.origin || location.protocol + "//" + location.hostname;
        var api = {
          sendMessage: function(message) {
            window.postMessage(message, origin);
          },
          onMessage: function(cb) {
            window.addEventListener('message', function(e) {
              if (e.origin === origin) {
                cb(e.data);
              }
            }, true);
          }
        };

        var bridgeMsgTools = {
          idPrefix: Math.floor(Math.random() * 1000),
          listenerArr: [],
          mkResponse: function(cbId) {
            var _this = this;
            var fn = cbId && function(msg) {
              var message = {
                tbr: true,
                idPrefix: _this.idPrefix,
                data: msg,
                responseId: cbId
              };
              return api.sendMessage(message);
            };
            return function(msg) {
              if (fn) {
                fn(msg);
                fn = null;
              }
            };
          },
          listener: function(message) {
            var _this = bridgeMsgTools;
            if (message && message.tbr && message.idPrefix !== _this.idPrefix && !message.responseId) {
              var respFn = _this.mkResponse(message.callbackId);
              _this.listenerArr.forEach(function(fn) {
                return fn(message.data, respFn);
              });
            }
          },
          onMessage: function(cb) {
            this.listenerArr.push(cb);
            if (this.listenerArr.length === 1) {
              api.onMessage(this.listener);
            }
          }
        };

        bridgeMsgTools.onMessage(function(msg, response) {
          if (msg && msg.action) {
            browser.sendMessage(msg, response);
          }
        });
      };

      var canInject = function() {
        if (document.body.parentNode.dataset.travelBar) {
          return false;
        }

        if (document.defaultView.self !== document.defaultView.top) {
          return false;
        }

        return true;
      };

      var insertScript = function() {
        var script = document.createElement('script');
        script.src = 'https://travelbar.tools/static/travelBar.lite.min.js#tbr=true';

        var _script = document.querySelector('script');
        if (_script) {
          initMessaging();
          _script.parentNode.insertBefore(script, _script);
        }
      };

      if (canInject()) {
        insertScript();
      }
    })();
  }, function isAvailable(initData) {
    "use strict";
    var preference = initData.getPreference;

    if (!preference.hasAviaBar) {
      return false;
    }

    if (!preference.aviaBarEnabled) {
      return false;
    }

    return true;
  }, function syncIsAvailable() {
    "use strict";
    if (mono.isIframe()) {
      return false;
    }

    var list = [
      '*://*.ozon.travel/*',
      '*://*.onetwotrip.com/*',

      '*://*.skyscanner.*/*',

      '*://*.aeroflot.ru/*',
      '*://*.momondo.*/*',
      '*://*.anywayanyday.com/*',
      '*://*.svyaznoy.travel/*',
      '*://avia.tickets.ru/*',
      '*://*.s7.ru/*',
      '*://*.kupibilet.ru/*',
      '*://*.trip.ru/*',
      '*://*.sindbad.ru/*',
      '*://*.aviakassa.ru/*',
      '*://*.aviakassa.com/*',
      '*://*.biletix.ru/*',
      '*://*.utair.ru/*',

      '*://*.kayak.*/*',
      '*://*.orbitz.com/*',
      '*://*.travelocity.com/*',
      '*://*.travelocity.ca/*',
      '*://*.expedia.*/*',
      '*://*.expedia-cn.com/*',
      '*://*.priceline.com/*',

      '*://booking.airasia.com/*',
      '*://*.ryanair.com/*',

      '*://*.booking.*/*',
      '*://*.agoda.*/*',
      '*://*.hotels.com/*',
      '*://*.ostrovok.ru/*',
      '*://*.travel.ru/*',
      '*://*.oktogo.ru/*',
      '*://*.roomguru.ru/*',
      '*://*.tripadvisor.ru/*',
      '*://*.hilton.ru/*',
      '*://*.hilton.com/*',
      '*://*.marriott.com/*',
      '*://*.hostelworld.com/*',
      '*://*.tiket.com/*',
      '*://*.hotelsclick.com/*',
      '*://*.hotelscombined.com/*',

      '*://*.avis.*/*',
      '*://*.budget.com/*',
      '*://*.wizzair.com/*',
      '*://*.emirates.com/*',
      '*://*.delta.com/*',
      "*://*.hertz.com/*",
      "*://*.europcar.com/*"
    ];

    for (var i = 0, item; item = list[i]; i++) {
      var re = new RegExp(mono.urlPatternToStrRe(item));
      if (re.test(location.protocol + '//' + location.hostname)) {
        mono.global.aviaBarProfile = item;
        mono.global.exAviaBar = true;
        return true;
      }
    }

    return false;
  });
  (typeof mono === 'undefined') && (mono = {
    loadModule: function() {
      this.loadModuleStack.push(arguments);
    },
    loadModuleStack: []
  });

  mono.loadModule('vimeo', function(moduleName, initData) {
    "use strict";

    var language = initData.getLanguage;
    var preference = initData.getPreference;
    var moduleState = preference.moduleVimeo ? 1 : 0;
    var iframe = mono.isIframe();

    mono.onMessage.addListener(function(message, cb) {
      if (message.action === 'getModuleInfo') {
        if (message.url !== location.href) return;
        return cb({
          state: moduleState,
          moduleName: moduleName
        });
      }
      if (message.action === 'changeState') {
        if (moduleName !== message.moduleName) {
          return;
        }
        return vimeo.changeState(message.state);
      }
    });

    if (moduleState) {
      mono.asyncCall(function() {
        vimeo.run();
      });
    }

    var vimeo = {
      panelId: 'savefrom__vimeo_links',
      btnBox: null,
      clipId: null,
      timer: null,
      btnPrefix: 'sd_ld_bnt_',
      popupIsShow: false,
      dlBtnClassName: 'sf-dl-btn',
      currentMenu: null,
      linkCache: {},

      run: function() {
        moduleState = 1;
        if (iframe) {
          vimeo.clipId = vimeo.getFrameClipId();
          if (vimeo.clipId) {
            return vimeo.appendIframeButtons();
          } else {
            iframe = false;
          }
        }

        this.videoFeed.injectStyle();

        if (SaveFrom_Utils.mutationWatcher.isAvailable()) {
          this.mutationMode.enable();
        }
      },

      changeState: function(state) {
        if (iframe) {
          return;
        }

        moduleState = state;

        vimeo.videoFeed.disable();

        vimeo.rmAllBtn();

        vimeo.mutationMode.stop();

        if (state) {
          vimeo.run();
        }
      },

      hideMenu: function() {
        if (vimeo.currentMenu) {
          vimeo.currentMenu.hide();
          vimeo.currentMenu = null;
        }
      },

      getFrameClipId: function() {
        var frameClipId = document.location.href.match(/player\.vimeo\.com\/video\/([\w\-]+)/i);
        frameClipId = frameClipId && frameClipId[1];
        if (frameClipId) {
          return frameClipId;
        }
      },

      getBrowserVideoData: function(container, id) {
        var btnParent = container.querySelector('.uploaded_on');
        if (!btnParent) {
          btnParent = container.querySelector('#info .meta .stats');
        }
        if (!btnParent) {
          return null;
        }
        if (id) {
          id = id.match(/([0-9]+)$/);
          id = id && id[1];
        }
        if (!id) {
          var firstLink = container.querySelector('a.js-title') || container.querySelector('a');
          if (!firstLink) {
            return;
          }
          var url = firstLink.getAttribute('href');
          if (!url) {
            return;
          }
          id = url.match(/\/([0-9]+)$/);
          id = id && id[1];
        }
        if (!id) {
          return;
        }
        return {
          id: id,
          parent: btnParent,
          style: 1
        };
      },

      getVideoId: function(container) {
        container = container || document;
        var id = null;
        var player;

        player = container.querySelector('.player[data-clip-id]');
        if (player) {
          return player.dataset.clipId;
        }

        player = container.querySelector('.player[data-fallback-url]');
        if (player) {
          var fallbackUrl = player.dataset.fallbackUrl || '';
          fallbackUrl = fallbackUrl.match(/video\/([0-9]+)\//);
          if (fallbackUrl) {
            return fallbackUrl[1];
          }
        }

        player = container.querySelector('div.player_wrapper > div.faux_player[data-clip_id]');
        if (player) {
          id = player.dataset.clip_id;
          if (id) {
            return id;
          }
        }
      },

      onBtnClick: function(videoData, e) {
        e.stopPropagation();
        e.preventDefault();
        var id = videoData.id;

        if (!id) {
          var container = null;
          if (videoData.playerContainer) {
            container = mono.getParent(videoData.parent, videoData.playerContainer);
          }
          id = vimeo.getVideoId(container);
        }

        if (vimeo.currentMenu && vimeo.currentMenu.isShow) {
          vimeo.hideMenu();
          return;
        }

        var links = language.download + ' ...';
        var details = {};
        if (videoData.style === 4) {
          details.offsetTop = 20;
        }

        var isMobile = this.dataset.sfMobile > 0;

        var menu;
        if (!isMobile) {
          menu = vimeo.currentMenu = SaveFrom_Utils.popupMenu.quickInsert(this, links, 'sf-popupMenu', details)
        } else {
          menu = vimeo.currentMenu = SaveFrom_Utils.mobileLightBox.show(links)
        }

        var onResponse = function(response) {
          if (response && response.links) {
            vimeo.linkCache[id] = response;
            var menuLinks = SaveFrom_Utils.popupMenu.prepareLinks.vimeo(response.links, response.title);
            menu.update(menuLinks);
          } else {
            menu.update(language.noLinksFound);
          }
        };

        var fromCache = vimeo.linkCache[id];
        if (fromCache) {
          onResponse(fromCache);
        } else {
          mono.sendMessagePromise({
            action: 'getVimeoLinks',
            extVideoId: id,
            url: location.href
          }).catch(function(err) {
            mono.error(err);
          }).then(onResponse);
        }
      },

      rmAllBtn: function() {
        ['sfSkip'].forEach(function(attr) {
          var dataAttr = mono.dataAttr2Selector(attr);
          var dataAttrList = document.querySelectorAll('[' + dataAttr + ']');
          for (var i = 0, item; item = dataAttrList[i]; i++) {
            item.removeAttribute(dataAttr);
          }
        });

        var btnList = document.querySelectorAll('.' + vimeo.dlBtnClassName);
        for (var i = 0, item; item = btnList[i]; i++) {
          if (item.dataset.sfType === '1' || item.dataset.sfType === '3') {
            item = item.parentNode;
          }
          item.parentNode.removeChild(item);
        }
        vimeo.videoFeed.rmBtn();

        vimeo.hideMenu();
      },

      appendBtn: function(videoData) {
        var box = videoData.parent;

        var exBtn = box.querySelector('.' + vimeo.dlBtnClassName);
        if (exBtn) {
          if (!exBtn.dataset.sfId && videoData.style !== 6) {
            return;
          }
          exBtn.parentNode.removeChild(exBtn);
          exBtn = null;
        }

        var btn;
        if (videoData.style === 1) {
          btn = mono.create('a', {
            text: language.download,
            class: [vimeo.dlBtnClassName, 'sf-style-1'],
            style: {
              display: 'inline'
            },
            data: {
              sfId: videoData.id,
              sfType: videoData.style
            },
            href: '#' + videoData.id
          });
        } else
        if (videoData.style === 2) {
          btn = mono.create('button', {
            text: language.download,
            class: [vimeo.dlBtnClassName, 'btn', 'iconify_down_b'],
            data: {
              sfId: videoData.id,
              sfType: videoData.style
            }
          });
        } else
        if (videoData.style === 5) {
          btn = mono.create('button', {
            class: [vimeo.dlBtnClassName, 'sf-type-5'],
            data: {
              sfId: videoData.id,
              sfType: videoData.style
            },
            append: [
              mono.create(SaveFrom_Utils.svg.getSvg('download', '#ffffff'), {
                style: {
                  display: 'inline-block',
                  width: '16px',
                  height: '16px',
                  verticalAlign: 'text-bottom',
                  marginRight: '.625rem'
                }
              }),
              mono.create('span', {
                style: {
                  marginLeft: 0
                },
                text: language.download
              })
            ]
          });
        } else
        if (videoData.style === 7) {
          btn = mono.create('button', {
            class: [vimeo.dlBtnClassName, 'sf-type-7'],
            data: {
              sfId: videoData.id,
              sfType: videoData.style
            },
            append: [
              mono.create(SaveFrom_Utils.svg.getSvg('download', '#ffffff'), {
                style: {
                  display: 'inline-block',
                  width: '16px',
                  height: '16px',
                  verticalAlign: 'text-bottom',
                  marginRight: '.625rem'
                }
              }),
              mono.create('span', {
                style: {
                  marginLeft: 0
                },
                text: language.download
              })
            ]
          });
        } else
        if (videoData.style === 3) {
          btn = mono.create('button', {
            class: [vimeo.dlBtnClassName, 'iris_btn', 'iris_btn-switch'],
            data: {
              sfId: videoData.id,
              sfType: videoData.style
            },
            append: [
              mono.create(SaveFrom_Utils.svg.getSvg('download', '#00adef'), {
                style: {
                  display: 'inline-block',
                  width: '16px',
                  height: '16px',
                  verticalAlign: 'text-bottom',
                  marginRight: '.625rem'
                }
              }),
              mono.create('span', {
                class: 'iris_btn-content',
                style: {
                  marginLeft: 0
                },
                text: language.download
              })
            ]
          });
        } else
        if (videoData.style === 4) {
          btn = mono.create('i', {
            class: [vimeo.dlBtnClassName, 'sf-style-4'],
            data: {
              sfId: videoData.id,
              sfType: videoData.style
            },
            style: {
              display: 'inline-block',
              border: '1px solid #F8F8F8',
              width: '20px',
              height: '20px',
              lineHeight: 0,
              cursor: 'pointer',
              marginLeft: '10px',
              verticalAlign: 'middle'
            },
            append: mono.create('style', {
              text: mono.style2Text([{
                selector: '.' + vimeo.dlBtnClassName + '.sf-style-4',
                style: {
                  background: 'url(' + SaveFrom_Utils.svg.getSrc('download', '#777777') + ') center no-repeat #F8F8F8',
                  backgroundSize: '12px'
                }
              }, {
                selector: '.' + vimeo.dlBtnClassName + '.sf-style-4:hover',
                style: {
                  background: 'url(' + SaveFrom_Utils.svg.getSrc('download', '#00B75A') + ') center no-repeat #F8F8F8',
                  backgroundSize: '12px'
                }
              }, {
                selector: '.' + vimeo.dlBtnClassName + '.sf-style-4:active',
                style: {
                  outline: 0,
                  boxShadow: 'inset 0 3px 5px rgba(0, 0, 0, 0.125)'
                }
              }])
            })
          });

          if (mono.isOpera) {
            btn.style.background = '#F8F8F8';
            btn.appendChild(mono.create('img', {
              src: SaveFrom_Utils.svg.getSrc('download', '#777777'),
              style: {
                width: '12px',
                height: '12px',
                margin: '4px',
                backgroundColor: '#F8F8F8'
              }
            }));
          }
        } else
        if (videoData.style === 6) {
          btn = mono.create('button', {
            class: [vimeo.dlBtnClassName, 'btn', 'btn_sm', 'btn_blue_o'],
            data: {
              sfId: videoData.id,
              sfType: videoData.style,
              sfMobile: 1
            },
            style: {
              marginLeft: '8px'
            },
            append: [
              mono.create(SaveFrom_Utils.svg.getSvg('download', '#00adef'), {
                style: {
                  display: 'inline-block',
                  width: '12px',
                  height: '12px',
                  verticalAlign: 'text-bottom',
                  marginRight: '4px'
                }
              }),
              mono.create('span', {
                class: 'btn_text',
                style: {
                  marginLeft: 0
                },
                text: language.download
              })
            ]
          });
        }

        btn.addEventListener('click', vimeo.onBtnClick.bind(btn, videoData));

        if (videoData.style === 1) {
          btn = mono.create('span', {
            append: [
              btn,
              ' | '
            ]
          });
        }

        if (videoData.style === 3) {
          btn = mono.create('div', {
            class: 'clip_info-user_actions',
            append: [
              btn
            ]
          });
        }

        if (videoData.style === 1 || videoData.style === 2 || videoData.style === 6) {
          var firstChild = box.firstChild;
          if (firstChild) {
            box.insertBefore(btn, firstChild);
          } else {
            box.appendChild(btn);
          }
        } else {
          box.appendChild(btn);
        }
      },

      playerStateChangeObserver: null,
      observeVideoUi: function(btnObj, node) {
        var playerMenu = node;
        if (playerMenu) {
          var hideBtnTimer = null;
          var controlsRe = /(\s|^)with-controls(\s|$)/;
          if (this.playerStateChangeObserver) {
            this.playerStateChangeObserver.stop();
          }
          this.playerStateChangeObserver = SaveFrom_Utils.mutationAttrWatcher.run({
            attr: 'class',
            target: playerMenu,
            callback: function(summaryList) {
              var summary = summaryList[0];
              var showBefore = !controlsRe.test(summary.oldValue);
              var showAfret = !controlsRe.test(summary.value);
              if (!showBefore && showAfret) {
                clearTimeout(hideBtnTimer);
                hideBtnTimer = setTimeout(function() {
                  if (!btnObj.lockHide) {
                    btnObj.container.classList.add('sf-hide-ui');
                  }
                }, 100);
              } else
              if (showBefore && !showAfret) {
                clearTimeout(hideBtnTimer);
                btnObj.container.classList.remove('sf-hide-ui');
              }
            }
          });
        }
      },

      appendIframeButtons: function() {
        var _this = this;
        var btnObj = SaveFrom_Utils.frameMenu.getBtn({
          quickBtnStyleObj: {
            display: 'inline-block',
            border: 0,
            borderRadius: '.3em',
            cursor: 'pointer',
            position: 'relative',
            padding: '6px 8px'
          },
          quickBtnCssStyle: {
            backgroundColor: 'rgba(23,35,34,.75)'
          },
          quickBtnOverCssStyle: {
            backgroundColor: 'rgb(0, 173, 239)'
          },
          nodeCssStyle: {
            display: 'none'
          },
          singleBtn: true,
          btnId: _this.panelId,
          containerStyle: {
            left: '10px',
            top: '10px'
          },
          quickBtnIcon: mono.create(SaveFrom_Utils.svg.getSvg('download', '#ffffff'), {
            style: {
              display: 'inline-block',
              width: '16px',
              height: '16px',
              verticalAlign: 'middle'
            }
          }),
          on: [
            ['click', function(e) {
              e.preventDefault();
              e.stopPropagation();

              if (_this.currentMenu && _this.currentMenu.isShow) {
                _this.hideMenu();
                return;
              }

              var id = _this.clipId;
              var fromCache = _this.linkCache[id];
              var links = language.download + ' ...';
              if (fromCache) {
                links = SaveFrom_Utils.popupMenu.prepareLinks.vimeo(fromCache.links, fromCache.title);
              }

              var menu = _this.currentMenu = SaveFrom_Utils.frameMenu.getMenu(this, links, 'sf-frame-menu', {
                leftMenuPos: true,
                container: btnObj.container,
                onShow: function() {
                  btnObj.node.classList.add('sf-over');
                },
                onHide: function() {
                  _this.currentMenu = null;
                  btnObj.node.classList.remove('sf-over');
                }
              });

              if (!fromCache) {
                _this.getLinksFromPage(function(links, title) {
                  var menuLinks = language.noLinksFound;
                  if (links) {
                    _this.linkCache[id] = {
                      links: links,
                      title: title
                    };
                    menuLinks = SaveFrom_Utils.popupMenu.prepareLinks.vimeo(links, title);
                  }
                  menu.update(menuLinks);
                });
              }
            }],
            ['mousedown', function(e) {
              e.stopPropagation();
              if (e.button === 2) {
                if (observer) {
                  observer.stop();
                  observer = null;
                }

                _this.hideMenu();

                if (btnObj.container.parentNode) {
                  btnObj.container.parentNode.removeChild(btnObj.container);
                }
              }
            }]
          ]
        });

        btnObj.quickBtn.title = language.download;

        btnObj.container = mono.create('div', {
          class: 'sf-btn-ctr',
          append: btnObj.node
        });

        mono.on(btnObj.container, 'mouseenter', function() {
          btnObj.lockHide = true;
        });

        mono.on(btnObj.container, 'mouseleave', function() {
          btnObj.lockHide = false;
        });

        btnObj.node.appendChild(mono.create('style', {
          text: mono.style2Text([{
            selector: [
              'body:hover .sf-btn-ctr:not(.sf-hide-ui) #' + _this.panelId,
              'body:hover .sf-btn-ctr:not(.sf-hide-ui) .sf-frame-menu'
            ],
            style: {
              display: 'block'
            }
          }])
        }));

        document.body.appendChild(btnObj.container);


        var observer = SaveFrom_Utils.mutationWatcher.run({
          callback: function(summaryList) {
            var summary = summaryList[0];
            var node = summary.added[0];
            if (node) {
              _this.observeVideoUi(btnObj, node);
              setTimeout(function() {
                observer.stop();
                observer = null;
              }, 0);
            }
          },
          queries: [{
            css: '#player .captions[aria-live="assertive"]',
            is: 'added'
          }]
        });
      },

      getLinksFromPage: function(cb) {
        var reList = [
          /"video":{/,
          /"request":{/,
          /"files":/
        ];
        var scriptList = mono.getPageScript(document.body.innerHTML, reList);

        var config = null;
        scriptList.some(function(script) {
          var jsonList = mono.findJson(script, reList);
          return jsonList.some(function(json) {
            if (json.video && json.request && json.request.files) {
              config = json;
              return true;
            }
          });
        });
        var request = null;
        var links = null;
        var title = null;

        var onResponse = function(response) {
          if (response) {
            links = response.links || null;
            title = response.title || null;
          }

          return cb(links, title);
        };

        if (config) {
          request = {
            action: 'getVimeoLinksFromConfig',
            config: config
          };

          return mono.sendMessage(request, onResponse);
        } else {
          request = {
            action: 'getVimeoLinks',
            extVideoId: vimeo.clipId
          };

          return mono.sendMessage(request, onResponse);
        }
      },

      videoFeed: {
        btnClassName: 'sf-feed-dl-btn',
        style: null,
        onClick: function(e) {
          e.preventDefault();
          e.stopPropagation();

          var id = this.dataset.sfId;
          var isCouchMode = this.dataset.sfCouchMode > 0;

          if (vimeo.currentMenu && vimeo.currentMenu.isShow) {
            vimeo.hideMenu();
            return;
          }

          var fromCache = vimeo.linkCache[id];
          var links = language.download + ' ...';
          if (fromCache) {
            links = SaveFrom_Utils.popupMenu.prepareLinks.vimeo(fromCache.links, fromCache.title);
          }

          var menu = vimeo.currentMenu = SaveFrom_Utils.popupMenu.quickInsert(this, links, 'sf-popupMenu');

          if (fromCache) {
            return;
          }

          var url = null;
          if (/"url"/.test(id)) {
            url = JSON.parse(id).url;
            id = null;
          }

          mono.sendMessage({
            action: 'getVimeoLinks',
            extVideoId: id,
            url: url
          }, function(response) {
            var menuLinks = null;
            if (response.links) {
              vimeo.linkCache[id] = response;
              menuLinks = SaveFrom_Utils.popupMenu.prepareLinks.vimeo(response.links, response.title);
            } else {
              menuLinks = language.noLinksFound;
            }
            menu.update(menuLinks);
          });
        },
        getBtn: function(details) {
          var btn = mono.create('i', {
            class: details.classList,
            data: {
              sfId: details.id,
              sfCouchMode: details.isCouchMode ? 1 : 0
            },
            on: ['click', this.onClick]
          });

          if (mono.isOpera) {
            btn.style.background = '#F8F8F8';
            btn.appendChild(mono.create('img', {
              src: SaveFrom_Utils.svg.getSrc('download', '#777777'),
              style: {
                width: '12px',
                height: '12px',
                margin: '4px',
                backgroundColor: '#F8F8F8'
              }
            }));
          }

          return btn;
        },
        onImgOver2: function(e) {
          var link = this.parentNode;

          var parent;
          var id;

          if (link.tagName !== 'A') {
            return;
          }

          var href = link.getAttribute('href');
          if (!href) {
            return;
          }

          id = href.match(/^\/(\d+)$/);
          id = id && id[1];

          if (!id) {
            return;
          }

          parent = link.parentNode;
          if (!parent || !parent.classList.contains('contextclip-img')) {
            return;
          }

          if (parent.dataset.sfBtn > 0) {
            return;
          }
          parent.dataset.sfBtn = '1';

          var _this = vimeo.videoFeed;

          var classList = [_this.btnClassName, 'sf-type1-btn'];

          link.appendChild(vimeo.videoFeed.getBtn({
            id: id,
            classList: classList
          }));

          link = null;
          parent = null;
        },
        onImgOver: function(e) {
          var link = this.parentNode;

          var parent;
          var id;

          if (mono.matches(this, 'a.contextclip-img-thumb')) {
            parent = this;
            link = this;
            var m = /\/([0-9]+)/.exec(this.href);
            if (m) {
              id = m[1];
            }
          }

          if (!id) {
            if (mono.matches(this, 'div.iris_video-vital') || mono.matches(this, 'li.clip_thumbnail')) {
              link = this.querySelector('.iris_thumbnail');
              parent = this;
              var linkNode = this.querySelector('a.iris_link-box');
              if (linkNode) {
                var url = linkNode.href;
                id = url.match(/\/([0-9]+)/);
                id = id && id[1];

                if (!id && url) {
                  id = JSON.stringify({
                    'url': url
                  });
                }
              }
            }
          }

          if (!id && link.tagName == 'LI') {
            id = link.dataset.resultId;
            if (id && id.substr(0, 5) === 'clip_') {
              id = id.substr(5);
              parent = link;
              link = this.querySelector('.thumbnail_wrapper');
            } else {
              return;
            }
          }

          if (!id) {
            if (link.tagName !== 'A') {
              return;
            }
            id = link.dataset.clipId;

            parent = link.parentNode;
            if (!parent) {
              return;
            }
          }

          var isCouchMode = false;
          if (!id) {
            id = parent.id;
            isCouchMode = id.substr(0, 7) === 'item_id' && parent.classList.contains('clip');
            if (!isCouchMode && id.substr(0, 4) !== 'clip') {
              id = undefined;
            }
            if (!id && parent.tagName === 'ARTICLE' && parent.classList.contains('clip_item')) {
              id = link.getAttribute('href');
            }
            if (!id) {
              return;
            }

            id = id.match(/([0-9]+)$/);
            if (id) {
              id = id[1];
            }
          }

          var hasBtn = parent.dataset.sfBtn;
          if (hasBtn) {
            return;
          }
          parent.dataset.sfBtn = '1';

          var _this = vimeo.videoFeed;

          var classList = [_this.btnClassName];
          if (this.classList.contains('thumbnail_lg_wide')) {
            classList.push('sf-type1-btn');
          }

          if (this.classList.contains('contextclip-img-thumb')) {
            classList.push('sf-type4-btn');
          }

          if (this.classList.contains('clip_thumbnail') || this.classList.contains('iris_video-vital')) {
            classList.push('sf-type3-btn');
          }

          var ol = parent.parentNode;
          if (ol && ol.id === 'clips') {
            classList.push('sf-type1-btn');
            // classList.push('sf-type2-btn');
          }
          ol = null;

          if (isCouchMode) {
            classList.push('sf-type1-btn');
          }

          if (parent.classList.contains('promo_clip') && classList.length === 1) {
            classList.push('sf-type1-btn');
            // classList.push('sf-type2-btn');
          }

          link.appendChild(vimeo.videoFeed.getBtn({
            id: id,
            classList: classList,
            isCouchMode: isCouchMode
          }));

          link = null;
          parent = null;
        },
        injectStyle: function() {
          if (this.style) {
            !this.style.parentNode && document.head.appendChild(this.style);
            return;
          }

          this.style = mono.create('style', {
            text: mono.style2Text([{
              selector: [
                '.sf-dl-btn.sf-type-5',
                '.sf-dl-btn.sf-type-7'
              ],
              style: {
                color: '#fff',
                borderColor: '#00adef',
                backgroundColor: '#00adef',
                minWidth: '4.25rem',
                minHeight: '2.1rem',
                padding: '0 .625rem',
                lineHeight: '2.14286',
                fontSize: '.875rem',
                width: 'auto',
                position: 'relative',
                margin: 0,
                fontWeight: 700,
                borderWidth: '.0625rem',
                borderStyle: 'solid',
                borderRadius: '.1875rem',
                letterSpacing: '.1px',
                transition: 'all .1s ease-in-out',
                cursor: 'pointer',
                marginLeft: '.5rem'
              }
            }, {
              selector: [
                '.sf-dl-btn.sf-type-5',
                '.sf-dl-btn.sf-type-7'
              ],
              style: {
                color: '#fff',
                borderColor: '#00adef',
                backgroundColor: '#00adef',
                minWidth: '4.25rem',
                minHeight: '2.1rem',
                padding: '0 .625rem',
                lineHeight: '2.14286',
                fontSize: '13px',
                width: 'auto',
                position: 'relative',
                margin: 0,
                fontWeight: 700,
                borderWidth: '.0625rem',
                borderStyle: 'solid',
                borderRadius: '.1875rem',
                letterSpacing: '.1px',
                transition: 'all .1s ease-in-out',
                cursor: 'pointer',
                marginLeft: '.5rem'
              }
            }, {
              selector: [
                '.sf-dl-btn.sf-type-5:hover',
                '.sf-dl-btn.sf-type-7:hover'
              ],
              style: {
                color: '#fff',
                borderColor: '#08c',
                backgroundColor: '#08c'
              }
            }, {
              selector: [
                'a > .sf-feed-dl-btn',
                'a .sf-feed-dl-btn.sf-type3-btn',
                'a > .sf-feed-dl-btn.sf-type4-btn'
              ],
              style: {
                display: 'none',
                border: '1px solid #F8F8F8',
                width: '20px',
                height: '20px',
                padding: 0,
                position: 'absolute',
                background: 'url(' + SaveFrom_Utils.svg.getSrc('download', '#777777') + ') center no-repeat #F8F8F8',
                backgroundSize: '12px',
                top: 'auto',
                left: 'auto',
                lineHeight: 0
              }
            }, {
              selector: [
                'a > .sf-feed-dl-btn.sf-type4-btn'
              ],
              style: {
                top: 0,
                left: 0
              }
            }, {
              selector: [
                'a > .sf-feed-dl-btn.sf-type1-btn',
                'a > div > .sf-feed-dl-btn.sf-type3-btn'
              ],
              style: {
                top: 0
              }
            }, {
              selector: [
                'a > .sf-feed-dl-btn.sf-type2-btn'
              ],
              style: {
                opacity: 0.5
              }
            }, {
              selector: [
                'a > div > .sf-feed-dl-btn.sf-type3-btn'
              ],
              style: {
                zIndex: 10
              }
            }, {
              selector: [
                'a > .sf-feed-dl-btn:hover',
                'a > div > .sf-feed-dl-btn.sf-type3-btn:hover'
              ],
              style: {
                background: 'url(' + SaveFrom_Utils.svg.getSrc('download', '#00B75A') + ') center no-repeat #F8F8F8',
                backgroundSize: '12px'
              }
            }, {
              selector: [
                'a > .sf-feed-dl-btn.sf-type2-btn:hover'
              ],
              style: {
                opacity: 0.8
              }
            }, {
              selector: [
                'a > .sf-feed-dl-btn:active',
                'a > div > .sf-feed-dl-btn.sf-type3-btn:active'
              ],
              style: {
                outline: 0,
                boxShadow: 'inset 0 3px 5px rgba(0, 0, 0, 0.125)'
              }
            }, {
              selector: [
                'a:hover > .sf-feed-dl-btn',
                'a:hover > div > .sf-feed-dl-btn.sf-type3-btn'
              ],
              style: {
                display: 'block'
              }
            }])
          });

          document.head.appendChild(this.style);
        },
        disable: function() {
          if (this.style) {
            this.style.parentNode && this.style.parentNode.removeChild(this.style);
          }
        },
        rmBtn: function() {
          var btnList = document.querySelectorAll('.sf-feed-dl-btn');
          for (var i = 0, item; item = btnList[i]; i++) {
            item.parentNode.removeChild(item);
          }

          var dataAttr = mono.dataAttr2Selector('sfBtn');
          var dataAttrList = document.querySelectorAll('[' + dataAttr + ']');
          for (i = 0, item; item = dataAttrList[i]; i++) {
            item.removeAttribute(dataAttr);
          }
        }
      },
      mutationMode: {
        observer: null,
        stop: function() {
          if (this.observer) {
            this.observer.stop();
          }
        },
        wrapOnImgOver: function() {
          if (!moduleState) {
            return;
          }
          vimeo.videoFeed.onImgOver.apply(this, arguments);
        },
        wrapOnImgOver2: function() {
          if (!moduleState) {
            return;
          }
          vimeo.videoFeed.onImgOver2.apply(this, arguments);
        },
        enable: function() {
          if (this.observer) {
            return this.observer.start();
          }

          this.observer = SaveFrom_Utils.mutationWatcher.run({
            callback: function(summaryList) {
              var summary, n, i, node, styleIndex, videoId;

              summary = summaryList[0];
              for (n = 0; node = summary.added[n]; n++) {
                vimeo.hideMenu();
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                styleIndex = 2;
                vimeo.appendBtn({
                  id: '',
                  parent: node,
                  style: styleIndex,
                  playerContainer: '#clip'
                });
              }

              summary = summaryList[1];
              for (n = 0; node = summary.added[n]; n++) {
                vimeo.hideMenu();
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                var stats = node.querySelector('.stats') || node.querySelector('.time');
                if (!stats) {
                  continue;
                }

                styleIndex = 1;
                vimeo.appendBtn({
                  id: '',
                  parent: stats,
                  style: styleIndex,
                  playerContainer: '#channel_clip_container'
                });
              }

              summary = summaryList[2];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                if (node.id.substr(0, 5) !== 'clip_') {
                  continue;
                }

                var videoData = vimeo.getBrowserVideoData(node, node.id);
                if (!videoData) {
                  continue;
                }

                vimeo.appendBtn(videoData);
              }

              summary = summaryList[3];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                mono.one(node, 'mouseenter', vimeo.mutationMode.wrapOnImgOver);
              }

              summary = summaryList[4];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                var parent = mono.getParentByClass(node, 'clip_thumbnail');

                mono.one(parent, 'mouseenter', vimeo.mutationMode.wrapOnImgOver);
              }

              summary = summaryList[5];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                var parent = mono.getParentByClass(node, 'iris_video-vital');

                mono.one(parent, 'mouseenter', vimeo.mutationMode.wrapOnImgOver);
              }

              summary = summaryList[6];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                var parent = mono.getParentByClass(node, 'contextclip-img-thumb');

                mono.one(parent, 'mouseenter', vimeo.mutationMode.wrapOnImgOver);
              }

              summary = summaryList[7];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                vimeo.hideMenu();

                var wrapper = mono.getParent(node, '.clip_info-wrapper');
                if (!wrapper) {
                  continue;
                }

                var clipInfoActions = wrapper.querySelector('.clip_info-actions');
                if (!clipInfoActions) {
                  continue;
                }

                styleIndex = 3;
                vimeo.appendBtn({
                  id: '',
                  parent: clipInfoActions,
                  style: styleIndex,
                  playerContainer: '.clip_main'
                });
              }

              summary = summaryList[8];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                vimeo.hideMenu();

                var wrapper = mono.getParent(node, '.clip_main-content');
                if (!wrapper) {
                  continue;
                }

                styleIndex = 5;
                vimeo.appendBtn({
                  id: '',
                  parent: node,
                  style: styleIndex,
                  playerContainer: '.clip_main'
                });
              }

              summary = summaryList[9];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                mono.one(node, 'mouseenter', vimeo.mutationMode.wrapOnImgOver2);
              }

              summary = summaryList[10];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                styleIndex = 4;
                vimeo.appendBtn({
                  id: '',
                  parent: node,
                  style: styleIndex,
                  playerContainer: '.clip'
                });
              }

              summary = summaryList[11];
              for (n = 0; node = summary.added[n]; n++) {
                styleIndex = 6;
                vimeo.appendBtn({
                  id: '',
                  parent: node,
                  style: styleIndex,
                  playerContainer: '.clip_wrapper'
                });
              }

              summary = summaryList[12];
              for (n = 0; node = summary.added[n]; n++) {
                styleIndex = 7;

                vimeo.appendBtn({
                  id: '',
                  parent: node,
                  style: styleIndex,
                  playerContainer: '#main'
                });
              }
            },
            queries: [{
                css: '#clip #info #tools',
                is: 'added'
              },
              {
                css: '#channel_clip_container #info .meta',
                is: 'added'
              },
              {
                css: '#browse_content ol.browse_videos_videos > li',
                is: 'added'
              },
              {
                css: 'img.thumbnail',
                is: 'added'
              },
              {
                css: '.clip_thumbnail .iris_thumbnail img',
                is: 'added'
              },
              {
                css: '.iris_video-vital .iris_thumbnail img',
                is: 'added'
              },
              {
                css: '.contextclip-img-thumb img',
                is: 'added'
              },
              {
                css: '.clip_main .clip_info a.js-user_link.iris_link-header',
                is: 'added'
              },
              {
                css: '.clip_main .clip_main-content div.clip_info-subline--inline',
                is: 'added'
              },
              {
                css: '.contextclip-img img',
                is: 'added'
              },
              {
                css: '.client_wrapper .clip header h1',
                is: 'added'
              },
              {
                css: '.clip_page .clip .meta_section_subinfo',
                is: 'added'
              },
              {
                css: '#main .clip_info-subline--inline',
                is: 'added'
              }
            ]
          });
        }
      }
    };

  }, null, function syncIsActive() {
    "use strict";

    if (mono.isSafari || mono.isGM) {
      var list = [
        '*://*.vimeo.com/*'
      ];

      var reStr = list.map(function(pattern) {
        return mono.urlPatternToStrRe(pattern);
      }).join('|');
      var re = new RegExp(reStr);

      if (!re.test(location.protocol + '//' + location.hostname)) {
        return false;
      }
    }

    return true;
  });
  (typeof mono === 'undefined') && (mono = {
    loadModule: function() {
      this.loadModuleStack.push(arguments);
    },
    loadModuleStack: []
  });

  mono.loadModule('vk', function(moduleName, initData) {
    "use strict";

    var language = initData.getLanguage;
    var preference = initData.getPreference;
    var moduleState = preference.moduleVkontakte ? 1 : 0;
    var allowDownloadMode = mono.isChrome || mono.isFirefox || (mono.isGM && mono.isTM);
    var Promise = mono.Promise;

    var iframe = mono.isIframe();
    var videoExt = false;

    if (iframe) {
      if (/\/video_ext\.php\?.+/.test(location.href)) {
        videoExt = true;
      } else
      if (/\/widget_comments\.php\?.+/.test(location.href)) {
        iframe = false;
      } else {
        return;
      }
    }

    mono.onMessage.addListener(function(message, cb) {
      if (message.action === 'getModuleInfo') {
        if (message.url !== location.href) return;
        return cb({
          state: moduleState,
          moduleName: moduleName
        });
      }
      if (message.action === 'changeState') {
        if (moduleName !== message.moduleName) {
          return;
        }
        return vk.changeState(message.state);
      }
      if (!moduleState) {
        return;
      }
      if (message.action === 'updateLinks') {
        updateLinks();
      }
      if (message.action === 'downloadMP3Files') {
        if (allowDownloadMode) {
          audio.downloadMP3Files();
        } else {
          audio.showListOfAudioFiles(false);
        }
      }
      if (message.action === 'downloadPlaylist') {
        audio.showListOfAudioFiles(true);
      }
      if (message.action === 'downloadPhotos') {
        photo.downloadPhoto();
      }
    });

    if (moduleState) {
      mono.asyncCall(function() {
        vk.run();
      });
    }

    var vk = {
      contextMenu: null,
      isMutation: false,
      run: function() {
        moduleState = 1;

        if (/m\.vk\.com/.test(location.hostname)) {
          return mVk.run();
        }

        if (videoExt) {
          video.addFrameBtn();
          return;
        }

        photo.injectStyle();

        if (SaveFrom_Utils.mutationWatcher.isAvailable()) {
          vk.isMutation = true;
          audio.addCustomStyle();
          vk.mutationMode.enable();
        }
      },
      changeState: function(state) {
        if (iframe) {
          return;
        }
        moduleState = state;
        removeDownloadLinks();
        audio.hideLinks();

        videoFeed.off();

        vk.hideMenu();

        photo.rmCurrentPhotoBtn();

        audio.rmBitrate();

        photo.rmPhotoAlbumDlBtn();

        vk.mutationMode.stop();

        if (state) {
          vk.run();
        }
      },
      hideMenu: function() {
        if (vk.contextMenu) {
          vk.contextMenu.hide();
          vk.contextMenu = null;
        }
      },
      mutationMode: {
        observer: null,
        stop: function() {
          if (this.observer) {
            this.observer.stop();
          }

          ['sfSkip'].forEach(function(attr) {
            var dataAttr = mono.dataAttr2Selector(attr);
            var dataAttrList = document.querySelectorAll('[' + dataAttr + ']');
            for (var i = 0, item; item = dataAttrList[i]; i++) {
              item.removeAttribute(dataAttr);
            }
          });
        },
        wrapNewAudioOnMouseOver: function() {
          if (!moduleState) {
            return;
          }
          audio.onNewMouseOver.apply(this, arguments);
        },
        wrapVideoFeedOnMouseOver: function() {
          if (!moduleState) {
            return;
          }
          videoFeed.onLinkHover.apply(this, arguments);
        },
        onVideoInsert: function(node) {
          var layer = SaveFrom_Utils.getParentById(node, 'mv_box');
          var player = video.getPlayerNode(layer);

          if (player) {
            video.getLinksFromPlayer(layer, player, video.newAppendButton.bind(video));
          } else {
            node.dataset.sfSkip = 0;
          }
        },
        onVideoChange: function(node) {
          var _this = this;
          if (!/video_box_wrap-?\d+_-?\d+/.test(node.id)) {
            _this.onVideoInsert(node);
          } else
          if (!node.sfWatch) {
            node.sfWatch = true;
            var sfArrtMutationWatcher = SaveFrom_Utils.mutationAttrWatcher.run({
              attr: 'id',
              target: node,
              callback: function() {
                _this.onVideoInsert(node);
              }
            });
            mono.onRemoveEvent(node, function() {
              sfArrtMutationWatcher.stop();
              node.sfWatch = false;
              node.dataset.sfSkip = 0;
            });
          } else {
            _this.onVideoInsert(node);
          }
        },
        enable: function() {
          var _this = this;
          if (this.observer) {
            return this.observer.start();
          }

          this.observer = SaveFrom_Utils.mutationWatcher.run({
            callback: function(summaryList) {
              var summary, n, i, node;

              summary = summaryList[0];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                mono.one(node, 'mouseenter', vk.mutationMode.wrapVideoFeedOnMouseOver);
              }

              summary = summaryList[1];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                _this.onVideoChange(node);
              }

              summary = summaryList[2];
              for (n = 0; node = summary.added[n]; n++) {
                node = node.parentNode;
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                _this.onVideoChange(node);
              }

              summary = summaryList[3];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                photo.addNewPhotoAlbumDlBtn(node);
              }

              summary = summaryList[4];
              for (n = 0; node = summary.added[n]; n++) {
                if (node.dataset.sfSkip > 0) {
                  continue;
                }
                node.dataset.sfSkip = '1';

                photo.addNewDlCurrentPhotoBtn(node);
              }

              for (i = 5; i < 8; i++) {
                summary = summaryList[i];
                for (n = 0; node = summary.added[n]; n++) {
                  if (node.dataset.sfSkip > 0) {
                    continue;
                  }
                  node.dataset.sfSkip = '1';

                  mono.one(node, 'mouseenter', vk.mutationMode.wrapNewAudioOnMouseOver);
                }
              }

              summary = summaryList[8];
              for (n = 0; node = summary.removed[n]; n++) {
                mono.onRemoveListener(node);
              }
            },
            queries: [{
                css: '.post_video_desc a.lnk',
                is: 'added'
              },

              {
                css: '#mv_box #mv_player_box > .video_box_wrap',
                is: 'added'
              },
              {
                css: '#mv_box #mv_player_box > .video_box_wrap > #video_player',
                is: 'added'
              },

              {
                css: '#photos_all_block',
                is: 'added'
              },

              {
                css: '.pv_photo_wrap .pv_img_area_wrap',
                is: 'added'
              },

              {
                css: '.audio_row',
                is: 'added'
              },
              {
                css: '.top_audio_player .top_audio_player_title',
                is: 'added'
              },
              {
                css: '.audio_page_player .audio_page_player_title_performer',
                is: 'added'
              },

              {
                css: '.' + mono.onRemoveClassName,
                is: 'removed'
              }
            ]
          });
        }
      }
    };

    var downloadLinkClassName = 'savefrom_vk_download';

    var updateLinks = function() {
      vk.changeState(0);
      vk.changeState(1);
    };

    var removeDownloadLinks = function() {
      var selector = 'a.' + downloadLinkClassName +
        ',div.' + downloadLinkClassName +
        ',span.' + downloadLinkClassName;

      audio.lastRow = null;

      var e = document.querySelectorAll(selector);
      for (var i = e.length - 1; i >= 0; i--) {
        if (audio.elIsHidden(e[i])) {
          e[i].parentNode.removeChild(e[i]);
        }
      }
    };

    var getFolderName = function() {
      var folderName = document.title;
      var sep = folderName.indexOf('|');
      if (sep !== -1) {
        folderName = folderName.substr(0, sep - 1);
      }

      return mono.fileName.modify(folderName);
    };

    var parseVkResponse = function(data) {
      var intval = function(e) {
        return e === !0 ? 1 : parseInt(e) || 0
      };

      var floatval = function(e) {
        return e === !0 ? 1 : parseFloat(e) || 0
      };

      var e = data.split('<!>');
      for (var o = e.length - 1; o >= 0; --o) {
        var n = e[o];
        if ("<!" == n.substr(0, 2)) {
          var a = n.indexOf(">"),
            i = n.substr(2, a - 2);
          switch (n = n.substr(a + 1), i) {
            case "json":
              var json = null;

              try {
                json = JSON.parse(n);
              } catch (e) {}

              e[o] = json;
              break;
            case "int":
              e[o] = intval(n);
              break;
            case "float":
              e[o] = floatval(n);
              break;
            case "bool":
              e[o] = intval(n) ? !0 : !1;
              break;
            case "null":
              e[o] = null;
              break;
            case "pageview_candidate":
              e.pop();
              break;
            case "debug":
              e.pop()
          }
        }
      }
      return e;
    };

    var rmEmTags = function(str) {
      var re = /<em>.*<\/em>/;
      if (re.test(str)) {
        str = str.replace(/<\/?em>/g, '');
      }
      return str;
    };


    ///////////////////////////////////////////////////////////////////
    //  AUDIO

    var audio = {
      audioElClassList: ['audio', 'audioRow', 'audioRowWall'],
      lastRow: null,
      className: downloadLinkClassName,
      cache: {},

      lastValidRequest: null,
      waitUntilUnblock: function(details) {
        var _this = this;
        var limit = 10;
        var interval = 15 * 1000;

        if (!_this.lastValidRequest) {
          return Promise.reject(new Error('Last valid request is empty!'));
        }

        var getData = function() {
          return new Promise(function(resolve) {
            setTimeout(resolve, interval);
          }).then(function() {
            if (details.abort) {
              throw new Error('Abort');
            }

            return mono.requestPromise(_this.lastValidRequest).then(function(response) {
              limit--;
              var list = parseVkResponse(response.body)[5];
              if (!list) {
                if (limit > 0) {
                  return getData();
                } else {
                  throw new Error('Can\'t request data');
                }
              }
            });
          });
        };
        return getData().then(function() {
          return new Promise(function(resolve) {
            setTimeout(resolve, 250);
          });
        });
      },

      needUnmask: function(idsArr) {
        var re = /audio_api_unavailable/;
        return idsArr.some(function(item) {
          if (re.test(item[2])) {
            return true;
          }
        });
      },

      unmaskUrlViaPlayer: (function() {
        var onReady = null;
        var findDecodeFn = function(modules) {
          return new Promise(function(resolve) {
            SaveFrom_Utils.bridge({
              args: [modules],
              func: function(modulesStr, cb) {
                try {
                  var modules = new Function([], 'return ' + modulesStr)();
                  modulesStr = null;

                  var unmaskFnId = null;
                  for (var index in modules) {
                    var fn = modules[index];
                    if (/\.audioUnmaskSource=/.test(fn)) {
                      unmaskFnId = index;
                      break;
                    }
                  }
                  if (unmaskFnId === null) {
                    throw new Error('Unmask fn is no found!');
                  }

                  var installed = {};
                  var loadModule = function(id) {
                    if (installed[id]) return installed[id].exports;
                    var module = installed[id] = {
                      exports: {},
                      id: id,
                      loaded: false
                    };
                    modules[id].call(module.exports, module, module.exports, loadModule);
                    module.loaded = true;
                    return module.exports
                  };

                  var result = loadModule(unmaskFnId);
                  if (!result.audioUnmaskSource) {
                    throw new Error('Unmask fn is no exists!');
                  }

                  window.sfUnmaskUrl = result.audioUnmaskSource;

                  cb(true);
                } catch (err) {
                  cb(false);
                }
              },
              cb: resolve
            });
          }).then(function(result) {
            if (!result) {
              throw new Error('Can\'t create unmask function!');
            }
          });
        };
        var loadPlayerJs = function(url) {
          return mono.requestPromise({
            url: url,
            localXHR: true
          }).then(function(respones) {
            var body = respones.body;

            var modules = '';
            var pos = body.indexOf('([function');
            if (pos !== -1) {
              modules = body.substr(pos);
            }

            if (pos === -1) {
              pos = body.indexOf('({0:function');
              if (pos !== -1) {
                modules = body.substr(pos);
              }
            }

            if (!modules) {
              throw new Error('Modules is not found!');
            }

            return modules;
          });
        };
        var getPlayerUrl = function() {
          var isMobile = /m\.vk\.com/.test(location.hostname);
          var scriptReList = null;
          if (isMobile) {
            scriptReList = [/\/js\/s_c\.js\?\d+/];
          } else {
            scriptReList = [
              /\/js\/al\/audioplayer\.js\?\d+/,
              /\/cmodules\/web\/audioplayer\.js\?\d+/
            ];
          }
          var scriptUrl = '';
          [].slice.call(document.querySelectorAll('script[src]')).some(function(node) {
            var url = node.src;
            return scriptReList.some(function(re) {
              if (re.test(url)) {
                scriptUrl = url;
                return true;
              }
            });
          });
          if (!scriptUrl) {
            return Promise.reject(new Error('Player url is not found!'));
          } else {
            return Promise.resolve(scriptUrl);
          }
        };
        return function(idsArr) {
          var needUnmask = audio.needUnmask(idsArr);
          if (!needUnmask) {
            return Promise.resolve(idsArr);
          }

          if (onReady === null) {
            onReady = getPlayerUrl().then(loadPlayerJs).then(findDecodeFn).then(function() {
              onReady = true;
            }).catch(function(err) {
              mono.debug('Unmask via player error!', err);
              onReady = false;
            });
          }

          if (typeof onReady === 'boolean') {
            return audio.unmaskUrl(idsArr);
          } else {
            return onReady.then(function() {
              return audio.unmaskUrl(idsArr);
            });
          }
        };
      })(),

      unmaskUrl: function(idsArr) {
        var needUnmask = audio.needUnmask(idsArr);
        var result;
        if (!needUnmask) {
          result = Promise.resolve(idsArr);
        } else {
          result = new Promise(function(resolve) {
            SaveFrom_Utils.bridge({
              args: [idsArr],
              func: function(idsArr, cb) {
                var aFail = false;
                var bFail = false;
                var unmaskUrl = function(url) {
                  var _url = '';
                  if (!aFail && window.sfUnmaskUrl) {
                    try {
                      _url = window.sfUnmaskUrl(url);
                    } catch (err) {
                      aFail = true;
                    }
                  }
                  if (!bFail && !_url && window.AudioPlayerFlash) {
                    try {
                      var r = {};
                      window.AudioPlayerFlash.prototype.setUrl.apply(r, [url]);
                      _url = r._url;
                    } catch (err) {
                      bFail = true;
                    }
                  }
                  if (typeof _url !== 'string') {
                    _url = '';
                  }
                  return _url;
                };
                idsArr.forEach(function(item) {
                  var url = unmaskUrl(item[2]);
                  if (url) {
                    item[2] = url;
                  }
                });
                cb(idsArr);
              },
              cb: resolve
            });
          }).then(function(_idsArr) {
            return _idsArr || idsArr;
          });
        }
        return result;
      },

      _getNewTrackListByIds: function(ids, details) {
        var _this = this;
        details = details || {};
        var limit = 10;
        var count = 0;
        var trackObj = {};
        var cache = _this.cache;

        var idsClone = ids.filter(function(id) {
          if (cache[id]) {
            trackObj[id] = cache[id];
            count++;
            return false;
          } else {
            return true;
          }
        });

        var partIds = [];
        while (idsClone.length) {
          partIds.push(idsClone.splice(0, limit));
        }
        var maxCount = ids.length;

        var promise = Promise.resolve();

        partIds.forEach(function(ids) {
          var requestIds = function() {
            if (details.abort) {
              throw new Error('Abort');
            }

            var requestDetails;
            return mono.requestPromise(requestDetails = {
              type: 'POST',
              headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'X-Requested-With': 'XMLHttpRequest'
              },
              data: mono.param({
                act: 'reload_audio',
                al: 1,
                ids: ids.join(',')
              }),
              url: '/al_audio.php',
              localXHR: true
            }).then(function(response) {
              var list = parseVkResponse(response.body)[5];
              if (!list) {
                throw new Error('Track list is not found!');
              } else {
                _this.lastValidRequest = requestDetails;

                list.forEach(function(track) {
                  var id = track[1] + '_' + track[0];
                  cache[id] = track;
                  trackObj[id] = track;
                  count++;
                });

                if (details.onProgress) {
                  details.onProgress(count, maxCount);
                }
              }

              return new Promise(function(resolve) {
                setTimeout(resolve, 250);
              });
            });
          };

          promise = promise.then(function() {
            return requestIds().catch(function(e) {
              if (e.message !== 'Track list is not found!') {
                throw e;
              }

              if (!details.withoutUnblock) {
                return _this.waitUntilUnblock(details).then(requestIds);
              }
            }).catch(function(e) {
              if (e.message !== 'Abort') {
                mono.debug('requestIds error!', e);
              }
            });
          });
        });

        promise = promise.then(function() {
          Object.keys(cache).slice(1000).forEach(function(id) {
            delete cache[id];
          });

          var idsArr = [];
          ids.forEach(function(id) {
            var track = trackObj[id];
            track && idsArr.push(track);
          });
          return idsArr;
        });

        promise = promise.then(function(idsArr) {
          return audio.unmaskUrlViaPlayer(idsArr);
        });

        return promise;
      },

      _getAlbumIdFromUrl: function(url) {
        var _this = this;
        var list = [url];
        var params = mono.parseUrl(url);
        if (params.z) {
          list.unshift(params.z);
        }

        var result = null;
        list.some(function(url) {
          result = _this._getAlbumId(url);
          if (result) {
            return true;
          }
        });
        return result;
      },

      _getAlbumId: function(url) {
        if (/[?&]q=/.test(url)) {
          return null;
        }

        var albumInfo = {
          url: '/al_audio.php',
          data: {}
        };

        var playlistMatch = /audio_playlist(-?\d+)_(-?\d+)(?:\/(\w+))?/.exec(url);
        if (playlistMatch) {
          albumInfo.data.access_hash = playlistMatch[3] || '';
          albumInfo.data.act = 'load_section';
          albumInfo.data.al = 1;
          albumInfo.data.claim = 0;
          // albumInfo.data.is_loading_all = 1;
          albumInfo.data.owner_id = playlistMatch[1];
          albumInfo.data.playlist_id = playlistMatch[2];
          albumInfo.data.type = 'playlist';
          albumInfo.data.offset = 0;
        }

        if (!albumInfo.data.act) {
          var audiosMatch = /audios(-?\d+)/.exec(url);
          if (audiosMatch) {
            var sectionMatch = /[?&]section=(\w+)/.exec(url);
            var sectionName = sectionMatch && sectionMatch[1];
            if (sectionName && ['playlists', 'all'].indexOf(sectionName) === -1) {
              return null;
            }

            albumInfo.data.access_hash = '';
            albumInfo.data.act = 'load_section';
            albumInfo.data.al = 1;
            albumInfo.data.claim = 0;
            albumInfo.data.owner_id = audiosMatch[1];
            albumInfo.data.playlist_id = -1;
            albumInfo.data.type = 'playlist';
            albumInfo.data.offset = 0;
          }
        }

        if (!albumInfo.data.act) {
          return null;
        } else {
          return albumInfo;
        }
      },

      getNewNodeTrackInfo: function(node, cb) {
        var _this = this;
        var track = _this.readNewDataAudio(node.dataset.audio);

        var info = _this.getNewTrackInfo(track);
        if (!info) {
          return cb("Track info is not found!");
        }

        if (info.url) {
          return audio.unmaskUrlViaPlayer([
            [null, null, info.url]
          ]).then(function(idArr) {
            info.url = idArr[0][2];
            cb(null, info);
          });
        } else
        if (info.fullId) {
          return cb(null, info);
        } else {
          return cb("Track info is not found!");
        }
      },

      _getAlbumTrackViaApi: function(albumInfo, details) {
        var _this = this;
        if (!albumInfo.url) {
          mono.debug('Page is not exists!', albumInfo);
          throw new Error('Page is not exists!');
        }

        var postData = JSON.parse(JSON.stringify(albumInfo.data));

        var requestList = function() {
          if (details.abort) {
            return Promise.reject(new Error('Abort'));
          }

          return mono.requestPromise({
            type: 'POST',
            headers: {
              'Content-Type': 'application/x-www-form-urlencoded',
              'X-Requested-With': 'XMLHttpRequest'
            },
            url: albumInfo.url,
            data: postData,
            timeout: 60 * 1000,
            localXHR: true
          }).then(function(response) {
            var data = parseVkResponse(response.body);
            var album = data[5];
            if (!album) {
              throw new Error('Album data is empty!');
            }

            return new Promise(function(resolve) {
              setTimeout(resolve, 250);
            }).then(function() {
              return album;
            });
          });
        };

        return requestList().then(function(album) {
          var limit = 20;
          var getOffset = function(offset) {
            if (!offset || limit < 0) {
              return album;
            }

            limit--;
            postData.offset = offset;
            return requestList().then(function(offsetAlbum) {
              if (offsetAlbum.list.length) {
                album.list.push.apply(album.list, offsetAlbum.list);
                return getOffset(offsetAlbum.nextOffset);
              } else {
                return album;
              }
            }, function(e) {
              if (e.message !== 'Abort') {
                mono.debug('getOffset error!', e);
              }
              return album;
            });
          };
          return getOffset(album.nextOffset);
        });
      },

      _getAllTrackViaDom: function(container, details) {
        var _this = this;
        details = details || {};

        var list = [];

        [].slice.call(container.querySelectorAll('.audio_row')).forEach(function(node) {
          if (details.fromPage && _this.elIsHidden(node)) {
            return;
          }

          if (!details.grabReply && photo.isReply(node)) {
            return;
          }

          var track = null;
          try {
            track = JSON.parse(node.dataset.audio);
          } catch (e) {}

          if (track) {
            list.push(track);
          }
        });

        return {
          list: list
        };
      },

      _getNewAudioLinks: function(container, details) {
        var _this = this;

        details = details || {};
        container = container || document;
        var fromPage = container === document;

        var popup = photo.getPopup('', 'audio', function onClose() {
          details.abort = true;
        });

        popup.onPrepare(language.download + ' ...');

        var findAudioAlbumLinks = function() {
          return Promise.resolve().then(function() {
            var albumInfo = _this._getAlbumIdFromUrl(location.h