lordralinc / DaEM Viewer

// ==UserScript==
// @name DaEM Viewer
// @namespace http://tampermonkey.net/
// @version 1.1.0
// @updateURL https://openuserjs.org/meta/lordralinc/DaEM_Viewer.meta.js
// @downloadURL https://openuserjs.org/install/lordralinc/DaEM_Viewer.user.js
// @copyright 2018, flyink13, lordralinc
// @description Показывает удаленные и отредактированные сообщения (только если открыт диалог)
// @author Flyink13, lordralinc
// @match https://*.vk.com/*
// @license MIT
//  
// ==/UserScript==

/* global geByClass1 */

/*
*
* Небольшой экскурс по настройкам
*
* deletedMessagesColor - цвет удаленных смс
* updatedMessagesColor - цвет обновленных смс
*
* ignore - сюда вставляются ID пользователей, чьи удаленные смс видеть не надо. Пример:
* ignore: ["1", "100", "460908267"] - не видим удаление/обновление смс Дурова, Администрации ВК и Юрия Юшманова
*
* debug - прикольные вещи будут выводиться в консоль
* showErrors - не прикольные вещи будут выводиться в консоль
*
* За редачи спасибо Арсению vk.com/belikanov
* */


function deletedAndEditedMessagesViewer() {

  const COLORS = {
    BLACK: 'rgb(0, 0, 0)',
    WHITE: 'rgb(255, 255, 255)',
    RED: 'rgb(255, 0, 0)',
    GREEN: 'rgb(0, 255, 0)',
    BLUE: 'rgb(0, 0, 255)',
    DEFAULT_DELETE: 'rgb(255, 230, 230)',
    DEFAULT_UPDATE: 'rgb(230, 255, 230)',

    OTHER: (r, g, b) => {return `rgb(${r}, ${g}, ${b})`}
  }

  const settings = {
    deletedMessagesColor: COLORS.DEFAULT_DELETE,
    updatedMessagesColor: COLORS.DEFAULT_UPDATE,
    ignore: [],
    debug: false,
    showErrors: false
  }

  function logDebug(...args){
    if (settings.debug){
      console.log("[DaEM Viewer]", ...args);
    }
  }

  function logError(...args){
    if (settings.showErrors){
      console.error("[DaEM Viewer]", ...args);
    }
  }
  const flagDelete = 1 << 7;
  const flagUpdate = 2;
  XMLHttpRequest.prototype.send = (function buildFakeSend(sendOrg) {
    return function fakeSend(...sendArgs) {
      this.onreadystatechange = (function buildFakeOnChang(changeOrg) {
        if (!changeOrg) return;

        return function fakeOnReadyStateChange(...changeArgs) {
          let isLongPoll = (/^https:\/\/.?im(v4)?\.vk\.com\/.?im\d+/.test(this.responseURL));
          let isReady = (this.readyState === 4);

          if (isLongPoll && isReady && this.responseText) {
            try {
              let newJson = JSON.parse(this.responseText);
              newJson.updates.forEach((update) => {

                let newEl;
                let isDelete = (update[0] === flagUpdate && update[2] && flagDelete);
                let isUpdate = (update[0] === 5);
                let el = geByClass1('_im_mess_' + update[1]);

                if (!(isDelete || isUpdate) || !el) {
                  return !(isDelete || isUpdate)
                }

                try {
                  let parentEl = el.parentElement.parentElement.parentElement;
                  if (settings.ignore.indexOf(parentEl.dataset.peer.toString()) !== -1){
                    return !(isDelete || isUpdate);
                  }
                } catch (e) {
                  logError(e);
                }

                if (isDelete || isUpdate) {
                  logDebug("triggered", update, el);
                }

                if (isDelete && el) {
                  if (el) {
                    newEl = el.cloneNode(true);
                    el.style.backgroundColor = settings.deletedMessagesColor;
                  }
                }

                if (isUpdate && el) {
                  if (el) {
                    newEl = el.cloneNode(true);
                    el.style.backgroundColor = settings.updatedMessagesColor;
                  }
                }
                if (newEl) {
                  el.parentElement.insertBefore(newEl, el);
                }
                return !(isDelete || isUpdate);
              });
            } catch (e) {
              logError(e);
            }
          }
          return changeOrg.apply(this, changeArgs);
        };
      })(this.onreadystatechange);
      return sendOrg.apply(this, sendArgs);
    };
  })(XMLHttpRequest.prototype.send);
}

(function injectScript() {
  let script = document.createElement('script');
  let code = '(' + deletedAndEditedMessagesViewer + ')();';
  script.appendChild(document.createTextNode(code));
  (document.body || document.head || document.documentElement).appendChild(script);
})();