UNPKG

xdl-node

Version:

A library for retrieving audio streams and other data from X Spaces, built on Node.js and TypeScript.

155 lines (154 loc) 6.72 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Twspace = void 0; // twspace.ts const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); class Twspace { /** * Конструктор принимает объект metadata, полученный от API. * @param metadata - объект с данными Space */ constructor(metadata) { // Инициализация полей по умолчанию this.id = ""; this.url = ""; this.title = ""; this.creator_name = ""; this.creator_id = ""; this.creator_screen_name = ""; this.creator_profile_image_url = ""; this.start_date = ""; this.state = ""; this.available_for_replay = ""; this.media_key = ""; if (metadata) { const root = (metadata.data && metadata.data.audioSpace && metadata.data.audioSpace.metadata) || {}; const creatorResults = root.creator_results && root.creator_results.result && root.creator_results.result.legacy; if (creatorResults) { this.creator_name = creatorResults.name; this.creator_screen_name = creatorResults.screen_name; // Убираем подстроку "_normal" из URL аватара this.creator_profile_image_url = creatorResults.profile_image_url_https.replace("_normal", ""); // Для creator_id можно было бы вызвать API.graphql_api.userId, здесь оставляем пустым } this.source = metadata; this.root = root; this.id = root.rest_id; this.url = "https://x.com/i/spaces/" + this.id; this.title = root.title; try { const ts = parseInt(root.started_at) / 1000; const date = new Date(ts * 1000); this.start_date = date.toISOString().split('T')[0]; } catch (err) { const ts = parseInt(root.scheduled_start) / 1000; const date = new Date(ts * 1000); throw new Error(`Space should start at ${date.toISOString()}, try again later`); } this.state = root.state; this.available_for_replay = root.is_space_available_for_replay; this.media_key = root.media_key; } } /** * Функция для "санитаризации" имени файла. * @param value - исходное имя файла. * @returns Допустимое имя файла. */ static sterilizeFn(value) { let ext = path_1.default.extname(value); let name = path_1.default.basename(value, ext); name = name.replace(/\0/g, ""); if (name.startsWith(".")) { name = "_" + name; } // Заменяем запрещённые символы name = name.replace(/[\/\\:*?"<>|]/g, "_").trim(); const invalidFilenames = [ "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9" ]; if (invalidFilenames.includes(name)) { name = "_" + name; } return name + ext; } /** * Формирует имя файла по заданному шаблону. * Пример шаблона: "(%(creator_name)s)%(title)s-%(id)s" * @param formatStr - шаблон имени файла. * @returns Полный путь к файлу. */ format(formatStr) { const actualFormatStr = path_1.default.basename(formatStr); const absDir = path_1.default.dirname(formatStr); // Заменяем подстроки вида %(property)s на значения из объекта let formatted = actualFormatStr.replace(/%\((\w+)\)s/g, (match, p1) => { return this[p1] || ""; }); formatted = Twspace.sterilizeFn(formatted); return path_1.default.join(absDir, formatted); } /** * Создаёт экземпляр Twspace по URL твиттер-спейса. * @param url - URL твиттер-спейса. * @param apiInstance - экземпляр TwitterAPI. * @returns Promise с экземпляром Twspace. */ static async fromSpaceUrl(url, apiInstance) { const regex = /spaces\/(\w+)/; const match = url.match(regex); if (!match) { throw new Error("Input URL is not valid. The URL format should be 'https://x.com/i/spaces/<space_id>'"); } const space_id = match[1]; if (!apiInstance.graphql_api) { throw new Error("GraphQL API is not initialized."); } const metadata = await apiInstance.graphql_api.audioSpaceById(space_id); return new Twspace(metadata); } /** * Создаёт экземпляр Twspace по URL пользователя (ищется текущий эфир). * @param user_url - URL пользователя. * @param apiInstance - экземпляр TwitterAPI. * @returns Promise с экземпляром Twspace. */ static async fromUserAvatar(user_url, apiInstance) { if (!apiInstance.graphql_api || !apiInstance.fleets_api) { throw new Error("APIs are not initialized."); } const user_id = await apiInstance.graphql_api.userIdFromUrl(user_url); const avatarContent = await apiInstance.fleets_api.avatarContent(user_id); let broadcast_id; try { broadcast_id = avatarContent.users[user_id].spaces.live_content.audiospace.broadcast_id; } catch (err) { throw new Error("Broadcast ID is not available. User is probably not live"); } const metadata = await apiInstance.graphql_api.audioSpaceById(broadcast_id); return new Twspace(metadata); } /** * Создаёт экземпляр Twspace из файла с metadata. * @param filePath - путь к файлу. * @returns Экземпляр Twspace. */ static fromFile(filePath) { const data = fs_1.default.readFileSync(filePath, 'utf8'); const metadata = JSON.parse(data); return new Twspace(metadata); } } exports.Twspace = Twspace;