buzzk 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,15 +15,27 @@
15
15
 
16
16
  ---
17
17
 
18
+ ## 업데이트 내역
19
+
20
+ - 자동완성 기능 지원
21
+
22
+ >
23
+
24
+ - 팔로우 / 언팔로우 기능 추가
25
+ - live.getLiveDetail의 Return 값에 chatLimit 추가 (팔로우 대상 채팅 등...)
26
+ - 폴링 함수 추가 (chatID 변경 감지)
27
+ - API 호출 실패 시 오류 핸들링 (Return true / null)
28
+ - chat.disconnect 함수 보완
29
+ - 버전 체크 함수 추가
30
+
18
31
  ## 설치
19
32
 
20
- 1. 레포지토리를 다운받아 프로젝트 폴더 안에 넣어주세요.
21
- 2. 폴더 이름을 `buzzk-master` 에서 `buzzk` 으로 변경해주세요.
22
- 3. `const buzzk = require("./buzzk");`
33
+ 1. `npm install buzzk`
34
+ 2. `const buzzk = require("buzzk");`
23
35
 
24
36
  ## 빠른. 시작.
25
37
 
26
- const buzzk = require("./buzzk");
38
+ const buzzk = require("buzzk");
27
39
  buzzk.login("NID_AUT 쿠키 값", "NID_SES 쿠키 값");
28
40
 
29
41
  const buzzkChat = buzzk.chat;
@@ -85,6 +97,12 @@ dotenv와 함께 사용하는 것을 매우 권장합니다.
85
97
 
86
98
  </details>
87
99
 
100
+ await buzzk.channel.followChannel("channelID 값");
101
+
102
+ >
103
+
104
+ await buzzk.channel.unFollowChannel("channelID 값");
105
+
88
106
  ---
89
107
 
90
108
  > live
@@ -99,6 +117,7 @@ dotenv와 함께 사용하는 것을 매우 권장합니다.
99
117
  - channelID
100
118
  - channel
101
119
  - chatID
120
+ - chatLimit //팔로워 전용 채팅 등...
102
121
  - userCount
103
122
  - now
104
123
  - total
@@ -189,4 +208,4 @@ dotenv와 함께 사용하는 것을 매우 권장합니다.
189
208
 
190
209
  >
191
210
 
192
- chat.disconnect(); //채팅창 연결 끊기
211
+ await chat.disconnect(); //채팅창 연결 끊기
package/lib/channel.js CHANGED
@@ -1,4 +1,4 @@
1
- const { reqChzzk } = require("./tool.js");
1
+ const { reqChzzk, exChzzk } = require("./tool.js");
2
2
 
3
3
  class chzzkChannel {
4
4
  constructor(channelID, name, description, follower, imageURL, isLive) {
@@ -11,13 +11,32 @@ class chzzkChannel {
11
11
  }
12
12
  }
13
13
 
14
+ /**
15
+ * @typedef {Object.<number, chzzkChannel>} chzzkChannels
16
+ */
17
+
18
+ /**
19
+ * @typedef {Object} chzzkChannel
20
+ * @property {string} channelID
21
+ * @property {string} name
22
+ * @property {string} description
23
+ * @property {string} follower
24
+ * @property {string} imageURL
25
+ * @property {string} isLive
26
+ */
27
+
28
+ /**
29
+ * @param {string} keyword
30
+ * @returns {Promise<chzzkChannels>}
31
+ */
14
32
  async function getChannel (keyword) {
15
33
  return new Promise(async (resolve, reject) => {
16
34
 
17
35
  let chSearch = await reqChzzk("service/v1/search/channels?keyword=" + keyword + "&offset=0&size=13&withFirstChannelContent=false");
36
+ if (chSearch.code != 200) return resolve(null);
18
37
  chSearch = chSearch.content.data;
19
38
 
20
- if (!chSearch) return resolve();
39
+ if (!chSearch) return resolve(null);
21
40
 
22
41
  let chRes = new Map();
23
42
 
@@ -31,6 +50,36 @@ async function getChannel (keyword) {
31
50
  });
32
51
  }
33
52
 
53
+ /**
54
+ * @param {string} channelID
55
+ * @returns {Promise<boolean>}
56
+ */
57
+ async function followChannel (channelID) {
58
+ return new Promise(async (resolve, reject) => {
59
+
60
+ let flRes = await exChzzk("POST", "service/v1/channels/" + channelID + "/follow");
61
+ if (flRes.code == 200) return resolve(true);
62
+ else return resolve(null);
63
+
64
+ });
65
+ }
66
+
67
+ /**
68
+ * @param {string} channelID
69
+ * @returns {Promise<boolean>}
70
+ */
71
+ async function unFollowChannel (channelID) {
72
+ return new Promise(async (resolve, reject) => {
73
+
74
+ let flRes = await exChzzk("DELETE", "service/v1/channels/" + channelID + "/follow");
75
+ if (flRes.code == 200) return resolve(true);
76
+ else return resolve(null);
77
+
78
+ });
79
+ }
80
+
34
81
  module.exports = {
35
- getChannel: getChannel
82
+ getChannel: getChannel,
83
+ followChannel: followChannel,
84
+ unFollowChannel: unFollowChannel
36
85
  }
package/lib/chat.js CHANGED
@@ -15,19 +15,25 @@ class chzzkChat {
15
15
  #svcid; //game
16
16
  #sid;
17
17
  #chatID;
18
+
19
+ #pollingStatus = false;
18
20
  //Private
19
21
 
22
+ /**
23
+ * @returns {Promise<boolean>}
24
+ */
20
25
  connect() {
21
26
  return new Promise(async (resolve, reject) => {
27
+ if (this.#ws) return resolve(null);
28
+
22
29
  //Get ChatID
23
30
  let cidRes = await getLiveStatus(this.channelID);
24
-
25
31
  this.#chatID = cidRes.chatID;
26
32
  //Get ChatID
27
33
 
28
34
  //Get accTkn
29
35
  let accRes = await reqGame("nng_main/v1/chats/access-token?channelId=" + this.#chatID + "&chatType=STREAMING");
30
-
36
+ if (accRes.code != 200) return resolve(null);
31
37
  this.#accTkn = accRes.content.accessToken;
32
38
  //Get accTkn
33
39
 
@@ -39,6 +45,10 @@ class chzzkChat {
39
45
  this.#ws = new WebSocket("wss://kr-ss" + this.#ssID + ".chat.naver.com/chat");
40
46
  //Connect Web Socket
41
47
 
48
+ //SetPolling
49
+ if (!this.#pollingStatus) this.polling();
50
+ //SetPolling
51
+
42
52
  //WS Open
43
53
  this.#ws.on("open", () => {
44
54
  console.log("[WS] Connected!");
@@ -90,7 +100,7 @@ class chzzkChat {
90
100
  //Ping Pong
91
101
 
92
102
  //Connected
93
- else if (data.cmd == 10100) resolve();
103
+ else if (data.cmd == 10100) resolve(true);
94
104
  //Connected
95
105
  });
96
106
  //WS Message
@@ -98,8 +108,13 @@ class chzzkChat {
98
108
  });
99
109
  }
100
110
 
111
+ /**
112
+ * @param {string} message
113
+ * @returns {Promise<boolean>}
114
+ */
101
115
  send(message) {
102
116
  return new Promise(async (resolve, reject) => {
117
+ if (!this.#ws) return resolve(null);
103
118
 
104
119
  let extras = {
105
120
  "chatType":"STREAMING",
@@ -129,12 +144,33 @@ class chzzkChat {
129
144
 
130
145
  this.#ws.send(JSON.stringify(sendOpt));
131
146
 
132
- return resolve();
147
+ return resolve(true);
133
148
  //WS Send
134
149
 
135
150
  });
136
151
  }
137
152
 
153
+ /**
154
+ * @typedef {Object.<number, chzzkMessage>} chzzkMessages
155
+ */
156
+
157
+ /**
158
+ * @typedef {Object} chzzkMessage
159
+ * @property {chzzkMessageAuthor} author
160
+ * @property {string} message
161
+ * @property {number} time
162
+ */
163
+
164
+ /**
165
+ * @typedef {Object} chzzkMessageAuthor
166
+ * @property {string} id
167
+ * @property {string} name
168
+ * @property {string} imageURL
169
+ */
170
+
171
+ /**
172
+ * @param {function(chzzkMessages)} callback
173
+ */
138
174
  onMessage(callback) {
139
175
  if (!this.#ws) return callback(null);
140
176
 
@@ -166,6 +202,10 @@ class chzzkChat {
166
202
  });
167
203
  }
168
204
 
205
+ /**
206
+ * @param {?number} size
207
+ * @return {Promise<chzzkMessages>}
208
+ */
169
209
  getRecentChat(size) {
170
210
  return new Promise(async (resolve, reject) => {
171
211
  if (!this.#ws) return resolve(null);
@@ -213,8 +253,31 @@ class chzzkChat {
213
253
  });
214
254
  }
215
255
 
216
- disconnect() {
217
- this.#ws.close();
256
+ /**
257
+ * @returns {Promise<boolean>}
258
+ */
259
+ async disconnect() {
260
+ return new Promise(async (resolve, reject) => {
261
+ if (!this.#ws) return resolve(null);
262
+
263
+ await this.#ws.close();
264
+ this.#ws = null;
265
+ return resolve(true);
266
+ });
267
+ }
268
+
269
+ async polling () {
270
+ if (!this.#ws) return this.#pollingStatus = false;
271
+ this.#pollingStatus = true;
272
+
273
+ //Get ChatID
274
+ let cidRes = await getLiveStatus(this.channelID);
275
+ this.#chatID = cidRes.chatID;
276
+ //Get ChatID
277
+
278
+ setTimeout(() => {
279
+ return this.polling();
280
+ }, cidRes.polling.callPeriodMilliSecond);
218
281
  }
219
282
  }
220
283
 
package/lib/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ require("./vm.js");
2
+
1
3
  module.exports = {
2
4
  channel: require("./channel.js"),
3
5
  chat: require("./chat.js").chzzkChat,
package/lib/live.js CHANGED
@@ -1,15 +1,42 @@
1
1
  const { reqChzzk } = require("./tool.js");
2
2
 
3
+ /**
4
+ * @typedef {Object} chzzkLiveDetail
5
+ * @property {string} channelID
6
+ * @property {Object} channel
7
+ * @property {string} chatID
8
+ * @property {string} chatLimit
9
+ * @property {userCount} userCount
10
+ * @property {string} title
11
+ * @property {string} startOn
12
+ * @property {string} closeOn
13
+ * @property {string} status
14
+ * @property {Object} polling
15
+ *
16
+ */
17
+
18
+ /**
19
+ * @typedef {Object} userCount
20
+ * @property {number} now
21
+ * @property {number} total
22
+ */
23
+
24
+ /**
25
+ * @param {string} channelID
26
+ * @returns {Promise<chzzkLiveDetail>}
27
+ */
3
28
  async function getLiveDetail (channelID) {
4
29
  return new Promise(async (resolve, reject) => {
5
30
 
6
31
  let res = await reqChzzk("service/v2/channels/" + channelID + "/live-detail");
32
+ if (res.code != 200) return resolve(null);
7
33
  res = res.content;
8
34
 
9
35
  let lvDetail = {
10
36
  channelID: res.channel.channelId,
11
37
  channel: res.channel,
12
38
  chatID: res.chatChannelId,
39
+ chatLimit: res.chatAvailableGroup,
13
40
  userCount: { now: res.concurrentUserCount, total: res.accumulateCount },
14
41
  title: res.liveTitle,
15
42
  startOn: res.openDate,
@@ -23,10 +50,26 @@ async function getLiveDetail (channelID) {
23
50
  });
24
51
  }
25
52
 
53
+ /**
54
+ * @typedef {Object} chzzkLiveStatus
55
+ * @property {string} channelID
56
+ * @property {string} chatID
57
+ * @property {userCount} userCount
58
+ * @property {string} title
59
+ * @property {string} status
60
+ * @property {Object} polling
61
+ *
62
+ */
63
+
64
+ /**
65
+ * @param {string} channelID
66
+ * @returns {Promise<chzzkLiveStatus>}
67
+ */
26
68
  async function getLiveStatus (channelID) {
27
69
  return new Promise(async (resolve, reject) => {
28
70
 
29
71
  let res = await reqChzzk("polling/v2/channels/" + channelID + "/live-status");
72
+ if (res.code != 200) return resolve(null);
30
73
  res = res.content;
31
74
 
32
75
  let lvStatus = {
package/lib/tool.js CHANGED
@@ -15,6 +15,21 @@ function reqChzzk (path) {
15
15
  });
16
16
  }
17
17
 
18
+ function exChzzk (method, path) {
19
+ return new Promise(async (resolve, reject) => {
20
+
21
+ fetch(chzzkBaseURL + path, {
22
+ method: method,
23
+ headers: {
24
+ "Cookie": "NID_AUT=" + NID.AUT + ";NID_SES=" + NID.SES
25
+ }
26
+ })
27
+
28
+ .then((response) => resolve(response.json()));
29
+
30
+ });
31
+ }
32
+
18
33
  function reqGame (path) {
19
34
  return new Promise(async (resolve, reject) => {
20
35
 
@@ -32,5 +47,6 @@ function reqGame (path) {
32
47
 
33
48
  module.exports = {
34
49
  reqChzzk: reqChzzk,
50
+ exChzzk: exChzzk,
35
51
  reqGame: reqGame
36
52
  }
package/lib/val.js CHANGED
@@ -6,6 +6,11 @@ let NID = {
6
6
  SES: null
7
7
  }
8
8
 
9
+
10
+ /**
11
+ * @param {string} NID_AUT
12
+ * @param {string} NID_SES
13
+ */
9
14
  function login (NID_AUT, NID_SES) {
10
15
  NID.AUT = NID_AUT;
11
16
  NID.SES = NID_SES;
package/lib/vm.js ADDED
@@ -0,0 +1,18 @@
1
+ async function check () {
2
+
3
+ let localPkg = require("../package.json");
4
+ let remotePkg = await fetch("https://raw.githubusercontent.com/Emin-G/buzzk/master/package.json");
5
+
6
+ if (remotePkg.status != 200) return console.log("[BUZZK] 최신 버전에 대한 정보를 불러오지 못했습니다.");
7
+
8
+ remotePkg = await remotePkg.json();
9
+
10
+ localPkg = String(localPkg.version).split(".");
11
+ remotePkg = String(remotePkg.version).split(".");
12
+
13
+ for (let v in remotePkg) {
14
+ if (parseInt(remotePkg[v]) > parseInt(localPkg[v])) return console.log("[BUZZK] 새로운 버전을 찾았습니다! ( npm install buzzk@" + remotePkg.join(".") + " )");
15
+ }
16
+ }
17
+
18
+ check();
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "buzzk",
3
3
  "displayName": "BUZZK",
4
- "version": "1.0.0",
4
+ "version": "1.2.0",
5
5
  "description": "뿌지직 (BUZZK) - 치지직(CHZZK) 챗봇을 더욱 쉽게 개발할 수 있도록 돕는 비공식 라이브러리.",
6
6
  "main": "lib/index.js",
7
+ "type": "commonjs",
7
8
  "directories": {
8
9
  "lib": "lib"
9
10
  },