Documentation for this module may be created at Module:DataAPIManifest/doc
-- Module:DataAPIManifest
--
-- Emits a JSON manifest describing the canonical entity-type categories
-- of the EveryCRT wiki, for use by third-party apps performing a full
-- or incremental sync of the wiki's semantic data.
--
-- Public functions:
-- p.json(frame) -- returns a pretty-printed JSON string describing
-- the wiki and its entity types, with live page
-- counts pulled from SMW.
--
-- See [[EveryCRT:Data API]] for full documentation and usage examples.
--
-- To add a new entity type to the API, add an entry to `entityTypes`
-- below. The category named here must exist (or be auto-populated by a
-- template, like Category:Documents) and contain all members of that
-- entity type.
local p = {}
-- This wiki is configured with $wgScriptPath = '' and $wgArticlePath = '/wiki/$1',
-- so api.php / rest.php live at the document root and articles at /wiki/PageName.
local API_URL = 'https://wiki.everycrt.com/api.php'
local BASE_URL = 'https://wiki.everycrt.com'
-- Canonical entity types. Each is enumerated via its MediaWiki category.
local entityTypes = {
{
key = 'crt_model',
label = 'CRT models',
category = 'CRT models',
description = 'CRT monitors, televisions, and professional video displays.',
},
{
key = 'av_device',
label = 'AV devices',
category = 'AV devices',
description = 'VCRs, TBCs, video mixers, switchers, and other vintage AV equipment.',
},
{
key = 'accessory',
label = 'Accessories',
category = 'Accessories',
description = 'Remotes, cables, antennas, and other accessories.',
},
{
key = 'part',
label = 'Parts',
category = 'Parts',
description = 'ICs, transistors, CRT tubes, flyback transformers, and other components.',
},
{
key = 'repair_service',
label = 'Repair services',
category = 'Repair services',
description = 'Repair shops and technicians serving the vintage AV community.',
},
{
key = 'document',
label = 'Documents',
category = 'Documents',
description = 'Manuals, brochures, spec sheets, service bulletins, and other reference documents.',
},
}
-- Returns the page count for a category by running #ask|format=count.
local function countCategory(frame, category)
local raw = frame:preprocess(
'{{#ask:[[Category:' .. category .. ']]|format=count}}'
)
if not raw then return 0 end
local stripped = raw:gsub('<[^>]+>', ''):gsub('^%s+', ''):gsub('%s+$', '')
return tonumber(stripped) or 0
end
-- Builds an action=ask URL that lists all pages of one entity type with
-- their last-modification timestamps -- suitable for indexing and for
-- driving incremental sync.
local function listUrl(category)
local query = '[[Category:' .. category .. ']]|?Modification date|limit=500|offset=0'
return API_URL .. '?action=ask&format=json&formatversion=2&query=' .. mw.uri.encode(query)
end
function p.json(frame)
local types = {}
for _, t in ipairs(entityTypes) do
table.insert(types, {
key = t.key,
label = t.label,
description = t.description,
category = t.category,
category_url = BASE_URL .. '/wiki/Category:' .. mw.uri.encode(t.category, 'WIKI'),
ask_query = '[[Category:' .. t.category .. ']]',
count = countCategory(frame, t.category),
list_url = listUrl(t.category),
})
end
local manifest = {
version = 1,
generated_at_utc = os.date('!%Y-%m-%dT%H:%M:%SZ'),
wiki = {
name = 'EveryCRT',
base_url = BASE_URL,
api_url = API_URL,
},
endpoints = {
list_entities = {
method = 'GET',
url = API_URL .. '?action=ask&format=json&formatversion=2&query=<ASK_QUERY>',
notes = 'Returns titles and selected printouts for entities matching the SMW ask query. Append |limit=N|offset=M for pagination (max limit 500).',
},
entity_facts = {
method = 'GET',
url = API_URL .. '?action=browsebysubject&format=json&formatversion=2&subject=<PAGE_TITLE>',
notes = 'Returns every SMW fact (property/value pair) for a single page, including subobjects (CRT inputs, outputs, voltage ranges, etc.).',
},
recent_changes = {
method = 'GET',
url = API_URL .. '?action=query&list=recentchanges&format=json&formatversion=2&rcprop=title%7Ctimestamp%7Cids%7Csizes%7Cuser&rclimit=500',
notes = 'Returns recent edits across all namespaces. Use rcend=<ISO timestamp> to fetch only changes since your last sync. Add &rcnamespace=N|N to filter by namespace.',
},
rdf_export = {
method = 'GET',
url = BASE_URL .. '/wiki/Special:ExportRDF?pages=<PAGE_TITLE>',
notes = 'Full RDF/OWL export. Use &recursive=1&pages=Category:CRT models to export an entire category subtree.',
},
},
entity_types = types,
}
local prettyFlag = mw.text.JSON_PRETTY or 0
return mw.text.jsonEncode(manifest, prettyFlag)
end
return p