Module:Report

local getArgs = require('Module:Arguments').getArgs local mergeArgsSyntax = require('Module:Arguments').mergeArgsSyntax local loader = require('Module:Loader')

local string, table, yesno, lu = loader.require('String', 'Table', 'Yesno', 'LibraryUtil')

local checkType = lu.checkType

local sep = ' • '

--Begin Exports local p = {}

--Helper Functions local function trimWhitespace(s) checkType('trimWhitespace', 1, s, 'string') return s:match( '^%s*(.-)%s*$' ) end

local function bracket(s) return string.wrapHtml( ('(%s)'):format(s), ' ', { style = 'font-size: 10px' } ) end

function p.trimUser(frame) local args = getArgs(frame) return p._trimUser(args[1], yesno(args[2], false)) end

function p._trimUser(s, link) checkType(1, s, 'string') local s = trimWhitespace(s) local replacements = { {			['^.-%[%[.-%:([^%|]-)%|.*%]%].*$'] = '%1',			['^.-%[%[.-%:(.-)%]%].*$'] = '%1',		},		{			['^.-%{%{.+%:(.-)%/.+%|?.*%}%}.*$'] = '%1',		},		{			['^.-%[?https?%:/%/%S-%/wiki%/.-%:(.+) ?.-%]?.*$'] = '%1', ['^AbuseLog%?wpSearchUser=(.+)$'] = '%1', ['Contribu?t?i?o?n?s%/ ' ]='', ['^(.-)%?.+$'] = '%1',			[' .-%]$'] = '',		},	}	if s:match('^.-(%[%[.-%]%]).*$') then s = string.gsubMulti(s, replacements[1]) elseif s:match('^.-%{%{.+%:(.-)%/.+%|?.*%}%}.*$') then s = string.gsubMulti(s, replacements[2]) elseif s:match('^.-%[?https?%:/%/%S-%/wiki%/.-%:(.+) ?.-%]?.*$') then s = string.gsubMulti(s, replacements[3]) end return link and table.concat{ , s,  } or s end

local function isIp(ip) if ip == nil or type(ip) ~= 'string' then return false end -- Check IPv4 local chunks = {ip:match('(%d+)%.(%d+)%.(%d+)%.(%d+)')} if (#chunks == 4) then for _,v in pairs(chunks) do			if (tonumber(v) < 0 or tonumber(v) > 255) then return false end end return true end -- Check IPv6 local _, chunks = ip:gsub('%:', '') if chunks == 7 then return true end return false end

local function getLinks(s) return { -- this uses 'fullUrl' since message wall links show up as wanted pages, so full url is used instead [Oct 2021] wall = string.fullUrl({ 'Message_wall:', s }, nil, 'wall'), contribs = string.wrapLink({ 'Special:Contributions/', s }, 'contribs'), posts = string.wrapLink({ 'Special:UserProfileActivity/', s }, 'posts'), delcontribs = string.wrapLink({ 'Special:DeletedContributions/', s }, 'del. contribs'), logs = string.wrapLink({ 'Special:Log/', s }, 'logs'), blocklog = string.fullUrl( 'Special:Log/block', { page = s }, 'block log'), abuse = string.fullUrl('Special:AbuseLog', { wpSearchUser = s }, 'abuse log'), block = string.wrapLink({ 'Special:Block/', s }, 'block'), nuke = string.fullUrl('Special:BlankPage', { blankspecial = 'nuke', nukeuser = s }, 'nuke'), whois = string.externalUrl({ 'https://cleantalk.org/whois/', s }, nil, 'whois'), proxy = string.externalUrl({ 'https://www.ipqualityscore.com/free-ip-lookup-proxy-vpn-test/lookup/', s }, nil, 'proxy check'), spam = string.externalUrl({ 'https://cleantalk.org/blacklists/', s }, nil, 'spam blacklist check'), edit = string.fullUrl(s, { action = 'edit' }, 'edit'), history = string.fullUrl(s, { action = 'history' }, 'history'), latest = string.fullUrl(s, { diff = 'cur' }, 'latest edit'), links = string.makeLink({ 'Special:WhatLinksHere/', s }, 'links'), subpages = string.makeLink({ 'Special:PrefixIndex/', s, '/' }, 'subpages'), logs = string.fullUrl('Special:Log', { page = s }, 'logs'), abuselog = string.fullUrl('Special:AbuseLog', { wpSearchTitle = s }, 'abuse log'), undelete = string.makeLink({ 'Special:Undelete/', s }, 'del. revisions'), protect = string.fullUrl(s, { action='protect' }, 'protect'), delete = string.fullUrl(s, { action='delete' }, 'delete'), move = string.makeLink({ 'Special:MovePage/', s }, 'move'), user = string.wrapLink({ 'User:', s }, s), usercontribs = string.wrapLink({ 'Special:Contributions/', s }, s), } end

function p._buildLinks(user, isIp) checkType(1, user, 'string') checkType(2, isIp, { 'boolean', 'nil' }) local ret = {} local res = getLinks(user) if not isIp then table.push(ret, res['wall'], res['contribs']) end table.push(ret, res['posts'], res['delcontribs'], res['logs'], res['blocklog'], res['abuselog'], res['block'], res['nuke']) if isIp then table.push( ret, res['whois'], res['proxy'], res['spam']) end return res['usercontribs'] .. ' ' .. bracket(table.concat(ret, sep)) end p.buildLinks = p._buildLinks

- -- Template: Userlinks -- -- Creates a link to a user's Userpage, wall, contributions, and posts. - function p.userLink(frame) local args = getArgs(frame) local value = args[1] return p._userLink(value, args['disableOther'] or args['disable']) end

- -- (Template: Userlinks) Module access point - function p._userLink(user, disableOthers) local res = getLinks(user) local ret = { res['wall'], res['contribs'], res['posts'] } return table.concat{ string.makeLink({ 'User:', user }, user), disableOthers and '' or ' ', not disableOthers and bracket(table.concat(ret, sep)) or '', } end

- -- Template: Report -- -- Generates a Report about a user - function p.main(frame) local args = getArgs(frame) local user = args['reported_user'] or args['ru'] or args['user'] or args['u'] or args[1] local reporter = args['reporter'] or args['r'] or args[2] local timestamp = args['timestamp'] or args['ts'] or args[3] local reason = args['reason'] or args['res'] or args[4] if not user then return error('Please provide a username to report!') elseif not reporter then return error('Please provide your signature!') elseif not reason then return error('Please provide a reason why you are reporting %s!', p._trimUser(user)) end return p._main(user, reporter, timestamp, reason) end

local function reportLink(user) return p._buildLinks(p._trimUser(user), isIp(user)) end

- -- (Template: Report) Module access point - function p._main(user, reporter, timestamp, reason) checkType(1, user, 'string') checkType(2, reporter, 'string') checkType(3, timestamp, 'string') checkType(4, reason, 'string') local links = reportLink(user) local reporter = p._trimUser(reporter) local split = mw.text.split(user, '%s*,%s*') local res = getLinks(reporter) if #split > 1 and type(split) == 'table' then local tmp = {} for i, v in ipairs(split) do			table.push(tmp, v)		end links = pipeline(table.map(split, function(v) return string.wrapTag(reportLink(v), 'li') end), 'ul', string.wrapTag) end local userinfo = table.concat({		res['wall'], res['contribs'],	}, sep) local listitems = table.map({		('Reported User%s: %s'):format((#split > 1 and type(split) == 'table') and 's' or '', links),		('Signature: %s %s'):format( res['user'], bracket(userinfo) ),		'Timestamp: ' .. timestamp,		'Reason: ' .. reason,	}, function(v)		return string.wrapHtml(v, 'li')	end) return string.wrapHtml(listitems, 'ul') end

- -- Template: UserList -- -- Creates a user list with links. - function p.userList(frame) return p._userList(table.unpackRaw(getArgs(frame))) end

- -- (Template: UserList) Module Access Point - function p._userList(users, ...) local split = string.split(users, '%s*,%s*') if not users:match',' then split = { users, ... }	end return table.concat(table.map(split, function(v) return p._userLink(v) end), ', ') end

- -- Template: Deletion request -- -- Generates a deletion request for a page - function p.delete(frame) local args = getArgs(frame) return p._delete(table.unpack(table.deepCopy(args))) end

local function buildPageLinks(page) checkType(1, page, 'string', true) page = page or mw.title.getCurrentTitle.fullText local res = getLinks(page) local ret = { res['edit'], res['history'], res['latest'], res['links'], res['subpages'], res['logs'], res['abuselog'], res['undelete'], res['protect'], res['delete'], res['move'], }	return string.wrapLink(page) .. bracket(table.concat(ret, sep)) end

- -- (Template: Deletion request) Module access point - function p._delete(...) local page, reporter, timestamp, reason, comments = ... checkTypeArgs({		'string',		'string',		'string',		'string',		'string',	}, ...) local page = trimWhitespace(page) local reason = trimWhitespace(reason) local links = buildPageLinks(page) local reporter = p._trimUser(reporter) local comments = trimWhitespace(comments) local timestamp = trimWhitespace(timestamp) local listitems = table.map({		'Page: ' .. links,		'Timestamp: ' .. timestamp,		'Reporter: ' .. reporter,		'Reason for report: ' .. reason,		'Addtional comments: ' .. reason,	}, function(v)		return string.wrapHtml(v, 'li')	end) return string.wrapHtml(listitems, 'ul') end

function p.afpage(frame) local args = getArgs(frame) return p._afpage(args) end

function p._afpage(args) if (table.length(args) < 1) then return '' end return table.concat(table.map(mergeArgsSyntax(args), function(v) return ('%s'):format(v, v)	end), ' ') end

--Finish Module/Exports return p