User:Edgars2007/tokyo2020.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
![]() | Documentation for this user script can be added at User:Edgars2007/tokyo2020. |
var api;
var category = '';
var stopThis = false;
const mapping = {
'Archery': 'Category:Archers at the 2024 Summer Olympics',
'Athletics': 'Category:Athletes (track and field) at the 2024 Summer Olympics',
'Badminton': 'Category:Badminton players at the 2024 Summer Olympics',
'Basketball': 'Category:Basketball players at the 2024 Summer Olympics',
'Breaking': 'Category:Breakdancers at the 2024 Summer Olympics',
'Beach volleyball': 'Category:Beach volleyball players at the 2024 Summer Olympics',
'Boxing': 'Category:Boxers at the 2024 Summer Olympics',
'Canoeing': 'Category:Canoeists at the 2024 Summer Olympics',
'Cycling': 'Category:Cyclists at the 2024 Summer Olympics',
'Diving': 'Category:Divers at the 2024 Summer Olympics',
'Equestrian': 'Category:Equestrians at the 2024 Summer Olympics',
'Fencing': 'Category:Fencers at the 2024 Summer Olympics',
'Field hockey': 'Category:Field hockey players at the 2024 Summer Olympics',
'Football': 'Category:Footballers at the 2024 Summer Olympics',
'Golf': 'Category:Golfers at the 2024 Summer Olympics',
'Gymnastics': 'Category:Gymnasts at the 2024 Summer Olympics',
'Handball': 'Category:Handball players at the 2024 Summer Olympics',
'Judo': 'Category:Judoka at the 2024 Summer Olympics',
'Modern pentathlon': 'Category:Modern pentathletes at the 2024 Summer Olympics',
'Rowing': 'Category:Rowers at the 2024 Summer Olympics',
'Sailing': 'Category:Sailors at the 2024 Summer Olympics',
'Shooting': 'Category:Shooters at the 2024 Summer Olympics',
'Swimming': 'Category:Swimmers at the 2024 Summer Olympics',
'Artistic swimming': 'Category:Artistic swimmers at the 2024 Summer Olympics',
'Table tennis': 'Category:Table tennis players at the 2024 Summer Olympics',
'Taekwondo': 'Category:Taekwondo practitioners at the 2024 Summer Olympics',
'Tennis': 'Category:Tennis players at the 2024 Summer Olympics',
'Triathlon': 'Category:Triathletes at the 2024 Summer Olympics',
'Volleyball': 'Category:Volleyball players at the 2024 Summer Olympics',
'Water polo': 'Category:Water polo players at the 2024 Summer Olympics',
'Weightlifting': 'Category:Weightlifters at the 2024 Summer Olympics',
'Wrestling': 'Category:Wrestlers at the 2024 Summer Olympics',
'Rugby sevens': 'Category:Rugby sevens players at the 2024 Summer Olympics',
'Surfing': 'Category:Surfers at the 2024 Summer Olympics',
'Skateboarding': 'Category:Skateboarders at the 2024 Summer Olympics',
'Baseball': 'Category:Baseball players at the 2024 Summer Olympics',
'Karate': 'Category:Karateka at the 2024 Summer Olympics',
'Softball': 'Category:Softball players at the 2024 Summer Olympics',
'Sport climbing': 'Category:Sport climbers at the 2024 Summer Olympics',
};
const addCategory = (wikitext, category) => {
if (wikitext.includes(category)) {
return null;
}
const re = /\[\[[Cc]ategory\s*:\s*[^\]]+\]\]/g;
let m;
let lastMatch;
while ((m = re.exec(wikitext))) {
lastMatch = m[0];
}
// console.log('lastMatch', lastMatch)
if (!lastMatch) {
return `${wikitext}[[${category}]]`;
}
return wikitext.replace(lastMatch, `${lastMatch}\n[[${category}]]`);
};
const handleRedirects = (titles) => {
return api
.get({
formatversion: 2,
titles: titles,
redirects: true,
})
.then(function (data) {
const { redirects } = data.query;
let mapping = {};
redirects.forEach((entry) => {
const { from, to } = entry;
mapping[from] = to;
});
return mapping;
});
};
const getCategoryMembers = (category, cmContinue = null) => {
if (stopThis) {
return;
}
let params = {
list: 'categorymembers',
redirects: 1,
formatversion: '2',
cmtitle: category,
cmnamespace: '0',
cmlimit: '500',
};
if (cmContinue) {
params = {
...params,
...cmContinue,
};
}
console.log('MADE API', params);
return api.get(params).then(function (data) {
return data;
});
};
const handleMembers = async (category) => {
let flag = true;
let cmContinue;
const pageResults = [];
let counter = 0;
while (flag) {
counter++;
if (counter === 15) {
alert('Too many API requests, maybe something is broken');
}
const resp = await getCategoryMembers(category, cmContinue);
if ('continue' in resp) {
cmContinue = resp.continue;
} else {
flag = false;
}
console.log(resp);
const currpages = resp.query.categorymembers.map((entry) => entry.title);
pageResults.push(...currpages);
}
console.log(pageResults);
return pageResults;
};
const getCategoryMembers_OLD = (category) => {
return api
.get({
list: 'categorymembers',
redirects: 1,
formatversion: '2',
cmtitle: category,
cmnamespace: '0',
cmlimit: '5',
})
.then(function (data) {
console.log(data);
const { categorymembers } = data.query;
return categorymembers.map((entry) => entry.title);
});
};
const getData = async (category, redirects) => {
const members = await handleMembers(category);
const redirs = redirects.length > 0 ? await handleRedirects(redirects) : {};
return {
members,
redirects: redirs,
};
};
const handlePageEdit = (ev) => {
const element = ev.target;
const canonical = element.getAttribute('data-canonical');
console.log(element, canonical);
new mw.Api()
.edit(canonical, function (revision) {
const newText = addCategory(revision.content, category);
if (!newText) {
return Promise.reject('ALREADY');
}
return {
text: newText,
summary: `add [[${category}]]`,
minor: true,
};
})
.then(function () {
console.log('Saved!');
var allButtons = document.getElementsByClassName('add-cat');
[...allButtons].forEach((btn) => {
const currCanonical = btn.getAttribute('data-canonical');
if (currCanonical === canonical) {
btn.parentNode.removeChild(btn);
}
});
});
};
const checker = (pageData, pageLinks) => {
const { members, redirects } = pageData;
console.log({ members, redirects });
for (const link of pageLinks) {
const href = link.getAttribute('href');
if (!href || !href.startsWith('/wiki/')) {
continue;
}
const title = decodeURIComponent(href.replaceAll('/wiki/', '').replaceAll('_', ' '));
if (title?.endsWith(' at the 2024 Summer Olympics')) {
continue;
}
const canonicalTitle = redirects[title] ?? title;
const included = members.includes(canonicalTitle);
// console.log(title, included)
if (!included) {
// link.setAttribute("data-canonical", canonicalTitle);
link.outerHTML += ` <button class="add-cat" data-canonical="${canonicalTitle}">ADD</button>`;
}
}
};
function init() {
api = new mw.Api({
ajax: {
// Use a user agent, so that sysadmins can find you and tell you to fix your tool
headers: { 'Api-User-Agent': 'w:en:User:Edgars2007/tokyo2020.js' },
},
});
var allLinks = document.getElementsByTagName('a');
var redirects = [].filter
.call(allLinks, (el) => el.classList.contains('mw-redirect'))
.map((element) => decodeURIComponent(element.getAttribute('href').replaceAll('/wiki/', '')));
var redirectNames = [...new Set(redirects)];
console.log(redirectNames);
getData(category, redirectNames).then((resp) => checker(resp, allLinks));
$(document).on('click', '.add-cat', (event) => {
handlePageEdit(event);
});
}
const getCompetitorsName = () => {
const pagetitle = mw.config.get('wgPageName').replace('_', ' ');
Object.keys(mapping).forEach(title => {
if (pagetitle.startsWith(title)) {
category = mapping[title];
return;
}
})
}
// mw.loader.using(['mediawiki.api', 'mediawiki.util'], init);
mw.loader.using(['mediawiki.api', 'mediawiki.util'], async () => {
mw.util.addPortletLink('p-cactions', '#', 'tokyo', 'ca-tokyo', 'Add participation category to articles', '5');
$(document).on('click', '#ca-tokyo', () => {
getCompetitorsName();
//category = prompt('Set category name');
init();
});
});