@racla-dev/node-iris
Version:
TypeScript port of Python irispy-client module for KakaoTalk bot development
279 lines • 11.4 kB
JavaScript
;
/**
* Utility functions for type checking and validation
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.isStringMessage = isStringMessage;
exports.isFeedMessage = isFeedMessage;
exports.isInviteUserFeed = isInviteUserFeed;
exports.isLeaveUserFeed = isLeaveUserFeed;
exports.isOpenChatJoinUserFeed = isOpenChatJoinUserFeed;
exports.isOpenChatKickedUserFeed = isOpenChatKickedUserFeed;
exports.isOpenChatPromoteManagerFeed = isOpenChatPromoteManagerFeed;
exports.isOpenChatDemoteManagerFeed = isOpenChatDemoteManagerFeed;
exports.isDeleteMessageFeed = isDeleteMessageFeed;
exports.isOpenChatHandOverHostFeed = isOpenChatHandOverHostFeed;
exports.isOpenChatHideMessageFeed = isOpenChatHideMessageFeed;
exports.isMentionListAttachment = isMentionListAttachment;
exports.isPhotoAttachment = isPhotoAttachment;
exports.isMultiPhotoAttachment = isMultiPhotoAttachment;
exports.isVideoAttachment = isVideoAttachment;
exports.isAudioAttachment = isAudioAttachment;
exports.isReplyAttachment = isReplyAttachment;
exports.isFileAttachment = isFileAttachment;
exports.isNewMultiPhotoAttachment = isNewMultiPhotoAttachment;
exports.hasPathProperty = hasPathProperty;
exports.getFeedLogMessage = getFeedLogMessage;
exports.safeParseMessage = safeParseMessage;
const utils_1 = require("@/utils");
const logger_1 = require("@/utils/logger");
const feed_types_1 = require("./feed-types");
// 타입 체크 유틸리티 함수들
function isStringMessage(msg) {
return typeof msg === 'string';
}
function isFeedMessage(msg) {
return typeof msg === 'object' && msg !== null && 'feedType' in msg;
}
function isInviteUserFeed(msg) {
return isFeedMessage(msg) && Number(msg.feedType) === 1;
}
function isLeaveUserFeed(msg) {
return isFeedMessage(msg) && Number(msg.feedType) === 2;
}
function isOpenChatJoinUserFeed(msg) {
return isFeedMessage(msg) && Number(msg.feedType) === 4;
}
function isOpenChatKickedUserFeed(msg) {
return isFeedMessage(msg) && Number(msg.feedType) === 6;
}
function isOpenChatPromoteManagerFeed(msg) {
return isFeedMessage(msg) && Number(msg.feedType) === 11;
}
function isOpenChatDemoteManagerFeed(msg) {
return isFeedMessage(msg) && Number(msg.feedType) === 12;
}
function isDeleteMessageFeed(msg) {
return isFeedMessage(msg) && Number(msg.feedType) === 14;
}
function isOpenChatHandOverHostFeed(msg) {
return isFeedMessage(msg) && Number(msg.feedType) === 15;
}
function isOpenChatHideMessageFeed(msg) {
return isFeedMessage(msg) && Number(msg.feedType) === 26;
}
// 첨부파일 타입 체크 유틸리티 함수들
function isMentionListAttachment(attachment) {
return (attachment !== null &&
typeof attachment === 'object' &&
'mentions' in attachment);
}
function isPhotoAttachment(attachment) {
return (attachment !== null &&
typeof attachment === 'object' &&
// 기본 형식 (url, w, h 필수)
(('url' in attachment && 'w' in attachment && 'h' in attachment) ||
// 레거시 호환 형식 (imageUrl만 있는 경우)
'imageUrl' in attachment));
}
function isMultiPhotoAttachment(attachment) {
return (attachment !== null &&
typeof attachment === 'object' &&
'imageUrls' in attachment);
}
function isVideoAttachment(attachment) {
return (attachment !== null &&
typeof attachment === 'object' &&
'url' in attachment &&
'd' in attachment);
}
function isAudioAttachment(attachment) {
return (attachment !== null &&
typeof attachment === 'object' &&
'url' in attachment &&
'd' in attachment &&
's' in attachment);
}
function isReplyAttachment(attachment) {
return (attachment !== null &&
typeof attachment === 'object' &&
'src_logId' in attachment);
}
function isFileAttachment(attachment) {
return (attachment !== null &&
typeof attachment === 'object' &&
'name' in attachment &&
'url' in attachment &&
'size' in attachment);
}
function isNewMultiPhotoAttachment(attachment) {
return (attachment !== null && typeof attachment === 'object' && 'C' in attachment);
}
// 첨부파일에 path 속성이 있는지 확인하는 함수
function hasPathProperty(attachment) {
return (attachment !== null &&
typeof attachment === 'object' &&
'path' in attachment);
}
// 피드 타입별 로그 메시지 생성 함수
function getFeedLogMessage(msg) {
if (isStringMessage(msg)) {
return msg;
}
// 타입 가드를 통해 feedType이 있는 객체임을 확인
if (!isFeedMessage(msg)) {
return '[Unknown FeedType]';
}
try {
const feedType = msg.feedType;
switch (feedType) {
case 1: // 사용자 초대
if (isInviteUserFeed(msg)) {
const memberNames = msg.members.map((m) => m.nickName).join(', ');
return `${msg.inviter.nickName}님이 ${memberNames}님을 초대했습니다. ()`;
}
break;
case 2: // 사용자 나감
if (isLeaveUserFeed(msg)) {
return msg.kicked
? `${msg.member.nickName}님이 내보내기되었습니다. (KICKED)`
: `${msg.member.nickName}님이 나가셨습니다. ()`;
}
break;
case 4: // 오픈채팅 입장
if (isOpenChatJoinUserFeed(msg)) {
const joinNames = msg.members.map((m) => m.nickName).join(', ');
return `${joinNames}님이 입장하셨습니다.`;
}
break;
case 6: // 오픈채팅 강퇴
if (isOpenChatKickedUserFeed(msg)) {
return `${msg.member.nickName}님이 내보내기되었습니다. (KICKED)`;
}
break;
case 11: // 매니저 임명
if (isOpenChatPromoteManagerFeed(msg)) {
return `${msg.member.nickName}님이 부방장(MANAGER)으로 임명되었습니다. (SYNCMEMT)`;
}
break;
case 12: // 매니저 해제
if (isOpenChatDemoteManagerFeed(msg)) {
return `${msg.member.nickName}님의 부방장(MANAGER) 권한이 해제되었습니다. (SYNCMEMT)`;
}
break;
case 14: // 메시지 삭제
if (isDeleteMessageFeed(msg)) {
return '메시지를 삭제되었습니다. (SYNCDLMSG)';
}
break;
case 15: // 호스트 이전
if (isOpenChatHandOverHostFeed(msg)) {
return `방장(HOST)이/가 ${msg.prevHost.nickName}님에서 ${msg.newHost.nickName}님으로 변경되었습니다. ()`;
}
break;
case 26: // 메시지 숨김
if (isOpenChatHideMessageFeed(msg)) {
return '관리자가 메시지를 숨겨졌습니다. (SYNCREWR)';
}
break;
default:
return `[Unknown FeedType: ${feedType}]`;
}
return `[Feed Message Processing Error: ${feedType}]`;
}
catch (error) {
return `[Feed Message Parsing Error: ${JSON.stringify(msg)}]`;
}
}
// 메시지 파싱 함수
function safeParseMessage(message) {
// 빈 문자열이나 null 체크
if (!message || typeof message !== 'string') {
return message || '';
}
const logger = new logger_1.Logger('Models: safeParseMessage');
try {
// JSON reviver 함수를 사용하여 큰 정수를 문자열로 보존
const parsed = (0, utils_1.safeJsonParseWithReviver)(message);
// feedType이 존재하고 숫자인지 확인 (BigInt도 허용)
if (parsed &&
typeof parsed === 'object' &&
parsed.feedType &&
(typeof parsed.feedType === 'number' ||
typeof parsed.feedType === 'bigint')) {
// BigInt를 number로 변환
const feedType = typeof parsed.feedType === 'bigint'
? Number(parsed.feedType)
: parsed.feedType;
// 매핑 테이블에서 지원하는 feedType인지 확인
if (feedType in feed_types_1.FEED_TYPE_MAP) {
// feedType을 number로 정규화
const normalizedParsed = {
...parsed,
feedType: feedType,
};
// 기본적인 구조 검증
const isValid = validateFeedStructure(normalizedParsed, feedType);
if (isValid) {
return normalizedParsed;
}
}
// 지원하지 않는 feedType이지만 유효한 JSON인 경우 원본 반환
logger.warn(`Unsupported feedType: ${feedType}`);
return message;
}
// feedType이 없는 일반 JSON은 원본 문자열로 반환
return message;
}
catch (error) {
// JSON 파싱 실패 시 원본 문자열 반환
return message;
}
}
// 피드 구조 검증 함수
function validateFeedStructure(parsed, feedType) {
try {
// userId는 숫자, 문자열, bigint 모두 허용
const isValidUser = (user) => user &&
(typeof user.userId === 'string' ||
typeof user.userId === 'number' ||
typeof user.userId === 'bigint') &&
typeof user.nickName === 'string';
switch (feedType) {
case 1: // InviteUserFeedType
return (isValidUser(parsed.inviter) &&
Array.isArray(parsed.members) &&
parsed.members.every(isValidUser));
case 2: // LeaveUserFeedType
return isValidUser(parsed.member);
case 4: // OpenChatJoinUserFeedType
return (Array.isArray(parsed.members) && parsed.members.every(isValidUser));
case 6: // OpenChatKickedUserType
return isValidUser(parsed.member);
case 11: // OpenChatPromoteManagerType
case 12: // OpenChatDemoteManagerType
return isValidUser(parsed.member);
case 14: // DeleteMessageType
return (parsed.logId &&
(typeof parsed.logId === 'string' ||
typeof parsed.logId === 'number' ||
typeof parsed.logId === 'bigint') &&
typeof parsed.hidden === 'boolean');
case 15: // OpenChatHandOverHostType
return isValidUser(parsed.newHost) && isValidUser(parsed.prevHost);
case 26: // OpenChatHideMessageType
return (parsed.logId &&
(typeof parsed.logId === 'string' ||
typeof parsed.logId === 'number' ||
typeof parsed.logId === 'bigint') &&
typeof parsed.hidden === 'boolean' &&
Array.isArray(parsed.chatLogInfos));
default:
return false;
}
}
catch (error) {
return false;
}
}
//# sourceMappingURL=utils.js.map