Module:Resource: Difference between revisions
From PC Gaming Shelter
No edit summary |
No edit summary |
||
| Line 329: | Line 329: | ||
local gameBadge = '' | local gameBadge = '' | ||
if game and pageExists(game) == true then | if game and pageExists(game) == true then | ||
gameBadge = string.format('[[%s|%s]]', game, makeBadge('Game', ' | gameBadge = string.format('[[%s|%s]]', game, makeBadge('Game', 'warning')) | ||
end | end | ||
Revision as of 08:58, 10 July 2026
Documentation for this module may be created at Module:Resource/doc
local utils = require( 'Module:Utils' )
local p = {}
local function splitBy(str, sep)
local t = {}
for part in str:gmatch("[^" .. sep .. "]+") do
table.insert(t, mw.text.trim(part))
end
return t
end
local function isValidUrl(url)
return utils.clean(url) and mw.ustring.match(url, '^https?://[^%s]+$') ~= nil
end
local function externalHost(url)
url = utils.clean(url)
if not url then
return nil
end
local host = mw.ustring.match(url, '^https?://([^/%?#]+)')
if not host then
return nil
end
local cleanedHost = mw.ustring.gsub(host, '^www%.', '')
return cleanedHost
end
local function urlDecode(value)
value = utils.clean(value)
if not value then
return nil
end
value = string.gsub(value, '+', ' ')
value = string.gsub(value, '%%(%x%x)', function(hex)
return string.char(tonumber(hex, 16))
end)
return value
end
local function queryParam(url, name)
url = utils.clean(url)
if not url then
return nil
end
local query = string.match(url, '%?([^#]+)')
if not query then
return nil
end
for key, value in string.gmatch(query, '([^&=]+)=([^&]*)') do
if urlDecode(key) == name then
return urlDecode(value)
end
end
return nil
end
local function pathMatch(url, pattern)
url = utils.clean(url)
if not url then
return nil
end
local path = string.match(url, '^https?://[^/]+([^%?#]*)') or ''
local value = string.match(path, pattern)
return urlDecode(value)
end
local function scrapeVideoId(url)
url = utils.clean(url)
if not isValidUrl(url) then
return nil
end
local host = mw.ustring.lower(externalHost(url) or '')
local id
if host == 'archive.org' then
id = pathMatch(url, '^/details/([^/]+)') or pathMatch(url, '^/embed/([^/]+)')
return id and { service = 'archiveorg', id = id } or nil
end
if host == 'player.bilibili.com' then
id = queryParam(url, 'bvid') or queryParam(url, 'aid')
return id and { service = 'bilibili', id = id } or nil
end
if host == 'bilibili.com' or host == 'm.bilibili.com' then
id = pathMatch(url, '^/video/([^/]+)')
return id and { service = 'bilibili', id = id } or nil
end
if host == 'play-tv.kakao.com' then
id = pathMatch(url, '^/embed/player/cliplink/([^/]+)')
return id and { service = 'kakaotv', id = id } or nil
end
if host == 'tv.kakao.com' then
id = pathMatch(url, '^/channel/[^/]+/cliplink/([^/]+)') or pathMatch(url, '^/v/([^/]+)')
return id and { service = 'kakaotv', id = id } or nil
end
if host == 'tv.naver.com' then
id = pathMatch(url, '^/embed/([^/]+)') or pathMatch(url, '^/v/([^/]+)')
return id and { service = 'navertv', id = id } or nil
end
if host == 'embed.nicovideo.jp' or host == 'nicovideo.jp' or host == 'www.nicovideo.jp' then
id = pathMatch(url, '^/watch/([^/]+)')
return id and { service = 'niconico', id = id } or nil
end
if host == 'soundcloud.com' then
return { service = 'soundcloud', id = url }
end
if host == 'open.spotify.com' then
local spotifyType = pathMatch(url, '^/(album)/[^/]+') or pathMatch(url, '^/(artist)/[^/]+') or pathMatch(url, '^/(track)/[^/]+')
id = pathMatch(url, '^/[^/]+/([^/]+)')
if spotifyType and id then
return { service = 'spotify' .. spotifyType, id = id }
end
end
if host == 'twitch.tv' or host == 'www.twitch.tv' then
id = pathMatch(url, '^/videos/([^/]+)')
if id then
return { service = 'twitchvod', id = id }
end
id = pathMatch(url, '^/[^/]+/clip/([^/]+)')
if id then
return { service = 'twitchclip', id = id }
end
id = pathMatch(url, '^/([^/]+)')
return id and { service = 'twitch', id = id } or nil
end
if host == 'clips.twitch.tv' then
id = pathMatch(url, '^/([^/]+)')
return id and { service = 'twitchclip', id = id } or nil
end
if host == 'vimeo.com' or host == 'www.vimeo.com' or host == 'player.vimeo.com' then
id = pathMatch(url, '^/video/([^/]+)') or pathMatch(url, '^/([^/]+)')
return id and { service = 'vimeo', id = id } or nil
end
if host == 'youtube.com' or host == 'www.youtube.com' or host == 'm.youtube.com' or host == 'music.youtube.com' then
id = queryParam(url, 'v') or pathMatch(url, '^/embed/([^/]+)') or pathMatch(url, '^/shorts/([^/]+)') or pathMatch(url, '^/live/([^/]+)')
if id then
return { service = 'youtube', id = id }
end
id = queryParam(url, 'list')
return id and { service = 'youtubeplaylist', id = id } or nil
end
if host == 'youtu.be' then
id = pathMatch(url, '^/([^/]+)')
return id and { service = 'youtube', id = id } or nil
end
return nil
end
local function propertiesPlan()
-- ['Form field name'] = { 'Semantic property', 'delimiter' }
local propMap = {
['Image'] = {'Image', 'file'},
['Has URL'] = {'Has URL' },
['Has short description'] = {'Has short description' },
['Related game'] = {'Related game' },
['Has resource type'] = {'Has resource type' },
['Has content type'] = {'Has content type', ',' },
['Has date'] = {'Has date' },
['Created by'] = {'Created by' },
['Has language'] = {'Has language', ',' },
['Has spoilers'] = {'Has spoilers', },
['Has subtitles'] = {'Has subtitles' },
['Has subtitles language'] = {'Has subtitles language', ',' }
}
return propMap
end
local function infoboxSectionPlan()
local sectionMap = {
['Cover image'] = {
heading = '',
template = 'Infobox/Resource Cover',
order = '1',
rows = {
'Image',
'Related game',
'Has resource type',
'Has short description'
}
},
['Resource Meta'] = {
heading = 'Resource Info',
template = 'Infobox/Resource Info',
order = '2',
rows = {
'Has short description',
'Related game',
'Has resource type',
'Has content type',
'Has spoilers',
'Has date',
'Created by',
'Has language',
'Has subtitles',
'Has subtitles language',
}
}
}
return sectionMap
end
function p.infobox(frame)
local template = frame:getParent().args
local url = template['Has URL']
local title = mw.title.getCurrentTitle().text
local resourceName = title or ''
local scraped = url
local service, id = '', ''
if url and template['Has resource type'] == 'Video' then
scraped = scrapeVideoId(url)
service = utils.clean(scraped.service)
id = utils.clean(scraped.id)
end
mw.smw.set({
['Has video provider'] = service,
['Has video id'] = id,
['Has resource name'] = resourceName
})
local category = 'Resources'
local properties = propertiesPlan()
local sections = infoboxSectionPlan()
local infobox = utils.createInfobox(frame, category, properties, sections)
return infobox
end
local function makeBadge(val, style)
if not val and val ~= '' then
return
end
local style = style or 'secondary'
local html = mw.html.create()
html:tag('span'):addClass('mr-2 badge badge-' .. style):wikitext(val)
return tostring(html)
end
local function pageExists(page)
local page = mw.smw.ask {
'[[' .. page .. ']][[Modification date::+]]',
} or {}
local check = #page > 0
return check
end
function p.inline(frame)
local args = frame:getParent().args
local url = args['Has URL']
local content = args['Has content type'] or ''
local subtitles = args['Has subtitles'] or ''
local sublang = args['Has subtitles language'] or ''
local spoilers = args['Has spoilers'] or ''
local restype = args['Has resource type'] or ''
local lang = args['Has language'] or ''
local game = args['Related game'] or ''
local description = args['Has short description'] or nil
if not isValidUrl(url) then
return
end
if content ~= '' then
content = splitBy(content, ',')
for i, ct in ipairs(content) do
content[i] = makeBadge(ct)
end
end
local subBadges = ''
if subtitles == "Yes" and sublang ~= '' then
sublang = splitBy(sublang, ',')
for i, st in ipairs(sublang) do
sublang[i] = makeBadge(st)
end
subBadges = "<span class='nowrap'>" .. makeBadge('CC', ' border border-secondary') .. table.concat(sublang, '') .. "</span>"
end
local spoilerBadge = ''
if spoilers == "Yes" then
spoilerBadge = makeBadge('SPOILERS', 'danger')
end
local resBadge = ''
if restype ~= '' then
resBadge = makeBadge(restype)
end
local contentBadge = ''
if content ~= '' and type(content) == 'table' then
contentBadge = table.concat(content, '')
end
local langBadge = ''
if lang ~= '' then
langBadge = makeBadge(lang, 'light')
end
local gameBadge = ''
if game and pageExists(game) == true then
gameBadge = string.format('[[%s|%s]]', game, makeBadge('Game', 'warning'))
end
local html = mw.html.create()
local resource = html:tag('div'):addClass('resource-item')
resource:tag('div')
:addClass('badges d-flex mb-2 plainlinks')
:wikitext(
string.format('[%s %s]', url, makeBadge('► Open', 'primary')) ..
string.format('<span>%s%s%s%s</span>'
, resBadge
, contentBadge
, spoilerBadge
, gameBadge
) ..
string.format('<span class="ml-sm-auto">%s%s</span>'
, langBadge
, subBadges
)
)
if description then
resource:tag('div'):wikitext(description)
end
resource:tag('div')
:tag('small'):addClass('text-muted'):wikitext(externalHost(url))
return html
end
return p
