UNPKG

@racla-dev/node-iris

Version:

TypeScript port of Python irispy-client module for KakaoTalk bot development

322 lines 12.1 kB
"use strict"; /** * Core classes for node-iris: Room, User, Avatar, ChatContext, ErrorContext */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ErrorContext = exports.ChatContext = exports.User = exports.Avatar = exports.Room = void 0; const utils_1 = require("@/utils"); const logger_1 = require("@/utils/logger"); const message_1 = require("./message"); class Room { constructor(id, name, api) { this.id = (0, utils_1.toSafeId)(id); this.name = name; this._api = api; } /** * Get ID as string for API compatibility */ getIdAsString() { return (0, utils_1.idToString)(this.id); } /** * Get ID as BigInt for numeric operations */ getIdAsBigInt() { return this.id; } async getType() { if (this._type !== undefined) { return this._type; } try { const results = await this._api.query('SELECT type FROM chat_rooms WHERE id = ?', [this.getIdAsString()]); if (results && results[0]) { this._type = results[0].type; return this._type; } this._type = null; return null; } catch (error) { this._type = null; return null; } } toString() { return `Room(id=${this.getIdAsString()}, name=${this.name})`; } } exports.Room = Room; class Avatar { constructor(id, chatId, api) { this.logger = new logger_1.Logger('Avatar'); this._id = (0, utils_1.toSafeId)(id); this._chatId = (0, utils_1.toSafeId)(chatId); this._api = api; } getIdAsString() { return (0, utils_1.idToString)(this._id); } getChatIdAsString() { return (0, utils_1.idToString)(this._chatId); } getIdAsBigInt() { return this._id; } async getUrl() { if (this._url !== undefined) { return this._url; } try { let results; if (this.getIdAsBigInt() < 10000000000n) { results = await this._api.query('SELECT T2.o_profile_image_url FROM chat_rooms AS T1 JOIN db2.open_profile AS T2 ON T1.link_id = T2.link_id WHERE T1.id = ?', [this.getChatIdAsString()]); this._url = results[0]?.o_profile_image_url || null; } else { results = await this._api.query('SELECT original_profile_image_url, enc FROM db2.open_chat_member WHERE user_id = ?', [this.getIdAsString()]); this._url = results[0]?.original_profile_image_url || null; } return this._url; } catch (error) { this._url = null; return null; } } async getImg() { if (this._img !== undefined) { return this._img; } const url = await this.getUrl(); if (!url) { this._img = null; return null; } try { const axios = require('axios'); const response = await axios.get(url, { responseType: 'arraybuffer', headers: { 'User-Agent': 'Mozilla/5.0 (compatible; node-iris)' }, }); this._img = Buffer.from(response.data); return this._img; } catch (error) { this.logger.error('Failed to load avatar image:', error); this._img = null; return null; } } toString() { return `Avatar(url=${this._url})`; } } exports.Avatar = Avatar; class User { constructor(id, chatId, api, name, botId) { this.id = (0, utils_1.toSafeId)(id); this._chatId = (0, utils_1.toSafeId)(chatId); this._api = api; this._name = name; this._botId = botId ? (0, utils_1.toSafeId)(botId) : undefined; this.avatar = new Avatar(this.id, this._chatId, api); } getIdAsString() { return (0, utils_1.idToString)(this.id); } getChatIdAsString() { return (0, utils_1.idToString)(this._chatId); } getIdAsBigInt() { return this.id; } async getName() { if (this._name !== undefined) { return this._name; } try { let results; if (this.id === this._botId) { results = await this._api.query('SELECT T2.nickname FROM chat_rooms AS T1 JOIN db2.open_profile AS T2 ON T1.link_id = T2.link_id WHERE T1.id = ?', [this._chatId]); this._name = results[0]?.nickname || null; } else if (BigInt(this.id) < 10000000000n) { results = await this._api.query('SELECT name, enc FROM db2.friends WHERE id = ?', [this.id]); this._name = results[0]?.name || null; } else { results = await this._api.query('SELECT nickname, enc FROM db2.open_chat_member WHERE user_id = ?', [this.id]); this._name = results[0]?.nickname || null; } return this._name; } catch (error) { this._name = null; return null; } } async getType() { if (this._type !== undefined) { return this._type; } try { let results; if (this.id === this._botId) { results = await this._api.query('SELECT T2.link_member_type FROM chat_rooms AS T1 INNER JOIN open_profile AS T2 ON T1.link_id = T2.link_id WHERE T1.id = ?', [this._chatId]); } else { results = await this._api.query('SELECT link_member_type FROM db2.open_chat_member WHERE user_id = ?', [this.id]); } const memberType = parseInt(results[0]?.link_member_type || '0'); switch (memberType) { case 1: this._type = 'HOST'; break; case 2: this._type = 'NORMAL'; break; case 4: this._type = 'MANAGER'; break; case 8: this._type = 'BOT'; break; default: this._type = 'UNKNOWN'; } return this._type; } catch (error) { this._type = 'REAL_PROFILE'; return this._type; } } toString() { return `User(name=${this._name})`; } } exports.User = User; class ChatContext { constructor(room, sender, message, raw, api) { this.logger = new logger_1.Logger('ChatContext'); this.room = room; this.sender = sender; this.message = message; this.raw = raw; this.api = api; } async reply(message, roomId) { const targetRoomId = roomId || this.room.id; const roomIdString = typeof targetRoomId === 'string' || typeof targetRoomId === 'number' ? (0, utils_1.idToString)(targetRoomId) : this.room.getIdAsString(); await this.api.reply(roomIdString, message); } async replyMedia(files, roomId) { const targetRoomId = roomId || this.room.id; const roomIdString = typeof targetRoomId === 'string' || typeof targetRoomId === 'number' ? (0, utils_1.idToString)(targetRoomId) : this.room.getIdAsString(); await this.api.replyMedia(roomIdString, files); } /** * Reply with images from URLs - automatically downloads and converts to base64 * @param imageUrls - Array of image URLs to download and send * @param roomId - Optional room ID (defaults to current room) */ async replyImageUrls(imageUrls, roomId) { const targetRoomId = roomId || this.room.id; // Temporary cast until interface is updated await this.api.replyImageUrls(targetRoomId, imageUrls); } /** * Reply with a single image from URL * @param imageUrl - Image URL to download and send * @param roomId - Optional room ID (defaults to current room) */ async replyImageUrl(imageUrl, roomId) { const targetRoomId = roomId || this.room.id; // Temporary cast until interface is updated await this.api.replyImageUrl(targetRoomId, imageUrl); } async getSource() { // Check if this message is a reply const replyData = this.raw.attachment?.reply; if (!replyData) { return null; } try { // Get the source message from the API const sourceMessage = await this.api.query('SELECT * FROM messages WHERE id = ? AND chat_id = ?', [replyData.src_logId, this.room.id]); if (!sourceMessage || sourceMessage.length === 0) { return null; } // Create ChatContext for source message const source = sourceMessage[0]; const sourceRoom = new Room(this.room.id, this.room.name, this.api); const sourceUser = new User(source.user_id, // parseInt 제거 this.room.id, this.api, source.sender_name); const sourceMsg = new message_1.Message(source.id, // parseInt 제거 parseInt(source.type), source.message, source.attachment, (0, utils_1.safeJsonParseWithReviver)(source.v || '{}')); return new ChatContext(sourceRoom, sourceUser, sourceMsg, source, this.api); } catch (error) { this.logger.error('Failed to get source message:', error); return null; } } async getNextChat(n = 1) { try { const nextMessages = await this.api.query('SELECT * FROM messages WHERE chat_id = ? AND id > ? ORDER BY id ASC LIMIT ?', [this.room.id, this.message.id, n]); if (!nextMessages || nextMessages.length === 0) { return null; } const next = nextMessages[n - 1] || nextMessages[nextMessages.length - 1]; const nextRoom = new Room(this.room.id, this.room.name, this.api); const nextUser = new User(next.user_id, // parseInt 제거 this.room.id, this.api, next.sender_name); const nextMsg = new message_1.Message(next.id, // parseInt 제거 parseInt(next.type), next.message, next.attachment, (0, utils_1.safeJsonParseWithReviver)(next.v || '{}')); return new ChatContext(nextRoom, nextUser, nextMsg, next, this.api); } catch (error) { this.logger.error('Failed to get next chat:', error); return null; } } async getPreviousChat(n = 1) { try { const prevMessages = await this.api.query('SELECT * FROM messages WHERE chat_id = ? AND id < ? ORDER BY id DESC LIMIT ?', [this.room.id, this.message.id, n]); if (!prevMessages || prevMessages.length === 0) { return null; } const prev = prevMessages[n - 1] || prevMessages[prevMessages.length - 1]; const prevRoom = new Room(this.room.id, this.room.name, this.api); const prevUser = new User(prev.user_id, // parseInt 제거 this.room.id, this.api, prev.sender_name); const prevMsg = new message_1.Message(prev.id, // parseInt 제거 parseInt(prev.type), prev.message, prev.attachment, (0, utils_1.safeJsonParseWithReviver)(prev.v || '{}')); return new ChatContext(prevRoom, prevUser, prevMsg, prev, this.api); } catch (error) { this.logger.error('Failed to get previous chat:', error); return null; } } } exports.ChatContext = ChatContext; class ErrorContext { constructor(event, func, exception, args) { this.event = event; this.func = func; this.exception = exception; this.args = args; } toString() { return `ErrorContext(event=${this.event}, error=${this.exception.message})`; } } exports.ErrorContext = ErrorContext; //# sourceMappingURL=classes.js.map