「利用者:Dragoniez/scripts/AN Reporter.js」の版間の差分

削除された内容 追加された内容
v4.3: 報告対象アカウントが4つ以上の場合、編集要約が「+4」などの形式で生成されるように変更
v4.4: VIP名称リスト表示機能の不明なバグを修正、報告後の差分表示機能を除去、コードのクリーンナップ
2行目:
* AN Reporter (ANR)
* Author: Dragoniez
* Version: 4.34
*************************************/
//<nowiki>
57行目:
};
 
// Define********** thePREPARATIONS positionBEFORE ofOPENING theTHE '報告'DIALOG button**********
 
let btnPosition;
// Debugging Mode
const debugMode = {
'scriptAd': false, // 'AN Reporter Experimental' if true
'editSummary': false, // 'Test edit via mediawiki API' + scriptAd if true
'editTarget': false, // 'User:Dragoniez/test' if true
'portletLink': false,
'causeIntentionalError': false
};
if (debugMode.scriptAd) {
var scriptAd = ' ([[User:Dragoniez/AN Reporter|AN Reporter Experimental]])';
} else {
var scriptAd = ' ([[User:Dragoniez/AN Reporter|AN Reporter]])';
}
if (debugMode.portletLink) {
var portletLinkText = '報告β';
} else {
var portletLinkText = '報告';
}
 
// Skin-dependent options
let btnPosition; // Where to place the '報告' link
let fSize; // Font size of the elements on the dialog
let s2fSize; // Font size of Select2 dropdown options
111 ⟶ 132行目:
let Logids = {}; // Object to store usernames and their corresponding logids
let checkBlockStatusBeforeEdit = true;
let checkDuplicateReportsBeforeEdit = true;
 
// Add ANR tab ('報告β' when debugging)
$(mw.util.addPortletLink(btnPosition, '#', '報告'portletLinkText, 'ca-anr', '管理者伝言板に利用者を報告', null, '#ca-move'))
.click(function(e){
 
364 ⟶ 385行目:
// Add the frame div to the page
$('body').append(modalHtml);
 
// Script ad for edit summary
const scriptAd = ' ([[User:Dragoniez/AN Reporter|AN Reporter]])';
//const scriptAd = ' ([[User:Dragoniez/AN Reporter|AN Reporter Experimental]])'; // For debugging
// Show dialog
466 ⟶ 483行目:
// WP:VIP list (for copy to clipboard)
async function VIPList() {
return new Promise(function(resolve, reject) {
new mw.Api().get({
'action': 'parse',
493 ⟶ 510行目:
let vipList = [];
for (let i = 0; i < sectionInfo.length; i++) {
if (!isInArray(sectionInfo[i].line, excludeList) && sectionInfo[i].level === '3') {
vipList.push(`<option>${sectionInfo[i].line}</option>`);
}
}
 
//if Show(vipList.length the=== VIP0) list on the dialog{
const VIPListHtml = resolve(mw.log.error('VIP list: There\'s no VIP to fetch.'));
'<div} class="anr-viplist-div"else style="width: 100%;">' +{
 
' <select id="anr-viplist-select">' +
' // Show the <optionVIP selectedlist disabledon hidden>[[Wikipedia:進行中の荒らし行為]]を検索</option>'the +dialog
const VIPListHtml vipList.join() +=
' '</selectdiv class="anr-viplist-div" style="width: 100%;">' +
` ' <buttonselect type="button" classid="anr-viplist-btnselect" style="${btnCSS}">コピー</button>`' +
' <option selected disabled hidden>[[Wikipedia:進行中の荒らし行為]]を検索</divoption>'; +
$('.anr-reason-div') vipList.beforejoin(VIPListHtml); +
$( '#anr-viplist- </select>').select2(); +
resolve(); ` <button type="button" class="anr-viplist-btn" style="${btnCSS}">コピー</button>` +
'</div>';
$('.anr-reason-div').before(VIPListHtml);
$('#anr-viplist-select').select2();
resolve();
 
}
 
} else {
resolve(mw.log.error('VIP list: The API returned an unresolvable object.'));
}
 
}).catch(function(){
resolve(mw.log.error('VIP list: Failed to retrieve data from the API.'));
});
});
653 ⟶ 676行目:
default:
sectionToEdit = ANSOptSelected;
}
 
} else if (pageToEdit === AN3RR) { // If WP:AN/3RR is selected as the target page to edit
728 ⟶ 751行目:
ep.duplicates.join(', ') + '\n\n' +
'プレビューを続行する場合は OK を、フォームに戻る場合は Cancel を押してください';
 
if (confirm(confirmMsg) === false) { // If cancelled
return;
772 ⟶ 795行目:
 
// Convert text on the dialog to html
const parsed = await convertWikitextToHtmlconvertWikitextToHtmlFormat(ep.textToSubmit, ep.editSummary);
if (parsed) {
 
800 ⟶ 823行目:
}]
});
 
}
 
809 ⟶ 832行目:
* @returns {{htmltext: string, htmlsummary: string}}
*/
async function convertWikitextToHtmlconvertWikitextToHtmlFormat(wikitext, wikisummary) {
return new Promise(function(resolve, reject) {
new mw.Api().post({
 
$.ajax({ 'action': 'parse',
'urltext': mw.util.wikiScript('api')wikitext,
'datasummary': {wikisummary,
'formatcontentmodel': 'jsonwikitext',
'actionprop': 'parsetext',
'textdisableeditsection': wikitexttrue,
'summaryformat': wikisummary,'json'
}).then(function(res) 'contentmodel': 'wikitext',{
'prop': 'text',
'disableeditsection': true
},
'dataType': 'json',
'type': 'POST',
success: function(res) {
resolve({
'htmltext': res.parse.text['*'],
'htmlsummary': res.parse.parsedsummary['*']
});
}).catch(function(err) },{
error: functionresolve(console.log(err) {);
console.log(err);
resolve();
}
});
 
});
}
844 ⟶ 857行目:
 
// Check if the necessary fields are filled and get edit information
letconst ep = editPrep();
if (ep.rqFieldsEmpty) {
alert('必須項目が入力・選択されていません'); // Show error and cancel the edit
853 ⟶ 866行目:
if (ep.duplicates.length !== 0) {
 
letconst confirmMsg =
'以下の利用者について、重複入力がある可能性があります。\n\n' +
ep.duplicates.join(', ') + '\n\n' +
865 ⟶ 878行目:
 
// Variables for edit
letconst $dialog = $('.anr-modal-dialog');
const dWidth = $dialog.width();
let msgEditing = '<div class="anr-editing" />';
let msgDone = ''; // Message to show when edit attempt is done
letconst wikiPagename = ep.pageToEdit + '#' + ep.sectionToEdit; // The wiki pagename for link
let editFailed = false; // Boolean value to pass to function when edit attempt is done
 
879 ⟶ 892行目:
 
// For debugging
//ep.pageToEditif =(debugMode.editSummary) '利用者:Dragoniez/test';{
// ep.editSummary = 'Test edit via mediawiki API' + scriptAd;
}
if (debugMode.editTarget) {
ep.pageToEdit = '利用者:Dragoniez/test';
}
 
/**
929 ⟶ 946行目:
$('.anr-editing').append(msgEditing);
let inputVal;
let $bsLinkDiv;
let $bsLink;
 
// Update dialog
for (let i = 1; i < Infinity; i++) { // Loop through all inputs
942 ⟶ 955行目:
} else { // if selector is found
 
const inputVal = $(`#anr-user${i}-input`).val().trim2();
const $bsLinkDiv = $(`#anr-user${i}-blockstatus-div`);
const $bsLink = $(`#anr-user${i}-blockstatus`);
 
$bsLinkDiv.css('display', 'none'); // Temporarily hide the div
1,239 ⟶ 1,252行目:
async function getLastestRevision() {
 
return new Promise(function(resolve, reject) {
 
msgEditing =
1,297 ⟶ 1,310行目:
// Function to get the section number from the section title
async function getSectionNumber() {
return new Promise(function(resolve, reject) {
new mw.Api().get({
1,311 ⟶ 1,324行目:
for (let i = 0; i < Object.keys(res.parse.sections).length; i++) {
sectionsAPI[res.parse.sections[i].line] = res.parse.sections[i].index;
}
// Return a section number if the section is found, undefined if not
1,345 ⟶ 1,358行目:
// Function to get the text to replace with the current text in the section
async function getTextToReplace(sectionNum) {
return new Promise(function(resolve, reject) {
// Get the text of the latest revision
1,435 ⟶ 1,448行目:
'basetimestamp': baseTS,
'starttimestamp': curTS,
'token': debugMode.causeIntentionalError ? '': mw.user.tokens.get('csrfToken'), // May comment this out for debugging
'curtimestamp': true
},
1,444 ⟶ 1,457行目:
// If the edit was successful
if (res && res.edit && res.edit.result == 'Success') {
setTimeout(async function(){
const diffNum = await getDiffNum(res.curtimestamp); // Get diff number
// Show message
toggleLoadingSpinner('remove');
$('.anr-editing').append(`<p style="color: MediumSeaGreen">報告が完了しました</p>`);
editDone($dialog, editFailed, wikiPagename, diffNum);
return;
 
}, 0);
 
// If the edit failed
1,685 ⟶ 1,693行目:
 
// Convert the wikitext to an html form
const wikitextInHtml = await convertWikitextToHtmlconvertWikitextToHtmlFormat(wikitext, '');
if (wikitextInHtml) {
1,891 ⟶ 1,899行目:
 
// Action for when edit is done (in any way)
function editDone($dialog, editFailed, wikiPagename, diffNum) {
 
// Get the page name without a section specifier
let tarPage = wikiPagename.split('#')[0];
// ButtonButtons to jumpshow toon the dialog when the edit attempt is diffdone
let btns = [];
let diffBtn, destBtn, closeBtn;
if (diffNum !== undefined) { // Show the button only if diff number is available
diffBtn = {
'text': '差分',
'click': function(){
window.open(mw.util.getUrl('特別:差分/' + diffNum), '_blank');
}
};
btns.push(diffBtn);
}
 
// Button to jump to the report page
2,147 ⟶ 2,146行目:
$(idlinkID).attr('href', mw.util.getUrl('Special:redirect/logid/' + logid)).text('特別:転送/logid/' + logid);
toggleBlockStatusLink(inputID, true, true);
}
if (Logids[inputVal] !== undefined) {
2,222 ⟶ 2,221行目:
$('.anr-addBtn').click(function(){
 
userCnt++;
let replaceTar = new RegExp(`${userCnt-1}-`, 'g');
userHtml = userHtml.replace(replaceTar, `${userCnt}-`); // 1 → 2, 2 → 3 and so forth
2,337 ⟶ 2,336行目:
// Function to check if a user exists locally
async function userExists(username) {
return new Promise(function(resolve, reject) {
new mw.Api().get({
'action': 'query',
2,344 ⟶ 2,343行目:
'formatversion': 2
}).done(function(res){
if resolve(res.query.users[0].userid !== undefined) {; // IfTrue if the user exists and false if not
resolve(1); // Return true
} else { // If user doesn't exist
resolve(0); // Return false
}
});
});
2,370 ⟶ 2,365行目:
$(selectID).prop('disabled', true).children('.anr-opt-none').prop('selected', true); // Disable dropdown and select 'none'
$(checkboxDivID).css('display', 'none'); // Hide 'hide username' checkbox
$(checkboxID).prop('checked', false); // Uncheck the checkbox
$(idlinkDivID).css('display', 'none'); // Hide logid/diff link
toggleBlockStatusLink(inputID, true, false);
2,512 ⟶ 2,507行目:
 
// API query
return new Promise(function(resolve, reject) {
new mw.Api().get({
'action': 'query',
2,558 ⟶ 2,553行目:
// Function to check if a given IP is blocked (true if the IP is blocked and false if not)
async function ipIsBlocked(ip) {
return new Promise(function(resolve, reject) {
new mw.Api().get({
2,568 ⟶ 2,563行目:
'formatversion': 2
}).done(function(res){
resolve(res.query.blocks.length !== 0);
if (res.query.blocks.length !== 0) { // If the IP is blocked
 
resolve(true);
} else { // If the IP is NOT blocked
 
resolve(false);
}
 
});
 
2,586 ⟶ 2,571行目:
// Function to get account creation logid
async function getLogid(username) {
return new Promise(function(resolve, reject) {
new mw.Api().get({
'action': 'query',
2,603 ⟶ 2,588行目:
});
}
 
// Function to get diff number and its URL after edit
async function getDiffNum(curtimestamp) {
return new Promise(function(resolve, reject) {
new mw.Api().get({
'action': 'query',
'list': 'allrevisions',
'arvprop': 'ids|timestamp',
'arvlimit': 5,
'arvuser': mw.config.get('wgUserName'),
'arvstart': curtimestamp,
'arvdir': 'newer',
'formatversion': 2
}).done(function(res){
if (res && res.query && res.query.allrevisions) {
let revArr = res.query.allrevisions;
for (let i = 0; i < revArr.length; i++) {
if (revArr[i].revisions[0].timestamp === curtimestamp) {
resolve(revArr[i].revisions[0].revid);
}
if (i === revArr.length -1) {
resolve();
}
}
}
});
});
}
} // if (userIsInGruoup)