UNPKG

umbot

Version:

Мультиплатформенный фреймворк для создания голосовых навыков и чат-ботов с единой бизнес-логикой. Встроенная поддержка ВКонтакте, Telegram, Viber, MAX, Яндекс Алисы, Маруси и Сбера SmartApp. Архитектура на адаптерах позволяет подключать любые другие платф

293 lines (292 loc) 10.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.UsersData = void 0; const Model_1 = require("./db/Model"); const RULES = [ { name: ['userId'], type: 'string', max: 250, }, { name: ['meta', 'data'], type: 'text', }, { name: ['platformName'], type: 'string', }, ]; const ATTRS_LABEL = { userId: 'ID', meta: 'User meta data', data: 'User Data', platform: 'Platform Name', }; /** * Модель для работы с пользовательскими данными. * Предоставляет единый интерфейс для работы с данными пользователей во всех поддерживаемых платформах. * * Основные возможности: * - Сохранение состояния пользователя между сессиями * - Хранение метаданных (например, статистика использования) * - Поддержка как файлового хранилища, так и БД * - Автоматическая сериализация/десериализация данных * * @example * Сохранение прогресса пользователя: * ```ts * class GameController extends BotController { * public async action(intentName: string): Promise<void> { * // Загрузка данных пользователя * const userData = new UsersData(this.appContext); * userData.userId = this.userId; * * // Если есть сохраненные данные - загружаем их * if (await userData.getOne()) { * const progress = userData.data.progress || 0; * this.text = `Ваш текущий прогресс: ${progress}%`; * } else { * // Создаем новые данные * userData.data = { progress: 0 }; * userData.meta = { firstVisit: new Date() }; * await userData.save(); * this.text = 'Добро пожаловать в игру!'; * } * } * } * ``` * * @example * Работа с разными платформами: * ```ts * const userData = new UsersData(appContext); * * // Для Алисы * userData.platform = T_ALISA; * * // Для Telegram * userData.platform = T_TELEGRAM; * ``` */ class UsersData extends Model_1.Model { /** * Название таблицы для хранения данных пользователей. * @readonly */ static TABLE_NAME = 'UsersData'; /** * Создает экземпляр модели пользовательских данных. * Предоставляет унифицированный интерфейс для хранения данных пользователя. * * @example * ```ts * const userData = new UsersData(appContext); * userData.userId = 'user123'; * userData.type = UsersData.T_TELEGRAM; * ``` */ constructor(appContext) { super(appContext); this.state = { userId: null, meta: null, data: null, platform: 'unknown', }; } getId() { return 'userId'; } /** * Уникальный идентификатор пользователя. * Может быть строкой или числом в зависимости от платформы. * @example "123456789" для Telegram, 123456789 для VK */ get userId() { return this.state.userId; } /** * Устанавливает уникальный идентификатор пользователя. * @param userId */ set userId(userId) { this.state.userId = userId; } /** * Метаданные пользователя. * Может содержать любые дополнительные данные о пользователе, такие как: * - Статистика использования * - Временные метки * - Настройки пользователя * - Дополнительная информация * @remarks При сохранении в БД автоматически преобразуется в JSON строку */ get meta() { return this.state.meta; } /** * Устанавливает метаданные пользователя. * @param meta */ set meta(meta) { this.state.meta = meta; } /** * Основные данные пользователя. * Содержит основное состояние пользователя, например: * - Прогресс в игре * - Сохраненные настройки * - История действий * - Другие пользовательские данные * @remarks При сохранении в БД автоматически преобразуется в JSON строку */ get data() { return this.state.data; } /** * Устанавливает основные данные пользователя. * @param data */ set data(data) { this.state.data = data; } /** * Тип платформы пользователя. * Определяет платформу, с которой работает пользователь. */ set platform(platform) { this.state.platform = platform; } /** * Тип платформы пользователя. * Определяет платформу, с которой работает пользователь. */ get platform() { return this.state.platform; } /** * Возвращает название таблицы/файла для хранения данных. * * @return {string} Название таблицы для хранения данных пользователей */ tableName() { return UsersData.TABLE_NAME; } /** * Определяет правила валидации полей модели. * * @return {IModelRules[]} Массив правил валидации */ rules() { return RULES; } /** * Возвращает описания атрибутов модели. * Используется для отображения понятных названий полей. * * @return {IUserDataModelState} Описания атрибутов */ attributeLabels() { return ATTRS_LABEL; } /** * Ищет одну запись в хранилище по текущим параметрам. * * @return {Promise<boolean>} true, если запись найдена * * @example * ```ts * const userData = new UsersData(appContext); * userData.userId = 'user123'; * if (await userData.getOne()) { * console.log('Пользователь найден:', userData.data); * } else { * console.log('Пользователь не найден'); * } * ``` */ async getOne() { const query = await this.selectOne(); if (query && query.status && this._appContext.database.adapter) { this.init(this._appContext.database.adapter.getValue(query)); return true; } return false; } safeStringify(obj) { const seen = new WeakSet(); return JSON.stringify(obj, (_, value) => { if (typeof value === 'object' && value !== null) { if (seen.has(value)) return '[Circular]'; seen.add(value); } return value; }); } /** * Валидирует значения перед сохранением. * Преобразует объекты meta и data в JSON при сохранении в БД. * * @throws {Error} Если данные не прошли валидацию * * @example * ```ts * userData.meta = { lastVisit: new Date() }; * userData.data = { progress: 75 }; * userData.validate(); // meta и data будут преобразованы в JSON * ``` */ validate() { if (this.meta && typeof this.meta !== 'string') { this.meta = this.safeStringify(this.meta); } if (this.data && typeof this.data !== 'string') { this.data = this.safeStringify(this.data); } super.validate(); } /** * Инициализирует модель данными. * Преобразует JSON строки meta и data в объекты при загрузке из БД. * * @param data - Данные для инициализации * @remarks * - При парсинге data, ошибки игнорируются для обеспечения обратной совместимости * - Парсинг происходит только если включено сохранение в БД (appContext.isSaveDb === true) * * @example * ```ts * const userData = new UsersData(appContext); * userData.init({ * userId: 'user123', * meta: '{"lastVisit":"2024-03-20T12:00:00Z"}', * data: '{"progress":75}', * platform: T_TELEGRAM * }); * console.log(userData.meta.lastVisit); // Date object * console.log(userData.data.progress); // 75 * ``` */ init(data) { super.init(data); if (typeof this.meta === 'string') { if (this.meta.startsWith('{') || this.meta.startsWith('[')) { this.meta = JSON.parse(this.meta); } } if (typeof this.data === 'string') { try { this.data = JSON.parse(this.data); } catch (e) { this._appContext?.logError(`UserData:init() Произошла ошибка при обработке данных. Скорей всего данные повреждены.`, { error: e, data: this.data, }); } } } } exports.UsersData = UsersData;