Module:RandomArticle

local p = {}

--================================= Custom Info Table ================================= --===== Use this to replace the automated info with custom image, description, etc ==== --Syntax: ["PAGENAME"] = {name = "Custom Name", image = "Custom Image", description = [=[Custom Description]=] --if you don't want to change one or more fields, leave them blank. --for the sake of maintenance, please add entries in alphabetical order custom_info = { ["Ikimonogakari"] = {name = "", image = "", description = [=[Ikimonogakari (いきものがかり) is a Japanese duo (formerly a trio) under Epic Records Japan. Several of their releases have topped the Oricon rankings and many of their songs have been featured in different media, such as Naruto Shippuden and the 2012 Olympic broadcast theme song etc.]=]}, ["marble≠marble"] = {name = "", image = "", description = [=[Tnaka is a solo idol that performs in the techno project marble≠marble.]=]}, ["OLDCODEX"] = {name = "", image = "", description = [=[OLDCODEX (オルドコデック) was a Japanese rock band under Lantis. They are best known for performing the theme songs of the animes Kuroko's Basketball, and Free!.]=]}, ["YOASOBI"] = {name = "", image = "", description = [=[YOASOBI is a pop duo formed by Vocaloid producer Ayase, and singer-songwriter ikura in 2019. Their debut song Yoru ni Kakeru topped multiple Japanese music charts and became the first song certified diamond for streaming by the RIAJ.]=]}, --[""] = {name = "", image = "", description = [=[]=]}, }

--========================== Module functions ========================== function firstToLower(str) return (str:gsub("^%u", string.lower)) end

function ParseImage(content) local image = nil --searching for images using different patterns until one of them (or none) finds an image --note: [gjpsw][einpv][befg][gp]? is intended to capture the extensions jpg, png, jpeg, webp, gif and svg --this can also capture any combination of those letters, due to lua not having optional capturing groups --pattern 1 --search for image in the infobox field "image" as 	local imgpattern = 'image%s*=%s*%[%[File:(.-%.[gjpsw][einpv][befg][gp]?)' image = string.match(content, imgpattern) --pattern 2 --search for image in the infobox field "image" as image.ext if(image == nil) then imgpattern = 'image%s*=%s*(.-%.[gjpsw][einpv][befg][gp]?)' image = string.match(content, imgpattern) end --pattern 3 --search for image anywhere else as [[File:image.ext	if(image == nil) then		imgpattern = '%[%[File:(.-%.[gjpsw][einpv][befg][gp]?)'		image = string.match(content, imgpattern)	end	--pattern 4	--search for image inside a gallery as image.ext	if(image == nil) then		imgpattern = , )	--removes the heading of the "Concept" section to include its content in the description, if available	description = description:gsub('==+%s*Concept%s*==+', )	--removes everything below (and including) the first section marker	description = description:gsub('==+.*==+.*', )	--replaces multiple linebreaks with a single one	description = description:gsub('\n\n+', '\n')	--removes any template in the text	description = description:gsub(, )	--removes empty parenthesis	description = description:gsub('%(%)', '')	--limiting maximum length of description	if(string.len(description) > 290) then		--cropping at 290 characters		description = description:sub(1,290)		--removing last word (possibly cropped) and replacing with "..."		description = description:gsub('%s%S*$', '...')	end	return description end

function ParsePage(frame, articleType, pagename) local name = nil local image = nil local description = nil local content = mw.title.new(pagename):getContent --checking if page is a redirect local redirect_pattern = '#REDIRECT%s*%[%[(.*)%]%]' local redirect_link = pagename while(redirect_link ~= null) do       --navigating through redirects until a page with no redirect is found redirect_link = string.match(content, redirect_pattern) if(redirect_link ~= null) then --if a redirect is found, pagename is replaced by the target of the redirect pagename = redirect_link content = mw.title.new(pagename):getContent end end --if page doesn't exist or is empty, get another page if(content == nil) then return p.GetArticle(frame) end

--using custom info if available, otherwise get data from page if(custom_info[pagename] == nil or custom_info[pagename]['name'] == '') then --determining article name --checking if name was changed using the magicword DISPLAYTITLE local displaytitle_pattern = "%{%{DISPLAYTITLE:(.-)%}%}" name = string.match(content, displaytitle_pattern) --getting name from PAGENAME if(name == nil) then --stripping text between parenthesis from PAGENAME name = pagename:gsub('%s%(.-%)', '') --checking if name was used with first letter in lowercase local lowercase_name_pattern = "'''%s*" .. firstToLower(EscapeStringSymbols(name)) .. "%s*'''.*" lowercase_name_match = string.match(content, lowercase_name_pattern) if(lowercase_name_match ~= nil) then name = firstToLower(name) end end else name = custom_info[pagename]['name'] end if(custom_info[pagename] == nil or custom_info[pagename]['image'] == '') then image = ParseImage(content) else image = custom_info[pagename]['image'] end if(custom_info[pagename] == nil or custom_info[pagename]['description'] == '') then description = ParseDescription(content, name) else description = custom_info[pagename]['description'] end return BuildOutput(frame, "Featured " .. articleType, pagename, name, image, description) end

function BuildOutput(frame, title, link, name, image, description) local IMGSIZE = '250px' local PRIMARYCOLOR = '#e15467' local IMGBACKGROUNDCOLOR = '#3c3c3c' --Using Template:Infocard to display collected data on desktop desktop_output = frame:expandTemplate{ title = 'Infocard', args = {title = title, name = name, link = link, description = description, file = image, imgsize = IMGSIZE, primarycolor = PRIMARYCOLOR, imgbackgroundcolor = IMGBACKGROUNDCOLOR} }	--Using Template:Infocard/mobile to display collected data on mobile mobile_output = frame:expandTemplate{ title = 'Infocard/mobile', args = {title = "'''" .. title .. "'''", name = name, link = link, description = description, file = image, imgsize = IMGSIZE, primarycolor = PRIMARYCOLOR, imgbackgroundcolor = IMGBACKGROUNDCOLOR} }	return ' ' .. desktop_output .. ' ' .. mobile_output .. ' ' end

function p.GetArticle(frame) local articleType = frame.args[1] if(articleType == 'Group' or articleType == 'Soloist' or articleType == 'Band' or articleType == 'Test') then --loading predefined data into tables local data = {} if(articleType == 'Test') then data = {"Ikimonogakari", "marble≠marble", "OLDCODEX", "YOASOBI"} else data = require('Module:RandomArticle/' .. articleType .. 's') end

if(#data > 0) then --getting random pagename math.randomseed(os.time) pagename = data[math.random(#data)] data = nil return ParsePage(frame, articleType, pagename) else return "RandomArticle:GetArticle: " .. articleType .. ": PAGENAME list not found or empty." end else return "RandomArticle:GetArticle: Invalid Type. Supported: Groups, Bands, Soloists, Test." end end return p