Coder Social home page Coder Social logo

chzzk's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

chzzk's Issues

Donation 이벤트 문제

chzzkChat.on으로 donation 이벤트를 수신할 때, 처음 시작 시에만 작동하고 chat 이벤트처럼 이벤트가 감지될때마다 새로 올라오지 않는 문제가 있습니다. systemMessage도 똑같을 것으로 예상됩니다.

LiveSettingParams Type 누락

live.d.ts쪽 코드

export interface LiveSettingParams {
    adult: boolean;
    categoryType?: string;
    chatActive: boolean;
    chatAvailableGroup: string;
    defaultLiveTitle: string;
    defaultThumbnailImageUrl?: string;
    liveCategory?: string;
    paidPromotion: boolean;
}

export interface LiveSetting {
    defaultLiveTitle: string;
    category: {
        categoryType?: "GAME" | "ETC";
        liveCategory?: string;
        liveCategoryName?: string;
    };
    defaultThumbnailImageUrl?: string;
    chatActive: boolean;
    chatAvailableGroup: string;
    paidPromotion: boolean;
    adult: boolean;
    chatAvailableCondition: string;
    minFollowerMinute: number;
}

LiveDetail, LiveSetting에는 chatAvailableCondition이 제대로 존재하지만, LiveSettingParams에는 누락되어 있습니다.

메시지가 고정 해제될 때 오류 발생

Bun 최신 버전, Node.js 21에서 공통적으로 발생하는 문제입니다.

  • Bun
252 |                 this.startPingTimer();
253 |             }
254 |         });
255 |     }
256 |     parseChat(chat, isRecent = false) {
257 |         const profile = JSON.parse(chat['profile']);
                              ^
SyntaxError: JSON Parse error: Unexpected identifier "undefined"
      at parseChat (/home/ubuntu/chzzkbot/node_modules/chzzk/dist/chat/chat.js:257:25)
      at /home/ubuntu/chzzkbot/node_modules/chzzk/dist/chat/chat.js:243:41
      at /home/ubuntu/chzzkbot/node_modules/chzzk/dist/chat/chat.js:8:9
      at new Promise (:1:21)
      at /home/ubuntu/chzzkbot/node_modules/chzzk/dist/chat/chat.js:4:12
  • Node.js
undefined:1
undefined
^

SyntaxError: "undefined" is not valid JSON
    at JSON.parse (<anonymous>)
    at ChzzkChat.parseChat (/home/ubuntu/chzzkbot/node_modules/chzzk/dist/chat/chat.js:257:30)
    at ChzzkChat.<anonymous> (/home/ubuntu/chzzkbot/node_modules/chzzk/dist/chat/chat.js:243:46)
    at Generator.next (<anonymous>)
    at /home/ubuntu/chzzkbot/node_modules/chzzk/dist/chat/chat.js:8:71
    at new Promise (<anonymous>)
    at __awaiter (/home/ubuntu/chzzkbot/node_modules/chzzk/dist/chat/chat.js:4:12)
    at ChzzkChat.handleMessage (/home/ubuntu/chzzkbot/node_modules/chzzk/dist/chat/chat.js:196:16)
    at callListener (/home/ubuntu/chzzkbot/node_modules/ws/lib/event-target.js:290:14)
    at WebSocket.onMessage (/home/ubuntu/chzzkbot/node_modules/ws/lib/event-target.js:209:9)

Node.js v21.6.1

메시지가 고정 해제되었을 때에 대한 예외처리가 필요해 보입니다.

disconnect() 메서드에 문제가 있는 것 같습니다.

async disconnect() {
  if (!this.connected) {
    throw new Error('Not connected')
  }
  // 이하 코드 생략
}

현 시점 모듈 코드의 채팅disconnect() 메서드 코드 일부입니다. 위 코드 진행대로라면 계정(봇) 이 채팅에 연결되어 있지 않을 때 Not connected 오류가 발생하며 코드 진행이 중단되게 되는 것 같습니다.
disconnect() 메서드를 사용하지 않는다면 발생하지 않을 문제지만, chatChannelId가 채널별 고정이 아닌 세션별 랜덤 생성이라는 점에서 disconnect() 메서드의 사용은 불가피할 것으로 판단됩니다.
위 코드를 오류가 발생하면 해당 오류를 알려주고 다시 시도 와 같이 프로그램이 다운되지 않도록 바꿔주실 수 있을까요?

[Bug] 검색 결과가 없을 시 오류 발생

검색 결과가 없을 때 content.page가 null로 대체되는데,
이것이 제대로 처리되지 않아 content.page.next.offset을 불러오려 할 때 오류가 발생합니다.

https://github.com/kimcore/chzzk/blob/main/src/api/search.ts#L59
https://github.com/kimcore/chzzk/blob/main/src/api/search.ts#L81
https://github.com/kimcore/chzzk/blob/main/src/api/search.ts#L109

추가로, search 메소드의 반환 타입을 제대로 지정하여 추후 이런 문제가 재발하지 않도록 하는것도 좋아보이네요.

방송이 시작된 후 채팅 받아오기 멈춤

방송이 켜져있을 때 친 채팅은 제대로 나오지만,
방송이 꺼진 후의 채팅은 나오지 않는 것으로 보입니다.
이로 인해 방송이 켜질 때마다 코드를 재실행해줘야하는 문제가 있습니다.
이 문제를 수정하면 채팅창에서 치지직 채팅창이 방송을 시작했을 때 새로고침을 하지 않아도 제대로 채팅이 나올 것 같습니다.

TypeError: fetch failed (ECONNRESET)

client.chat을 이용하고 있는도중 간헐적인 에러가 발생합니다.
정확한 원인은 callstack이 명확하게 표시되지 않아서 알기어렵지만 아래와 같은 로그가 표시됩니다.

node:internal/deps/undici/undici:12344
    Error.captureStackTrace(err, this);
          ^

TypeError: fetch failed
    at node:internal/deps/undici/undici:12344:11
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  cause: Error: read ECONNRESET
      at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) {
    errno: -4077,
    code: 'ECONNRESET',
    syscall: 'read'
  }
}

fetch failed임을 봤을때 요청 관련 에러로 보이며
ECONNRESET code는 반대편에서 연결을 끊었을때 발생합니다.

아래 에러 로그처럼 간헐적으로 발생합니다 (로그 시간 참고)
모든 에러의 초가 14초, 44초로 30초 간격으로 맞아떨어짐으로 짐작하자면 스케줄링된 polling 관련 로직이 아닐까 합니다.

/user/.pm2/logs/project-error-23.log last 200 lines:
23|project  | 2024-02-08T14:23:14: TypeError: fetch failed
23|project  | 2024-02-08T14:23:14:     at node:internal/deps/undici/undici:12344:11
23|project  | 2024-02-08T14:23:14:     at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
23|project  | 2024-02-08T14:23:14:   cause: Error: read ECONNRESET
23|project  | 2024-02-08T14:23:14:       at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) {
23|project  | 2024-02-08T14:23:14:     errno: -104,
23|project  | 2024-02-08T14:23:14:     code: 'ECONNRESET',
23|project  | 2024-02-08T14:23:14:     syscall: 'read'
23|project  | 2024-02-08T14:23:14:   }
23|project  | 2024-02-08T14:23:14: }
23|project  | 2024-02-08T14:34:14: TypeError: fetch failed
23|project  | 2024-02-08T14:34:14:     at node:internal/deps/undici/undici:12344:11
23|project  | 2024-02-08T14:34:14:     at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
23|project  | 2024-02-08T14:34:14:   cause: Error: read ECONNRESET
23|project  | 2024-02-08T14:34:14:       at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) {
23|project  | 2024-02-08T14:34:14:     errno: -104,
23|project  | 2024-02-08T14:34:14:     code: 'ECONNRESET',
23|project  | 2024-02-08T14:34:14:     syscall: 'read'
23|project  | 2024-02-08T14:34:14:   }
23|project  | 2024-02-08T14:34:14: }
23|project  | 2024-02-08T14:45:44: TypeError: fetch failed
23|project  | 2024-02-08T14:45:44:     at node:internal/deps/undici/undici:12344:11
23|project  | 2024-02-08T14:45:44:     at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
23|project  | 2024-02-08T14:45:44:   cause: Error: read ECONNRESET
23|project  | 2024-02-08T14:45:44:       at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) {
23|project  | 2024-02-08T14:45:44:     errno: -104,
23|project  | 2024-02-08T14:45:44:     code: 'ECONNRESET',
23|project  | 2024-02-08T14:45:44:     syscall: 'read'
23|project  | 2024-02-08T14:45:44:   }
23|project  | 2024-02-08T14:45:44: }
23|project  | 2024-02-08T14:55:44: TypeError: fetch failed
23|project  | 2024-02-08T14:55:44:     at node:internal/deps/undici/undici:12344:11
23|project  | 2024-02-08T14:55:44:     at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
23|project  | 2024-02-08T14:55:44:   cause: Error: read ECONNRESET
23|project  | 2024-02-08T14:55:44:       at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) {
23|project  | 2024-02-08T14:55:44:     errno: -104,
23|project  | 2024-02-08T14:55:44:     code: 'ECONNRESET',
23|project  | 2024-02-08T14:55:44:     syscall: 'read'
23|project  | 2024-02-08T14:55:44:   }
23|project  | 2024-02-08T14:55:44: }
23|project  | 2024-02-08T15:19:44: TypeError: fetch failed
23|project  | 2024-02-08T15:19:44:     at node:internal/deps/undici/undici:12344:11
23|project  | 2024-02-08T15:19:44:     at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
23|project  | 2024-02-08T15:19:44:   cause: Error: read ECONNRESET
23|project  | 2024-02-08T15:19:44:       at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) {
23|project  | 2024-02-08T15:19:44:     errno: -104,
23|project  | 2024-02-08T15:19:44:     code: 'ECONNRESET',
23|project  | 2024-02-08T15:19:44:     syscall: 'read'
23|project  | 2024-02-08T15:19:44:   }
23|project  | 2024-02-08T15:19:44: }
23|project  | 2024-02-08T15:32:14: TypeError: fetch failed
23|project  | 2024-02-08T15:32:14:     at node:internal/deps/undici/undici:12344:11
23|project  | 2024-02-08T15:32:14:     at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
23|project  | 2024-02-08T15:32:14:   cause: Error: read ECONNRESET
23|project  | 2024-02-08T15:32:14:       at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) {
23|project  | 2024-02-08T15:32:14:     errno: -104,
23|project  | 2024-02-08T15:32:14:     code: 'ECONNRESET',
23|project  | 2024-02-08T15:32:14:     syscall: 'read'
23|project  | 2024-02-08T15:32:14:   }
23|project  | 2024-02-08T15:32:14: }
23|project  | 2024-02-08T15:42:14: TypeError: fetch failed
23|project  | 2024-02-08T15:42:14:     at node:internal/deps/undici/undici:12344:11
23|project  | 2024-02-08T15:42:14:     at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
23|project  | 2024-02-08T15:42:14:   cause: Error: read ECONNRESET
23|project  | 2024-02-08T15:42:14:       at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) {
23|project  | 2024-02-08T15:42:14:     errno: -104,
23|project  | 2024-02-08T15:42:14:     code: 'ECONNRESET',
23|project  | 2024-02-08T15:42:14:     syscall: 'read'
23|project  | 2024-02-08T15:42:14:   }
23|project  | 2024-02-08T15:42:14: }
23|project  | 2024-02-08T18:36:14: TypeError: fetch failed
23|project  | 2024-02-08T18:36:14:     at node:internal/deps/undici/undici:12344:11
23|project  | 2024-02-08T18:36:14:     at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
23|project  | 2024-02-08T18:36:14:   cause: Error: read ECONNRESET
23|project  | 2024-02-08T18:36:14:       at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) {
23|project  | 2024-02-08T18:36:14:     errno: -104,
23|project  | 2024-02-08T18:36:14:     code: 'ECONNRESET',
23|project  | 2024-02-08T18:36:14:     syscall: 'read'
23|project  | 2024-02-08T18:36:14:   }
23|project  | 2024-02-08T18:36:14: }

위 정황들로 파악했을때
api / live.ts > ChzzkLive > status > fetch(`/polling/v2/channels/${channelId}/live-status`)에서 발생하는것으로 추측됩니다
.catch(()=>{ //logic })을 추가하여 관련 핸들링이 필요해보입니다

JSON Parse error: Unexpected identifier "undefined"

Node.js v21.5.0

undefined:1
undefined
^

SyntaxError: "undefined" is not valid JSON
    at JSON.parse (<anonymous>)
    at /node_modules/chzzk/dist/api/live.js:48:55
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async /index.js:41:24

Node.js v21.5.0

Bun v1.0.21

43 |                 const livePlaybackJson = content['livePlaybackJson'];
44 |                 const livePlayback = livePlaybackJson ? JSON.parse(livePlaybackJson) : null;
45 |                 delete content['livePlaybackJson'];
46 |                 const channel = content['channel'];
47 |                 const channelLivePollingStatusJson = channel['livePollingStatusJson'];
48 |                 const channelLivePollingStatus = JSON.parse(channelLivePollingStatusJson);
                                                      ^
SyntaxError: JSON Parse error: Unexpected identifier "undefined"
      at /node_modules/chzzk/dist/api/live.js:48:50
      at processTicksAndRejections (:61:77)

1.1.1 버전까지는 발생하지 않던 오류였으나, 1.1.2 버전에서 오류가 발생합니다.

  • 문제가 발생하는 코드
const liveDetail = await client.live.detail(channel.channelId);

로그인 쿠키 관련.

혹시 cookie 에서 수동으로 복사 붙여넣기 하는 방법 이외에는 로그인 할수 있는 방법이 아직 없을까요?

그리고 chat 기능은 로그인이 필수일까요? (read만 하려고하는 경우)

감사합니다.

livePlaybackJson

현재 livePlaybackJson은 모듈 내에서 "livePlayback"으로 되어있습니다.
livePlaybackJson으로 변경이 필요할 듯 합니다.

  • live.d.ts (기존)
export interface Live {
    liveTitle: string;
    liveImageUrl: string;
    defaultThumbnailImageUrl?: string;
    concurrentUserCount: number;
    accumulateCount: number;
    openDate: string;
    liveId: number;
    adult: boolean;
    chatChannelId: string;
    categoryType?: string;
    liveCategory?: string;
    liveCategoryValue?: string;
    channelId: string;
    livePlayback: LivePlayback;
    channel: PartialChannel;
}
  • live.d.ts (변경)
export interface Live {
    liveTitle: string;
    liveImageUrl: string;
    defaultThumbnailImageUrl?: string;
    concurrentUserCount: number;
    accumulateCount: number;
    openDate: string;
    liveId: number;
    adult: boolean;
    chatChannelId: string;
    categoryType?: string;
    liveCategory?: string;
    liveCategoryValue?: string;
    channelId: string;
    livePlaybackJson: LivePlayback;
    channel: PartialChannel;
}

채팅 구독 뱃지 지원

채팅에서 구독 뱃지 관련 데이터를 가져오기 위해 StreamingProperty에 subscription을 정의해야 할 것 같습니다.

첫 실행 시 오류 발생

node_modules/chzzk/dist/chat/chat.js:146
                    for (const chat of chats) {
                                       ^

TypeError: chats is not iterable
    at ChzzkChat.<anonymous> (node_modules/chzzk/dist/chat/chat.js:146:40)
    at Generator.next (<anonymous>)
    at node_modules/chzzk/dist/chat/chat.js:8:71
    at new Promise (<anonymous>)
    at __awaiter (node_modules/chzzk/dist/chat/chat.js:4:12)
    at ChzzkChat.handleMessage (node_modules/chzzk/dist/chat/chat.js:124:16)
    at callListener (node_modules/ws/lib/event-target.js:290:14)
    at WebSocket.onMessage (node_modules/ws/lib/event-target.js:209:9)
    at WebSocket.emit (node:events:517:28)
    at Receiver.receiverOnMessage (node_modules/ws/lib/websocket.js:1203:20)

Node.js 18, 19, 20, 21 모두 오류가 발생합니다.

README.md 수정 요청

// 유저의 팔로우 일시 불러오기
// client.chat.profileCard(chzzkChat.chatChannelId, chat.profile.userIdHash).then(profile => {
//     console.log(profile.following ? `${profile.following.followDate} 에 팔로우 함` : "팔로우 안함")
// })

위 예시를 보면 profile.followingprofile.following.followDate가 있습니다.
하지만, 실제 API를 보면 profile.streamingProperty.followingprofile.streamingProperty.following.followDate로 되어있습니다.
위 텍스트를 수정해주시면 감사하겠습니다.

subscription 이벤트 웹소켓

msgTypeCode (코드 내 기준 ChatType) 는 11이고, cmd (코드 내 기준 ChatCmd) 는 93102로 확인되었습니다.
아래 스크린샷 확인 부탁드립니다.

스크린샷 2024-03-08 220722

subscription 이벤트를 추가하는 데 도움이 될 것 같아 올립니다.

API 버전 자동 변경

현재 v1 API에 들어가면, code 9004와 함께 "앱 업데이트 후에 정상 시청 가능합니다." 메시지가 나옵니다.

코드가 9004라면 v1에서 v2로, v2에서도 코드가 9004라면 v2에서 v3로 자동으로 올려주는 기능이 추가되면 모듈을 계속 업데이트하지 않아도 사용할 수 있을 것 같아 편리할 것 같습니다.

이모티콘 전송 기능

이모티콘등을 전송할수있도록 sendChat 메서드 내에 extras를 수정할 수 있는 추가 인자를 추가해주셨으면 좋겠습니다

Chat list is not iterable

프로그램 실행 중, 간헐적으로 채팅을 받아올 때 #3 와 똑같은 오류가 발생합니다.

환경 : Node.js 18, 19, 20, 21 | Bun 1.0.15, 1.0.16, 1.0.17, 1.0.18, 1.0.19, 1.0.20

로컬 개발 환경에서 CORS 프록시 사용을 위한 코드 개선

클라이언트 앱에서 본 비공식 API 사용 시, 개발 단계에서 로컬 프록시를 이용할 수 있도록
ChzzkClient 객체 생성 시점에 API 주소를 주입 받을 수 있게 개선하면 좋을 것 같습니다.

예를 들어 http-proxy-middleware 라이브러리를 사용하면
별도의 node 서버를 세팅하지 않고도 로컬 프록시 구조를 만들 수 있습니다.

아래와 같은 프록시 구조를 만들기 위해서는
client --> /api --> 프록시서버 --> https://api.chzzk.naver.com

이와 같은 코드를 작성하면 됩니다.

const { createProxyMiddleware } = require("http-proxy-middleware");

module.exports = function (app) {
  app.use(
    "/api",
    createProxyMiddleware({
      target: "https://api.chzzk.naver.com",
      changeOrigin: true,
      pathRewrite: { "^/api": "" },
    })
  );
};

위 프록시 세팅 코드는
fetch("/api") 요청을 프록시 서버가 받아들이고
프록시 서버가 다시 /api 요청을 그대로 https://api.chzzk.naver.com 로 보내서
응답을 반환하도록 하는 세팅입니다.

하지만 위와 같은 로컬 프록시 라이브러리가 동작하도록 하려면
ChzzkClient 가 로컬 프록시 주소를 주입받을 수 있도록 코드를 변경해야 합니다.
현재는 ChzzkClient 가 고정적으로 consts.ts로 부터 네이버측 api 주소를 받아서 fetch 하고 있습니다.
대신 ChzzkClient 가 생성 시점이나 세팅 메서드를 통해서 프록시 주소 /api를 받아서 fetch 할 수 있도록 개선하면 좋을 것 같습니다.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.