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
MediaWiki Appliance - Powered by TurnKey Linux