Module:Resource: Difference between revisions
From PC Gaming Shelter
No edit summary |
No edit summary |
||
| Line 287: | Line 287: | ||
makeBadge(args['Has resource type']) .. | makeBadge(args['Has resource type']) .. | ||
table.concat(content, '') .. | table.concat(content, '') .. | ||
string.format('<span class="">') .. | string.format('<span class="ml-auto">') .. | ||
makeBadge(args['Has language'], ' | makeBadge(args['Has language'], 'light') .. | ||
string.format('</span>') | string.format('</span>') | ||
) | ) | ||
Revision as of 13:20, 3 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 = {
['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/Cover',
order = '1',
rows = {
'Image'
}
},
['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',
}
},
['Resource Info'] = {
heading = 'Link',
template = 'Infobox/Resource Link',
order = '2',
rows = {
'Has URL',
'Has video provider',
'Has video id',
'Has language',
'Has subtitles',
'Has subtitles language',
'Has date',
'Created by'
}
}
}
return sectionMap
end
function p.infobox(frame)
local url = frame:getParent().args['Has URL']
local title = mw.title.getCurrentTitle().text
local resourceName = title or ''
local scraped = scrapeVideoId(url)
local service = utils.clean(scraped.service) or ''
local id = utils.clean(scraped.id) or ''
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
function p.inline(frame)
local args = frame:getParent().args
local url = args['Has URL']
if not isValidUrl(url) then
return
end
local content = splitBy(args['Has content type'], ',')
for i, ct in ipairs(content) do
content[i] = makeBadge(ct)
end
local html = mw.html.create()
local resource = html:tag('div'):addClass('resource-item')
resource:tag('div')
:addClass('badges mb-2 plainlinks')
:wikitext(
string.format('[%s %s]', url, makeBadge('► Open', 'primary')) ..
makeBadge(args['Has resource type']) ..
table.concat(content, '') ..
string.format('<span class="ml-auto">') ..
makeBadge(args['Has language'], 'light') ..
string.format('</span>')
)
resource:tag('div'):wikitext(args['Has short description'])
resource:tag('div')
:tag('small'):addClass('text-muted'):wikitext(externalHost(url))
return html
end
return p
