Данное API предназначено для централизованного хранения данных пользователя. Здесь описывается не физическая структура хранения, а логическая структура данных пользователя. Сервис предполагает доступ только аутентифицированного пользователя.
Примерами использования данного API являются:
Поскольку API использует гибкую структуру хранения данных, над которыми могут производится различные операции выборки, крайне не рекомендуется использовать атрибуты классов не по назначению, а также хранить комплексные агрегированные данные в рамках одного атрибута, если это явно не оговорено.
В этом документе используются термины и определения, описанные в документах «О программных интерфейсах сервисов Инетры» и «Термины и определения».
Данные пользователя имеют древовидную структуру элементов, на одном уровне иерархии которого не может существовать двух элементов с одинаковым идентификатором. Элементы, лежащие уровнем ниже относительно элемента называются «дочерними» элементами, для которых он, в свою очередь, называется «родительским».
Каждый элемент имеет идентификатор и относится к одному или более классам. Класс определяет набор атрибутов элемента.
Атрибуты элементов могут быть следующих типов данных:
Виды атрибутов:
Каждый элемент имеет следующие атрибуты:
id
— строковый единичный — уникальный (среди элементов текущего уровня) идентификатор элементаclass_name
— строковый необязательный множественный — множество классов элементаcreated_by
— строковый обязательный единичный — идентификатор приложения, создавшего элементautogenerated_id
— булев обязательный единичный — признак автоматически сгенерированного идентификатора элементаctime
— целочисленный обязательный единичный — время создания элемента (в формате Unix timestamp)mtime
— целочисленный обязательный единичный — время последнего изменения атрибутов элемента (в формате Unix timestamp)С точки зрения структур передаваемых данных id
элемента не является его атрибутом.
Путем до элемента называется строка, состоящая из идентификаторов его родительских элементов, разделенных символом /
. При этом идентификаторы элементов должны быть закодированы также, как кодируются элементы URI.
При выборке элементов используется понятие фильтра элементов. Фильтр — это выражение, определяющее критерии отбора элементов. Если фильтр не указан, в выборку попадают все элементы.
Выражение фильтра элементов записывается в префиксной нотации, состоящей из логических операторов и операндов, в свою очередь являющихся внутренними операторами сопоставления значений атрибутов (в левой части) с выражениями (в правой части) с использованием знака оператора.
Одним из операторов сопоставления значений является пустой оператор, в таком случае фильтр интерпретируется как допускающий любое заполненное значение для необязательного атрибута.
Все остальные операторы работают по–разному в зависимости того, применяются они к единичным атрибутам или ко множественным.
Так как для всех типов данных атрибутов определено отношение порядка, для единичных атрибутов определены операторы больше и меньше. Полная таблица операторов:
название | обозначение | количество аргументов | описание |
---|---|---|---|
строго меньше | < |
1 | фильтрует элементы с меньшими значениями атрибута, чем операнд в правой части |
строго больше | > |
1 | фильтрует элементы с большими значениями атрибута, чем операнд в правой части |
равенство | = |
1 или больше | фильтрует элементы со значениями атрибута, равными одному из перечисленных в операнде в правой части |
Оператор равенства для единичных атрибутов позволяет сокращать запись для огранизации множественных выборок, указывая имя атрибута один раз (ср. с оператором IN
в SQL)
Для множественных атрибутов операции равносильны работе со множествами, при этом правый операнд трактуется как множество, состоящее из перечисленных через запятую элементов.
При этом вводится дополнительное отношение порядка «строго меньше» для множеств, содержащих упорядоченные элементы (лексикографический). Множество A
считается «строго меньшим» множества B
, если после сортировки элементов множеств A
и B
, существует такой индекс n
, что выполняется:
i
, (i < n) => (A[i] = B[i])
,A
меньше n
, но количество элементов B
не меньше n
,A[n]
и B[n]
существуют и A[n] < B[n]
.название | обозначение | количество аргументов | описание |
---|---|---|---|
строго меньше | < | 1 или больше | фильтрует элементы, атрибут которых «строго меньше» множества значений из оператора в правой части |
строго больше | > | 1 или больше | фильтрует элементы, атрибут которых «строго больше» множества значений из оператора в правой части |
равенство | = | 1 или больше | фильтрует элементы, атрибут которых равен множеству значений из операнда в правой части |
является подмножеством | << | 1 или больше | фильтрует элементы, атрибут которых включает в себя все значения из операнда в правой части |
является надмножеством | >> | 1 или больше | фильтрует элементы, атрибут которых является подмножеством множества значений из операнда в правой части |
Например, имеется следующий набор элементов:
{ id: 'a', class_name: ['1'] },
{ id: 'b', class_name: ['1', '2'] },
{ id: 'c', class_name: ['1', '2', '3'] },
{ id: 'd', class_name: ['2', '3'] }
фильтр | список идентификаторов элементов после применения фильтра |
---|---|
class_name>1,2 |
[ 'b', 'c' ] |
class_name<1,2 |
[ 'a', 'b' ] |
class_name=1,2 |
[ 'b' ] |
class_name>>1,2 |
[ 'c', 'd' ] |
class_name>>2,3 |
[ ] |
Самым простым фильтром является выборка элементов, содержащих заполненным необязательный атрибут. В таком случае в качестве фильтра стоит использовать строковое имя атрибута или его числовой код в протоколе Google Protocol Buffers.
Так, фильтр id
выберет все элементы. А фильтр class_name
— только элементы, содержащие атрибуты не только базового класса.
Чтобы выбрать элементы, в которых атрибут не только задан, но и имеет определенное значение, необходимо указать имя (строковое или числовое) атрибута, операцию и значения.
Например,
created_by=app_1
выберет элементы, созданные приложением app_1
created_by=app_1,app_2
выберет элементы, созданные приложением app_1
или приложением app_2
. Атрибут created_by
является единичным, поэтому символ ,
интерпретируется как операция «ИЛИ»class_name=action
выберет элементы с классом action
(и только с ним)class_name=action,catalogue_item
выберет элементы с классами action
и catalogue_item
(и только с ними). Атрибут class_name
является множественным, поэтому символ ,
интерпретируется как операция «И»class_name>action,catalogue_item
выберет элементы, у которых имеются классы action
и catalogue_item
(но могут быть заданы и другие классы)Для того, чтобы выбрать элементы для которых нужное условие является ложным, необходимо перед условием поставить символ !
:
!class_name
выберет только элементы базового класса!created_by=app_1,app_2
выберет элементы, созданные не в приложении app_1
и не в приложении app_2
Для построения более сложных конструкций используются префиксные операции «И» и «ИЛИ», в которых операнды отделяются друг от друга символом ;
. Стоит обратить внимание, что для корректной обработки фильтра список операндов должен также завершаться символом ;
.
Например, фильтр created_by=app_1,app_2
эквивалентен фильтру |created_by=app_1;created_by=app_2;
.
Напоследок рассмотрим сложный фильтр: &!created_by=app_1,app_2;class_name=cl_1,cl_2;|id=1;mtime>10;;
. Выберет элементы, для которых выполняются:
app_1
или app_2
cl_1
+cl_2
и ничего большеid
равен 1
mtime
больше 10
Аналогичное высказывание на ECMAScript выглядело бы так:
!( created_by === "app_1" || created_by === "app_2" ) &&
( class_name === [ "cl_1", "cl_2"] ) &&
( id === "1" || mtime > "10" )
Filter := Equation
Filter := "!" Filter
Filter := "&" Filter ";" [ ... Filter ";" ]
Filter := "|" Filter ";" [ ... Filter ";" ]
Equation := attribute
Equation := attribute "=" multi_value
Equation := attribute "<" multi_value
Equation := attribute ">" multi_value
Equation := attribute "<<" multi_value
Equation := attribute ">>" multi_value
multi_value := value [ ... "," value ]
attribute := экранированная_строка
value := экранированная_строка
Атрибуты и значения атрибутов могут содержать символы, которые в языке фильтра несут особую смысловую нагрузку, — такие символы необходимо экранировать при помощи символа обратного слэша (\
):
Cимвол | Замена |
---|---|
\ |
\\ |
! |
\! |
& |
\& |
| |
\| |
; |
\; |
= |
\= |
< |
\< |
> |
\> |
, |
\, |
При выдаче элементов важной частью является порядок, в котором возвращаются элементы. Порядок сортировки определяется пользователем указанием последовательности имен атрибутов через запятую, предваряя символом -
при необходимости сортировки в убывающем порядке.
Если в именах атрибутов встречаются символы -
или ,
, они должны быть экранированы с помощью символа обратного слэша: \-
и \,
, соответственно.
Для множественных атрибутов сортировка осуществляется c помощью операций «строго больше» и «строго меньше».
Авторизация доступа для приложений состоит из
created_by
и autogenerated_id
, доступных всем приложениям только для чтения)Наличие доступа до элемента автоматически влечет наследование авторизации доступа приложения для всех его дочерних элементов.
Создание или изменение атрибутов элементов может быть связано с использованием определенных ресурсов, количество и размер которых может быть ограничен. Ограничение описывает максимальный уровень использования ресурсов.
Ограничения накладывается на дочерние элементы, список ограничений может быть получен при помощи метода quotas
.
Полученная клиентом информация об ограничениях предназначена только для интерпретации ошибок или вывода ознакомительной информации для пользователя.
Для ограничений можно провести аналогию с хранением данных в файловой системе. Допустим, в файловой системе создан отдельный логический раздел D, который ограничен объемом хранения данных в 10Гб. Пользователь может заполнить все свободное место на логическом разделе D, но не сможет превысить ограничение, несмотря на то, что логический раздел D представляет только часть физического диска, суммарный объем которого может быть значительно больше 10Гб.
При объединении учетных записей необходимо также произвести слияние элементов пользовательских данных. Для слияния элементов используется следующий алгоритм:
new_name
;new_name
;new_name
в качестве идентификатора нового элемента.new_name
;new_name
;new_name
в качестве идентификатора нового элемента;Пример реализации:
function merge_elements(dst, src, resolve_conflicts_in_favor_of_dst) {
merge_attributes(dst.attributes, src.attributes, resolve_conflicts_in_favor_of_dst);
for (child in src.children) {
var new_name;
if (!(child.id in dst)) {
dst[child.id] = child;
} else {
if (child.autogenerated_id) {
new_name = generate_child_id(dst);
dst[new_name] = child;
dst[new_name].id = new_name;
} elif (dst[child.name].autogenerated_id) {
new_name = generate_child_id(dst);
dst[new_name] = dst[child.id];
dst[new_name].id = new_name;
dst[child.id] = child;
} else {
merge_elements(dst[child.id], child, resolve_conflicts_in_favor_of_dst);
}
}
}
}
При слиянии атрибутов элемента в результате всегда получается корректное множество атрибутов, в котором заполненность обязательных атрибутов полностью соответствует описанию результирующего списка классов элемента.
Поэтому слияние множества атрибутов равносильно слиянию значений атрибутов источника в элемент–получатель.
protobuf_numbered_tag
отсутствует в получателе, то сохранить его в получателе без измененийПример реализации:
merge_attributes(dst, src, resolve_conflicts_in_favor_of_dst) {
for (protobuf_numbered_tag in src) {
if (!(protobuf_numbered_tag in dst)) {
dst[protobuf_numbered_tag] = src[protobuf_numbered_tag];
} else {
if (AttributeDescription[protobuf_numbered_tag].multivalue) {
dst[protobuf_numbered_tag] = merge_values(
dst[protobuf_numbered_tag],
src[protobuf_numbered_tag]
);
} else {
if (resolve_conflicts_in_favor_of_dst) {
dst[protobuf_numbered_tag] = src[protobuf_numbered_tag];
}
}
}
}
}
Для множественных атрибутов одно и то же значение может храниться несколько раз. При этом в результате слияния количество каждого уникального значения возрасти не может.
Так, при слиянии массива значений [1, 2, 2, 3, 3, 3]
с массивом [1, 1, 1, 2, 2, 3]
результат: [1, 1, 1, 2, 2, 3, 3, 3]
.
Реализация может иметь следующий алгоритм:
src
, dst
)src
и dst
, s
и d
, соответственноsrc[s]
и dst[d]
равны, сохраняем это значение в результативном массиве и увеличиваем значения обоих индексов, s
и d
Пример реализации:
function merge_values(dst, src) {
result = [];
dst.sort();
src.sort();
for (var d = 0, s = 0; d < dst.length && s < src.length; ) {
if (dst[d] === src[s]) {
result.push(dst[d]);
s++;
d++;
} else if (dst[d] > src[s]) {
result.push(src[s]);
s++;
} else { // dst[d] < src[s]
result.push(dst[d]);
d++;
}
}
return result.concat(dst.slice(d), src.slice(s));
}
API работает по протоколу HTTPS (передаваемые данные должны шифроваться), корень доступа до API получается приложением из Регистратуры. Запросы к API составляются следующим образом:
https://<path_to_api>/<path_to_element>?method=<method>&format=<format>&[extra_data]
Где:
path_to_api
— путь до API, полученный в Регистратуреpath_to_elem
— путь до элемента, над которым производится действиеmethod
— метод, который производится над элементомformat
— формат упаковки данныхextra_data
— дополнительные параметры методовФормат упаковки параметров в теле ответа (или в теле запроса) может быть одним из:
json
— JSON;protobuf
— Google Protocol Buffers.Значения всех параметров перед передачей серверу необходимо кодировать для предотвращения неоднозначной интерпретации так, как это рекомендуется в RFC3986.
Некоторые запросы, такие как вставка элементов и изменение атрибутов элементов, могут потребовать передачи большого количества параметров, в таком случае они передаются в теле запроса методом POST. Возможны также «облегченные» варианты, когда параметров не очень много, они могут быть переданы в строке запроса. Способ кодирования параметров в таком случае обычно принимается как атрибут=значение
, в отдельных случаях, когда данный способ кодирования не подходит для элементов класса, он должен быть описан вместе с описанием класса.
Для аутентификации пользователя клиент должен передать полученный ранее токен доступа, выданный Auth API контрагента, по схеме аутентификации в соответствии с типом токена, например, «Bearer».
Для авторизации по типу токена «Bearer» рекомендуется использовать HTTP заголовок Authorization
, пример:
Authorization: Bearer 18dasd81230dah12032
Для каждого метода API предусмотрены стандартные коды ответов (RFC2616). При этом, если это была групповая операция, то существует код ответа для групповой операции вцелом, а также коды ответов для каждой элементарной операции. Ниже приведены стандартные коды ответов:
200
— успешное завершение операции400
— ошибка декодирования параметров метода401
— требуется аутентификация:
403
— доступ запрещен:
404
— элемент или атрибут не найден409
— ошибка схемы данных. Возможные причины:
В случае ошибки при выполнении запроса необходимо возвращать пустое тело ответа, а для кодов 401
, 403
должен быть передан HTTP заголовок WWW-Authenticate
с указанием ожидаемой схемы аутентификации и дополнительнной информации (если применимо). Например, для схемы «Bearer» может быть указан дополнительный атрибут error
со значением:
invalid_token
— передан некорректный, просроченный или отозванный токен доступа (код 401
);insufficient_scope
— запрос требует более высоких привилегий, чем те, которыми обладает токен доступа (код 403
).Дополнительные параметры (передаются в строке запроса):
параметр | по умолчанию | смысл |
---|---|---|
filter |
отсутствует | фильтр элементов |
order |
отсутствует | порядок возвращаемых элементов |
quantity |
отсутствует | максимальное количество возвращаемых элементов |
skip |
0 |
количество элементов, которые необходимо пропустить при выдаче |
Формат ответа: сообщение ElementsList
.
Также в заголовках ответа должно присутствовать поле X-Ordered-By
с описанием сортировки, использованной при выдаче элементов. Если порядок возвращаемых элементов не задан, сервер должен поддерживать порядок при постраничной выдаче элементов, например, с использованием внутренних идентификаторов.
За сервером остается право уменьшить количество возвращаемых элементов (рекомендуемое ограничение — 100 элементов).
Клиент может передать желаемое количество элементов в параметре quantity
, однако за сервером остается право уменьшить данное значение на своей стороне.
Дополнительные параметры передаются в теле запроса методом POST. Формат запроса — сообщение ModifyRequests
, кодируется форматом, указанным в параметре запроса.
Параметр operation
отвечает за тип производимых изменений и может принимать следующие значения:
0
— add — добавление значений для множественных атрибутов;1
— delete — удаление переданных значений атрибута;2
— replace — замена всех значений атрибута переданными.Формат ответа: сообщение ActionResults
.
В теле ответа содержатся результаты операций (сгруппированные по элементам) в том же порядке, в котором они были запрошены. В случае неуспешного запроса к элементу не применяется ни одна из операций, участвующих в нем.
Изменение элемента с несуществующим (или не указанным) идентификатором фактически означает запрос на его создание, идентификатор в таком случае создается сервером. При этом, последний должен сохранять признак самостоятельной генерации идентификатора элемента (выставлять атрибут id_autogenerated
в значение true
). В дальнейшем данный атрибут необходим для эффективной работы алгоритма объединения данных пользователей.
Удаление атрибутов элемента производится по значению, при этом отсутствие указанного значения атрибута молча игнорируется (считается, что действие успешно произведено). При этом, если множественный атрибута имеет несколько одинаковых значений, удаляется лишь столько из них, сколько было указано в запросе.
Например, если для целочисленного множественного атрибута foo
, имеющего значения [0, 1, 1, 1, 2, 2, 3]
, поступил запрос на удаление значений [1, 1, 2, 2, 3, 3, 4, 4]
, то в результате операции значение атрибута станет равным [0, 1]
.
Запросы на изменения производятся поэлементно и для каждого элемента должны быть произведены сервером либо все, либо ни один. При этом после всех произведенных операций:
Если хотя бы одно из данных условий не выполняется, изменения атрибутов элемента не производится, а в ответ клиенту отправляется код ошибки 409
для операции изменения данного элемента.
Дополнительные коды ответов:
201
— элемент создан;489
— превышено ограничение по использованию ресурсов.Дополнительные параметры:
параметр | по умолчанию | смысл |
---|---|---|
filter |
отсутствует | фильтр элементов |
id |
отсутствует | идентификаторы удаляемых дочерних элементов (устарело с версии 1.13) |
При удалении элемента также удаляются все его дочерние элементы.
К значению параметра id
данного метода применяются те же правила, что и к обычному Equation
: в идентификаторах элементов нужно экранировать символ ,
, а чтобы удалить несколько дочерних элементов, необходимо перечислить их через запятую. Все значение параметра id
необходимо закодировать стандартным алгоритмом кодирования значений элементов URI.
Параметры id
и filter
являются взаимоисключающими, если будут указаны оба параметра, то сервер проигнорирует параметр id
.
Отсутствие заданного значения для параметра id
(либо filter
) должно трактоваться сервером как запрос на удаление всех дочерних элементов.
Если количество удаляемых элементов достаточно велико, допускается передача параметра id
методом POST, кодирование производится таким же способом, как в при использовании метода GET.
Формат ответа: сообщение ActionResults
.
Рекомендации к реализации на сервере:
Данный метод позволяет получить список установленных ограничений. Если ограничения отсутствуют, то метод вернет пустой список. Не допускается наличие нескольких ограничений одного типа.
Каждое ограничение описывает текущий и максимальный уровень потребления ресурсов.
Для указания языка, на котором стоит возвращать описание квот, необходимо в запросе использовать HTTP заголовок Accept-Language
.
Формат ответа: сообщение QuotaList
Данный метод позволяет приложениям получить доступ к описанию классов, зарегистрированных в системе. Элемент, переданный в параметрах, игнорируется.
Дополнительные параметры:
параметр | значение по умолчанию | смысл |
---|---|---|
quantity |
10 |
максимальное количество возвращаемых классов |
skip |
0 |
количество классов, которые необходимо пропустить при выдаче |
Формат ответа: сообщение Classes
.
Классы в выдаче должны быть упорядочены по имени, при этом класс без имени является базовым классом.
message AttributeDescription {
optional string name = 1;
optional AttributeValueType value_type = 2;
optional bool mandatory = 3 [ default = false ];
optional bool multivalue = 4 [ default = false ];
optional int32 protobuf_numbered_tag = 5;
optional bool read_only = 6 [ default = false ];
}
Описание класса сводится к описанию атрибутов, которые принадлежат ему. Описание упаковывается в сообщение AttributeDescription
, в котором:
name
— имя атрибута. Используется для представления атрибута в формате JSONvalue_type
— тип данныхmandatory
— признак обязательностиmultivalue
— признак множественностиprotobuf_numbered_tag
— число, которым кодируются значения атрибута в формате Google Protocol Buffersread_only
— признак того, что атрибут доступен только для чтенияДля упрощения понимания структуры хранения данных, иерархии данных и упаковки атрибутов возможно рассматривать аналогию в виде дерева файлов и каталогов:
id
элемента — имя каталогаПри этом:
find . -mindepth 1 -maxdepth 1 -type d
grep -n . *
echo "value" >> name
import "google/protobuf/descriptor.proto";
package UserDataAPIv1;
extend google.protobuf.FieldOptions {
optional bool mandatory = 50000;
optional bool read_only = 50001;
}
extend google.protobuf.MessageOptions {
optional string class_name = 50000;
}
message Element {
optional string id = 1;
optional bytes attributes = 2;
}
message ElementsList {
repeated Element elements = 1;
optional int32 total_count = 2;
optional int32 items_skipped = 3 [default = 0];
}
message ModifyRequest {
message Change {
enum Operation {
ADD = 0;
DELETE = 1;
REPLACE = 2;
}
optional Operation operation = 1;
optional bytes attributes = 2;
}
optional string id = 1;
repeated Change changes = 2;
}
message ModifyRequests {
repeated ModifyRequest modify_requests = 1;
}
message ActionResult {
optional string id = 1;
optional int32 code = 2;
optional string message = 3;
}
message ActionResults {
repeated ActionResult results = 1;
}
enum AttributeValueType {
BOOLEAN = 0;
INTEGER = 1;
FLOAT = 2;
STRING = 3;
}
message AttributeDescription {
optional string name = 1;
optional AttributeValueType value_type = 2;
optional bool mandatory = 3 [ default = false ];
optional bool multivalue = 4 [ default = false ];
optional int32 protobuf_numbered_tag = 5;
optional bool read_only = 6 [ default = false ];
}
message Class {
optional string name = 1;
repeated AttributeDescription attributes = 2;
}
message Classes {
repeated Class classes = 1;
optional int32 total_count = 2;
optional int32 items_skipped = 3 [default = 0];
}
Замечания:
Element
в формат JSON параметр attributes
превращается в отдельный объект, описывающий атрибуты.Element
в формат Protocol Buffers параметр attributes
превращается в отдельное сообщение, содержащее атрибуты.message QuotaUnit {
optional int64 quantity = 1;
optional string title = 2;
}
message Quota {
optional int64 level = 1;
optional int64 limit = 2;
optional string title = 3;
repeated QuotaUnit units = 4;
}
message QuotaList {
repeated Quota quotas = 1;
}
Замечания:
level
— текущий уровень использования ресурсов;limit
— максимальный уровень использования ресурсов;title
— локализованное название ограничения;units
— единицы измерения:
QuotaUnit.quantity
— величина, характеризующая единицу измерения;QuotaUnit.title
— локализованное название единицы измерения.С точки зрения Google Protocol Buffers, как формата упаковки данных, все атрибуты упаковываются в одно сообщение, которое расширяется каждым классом по отдельности.
При описании класса атрибут может снабжаться опцией mandatory
, означающей обязательность атрибута для данного класса. Отсутствие или значение false
данной опции означает необязательность атрибута.
Необходимо заметить, что обязательность специально не оформляется в рамках протокола Google Protocol Buffers для поддержания возможности иметь различный набор обязательных атрибутов у различных классов.
Как было описано ранее, в базовом классе определены следующие атрибуты:
class_name
created_by
autogenerated_id
ctime
mtime
Описание в формате JSON:
{
'description': [
{
'name': 'class_name',
'value_type': 3,
'mandatory': false,
'multivalue': true,
'protobuf_numbered_tag': 1
},
{
'name': 'created_by',
'value_type': 3,
'mandatory': true,
'multivalue': false,
'protobuf_numbered_tag': 2,
'read_only': true
},
{
'name': 'autogenerated_id',
'value_type': 0,
'mandatory': true,
'multivalue': false,
'protobuf_numbered_tag': 3,
'read_only': true
},
{
'name': 'ctime',
'value_type': 1,
'mandatory': true,
'multivalue': false,
'protobuf_numbered_tag': 4,
'read_only': true
},
{
'name': 'mtime',
'value_type': 1,
'mandatory': true,
'multivalue': false,
'protobuf_numbered_tag': 5,
'read_only': true
}
]
}
При переводе описания атрибута на язык Google Protocol Buffers производятся следующие действия:
name
становится строковым именем поляvalue_type
становится типом данных поля, соответствие типов:
0
, BOOLEAN
— bool
1
, INTEGER
— int64
2
, FLOAT
— float
3
, STRING
- string
mandatory
и read_only
становятся значениями одноименных опцийrepeated
полями, единичные — optional
protobuf_numbered_tag
говорит само за себяТаким образом описание базового класса в формате Google Protocol Buffers:
message BaseClass {
repeated string class_name = 1 [(mandatory) = false];
optional string created_by = 2 [(mandatory) = true];
optional bool autogenerated_id = 3 [(mandatory) = true, (read_only) = true];
optional int64 ctime = 4 [(mandatory) = true, (read_only) = true];
optional int64 mtime = 5 [(mandatory) = true, (read_only) = true];
}
message DeviceClass {
option (class_name) = "device";
// человеко-читаемое название
optional string title = 100;
// операционная система, под управлением которой работает устройство
optional int64 platform = 101;
// версия операционной системы
optional string platform_version = 102;
// название модели устройства
optional string model_name = 122;
// версия модели(ревизия)
optional string model_version = 123;
}
platform
может принимать следующие значения:
платформа | значение |
---|---|
Apple iOS | 0 |
Apple OS X | 1 |
Google Android | 2 |
Microsoft Windows | 3 |
Blackberry | 4 |
Linux | 5 |
Eltex NV100/101 | 6 |
Пример использования класса
message ApplicationClass {
option (class_name) = "application";
// человеко-читаемое название
optional string title = 103;
// идентификатор устройства, под управлением которого работает приложения
optional string device_id = 104;
// токен для отправки push-уведомлений
optional string push_token = 114;
// версия приложения
optional string version = 120;
}
Пример использования класса
message CatalogueItemClass {
option (class_name) = "catalogue_item";
// идентификатор элемента каталога
optional string catalogue_item_id = 106 [(mandatory) = true];
// идентификатор каталога
optional string catalogue_id = 107;
}
Пример использования класса
message ActionClass {
option (class_name) = "action";
// время события, в UTC
optional int64 action_time = 108 [(mandatory) = true];
// идентификатор приложения, в котором случилось событие
optional string application_id = 109;
}
message TimeLimitedPlaybackClass {
option (class_name) = "time_limited_playback";
// позиция в воспроизводимом элементе, в миллисекундах
optional int64 playback_position = 110 [(mandatory) = true];
// приостановлено ли воспроизведение
optional bool playback_stopped = 111 [(mandatory) = true];
}
message Bookmark {
option (class_name) = "bookmark";
// заголовок закладки
optional string bookmark_title = 112 [(mandatory) = true];
// URL закладки
optional string bookmark_url = 113 [(mandatory) = true];
}
Пример использования класса
message Location {
option (class_name) = "location";
// идентификатор территории из Регистратуры
optional int64 territory_id = 115;
// идентификатор контрагента из Регистратуры
optional int64 contractor_id = 116;
// географические координаты: широта
optional float latitude = 117;
// географические координаты: долгота
optional float longitude = 118;
}
Пример использования класса
enum EventType {
// Событие от редакции
EDITOR_CHOICE = 1;
// Новый рип (для элемента каталога)
NEW_RIP_AVAILABLE = 2;
}
message CatalogueItemSubscription {
option (class_name) = "subscription";
optional int64 event_type = 119;
}
Пример использования класса
message StorageConstraint {
option (class_name) = "storage_constraint";
// Длительность хранения в секундах
optional int64 storage_time = 121;
}
Пример использования класса
message Credential {
option (class_name) = "credential";
// Секретная фраза
optional string secret_phrase = 124;
}
Пример использования класса
message ApplicationReference {
option (class_name) = "application_reference";
// идентификатор приложения
optional string application_id = 125 [(mandatory) = true];
}
Пример использования класса
message Purchase {
option (class_name) = "purchase";
optional string store_id = 126 [(mandatory) = true];
optional bytes purchase_info = 127 [(mandatory) = true];
}
message GooglePlayReceipt {
// идентификатор пакета приложения
optional string package_name = 1;
// идентификатор продукта
optional string product_id = 2;
// токен покупки
optional string token = 3;
}
message AppStoreReceipt {
// идентификатор пакета приложения
optional string package_name = 1;
// информация о покупке, закодированная в base64
optional string receipt_data = 2;
// признак sandbox-окружения
optional bool sandbox = 3;
}
message RobokassaReceipt {
// идентификатор счета
optional string invoice_id = 1;
}
Замечания:
store_id
— идентификатор внешней платежной системы, возможные значения:
google_play
— Google Play;apple_store
— Apple AppStore;robokassa
— Robokassa.purchase_info
— информация о покупке в формате соотвественно сообщению:
GooglePlayReceipt
— для Google Play;AppStoreReceipt
— для Apple AppStore;RobokassaReceipt
— для Robokassa.Пример использования класса
Рекомендованная иерархия элементов (первым указывается id
элемента, во вложенных списках указываются дочерние элементы):
devices
— устройстваapplications
— приложенияhistory
— история
playback
— история воспроизведения
rips
— рипов фильмовchannels
— телевизионных каналовlocations
— история геолокацииtelecasts
— история просмотров выпусков передачfavourites
— избранное
tv
— избранное в телевидении
channels
— телевизионные каналыbookmarks
— закладки
playlists
— списки воспроизведенияsubscriptions
— подписки пользователя
catalogue
— подписки на действия с элементами каталогаcloud
— личный архив пользователя
telecasts
— список выпусков телепередач, хранимых в личном архиве.credentials
— пользовательские секретные данные
parental_control
— PIN–коды родительского контроляpurchases
— данные о покупках пользователяВАЖНО: использование объявленных классов и рекомендуемой иерархии не по назначению может иметь негативные последствия при объединении данных пользователя. Если сценарий использования класса (-ов), не описан в данной документации, то необходимо обратиться к инженеру, сопровождающему документацию.
Хранит устройства пользователя. Может использоваться для организации проталкивающих уведомлений на устройства пользователя.
Дочерними выступают элементы класса device
, дочерние элементы являются терминальными.
В качестве идентификаторов элементов выступают идентификаторы устройств.
Хранит приложения пользователя для указания их, например, в списке истории просмотра фильмов.
Дочерними выступают элементы класса application
, дочерние элементы являются терминальными.
В качестве идентификаторов элементов выступают идентификаторы экземпляра инсталляции программы.
Хранит историю воспроизведения рипов фильмов. Используется для удобства продолжения просмотра.
Дочерними выступают элементы классов action
+time_limited_playback
+catalogue_item
.
В качестве идентификаторов элементов используются идентификаторы рипов (MediaPart::id
в терминах Films API). Уточнения по атрибутам:
catalogue_item_id
— идентификатор карточки афиши (элемента каталога), CatalogueItem::id
из Films APIcatalogue_id
— идентификатор афиши (сервиса фильмов из Registry API)Хранит историю воспроизведения телевизионных каналов.
Дочерними выступают элементы классов action
+catalogue_item
.
Именование элементов можно как делегировать серверу, так и использовать идентификаторы каналов из «Телепрограммы». Уточнения по атрибутам:
catalogue_item_id
— идентификатор канала, Channel::id
из Media Guide APIcatalogue_id
— идентификатор сервиса «Телепрограмма»catalogue_item_id
— название канала, если оно было указано, иначе — номер строки канала в спискеcatalogue_id
— идентификатор сервиса телевиденияХранит историю определения геолокации пользователя.
Дочерними выступают элементы класса location
.
Используется сервером для таргетирования проталкивающих уведомлений по абонентам операторов и территориям. Создание идентификаторов элементов следует производить на стороне сервера.
Хранит историю просмотров выпусков передач. Используется для удобства продолжения просмотра.
Дочерними выступают элементы классов time_limited_playback
+ catalogue_item
.
В качестве идентификаторов элементов используются идентификаторы выпусков передач. Уточнения по атрибутам:
catalogue_item_id
— идентификатор выпуска передачи (элемента каталога)Хранит список избранных телевизионных каналов.
Дочерними выступают элементы класса catalogue_item
.
В качестве идентификаторов элементов следует использовать идентификаторы каналов из сервиса «Телепрограмма». Рекомендуется указывать в качестве каталога:
Если для канала с названием удалось определить идентификатор, то необходимо удалить существующий элемент и добавить новый с определенным идентификатором.
Хранит закладки на пользовательские списки воспроизведения.
Дочерними выступают элементы класса bookmark
.
Создание идентификаторов элементов следует производить на стороне сервера.
Хранит подписки пользователя на события медийного каталога.
Дочерними выступают элементы класса subscription
и, возможно catalogue_item
, если подписка привязана к элементу каталога.
Возможные виды подписок:
subscription
, в котором атрибут event_type
выставлен в значение 1
(EDITOR_CHOICE
).subscription,catalogue_item
, в котором:
event_type
равен 2
(NEW_RIP_AVAILABLE
)catalogue_item_id
равен идентификатору сериалаcatalogue_item_id
сохраняется соответствующий идентификатор выпуска телепередачи.Отказ от подписки осуществляется удалением элемента с описанием подписки.
Хранит список выпусков телепередач из личного архива пользователя.
Дочерними выступают элементы классов catalogue_item
и storage_constraint
.
При добавлении элементов в личных архив допускается не указывать время хранения элементов при помощи атрибута storage_time
. В этом случае сервер автоматически установит значение по умолчанию. Стоит учитывать, что максимальный период хранения может быть ограничен.
В качестве идентификаторов элементов каталога должны выступать идентификаторы выпусков телепередач.
Допускается добавление выпуска телепередачи, который еще не был полностью записан. В этом случае выпуск будет поставлен в очередь на добавление в облачное хранилище, после завершения записи выпуск автоматически будет скопирован в облачное хранилище.
Выпуск телепередачи не будет сохранен в следующих случаях:
Хранит список PIN–кодов родительского контроля.
Дочерними выступают элементы классов credential
и application-reference
(опционально).
Рекомендуется использовать автоматическую генерацию идентификатора элемента.
Класс application-reference
используется для связывания PIN–кода с конкретной установкой приложения. Если связывание не требуется, то атрибуты данного класса и класс не указываются для элемента.
Атрибут secret_phrase
может быть пустым или отсутствовать, с точки зрения родительского контроля данный факт следует интерпретировать как отсутствие ограничений.
В случае наличия нескольких элементов клиент должен:
application_id
, а идентификатор установки соответствует идентификатору текущей установки.application_id
.Отсутствие элементов по данному пути означает, что PIN–код родительского контроля не был получен ранее.
Рекомендуется хранить не более одного PIN–кода, привязанного к конкретной установке, т.е. при добавлении нового PIN–кода необходимо удалить старый.
Хранит информацию о покупках, выполненных пользователем во внешних платежных системах.
Дочерними выступают элементы класса purchase
. Необходимо использовать автоматическую генерацию идентификатора элемента.
При добавлении покупки сервер синхронно произведет автоматическую верификацию покупки, в случае негативного результата верификации (некорректная покупка) элемент не будет создан.
Элемент может быть удален автоматически по истечению срока действия покупки, если покупка ограничена сроком действия.
Замечание: если по техническим причинам сервер не может произвести верификацию покупки, то элемент будет создан, а верификация будет произведена позже. При негативном результате последующей верификации элемент будет автоматически удален.
modify
class_name
теперь необязательныйautogenerated_id
и created_by
разрешено видеть пользователямdelete
при отсутствующем параметре id
Element
убрано поле class_name
, описывающее одноименный атрибутbookmark
/bookmarks/playlists
push_token
для класса device
location
/history/locations
subscription
/subscriptions/catalogue
modify
и delete
ctime
и mtime
read_only
mtime
application
убран атрибут client_id
, добавлен version
push_token
перенесен из класса device
в класс application
version
класса device
заменен двумя атрибутами model_name
, model_version
platform_version
для класса device
platform_version
в классе device
quotas
для получения списка ограничений для дочерних элементов;storage_constraint
, описывающий политику хранения элементов;/cloud/telecasts
), сохраняемых в личном архиве пользователя.credential
для хранения секретных фраз;/credentials/parental_control
).list
с использованием атрибутов классов (параметр filter
).list
;quantity
из метода list
, в целях согласования документации и фактической реализации.401
;WWW-Authenticate
в случае ошибок запроса с кодами ответа 401
, 403
.AppStoreReceipt
добавлен признак sandbox–окружения.purchase
.purchase
.quantity
для метода list
list
playback_position
в классе time_limited_playback
теперь указывается в миллисекундахtoken
filter
для метода delete
<api_version>
, т.к. является частью <path_to_api>
<token>
в связи с переходом на авторизацию по схеме Bearermessage
в сообщении ActionResult
ctime
, mtime