Module:Wd

local wd = { -- -- -- Константы ET_xxx	(entity types) -- ET_ITEM      = "item", ET_PROPERTY  = "property", ET_STATEMENT = "statement", -- -- -- Константы DT_xxx	(data types) -- DT_ITEM      = "wikibase-item",        --  "datavalue": { "value": { "numeric-id": 1551807, "entity-type": "item" }, "type": "wikibase-entityid" } DT_PROPERTY  = "wikibase-property",    --  "datavalue": { "value": { "numeric-id": 1753, "entity-type": "property" }, "type": "wikibase-entityid" } DT_DATETIME  = "time",                 --  "datavalue": { "value": { "before": 0, "time": "+2013-10-28T00:00:00Z", "timezone": 0, "precision": 11, "after": 0, --                           "calendarmodel": "http://www.wikidata.org/entity/Q1985727"}, --                "type": "time"} DT_COMMONS   = "commonsMedia",         --  "datavalue": { "value": "Turgenev by Repin.jpg", "type": "string" }, "datatype": "commonsMedia" } DT_STRING    = "string",               --  "datavalue": { "value": "/m/04j_pj", "type": "string" } DT_URL       = "url",                  --  "datavalue": { "value": "http://www.acme.com/", "type": "string" } DT_ML_STRING = "monolingualtext",      --  "datavalue": { "value": { "language": "ru", "text": "Накануне" }, "type": "monolingualtext" } DT_COORD     = "globe-coordinate",     --  "datavalue": { "value": { "longitude": 30.352547, "precision": 1e-05, --                           "globe": "http://www.wikidata.org/entity/Q2", "latitude": 59.943044 }, --                "type": "globecoordinate" } DT_QUANTITY  = "quantity",             --  "datavalue": { "value": { "amount": "+103", "upperBound": "+104", "lowerBound": "+102", --                           "unit": "http://www.wikidata.org/entity/Q42289" }, --                "type": "quantity" } -- -- -- Константы VT_xxx	(value types) -- VT_ENTITY_ID = "wikibase-entityid",   -- используется для DT_ITEM и DT_PROPERTY VT_DATETIME  = "time",                -- используется для DT_DATETIME VT_COORD     = "globecoordinate",     -- используется для DT_COORD VT_STRING    = "string",              -- используется для DT_STRING, DT_URL и DT_COMMONS VT_ML_STRING = "monolingualtext",     -- используется для DT_ML_STRING VT_QUANTITY  = "quantity",            -- используется для DT_QUANTITY -- -- -- Константы ST_xxx	(snak types) -- ST_VALUE    = "value",        -- "конкретное значение" ST_UNKNOWN  = "somevalue",    -- "значение неизвестно" ST_NO_VALUE = "novalue",      -- "значение отсутствует" -- -- -- Константы RANK_xxx	(ranks) -- RANK_NORNAL     = "normal",       -- "нормальный ранг" RANK_PREFERRED  = "preferred",    -- "предпочтительный ранг" RANK_DEPRECATED = "deprecated",   -- "нерекомендуемый ранг" -- -- -- Константы TP_xxx	(time precision) -- TP_10E8_YEARS =  1,   -- 100 млн лет TP_10E7_YEARS =  2,   -- 10 млн лет TP_10E6_YEARS =  3,   -- 1 млн лет TP_10E5_YEARS =  4,   -- 100 тыс лет TP_10E4_YEARS =  5,   -- 10 тыс лет TP_10E3_YEARS =  6,   -- 1 тыс лет TP_CENTURY    =  7,   -- 100 лет TP_DECADE     =  8,   -- 10 лет TP_YEAR       =  9,   -- 1 год TP_MONTH      = 10,   -- 1 месяц TP_DAY        = 11,   -- 1 день -- -- -- Константы CM_xxx	(calendar model) -- CM_GREGORIAN = "http://www.wikidata.org/entity/Q1985727",  -- пролептический григорианский календарь CM_JULIAN    = "http://www.wikidata.org/entity/Q1985786",  -- пролептический юлианский календарь -- -- -- Константа GLOBE_xxx	(небесное тело, к которому относятся координаты) -- GLOBE_EARTH  = "http://www.wikidata.org/entity/Q2",    -- Земля GLOBE_MOON   = "http://www.wikidata.org/entity/Q405"   -- Луна -- }; -- -- -- Константы -- local LANG_EN = "en"; local MSG_NO_LABEL = "нет метки"; local MSG_NO_DESCRIPTION = "нет описания"; -- -- -- Сообщения об ошибках -- local ERRMSG_PROPERTY_NOT_FOUND = "свойство %s не найдено"; local ERRMSG_ITEM_NOT_FOUND = "элемент %s не найден"; local ERRMSG_ENTITY_NOT_FOUND = "сущность %s не найдена"; local ERRMSG_CLAIM_NOT_FOUND = "%s не имеет %s"; -- -- -- function wd.is_property(entity) return (entity ~= nil) and (entity["type"] == wd.ET_PROPERTY); end; -- function wd.is_item(entity) return (entity ~= nil) and (entity["type"] == wd.ET_ITEM); end; -- function wd.is_statement(statement) return (statement ~= nil) and (statement["type"] == wd.ET_STATEMENT); end; -- function wd.get_statement_value(statement, s_datatype, s_value_type) if statement == nil then return nil; end; local snak = statement["mainsnak"]; if (snak == nil) or (snak["datatype"] ~= s_datatype) or (snak["snaktype"] ~= wd.ST_VALUE) then return nil; end; local datavalue = snak["datavalue"]; if (datavalue == nil) or (datavalue["type"] ~= s_value_type) then return nil; end; return datavalue["value"]; end; -- function wd.get_item_id(statement) local value = wd.get_statement_value(statement, wd.DT_ITEM, wd.VT_ENTITY_ID); if (value == nil) or (value["entity-type"] ~= wd.ET_ITEM) then return nil; end; return value["numeric-id"]; end; -- function wd.get_item_qid(statement) local n_id = wd.get_item_id(statement); if n_id == nil then return nil; else return "Q" .. tostring(n_id); end; end; -- function wd.has_valid_item_value (entity, s_property_id, n_item_id) local claim = nil; if (entity ~= nil) and (entity.claims ~= nil) then claim = entity.claims[s_property_id]; end; if claim ~= nil then for key, value in pairs(claim) do     if (value.rank ~= wd.RANK_DEPRECATED) and (wd.get_item_id(value) == n_item_id) then return true; end; end; end; return false; end; -- function wd.get_label(entity, s_lang, s_default) local s_label = s_default; if entity["labels"] ~= nil then local l = entity.labels[s_lang]; if (l == nil) and (s_lang ~= LANG_EN) then l = entity.labels[LANG_EN]; end; if l ~= nil then s_label = l.value; end; end; return s_label; end; -- function wd.get_description(entity, s_lang, s_default) local s_description = s_default; if entity["descriptions"] ~= nil then local l = entity.descriptions[s_lang]; if (l == nil) and (s_lang ~= LANG_EN) then l = entity.descriptions[LANG_EN]; end; if l ~= nil then s_description = l.value; end; end; return s_description; end; -- -- -- Функции для получения ссылки на данный вики-проект в виде (пример для Q644102): --  { "site": "ruwiki", "title": "Спасо-Преображенский собор (Санкт-Петербург)", "badges": { 1: "Q17437798" } } -- Если ссылки нет, возвращает nil. -- Примеры --  local sitelink = wd.get_sitelink(entity, "ruwiki"); --  local sitelink = wd.get_sitelink_by_lang(entity, "wiki", ["ru", "de", "en"]); -- function wd.get_sitelink(entity, s_code) if entity["sitelinks"] == nil then return nil; end; return entity.sitelinks[s_code]; end; -- function wd.get_sitelink_by_lang(entity, s_suffix, langs) if entity["sitelinks"] == nil then return nil; end; local sitelink = nil; for key, s_lang in pairs(langs) do   sitelink = entity.sitelinks[s_lang .. s_suffix]; if sitelink ~= nil then break; end; end; return sitelink; end; -- local map = { ruwikisource   = "s:", ruwiki         = "", ruwikiquote    = "q:", ruwikinews     = "n:", ruwikivoyage   = "voy:", commonswiki    = "commons:", wikidatawiki   = "d:", specieswiki    = "species:" }; -- local lang_map = { wikisource   = "s:", wiki         = "", wikiquote    = "q:", wikinews     = "n:", wikivoyage   = "voy:" }; -- function wd.map_sitelink_to_prefix(s_site) local s_iw_prefix = map[s_site]; if s_iw_prefix ~= nil then return s_iw_prefix; end; local n_len = mw.ustring.len(s_site); for s_suffix, s_iw_prefix in pairs(lang_map) do   --mw.log("suffix: "..s_suffix); --mw.log("interwiki prefix: "..s_iw_prefix); local n_suffix_len = mw.ustring.len(s_suffix); local n_lang_len = n_len - n_suffix_len; if (n_lang_len > 0) and (mw.ustring.sub(s_site, -n_suffix_len) == s_suffix) then return s_iw_prefix .. mw.ustring.sub(s_site, 1, n_lang_len) .. ":";   end; end; error("Can't map " .. s_site .. " to a interwiki link"); end; -- -- --  --  --  function wd.map_sitelink (frame) return ""..wd.map_sitelink_to_prefix(tostring(frame.args[1]))..""; end; -- -- --  --  --function wd.dump_iwikimap (frame) -- return wd.table_to_string(mw.site.interwikiMap(tostring(frame.args[1])), ""); --end; -- -- -- Функция для Шаблон:WD label -- Возвращает метку элемента или свойства -- -- Примеры для свойств: --   → дата рождения --   → date of birth --   → Geburtsdatum --   → natus -- --   → титул --   → noble title --   → noble title (так как метки на латыни нет) -- --   → ошибка  (несуществующее свойство) -- -- Примеры для элементов: --  → Земля --  → Earth --  → Erde --  → Tellus -- --  → ошибка  (несуществующий элемент) --  → Category:Aquitanians (перенаправление Q8258093 → Q6305566) -- function wd.label (frame) local s_id = tostring(frame.args[1]); local s_lang = tostring(frame.args[2]); local entity = mw.wikibase.getEntityObject(s_id); if entity == nil then if mw.ustring.match(s_id, "[Qq]%d+") ~= nil then error(mw.ustring.format(ERRMSG_ITEM_NOT_FOUND, s_id)); elseif mw.ustring.match(s_id, "[Pp]%d+") ~= nil then error(mw.ustring.format(ERRMSG_PROPERTY_NOT_FOUND, s_id)); else error(mw.ustring.format(ERRMSG_ENTITY_NOT_FOUND, s_id)); end; end; return wd.get_label(entity, s_lang, MSG_NO_LABEL); end; -- function wd.description (frame) local s_id = tostring(frame.args[1]); local s_lang = tostring(frame.args[2]); local entity = mw.wikibase.getEntityObject(s_id); if entity == nil then if mw.ustring.match(s_id, "[Qq]%d+") ~= nil then error(mw.ustring.format(ERRMSG_ITEM_NOT_FOUND, s_id)); elseif mw.ustring.match(s_id, "[Pp]%d+") ~= nil then error(mw.ustring.format(ERRMSG_PROPERTY_NOT_FOUND, s_id)); else error(mw.ustring.format(ERRMSG_ENTITY_NOT_FOUND, s_id)); end; end; return wd.get_description(entity, s_lang, MSG_NO_DESCRIPTION); end; -- function wd.datatype (frame) local s_id = tostring(frame.args[1]); local entity = mw.wikibase.getEntityObject(s_id); if (entity == nil) or (not wd.is_property(entity)) then error(mw.ustring.format(ERRMSG_PROPERTY_NOT_FOUND, s_id)); end; return entity.datatype; end; -- -- --  --  --  --  -- function wd.sitelink (frame) local s_item_id = tostring(frame.args[1]); local s_code = tostring(frame.args[2]); local entity = mw.wikibase.getEntityObject(s_item_id); if (entity == nil) or not wd.is_item(entity) then error(mw.ustring.format(ERRMSG_ITEM_NOT_FOUND, s_item_id)); end; local sitelink = nil; local s_lang = frame.args[3]; if s_lang == nil then   -- если третий параметр не указан, вызываем get_sitelink sitelink = wd.get_sitelink(entity, s_code); else local langs = {}; -- пустой массив langs[3] = tostring(s_lang); local n_index = 4; s_lang = frame.args[3]; while s_lang ~= nil do     langs[n_index] = tostring(s_lang); n_index = n_index + 1; s_lang = frame.args[n_index]; end; sitelink = wd.get_sitelink_by_lang(entity, s_code, langs); end; if sitelink == nil then return nil; else return wd.map_sitelink_to_prefix(sitelink.site) .. sitelink.title; end; end; -- -- s_suffix - sitelink проекта ("wiki", "wikisource", "wikiwikiquote", "wikivoyage" или "wikinews") function wd.get_multilingual_sitelink(entity, s_suffix, lang_properties) if (entity == nil) or (entity["sitelinks"] == nil) then return nil; end; local sitelink = entity.sitelinks["ru" .. s_suffix]; if sitelink ~= nil then return wd.map_sitelink_to_prefix(sitelink.site) .. sitelink.title; elseif lang_properties == nil then return nil; end; -- собираем языки в langs local langs = {Q7737="ru"};  -- список языков, sitelink'и для которых мы уже проверили local lang_cache = nil;         -- кэш языков из Модуль:Wikidata:Dictionary/P424 for key1, s_lang_property in pairs(lang_properties) do   --mw.log("look at " .. s_lang_property); for key2, statement in pairs(entity:getBestStatements(s_lang_property)) do     local s_lang_qid = wd.get_item_qid(statement); --mw.log(" " .. s_lang_qid); if (s_lang_qid ~= nil) and langs[s_lang_qid] == nil then if lang_cache == nil then     -- кэш языков загружаем только в первый раз lang_cache = mw.loadData('Модуль:Wikidata:Dictionary/P424'); end; local l = lang_cache[s_lang_qid]; if l == nil then mw.log("В Модуль:Wikidata:Dictionary/P424 отсутствует язык " .. s_lang_qid); else for key3, s_lang in pairs(l) do           sitelink = entity.sitelinks[s_lang..s_suffix]; if sitelink ~= nil then return wd.map_sitelink_to_prefix(sitelink.site) .. sitelink.title; end; langs[s_lang_qid] = s_lang; end; end; end; end; end; return nil; end; -- -- function s.test_get_multilingual_sitelink (frame) local s_qid     = tostring(frame.args[1]);  local s_suffix  = tostring(frame.args[2]);  local entity = mw.wikibase.getEntityObject(s_qid);  local s_sitelink = s.get_multilingual_sitelink(entity, s_suffix, {"P1412","P103"});  if s_sitelink == nil then    return "nil";  else    return s_sitelink;  end; end; -- -- -- Функция для Шаблон:WD property -- Возвращает строку вида: <метка> (Pxxx) -- -- -- Параметры: -- id — идентификатор свойства Викиданных (Pxxx) -- lang — двухбуквенный код языка, на котором отображается метка (ru, en, de, etc) -- -- Если метки на этом языке нет, то возвращается метка на английском (она почти всегда есть) -- -- Примеры: --   → дата рождения (P569) --   → date of birth (P569) --   → Geburtsdatum (P569) --   → natus (P569) -- --   → титул (P97) --   → noble title (P97) --   → noble title (P97) (так как метки на латыни нет) -- --   → ошибка  (несуществующее свойство) -- function wd.format_property (frame) local s_property_id = tostring(frame.args[1]); local s_lang = tostring(frame.args[2]); local entity = mw.wikibase.getEntityObject(s_property_id); if (entity == nil) or not wd.is_property(entity) then error(mw.ustring.format(ERRMSG_PROPERTY_NOT_FOUND, s_property_id)); end; return "" .. wd.get_label(entity, s_lang, MSG_NO_LABEL) .. " (" .. entity.id .. ")"; end; -- -- -- Функция для Шаблон:WD item -- Возвращает строку вида: <метка> (Qxxx) -- -- -- Параметры: -- id — идентификатор элемента Викиданных (Qxxx) -- lang — двухбуквенный код языка, на котором отображается метка (ru, en, de, etc) -- -- Если метки на этом языке нет, то возвращается метка на английском -- -- Примеры: --  → Земля (Q2) --  → Earth (Q2) --  → Erde (Q2) --  → Tellus (Q2) -- --  → ошибка (несуществующий элемент) --  → Category:Aquitanians (Q6305566) (перенаправление Q8258093 → Q6305566) -- function wd.format_item (frame) local s_item_id = tostring(frame.args[1]); local s_lang = tostring(frame.args[2]); local entity = mw.wikibase.getEntityObject(s_item_id); if (entity == nil) or not wd.is_item(entity) then error(mw.ustring.format(ERRMSG_ITEM_NOT_FOUND, s_item_id)); end; return "" .. wd.get_label(entity, s_lang, MSG_NO_LABEL) .. " (" .. entity.id .. ")"; end; -- -- -- Сервисная функция, позволяющая преобразовать таблицу LUA в её текстовое представление -- function wd.table_to_string(t, s_indent) local s_result = "{"; -- флажок, чтобы не добавлять запятую после последнего элемента, и чтобы при пустой таблице возвращалось "{" .. s_indent .. "}" local b_first = true; for key, value in pairs(t) do   if b_first then s_result = s_result .. " "; -- перед первым элементом добавляем перевод строки b_first = false;                -- и сбрасываем флажок else s_result = s_result .. ", "; -- перед всеми последующими добавляем запятую и перевод строки end; local s_str = ""; if value == nil then s_str = "nil"; elseif type(value) == "table" then s_str = wd.table_to_string(value, s_indent .. " "); elseif type(value) == "string" then s_str = "\"" .. value .. "\""; else -- type(value) == "number", "boolean" или "function" s_str = tostring(value); end; if (type(key) == "number") or (type(key) == "boolean") then s_result = s_result .. s_indent .. tostring(key) .. ": " .. s_str; else s_result = s_result .. s_indent .. "\"" .. tostring(key) .. "\": " .. s_str; end; end; if not b_first then s_result = s_result .. " "; -- если был хотя бы один элемент, добавляем перевод строки end; return s_result .. s_indent .. "}"; end; -- -- -- Отладочная функция, позволяющая показать элемент или свойство Викиданных, возвращаемое функцией mw.wikibase.getEntityObject -- -- Примеры: -- -- -- function wd.dump_entity(frame) local s_id = tostring(frame.args[1]); local entity = mw.wikibase.getEntityObject(s_id); if entity == nil then if mw.ustring.match(s_id, "[Qq]%d+") ~= nil then error(mw.ustring.format(ERRMSG_ITEM_NOT_FOUND, s_id)); elseif mw.ustring.match(s_id, "[Pp]%d+") ~= nil then error(mw.ustring.format(ERRMSG_PROPERTY_NOT_FOUND, s_id)); else error(mw.ustring.format(ERRMSG_ENTITY_NOT_FOUND, s_id)); end; end; return wd.table_to_string(entity, ""); end; -- -- -- -- function wd.dump_sitelinks(frame) local s_id = tostring(frame.args[1]); local entity = mw.wikibase.getEntityObject(s_id); if (entity == nil) or not wd.is_item(entity) then error(mw.ustring.format(ERRMSG_ITEM_NOT_FOUND, s_item_id)); end; if entity["sitelinks"] == nil then return "nil" else return wd.table_to_string(entity.sitelinks, ""); end; end; -- --[[ (item, одно значение) (wikibase-entityid) (time)

(monolingualtext) (url)

Примеры значений переменной value (вязто с помощью https://www.wikidata.org/wiki/Special:EntityData/Q15920521.json): [{"id":"Q15920521$f7c04336-4b68-8307-c98c-569412466eaa", "mainsnak":{"snaktype":"value", "property":"P1476", "datatype":"monolingualtext", "datavalue":{"value":{"text":"Ночные мысли","language":"ru"},"type":"monolingualtext"}}, "type":"statement", "rank":"normal"}]

[{"id":"Q359$36814403-433c-591b-eaff-22a38472a46b", "mainsnak":{"snaktype":"value", "property":"P856", "datatype":"url", "datavalue":{"value":"https://wikileaks.org/","type":"string"}}, "type":"statement", "rank":"normal"}] ]] function wd.dump_statements(frame) local s_id = tostring(frame.args[1]); local s_property_id = tostring(frame.args[2]); local entity = mw.wikibase.getEntityObject(s_id); if entity == nil then if mw.ustring.match(s_id, "[Qq]%d+") ~= nil then error(mw.ustring.format(ERRMSG_ITEM_NOT_FOUND, s_id)); elseif mw.ustring.match(s_id, "[Pp]%d+") ~= nil then error(mw.ustring.format(ERRMSG_PROPERTY_NOT_FOUND, s_id)); else error(mw.ustring.format(ERRMSG_ENTITY_NOT_FOUND, s_id)); end; end; local claim = nil; if entity.claims ~= nil then claim = entity.claims[s_property_id]; end; if claim == nil then error(mw.ustring.format(ERRMSG_CLAIM_NOT_FOUND, s_id, s_property_id)); end; return wd.table_to_string(claim, ""); -- local s_result = ""  for key, value in pairs(claim) do    local snak = value.mainsnak;    s_result = s_result .. "[" .. key .. "]: id = " .. value.id .. ", type = " .. value.type .. ", rank = " .. value.rank .. ", snaktype = " .. snak.snaktype .. ", property = " .. snak.property    if snak.snaktype == "value" then      s_result = s_result .. ", datatype = " .. snak.datavalue.type      if snak.datavalue.type == "wikibase-entityid" then          s_result = s_result .. ", value = Q".. tostring(snak.datavalue.value["numeric-id"])      elseif snak.datavalue.type == "string" then          s_result = s_result .. ", value = '" .. snak.datavalue.value .."'"      elseif snak.datavalue.type == "monolingualtext" then          s_result = s_result .. ", language = '" .. snak.datavalue.value.language .. "', value = '" .. snak.datavalue.value.text .."'"      elseif snak.datavalue.type == "url" then          s_result = s_result .. ", value = '" .. snak.datavalue.value .."'"      elseif snak.datavalue.type == "time" then          s_result = s_result .. ", value = " .. snak.datavalue.value.time .. " (precision = " .. tostring(snak.datavalue.value.precision) .. ", before = " .. tostring(snak.datavalue.value.before) .. ",  after = " .. tostring(snak.datavalue.value.after) .. ", timezone = " .. tostring(snak.datavalue.value.timezone) .. ", calendarmodel = " .. tostring(snak.datavalue.value.calendarmodel) .. ")"      end    end    s_result = s_result .. " "  end;  return s_result; end;

return wd;