PowerShell и ЖЖ: функция «syncitems» и данные от нее, ч.1

Feb 25, 2023 16:55

Ранее в этой серии постов:
...
21. PowerShell: улучшаю преобразование данных от ЖЖ (интерфейс «flat») в хеш-таблицу
22. PowerShell и ЖЖ: простейшее кэширование результата HTTP(S)-запроса
23. PowerShell: таблицы для анализа данных

Окружение: операционная система «Windows 10», программа-оболочка «PowerShell» версии 7.

Чтобы выстроить эффективную работу с ЖЖ («Живым Журналом») из своего веб-клиента, нужно хотя бы примерно представлять, что закладывали авторы программы-сервера ЖЖ в свою программу, как по их мнению должна выглядеть работа веб-клиента и его взаимодействие с ЖЖ.

Насколько я понимаю, в их представлении веб-клиент на компьютере автора журнала (блогера) должен поддерживать свою локальную копию журнала (блога) со всеми постами. То есть существует оригинал блога на сервере ЖЖ и существует локальная копия блога на компьютере блогера, владельца веб-клиента. Ну а поскольку есть две копии журнала, то между ними следует обеспечить синхронизацию (ликвидацию различий между двумя копиями данных).

В предельном случае существует только оригинальный набор данных - журнал на сервере ЖЖ. Тогда синхронизацией можно считать создание локальной копии оригинального набора данных у себя на компьютере, другими словами, создание архива своего ЖЖ.

Для организации такой синхронизации в наборе удалённых функций программы-сервера ЖЖ есть функция «syncitems». В документации даны очень короткие пояснения о том, как работает эта функция. Лично мне этих объяснений было недостаточно, чтобы разобраться в работе этой функции. Поэтому я решил анализировать возвращаемые этой функцией данные и разбираться уже на основании этого анализа и этих данных.

Подготовка вспомогательных функций

Эти две функции были подробно описаны в предыдущих постах. Функция toHashTable используется для преобразования полученной в теле HTTP(S)-ответа многострочной строки с параметрами в хеш-таблицу. Функция getHash используется для получения хеш-суммы заданной строки по указанному алгоритму.

function toHashTable($str) {
$arr = $str -split '\r?\n'
$hash = @{}
$len = if ($arr.Length % 2) { $arr.Length - 1 } else { $arr.Length }
for ($i = 0; $i -lt $len; $i += 2) {
$hash[$arr[$i]] = $arr[$i + 1]
}
return $hash
}

function getHash($str, $alg) {
$stringAsStream = [System.IO.MemoryStream]::new()
$writer = [System.IO.StreamWriter]::new($stringAsStream)
$writer.write($str)
$writer.Flush()
$stringAsStream.Position = 0
(Get-FileHash -InputStream $stringAsStream -Algorithm $alg).Hash.ToLower()
}

Отправка HTTP(S)-запроса на запуск функции «syncitems»

При отправке HTTP(S)-запроса на запуск функции «syncitems» я буду использовать аутентификацию «challenge-response», которая была подробно разобрана в предыдущих постах. Общение с ЖЖ будет происходить по интерфейсу «flat». Как и ранее, я буду получать данные о журнале пользователя vbgtut.

$body = @{
mode = "getchallenge"
}
$Response = Invoke-WebRequest -URI "https://www.livejournal.com/interface/flat" `
-Body $body -Method "POST"
$params = toHashTable($Response.Content)
$hPass = getHash "пароль" "MD5"
$hResp = getHash ($params["challenge"] + $hPass) "MD5"
$body = @{
mode = "syncitems"
user = "vbgtut"
auth_method = "challenge"
auth_challenge = $params["challenge"]
auth_response = $hResp
}
$Response = Invoke-WebRequest -URI "https://www.livejournal.com/interface/flat" `
-Body $body -Method "POST"
$params = toHashTable($Response.Content)
$params["success"]

OK

Отмечу, что я не указал входной параметр «lastsync», в котором для функции «syncitems» следует передавать дату и время проведения последней синхронизации. Без указания этого параметра считается, что мы хотим получить полностью все данные, которые может вернуть функция «syncitems», а не только данные об обновлениях журнала с определенной даты. Насколько я понимаю, если параметр «lastsync» не указан, то считается, что он равен дате начала «эпохи Unix», то есть значению "1970-01-01 00:00:00".

(О значении по умолчанию параметра «lastsync» не сказано в документации от 2008 года, на которую я постоянно ссылаюсь в этих постах. Однако, об этом сказано в некоем документе в формате PDF, который можно найти в интернетах (например). Дата актуальности этого документа - 28.02.2011 г., автор - «SUP Fabrik». Видно, что этот документ написан на базе документации от 2008 года, но в нем есть дополнения.)

Под датой и временем в параметре «lastsync» имеется в виду не дата и время предыдущего запуска функции «syncitems». Функция «syncitems» не предназначена для выполнения самой синхронизации, эта функция возвращает лишь информацию, которую в дальнейшем можно использовать для синхронизации.

Начало анализа полученных данных

PS C:\> ($Response.Content).Length
14441
PS C:\> $params.Count
582
PS C:\> $params["sync_total"]
193
PS C:\> $params["sync_count"]
193

Как видно из блока кода выше, на описанный HTTP(S)-запрос функция «syncitems» вернула многострочную строку длиной в 14 тысяч 441 символ. Функция toHashTable преобразовала эту многострочную строку в хеш-таблицу из 582 параметров. Это значит, что в полученной многострочной строке всего 1164 линии (582 × 2).

Из полученных 582 параметров три являются общими для данной порции данных: «success», «sync_total» и «sync_count». Остальные 579 параметров (582 − 3) описывают записи (по-английски «items») о создании новых постов, внесении изменений в посты, появлении новых комментариев к постам и, возможно, других событий-обновлений журнала (блога).

Каждая запись об обновлении журнала (item) представлена тремя параметрами: «sync_n_item» (тип обновленного объекта и его идентификатор), «sync_n_action» (тип действия: создание или обновление поста или комментария) и «sync_n_time» (момент времени, в который случилось обновление журнала). Число n внутри каждого из названий этих параметров - это номер записи об обновлении журнала в составе этой порции данных. Например, вот первая запись об обновлении журнала в составе этой порции данных:

PS C:\> $params["sync_1_item"]
L-2
PS C:\> $params["sync_1_action"]
update
PS C:\> $params["sync_1_time"]
2010-10-16 16:25:33
Или то же самое в одной строке таблицы (я создам эту таблицу позже):

num item action time
--- ---- ------ ----
1 L-2 update 2010-10-16 16:25:33

Понятно, что если параметров, описывающих записи об обновлении журнала, всего 579 штук, тогда полученных записей всего 193 штуки (579 / 3). Нумерация полученных в каждой порции данных записей начинается с единицы. Общее количество полученных записей (в этой порции данных), как видно из блоков кода выше, есть в параметре «sync_count».

Порции данных

Почему в приведенном выше начале анализа данных я постоянно упоминаю про порции данных? Дело в том, что программа-сервер ЖЖ, насколько я понимаю, спроектирована так, чтобы в ней можно было регулировать нагрузку, дозируя отдаваемые веб-клиентам данные. В случае вышеописанного примера с данными, полученными от функции «syncitems» для журнала пользователя «vbgtut», количество записей об обновлении журнала «vbgtut» относительно маленькое, всего 193 записи. Программе-серверу ЖЖ не слишком затратно выдать по описанному выше HTTP(S)-запросу сразу все эти записи в одной порции данных. Поэтому мы и получили сразу все эти записи.

Однако, в случае журналов с большим количеством постов и обновлений записей об обновлениях может быть слишком много. Программа-сервер ЖЖ может выдавать эти записи не все сразу одной порцией, а несколькими порциями. Например, я сделал подобный вышеописанному HTTP(S)-запрос для своего основного журнала «ilyachalov», в котором на данный момент больше тысячи постов (а обновлений и того больше). В результате я получил следующее:

PS C:\> $params.Count
1503
PS C:\> $params["sync_total"]
2212
PS C:\> $params["sync_count"]
500

Эти числа означают, что на момент получения этих данных программа-сервер ЖЖ может выдавать количество записей об обновлении журнала порциями не более, чем по 500 записей в порции. Параметр «sync_total» показывает, сколько обновлений журнала было с момента, указанного во входном параметре «lastsync» (поскольку мы входной параметр «lastsync» в HTTP(S)-запросе не указывали, параметр «sync_total» показывает число обновлений журнала с момента его создания).

Думаю, теперь должно быть понятно, чем отличаются параметры «sync_total» (число обновлений журнала с момента, указанного во входном параметре «lastsync») и «sync_count» (число записей об обновлениях журнала, полученных в этой порции). В документации описан примерный алгоритм получения всех записей об обновлениях журнала для любого журнала, хоть маленького, хоть большого. Я постараюсь реализовать этот алгоритм в одном из следующих постов.

Продолжение следует.

Инструмент, Образование, Сайтостроение, Программирование, Английский язык, ЖЖ

Previous post Next post
Up