Moduł:Autor

Z Nonsensopedii, polskiej encyklopedii humoru

Moduł do wykorzystania w szablonie {{Information}} do przetwarzania pola author=. Informacje o dozwolonych formatach przez ten szablon znajdziesz na stronie Nonsensopedia:Opisywanie grafik.

Funkcja process tego modułu może być wykorzystywana przez inne moduły.


local autor = {}
local allLanguages
local tools = require('Moduł:Narzędzia')
local linki = require('Moduł:Linki')
local hasPlaintext = false		-- paskudny global, nk naprawi

local invalidAuthors = {
	'nieznany',
	'brak',
	'nie wiem',
	'internet',
	'z sieci',
	'po sieci'
}

local badUrls = {
	'wikipedia',
	'nonsa',
	'nonsensopedia',
	'commons',
	'uncyclopedia'
}

local function isAuthorInvalid(a)
	a = mw.ustring.lower(a)
	
	for _,val in ipairs(invalidAuthors) do
		if mw.ustring.find(a, val, 1, true) then
			return true
		end
	end
	
	return false
end

-- formatowanie linków dla użytkowników Nonsy
local function makeUserLink(user)
	user = tools._firstLarge(user)
	return '[[Użytkownik:' .. user .. '|' .. user .. ']] ([[Specjalna:Wkład/' .. user .. '|wkład]])'
end

-- funkcja pomocnicza do scalania tabel atrybutów
local function appendSubtable(t, key, value)
	t[key] = t[key] or {}
	table.insert(t[key], value)
end

local function addWarning(t, value)
	appendSubtable(t, 'Ma ostrzeżenie autorstwa', value)
	return ' ' .. mw.smw.info(value, 'warning')
end

-- formatowanie linków do Wikipedii na podstawie getAuthorData
local function makeWikipediaLink(ad)
	return '[[wikipedia:' .. ad['wikipediaArticleLang'] .. ':' .. 
		ad['wikipediaArticleTitle'] .. '|' .. ad['wikipediaArticleTitle'] .. ']]'
end

-- przetwórz link wewnętrzny
local function processInternal(val, desc, surelink)
	local props = {}
	local parts = mw.text.split(mw.ustring.gsub(val, '^:', ''), ':', true)
	local warn = ''
	
	local iw, ns, title = '', '', ''
	if #parts == 0 then
		return props, s .. addWarning(props, 'Nierozpoznany format autorstwa')
	elseif #parts == 1 then
		title = parts[1]
	elseif #parts == 2 then
		-- zakładamy że IW zawsze odnoszą się do jakiejś strony nie w głównej ns
		-- np. commons:Creator:Jan Kowalski, mw:User:Janka Kowalska
		ns = parts[1]
		title = parts[2]
	elseif #parts >= 3 then
		iw = parts[1]
		ns = parts[2]
		title = table.concat(parts, ':', 3)
	end
	
	iw = mw.ustring.lower(mw.text.trim(iw))
	ns = mw.ustring.lower(mw.text.trim(ns))
	title = mw.text.trim(title)
	
	-- wikipedia
	if iw == 'wikipedia' and #ns < 4 and not mw.ustring.find(title, ':', 1, true)
		or ns == 'wikipedia'
	then
		-- #ns < 4 to badziewna heurystyka żeby nie wpadały tu linki do stron użytkowników
		local ad = mw.ext.commonsClient.getAuthorData(val)[val]
		if ad then
			return autor.getAuthorFromCommonsData(ad, val)
		else
			warn = addWarning(props, 'Nie znaleziono autora na Wikipedii')
		end
	
	-- interwiki
	elseif iw ~= '' then
		if allLanguages == nil then
			allLanguages = mw.language.fetchLanguageNames()		-- lazy
		end
		
		if allLanguages[iw] ~= nil then
			appendSubtable(props, 'Ma autora z innej wersji językowej', val)
			
			if mw.ustring.sub(val, 1, 1) ~= ':' then
				val = ':' .. val
			end
		elseif iw == 'commons' then
			appendSubtable(props, 'Ma autora z Wikimedia Commons', val)
		else
			appendSubtable(props, 'Ma autora interwiki', val)
		end
		
		appendSubtable(props, 'Ma autora', tools._firstLarge(title))
	
	-- Wikidata
	elseif (ns == 'wikidata' or ns == '') and mw.ustring.match(title, '^Q%d+$') ~= nil then
		local ad = mw.ext.commonsClient.getAuthorData(title)[title]
		
		if ad then
			return autor.getAuthorFromCommonsData(ad, title)
		else
			warn = addWarning(props, 'Nie znaleziono autora w Wikidanych')
		end
	
	-- wewnętrzne
	elseif ns ~= '' then
		if ns == 'user' or ns == 'użytkownik' or ns == 'użytkowniczka' then
			appendSubtable(props, 'Ma autora z Nonsensopedii', val) -- so proud
			appendSubtable(props, 'Ma autora', tools._firstLarge(title))
			return props, makeUserLink(title)
		elseif ns == 'special' or ns == 'specjalna' then
			-- przypadek linków do Specjalna:Wkład, FUJ
			local iSlash = mw.ustring.find(title, '/')
			
			if iSlash ~= nil then
				local p1 = mw.ustring.lower(mw.ustring.sub(title, 1, iSlash - 1))
				
				if p1 == 'contributions' or p1 == 'wkład' then
					local user = tools._firstLarge(mw.ustring.sub(title, iSlash + 1))
					appendSubtable(props, 'Ma autora z Nonsensopedii', 'Użytkownik:' .. user)
					appendSubtable(props, 'Ma autora', user)
					return props, makeUserLink(user)
				end
			end
			
			warn = addWarning(props, 'Nieznana strona specjalna')
		elseif surelink then
			warn = addWarning(props, 'Nierozpoznany format autorstwa')
		else
			appendSubtable(props, 'Ma autora', title)
			hasPlaintext = true
			return props, title
		end
		
	-- statyczne różne
	else
		-- lepszego pomysłu nie mamy
		appendSubtable(props, 'Ma autora', title)
		hasPlaintext = true
		return props, title
	end
	
	local linkTitle = mw.text.trim(desc)
	if linkTitle == '' then
		linkTitle = title
	end
	
	if val == linkTitle then
		return props, '[[' .. val .. ']]' .. warn
	else
		return props, '[[' .. val .. '|' .. linkTitle .. ']]' .. warn
	end
end

-- przetwórz link zewnętrzny
local function processExternal(val, desc)
	local props = {}
	local val2 = mw.ustring.gsub(val, ';', '\\;')
	
	for _,v in ipairs(badUrls) do
		if mw.ustring.find(val, v) then
			addWarning(props, 'Zbędny link zewnętrzny')
		end
	end
	
	if mw.text.trim(desc) ~= '' then
		appendSubtable(props, 'Ma autora', desc)
		appendSubtable(props, 'Ma zewnętrznego autora', val2 .. ';' .. mw.ustring.gsub(desc, ';', '\\;'))
		return props, '[' .. val .. ' ' .. desc .. ']'
	else
		appendSubtable(props, 'Ma zewnętrznego autora', val2)
		return props, '[' .. val .. ']' .. addWarning(props, 'Brak nazwy autora')
	end
end

-- do użytku prosto w Information
function autor.autor(frame)
	local s = frame.args[1]
	
	if s == nil then
		error("Ta funkcja wymaga podania dokładnie jednego argumentu.")
	end
	
	local props, s = autor.process(s)
	mw.smw.set(props)
	return s
end

-- zwraca listę atrybutów SMW do ustawienia i tekst wyjściowy
function autor.process(s)
	hasPlaintext = false
	local props = {}
	local strings = {}
	if not s then s = '' end
	s = mw.text.trim(s)
	
	local function mergeStuff(wProps, wS)
		table.insert(strings, wS)
		
		-- scalanie tabel atrybutów
		for p, pv in pairs(wProps) do
			for i, ppv in ipairs(pv) do
				appendSubtable(props, p, ppv)
			end
		end
	end
	
	local c = 0
	
	-- linki zewnętrzne
	for v, d in pairs(linki.wExtLink(s)) do
		mergeStuff(processExternal(v, d))
		c = c + 1
	end
	
	-- podwójne kwadratowe
	for v, d in pairs(linki.wLink(s)) do
		mergeStuff(processInternal(v, d, true))
		c = c + 1
	end
	
	local plainC, invalid = 0, false
	if c == 0 then
		-- linków nie było, potraktujmy to jako plaintext
		local parts = mw.text.split(s, ',', true)
		
		for i, p in ipairs(parts) do
			local pp = mw.text.trim(p)
			
			if pp ~= '' then
				mergeStuff(processInternal(pp, '', false))
				plainC = plainC + 1
				
				if not invalid and isAuthorInvalid(pp) then
					invalid = true
				end
			end
		end
	end
	
	local out = ''
	
	if #strings == 0 then
		appendSubtable(props, 'Nie ma podanego autora', 'true')
		
		if mw.ustring.match(s, '[^%s]') ~= nil then
			appendSubtable(props, 'Ma ostrzeżenie autorstwa', 'Zachowany oryginalny opis autorstwa')
		end
		
		out = s
	else
		if plainC == 1 and not hasPlaintext then
			out = strings[1]
		else
			-- czyścimy z linków, by ustalić czy coś straciliśmy w procesie
			local clean = mw.ustring.gsub(s, '%[%[.-|?.-%]%]', '')
			clean = mw.ustring.gsub(clean, 'https?://[^%s]*', '')
			clean = mw.ustring.gsub(clean, '%[[^%[]-%]', '')
			
			if mw.ustring.match(clean, '[^%s:,;]') ~= nil then
				appendSubtable(props, 'Ma ostrzeżenie autorstwa', 'Zachowany oryginalny opis autorstwa')
				out = s
			else
				out = table.concat(strings, ', ')
			end
		end
		
		-- Nadpisujemy inne już ustawione opisy, żeby był tylko jeden
		-- no chyba że jest już jeden
		if #(props['Ma opis autorstwa'] or {}) ~= 1 then
			props['Ma opis autorstwa'] = { out }
		end
	end
	
	if invalid then
		out = out .. addWarning(props, 'Niepotrzebny opis autora')
	end
	
	return props, out
end

-- Memła tablicę danych o autorze i zwraca coś co da się użyć
-- Argumenty:
--   a: tablica danych dla autora pobrana wcześniej z SCC
--   name: klucz wyszukiwania danych w SCC (opcjonalne)
-- Zwraca:
--  * tablicę propów SMW
--  * tekst do wyświetlenia
--  * rodzaj autora, krótki string
function autor.getAuthorFromCommonsData(a, name)
	local props = {}
	local text, warn, aType = '', '', ''
	
	-- zapisujemy klucz wyszukiwania
	if name then appendSubtable(props, 'Importuje informacje o autorze', name) end
	
	-- i inne dane
	if a.wikidataId then appendSubtable(props, 'Ma autora z Wikidanych', a.wikidataId) end
	appendSubtable(props, 'Ma autora', a.text or a.wikidataId or name or '')
	
	-- anonim
	if a.isAnonymous then
		text = 'anonim'
		aType = 'anonim'
		
	-- gwiazda z artem na wikipedii
	elseif a.wikipediaArticleTitle then
		text = '[[wikipedia:' .. a.wikipediaArticleLang .. ':' .. 
			a.wikipediaArticleTitle .. '|' .. a.wikipediaArticleTitle .. ']]'
			aType = 'Wikipedia'
			
	-- commonsiarz
	elseif a.wikimediaUsername then
		appendSubtable(props, 'Ma autora z Wikimedia Commons', 'commons:User:' .. a.wikimediaUsername)
		text = '[[commons:User:' .. a.wikimediaUsername .. '|' .. a.wikimediaUsername .. ']]'
		aType = 'użytkownik Commons'
		
	-- coś z Wikidanych, ale bez arta na wikipedii
	elseif a.wikidataId then
		text = '[[wikidata:' .. a.wikidataId .. '|' .. (a.text or a.wikidataId) .. ']]'
		warn = ' ' .. mw.smw.info('Nie znaleziono artykułu o autorze na Wikipedii, ale to nie szkodzi')
		aType = 'Wikidane'
			
	-- jakiś link
	elseif a.url then
		text = '[' .. a.url .. ' ' .. mw.ustring.gsub(a.text or '', '[%[%]]', '') .. ']'
		aType = 'link'
		
	-- sam tekst
	else 
		text = a.text or ''
		aType = 'tekst'
	end
	
	appendSubtable(props, 'Ma opis autorstwa', text)
	return props, text .. warn, aType
end

return autor