alice-asset-manager v1.2.0
alice-asset-manager
Node.js API для загрузки изображений и звуков в навык Алисы.
Позволяет:
- загружать/удалять изображения и звуки
- в режиме синхронизации загружать только измененные файлы и удалять неиспользуемые файлы с сервера
- просматривать загруженные изображения/звуки на реальном устройстве через встроенный навык
Содержание
Установка
npm i alice-asset-manager --save-devИзображения
new ImageManager()
Создает инстанс менеджера изображений.
Параметры:
/**
* @param {string} token OAuth-токен
* @param {string} skillId идентификатор навыка
*/Как получить token и skillId - описано в документации.
Пример:
const { ImageManager } = require('alice-asset-manager');
const imageManager = new ImageManager({
token: 'TOKEN',
skillId: 'SKILL_ID',
});.getQuota()
Получить данные о занятом месте.
await imageManager.getQuota();
/*
{
total: 104857600,
used: 379850
}
*/.upload()
Загрузить изображение из файла.
Параметры:
/**
* @param {string} filePath путь до файла
* @returns {Promise}
*/Пример:
await imageManager.upload('images/test.jpg');
/*
{
id: '213044/aef2a365f198b4435611',
size: 8596,
createdAt: '2019-12-09T06:05:35.035Z',
url: 'https://avatars.mds.yandex.net/get-dialogs-skill-card/213044/aef2a365f198b4435611/orig'
}
*/.getItems()
Получить список всех изображений на сервере.
await imageManager.getItems();
/*
[
{
id: '213044/aef2a365f198b4435611',
origUrl: null,
size: 8596,
createdAt: '2019-12-09T06:05:35.035Z',
url: 'https://avatars.mds.yandex.net/get-dialogs-skill-card/213044/aef2a365f198b4435611/orig'
}
...
]
*/.getItem()
Получить данные об отдельном изображении.
Параметры:
/**
* @param {string} imageId
* @returns {Promise}
*/Пример:
await imageManager.getItem('213044/aef2a365f198b4435611');
/*
{
id: '213044/aef2a365f198b4435611',
origUrl: null,
size: 8596,
createdAt: '2019-12-09T06:05:35.035Z',
url: 'https://avatars.mds.yandex.net/get-dialogs-skill-card/213044/aef2a365f198b4435611/orig'
}
*/.getUrl()
Получить ссылку на изображение.
Параметры:
/**
* @param {string} imageId
* @returns {string}
*/Пример:
imageManager.getUrl('213044/aef2a365f198b4435611');
/*
'https://avatars.mds.yandex.net/get-dialogs-skill-card/213044/aef2a365f198b4435611/orig'
*/.delete()
Удалить изображение с сервера.
Параметры:
/**
* @param {string} imageId
* @returns {Promise}
*/Пример:
await imageManager.delete('213044/aef2a365f198b4435611');.uploadChanged()
Загрузить новые и измененные изображения на сервер.
Параметры:
/**
* @param {string} pattern путь/паттерн до папки с изображениями
* @param {string} dbFile путь до файла с данными о загрузках
* @param {function} [getLocalId] функция вычисления localId по имени файла
* @param {function} [transform] функция обработки файлов (buffer, filepath) => buffer
* @param {boolean} [dryRun=false] запуск без фактической загрузки файлов
* @returns {Promise}
*/Как это работает:
При каждом вызове uploadChanged() сохраняет результаты загрузки во вспомогательный файл
и при последующих вызовах использует сохраненную информацию, чтобы определить файлы для загрузки.
Чтобы избежать повторной загрузки файла при переименовании,
для каждого файла вычисляется localId - уникальный идентификатор,
который должен сохраняться при переименовании.
По умолчанию localId ищется в квадратных скобках [] в имени файла:
image[foo].png -> fooПример:
В папке images лежат два изображения my_image_1[alice].png и my_image_2[bob].png.
Их localId следующие:
my_image_1[alice].png -> alice
my_image_2[bob].png -> bobЗапускаем первую зарузку - на сервер загрузятся оба файла:
await imageManager.uploadChanged({
pattern: 'images/*.png', // путь/паттерн до папки с изображениями
dbFile: 'images.json', // путь до файла с данными о загрузках (изначально файла нет)
});
/*
uploaded: 'images/my_image_1[alice].png', 'images/my_image_2[bob].png'
skipped: 0
*/В images.json запишется примерно следующее:
{
"ids": {
"alice": "213044/aef2a365f198b4435611",
"bob": "834732/sdg3s44fjh234524j2h4"
},
"meta": {
"alice": {
"file": "images/my_image_1[alice].png",
"url": "https://avatars.mds.yandex.net/get-dialogs-skill-card/213044/aef2a365f198b4435611/orig",
"mtimeMs": 1576249136829.0754
},
"bob": {
"file": "images/my_image_2[bob].png",
"url": "https://avatars.mds.yandex.net/get-dialogs-skill-card/834732/sdg3s44fjh234524j2h4/orig",
"mtimeMs": 1576249136830.0842
}
}
}Файл images.json удобно использовать в коде вашего навыка, вставляя изображения по их localId.
Главный плюс в том, что при изменении изображения и получении нового image_id на сервере,
в коде навыка ничего менять не нужно - новый image_id подтянется по localId автоматически:
const images = require('./images.json').ids;
// ...
response.card.image_id = images.alice;Если повторно вызвать uploadChanged() ничего не меняя, то загрузок не произойдет,
т.к. файлы не изменились и уже загружены на сервер:
await imageManager.uploadChanged({
pattern: 'images/*.png',
dbFile: 'images.json',
});
/*
uploaded: 0
skipped: 'images/my_image_1[alice].png', 'images/my_image_2[bob].png'
*/Если изменить в фоторедакторе один из файлов (например my_image_1[alice].png),
то при вызове uploadChanged() загрузится только этот измененный файл:
await imageManager.uploadChanged({
pattern: 'images/*.png',
dbFile: 'images.json',
});
/*
uploaded: 'images/my_image_1[alice].png'
skipped: 'images/my_image_2[bob].png'
*/Информация в images.json также обновится - туда запишется новый image_id для my_image_1[alice].png.
Использование в коде навыка останется прежним:
const images = require('./images.json').ids;
// ...
response.card.image_id = images.alice;Для обработки загружаемых файлов (например изменения размеров изображений) можно использовать параметр transform.
Вот готовый пример кода для подгона изображений под размер 776х344 с использованием библиотеки Jimp:
await imageManager.uploadChanged({
pattern: 'images/*.png',
dbFile: 'images.json',
transform: async buffer => {
const image = await Jimp.read(buffer);
return image
.normalize()
.background(0xFFFFFFFF)
.contain(776, 344)
.quality(75)
.getBufferAsync(Jimp.AUTO);
}
});.deleteUnused()
Удалить неиспользуемые изображения с сервера.
Параметры:
/**
* @param {string} dbFile путь до файла с данными о загрузках, созданный методом uploadChanged()
* @param {boolean} [dryRun=false] запуск без фактического удаления изображений
* @returns {Promise}
*/Работает только в связке с .uploadChanged().
При частых изменениях файлов и многократных вызовах .uploadChanged()
на сервере накапливаются неиспользуемые изображения.
Их нужно периодически удалять, чтобы освободить место.
Метод .deleteUnused() сравнивает то, что записано в dbFile с тем что лежит на сервере, и удаляет с сервера лишнее.
Пример:
В навыке используются два изображения my_image_1[alice].png и my_image_2[bob].png.
Они были загружены на сервер через .uploadChanged() и информация сохранена в dbFile: 'images.json'.
В новой версии навыка файл my_image_1[alice].png не используется и был удален.
После вызова .uploadChanged() в images.json останется только запись про второй файл images/my_image_2[bob].png:
{
"ids": {
"bob": "834732/sdg3s44fjh234524j2h4"
},
"meta": {
"bob": {
"file": "images/my_image_2[bob].png",
"url": "https://avatars.mds.yandex.net/get-dialogs-skill-card/834732/sdg3s44fjh234524j2h4/orig",
"mtimeMs": 1576249136830.0842
}
}
}Но на сервере все еще лежат два файла.
Это нужно для того, чтобы текущая версия навыка продолжала нормально работать.
Когда новая версия навыка выкатится, запись про my_image_1[alice].png можно удалить с сервера:
await imageManager.deleteUnused({
dbFile: 'images.json',
});
/*
{
deleted: [ '213044/aef2a365f198b4435611' ],
used: [ 'images/my_image_2[bob].png' ]
}
*/Чтобы предварительно посмотреть, какие изображения будут удалены с сервера - можно вызвать метод
с параметром dryRun: true:
await imageManager.deleteUnused({
dbFile: 'images.json',
dryRun: true
});
/*
{
deleted: [ '213044/aef2a365f198b4435611' ],
used: [ 'images/my_image_2[bob].png' ]
}
*/.createViewServer()
Создает HTTP-сервер для просмотра загруженных изображений через навык.
Параметры:
/**
* @param {string} [dbFile] путь до файла с данными о загрузках, созданный методом uploadChanged()
*/Создаваемый HTTP-сервер позволяет быстро посмотреть загруженные изображения на экране смартфона.
Пример:
const server = imageManager.createViewServer();
server.listen(3000);Когда сервер запустился на 3000 порту, можно используя любой прокси-навык
(например alice-dev.vitalets.xyz) проверить все изображения на смартфоне.
Изображения в навыке отсортированы по дате загрузки, поэтому в первую очередь будут показаны недавно измененные файлы.
Чтобы рядом с изображениями дополнительно выводилось имя файла и localId, нужно указать в параметрах dbFile:
const server = imageManager.createViewServer({
dbFile: 'images.json'
});
server.listen(3000);Чтобы сервер автоматически перезапускался при изменениях images.json
можно использовать nodemon:
nodemon ./image-server.js --watch ./images.jsonЗвуки
new SoundManager()
Создает инстанс менеджера звуков.
Параметры:
/**
* @param {string} token OAuth-токен
* @param {string} skillId идентификатор навыка
*/Как получить token и skillId - описано в документации.
Пример:
const { SoundManager } = require('alice-asset-manager');
const soundManager = new SoundManager({
token: 'TOKEN',
skillId: 'SKILL_ID',
});.getQuota()
Получить данные о занятом месте.
await soundManager.getQuota();
/*
{
total: 104857600,
used: 379850
}
*/.upload()
Загрузить звук из файла.
Параметры:
/**
* @param {string} filePath путь до файла
* @returns {Promise}
*/Пример:
await soundManager.upload('images/test.mp3');
/*
{
id: 'c72463ae-01b5-48a1-a7f2-e657e4594166',
skillId: 'SKILL_ID',
size: null,
originalName: 'test.mp3',
createdAt: '2019-12-09T06:13:49.595Z',
isProcessed: false,
error: null,
url: 'https://yastatic.net/s3/dialogs/dialogs-upload/sounds/opus/SKILL_ID/c72463ae-01b5-48a1-a7f2-e657e4594166.opus'
}
*/.getItems()
Получить список всех звуков на сервере.
await soundManager.getItems();
/*
[
{
id: 'c72463ae-01b5-48a1-a7f2-e657e4594166',
skillId: 'SKILL_ID',
size: 24915,
originalName: 'test.mp3',
createdAt: '2019-12-09T06:19:48.317Z',
isProcessed: true,
error: null,
url: 'https://yastatic.net/s3/dialogs/dialogs-upload/sounds/opus/SKILL_ID/c72463ae-01b5-48a1-a7f2-e657e4594166.opus'
}
...
]
*/.getItem()
Получить данные об отдельном звуке на сервере.
Параметры:
/**
* @param {string} soundId
* @returns {Promise}
*/Пример:
await soundManager.getItem('c72463ae-01b5-48a1-a7f2-e657e4594166');
/*
{
id: 'c72463ae-01b5-48a1-a7f2-e657e4594166',
skillId: 'SKILL_ID',
size: 24915,
originalName: 'test.mp3',
createdAt: '2019-12-09T06:19:48.317Z',
isProcessed: true,
error: null,
url: 'https://yastatic.net/s3/dialogs/dialogs-upload/sounds/opus/SKILL_ID/c72463ae-01b5-48a1-a7f2-e657e4594166.opus'
}
*/.getUrl()
Получить ссылку на звук.
Параметры:
/**
* @param {string} soundId
* @returns {string}
*/Пример:
soundManager.getUrl('c72463ae-01b5-48a1-a7f2-e657e4594166');
/*
'https://yastatic.net/s3/dialogs/dialogs-upload/sounds/opus/SKILL_ID/c72463ae-01b5-48a1-a7f2-e657e4594166.opus'
*/.getTts()
Получить tts для вставки звука в ответ навыка.
Параметры:
/**
* @param {string} soundId
* @returns {string}
*/Пример:
soundManager.getTts('c72463ae-01b5-48a1-a7f2-e657e4594166');
/*
'<speaker audio="dialogs-upload/SKILL_ID/c72463ae-01b5-48a1-a7f2-e657e4594166.opus">'
*/.delete()
Удалить звук с сервера.
Параметры:
/**
* @param {string} soundId
* @returns {Promise}
*/Пример:
await soundManager.delete('213044/aef2a365f198b4435611');.uploadChanged()
Загрузить новые и измененные звуки на сервер.
Параметры:
/**
* @param {string} pattern путь/паттерн до папки со звуками
* @param {string} dbFile путь до файла с данными о загрузках
* @param {function} [getLocalId] функция вычисления localId по имени файла
* @param {boolean} [dryRun=false] запуск без зфактической загрузки файлов
* @returns {Promise}
*/Все работает аналогично методу .uploadChanged() для изображений.
.deleteUnused()
Удалить неиспользуемые звуки с сервера.
Параметры:
/**
* @param {string} dbFile путь до файла с данными о загрузках, созданный методом uploadChanged()
* @param {boolean} [dryRun=false] запуск без фактического удаления звуков
* @returns {Promise}
*/Все работает аналогично методу .deleteUnused() для изображений.
.createViewServer()
Создает HTTP-сервер для прослушивания загруженных звуков через навык.
Параметры:
/**
* @param {string} [dbFile] путь до файла с данными о загрузках, созданный методом uploadChanged()
*/Все работает аналогично методу .createViewServer() для изображений.
Лицензия
MIT @ Vitaliy Potapov