Jump to content
This is a wiki for a reason. Anyone can contribute. If you see something that is inaccurate or can be improved, don't ask that it be fixed--just improve it.
[ Disclaimer, Create new user --- Wiki markup help, Install P99 ]

MediaWiki:SpamRemoval.js

From p99 Backup
Revision as of 22:10, 15 April 2025 by imported>Loramin
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
//Part 1: Raw/Original Bookmarklet code

const fetchHtml = async (url, options = undefined) => {
  const response = await fetch(url, options);
  return await response.text();
};

const getPageEditToken = async (name) => {
  const url =
    'https://wiki.project1999.com/index.php?title=' + name + '&action=delete';
  const html = await await fetchHtml(url);
  const index = html.indexOf('wpEditToken');
  return html.slice(index - 42, index - 8);
};

const getUserEditToken = async (name) => {
  const url =
    'https://wiki.project1999.com/Special:Block/' + encodeURIComponent(name);
  const html = await fetchHtml(url);
  const junk = ' id="wpEditToken" type="hidden" value="';
  const index = html.indexOf(junk);
  const token = html.slice(index + junk.length).split('"')[0];
  return token;
};

const getCreatorUsername = async (pageName) => {
  const url =
    'https://wiki.project1999.com/index.php?title=' +
    pageName +
    '&action=history';
  let html = await fetchHtml(url);
  html = html.split(' | prev)')[1];
  const junkStart1 = "<span class='history-user'><a href=\"/User:";
  const junkEnd1 = '" title="';
  let startIndex;
  if (html.includes(junkStart1)) {
    console.log(html)
    startIndex = html.lastIndexOf(junkStart1) + junkStart1.length;
    return html.substring(startIndex, html.indexOf(junkEnd1, startIndex));
  }

  const junkStart2 =
    "<span class='history-user'><a href=\"/index.php?title=User:";
  const junkEnd2 = '&amp;action';
  if (html.includes(junkStart2)) {
    startIndex = html.indexOf(junkStart2) + junkStart2.length;
    return html.substring(startIndex, html.indexOf(junkEnd2, startIndex));
  }

  return alert('Unexpected history page HTML for :' + pageName + '"');
};

const blockUserName = async (username) => {
  const userHtml = await fetchHtml(
    'https://wiki.project1999.com/Special:Block/' + username
  );
  const alreadyBanned = userHtml.includes(
    username + ' is already blocked. Do you want to change the settings?'
  );
  if (alreadyBanned) {
    alert('The user "' + username + '" was already banned.');
    return true;
  }

  const editToken = await getUserEditToken(username);
  const encodedName = encodeURIComponent(username);
  const url = 'https://wiki.project1999.com/Special:Block/' + encodedName;
  const options = {
    body:
      'wpTarget=' +
      username +
      '&wpExpiry=infinite&wpExpiry-other=' +
      '&wpReason=Spamming+links+to+external+sites' +
      '&wpReason-other=' +
      '&wpCreateAccount=1' +
      '&wpAutoBlock=1' +
      '&wpEditToken=' +
      encodeURIComponent(editToken) +
      '&title=Special%3ABlock%2F' +
      username +
      '&redirectparams=' +
      '&wpPreviousTarget=' +
      username +
      '&wpConfirm=',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    method: 'POST',
  };
  const responseHtml = await fetchHtml(url, options);
  return responseHtml.includes('Block succeeded');
};

const deletePage = async (pageName) => {
  const creator = await getCreatorUsername(pageName);
  if (!creator || creator.length > 50) {
    return alert(
      'Unable to find creator of "' + pageName + '" (found ' + creator + ')'
    );
  }

  const banSucceess = await blockUserName(creator);
  if (!banSucceess) {
    return alert('Something went wrong when blocking "' + creator + '"');
  }

  const url =
    'https://wiki.project1999.com/index.php?title=' +
    pageName +
    '&action=delete';
  const editToken = await getPageEditToken(pageName);
  const options = {
    body:
      'wpDeleteReasonList=Vandalism' +
      '&wpReason=Content+was+inappropriate' +
      '&wpConfirmB=Delete+page' +
      '&wpEditToken=' +
      encodeURIComponent(editToken),
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    method: 'POST',
  };

  const responseHtml = await fetchHtml(url, options);
  const deleteSuccess = responseHtml.includes('Action complete');
  alert(
    deleteSuccess
      ? '"' + pageName + '" was deleted and "' + creator + '" was banned.'
      : 'Deleting "' + pageName + '" failed: see Network tab for details.'
  );
};

$('body').one('click', (e) => {
  if (e.target.tagName !== 'A') return;

  deletePage(e.target.innerHTML);
  return false;
});

/**
 * Use the following URL to "build" this bookmarklet
 * https://caiorss.github.io/bookmarklet-maker/
 */

// Part 2: Escaped bookmarklet, as a string

const escapedOneUseBookmarklet = `javascript:(function()%7Bconst%20fetchHtml%20%3D%20async%20(url%2C%20options%20%3D%20undefined)%20%3D%3E%20%7B%0A%20%20const%20response%20%3D%20await%20fetch(url%2C%20options)%3B%0A%20%20return%20await%20response.text()%3B%0A%7D%3B%0A%0Aconst%20getPageEditToken%20%3D%20async%20(name)%20%3D%3E%20%7B%0A%20%20const%20url%20%3D%0A%20%20%20%20'https%3A%2F%2Fwiki.project1999.com%2Findex.php%3Ftitle%3D'%20%2B%20name%20%2B%20'%26action%3Ddelete'%3B%0A%20%20const%20html%20%3D%20await%20await%20fetchHtml(url)%3B%0A%20%20const%20index%20%3D%20html.indexOf('wpEditToken')%3B%0A%20%20return%20html.slice(index%20-%2042%2C%20index%20-%208)%3B%0A%7D%3B%0A%0Aconst%20getUserEditToken%20%3D%20async%20(name)%20%3D%3E%20%7B%0A%20%20const%20url%20%3D%0A%20%20%20%20'https%3A%2F%2Fwiki.project1999.com%2FSpecial%3ABlock%2F'%20%2B%20encodeURIComponent(name)%3B%0A%20%20const%20html%20%3D%20await%20fetchHtml(url)%3B%0A%20%20const%20junk%20%3D%20'%20id%3D%22wpEditToken%22%20type%3D%22hidden%22%20value%3D%22'%3B%0A%20%20const%20index%20%3D%20html.indexOf(junk)%3B%0A%20%20const%20token%20%3D%20html.slice(index%20%2B%20junk.length).split('%22')%5B0%5D%3B%0A%20%20return%20token%3B%0A%7D%3B%0A%0Aconst%20getCreatorUsername%20%3D%20async%20(pageName)%20%3D%3E%20%7B%0A%20%20const%20url%20%3D%0A%20%20%20%20'https%3A%2F%2Fwiki.project1999.com%2Findex.php%3Ftitle%3D'%20%2B%0A%20%20%20%20pageName%20%2B%0A%20%20%20%20'%26action%3Dhistory'%3B%0A%20%20let%20html%20%3D%20await%20fetchHtml(url)%3B%0A%20%20html%20%3D%20html.split('%20%7C%20prev)')%5B1%5D%3B%0A%20%20const%20junkStart1%20%3D%20%22%3Cspan%20class%3D'history-user'%3E%3Ca%20href%3D%5C%22%2FUser%3A%22%3B%0A%20%20const%20junkEnd1%20%3D%20'%22%20title%3D%22'%3B%0A%20%20let%20startIndex%3B%0A%20%20if%20(html.includes(junkStart1))%20%7B%0A%20%20%20%20console.log(html)%0A%20%20%20%20startIndex%20%3D%20html.lastIndexOf(junkStart1)%20%2B%20junkStart1.length%3B%0A%20%20%20%20return%20html.substring(startIndex%2C%20html.indexOf(junkEnd1%2C%20startIndex))%3B%0A%20%20%7D%0A%0A%20%20const%20junkStart2%20%3D%0A%20%20%20%20%22%3Cspan%20class%3D'history-user'%3E%3Ca%20href%3D%5C%22%2Findex.php%3Ftitle%3DUser%3A%22%3B%0A%20%20const%20junkEnd2%20%3D%20'%26amp%3Baction'%3B%0A%20%20if%20(html.includes(junkStart2))%20%7B%0A%20%20%20%20startIndex%20%3D%20html.indexOf(junkStart2)%20%2B%20junkStart2.length%3B%0A%20%20%20%20return%20html.substring(startIndex%2C%20html.indexOf(junkEnd2%2C%20startIndex))%3B%0A%20%20%7D%0A%0A%20%20return%20alert('Unexpected%20history%20page%20HTML%20for%20%3A'%20%2B%20pageName%20%2B%20'%22')%3B%0A%7D%3B%0A%0Aconst%20blockUserName%20%3D%20async%20(username)%20%3D%3E%20%7B%0A%20%20const%20userHtml%20%3D%20await%20fetchHtml(%0A%20%20%20%20'https%3A%2F%2Fwiki.project1999.com%2FSpecial%3ABlock%2F'%20%2B%20username%0A%20%20)%3B%0A%20%20const%20alreadyBanned%20%3D%20userHtml.includes(%0A%20%20%20%20username%20%2B%20'%20is%20already%20blocked.%20Do%20you%20want%20to%20change%20the%20settings%3F'%0A%20%20)%3B%0A%20%20if%20(alreadyBanned)%20%7B%0A%20%20%20%20alert('The%20user%20%22'%20%2B%20username%20%2B%20'%22%20was%20already%20banned.')%3B%0A%20%20%20%20return%20true%3B%0A%20%20%7D%0A%0A%20%20const%20editToken%20%3D%20await%20getUserEditToken(username)%3B%0A%20%20const%20encodedName%20%3D%20encodeURIComponent(username)%3B%0A%20%20const%20url%20%3D%20'https%3A%2F%2Fwiki.project1999.com%2FSpecial%3ABlock%2F'%20%2B%20encodedName%3B%0A%20%20const%20options%20%3D%20%7B%0A%20%20%20%20body%3A%0A%20%20%20%20%20%20'wpTarget%3D'%20%2B%0A%20%20%20%20%20%20username%20%2B%0A%20%20%20%20%20%20'%26wpExpiry%3Dinfinite%26wpExpiry-other%3D'%20%2B%0A%20%20%20%20%20%20'%26wpReason%3DSpamming%2Blinks%2Bto%2Bexternal%2Bsites'%20%2B%0A%20%20%20%20%20%20'%26wpReason-other%3D'%20%2B%0A%20%20%20%20%20%20'%26wpCreateAccount%3D1'%20%2B%0A%20%20%20%20%20%20'%26wpAutoBlock%3D1'%20%2B%0A%20%20%20%20%20%20'%26wpEditToken%3D'%20%2B%0A%20%20%20%20%20%20encodeURIComponent(editToken)%20%2B%0A%20%20%20%20%20%20'%26title%3DSpecial%253ABlock%252F'%20%2B%0A%20%20%20%20%20%20username%20%2B%0A%20%20%20%20%20%20'%26redirectparams%3D'%20%2B%0A%20%20%20%20%20%20'%26wpPreviousTarget%3D'%20%2B%0A%20%20%20%20%20%20username%20%2B%0A%20%20%20%20%20%20'%26wpConfirm%3D'%2C%0A%20%20%20%20headers%3A%20%7B%20'Content-Type'%3A%20'application%2Fx-www-form-urlencoded'%20%7D%2C%0A%20%20%20%20method%3A%20'POST'%2C%0A%20%20%7D%3B%0A%20%20const%20responseHtml%20%3D%20await%20fetchHtml(url%2C%20options)%3B%0A%20%20return%20responseHtml.includes('Block%20succeeded')%3B%0A%7D%3B%0A%0Aconst%20deletePage%20%3D%20async%20(pageName)%20%3D%3E%20%7B%0A%20%20const%20creator%20%3D%20await%20getCreatorUsername(pageName)%3B%0A%20%20if%20(!creator%20%7C%7C%20creator.length%20%3E%2050)%20%7B%0A%20%20%20%20return%20alert(%0A%20%20%20%20%20%20'Unable%20to%20find%20creator%20of%20%22'%20%2B%20pageName%20%2B%20'%22%20(found%20'%20%2B%20creator%20%2B%20')'%0A%20%20%20%20)%3B%0A%20%20%7D%0A%0A%20%20const%20banSucceess%20%3D%20await%20blockUserName(creator)%3B%0A%20%20if%20(!banSucceess)%20%7B%0A%20%20%20%20return%20alert('Something%20went%20wrong%20when%20blocking%20%22'%20%2B%20creator%20%2B%20'%22')%3B%0A%20%20%7D%0A%0A%20%20const%20url%20%3D%0A%20%20%20%20'https%3A%2F%2Fwiki.project1999.com%2Findex.php%3Ftitle%3D'%20%2B%0A%20%20%20%20pageName%20%2B%0A%20%20%20%20'%26action%3Ddelete'%3B%0A%20%20const%20editToken%20%3D%20await%20getPageEditToken(pageName)%3B%0A%20%20const%20options%20%3D%20%7B%0A%20%20%20%20body%3A%0A%20%20%20%20%20%20'wpDeleteReasonList%3DVandalism'%20%2B%0A%20%20%20%20%20%20'%26wpReason%3DContent%2Bwas%2Binappropriate'%20%2B%0A%20%20%20%20%20%20'%26wpConfirmB%3DDelete%2Bpage'%20%2B%0A%20%20%20%20%20%20'%26wpEditToken%3D'%20%2B%0A%20%20%20%20%20%20encodeURIComponent(editToken)%2C%0A%20%20%20%20headers%3A%20%7B%20'Content-Type'%3A%20'application%2Fx-www-form-urlencoded'%20%7D%2C%0A%20%20%20%20method%3A%20'POST'%2C%0A%20%20%7D%3B%0A%0A%20%20const%20responseHtml%20%3D%20await%20fetchHtml(url%2C%20options)%3B%0A%20%20const%20deleteSuccess%20%3D%20responseHtml.includes('Action%20complete')%3B%0A%20%20alert(%0A%20%20%20%20deleteSuccess%0A%20%20%20%20%20%20%3F%20'%22'%20%2B%20pageName%20%2B%20'%22%20was%20deleted%20and%20%22'%20%2B%20creator%20%2B%20'%22%20was%20banned.'%0A%20%20%20%20%20%20%3A%20'Deleting%20%22'%20%2B%20pageName%20%2B%20'%22%20failed%3A%20see%20Network%20tab%20for%20details.'%0A%20%20)%3B%0A%7D%3B%0A%0A%24('body').one('click'%2C%20(e)%20%3D%3E%20%7B%0A%20%20if%20(e.target.tagName%20!%3D%3D%20'A')%20return%3B%0A%0A%20%20deletePage(e.target.innerHTML)%3B%0A%20%20return%20false%3B%0A%7D)%3B%7D)()%3B`;


// Part 3: Code to show the bookmarklet (and its multi-use variant) in the wiki (since wiki's can't have "javascript:" links)

$('#oneUsePlaceholder').html(`<a>One-Use Spam Deletion</a>`);

// Don't use jQuery because it will escape the code (incorrectly)
$('#oneUsePlaceholder a').get(0).setAttribute('href', escapedOneUseBookmarklet);

const multiUseBookmarklet = escapedOneUseBookmarklet.replace(`.one('click'%2C%20(e)`, `.click((e)`);

$('#multiplePlaceholder').html(`<a>Multi-Use Spam Deletion</a>`);
$('#multiplePlaceholder a').attr('href', multiUseBookmarklet);