Module:YouTube/Bac à sable

Ce module Lua est utilisé par le modèle {{YouTube}}.

Page à prévisualiser pour vérifier les modifications : Discussion module:YouTube/Test.

--[[
* format canonique : 1230s (tout en secondes)

* YouTube supporte davantage de formats, mais redirige vers le format canonique :
** il peut y avoir des leading zeroes
** heures, minutes, secondes peuvent être spécifiés dans n'importe quel ordre
** si on spécifie uniquement des secondes, le suffixe "s" peut être omis
]]

local p = {}

local function toSeconds( number, unit )
	if unit == 's' then
		return tonumber( number )
	elseif unit == 'm' or unit == 'min' then
	--elseif unit == 'm' then
		return number * 60
	elseif unit == 'h' then
		return number * 3600
	end
end

local function validateUnit( unit )
	return unit == 's' or unit == 'm' or unit == 'min' or unit == 'h'
end

local function timestampToNbSeconds( timestamp )
	local num1, unit1, num2, unit2, num3, unit3

	-- "30s" (format canonique de YouTube)
	num1, unit1 = timestamp:match( '^0*(%d+)([hms])$' )
	if num1 then
		return toSeconds( num1, unit1 )
	end

	-- "20m30s" (format aussi reconnu par YouTube)
	num1, unit1, num2, unit2 = timestamp:match( '^0*(%d+)([hms])0*(%d+)([hms])$' )
	if num1 then
		return toSeconds( num1, unit1 ) + toSeconds( num2, unit2 )
	end

	-- "1h20m30s" (format aussi reconnu par YouTube)
	num1, unit1, num2, unit2, num3, unit3 = timestamp:match( '^0*(%d+)([hms])0*(%d+)([hms])0*(%d+)([hms])$' )
	if num1 then
		return toSeconds( num1, unit1 ) + toSeconds( num2, unit2 ) + toSeconds( num3, unit3 )
	end

	local hours, minutes, seconds

	-- "30" (format aussi reconnu par YouTube)
	seconds = timestamp:match( '^0*(%d+)$' )
	if seconds then
		return tonumber( seconds )
	end

	-- "20:30" (format *non* reconnu par YouTube)
	minutes, seconds = timestamp:match( '^0*(%d+):0*(%d+)$' )
	if minutes then
		return minutes * 60 + seconds
	end

	-- "1:20:30" (format *non* reconnu par YouTube)
	hours, minutes, seconds = timestamp:match( '^0*(%d+):0*(%d+):0*(%d+)$' )
	if hours then
		return hours * 3600 + minutes * 60 + seconds
	end


	--[[
		SANDBOX WIP :
		* support de l'unité "min"
		* support d'espaces optionnelles

		TODO :
		* serait combinable avec les règles "30s", "20m30s", "1h20m30s" du début de cette fonction
		  (mais ça ferait des règles avec un mélange de formats reconnus et non reconnus par YouTube)
		* support de 20 min 30, 20 m 30, 1 h 20 min 30, 1 h 20 m 30, etc. (omission de l'unité "s")
	--]]

	-- 30 s, 20 min, 20min
	num1, unit1 = timestamp:match( '^0*(%d+) *([a-z]+)$' )
	if num1 and validateUnit( unit1 ) and validateUnit( unit2 ) then
		return toSeconds( num1, unit1 ) + toSeconds( num2, unit2 )
	end

	-- 20 min 30 s, 20min 30s, 20min30s
	num1, unit1, num2, unit2 = timestamp:match( '^0*(%d+) *([a-z]+) *0*(%d+) *([a-z]+)$' )
	if num1 and validateUnit( unit1 ) and validateUnit( unit2 ) then
		return toSeconds( num1, unit1 ) + toSeconds( num2, unit2 )
	end

	-- 1 h 20 min 30 s, 1h 20min 30s, 1h20min30s
	num1, unit1, num2, unit2, num3, unit3 = timestamp:match( '^0*(%d+) *([a-z]+) *0*(%d+) *([a-z]+) *0*(%d+) *([a-z]+)$' )
	if num1 and validateUnit( unit1 ) and validateUnit( unit2 ) and validateUnit( unit3 ) then
		return toSeconds( num1, unit1 ) + toSeconds( num2, unit2 ) + toSeconds( num3, unit3 )
	end


	return false
end

local function abbr( text, title )
	return '<abbr class="abbr" title="' .. title .. '">' .. text .. '</abbr>'
end

function p.timestamp( frame )
	local timestamp = frame.args[ 1 ]

	local nbSeconds = timestampToNbSeconds( timestamp )
	if not nbSeconds then
		-- fallback: return the original input
		return timestamp
	end

	return nbSeconds .. 's'
end

function p.libelle( frame )
	local timestamp = frame.args[ 1 ]

	local nbSeconds = timestampToNbSeconds( timestamp )
	if not nbSeconds then
		-- fallback: return the original input
		return timestamp
	end

	if nbSeconds == 0 then
		-- special case: if timestamp at 0:00, return « 0 s » rather than empty string
		return '0' .. '\194\160' .. abbr( 's', 'seconde' )
	end

	local parts = {}

	local hours = math.floor( nbSeconds / 3600 )
	if hours > 0 then
		parts[ #parts + 1 ] = hours .. '\194\160' .. abbr( 'h', 'heure' .. ( hours > 1 and 's' or '' ) )
		nbSeconds = nbSeconds - hours * 3600
	end

	local minutes = math.floor( nbSeconds / 60 )
	if minutes > 0 then
		parts[ #parts + 1 ] = minutes .. '\194\160' .. abbr( 'min', 'minute' .. ( minutes > 1 and 's' or '' ) )
		nbSeconds = nbSeconds - minutes * 60
	end

	if nbSeconds > 0 then
		parts[ #parts + 1 ] = nbSeconds .. '\194\160' .. abbr( 's', 'seconde' .. ( nbSeconds > 1 and 's' or '' ) )
	end

	return table.concat( parts, '\194\160' )
end

return p