Module:YouTubeSubscribers
Appearance
![]() | This Lua module is used on approximately 3,400 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them. |
![]() | This module is rated as beta, and is ready for widespread use. It is still new and should be used with some caution to ensure the results are as expected. |
![]() | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
This module fetches a YouTube channel's subscriber count from its Wikidata entity.
Usage
{{#invoke:YouTubeSubscribers|subCount|qid=Wikidata entity ID (optional)}}
{{#invoke:YouTubeSubscribers|subCountNice|qid=Wikidata entity ID (optional)}}
– formats the subscriber count
{{#invoke:YouTubeSubscribers|date|qid=Wikidata entity ID (optional)}}
{{#invoke:YouTubeSubscribers|dateNice|qid=Wikidata entity ID (optional)}}
Data retrieval problem codes
- -404 – Could not find a single best YouTube channel ID for this item. Add a YouTube channel ID or set the rank of one channel ID to be preferred
- -412 – Found an associated YouTube channel ID but could not find a most recent value for social media followers (i.e. P8687 qualified with P585 and P2397)
- -424 – No qid found for page. Please make a Wikidata item for this article
Error tracking category
POINT_IN_TIME_PID = "P585"
YT_CHAN_ID_PID= "P2397"
SUB_COUNT_PID = "P8687"
local p = {}
-- taken from https://en.wikipedia.org/wiki/Module:Wd
function parseDate(dateStr, precision)
precision = precision or "d"
local i, j, index, ptr
local parts = {nil, nil, nil}
if dateStr == nil then
return parts[1], parts[2], parts[3] -- year, month, day
end
-- 'T' for snak values, '/' for outputs with '/Julian' attached
i, j = dateStr:find("[T/]")
if i then
dateStr = dateStr:sub(1, i-1)
end
local from = 1
if dateStr:sub(1,1) == "-" then
-- this is a negative number, look further ahead
from = 2
end
index = 1
ptr = 1
i, j = dateStr:find("-", from)
if i then
-- year
parts[index] = tonumber(mw.ustring.gsub(dateStr:sub(ptr, i-1), "^\+(.+)$", "%1"), 10) -- remove '+' sign (explicitly give base 10 to prevent error)
if parts[index] == -0 then
parts[index] = tonumber("0") -- for some reason, 'parts[index] = 0' may actually store '-0', so parse from string instead
end
if precision == "y" then
-- we're done
return parts[1], parts[2], parts[3] -- year, month, day
end
index = index + 1
ptr = i + 1
i, j = dateStr:find("-", ptr)
if i then
-- month
parts[index] = tonumber(dateStr:sub(ptr, i-1), 10)
if precision == "m" then
-- we're done
return parts[1], parts[2], parts[3] -- year, month, day
end
index = index + 1
ptr = i + 1
end
end
if dateStr:sub(ptr) ~= "" then
-- day if we have month, month if we have year, or year
parts[index] = tonumber(dateStr:sub(ptr), 10)
end
return parts[1], parts[2], parts[3] -- year, month, day
end
-- taken from https://en.wikipedia.org/wiki/Module:Wd
local function datePrecedesDate(aY, aM, aD, bY, bM, bD)
if aY == nil or bY == nil then
return nil
end
aM = aM or 1
aD = aD or 1
bM = bM or 1
bD = bD or 1
if aY < bY then
return true
end
if aY > bY then
return false
end
if aM < bM then
return true
end
if aM > bM then
return false
end
if aD < bD then
return true
end
return false
end
function serializeTable(val, name, skipnewlines, depth)
skipnewlines = skipnewlines or false
depth = depth or 0
local tmp = string.rep(" ", depth)
if name then tmp = tmp .. name .. " = " end
if type(val) == "table" then
tmp = tmp .. "{" .. (not skipnewlines and "\n" or "")
for k, v in pairs(val) do
tmp = tmp .. serializeTable(v, k, skipnewlines, depth + 1) .. "," .. (not skipnewlines and "\n" or "")
end
tmp = tmp .. string.rep(" ", depth) .. "}"
elseif type(val) == "number" then
tmp = tmp .. tostring(val)
elseif type(val) == "string" then
tmp = tmp .. string.format("%q", val)
elseif type(val) == "boolean" then
tmp = tmp .. (val and "true" or "false")
else
tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\""
end
return tmp
end
function getClaimDate(claim)
if claim['qualifiers'] and claim['qualifiers'][POINT_IN_TIME_PID] then
local pointsInTime = claim['qualifiers'][POINT_IN_TIME_PID]
if #pointsInTime ~= 1 then
-- be conservative in what we accept
return nil
end
local pointInTime = pointsInTime[1]
if pointInTime and pointInTime['datavalue'] and pointInTime['datavalue']['value'] and pointInTime['datavalue']['value']['time'] then
return parseDate(pointInTime['datavalue']['value']['time'])
end
end
return nil
end
function newestMatching(claims, chanId)
--if v['qualifiers'] and v['qualifiers'][POINT_IN_TIME_PID] then
end
function p.date( frame )
local qid = frame.args["qid"]
if not qid then
qid = mw.wikibase.getEntityIdForCurrentPage()
end
local e = mw.wikibase.getEntity(qid)
local chanIds = e:getBestStatements(YT_CHAN_ID_PID)
local firstChanId = chanIds[1]["mainsnak"]["datavalue"]["value"]
local subCounts = e:getBestStatements(SUB_COUNT_PID)
local subCount = nil
for k, v in pairs(subCounts) do
if v['qualifiers'] and v['qualifiers'][YT_CHAN_ID_PID] then
local yt_qualifier = v['qualifiers'][YT_CHAN_ID_PID]
return getClaimDate(v)
end
end
end
function p.subCount( frame )
local qid = frame.args["qid"]
if not qid then
qid = mw.wikibase.getEntityIdForCurrentPage()
end
local e = mw.wikibase.getEntity(qid)
local subCount = nil
local chanIds = e:getBestStatements(YT_CHAN_ID_PID)
if #chanIds == 1 then
local firstChanId = chanIds[1]["mainsnak"]["datavalue"]["value"]
local subCounts = e:getBestStatements(SUB_COUNT_PID)
for k, v in pairs(subCounts) do
if v['qualifiers'] and v['qualifiers'][YT_CHAN_ID_PID] then
local yt_qualifier = v['qualifiers'][YT_CHAN_ID_PID]
if yt_qualifier[1]['datavalue']['value'] == firstChanId then
subCount = v["mainsnak"]["datavalue"]["value"]["amount"]
end
end
end
end
if subCount then
return tonumber(subCount)
else
error("could not find sub count")
return "?"
end
end
return p