Модуль:Interwiki

Материал из свободной русской энциклопедии «Традиция»
Перейти к навигации Перейти к поиску

Для документации этого модуля может быть создана страница Модуль:Interwiki/doc

--[[
	Некоторые утилиты для получения данных других википроектов
--]]

-- Dependencies:
local concat = table.concat
local gsub, gmatch = mw.ustring.gsub, mw.ustring.gmatch
local lang = mw.language.getContentLanguage ()
local lang_name = require 'Module:Language'.name
local uri = mw.uri
local dump = mw.dumpObject
local ED = require 'Module:External data'
local fetch, all = ED.fetch, ED.fetch_all

-- Settings:
local settings = {
	{	-- 1
		title = "Сведения о ''[[MediaWiki]]''"
	  , page = 'api.php'
	  , format = 'XML'
	  , query = '?action=query&format=xml&meta=siteinfo&siprop=statistics|general'
	  , common = '/api/query/'
	  , {node = 'statistics/@pages',	label = 'Страниц'}
	  , {node = 'statistics/@articles',	label = 'Статей',	property = 'Содержит статей'}
	  , {node = 'statistics/@views',	label = 'Просмотров'}
	  , {node = 'statistics/@edits',	label = 'Правок'}
	  , {node = 'statistics/@images',	label = 'Изображений'}
	  , {node = 'statistics/@users',	label = 'Участников'}
	  , {node = 'statistics/@activeusers',label = 'Активных участников'}
	  , {node = 'statistics/@admins',	label = 'Администраторов'}
	  , {node = 'statistics/@jobs',		label = 'Заданий'}
	  , {node = 'general/@generator',	label = 'Движок',	property = 'Использует вики-движок'}
	  , {node = 'general/@dbtype',		label = 'Сервер БД'}
	  , {node = 'general/@dbversion',	label = 'Версия БД'}			  
	  , {node = 'general/@phpsapi',		label = 'Режим [[PHP]]'}
	  , {node = 'general/@phpversion',	label = 'Версия [[PHP]]'}
--[=[
	  , {node = 'general/@logo',		label = 'Логотип'}
	  , {node = 'general/@favicon',		label = 'Значок'}
--]=]
	  , {node = 'general/@lang',		label = 'Язык',		property = 'Основной раздел на языке', after = lang_name}
	  -- , {							label = 'Время', after = format_time}
	  -- , {							label = 'Просрочено'}
	
	}	-- 1
  , {	-- 2
  		title = "Сведения о ''[[Semantic MediaWiki]]''"
	  , page = 'api.php'
	  , format = 'XML'
  	  , query = '?action=smwinfo&format=xml&info=propcount|errorcount|deletecount'
  			 .. '|totalpropcount|usedpropcount|declaredpropcount|proppagecount'
  			 .. '|querycount|querysize|formatcount|conceptcount|subobjectcount|jobcount'
	  , common = '/api/info/'
	  , optional = true
	  , {node = '@propcount',		label = 'Значений свойств [[SMW]]'}
	  , {node = '@errorcount',		label = 'Ошибочных аннотаций SMW'}
	  , {node = '@deletecount',		label = 'Удалённых объектов SMW'}					  
	  , {node = '@usedpropcount',	label = 'Использованных свойств SMW'}					  
	  , {node = '@totalpropcount',	label = 'Всего свойств SMW'}
  	  , {node = '@declaredpropcount',label = 'Свойств SMW с типом'}
   	  , {node = '@proppagecount',	label = 'Страниц свойств SMW'}
   	  , {node = '@querycount',		label = 'Количество запросов SMW'}
   	  , {node = '@querysize',		label = 'Общее количество условий в запросах SMW'}
-- 				  , {node = 'formatcount',		label = 'Форматы запросов SMW'}
   	  , {node = '@conceptcount',	label = 'Количество концепций SMW'}
   	  , {node = '@subobjectcount',	label = 'Количество подобъектов SMW'} 
  	}	-- 2
  --[===[
  , { -- 3
  		title = 'Программное обеспечение'
  	  , page = 'Special:Version'
  	  , format = 'text'
	  , regex = [==[
/<a\s+class="external\s+mw-version-ext-name"\s+href="(?'url'[^"]+)">(?'name'.+?)<\/a>/
]==]
	  , loop = true
	  , template = 'Ссылка на расширение'
  	  , {node = 'name', label = 'Расширение'}
  	  , {node = 'url', label = 'URL'}
	}	-- 3
	--]===]
}	-- local settings

local function format_time (timestamp)
	return lang:formatDate ('d xg Y H:i:s', '@' .. tostring (timestamp), true)
end	-- local function format_time (timestamp)

local function format_num (str)
	return type (str) == 'number' and lang:formatNum (str) or str
end	-- local function format_num (str)
		
-- Свёртываемые таблицы:
local function hide (title, content)
	return '\n{{Навигационная полоса|заглавие = ' .. title .. ' | содержание = ' .. content .. '\n}}'
end	-- local function hide (title, content)

-- Попытка получения адреса страницы/api по URL викисайта:
local function pages (urls, page)
	-- Возможные пути к странице/api.php:
	local mw_paths = {'/w', '', '/mediawiki', '/mw', '/wikipedia', '/wiki'}
	local paths = {}
	if urls then
		for url in gmatch (urls, 'https?://%S+') do
			local hp_uri = uri.new (url)
			for key, path in ipairs (mw_paths) do
				hp_uri.path = path .. '/' .. page
				paths [#paths + 1] = tostring (hp_uri)
			end
		end
		return paths
	else
		return nil
	end
end	-- local function pages (urls, page)

-- Параметр data для #get_web_data:
local function mappings (data, common)
	local mappings = {}
	for _, datum in ipairs (data) do
		if datum.label then
			mappings [datum.label] = datum.node and (common or '') .. datum.node or datum.label
		end
	end
	return mappings
end	-- local function mappings (data, common)

-- Получение статистики по API викисайта:
local function fetch_stats (frame, paths, format, query, common, data, loop, template)
	local mappings = mappings (data, common)
	local errors = {}
	for _, path in ipairs (paths) do
		local fetched, real_path, date, error
		if loop then											--[[    one hour, use stale ]]
			fetched, real_path, date, error
				= all   (frame, path .. (query or ''), format, mappings, 60 * 60, true, template)
		else
			fetched, real_path, date, error
				= fetch (frame, path .. (query or ''), format, mappings, 60 * 60, true)
		end
		if fetched then
			return fetched, real_path
		else
			errors [#errors + 1] = error
		end	-- if fetched
	end	-- 	for _, path in ipairs (paths)
	return 'Ошибка соединения:\n{{под кат|1={{--}}\n* ' .. concat (errors, '\n* ') .. '}}'
end	-- local function fetch_stats (frame, paths, format, query, common, data, loop, template)

-- Форматирование одного статистического показателя:
local function format_one (values, property)
	if type (values) ~= 'table' then
		values = {values}
	end
	local annotations = {}
	for _, value in ipairs (values) do
		local annotation = property
			and ('[[' .. property .. '::' .. tostring (value)
			  .. '|' .. format_num (value) .. ']]')
			or format_num (value)
		if type (value) == 'number' then
			annotation = 'style="text-align:right; white-space: nowrap;" {{!}} ' .. annotation
		end
		annotations [#annotations + 1] = annotation
	end
	return concat (annotations, ', ')
end	-- local function format_one (values, property)

-- Форматирование статистических показателей в таблицу, с аннотациями SMW, где надо:
local function format_stats (stats, settings, url, title)
	if not stats or type (stats) == 'table' and not next (stats) then
		return nil
	end
	
	local formatted = '\n{{{!}} class="wikitable" style="background: transparent; width: 100%; word-wrap: anywhere;"'
	local time, stale = '', ''
	for _, stat in ipairs (settings) do
		local value = stats [stat.label]
		if value then
			if stat.after then
				value = stat.after (value)
			end
			if stat.label == '__time' then
				time = value
			elseif stat.label == '__stale' then
				stale = value == 'stale' and " ''(просрочено)''" or ''
			else
				formatted = formatted .. '\n{{!}}-\n{{!}} style="text-align:left" {{!}}' .. stat.label
									  .. '\n{{!}} ' .. format_one (value, stat.property)
			end	-- if stat.label ~= '__time'
		end	-- if value
	end	-- for _, stat in ipairs (settings)
	formatted = formatted .. '\n{{!}}}\n'
						  .. '<div align="right">на ' .. time .. stale
						  .. " ''([" .. gsub ((url or ''), '|' , '{{!}}') .. " источник])''</div>\n"
	return hide (title, formatted)
end	-- local function format_stats (stats, settings, url, title)

local function implement_statistics (url, script, frame)
	if url and url ~= '' and script then
		local stats, errors = {}, {}
		for _, request in ipairs (settings) do
			local pages = script and script ~= ''
				and {script}
				or pages (url, request.page)
			local result, real_url = fetch_stats (
				frame
			  , pages
			  , request.format
			  , request.query
			  , request.common
			  , request
			  , request.loop
			  , request.template
			)
			stats [#stats + 1] = real_url
				and format_stats (result, request, real_url, request.title)
				 or not request.optional and dump (result) or nil
		end
		return stats
	end
end	-- local function implement_statistics (url, api, frame)

--[[
	WikiData
--]]
local wd_api = 'https://www.wikidata.org/w/api.php?action=wbgetentities&languages=ru&format=xml&ids='

local function get_wikidata (frame, id)
	local mappings = {
		property	= '//property/@id'
	  , value		= '//datavalue/@value|//datavalue/value/@id|//datavalue/value/@time'
	  , type		= '//datavalue/@type'
	}	-- mappings
	local props, real_path, date, error = fetch (
		frame
	  , wd_api .. id
	  , 'XML'
	  , mappings
	  , --[[cache for one month]] 30 * 24 * 60 * 60
	  , --[[stale = ]] true
	)	-- local fetched, real_path, date, error = fetch (...)
	return props
end	-- local function get_wikidata (frame, id)

--[[
	Interface
--]]
return {
	statistics = function (frame)
		local stats = implement_statistics (frame.args.url, frame.args.api, frame)
		if type (stats) == 'table' and #stats > 0 then
			return frame:preprocess (concat (stats, '\n\n'))
		else
			return 'Передайте параметр api'
		end		
	end	-- statistics = function (frame)
}	-- return {...}