User:DreamRimmer/User not around.js

//

// Fork of User:Andrybak/Scripts/Not around.js

// This script helps you add a "Not around" template to a user's talk page if they haven't edited in the last 6 months

(function() {

'use strict';

const config = {

wikipage: 'User not around.js',

};

const USERSCRIPT_NAME = 'Not around userscript';

const LOG_PREFIX = `[${USERSCRIPT_NAME}]:`;

function error(...toLog) {

console.error(LOG_PREFIX, ...toLog);

}

function warn(...toLog) {

console.warn(LOG_PREFIX, ...toLog);

}

function info(...toLog) {

console.info(LOG_PREFIX, ...toLog);

}

function debug(...toLog) {

console.debug(LOG_PREFIX, ...toLog);

}

function notify(notificationMessage) {

mw.notify(notificationMessage, {

title: USERSCRIPT_NAME

});

}

function errorAndNotify(errorMessage, rejection) {

error(errorMessage, rejection);

notify(errorMessage);

}

const ABSENSE_MONTHS_MINIMUM = 6;

const MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

const mw = window.mw;

const DEBUG = false;

function constructAd() {

return `(using ${config.wikipage})`;

}

function constructEditSummary(username, lastContribDate) {

const day = lastContribDate.getUTCDate();

const month = MONTHS[lastContribDate.getUTCMonth()];

const year = lastContribDate.getUTCFullYear();

return `/* top */ add Template:Not around – user ${username} hasn't edited since ${day} ${month} ${year} (${constructAd()})`;

}

/**

* Asynchronously load specified number of contributions of specified username.

*/

function loadNLastUserContribs(username, n) {

const api = new mw.Api();

return api.get({

action: 'query',

list: 'usercontribs',

ucuser: username,

uclimit: n

});

}

/**

* Asynchronously load the very last contribution of specified username.

*/

function loadLastUserContrib(username) {

return new Promise((resolve, reject) => {

loadNLastUserContribs(username, 1).then(response => {

debug(response);

const lastContrib = response.query.usercontribs[0];

resolve(lastContrib);

}, rejection => {

reject(rejection);

});

});

}

function isoStringToDate(timestamp) {

const d = new Date(timestamp);

return d;

}

function loadCurrentWikitext(pagename) {

return new Promise((resolve, reject) => {

const api = new mw.Api();

api.get({

action: 'query',

titles: pagename,

prop: 'revisions',

rvprop: 'content',

rvslots: 'main',

formatversion: 2

}).then(response => {

resolve(response.query.pages[0].revisions[0].slots.main.content);

}, rejection => {

reject(rejection);

});

});

}

function addNotAroundTemplateIfAbsent(username, lastContribDate) {

const day = lastContribDate.getUTCDate();

const month = MONTHS[lastContribDate.getUTCMonth()];

const year = lastContribDate.getUTCFullYear();

info(`${username} hasn't edited since ${day} ${month} ${year}.`);

const userTalkPageTitle = 'User_talk:' + username;

loadCurrentWikitext(userTalkPageTitle).then(wikitext => {

const regex = /\{\{\s*not\s*around\s*(?:\s*\|[^}]+)?\s*\}\}/i;

if (regex.test(wikitext)) {

info(userTalkPageTitle + ' already has the template. Showing it to the user and aborting.');

location.assign('/wiki/' + userTalkPageTitle);

return;

}

const formHtml = `

Choose the appropriate option:

This user is not currently active on Wikipedia


This user may have left Wikipedia (default)

`;

const dialog = $('

').html(formHtml).dialog({

title: 'Not around',

width: 400,

buttons: {

'Preview': function() {

const isInactive = $('#inactiveCheckbox').prop('checked');

const isLeft = $('#leftCheckbox').prop('checked');

let template;

if (isInactive) {

template = `{{Not around|is not currently active on Wikipedia|date=${day} ${month} ${year}}}`;

} else if (isLeft) {

template = `{{Not around|date=${day} ${month} ${year}}}`;

}

const newWikitext = `${template}\n` + wikitext;

const editSummary = constructEditSummary(username, lastContribDate);

if (DEBUG) {

debug(newWikitext.slice(0, 40));

debug(editSummary);

}

const previewWikitext = newWikitext.split("\n").slice(0, 10).join("\n");

const previewText = previewWikitext.replace(template, `${template}`);

const previewDialog = $('

').html(`

Preview of the edit (Wikitext):

${previewText}

Do you want to add the above template to the user talk page?

`).dialog({

title: 'Preview',

buttons: {

'Submit': function() {

const api = new mw.Api();

api.postWithEditToken({

action: 'edit',

title: userTalkPageTitle,

text: newWikitext,

summary: editSummary

}).then(response => {

loadLastUserContrib(mw.user.getName()).then(theEdit => {

location.assign('/wiki/Special:Diff/' + theEdit.revid);

}, rejection => {

errorAndNotify(`Cannot load last contribution by ${mw.user.getName()}.`, rejection);

});

}, rejection => {

errorAndNotify(`Cannot edit page ${userTalkPageTitle}`, rejection);

});

$(this).dialog('close');

},

'Cancel': function() {

$(this).dialog('close');

}

}

});

$(this).dialog('close');

},

'Cancel': function() {

$(this).dialog('close');

}

}

});

$('#inactiveCheckbox').change(function() {

if ($(this).prop('checked')) {

$('#leftCheckbox').prop('checked', false);

}

});

$('#leftCheckbox').change(function() {

if ($(this).prop('checked')) {

$('#inactiveCheckbox').prop('checked', false);

}

});

});

}

function runPortlet () {

const username = mw.config.get('wgRelevantUserName');

if (!username) {

errorAndNotify('Cannot find a username', null);

return;

}

loadLastUserContrib(username).then(lastContrib => {

if (!lastContrib) {

notify(`User ${username} has zero contributions. Aborting.`);

return;

}

if (lastContrib.user != username) {

errorAndNotify(`Received wrong user. Actual ${lastContrib.user} ≠ expected ${username}. Aborting.`, null);

return;

}

const lastContribDate = isoStringToDate(lastContrib.timestamp);

const currentDate = new Date();

info('Last edit timestamp =', lastContrib.timestamp);

const daysSinceLastEdit = Math.floor((currentDate - lastContribDate) / (1000 * 60 * 60 * 24));

if (daysSinceLastEdit >= ABSENSE_MONTHS_MINIMUM * 30) {

addNotAroundTemplateIfAbsent(username, lastContribDate);

} else {

notify(`${username} is still an active user. Last edit was on ${lastContribDate.getUTCDate()} ${MONTHS[lastContribDate.getUTCMonth()]} ${lastContribDate.getUTCFullYear()}. Aborting.`);

}

}, rejection => {

errorAndNotify(`Cannot load contributions of ${username}. Aborting.`, rejection);

});

}

function lazyLoadNotAround() {

debug('Loading...');

const namespaceNumber = mw.config.get('wgNamespaceNumber');

if (namespaceNumber === -1 || namespaceNumber === 2 || namespaceNumber === 3) {

if (!mw.loader.using) {

warn('Function mw.loader.using is not loaded yet. Retrying...');

setTimeout(lazyLoadNotAround, 300);

return;

}

mw.loader.using(

['mediawiki.util'],

() => {

const link = mw.util.addPortletLink('p-cactions', '#', 'Not around', 'ca-notaround', 'add template {{Not around}}');

if (!link) {

info('Cannot create portlet link (mw.util.addPortletLink). Assuming unsupported skin. Aborting.');

return;

}

link.onclick = event => {

event.preventDefault();

mw.loader.using('mediawiki.api', runPortlet);

};

},

(e) => {

error('Cannot add portlet link', e);

}

);

} else {

warn('Triggered on a bad namespace =', namespaceNumber);

}

}

if (document.readyState !== 'loading') {

lazyLoadNotAround();

} else {

warn('Cannot load yet. Setting up a listener...');

document.addEventListener('DOMContentLoaded', lazyLoadNotAround);

}

})();

//