Документация

Система шаблонов {{ЗКА:Быстрые}} и {{ЗКА:Быстрый запрос}} поддерживает страницу Википедия:Запросы к администраторам/Быстрые (ВП:ЗКАБ).

Она работает с помощью:

Использование

Шаблон для вставки {{ЗКА:Быстрый запрос}}:

{{ЗКА:Быстрый запрос|
<!-- Не редактируйте эту строку, если не являетесь администратором -->
| статус = 
<!-- Участник, IP-адрес или название страницы -->
| вопрос = 
<!-- Дополнительные действия для выполнения запроса, пояснения администраторам и т. п. -->
| пояснение = 
<!-- Не редактируйте эту строку -->
| автор = {{подст:зкаб}}
<!-- Администраторам: вставьте {{подст:зкаб|}} -->
| администратор = 
}}
require( 'strict' )
local p = {}

local page = 'Википедия:Запросы к администраторам/Быстрые'
local substPage = 'Шаблон:ЗКА:Быстрый запрос/subst'

local botList = {
	['Рейму Хакурей'] = true,
	['NapalmBot'] = true,
	['QBA-bot'] = true,
	['QBA-II-bot'] = true,
}

local getArgs = require( 'Module:Arguments' ).getArgs
local isIp = require( 'Module:IPAddress' )._isIp
local mwLang = mw.language.getContentLanguage()

local function isEmpty( val )
	return val == nil or val == ''
end

local function getTimestamp( request, author )
	if isEmpty( request ) or isEmpty( author ) then
		return nil
	end
	local s = mw.text.split( author, '/', true )
	local timestamp = s[ 2 ]
	if isEmpty( timestamp ) then
		return nil
	end
	return timestamp
end

local function getToggleTooltip( status )
	local tooltip = 'Показать итог от администратора, '
	if status == '+' then
		tooltip = tooltip .. ' выполнившего запрос'
	elseif status == '-' then
		tooltip = tooltip .. ' отклонившего запрос'
	else
		tooltip = tooltip .. ' <нет действия>'
	end
	
	return tooltip
end

local function parseStatus( status, part, admin )
	if isEmpty( status ) then
		return nil
	end
	
	-- Do not return anything if admin field is filled incorrectly
	if isEmpty( admin ) or mw.ustring.match( admin, '[^/]+/%d%d%d%d%d%d%d%d%d%d%d%d%d%d' ) == nil then
		return nil
	end

	-- Return status code: + or -
	if part == 1 then
		if mw.ustring.match( status, '%S' ) == '-' then
			return '-'
		else
			return '+'
		end
	end

	-- Return status text
	if part == 2 then
		local result = mw.ustring.gsub( status, '^%s*[+-]%s*/?', '' )
		return result
	end
end

local function renderError( error )
	local html = mw.html.create( 'strong' )
		:addClass( 'error' )
		:wikitext( 'Укажите, кто и когда установили шаблон.' )
	
	return tostring( html )
end

local function renderIcon( timestamp, status, response, admin )
	local icons = {
		['+'] = '[[File:OOjs UI icon check-progressive.svg|20px|link=|alt=Выполнен]]',
		['-'] = '[[File:OOjs UI icon close-ltr-destructive.svg|20px|link=|alt=Отклонён]]'
	}
	
	if isEmpty( response ) then
		return icons[ status ]
	end
	
	local icon = mw.ustring.gsub( icons[ status ], '%]%]', ' (есть итог)]]' )
	local html = mw.html.create( 'div' )
		:addClass( 'mw-customtoggle-raaf-' .. timestamp )
		:attr( 'title', getToggleTooltip( status ) )
		:wikitext( tostring( icon ) )
	return tostring( html )
end

local function renderDesc( timestamp, request, comment, status, response )
	if isEmpty( request ) then
		return renderError( 'Укажите причину запроса (страницу или участника).' )
	end
	
	local frame = mw.getCurrentFrame()
	local html = mw.html.create()
	
	local req = mw.text.split( request, '/', true )
	local type = req[ 1 ]
	local target = req[ 2 ] or req[ 1 ]
	
	local userTargets = {
		['айпи'] = true,
		['ip'] = true,
		['у'] = true,
		['участник'] = true,
		['u'] = true,
		['user'] = true,
	}
	
	local template = 'Pagelinks'
	if userTargets[ type ] then
		template = 'Userlinks'
	else
		target = request
	end
	
	local req = html:tag( 'div' )
		:addClass( 'tmpl-raaf-request' )
	
	if template == 'Userlinks' then
		req:tag( 'span' )
			:addClass( 'sr-only' )
			:wikitext( 'Учётная запись: ' )
	end
	req:wikitext( frame:expandTemplate{ title = template, args = { target } } )
	
	if not isEmpty( comment ) then
		html:tag( 'div' )
			:addClass( 'tmpl-raaf-comment' )
			:wikitext( comment )
	end
	
	if not isEmpty( response ) then
		local noComment = ''
		if isEmpty( comment ) then
			noComment = ' is-descriptionless'
		end
		html:tag( 'span' )
			:addClass( 'raaf-result-toggle tmpl-raaf-toggle ' .. noComment )
			:addClass( 'mw-customtoggle-raaf-' .. timestamp )
			:attr( 'title', getToggleTooltip( status ) )
			:tag( 'span' )
				:wikitext( 'Итог' )
	end
	
	return tostring( html )
end

local function renderUser( userInfo )
	if isEmpty( userInfo ) then
		return renderError( 'Укажите, кто и когда установили шаблон.' )
	end
	
	local s = mw.text.split( userInfo, '/', true )
	local user = s[ 1 ]
	local timestamp = s[ 2 ]
	if isEmpty( timestamp ) then
		return renderError( 'Укажите, кто и когда установили шаблон.' )
	end
	
	local html = mw.html.create()
	
	-- Check if user is a bot
	if botList[ user ] then
		html:tag( 'abbr' )
			:addClass( 'botedit' )
			:attr( 'title', 'Этот запрос добавлен ботом' )
			:wikitext( 'б' )
			:done()
			:wikitext( ' ' )
	end
	
	local linkTarget = 'user:' .. user
	if isIp( user ) then
		linkTarget = 'Special:Contributions/' .. user
	end
	
	html
		:wikitext( string.format( '[[%s|%s]] ([[%s|обс.]])<br>', linkTarget, user, 'User talk:' .. user ) )
		:wikitext( string.format( '%s&nbsp;(UTC)', mwLang:formatDate( 'H:i, j xg Y', timestamp ) ) )
	
	return tostring( html )
end

local function renderAdmin( content, user, request, author )
	if not isEmpty( user ) then
		return renderUser( user )
	end
	
	if isEmpty( author ) or isEmpty( request ) then
		return nil
	end
	
	local authorTimestamp = mw.text.split( author, '/', true )[ 2 ]
	local headingName = request .. '/' .. authorTimestamp
	
	-- Count headings until we find ours
	local iterator = mw.ustring.gmatch( content, '==[^\n]+==' )
	local sectionNumber = 0
	local sectionFound = false
	for sectionName in iterator do
		sectionNumber = sectionNumber + 1
		sectionName = mw.text.trim( sectionName, '=\t\r\n\f%s' )
		
		if sectionName == headingName then
			sectionFound = true
			break
		end
	end
	
	if sectionFound then
		local html = mw.html.create( 'span' )
			:addClass( 'mw-editsection-like tmpl-raaf-editsection is-inline plainlinks' )
			:wikitext( '<span class="mw-editsection-bracket">[</span>' )
			:wikitext( '['
				..	tostring( mw.uri.fullUrl( page, { action = 'edit', section = sectionNumber } ) )
				.. ' править]'
			)
			:wikitext( '<span class="mw-editsection-bracket">]</span>' )
		
		return tostring( html )
	end
	
	return nil
end

-- Substitute with {{ЗКА:Быстрый запрос/subst}}
function p._substTemplate( request, comment, author )
	local frame = mw.getCurrentFrame()
	return frame:expandTemplate{
		title = substPage,
		args = {
			['вопрос'] = request,
			['пояснение'] = comment,
			['автор'] = author,
		}
	}
end

-- Replace {{ЗКА:Быстрый запрос}}
function p.main( frame )
	local args = getArgs( frame )
	local html = mw.html.create()
	
	local status = args[ 'статус' ] or args[ 'status' ]
	local request = args[ 'вопрос' ] or args[ 'request' ]
	local comment = args[ 'пояснение' ] or args[ 'comment' ]
	local author = args[ 'автор' ] or args[ 'author' ]
	local admin = args[ 'администратор' ] or args[ 'admin' ]
	
	-- Substitute the template here
	if mw.isSubsting() then
		return p._substTemplate( request, comment, author )
	end
	
	local timestamp = getTimestamp( request, author )
	local actualStatus = parseStatus( status, 1, admin )
	local response = parseStatus( status, 2, admin )
	
	-- Calculate row classes
	local rowClass = ''
	if not isEmpty( actualStatus ) then
		rowClass = ' is-done'
	end
	if actualStatus == '-' then
		rowClass = rowClass .. ' is-declined'
	end
	
	-- Get page content to calculate headers from
	local title = mw.title.new( page )
	local content = ''
	if not isEmpty( title ) and title.exists then
		content = title:getContent()
	end
	
	-- Row with the request itself
	html:tag( 'tr' )
		:addClass( 'tmpl-raaf-row ' .. rowClass )
		:tag( 'td' )
			:addClass( 'tmpl-raaf-iconCell' )
			:wikitext( renderIcon( timestamp, actualStatus, response, admin ) )
		:tag( 'td' )
			:addClass( 'tmpl-raaf-cell' )
			:wikitext( renderDesc( timestamp, request, comment, actualStatus, response ) )
		:tag( 'td' )
			:addClass( 'tmpl-raaf-cell is-user' )
			:wikitext( renderUser( author ) )
		:tag( 'td' )
			:addClass( 'tmpl-raaf-cell is-user' )
			:wikitext( renderAdmin( content, admin, request, author ) )
		:done()
	
	-- Row with the administrator response
	if not isEmpty( response ) then
		html:tag( 'tr' )
			:addClass( 'mw-collapsible mw-collapsed tmpl-raaf-row tmpl-raaf-result raaf-result' .. rowClass )
			:attr( 'id', 'mw-customcollapsible-raaf-' .. timestamp )
			:tag( 'td' )
				:addClass( 'tmpl-raaf-iconCell' )
			:tag( 'td' )
				:attr( 'colspan', 3 )
				:addClass( 'tmpl-raaf-cell' )
				:wikitext( '<b>Итог:</b> ' .. response )
			:done()
	end
	
	-- Not using mw.html here because we need to hide the heading like this
	html:wikitext( '<tr class="tmpl-raaf-hidden"><td colspan="5">' )
	
	return tostring( html )
end

return p