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

削除された内容 追加された内容
m v2.3R: LTA:HGTCHDPを追加
v3.0: プレビュー機能を追加他
2行目:
* AN Reporter (ANR)
* Author: Dragoniez
* Version: 23.3R0
*************************************/
//<nowiki>
14行目:
 
// Load CSS source for Select2
$('head').append($('<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css">'));
 
// Default CSS for Select2
$('head').append($(
'<style>' +
' .select2-selection__rendered {' +
29行目:
' }' +
'</style>'
));
 
// Run the script only if the user is autoconfirmed and the page is not an edit page
175行目:
` <option>新川温泉系 (SNKW)</option>` +
` <option>ソウ系(SOH)</option>` +
` <option>埼玉楽天モバイルIP系 (STRM)</option>` +
` <option>Suzukitaro系 (ツバル、SUZU)</option>` +
` <option>Syun respect for music系 (SYUN)</option>` +
186行目:
` <option>Wpcon abuse系 (WPCON)</option>` +
` <option>Yanajin33系(YAN)</option>` +
` <option>揶揄リダイレクト作成荒らし系(YAYURE)</option>` +
` <option>黄色関係のIP系 (YELLOW)</option>` +
` <option>Yqm系(YQM)</option>` +
217行目:
` <a id="anr-user1-a" href="" target="_blank"></a>` +
` </div>`;
// </div>
 
// The whole html contour
263行目:
 
// Add the frame div to the page
$('body').append($('<div class="anr-modal-dialog" title="AN Reporter" style="max-height: 80vh;"/>'));
 
// Create html elements inside the div
$('.anr-modal-dialog').html(modalHtml);
 
// Variables
const scriptAd = ' ([[User:Dragoniez/AN Reporter|AN Reporter]])';
 
// Show dialog
302 ⟶ 305行目:
},
'buttons': [{
'text': '報告',
 
// Event to trigger when the "報告"'Preview' button is hit
'text': 'プレビュー',
'click': function() {
 
// Check if atthe leastnecessary onefields usernameare is givenfilled and get users to report (and their UserANedit types)information
var usersep = []editPrep();
varif types(ep.rqFieldsEmpty) = [];{
for (let i = 1alert('必須項目が入力・選択されていません'); i// <Show Infinity; i++) { //error Loopand throughcancel allthe inputspreview
if ($(`#anr-user${i}-input`).length === 0) { // if selector is not foundreturn;
break; // exit for
} else { // if selector is found
if (trimA($(`#anr-user${i}-input`).val()) !== '') { // if input is not empty
users.push(trimA($(`#anr-user${i}-input`).val())); // Push the username into the array
types.push($(`#anr-user${i}-select`).children('option').filter(':selected').text()); // Push the UserAN type into the array
}
}
}
// Preview dialog contour
const ANSMisc = `<a href="${mw.util.getUrl('WP:AN/S#OTH')}" target="_blank">WP:AN/S#その他</a>`;
var previewDiv =
'<div class="anr-preview-dialog" title="AN Reporter - プレビュー">' +
' <div id="anr-preview-header" style="padding: 0.5em;">' +
' <p id="anr-preview-loading" style="font-weight: bold">' +
' プレビューを読み込み中...' +
' </p>' +
' <p id="anr-preview-warning" style="display: none;">' +
' 注意1: このプレビュー上のリンクは全て新しいタブで開かれます' +
' <br>' +
` 注意2: 報告先が ${ANSMisc} の場合、このプレビューには表示されませんが「他X月X日」のヘッダーは必要に応じて自動挿入されます` +
' </p>' +
' </div>' +
' <div id="anr-preview-body" style="display: none; font-size: 1.15em; padding: 1em 0; border-top: 1px solid silver;">' +
' <div id="anr-preview-text" style="border: 1px solid silver; padding: 0.2em 0.5em;">' +
// previewHtml
' </div>' +
' <div id="anr-preview-summary" style="margin-top: 0.8em; border: 1px solid silver; padding: 0.2em 0.5em;">' +
// summaryHtml
' </div>' +
' </div>' +
'</div>';
 
// Get the name of the section to edit Show preview dialog
var pageToEdit = $('#anr-target-optionsbody').children('option').filter(':selected').textappend(previewDiv);
var sectionToEdit = $('選択してください.anr-preview-dialog';).dialog({
var ANSOptSelected = $( '#anr-section-options-s').find('option').filter(height':selected 'auto').text();,
var reportToANS = false; 'width': $('#content').width() * 0.8,
'modal': true,
'buttons': [{
'text': '閉じる',
'click': function(){
$(this).dialog('close');
}
}],
'open': function(){
 
if (pageToEdit === ANI) { // If WP:AN //I isConvert selectedtext ason the target pagedialog to edithtml
new mw.Api().get({
'action': 'parse',
'text': ep.textToSubmit,
'summary': ep.editSummary,
'contentmodel': 'wikitext',
'prop': 'text',
'disableeditsection': true,
'formatversion': 2
}).then(function(res){
 
sectionToEdit = $ if ('#anr-section-options-i')res && res.children('option'parse).filter(':selected').text(); {
 
} else if (pageToEdit === ANS) { // If WP:AN/S is selected as the target page tovar previewHtml = editres.parse.text;
var rep = new RegExp('API', 'g');
var summaryHtml = res.parse.parsedsummary.replace(rep, ep.pageToEdit);
$('#anr-preview-text').append(previewHtml);
$('#anr-preview-summary').append(summaryHtml);
$('.autocomment a').css('color', 'gray'); // Change color of section spec in summary
$('.anr-preview-dialog a').attr('target', '_blank'); // Open all links on a new tab
$('#anr-preview-body').css('display', 'block');
$('#anr-preview-loading').css('display', 'none');
$('#anr-preview-warning').css('display', 'inline');
 
reportToANS = true; } else {
if (ANSOptSelected === 'Iccic系 $(Iccic'#anr-preview-loading').text('プレビューの読み込みに失敗しました').css('color', {'red');
pageToEdit = Iccic; setTimeout(function(){
sectionToEdit = $('.anr-preview-dialog').dialog('新規依頼close');
} else if (ANSOptSelected === 'いせちか系 (ISECHIKA)') { }, 3000);
pageToEdit = ISECHIKA; }
sectionToEdit = '新規依頼';
} else if (ANSOptSelected === '影武者系(KAGE)'}) {;
pageToEdit = KAGE;
sectionToEdit = '新規依頼';
} else if (ANSOptSelected === '清島達郎系 (清島、KIYOSHIMA)') {
pageToEdit = KIYOSHIMA;
sectionToEdit = '新規依頼';
} else if (ANSOptSelected === '真珠王子系(SHINJU)') {
pageToEdit = SHINJU;
sectionToEdit = '新規依頼';
} else {
sectionToEdit = ANSOptSelected;
}
});
}}, {
 
} else if (pageToEdit === AN3RR) { // If WP:AN/3RR is selected as the target page to報告 editbutton
'text': '報告',
'click': function() {
 
// Check if the sectionToEditnecessary =fields '3RR';are filled and get edit information
var ep = editPrep();
 
}if (ep.rqFieldsEmpty) {
 
if ( // Check if necessary fields are filled
pageToEdit === '選択してください' || // The page dropdown's remained 選択してください
sectionToEdit === '選択してください' || // The section dropdown's remained 選択してください
trimA($('#anr-reason-text').val()) === '' || // No reason is given
users.length === 0 // No username is given
) {
alert('必須項目が入力・選択されていません'); // Show error and cancel the edit
return;
379 ⟶ 413行目:
$dialog.dialog('option', 'width', width);
$dialog.dialog({'buttons': [] }); // Hide the button
$dialog.append($(msgEditing));
// UserAN template and the reason of the report
const UserAN = '{{UserAN|t=TYPE|USER}}';
var reason = trimA($('#anr-reason-text').val());
if (reason.substring(reason.length - 4) !== '~~~~') { // If reason doesn't contain signature, add one
reason = reason + '--~~~~';
}
 
// Get edit summary
const scriptAd = ' ([[User:Dragoniez/AN Reporter|AN Reporter]])';
const editSummarySection = '/*' + sectionToEdit + '*/';
 
var editSummary =
trimA($('#anr-summary-text').val()) === '' ?
editSummarySection + genEditSummary() + scriptAd:
editSummarySection + trimA($('#anr-summary-text').val()) + scriptAd;
 
// Get text to add to the page
var textToSubmit = '';
if (users.length < 2) { // If user to report is just one
textToSubmit = '* ' + UserAN.replace('TYPE', types[0]).replace('USER', users[0]) + ' - ' + reason;
} else { // If two or more
for (let i = 0; i < users.length; i++) {
textToSubmit += '\* ' + UserAN.replace('TYPE', types[i]).replace('USER', users[i]) + '\n';
}
textToSubmit += ': ' + reason;
}
 
// For debugging
//ep.pageToEdit = '利用者:Dragoniez/test';
//ep.editSummary = 'Test edit via mediawiki API';
 
// Get the wiki pagename for link
var wikiPagename = ep.pageToEdit + '#' + ep.sectionToEdit;
 
// Boolean value to pass to function when edit attempt is done
420 ⟶ 427行目:
// Get the latest revision
new mw.Api().get({
'action': 'query',
'titles': ep.pageToEdit,
'prop': 'revisions',
'curtimestamp': true,
'formatversion': 2
}).done(function(res1){
 
438 ⟶ 445行目:
' <p style="color: MediumSeaGreen">取得に成功しました</p>' +
' <p>セクション番号を取得しています</p>';
$('.anr-editing').append($(msgEditing));
 
// Get section numbers
444 ⟶ 451行目:
var msgDone = ''; // Message to show when edit attempt is done
new mw.Api().get({
'action': 'parse',
'page': ep.pageToEdit,
'formatversion': 2
}).done(function(res2){
 
456 ⟶ 463行目:
}
var sectionNum = sectionsAPI[ep.sectionToEdit];
if (sectionNum === undefined) { // If section title in the dropdown is not found
 
467 ⟶ 474行目:
`<p>2. 通信に失敗した</p>` +
`<p>3. スクリプトのバグ</p>` +
'<br>' +manualEdit();
$('<p>手動編集用:</p>.anr-editing' +).append(msgDone);
`<textarea disabled rows="4" style="width: 100%">${textToSubmit}</textarea>` +
'<br>' +
'<p>要約:</p>' +
`<textarea disabled rows="2" style="width: 100%">${editSummary.replace(scriptAd, '')}</textarea>`;
$('.anr-editing').append($(msgDone));
 
$dialog.dialog('option', 'width', width);
485 ⟶ 487行目:
' <p style="color: MediumSeaGreen">取得に成功しました</p>' +
' <p>最新版のテキストを取得しています</p>';
$('.anr-editing').append($(msgEditing));
 
// Get the text of the revision
new mw.Api().get({
'action': 'parse',
'page': ep.pageToEdit,
'section': sectionNum,
'prop': 'wikitext',
'formatversion': 2
}).done(function(res3){
 
502 ⟶ 504行目:
' <p style="color: MediumSeaGreen">取得に成功しました</p>' +
' <p>報告を試みています</p>';
$('.anr-editing').append($(msgEditing));
 
// Get the whole text to append
510 ⟶ 512行目:
const miscHeader = `{{bgcolor|#eee|{{Visible anchor|他${today()}}}|div}}`;
 
if (ep.reportToANS) { // If the target is WP:AN/S
 
// Add div if the target section is 'その他' but lacks div for the current date
if (ep.sectionToEdit === 'その他' && wikitextObtained.indexOf(miscHeader) === -1) {
ep.textToSubmit = '; ' + miscHeader + '\n\n' + ep.textToSubmit;
}
 
523 ⟶ 525行目:
wholeTextToSubmit =
wikitextSplit[0] + delimiter + trimA(wikitextSplit[1]) + '\n\n' +
ep.textToSubmit + '\n\n' + delimiter + wikitextSplit[2];
 
} else { // If section structure has been changed
533 ⟶ 535行目:
`<a href="${mw.util.getUrl('User talk:Dragoniez/AN Reporter')}" target="_blank">開発者</a>` +
'に連絡をお願いします</p>' +
'<br>' +manualEdit();
$('<p>手動編集用:</p>.anr-editing' +).append(msgDone);
`<textarea disabled rows="4" style="width: 100%">${textToSubmit}</textarea>` +
'<br>' +
'<p>要約:</p>' +
`<textarea disabled rows="2" style="width: 100%">${editSummary.replace(scriptAd, '')}</textarea>`;
$('.anr-editing').append($(msgDone));
 
$dialog.dialog('option', 'width', width);
550 ⟶ 547行目:
} else { // If the target is WP:AN/I or WP:AN/3RR
 
wholeTextToSubmit = trimA(wikitextObtained) + '\n\n' + ep.textToSubmit;
 
}
556 ⟶ 553行目:
// Edit the page
$.ajax({
'url': mw.util.wikiScript('api'),
'data': {
'format': 'json',
'action': 'edit',
'title': ep.pageToEdit,
'section': sectionNum,
'summary': ep.editSummary,
'basetimestamp': baseTS,
'starttimestamp': curTS,
'text': wholeTextToSubmit,
'token': mw.user.tokens.get('csrfToken'),
'curtimestamp': true
},
'dataType': 'json',
'type': 'POST',
success: function(res4) {
580 ⟶ 577行目:
// Show message
$('.anr-editing').append($(`<p style="color: MediumSeaGreen">報告が完了しました</p>`));
$dialog.dialog('option', 'width', width);
editDone($dialog, editFailed, wikiPagename, diffNum);
594 ⟶ 591行目:
'<p>詳細:</p>' +
`<p>${res4.error.info}</p>` +
'<br>' +manualEdit();
$('<p>手動編集用:</p>.anr-editing' +).append(msgDone);
`<textarea disabled rows="4" style="width: 100%">${textToSubmit}</textarea>` +
'<br>' +
'<p>要約:</p>' +
`<textarea disabled rows="2" style="width: 100%">${editSummary.replace(scriptAd, '')}</textarea>`;
$('.anr-editing').append($(msgDone));
 
$dialog.dialog('option', 'width', width);
611 ⟶ 603行目:
// Show message
msgDone =
'<p style="color: MediumVioletRed">不明なエラーが発生しました</p>' + manualEdit();
$('<br>.anr-editing' +).append(msgDone);
'<p>手動編集用:</p>' +
`<textarea disabled rows="4" style="width: 100%">${textToSubmit}</textarea>` +
'<br>' +
'<p>要約:</p>' +
`<textarea disabled rows="2" style="width: 100%">${editSummary.replace(scriptAd, '')}</textarea>`;
$('.anr-editing').append($(msgDone));
 
$dialog.dialog('option', 'width', width);
624 ⟶ 610行目:
editDone($dialog, editFailed, wikiPagename);
}
 
}
645 ⟶ 631行目:
 
msgDone =
'<p style="color: MediumVioletRed">エラー: 報告先のページが存在しません</p>' + manualEdit();
$('<br>.anr-editing' +).append(msgDone);
'<p>手動編集用:</p>' +
`<textarea disabled rows="4" style="width: 100%">${textToSubmit}</textarea>` +
'<br>' +
'<p>要約:</p>' +
`<textarea disabled rows="2" style="width: 100%">${editSummary.replace(scriptAd, '')}</textarea>`;
$('.anr-editing').append($(msgDone));
$dialog.dialog('option', 'width', width);
669 ⟶ 649行目:
function queryFailed() {
msgDone =
'<p style="color: MediumVioletRed">取得に失敗しました</p>' + manualEdit();
$('<br>.anr-editing' +).append(msgDone);
'<p>手動編集用:</p>' +
`<textarea disabled rows="4" style="width: 100%">${textToSubmit}</textarea>` +
'<br>' +
'<p>要約:</p>' +
`<textarea disabled rows="2" style="width: 100%">${editSummary.replace(scriptAd, '')}</textarea>`;
$('.anr-editing').append($(msgDone));
$dialog.dialog('option', 'width', width);
682 ⟶ 656行目:
editDone($dialog, editFailed, wikiPagename);
}
}
 
// Function to generate the html for the manul edit helper tab
}]
function manualEdit() {
var meHtml =
'<br>' +
'<p>手動編集用:</p>' +
`<textarea disabled rows="4" style="width: 100%">${ep.textToSubmit}</textarea>` +
'<br>' +
'<p>要約:</p>' +
`<textarea disabled rows="2" style="width: 100%">${ep.editSummary.replace(scriptAd, '')}</textarea>`;
return meHtml;
}
 
}
}]
});
 
// ********** EVENT HANDLERS **********
 
// Reset dialog when closed
$(document).on('dialogclose', '.anr-modal-dialog'), .on('dialogcloseanr-preview-dialog', function() {
$(this).remove();
});
746 ⟶ 731行目:
});
 
// Dynamically change the display of the form depending on the UserAN type
$(document).on('change','.anr-user-div select', function(e){
 
755 ⟶ 740行目:
var aDivID = selectID.replace('select', 'a-div'); // ID of div containing <a> tag
var aID = selectID.replace('select', 'a'); // ID of a
var valInput = trimA($(selectID.replace('select', 'input')).val()); // The input value
 
if (valSelected === 'UNL' || valSelected === 'User2' ) { // if type=UNL or User2
790 ⟶ 775行目:
resetDropdown(inputID, selectID);
 
});
// When 'hide username' is clicked, get logid, change dropdown options, show href and so on
806 ⟶ 791行目:
// Function to update type dropdown
var updateDropdown = function(logid) {
$(selectID).children('.anr-opt-UNL').prop('hidden', true);
$(selectID).children('.anr-opt-User2').prop('hidden', true);
812 ⟶ 797行目:
$(selectID).children('.anr-opt-logid').prop('hidden', false).prop('selected', true);
$(selectID).children('.anr-opt-diff').prop('hidden', false);
$(selectID).children('.anr-opt-none').prop('hidden', false);
$(aDivID).css('display', 'block');
$(aID).attr('href', mw.util.getUrl('Special:redirect/logid/' + logid)).text('特別:転送/logid/' + logid);
}
var logid;
if (objLogid[inputVal] !== undefined) {
823 ⟶ 808行目:
updateDropdown(objLogid[inputVal]);
} else {
// if the object doesn't know the logid for the user, ask the API
829 ⟶ 814行目:
// Get logid from the API
logid = await getLogid(inputVal);
// Check the obtained logid
853 ⟶ 838行目:
}, 0);
}
} else { // if the checkbox is unchecked
874 ⟶ 859行目:
'場合のみ、その逆の変換が可能です');
$(checkboxID).prop('checked', true);
}
}
897 ⟶ 882行目:
var $textarea = $('#anr-summary-text');
 
if ($(this).is(':checked')) { // Box is checked
 
// Show textarea
908 ⟶ 893行目:
 
// ********** USER-DEFINED FUNCTIONS **********
 
function editPrep() {
var rqFieldsEmpty = false;
 
// Check if at least one username is given and get users to report (and their UserAN types)
var users = [];
var types = [];
for (let i = 1; i < Infinity; i++) { // Loop through all inputs
if ($(`#anr-user${i}-input`).length === 0) { // if selector is not found
break; // exit for
} else { // if selector is found
if (trimA($(`#anr-user${i}-input`).val()) !== '') { // if input is not empty
users.push(trimA($(`#anr-user${i}-input`).val())); // Push the username into the array
types.push($(`#anr-user${i}-select`).children('option').filter(':selected').text()); // Push the UserAN type into the array
}
}
}
 
// Get the name of the section to edit
var pageToEdit = $('#anr-target-options').children('option').filter(':selected').text();
var sectionToEdit = '選択してください';
var ANSOptSelected = $('#anr-section-options-s').find('option').filter(':selected').text();
var reportToANS = false;
 
if (pageToEdit === ANI) { // If WP:AN/I is selected as the target page to edit
 
sectionToEdit = $('#anr-section-options-i').children('option').filter(':selected').text();
 
} else if (pageToEdit === ANS) { // If WP:AN/S is selected as the target page to edit
 
reportToANS = true;
if (ANSOptSelected === 'Iccic系 (Iccic)') {
pageToEdit = Iccic;
sectionToEdit = '新規依頼';
} else if (ANSOptSelected === 'いせちか系 (ISECHIKA)') {
pageToEdit = ISECHIKA;
sectionToEdit = '新規依頼';
} else if (ANSOptSelected === '影武者系(KAGE)') {
pageToEdit = KAGE;
sectionToEdit = '新規依頼';
} else if (ANSOptSelected === '清島達郎系 (清島、KIYOSHIMA)') {
pageToEdit = KIYOSHIMA;
sectionToEdit = '新規依頼';
} else if (ANSOptSelected === '真珠王子系(SHINJU)') {
pageToEdit = SHINJU;
sectionToEdit = '新規依頼';
} else {
sectionToEdit = ANSOptSelected;
}
 
} else if (pageToEdit === AN3RR) { // If WP:AN/3RR is selected as the target page to edit
 
sectionToEdit = '3RR';
 
}
 
if ( // Check if necessary fields are filled
pageToEdit === '選択してください' || // The page dropdown's remained 選択してください
sectionToEdit === '選択してください' || // The section dropdown's remained 選択してください
trimA($('#anr-reason-text').val()) === '' || // No reason is given
users.length === 0 // No username is given
) {
rqFieldsEmpty = true;
}
// UserAN template and the reason of the report
const UserAN = '{{UserAN|t=TYPE|USER}}';
var reason = trimA($('#anr-reason-text').val());
if (reason.substring(reason.length - 4) !== '~~~~') { // If reason doesn't contain signature, add one
reason = reason + '--~~~~';
}
 
// Get edit summary
const editSummarySection = '/*' + sectionToEdit + '*/';
 
var editSummary =
trimA($('#anr-summary-text').val()) === '' ?
editSummarySection + genEditSummary() + scriptAd:
editSummarySection + trimA($('#anr-summary-text').val()) + scriptAd;
 
// Get text to add to the page
var textToSubmit = '';
if (users.length < 2) { // If user to report is just one
textToSubmit = '* ' + UserAN.replace('TYPE', types[0]).replace('USER', users[0]) + ' - ' + reason;
} else { // If two or more
for (let i = 0; i < users.length; i++) {
textToSubmit += '\* ' + UserAN.replace('TYPE', types[i]).replace('USER', users[i]) + '\n';
}
textToSubmit += ': ' + reason;
}
 
// Return values
return {
'pageToEdit': pageToEdit,
'sectionToEdit': sectionToEdit,
'reportToANS': reportToANS,
'rqFieldsEmpty': rqFieldsEmpty,
'editSummary': editSummary,
'textToSubmit': textToSubmit
}
}
 
// Action for when edit is done (in any way)
943 ⟶ 1,029行目:
'text': '閉じる',
'click': function(){
$(this).dialog('close');
var curPage = mw.config.get('wgPageName');
if (
1,008 ⟶ 1,094行目:
default:
contribs = reportee;
}
 
// Push the link into the array
1,015 ⟶ 1,101行目:
}
 
}
i++;
 
1,034 ⟶ 1,120行目:
return textToShow;
 
}
 
});
1,086 ⟶ 1,172行目:
ususers: username,
formatversion: 2
}).done(function(res){
if (res.query.users[0].userid !== undefined) { // If user exists
resolve(1); // Return true
1,144 ⟶ 1,230行目:
$(checkboxID).prop('checked', false); // uncheck the checkbox
 
} else { // if something else (like random numbers or strings)
 
$(selectID).children('.anr-opt-UNL').prop('hidden', true);
1,182 ⟶ 1,268行目:
// Function to get account creation logid
async function getLogid(username) {
return new Promise(function(resolve, reject) {
new mw.Api().get({
action: 'query',
1,202 ⟶ 1,288行目:
// 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',
1,212 ⟶ 1,298行目:
arvdir: 'newer',
formatversion: 2
}).done(function(res){
if (res && res.query && res.query.allrevisions) {
var revArr = res.query.allrevisions;
for (let i = 0; i < revArr.length; i++) {
1,222 ⟶ 1,308行目:
resolve(undefined);
}
}
}
}
});
});
1,237 ⟶ 1,323行目:
// Function to check if an element is in an array
function isInArray (el, arr) {
if (arr.indexOf(el) !== -1) {
return true;
} else {
1,250 ⟶ 1,336行目:
} else {
return false;
}
}