Module:Cite Web: Difference between revisions
Jump to navigation
Jump to search
mNo edit summary |
PhantomCaleb (talk | contribs) No edit summary |
||
Line 25: | Line 25: | ||
end | end | ||
if archive then | if archive then | ||
local archivedUrl = string.match(archive, "https?://twitter%.com.*$") | local archivedUrl = string.match(archive, "https?://twitter%.com.*$") or string.match(archive, "https?://x%.com.*$") | ||
url = url or archivedUrl | url = url or archivedUrl | ||
if url ~= archivedUrl then | if url ~= archivedUrl then | ||
Line 36: | Line 36: | ||
local _, _, user, tweetId = string.find(url, "https?://twitter%.com/([^/]+)/status/([%d]+)/?") | local _, _, user, tweetId = string.find(url, "https?://twitter%.com/([^/]+)/status/([%d]+)/?") | ||
if not user or not tweetId then | |||
_, _, user, tweetId = string.find(url, "https?://x%.com/([^/]+)/status/([%d]+)/?") | |||
end | |||
if not user or not tweetId then | if not user or not tweetId then | ||
warn("Invalid tweet url detected: %s", url) | warn("Invalid tweet url detected: %s", url) | ||
Line 141: | Line 144: | ||
}, | }, | ||
{ | { | ||
desc = "Both <code>twitter.com</code> and <code>x.com</code> URLs are supported.", | |||
args = { | |||
url = "https://x.com/NintendoUK/status/1569326012156059649", | |||
}, | |||
}, | }, | ||
{ | { | ||
desc = "<code>url</code> must be a full, valid URL to a specific tweet", | desc = "<code>url</code> must be a full, valid URL to a specific tweet.", | ||
args = { | args = { | ||
url = "https://twitter.com/not-a-real-url", | url = "https://twitter.com/not-a-real-url", | ||
}, | }, | ||
}, | |||
{ | |||
desc = "<code>url</code> is not required if <code>archive</code> is specified as the former can be inferred from the latter.", | |||
quote = "", | |||
url = "", | |||
archive = "http://web.archive.org/web/20220108160756/https://twitter.com/Dom_Auf/status/1100314210343505921", | |||
}, | }, | ||
{ | { |
Latest revision as of 00:23, 20 May 2024
This is the main module for the following templates:
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.."[[Category:"..CATEGORY_INVALID_ARGS.."]]"
warn("<code>url</code> or <code>archive</code> parameter is required.")
return "[https://twitter.com Twitter]", categories
end
if archive then
local archivedUrl = string.match(archive, "https?://twitter%.com.*$") or string.match(archive, "https?://x%.com.*$")
url = url or archivedUrl
if url ~= archivedUrl then
warn("<code>url</code> does not match the archived url in <code>archive</code>\n:Url: %s\n:Archived Url: %s", url, archivedUrl)
categories = categories.."[[Category:"..CATEGORY_INVALID_ARGS.."]]"
end
else
categories = categories.."[[Category:"..CATEGORY_NEEDING_ARCHIVAL.."]]"
end
local _, _, user, tweetId = string.find(url, "https?://twitter%.com/([^/]+)/status/([%d]+)/?")
if not user or not tweetId then
_, _, user, tweetId = string.find(url, "https?://x%.com/([^/]+)/status/([%d]+)/?")
end
if not user or not tweetId then
warn("Invalid tweet url detected: %s", url)
categories = categories.."[[Category:"..CATEGORY_INVALID_ARGS.."]]"
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.."[[Category:"..CATEGORY_INVALID_ARGS.."]]"
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([["<i>%s</i>" — %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
-- Quick fix for Tweets before epoch with Tweet IDs >=two32
if timestamp <= epoch + 10 then
return nil
else
return timestamp
end
end
p.Templates = {
["Cite Twitter"] = {
purpose = "For citing Twitter posts in [[Guidelines:References|references]]. Can also be used in the <code>source</code> 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 <code>archive</code> is provided.",
trim = true,
nilIfEmpty = true,
},
archive = {
type = "url",
desc = "A link to a [https://web.archive.org web archive] of the Tweet.",
suggested = true,
trim = true,
nilIfEmpty = true,
},
date = {
type = "date",
desc = "<p>Date the tweet was posted in the format <code>Month Day, Year</code>.</p><p>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.</p>",
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",
},
{
desc = "Both <code>twitter.com</code> and <code>x.com</code> URLs are supported.",
args = {
url = "https://x.com/NintendoUK/status/1569326012156059649",
},
},
{
desc = "<code>url</code> must be a full, valid URL to a specific tweet.",
args = {
url = "https://twitter.com/not-a-real-url",
},
},
{
desc = "<code>url</code> is not required if <code>archive</code> is specified as the former can be inferred from the latter.",
quote = "",
url = "",
archive = "http://web.archive.org/web/20220108160756/https://twitter.com/Dom_Auf/status/1100314210343505921",
},
{
desc = "If both <code>url</code> and <code>archive</code> 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 = "<code>url</code> and <code>archive</code> cannot both be empty.",
args = {quote = "", url = "", archive = ""},
},
{
desc = "<code>date</code> 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 [[Guidelines:References|references]]. Can also be used in the <code>source</code> field of [[Template:FileInfo]].",
categories = {"Citation Templates", "File Source Templates"},
paramOrder = {"quote", "title", "channel", "date", "url", "archive", "time"},
boilerplate = {
tabs = {
{
label = "YouTube Video",
params = {"quote", "title", "channel", "date", "url", "archive"},
},
{
label = "YouTube Video with Timestamp",
params = {"quote", "title", "channel", "date", "url", "archive", "time"},
}
}
},
params = {
quote = {
type = "content",
desc = "An quote from the YouTube video. Leave this blank for file sources."
},
title = {
type = "content",
desc = "The title of the YouTube video.",
trim = true,
nilIfEmpty = true,
},
channel = {
type = "content",
desc = "The handle of the channel the video was uploaded to. This is found underneath the display name on their channel page; this always starts with an \"\@\" symbol."
},
date = {
type = "date",
desc = "The upload date of the YouTube video in the format <code>Month Day, Year</code>.",
trim = true,
nilIfEmpty = true,
},
url = {
type = "url",
desc = "The URL of the YouTube to cite. Do not include any URL parameters other than the ID of the YouTube video (i.e. <code>&t=</code>, <code>&feature=</code>, etc.)",
trim = true,
nilIfEmpty = true,
},
archive = {
type = "url",
desc = "The URL of a [https://web.archive.org/ Web Archive] of the YouTube video.",
suggested = true,
trim = true,
nilIfEmpty = true,
},
time = {
type = "string",
desc = "The timestamp of the exact point you are referencing in the video. Travel to the point in the video, right click, and select \"Copy video URL at current time.\" Paste it somewhere where you can see it, and the number after <code>?t=</code> is what you should enter here.",
trim = true,
nilIfEmpty = true,
}
},
examples = {
{
quote = "5.12.2023",
title = "The Legend of Zelda: Tears of the Kingdom – Official Trailer #2",
channel = "@NintendoAmerica",
date = "Feburary 8, 2023",
url = "https://www.youtube.com/watch?v=fYZuiFDQwQw",
archive = "https://web.archive.org/web/20230208233422/https://www.youtube.com/watch?v=fYZuiFDQwQw",
},
{
desc = "With timestamp included",
args = {
quote = "5.12.2023",
title = "The Legend of Zelda: Tears of the Kingdom – Official Trailer #2",
channel = "@NintendoAmerica",
date = "Feburary 8, 2023",
url = "https://www.youtube.com/watch?v=fYZuiFDQwQw",
archive = "https://web.archive.org/web/20230208233422/https://www.youtube.com/watch?v=fYZuiFDQwQw",
time = "128s",
},
},
{
desc = "With bare minimum required parameters",
args = {
title = "The Legend of Zelda: Tears of the Kingdom – Official Trailer #2",
channel = "@NintendoAmerica",
url = "https://www.youtube.com/watch?v=fYZuiFDQwQw",
},
},
{
desc = "<code>title</code>, <code>channel</code>, and <code>url</code> cannot be empty.",
args = {title = "", channel = "", url = ""},
},
}
}
}
return p