User:MagicMason1000/Sandbox/Cite YouTube

local p = {}

local utilsArg = require("Module:UtilsArg")

local CATEGORY_NEEDING_ARCHIVAL = "Web Citations Needing Archival" local CATEGORY_INVALID_ARGS = require("Module:Constants/category/invalidArgs")

function warn(msg, ...) local utilsError = require("Module:UtilsError") msg = string.format(msg, ...) utilsError.warn(msg) end

function p.Twitter(frame) local args, err = utilsArg.parse(frame:getParent.args, p.Templates["Cite Twitter"]) local categories = err and err.categoryText or "" local quote, url, archive = args.quote, args.url, args.archive if not url and not archive then local utilsError = require("Module:UtilsError") categories = categories.."" warn(" or   parameter is required.") return "Twitter", categories end if archive then local archivedUrl = string.match(archive, "https?://twitter%.com.*$") url = url or archivedUrl if url ~= archivedUrl then warn(" does not match the archived url in  \n:Url: %s\n:Archived Url: %s", url, archivedUrl) categories = categories.."" end else categories = categories.."" end local _, _, user, tweetId = string.find(url, "https?://twitter%.com/([^/]+)/status/([%d]+)/?") if not user or not tweetId then warn("Invalid tweet url detected: %s", url) categories = categories.."" end local timestamp = tweetId and p.getTimestamp(tweetId) local autoDate = timestamp and os.date("%B %e, %Y", timestamp) local date = args.date or autoDate if autoDate and args.date and autoDate ~= args.date then warn("The provided date does not match the date derived from the tweet url.\n:Provided date: %s\n:Derived date: %s\n:Url: %s", args.date, autoDate, url) categories = categories.."" end local link = user and string.format("[%s @%s on Twitter]", url, user or "Twitter") or string.format("[%s Twitter]", url) local source = link if date then source = source..", "..date end local citation = source if quote then citation = string.format("%s" — %s, quote, source) end if archive then citation = citation..string.format(" ([%s Archive])", archive) end return citation, categories end

-- From https://en.wikipedia.org/wiki/Module:TwitterSnowflake function p.getTimestamp(id_str) local epoch = 1288834974 local hi, lo = 0, 0 local hiexp = 1 local two32 = 2^32 for c in id_str:gmatch(".") do		lo = lo * 10 + c		if lo >= two32 then hi, lo = hi * 10^hiexp + math.floor(lo / two32), lo % two32 hiexp = 1 else hiexp = hiexp + 1 end end hi = hi * 10^(hiexp-1) local timestamp = math.floor((hi * 1024 + math.floor(lo / 4194304)) / 1000) + epoch if timestamp == epoch then return nil else return timestamp end end

function p.YouTube(frame) local args, err = utilsArg.parse(frame:getParent.args, p.Templates["Cite YouTube"]) local categories = err and err.categoryText or "" local title, channel, date, url, archive, time = args.title, args.channel, args.date, args.url, args.archive, args.time if not url and not archive then local utilsError = require("Module:UtilsError") categories = categories.."" warn(" or   parameter is required.") return "YouTube", categories end if archive then local archivedUrl = string.match(archive, "https?://youtube%.com/watch\?v\=.*$") url = url or archivedUrl if url ~= archivedUrl then warn(" does not match the archived url in  \n:Url: %s\n:Archived Url: %s", url, archivedUrl) categories = categories.."" end else categories = categories.."" end if time then url = url .. "\&t=" .. time end local link = channel and string.format("[%s @%s on YouTube]", url, user or "YouTube") or string.format("[%s YouTube]", url) local source = link if date then source = source..", "..date end local citation = source if title then citation = string.format("%s" — %s, quote, source) end if archive then citation = citation..string.format(" ([%s Archive])", archive) end return citation, categories end

p.Templates = { ["Cite Twitter"] = { purpose = "For citing Twitter posts in references. Can also be used in the  field of Template:FileInfo.", categories = {"Citation Templates", "File Source Templates"}, paramOrder = {"quote", "url", "archive", "date"}, boilerplate = { tabs = { {					label = "Tweets posted on or after November 4, 2010", params = {"quote", "url", "archive"}, },				{					label = "Tweets posted before November 4, 2010", params = {"quote", "url", "archive", "date"}, }			}			},		params = { quote = { type = "content", desc = "An excerpt from the tweet. Leave this blank for file sources.", trim = true, nilIfEmpty = true, },			url = { type = "url", desc = "The URL of the Tweet to cite. Optional if  is provided.", trim = true, nilIfEmpty = true, },			archive = { type = "url", desc = "A link to a web archive of the Tweet.", suggested = true, trim = true, nilIfEmpty = true, },			date = { type = "date", desc = " Date the tweet was posted in the format .  Omit this parameter if the tweet was posted on or after November 4, 2010. For such tweets the date can be derived from the URL. ", trim = true, nilIfEmpty = true, }		},		examples = { {				quote = "As a mark of respect during this period of national mourning, we will not livestream tomorrow’s Nintendo Direct. It will be published as a video-on-demand on our YouTube channel at 16:00 (UK time) tomorrow.", url = "https://twitter.com/NintendoUK/status/1569326012156059649", },			{				quote = "", url = "", archive = "http://web.archive.org/web/20220108160756/https://twitter.com/Dom_Auf/status/1100314210343505921", },			{				desc = " must be a full, valid URL to a specific tweet", args = { url = "https://twitter.com/not-a-real-url", },			},			{				desc = "If both  and   are specified, the URLs must match.", args = { url = "https://twitter.com/Dom_Auf/status/1100314210343505921", archive = "http://web.archive.org/web/20220108160756/https://twitter.com/Dom_Auf/status/notthesame", },			},			{				desc = " and   cannot both be empty.", args = {quote = "", url = "", archive = ""}, },			{				desc = " cannot be automatically generated for Tweets posted before November 4, 2010.", args = { quote = "just setting up my twttr", url = "https://twitter.com/jack/status/20", },			},		}	},	["Cite YouTube"] = { purpose = "For citing YouTube posts in references. Can also be used in the  field of Template:FileInfo.", categories = {"Citation Templates", "File Source Templates"}, paramOrder = {"title", "channel", "date", "url", "archive", "time"}, boilerplate = { tabs = { {					label = "YouTube Video", params = {"title", "channel", "date", "url", "archive"}, },				{					label = "YouTube Video with Timestamp", params = {"title", "channel", "date", "url", "archive", "time"}, }			}			},		params = { title = { type = "content", desc = "The title of the YouTube video.", trim = true, nilIfEmpty = true, },			channel = { type = "author", desc = "The handle of the YouTube channel the video was uploaded to. (Click on the channel and see the name starting with an \"@\" under their username.)" },			url = { type = "url", desc = "The URL of the YouTube video to cite. Optional if  is provided.", trim = true, nilIfEmpty = true, },			archive = { type = "url", desc = "A link to a web archive of the video.", suggested = true, trim = true, nilIfEmpty = true, },			date = { type = "date", desc = "Date the video was uploaded in the format .", trim = true, nilIfEmpty = true, }		},		examples = { {				title = "The Legend of Zelda: Tears of the Kingdom – Official Trailer #2", url = "https://www.youtube.com/watch?v=fYZuiFDQwQw", },			{				title = "", url = "", archive = "https://web.archive.org/web/20200406200840/https://www.youtube.com/watch?v=zw47_q9wbBE", },			{				desc = " must be a full, valid URL to a specific tweet", args = { url = "https://youtube.com/not-a-real-url", },			},			{				desc = "If both  and   are specified, the URLs must match.", args = { url = "https://www.youtube.com/watch?v=NIrY56yg7dY", archive = "http://web.archive.org/web/20220108160756/https://youtube.com/watch?v=differentcode", },			},			{				desc = " and   cannot both be empty.", args = {title = "", url = "", archive = ""}, },		}	} }

return p