Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.

  • Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
  • Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
  • Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
/* jshint esversion: 6 */
var OhNotAgain = {
  queryParamsView      : {
    action: 'query',
    prop: ['revisions'],
    pageids: mw.config.get('wgArticleId'),
    rvprop: ['comment', 'timestamp', 'user', 'sha1', 'ids'],
    rvslots: 'main',
    rvlimit: '25',
    rvend: null
  },
  cachedRevisions      : { },
  savedBackgroundColor : 0,
  api : 0,

  execute : function () {
    if(mw.config.get('wgNamespaceNumber') !== 0)
      return;
    action = mw.config.get('wgAction');
    if(action != 'edit' && action != 'submit')
      return;
    var summary = document.getElementById('wpSummary');
    if(!summary)
      return;
    let date = new Date();
    date.setFullYear(date.getFullYear() - 1);
    OhNotAgain.queryParamsView.rvend = date.getFullYear().toString().padStart(4, '0') + '-' +
                                       (date.getMonth() + 1).toString().padStart(2, '0') + '-' +
                                       date.getDay().toString().padStart(2, '0') + 'T' +
                                       date.getHours().toString().padStart(2, '0') + ':' +
                                       date.getMinutes().toString().padStart(2, '0') + ':' +
                                       date.getSeconds().toString().padStart(2, '0') + '.000Z';
    OhNotAgain.savedBackgroundColor = document.getElementById('wpSummary').style.backgroundColor;
    OhNotAgain.api = new mw.Api();
    summary.addEventListener('input', function() {
        if(Object.entries(OhNotAgain.cachedRevisions).length === 0)
          OhNotAgain.doQuery(OhNotAgain.api, OhNotAgain.wurschtelAndCache, OhNotAgain.queryParamsView);
        else
          OhNotAgain.wurschtel(OhNotAgain.cachedRevisions);
      });
    if(mw.config.get('wgEditMessage') == 'editing') {
      textbox = document.getElementById('wpTextbox1');
      if(textbox) {
        textbox.addEventListener('focusout', function() {
            if(Object.entries(OhNotAgain.cachedRevisions).length === 0)
              OhNotAgain.doQuery(OhNotAgain.api, OhNotAgain.wurschtelAndCache, OhNotAgain.queryParamsView);
            else
              OhNotAgain.wurschtel(OhNotAgain.cachedRevisions);
          });
      }
    }

    if(Object.entries(OhNotAgain.cachedRevisions).length === 0)
      OhNotAgain.doQuery(OhNotAgain.api, OhNotAgain.wurschtelAndCache, OhNotAgain.queryParamsView);
    else
      OhNotAgain.wurschtel(OhNotAgain.cachedRevisions);
  },

  wurschtelAndCache : function (api, res) {
    if(!res || !res.query || !res.query.pages)
      return;
    // modify the result, add link to other revisions with same hash
    var pages = res.query.pages, p;
    for (p in pages) {
      if(!pages[p].revisions)
        return;
      var shaMap = new Map();
      for(var i = 0; pages[p].revisions && i < pages[p].revisions.length; ++ i) {
        var r = pages[p].revisions[i];
        if(shaMap.has(r.sha1)) {
          res.query.pages[p].revisions[shaMap.get(r.sha1)].revertOf = i;
//          for(var ii = shaMap.get(r.sha1); ii < i; ++ ii) {
//            res.query.pages[p].revisions[ii].revertOf = i;
//          }
        }
        else {
          res.query.pages[p].revisions[i].revertOf = -1;
          shaMap.set(r.sha1, i);
        }
        var pos, posE;
        if((pos = r.comment.indexOf('/*')) != -1 && (posE = r.comment.indexOf('*/')) != -1)
          res.query.pages[p].revisions[i].cleanedComment = (r.comment.substring(0, pos) + r.comment.substring(posE + 2)).replaceAll('  ', ' ').trim();
        else
          res.query.pages[p].revisions[i].cleanedComment = r.comment.replaceAll('  ', ' ');
      }
    }
    OhNotAgain.cachedRevisions = res;
    OhNotAgain.wurschtel(res);
  },

  wurschtel : function (res) {
    var newSha1 = '';
    var newNlSha1 = '';
    if(mw.config.get('wgEditMessage') == 'editing') {
      var textbox = document.getElementById('wpTextbox1');
      if(textbox) {
        newSha1 = OhNotAgain.sha1(textbox.value.trim());
        newNlSha1 = OhNotAgain.sha1('\n' + textbox.value.trim());
      }
    }

    if(!res || !res.query || !res.query.pages)
      return;
    var pages = res.query.pages, p;
    for(p in pages) {
      if(!pages[p].revisions)
        return;
      var summaryVal = document.getElementById('wpSummary').value;
      // if(summaryVal.startsWith('Änderung [[Spezial:Diff/'))
        // return;
      if((pos = summaryVal.indexOf('/*')) != -1 && (posE = summaryVal.indexOf('*/')) != -1)
        summaryVal = summaryVal.substring(0, pos) + summaryVal.substring(posE + 2);
      summaryVal = summaryVal.replaceAll('  ', ' ').trim();
      if(summaryVal != '' || newSha1 != '') {
        var parentElems = document.getElementsByName('altBaseRevId'); // revert
        var parentId = 0;
        if(parentElems.length > 0)
          parentId = parentElems[0].value;
        if(parentId == 0) {
          parentElems = document.getElementsByName('parentRevId'); // edit old version
          if(parentElems.length > 0)
            parentId = parentElems[0].value;
        }
        var summaryVals = summaryVal.split(',');
        var parentSha1 = '', r;
        for(var i = 0; pages[p].revisions && i < pages[p].revisions.length; ++ i) {
          r = pages[p].revisions[i];
          if(parentId == r.revid) {
            parentSha1 = r.sha1;
          }
        }
        
        var revertIndex = -1;
        for(i = 0; pages[p].revisions && i < pages[p].revisions.length; ++ i) {
          r = pages[p].revisions[i];
          if(parentId != r.revid && r.sha1 != parentSha1 && (newSha1 == r.sha1 || newNlSha1 == r.sha1)) {
            if(revertIndex > i) {
              mw.notify('Achtung! Revertierte Änderung von User ' + r.user + ' am ' + OhNotAgain.fmtTimestamp(r.timestamp), { autoHide: true, title: 'Möglicher Edit-War!', tag: 'OhNotAgain-error', type: 'error', autoHideSeconds: 'long' });
              document.getElementById('wpSummary').style.backgroundColor = "#FF8080";
            }
            else {
              mw.notify('Achtung! Gleicher Inhalt wie User ' + r.user + ' am ' + OhNotAgain.fmtTimestamp(r.timestamp), { autoHide: true, title: 'Möglicher Edit-War!', tag: 'OhNotAgain-error', type: 'warn', autoHideSeconds: 'long' });
              document.getElementById('wpSummary').style.backgroundColor = "#FFB080";
            }
            return;
          }

          if(summaryVal != '') {
            var commentVals = r.cleanedComment.split(',').filter(function (txt) {
                return txt.trim() != '';
              });
            if(commentVals.some(element => {
                  return summaryVals.includes(element.trim());
                })) {
              if(revertIndex > i) {
                mw.notify('Achtung! Revertierte Änderung von User ' + r.user + ' am ' + OhNotAgain.fmtTimestamp(r.timestamp), { autoHide: true, title: 'Möglicher Edit-War!', tag: 'OhNotAgain-error', type: 'error', autoHideSeconds: 'long' });
                document.getElementById('wpSummary').style.backgroundColor = "#FF8080";
              }
              else {
                mw.notify('Achtung, Änderungskommentar beachten! User ' + r.user + ' am ' + OhNotAgain.fmtTimestamp(r.timestamp), { autoHide: true, title: 'Möglicher Edit-War!', tag: 'OhNotAgain-error', type: 'warn', autoHideSeconds: 'long' });
                document.getElementById('wpSummary').style.backgroundColor = "#FFB080";
              }
              return;
            }
          }
          if(revertIndex == -1 || revertIndex == i)
            revertIndex = r.revertOf;
        }
      }
    }
    document.getElementById('wpSummary').style.backgroundColor = OhNotAgain.savedBackgroundColor;
  },

  fmtTimestamp : function(timestamp) {
    const time = new Date(Date.UTC(timestamp.substring(0, 4), parseInt(timestamp.substring(5, 7)) - 1, timestamp.substring(8, 10), timestamp.substring(11, 13), timestamp.substring(14, 16), timestamp.substring(17, 19)));
    return time.getHours().toString().padStart(2, '0') + ':' + time.getMinutes().toString().padStart(2, '0') + ', ' + time.toLocaleDateString('de-DE', { year: 'numeric', month: 'short', day: 'numeric' });
  },

/**
*
*  Secure Hash Algorithm (SHA1)
*  http://www.webtoolkit.info/
*
**/
  sha1 : function(msg) {
    function rotate_left(n,s) {
      var t4 = (n << s) | (n >>> (32 - s));
      return t4;
    }
    function cvt_hex(val) {
      var str = '';
      var i;
      var v;
      for(i = 7; i >= 0; -- i) {
        v = (val >>> (i * 4)) & 0x0f;
        str += v.toString(16);
      }
      return str;
    }
    function Utf8Encode(string) {
      string = string.replace(/\r\n/g, '\n');
      var utftext = '';
      for(var n = 0; n < string.length; ++ n) {
        var c = string.charCodeAt(n);
        if(c < 128) {
          utftext += String.fromCharCode(c);
        }
        else if((c > 127) && (c < 2048)) {
          utftext += String.fromCharCode((c >> 6) | 192);
          utftext += String.fromCharCode((c & 63) | 128);
        }
        else {
          utftext += String.fromCharCode((c >> 12) | 224);
          utftext += String.fromCharCode(((c >> 6) & 63) | 128);
          utftext += String.fromCharCode((c & 63) | 128);
        }
      }
      return utftext;
    }
    var blockstart;
    var i, j;
    var W = new Array(80);
    var H0 = 0x67452301;
    var H1 = 0xEFCDAB89;
    var H2 = 0x98BADCFE;
    var H3 = 0x10325476;
    var H4 = 0xC3D2E1F0;
    var A, B, C, D, E;
    var temp;
    msg = Utf8Encode(msg);
    var msg_len = msg.length;
    var word_array = new Array();
    for(i = 0; i < msg_len - 3; i += 4) {
      j = msg.charCodeAt(i) << 24 | msg.charCodeAt(i + 1) << 16 |
      msg.charCodeAt(i + 2) << 8 | msg.charCodeAt(i + 3);
      word_array.push(j);
    }
    switch(msg_len % 4) {
    case 0:
      i = 0x080000000;
      break;
    case 1:
      i = msg.charCodeAt(msg_len - 1) << 24 | 0x0800000;
      break;
    case 2:
      i = msg.charCodeAt(msg_len - 2) << 24 | msg.charCodeAt(msg_len - 1) << 16 | 0x08000;
      break;
    case 3:
      i = msg.charCodeAt(msg_len - 3) << 24 | msg.charCodeAt(msg_len - 2) << 16 | msg.charCodeAt(msg_len - 1) << 8 | 0x80;
      break;
    }
    word_array.push(i);
    while((word_array.length % 16) != 14)
      word_array.push(0);
    word_array.push(msg_len >>> 29);
    word_array.push((msg_len << 3) & 0x0ffffffff);
    for(blockstart = 0; blockstart < word_array.length; blockstart += 16) {
      for(i = 0; i < 16; ++ i)
        W[i] = word_array[blockstart + i];
      for(i = 16; i <= 79; ++ i)
        W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
      A = H0;
      B = H1;
      C = H2;
      D = H3;
      E = H4;
      for(i = 0; i <= 19; ++ i) {
        temp = (rotate_left(A, 5) + ((B&C) | (~B&D)) + E + W[i] + 0x5A827999) & 0x0ffffffff;
        E = D;
        D = C;
        C = rotate_left(B, 30);
        B = A;
        A = temp;
      }
      for(i = 20; i <= 39; ++ i) {
        temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff;
        E = D;
        D = C;
        C = rotate_left(B, 30);
        B = A;
        A = temp;
      }
      for(i = 40; i <= 59; ++ i) {
        temp = (rotate_left(A, 5) + ((B&C) | (B&D) | (C&D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff;
        E = D;
        D = C;
        C = rotate_left(B, 30);
        B = A;
        A = temp;
      }
      for(i = 60; i <= 79; ++ i) {
        temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff;
        E = D;
        D = C;
        C = rotate_left(B, 30);
        B = A;
        A = temp;
      }
      H0 = (H0 + A) & 0x0ffffffff;
      H1 = (H1 + B) & 0x0ffffffff;
      H2 = (H2 + C) & 0x0ffffffff;
      H3 = (H3 + D) & 0x0ffffffff;
      H4 = (H4 + E) & 0x0ffffffff;
    }
    temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4);

    return temp.toLowerCase();
  }
};

OhNotAgain.doQuery = function(api, callback, queryParams, continueParams) {
  api.get($.extend({}, queryParams, continueParams || { 'continue': '' })).then(function(data) {
    callback( api, data );
  }).fail(function(code, data) {
    var extraText;
    if(code === 'http' && data) {
      extraText = (data.xhr && data.xhr.status ? '[' + data.xhr.status + ']' : '') +
                  (data.textStatus ? '' + data.textStatus + (data.exception ? ': ' : '') : '') +
                  (data.exception ? '' + data.exception : '');
    }
    else {
      extraText = code + ( data && data.error && data.error.info ? ': ' + data.error.info : '' );
    }
    mw.notify('OhNotAgain: Fehler beim Lesen der Versionsgeschichte' + ' (' + extraText + ')', { tag: 'OhNotAgain-error' });
  });
};

$(OhNotAgain.execute);