Module:Infobox song: Difference between revisions
MusikAnimal (talk | contribs) No edit summary |
MusikAnimal (talk | contribs) No edit summary |
||
(4 intermediate revisions by the same user not shown) | |||
Line 221: | Line 221: | ||
function p._studio_sessions(song) | function p._studio_sessions(song) | ||
local results = cargo.query( | local results = cargo.query( | ||
'studio_sessions, recordings, songs', | 'studio_sessions, recordings, songs', | ||
Line 265: | Line 264: | ||
local Date = require('Module:Date')._Date | local Date = require('Module:Date')._Date | ||
release_date = Date(release_date) | release_date = Date(release_date) | ||
if release_date ~= nil then | if release_date ~= nil then | ||
return release_date:text('ymd') | return release_date:text('ymd') | ||
Line 270: | Line 270: | ||
-- Try to find the earliest US date, or earliest date overall if there isn't a US date. | -- Try to find the earliest US date, or earliest date overall if there isn't a US date. | ||
local results = cargo.query( | local results = cargo.query( | ||
"songs, albums, releases", | "songs, albums, releases", | ||
Line 326: | Line 325: | ||
local song = frame.args[2] | local song = frame.args[2] | ||
local release_date = frame.args[3] | local release_date = frame.args[3] | ||
return p._validateOrFetchReleaseDate(artist, song, release_date) | |||
end | end | ||
Line 347: | Line 343: | ||
-- Writer | -- Writer | ||
local writers_table = {} | |||
if args.writer ~= nil and args.writer ~= '' then | if args.writer ~= nil and args.writer ~= '' then | ||
for writer in string.gmatch(args.writer, "([^,]+)") do | for writer in string.gmatch(args.writer, "([^,]+)") do | ||
Line 352: | Line 349: | ||
local page = mw.title.new(writer) | local page = mw.title.new(writer) | ||
if page.exists then | if page.exists then | ||
writer = '[[' .. writer .. ']]' | |||
end | end | ||
table.insert(writers_table, writer) | |||
end | end | ||
end | end | ||
frame.args.data40 = | frame.args.data40 = table.concat(writers_table, ', ') | ||
-- Producer | -- Producer | ||
Line 402: | Line 400: | ||
'_table=songs', | '_table=songs', | ||
name = song, | name = song, | ||
type = args.type, | type = args.type or 'song', | ||
artist = artist, | artist = artist, | ||
original_artist = moduleDelink._delink({args.original_artist}), | original_artist = moduleDelink._delink({args.original_artist}), |
Latest revision as of 03:59, 23 October 2024
Documentation for this module may be created at Module:Infobox song/doc
local p = {}
local cargo = mw.ext.cargo
local moduleInfobox = require('Module:Infobox')
local moduleDelink = require('Module:Delink')
local types = {
['single'] = {
color = 'khaki',
link = '[[:Category:Singles|Single]]',
category = 'Singles'
},
['song'] = {
color = '#E6E8FA',
link = '[[:Category:Songs|Song]]',
category = 'Songs'
},
['promo'] = {
color = '#E6E8FA',
link = '[[:Category:Promotional singles|Promotional single]]',
category = 'Promotional singles'
},
['cover'] = {
color = '#E6E8FA',
link = '[[:Category:Cover songs|Cover song]]',
category = 'Cover songs'
},
['instrumental'] = {
color = '#E6E8FA',
link = '[[:Category:Instrumental songs|Instrumental song]]',
category = 'Instrumental songs'
}
}
function p.link( frame )
local given = frame.args[1]
if given == '' or given == nil then
given = 'song'
end
local given = mw.text.split(given, "%s*,%s*")
return types[given[1]].link
end
function p.color( frame )
local given = frame.args[1]
if given == '' or given == nil then
given = 'song'
end
given = mw.text.split(given, "%s*,%s*")
return types[given[1]].color
end
function p._categories( artist, album, release_date, args )
if mw.title.getCurrentTitle().namespace ~= 0 then
return ''
end
local songType = args.type
if args.type == '' or args.type == nil then
songType = 'song'
end
songType = mw.text.split(songType, "%s*,%s*")
local cats = '[[Category:Songs]]'
local is_cover = false
-- [[Category:Singles]], [[Category:Cover songs]], [[Category:Billy Corgan cover songs]], etc.
for _, v in ipairs(songType) do
local data = types[v]
if v == 'cover' then
is_cover = true
end
cats = cats .. '[[Category:' .. data.category .. ']]'
if artist ~= nil and args.nonstandard_artist == nil and args.side_project == nil and (is_cover and v == 'cover') == false then
cats = cats .. '[[Category:' .. artist .. ' ' .. data.category:lower() .. ']]'
end
end
-- [[Category:Album songs]]
cats = cats .. '[[Category:' .. album .. ' songs]]'
-- [[Category:Artist side projects]], [[Category:Arist songs]]
if args.side_project ~= nil then
cats = cats .. "[[Category:" .. args.side_project .. " side projects]]"
elseif artist ~= nil and args.nonstandard_artist == nil and is_cover == false then
cats = cats .. "[[Category:" .. artist .. " songs]]"
end
-- [[Category:Music videos]], [[Category:Artist music videos]]
if args.video ~= '' and args.video ~= nil then
cats = cats .. '[[Category:Music videos]]'
if args.side_project == '' or args.side_project == nil then
cats = cats .. '[[Category:' .. artist .. ' music videos]]'
end
end
-- [[Category:YYYY singles]], [[Category:YYYY songs]]
if args.nonstandard_artist == nil and args.released ~= nil then
local cat_type = (args.type == 'single') and 'single' or 'song'
-- Categorize each release
local matches = string.gmatch( args.released, "%d%d%d%d" )
for year in matches do
cats = cats .. '[[Category:' .. year .. ' ' .. string.lower(cat_type) .. 's]]'
end
-- Categorize the first release as 'single'/'cover'/etc., if applicable
local first_year = string.match( args.released, "%d%d%d%d" )
if first_year and cat_type ~= 'song' then
cats = cats .. '[[Category:' .. first_year .. ' ' .. 'songs]]'
end
end
-- [[Category:Songs written by artist]]
if args.writer ~= nil and args.writer ~= '' then
local writersToCategorize = {
['Billy Corgan'] = true,
['James Iha'] = true,
["D'arcy Wretzky"] = true,
['Jimmy Chamberlin'] = true,
['Kerry Brown'] = true,
['Jeff Schroeder'] = true,
['Courtney Love'] = true,
['Frank Catalano'] = true
}
local writers = mw.text.split(args.writer, "%s*,%s*")
for _i, writer in ipairs(writers) do
if writersToCategorize[writer] then
cats = cats .. '[[Category:Songs written by ' .. writer .. ']]'
end
end
else
cats = cats .. '[[Category:Songs with unknown writers]]'
end
-- [[Songs produced by artist]]
if args.producer ~= nil and args.producer ~= '' then
local producersToCategorize = {
['Billy Corgan'] = true,
['James Iha'] = true,
["D'arcy Wretzky"] = true,
['Jimmy Chamberlin'] = true,
['Butch Vig'] = true,
['Flood'] = true,
['Alan Moulder'] = true,
['Kerry Brown'] = true,
['Bjorn Thorsrud'] = true,
['Nellee Hooper'] = true,
['Terry Date'] = true,
['Jeff Schroeder'] = true,
['Howard Willing'] = true,
['Rick Rubin'] = true,
['Roy Thomas Baker'] = true,
['Brad Wood'] = true,
['Dale Griffin'] = true,
['Ted de Bono' ] = true
}
local producers = mw.text.split(args.producer, "%s*,%s*")
for _i, producer in ipairs(producers) do
if producersToCategorize[producer] then
cats = cats .. '[[Category:Songs produced by ' .. producer .. ']]'
end
end
end
return cats
end
function p._track_listing(song, album)
local results = cargo.query(
'track_listings',
'track, song, song_page_title',
{
where = 'work = "' .. album .. '" AND main_listing = 1',
orderBy = 'track_listings._ID ASC'
}
)
local root = mw.html.create()
local olRoot = root:tag('ol')
local has_match = false
for r = 1, #results do
local result = results[r]
local page = mw.title.new(result['song_page_title'])
local wikitext = result['song']
if page.exists then
wikitext = '[[' .. result['song_page_title'] .. '|' .. result['song'] .. ']]'
end
olRoot:tag('li')
:attr('value', result['track'])
:wikitext(wikitext)
if result['song'] == song then
has_match = true
end
end
if has_match then
return tostring(root)
end
return ''
-- local tableRoot = root:tag('table')
-- for r = 1, #results do
-- local row = tableRoot:tag('tr')
-- local result = results[r]
-- row:tag('td')
-- :css('padding-right', '5px')
-- :wikitext(result['track'] .. '.')
-- row:tag('td'):wikitext('[[' .. result['song_page_title'] .. '|' .. result['song'] .. ']]')
-- end
end
function p.track_listing(frame)
local song = frame.args[1]
local album = frame.args[2]
return p._track_listing(song, album)
end
function p._studio_sessions(song)
local results = cargo.query(
'studio_sessions, recordings, songs',
'studio_sessions._pageName=page',
{
where = 'songs._pageName = "' .. song .. '"',
join = 'recordings.song=songs.name,studio_sessions._pageName=recordings._pageName',
groupBy = 'studio_sessions._pageName',
orderBy = 'studio_sessions.date_from ASC'
}
)
if 0 == #results then
return ''
elseif 1 == #results then
return '[[' .. results[1]['page'] .. ']]'
end
local root = mw.html.create()
local ulRoot = root:tag('ul')
:addClass('studio-sessions')
local sessions = {}
for r = 1, #results do
local page = results[r]['page']
if page ~= nil and page ~= '' then
ulRoot:tag('li')
:wikitext('[[' .. page .. ']]')
end
end
return tostring(root)
-- return table.concat(sessions, ' • ')
end
function p.studio_sessions(frame)
local album = frame.args[1]
return p._studio_sessions(album)
end
function p._validateOrFetchReleaseDate(artist, song, release_date)
local Date = require('Module:Date')._Date
release_date = Date(release_date)
if release_date ~= nil then
return release_date:text('ymd')
end
-- Try to find the earliest US date, or earliest date overall if there isn't a US date.
local results = cargo.query(
"songs, albums, releases",
"songs._pageName, songs.name, releases.country, releases.release_date, albums.released",
{
where = "songs.artist = \"" .. artist .. "\" AND songs.name = \"" .. song .. '"',
join = "songs._pageName = releases._pageName, songs.main_album = albums.name",
}
)
if next(results) == nil or (#results == 1 and results[1]['releases.release_date'] == nil and results[1]['albums.released'] == nil) then
return ''
end
local currentDate = Date('currentdate')
-- earliestDate is the earliest release date, either the single or the album
local earliestDate = currentDate
-- earliestDateUS is only for single release dates, not albums
local earliestDateUS = currentDate
for r = 1, #results do
local row = results[r]
local release_table_date = Date(row['releases.release_date']) or currentDate
local album_table_date = Date(row['albums.released']) or currentDate
local isUS = row['releases.country'] == 'US' or row['releases.country'] == 'Worldwide'
if release_table_date < album_table_date then
-- single release date came first
if isUS and release_table_date < earliestDateUS then
earliestDateUS = release_table_date
end
if release_table_date < earliestDate then
earliestDate = release_table_date
end
else
-- album release date came first
if isUS and release_table_date < earliestDateUS then
earliestDateUS = release_table_date
end
if album_table_date < earliestDateUS then
earliestDate = album_table_date
end
end
end
if earliestDateUS < currentDate then
return earliestDateUS:text('ymd')
else
return earliestDate:text('ymd')
end
end
function p.validateOrFetchReleaseDate(frame)
local artist = frame.args[1]
local song = frame.args[2]
local release_date = frame.args[3]
return p._validateOrFetchReleaseDate(artist, song, release_date)
end
function p.infobox(frame)
local args = frame:getParent().args
local song = args.name or tostring(mw.title.getCurrentTitle())
local artist = moduleDelink._delink({mw.getContentLanguage():ucfirst(args.artist or '')})
local album = moduleDelink._delink({args.album or ''})
local release_date = p._validateOrFetchReleaseDate(artist, song, args.released_cargo or args.released) or ''
local categories = p._categories(artist, album, release_date, args)
-- Infobox parameters
frame.args.above = '"' .. song .. '"'
if (args.nonstandard_artist == '' or args.nonstandard_artist == nil) and release_date ~= '' then
frame.args.data10 = args.released
end
-- Writer
local writers_table = {}
if args.writer ~= nil and args.writer ~= '' then
for writer in string.gmatch(args.writer, "([^,]+)") do
writer = moduleDelink._delink({writer})
local page = mw.title.new(writer)
if page.exists then
writer = '[[' .. writer .. ']]'
end
table.insert(writers_table, writer)
end
end
frame.args.data40 = table.concat(writers_table, ', ')
-- Producer
if args.producer ~= nil and args.producer ~= '' then
local producers = {}
for _i, producer in ipairs(mw.text.split(args.producer, '%s*,%s*')) do
producer = moduleDelink._delink({producer})
local page = mw.title.new(producer)
if page and page.exists then
table.insert(producers, '[[' .. producer .. ']]')
else
table.insert(producers, producer)
end
end
frame.args.data43 = table.concat(producers, ', ')
end
-- Studio sessions
if args.recorded == nil or args.recorded == '' then
frame.args.data12 = p._studio_sessions(song)
else
frame.args.data12 = args.recorded .. (args.recorded_ref or '')
frame.args.data13 = require('Module:Link')._studio(args.studio or '')
end
-- Track listings
local track_listing = p._track_listing(song, album)
if track_listing ~= '' then
frame.args.below = (args.misc or '') .. frame:expandTemplate{
title = 'hidden',
args = {
class = 'nomobile',
headerstyle = 'background:' .. frame:expandTemplate{
title = 'Infobox song/color',
args = { args.type }
},
'[[' .. album .. ']]',
track_listing
}
}
end
-- Cargo storage
local cargo_data = {
'_table=songs',
name = song,
type = args.type or 'song',
artist = artist,
original_artist = moduleDelink._delink({args.original_artist}),
main_album = album,
song_release_date = release_date,
writer = moduleDelink._delink({args.writer}),
video = args.video ~= '' and args.video ~= nil,
spotify = args.spotify,
discogs = args.discogs,
musicbrainz = args.musicbrainz,
cover = args.cover
}
frame:callParserFunction('#cargo_store', cargo_data)
-- Cargo storage for EPs (which get stored as an album)
if args.is_ep ~= nil and args.is_ep ~= '' then
frame:expandTemplate{
title = 'Infobox song/Album store',
args = {
name = song,
cover = args.cover,
type = 'ep',
artist = artist,
producer = args.producer,
engineer = args.engineer,
released = release_date,
discogs = args.discogs,
musicbrainz = args.musicbrainz
}
}
end
return moduleInfobox.infobox(frame.args) .. categories
end
return p