「利用者:Dragoniez/scripts/AN Reporter.js」の版間の差分
削除された内容 追加された内容
v7.3: 潜在的な、テンプレートの表示バグに繋がりうるコーディングを修正 (関連: 特別:差分/90126179) |
v7.4: 報告先改名の下準備、多少立ち上げと報告処理を高速化、LTA名称リンクのコピー機能を追加、ブラウザ互換性向上に向けて多少改変 |
||
2行目:
* AN Reporter (ANR) *
* Author: Dragoniez *
* Version: 7.
************************************/
//<nowiki>
78行目:
// Debugging Mode
'scriptAd': false, // 'AN Reporter Experimental' if true
'editTarget': false, // 'User:Dragoniez/test' if true
'portletLink': false,
87 ⟶ 86行目:
'drPreviewSections': 'tarSectionsS' // I, S, 3RR, SubpagedLTA
};
var ScriptAd = ' ([[User:Dragoniez/scripts/AN Reporter|' + (DebugMode.scriptAd ? 'AN Reporter Experimental]])' : 'AN Reporter]])'),
PortletLinkText = DebugMode.portletLink ? '報告β' : '報告',
DeveloperLink = '<a href="' + mw.util.getUrl('User talk:Dragoniez/scripts/AN Reporter') + '" target="_blank">開発者</a>',
Library = DebugMode.library ?
'http://127.0.0.1:5500/dragoLib/dragoLib.js' : // Page names
// Iccic = ANS + '/Iccic',
// ISECHIKA = ANS + '/いせちか',
// KAGE = ANS + '/影武者',
// KIYOSHIMA = ANS + '/清島達郎',
// SHINJU = ANS + '/真珠王子',
var ANI = 'Wikipedia:管理者伝言板/投稿ブロック',
ANS = 'Wikipedia:管理者伝言板/投稿ブロック/ソックパペット',
AN3RR = 'Wikipedia:管理者伝言板/3RR',
Iccic = 'Wikipedia:進行中の荒らし行為/長期/Iccic/投稿ブロック依頼',
ISECHIKA = 'Wikipedia:管理者伝言板/投稿ブロック/いせちか',
KAGE = 'Wikipedia:管理者伝言板/投稿ブロック/影武者',
KIYOSHIMA = 'Wikipedia:管理者伝言板/投稿ブロック/清島達郎',
SHINJU = 'Wikipedia:管理者伝言板/投稿ブロック/真珠王子',
VIP = 'Wikipedia:進行中の荒らし行為',
TEST = '利用者:Dragoniez/test';
/**
* Object to store logids for usernames {user1: logid, user2: logid...}
*/
// Related to dialog creation
var userDiv
}, {
}, {
$(this).dialog('close');
}
132 ⟶ 142行目:
$.when(
$.getScript('https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js'),
$.getScript(
mw.loader.using('jquery.ui'),
$.ready
140 ⟶ 150行目:
$('head').append('<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css">'); // For Select2
$('head').append(
'.select2-selection__rendered {' +
'padding: 1px 2px;' +
'font-size: 1em;' +
'line-height: normal !important;' +
'}' +
'.select2-results__option,' +
'.select2-results__group {' + 'padding: 1px 8px;' +
'font-size:
'margin: 0;' +
'}' +
'.select2-container,' +
'.select2-selection--single {' + 'height: auto !important;' +
'}' +
'.anr-dialog-label {' +
'display: inline-block;' +
'width: 8ch;' +
'}' +
'.anr-dialog-select,' +
'.anr-dialog-input {' + 'border: 1px solid #d3d3d3;' +
'border-radius: 1%;' +
'background-color: white;' +
'padding: 2px 4px;' +
'}' +
'.anr-dialog-button {' +
'color: black;' +
'font-weight: normal;' +
'border: 1px solid #d3d3d3;' +
'background-color: white;' +
'padding: 0.2em 0.5em;' +
'border-radius: 10%;' +
'}' +
'.anr-dialog-textarea {' +
'width: 100%;' +
'box-sizing: border-box;' +
'}' +
'.anr-dialog-needmargin {' +
'margin:
'}' +
'#anr-modal-dialog input {' +
'margin-right: 0.3em;' +
'}' +
'</style>'
);
185 ⟶ 201行目:
if (dragoLib.inGroup('autoconfirmed') && mw.config.get('wgAction') !== 'edit') {
// Add a portletlink for ANR
$(mw.util.addPortletLink(anrConfig.portletlinkPosition, '#',
}
196 ⟶ 212行目:
// The whole html contour
'<option selected>定型文を使用する場合は選択してください</option>' +
'</select>' +
'</div>' +
'<input checked id="anr-blockstatus-checkbox" type="checkbox">' +
'<label for="anr-blockstatus-checkbox">報告前にブロック状態をチェック</label>' +
'<br>' +
'<input checked id="anr-duplicatereport-checkbox" type="checkbox">' +
'<label for="anr-duplicatereport-checkbox">報告前に重複報告をチェック</label>' +
'<br>' +
'<input checked id="anr-watchlist-checkbox" type="checkbox">' +
'<label for="anr-watchlist-checkbox">報告対象者をウォッチリストに追加</label>' +
'</div>' +
'</form>' +
'</div>' +
'</div>';
// Add the frame div to the page
$('body').append(
// Show dialog
324 ⟶ 349行目:
'modal': true,
'open': initializeAnrDialog,
'buttons':
});
335 ⟶ 360行目:
userCnt = 1;
dragoLib.dialogCSS(anrConfig.headerColor, anrConfig.backgroundColor, anrConfig.fontSize); // Initialize the design of the dialog
getSectionTitles();
getLtaList();
getPredefinedReasons(); // Show the select box for predefined reasons
// Add to wathchlist?
if (anrConfig.addToWatchlist === false)
// Get the name of the user to report if it can be retrieved from the page
350 ⟶ 373行目:
// Workaround to pick up IP ranges
if (!username && mw.config.get('wgCanonicalSpecialPageName') === 'Contributions') {
if (mw.util.isIPAddress(relUsername, true)) username = relUsername;
}
358 ⟶ 381行目:
// Initialize the username input and type dropdown
selectID = '#anr-user1-select', checkboxDivID = '#anr-user1-checkbox-div'; $(inputID).val(username); // Fill the input with the username
384 ⟶ 409行目:
$(checkboxDivID).css('display', 'block'); // show 'hide username' checkbox
toggleBlockStatusLink(inputID, false, false);
}
}
/**
* Get the section titles of WP:AN/S and WP:VIP, sort them out, and show then on the dialog as dropdown options
* @returns {jQuery.Promise}
*/
function getSectionTitles() {
var def = new $.Deferred();
var $label = $('#anr-target-options-label'); // Label of '報告先'
$label.append(dragoLib.toggleLoadingSpinner('add')); // Show a loading spinner while trying to get sections on WP:AN/S
// Get the latest revisions of the two pages including their contents
dragoLib.getLatestRevision([ANS, VIP]).then(function(lr) {
dragoLib.toggleLoadingSpinner('remove');
return alert('WP:AN/Sのセクション情報の取得に失敗しました。ダイアログを開き直すと改善する場合があります。');
}
// Create an object
var pages =
'
'
'
'
'
'
'
'
'暫定D',
'N. 未分類',
'サブページなし',
'休止中N'
]
},
VIP: {
content: undefined,
sections: undefined,
exclude: [
'記述について',
'急を要する二段階',
'配列',
'ブロック等の手段',
'このページに利用者名を加える',
'注意と選択',
'警告の方法',
'未登録(匿名・IP)ユーザーの場合',
'登録済み(ログイン)ユーザーの場合',
'警告中',
'関連項目'
]
}
};
// Get the content of each page from the resnpose of the API request
lr.forEach(function(obj) {
if (obj.title === ANS) pages.ANS.content = obj.content;
if (obj.title === VIP) pages.VIP.content = obj.content;
});
// Get setion titles of WP:AN/S and add them to the dropdown
if (pages.ANS.content) pages.ANS.sections = dragoLib.parseContentBySection(pages.ANS.content);
var sectionTitles;
if (pages.ANS.sections && pages.ANS.sections.length !== 0) {
sectionTitles = pages.ANS.sections.filter(function(obj) {
return obj.title && $.inArray(obj.title, pages.ANS.exclude) === -1;
}).map(function(obj) {
return '<option>' + obj.title + '</option>';
});
if (sectionTitles.length !== 0) $('#anr-section-s-lta').append(sectionTitles.join(''));
dragoLib.toggleLoadingSpinner('remove');
}
// Get setion titles of WP:VIP and add them to the dropdown
if (pages.VIP.content) pages.VIP.sections = dragoLib.parseContentBySection(pages.VIP.content);
var sectionTitles;
if (pages.VIP.sections && pages.VIP.sections.length !== 0) {
sectionTitles = pages.VIP.sections.filter(function(obj) {
return obj.title && $.inArray(obj.title, pages.VIP.exclude) === -1 && obj.level === 3;
}).map(function(obj) {
return '<option>' + obj.title + '</option>';
});
if (sectionTitles.length !== 0) {
$('#anr-viplist-select')
.css('width', $('#anr-target-options').innerWidth())
.select2()
.children('optgroup').append(sectionTitles.join(''));
$('#anr-viplist-div').css('display', 'block');
dragoLib.centerDialog('#anr-modal-dialog');
}
}
});
return def.promise();
}
/**
* Get a list of LTA names
* @returns {jQuery.Promise}
*/
function getLtaList() {
// Prepare an independent function as a workaround for when more than 500 names match
var ltalist = [];
var query = function(apcontinue) {
var deferred = new
new
action: '
list: '
apprefix: '
apnamespace: '0',
apfilterredir: 'redirects',
aplimit: '
var resPages;
if (!res || !res.query || !(resPages = res.query.allpages)) return deferred.resolve();
resPages.forEach(function(obj) {
if (obj.title !== 'LTA:' && obj.title.match(/^LTA:/) && obj.title.indexOf('/') === -1) ltalist.push(obj.title.replace(/^LTA:/, ''));
});
if (res.continue) {
query(res.continue.apcontinue).then(function() {
deferred.resolve();
});
} else {
deferred.resolve();
}
}
return deferred.promise();
};
query().then(function() {
if (ltalist.length === 0) return def.resolve();
ltalist = ltalist.map(function(lta) {
return '<option>' + lta + '</option>';
}).sort();
$('#anr-ltalist-select')
.css('width', $('#anr-target-options').innerWidth())
.select2()
.children('optgroup').append(ltalist.join(''));
$('#anr-ltalist-div').css('display', 'block');
dragoLib.centerDialog('#anr-modal-dialog');
def.resolve();
});
return def.promise();
}
483 ⟶ 596行目:
// Function to show the select div for predefined report reasons if they're predefined
function getPredefinedReasons() {
if (typeof pdReasons !== 'undefined' && !$.isEmptyObject(pdReasons)) { // If the user has fixed reasons prepared
$reasons.css('width', $('#anr-target-options').innerWidth()).select2();
for (
$reasons.children('optgroup').append(
}
$('#anr-predefinedreasons-div').css('display', 'block');
589 ⟶ 702行目:
// Check if necessary fields are filled
if (pageToEdit === '選択してください' || sectionToEdit === '選択してください' || reason === '' || users.length === 0) {
return alert('必須項目が入力・選択されていません');
}
602 ⟶ 714行目:
// If the reason doesn't contain a signature, add one
if (reason.substring(reason.length - 4) !== '~~~~')
// Get edit summary
632 ⟶ 742行目:
const customSummary = dragoLib.trim2($('#anr-summary-text').val()),
editSummarySection = '/*' + sectionToEdit + '*/';
const editSummary = editSummarySection + '+' + summaryLinks + (customSummary ? ' - ' + customSummary : '') +
// Get text to add to the page
647 ⟶ 757行目:
'users': users,
'types': types,
'pageToEdit':
'sectionToEdit': sectionToEdit,
'wikiPagename':
'reportToANS': reportToANS,
'editSummary'
'reportText': reportText
};
}
782 ⟶ 893行目:
$(this).dialog({
'width': 'auto',
'buttons':
});
}
849 ⟶ 960行目:
var msg = `<p>最新版を取得しています${dragoLib.toggleLoadingSpinner('add')}</p>`;
$('.anr-editing').append(msg);
if (!lr || lr.length === 0) return queryFailed(ep);
lr =
// Parse the content by section and get the content and number of the section to which the report will be added
var sections = dragoLib.parseContentBySection(lr.content);
var sectionNum, wikitext;
if (sections && sections.length !== 0) {
sections.some(function(obj) {
if (obj.title === ep.sectionToEdit) {
sectionNum = obj.index;
wikitext = obj.content;
return true;
}
});
}
if (!sectionNum) return sectionNotFound(ep);
//
var reportText;
if (
// Add div if the target section is 'その他' but lacks div for the current date
var miscHeader = `{{bgcolor|#eee|{{Visible anchor|他${dragoLib.today()}}}|div}}`;
if (ep.sectionToEdit === 'その他' && wikitext.indexOf(miscHeader) === -1) ep.reportText = '; ' + miscHeader + '\n\n' + ep.reportText;
// Get the report text to submit
var sockInfo = dragoLib.findTemplates(wikitext, 'sockinfo'); // Array
if (sockInfo.length === 1) { // One section on WP:AN/S should have one SockInfo
sockInfo = sockInfo[0];
var sockInfoNoClosure = dragoLib.trim2(sockInfo.substring(0, sockInfo.length - 2));
reportText = wikitext.replace(sockInfo, sockInfoNoClosure + '\n\n' + ep.reportText + '\n\n}}');
} else { // There's a problem with SockInfo
msg = // Show error and quit the procedure
dragoLib.toggleLoadingSpinner('remove') +
'<p style="color: MediumVioletRed">取得に失敗しました</p>' +
`<p>報告先セクションに{{SockInfo}}がない、または複数個あるため報告場所を特定できませんでした</p>` +
manualEdit(ep);
$('.anr-editing').append(msg);
editDone(ep, true);
return;
}
} else { // If the target is WP:AN/I or WP:AN/3RR
reportText = dragoLib.trim2(wikitext) + '\n\n' + ep.reportText;
}
msg = '<p style="color: MediumSeaGreen">取得に成功しました</p>' +
`<p>報告を試みています${dragoLib.toggleLoadingSpinner('move')}</p>`;
904 ⟶ 1,012行目:
// Edit
const result = await new mw.Api().post({
action: 'edit',
title: ep.pageToEdit,
section: sectionNum,
text: reportText,
basetimestamp: lr.basetimestamp,
starttimestamp: lr.curtimestamp,
summary: ep.editSummary,
token: DebugMode.causeIntentionalError ? '' : mw.user.tokens.get('csrfToken'),
format: 'json'
}).then(function(res) {
if (res && res.edit) {
if (res.edit.result === 'Success') return true;
}
return false;
}).catch(function(code, err) {
return err.error.info;
});
dragoLib.toggleLoadingSpinner('remove');
switch(result) {
1,057 ⟶ 1,182行目:
break;
case TEST: // For debugging
eval(`tarSections = ${
break;
default: // Error: Target pagename not defined
1,063 ⟶ 1,188行目:
dragoLib.toggleLoadingSpinner('remove') +
'<p style="color: MediumVioletRed">致命的なエラーが発生しました</p>' +
`<p>${
manualEdit(ep);
$('.anr-editing').append(msg);
1,192 ⟶ 1,317行目:
'<p>手動編集用:</p>' +
`<textarea disabled class="anr-dialog-textarea" rows="3">${ep.reportText}</textarea>` +
`<textarea disabled class="anr-dialog-textarea" rows="2" style="margin-top: 0.5em;">${ep.editSummary.replace(
return meHtml;
}
1,465 ⟶ 1,590行目:
// ******************** EVENT HANDLERS ********************
// Copy a VIP/LTA name when the selection is changed
$(document).off('change', '#anr-viplist-select, #anr-ltalist-select').on('change', '#anr-viplist-select, #anr-ltalist-select', function() {
var id = $(this).prop('id'),
selectVal = $('#' + id).find('option').filter(':selected').text().trim();
switch (id) {
case 'anr-viplist-select':
dragoLib.copyToClipboard('[[WP:VIP#' + selectVal + ']]');
break;
case 'anr-ltalist-select':
dragoLib.copyToClipboard('[[LTA:' + selectVal + ']]');
}
});
|