김연수

Merge branch 'ocr' into 'master'

Ocr

Change the category of help function from example to help

See merge request !3
...@@ -69,7 +69,7 @@ exports.run = async (client, msg, args, prefix) => { ...@@ -69,7 +69,7 @@ exports.run = async (client, msg, args, prefix) => {
69 exports.config = { 69 exports.config = {
70 name: '도움말', 70 name: '도움말',
71 aliases: ['도움', '명령어', 'commands', 'help'], 71 aliases: ['도움', '명령어', 'commands', 'help'],
72 - category: ['example'], 72 + category: ['Help'],
73 des: ['봇에 대한 명령어 리스트들을 불러옵니다.'], 73 des: ['봇에 대한 명령어 리스트들을 불러옵니다.'],
74 use: ['!도움말 <명령어>'] 74 use: ['!도움말 <명령어>']
75 }; 75 };
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -75,14 +75,11 @@ exports.run = async (client, msg, args, prefix) => { ...@@ -75,14 +75,11 @@ exports.run = async (client, msg, args, prefix) => {
75 } 75 }
76 }; 76 };
77 77
78 -function kor(attachment) {
79 -
80 -}
81 78
82 exports.config = { 79 exports.config = {
83 name: 'ocr', 80 name: 'ocr',
84 aliases: ['ㅐㅊㄱ'], 81 aliases: ['ㅐㅊㄱ'],
85 - category: ['ocr'], 82 + category: ['Ocr'],
86 des: ['이미지를 첨부하고 명령어를 입력하면, 이미지에 있는 텍스트를 추출합니다.'], 83 des: ['이미지를 첨부하고 명령어를 입력하면, 이미지에 있는 텍스트를 추출합니다.'],
87 use: ['!ocr <사용 언어>'] 84 use: ['!ocr <사용 언어>']
88 }; 85 };
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -7,19 +7,19 @@ exports.run = async (client, msg, args, prefix) => { ...@@ -7,19 +7,19 @@ exports.run = async (client, msg, args, prefix) => {
7 7
8 // 검색 대기 시간이 길어질 수 있으므로 사용자에게 진행상황을 알려줄 필요가 있다 8 // 검색 대기 시간이 길어질 수 있으므로 사용자에게 진행상황을 알려줄 필요가 있다
9 msg.reply("검색중 ..."); 9 msg.reply("검색중 ...");
10 - 10 +
11 //include Puppeteer Library 11 //include Puppeteer Library
12 const puppeteer = require('puppeteer'); 12 const puppeteer = require('puppeteer');
13 13
14 const withBrowser = async (fn) => { 14 const withBrowser = async (fn) => {
15 - const browser = await puppeteer.launch({headless:true}); 15 + const browser = await puppeteer.launch({ headless: true });
16 try { 16 try {
17 return await fn(browser); 17 return await fn(browser);
18 } finally { 18 } finally {
19 await browser.close(); 19 await browser.close();
20 } 20 }
21 - } 21 + };
22 - 22 +
23 const withPage = (browser) => async (fn) => { 23 const withPage = (browser) => async (fn) => {
24 const page = await browser.newPage(); 24 const page = await browser.newPage();
25 try { 25 try {
...@@ -27,7 +27,7 @@ exports.run = async (client, msg, args, prefix) => { ...@@ -27,7 +27,7 @@ exports.run = async (client, msg, args, prefix) => {
27 } finally { 27 } finally {
28 await page.close(); 28 await page.close();
29 } 29 }
30 - } 30 + };
31 31
32 const urls = ['http://www.bestpen.kr/shop/shopbrand.html?&search=', 'http://www.pencafe.co.kr/shop/shopbrand.html?&search=', 'https://blueblack.co.kr/product/search.html?&keyword=', 'http://japan9.co.kr/shop/shopbrand.html?&search=']; 32 const urls = ['http://www.bestpen.kr/shop/shopbrand.html?&search=', 'http://www.pencafe.co.kr/shop/shopbrand.html?&search=', 'https://blueblack.co.kr/product/search.html?&keyword=', 'http://japan9.co.kr/shop/shopbrand.html?&search='];
33 const results = await withBrowser(async (browser) => { 33 const results = await withBrowser(async (browser) => {
...@@ -35,263 +35,265 @@ exports.run = async (client, msg, args, prefix) => { ...@@ -35,263 +35,265 @@ exports.run = async (client, msg, args, prefix) => {
35 return withPage(browser)(async (page) => { 35 return withPage(browser)(async (page) => {
36 // 각 사이트별 제품 검색 36 // 각 사이트별 제품 검색
37 var result = ''; 37 var result = '';
38 - site : switch(urls.indexOf(url)) { 38 + site: switch (urls.indexOf(url)) {
39 - case 0: 39 + case 0:
40 - // 베스트펜 40 + // 베스트펜
41 - try {
42 - var bestpen_url = url + search + "&sort=price"
43 - await page.goto(bestpen_url);
44 - // console.log("bestpen crawling");
45 -
46 - // 페이지 로딩 대기
47 - await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(4) > dd > ul > li.prd-name > a');
48 - } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지
49 -
50 - // 검색 결과 가져오기 (최대 4개)
51 - searchLoop : for (var i = 1; i <= 4; i++) {
52 try { 41 try {
53 - var title = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-name > a', element => { 42 + var bestpen_url = url + search + "&sort=price";
54 - return element.textContent; 43 + await page.goto(bestpen_url);
55 - }); 44 + // console.log("bestpen crawling");
56 - // console.log("베스트펜 검색 결과 제품명 : ", title); 45 +
57 - 46 + // 페이지 로딩 대기
58 - var link = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dt > a', element => { 47 + await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(4) > dd > ul > li.prd-name > a');
59 - return element.href; 48 + } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지
60 - }); 49 +
61 - // console.log("베스트펜 검색 링크 : ", link); 50 + // 검색 결과 가져오기 (최대 4개)
62 - 51 + searchLoop: for (var i = 1; i <= 4; i++) {
63 - // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음
64 - // -> 글자수 제한(1024)도 있으므로 제거
65 - link = link.slice(0, link.indexOf('&search'));
66 -
67 try { 52 try {
68 - var price = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-price > p:nth-child(2) > span.price', element => { 53 + var title = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(' + i + ') > dd > ul > li.prd-name > a', element => {
69 return element.textContent; 54 return element.textContent;
70 }); 55 });
71 - // console.log("베스트펜 검색 결과 가격 : ", price); 56 + // console.log("베스트펜 검색 결과 제품명 : ", title);
72 - } catch { 57 +
73 - // 품절이라서 금액정보가 없을 경우 "SOLD OUT"으로 표시 58 + var link = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(' + i + ') > dt > a', element => {
74 - price = "SOLD OUT"; 59 + return element.href;
75 - } 60 + });
61 + // console.log("베스트펜 검색 링크 : ", link);
62 +
63 + // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음
64 + // -> 글자수 제한(1024)도 있으므로 제거
65 + link = link.slice(0, link.indexOf('&search'));
76 66
77 - result += `[${title}](${link}) - ${price}` + '\n'; 67 + try {
78 - } catch { 68 + var price = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(' + i + ') > dd > ul > li.prd-price > p:nth-child(2) > span.price', element => {
79 - if (i == 1) { 69 + return element.textContent;
80 - // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 70 + });
81 - result += "검색결과 없음" + '\n'; 71 + // console.log("베스트펜 검색 결과 가격 : ", price);
82 - break searchLoop; 72 + } catch {
83 - } else { 73 + // 품절이라서 금액정보가 없을 경우 "SOLD OUT"으로 표시
84 - // 제품 개수가 4개 이하인 경우 74 + price = "SOLD OUT";
85 - break searchLoop; 75 + }
76 +
77 + result += `[${title}](${link}) - ${price}` + '\n';
78 + } catch {
79 + if (i == 1) {
80 + // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시
81 + result += "검색결과 없음" + '\n';
82 + break searchLoop;
83 + } else {
84 + // 제품 개수가 4개 이하인 경우
85 + break searchLoop;
86 + }
86 } 87 }
87 } 88 }
88 - } 89 + break site;
89 - break site; 90 + case 1:
90 - case 1: 91 + // 펜카페
91 - // 펜카페
92 - try {
93 - var pencafe_url = url + search + "&sort=price"
94 - await page.goto(pencafe_url);
95 - // console.log("pencafe crawling");
96 -
97 - // 페이지 로딩 대기
98 - await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(4) > dd > ul > li.prd-name > a');
99 - } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지
100 -
101 - // 검색 결과 가져오기 (최대 4개)
102 - searchLoop : for (var i = 1; i <= 4; i++) {
103 try { 92 try {
104 - var title = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-name > a', element => { 93 + var pencafe_url = url + search + "&sort=price";
105 - return element.textContent; 94 + await page.goto(pencafe_url);
106 - }); 95 + // console.log("pencafe crawling");
107 - // console.log("펜카페 검색 결과 제품명 : ", title); 96 +
108 - 97 + // 페이지 로딩 대기
109 - // 펜카페 구조상 제품명 앞에 할인률(ex. 17%)이 붙는 경우가 많음 -> 제거 98 + await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(4) > dd > ul > li.prd-name > a');
110 - if (title.indexOf('%') != -1) { title = title.slice(title.indexOf('%')+1); } 99 + } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지
111 - // 펜카페 구조상 제품명 뒤에 사족(ex. (색상선택/금장~~~))이 붙는 경우가 많음 -> 제거 100 +
112 - if (title.lastIndexOf(')') == title.length-1) { title = title.slice(0, title.lastIndexOf('(')); } 101 + // 검색 결과 가져오기 (최대 4개)
113 - 102 + searchLoop: for (var i = 1; i <= 4; i++) {
114 - var link = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-name > a', element => {
115 - return element.href;
116 - });
117 - // console.log("펜카페 검색 링크 : ", link);
118 -
119 - // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음
120 - // -> 글자수 제한(1024)도 있으므로 제거
121 - link = link.slice(0, link.indexOf('&search'));
122 -
123 try { 103 try {
124 - var price = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-price > span', element => { 104 + var title = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(' + i + ') > dd > ul > li.prd-name > a', element => {
125 return element.textContent; 105 return element.textContent;
126 }); 106 });
127 - // console.log("펜카페 검색 결과 가격 : ", price); 107 + // console.log("펜카페 검색 결과 제품명 : ", title);
128 - } catch {
129 - // 품절이라서 금액정보가 없을 경우 "SOLD OUT"으로 표시
130 - price = "SOLD OUT";
131 - }
132 108
133 - result += `[${title}](${link}) - ${price}` + '\n'; 109 + // 펜카페 구조상 제품명 앞에 할인률(ex. 17%)이 붙는 경우가 많음 -> 제거
134 - } catch { 110 + if (title.indexOf('%') != -1) { title = title.slice(title.indexOf('%') + 1); }
135 - if (i == 1) { 111 + // 펜카페 구조상 제품명 뒤에 사족(ex. (색상선택/금장~~~))이 붙는 경우가 많음 -> 제거
136 - // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 112 + if (title.lastIndexOf(')') == title.length - 1) { title = title.slice(0, title.lastIndexOf('(')); }
137 - result += "검색결과 없음" + '\n'; 113 +
138 - break searchLoop; 114 + var link = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(' + i + ') > dd > ul > li.prd-name > a', element => {
139 - } else { 115 + return element.href;
140 - // 제품 개수가 4개 이하인 경우 116 + });
141 - break searchLoop; 117 + // console.log("펜카페 검색 링크 : ", link);
118 +
119 + // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음
120 + // -> 글자수 제한(1024)도 있으므로 제거
121 + link = link.slice(0, link.indexOf('&search'));
122 +
123 + try {
124 + var price = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(' + i + ') > dd > ul > li.prd-price > span', element => {
125 + return element.textContent;
126 + });
127 + // console.log("펜카페 검색 결과 가격 : ", price);
128 + } catch {
129 + // 품절이라서 금액정보가 없을 경우 "SOLD OUT"으로 표시
130 + price = "SOLD OUT";
131 + }
132 +
133 + result += `[${title}](${link}) - ${price}` + '\n';
134 + } catch {
135 + if (i == 1) {
136 + // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시
137 + result += "검색결과 없음" + '\n';
138 + break searchLoop;
139 + } else {
140 + // 제품 개수가 4개 이하인 경우
141 + break searchLoop;
142 + }
142 } 143 }
143 } 144 }
144 - } 145 + break site;
145 - break site; 146 + case 2:
146 - case 2: 147 + // 블루블랙
147 - // 블루블랙
148 - try {
149 - var blueblack_url = url + search + "&order_by=priceasc"
150 - await page.goto(blueblack_url);
151 - // console.log("blublack crawling");
152 -
153 - // 페이지 로딩 대기
154 - await page.waitForSelector('#contents > div:nth-child(4) > ul > li:nth-child(4) > div.description > p.name > a > span:nth-child(2)');
155 - } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지
156 -
157 - // 검색 결과 가져오기 (최대 4개)
158 - searchLoop : for (var i = 1; i <= 4; i++) {
159 try { 148 try {
160 - var title = await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child('+i+') > div.description > p.name > a > span:nth-child(2)', element => { 149 + var blueblack_url = url + search + "&order_by=priceasc";
161 - return element.textContent; 150 + await page.goto(blueblack_url);
162 - }); 151 + // console.log("blublack crawling");
163 - // console.log("블루블랙 검색 결과 제품명 : ", title);
164 -
165 - var link = await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child('+i+') > div.description > p.name > a', element => {
166 - return element.href;
167 - });
168 - // console.log("블루블랙 검색 링크 : ", link);
169 -
170 - // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음
171 - // -> 글자수 제한(1024)도 있으므로 제거
172 - link = link.slice(0, link.indexOf('&cate_no'));
173 152
153 + // 페이지 로딩 대기
154 + await page.waitForSelector('#contents > div:nth-child(4) > ul > li:nth-child(4) > div.description > p.name > a > span:nth-child(2)');
155 + } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지
156 +
157 + // 검색 결과 가져오기 (최대 4개)
158 + searchLoop: for (var i = 1; i <= 4; i++) {
174 try { 159 try {
175 - // 품절 아이콘이 있는지 확인 160 + var title = await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child(' + i + ') > div.description > p.name > a > span:nth-child(2)', element => {
176 - await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child('+i+') > div.description > div.status > div > img', element => { 161 + return element.textContent;
177 - return element.getAttribute("src");
178 }); 162 });
163 + // console.log("블루블랙 검색 결과 제품명 : ", title);
164 +
165 + var link = await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child(' + i + ') > div.description > p.name > a', element => {
166 + return element.href;
167 + });
168 + // console.log("블루블랙 검색 링크 : ", link);
169 +
170 + // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음
171 + // -> 글자수 제한(1024)도 있으므로 제거
172 + link = link.slice(0, link.indexOf('&cate_no'));
179 173
180 - var price = 'SOLD OUT';
181 - } catch {
182 try { 174 try {
183 - // 품절 아이콘이 없을 경우 175 + // 품절 아이콘이 있는지 확인
184 - var price = await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child('+i+') > div.description > ul > li:nth-child(3) > span:nth-child(2)', element => { 176 + await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child(' + i + ') > div.description > div.status > div > img', element => {
185 - return element.textContent; 177 + return element.getAttribute("src");
186 }); 178 });
179 +
180 + var price = 'SOLD OUT';
187 } catch { 181 } catch {
188 - var price = '0원'; 182 + try {
183 + // 품절 아이콘이 없을 경우
184 + var price = await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child(' + i + ') > div.description > ul > li:nth-child(3) > span:nth-child(2)', element => {
185 + return element.textContent;
186 + });
187 + } catch {
188 + var price = '0원';
189 + }
190 + }
191 + // console.log("블루블랙 검색 결과 가격 : ", price);
192 +
193 + result += `[${title}](${link}) - ${price}` + '\n';
194 + } catch {
195 + if (i == 1) {
196 + // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시
197 + result += "검색결과 없음" + '\n';
198 + break searchLoop;
199 + } else {
200 + // 제품 개수가 4개 이하인 경우
201 + break searchLoop;
189 } 202 }
190 - }
191 - // console.log("블루블랙 검색 결과 가격 : ", price);
192 -
193 - result += `[${title}](${link}) - ${price}` + '\n';
194 - } catch {
195 - if (i == 1) {
196 - // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시
197 - result += "검색결과 없음" + '\n';
198 - break searchLoop;
199 - } else {
200 - // 제품 개수가 4개 이하인 경우
201 - break searchLoop;
202 } 203 }
203 } 204 }
204 - } 205 + break site;
205 - break site; 206 + case 3:
206 - case 3: 207 + // 재팬나인
207 - // 재팬나인
208 - try {
209 - await page.goto(url);
210 - // console.log("japannine crawling");
211 -
212 - var japannine_url = url + search + "&sort=price"
213 - await page.goto(japannine_url);
214 - // console.log("japannine crawling");
215 -
216 - // 페이지 로딩 대기
217 - await page.waitForSelector('#mk_search_production > tbody > tr:nth-child(17) > td:nth-child(3) > a');
218 - } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지
219 -
220 - // 검색 결과 가져오기 (최대 4개)
221 - searchLoop : for (var i = 1; i <= 4; i++) {
222 try { 208 try {
223 - var title = await page.$eval('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td:nth-child(3) > a', element => { 209 + await page.goto(url);
224 - return element.textContent; 210 + // console.log("japannine crawling");
225 - }); 211 +
226 - // console.log("재팬나인 검색 결과 제품명 : ", title); 212 + var japannine_url = url + search + "&sort=price";
227 - 213 + await page.goto(japannine_url);
228 - // 재팬나인 구조상 제품명 앞에 항상 '/n'이 붙는다 -> 제거 214 + // console.log("japannine crawling");
229 - title = title.slice(1);
230 - // 재팬나인 구조상 제품명 앞과 뒤에 [쿠폰적용 || 주문예약상품]이 붙는 경우가 많음 -> 제거
231 - if (title.indexOf('[') == 0) { title = title.slice(title.indexOf(']')+1); }
232 - if (title.lastIndexOf(']') == title.length-1) { title = title.slice(0, title.lastIndexOf('[')); }
233 - if (title.indexOf('{') == 0) { title = title.slice(title.indexOf('}')+1); }
234 - if (title.lastIndexOf('}') == title.length-1) { title = title.slice(0, title.lastIndexOf('{')); }
235 -
236 - var link = await page.$eval('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td:nth-child(3) > a', element => {
237 - return element.href;
238 - });
239 - // console.log("재팬나인 검색 링크 : ", link);
240 -
241 - // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음
242 - // -> 글자수 제한(1024)도 있으므로 제거
243 - link = link.slice(0, link.indexOf('&search'));
244 215
216 + // 페이지 로딩 대기
217 + await page.waitForSelector('#mk_search_production > tbody > tr:nth-child(17) > td:nth-child(3) > a');
218 + } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지
219 +
220 + // 검색 결과 가져오기 (최대 4개)
221 + searchLoop: for (var i = 1; i <= 4; i++) {
245 try { 222 try {
246 - // 품절 아이콘이 있는지 확인 223 + var title = await page.$eval('#mk_search_production > tbody > tr:nth-child(' + (5 + ((i - 1) * 4)) + ') > td:nth-child(3) > a', element => {
247 - var img_src = await page.$eval('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td:nth-child(6) > img', element => { 224 + return element.textContent;
248 - return element.getAttribute("src");
249 }); 225 });
226 + // console.log("재팬나인 검색 결과 제품명 : ", title);
250 227
251 - if (img_src.indexOf('no_amount0') != -1) { var price = 'SOLD OUT'; } 228 + // 재팬나인 구조상 제품명 앞에 항상 '/n'이 붙는다 -> 제거
252 - } catch { 229 + title = title.slice(1);
253 - // 품절 아이콘이 없을 경우 230 + // 재팬나인 구조상 제품명 앞과 뒤에 [쿠폰적용 || 주문예약상품]이 붙는 경우가 많음 -> 제거
254 - var price = await page.$eval('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td.brandprice > span', element => { 231 + if (title.indexOf('[') == 0) { title = title.slice(title.indexOf(']') + 1); }
255 - return element.textContent; 232 + if (title.lastIndexOf(']') == title.length - 1) { title = title.slice(0, title.lastIndexOf('[')); }
233 + if (title.indexOf('{') == 0) { title = title.slice(title.indexOf('}') + 1); }
234 + if (title.lastIndexOf('}') == title.length - 1) { title = title.slice(0, title.lastIndexOf('{')); }
235 +
236 + var link = await page.$eval('#mk_search_production > tbody > tr:nth-child(' + (5 + ((i - 1) * 4)) + ') > td:nth-child(3) > a', element => {
237 + return element.href;
256 }); 238 });
239 + // console.log("재팬나인 검색 링크 : ", link);
257 240
258 - // 재팬나인 구조상 금액 뒤에 (옵션에 따라 변동)이 붙는 경우가 있다 -> 제거 241 + // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음
259 - if (price.indexOf('(') != -1) { price = price.slice(0, price.indexOf('원')+1); } 242 + // -> 글자수 제한(1024)도 있으므로 제거
260 - } 243 + link = link.slice(0, link.indexOf('&search'));
261 - // console.log("재팬나인 검색 결과 가격 : ", price); 244 +
262 - 245 + try {
263 - result += `[${title}](${link}) - ${price}` + '\n'; 246 + // 품절 아이콘이 있는지 확인
264 - } catch { 247 + var img_src = await page.$eval('#mk_search_production > tbody > tr:nth-child(' + (5 + ((i - 1) * 4)) + ') > td:nth-child(6) > img', element => {
265 - if (i == 1) { 248 + return element.getAttribute("src");
266 - // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 249 + });
267 - result += "검색결과 없음" + '\n'; 250 +
268 - break searchLoop; 251 + if (img_src.indexOf('no_amount0') != -1) { var price = 'SOLD OUT'; }
269 - } else { 252 + } catch {
270 - // 제품 개수가 4개 이하인 경우 253 + // 품절 아이콘이 없을 경우
271 - break searchLoop; 254 + var price = await page.$eval('#mk_search_production > tbody > tr:nth-child(' + (5 + ((i - 1) * 4)) + ') > td.brandprice > span', element => {
255 + return element.textContent;
256 + });
257 +
258 + // 재팬나인 구조상 금액 뒤에 (옵션에 따라 변동)이 붙는 경우가 있다 -> 제거
259 + if (price.indexOf('(') != -1) { price = price.slice(0, price.indexOf('원') + 1); }
260 + }
261 + // console.log("재팬나인 검색 결과 가격 : ", price);
262 +
263 + result += `[${title}](${link}) - ${price}` + '\n';
264 + } catch {
265 + if (i == 1) {
266 + // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시
267 + result += "검색결과 없음" + '\n';
268 + break searchLoop;
269 + } else {
270 + // 제품 개수가 4개 이하인 경우
271 + break searchLoop;
272 + }
272 } 273 }
273 } 274 }
274 - } 275 + break site;
275 - break site;
276 } 276 }
277 - 277 +
278 return result; 278 return result;
279 }); 279 });
280 - })) 280 + }));
281 }); 281 });
282 282
283 // 검색 결과 챗봇에 출력 283 // 검색 결과 챗봇에 출력
284 let Commands = new Discord.MessageEmbed() 284 let Commands = new Discord.MessageEmbed()
285 - .setTitle(`${search}에 대한 검색 결과`) 285 +
286 - .setColor("E5D49A") 286 + .setTitle(`${search}에 대한 검색 결과`)
287 - // 베스트펜 검색 결과 (ex. 제품명(링크) - 금액) 287 + .setColor("E5D49A")
288 - .addField('베스트펜', `${results[0].slice(0, 1023)}`) 288 + // 베스트펜 검색 결과 (ex. 제품명(링크) - 금액)
289 - // 펜카페 검색 결과 289 + .addField('베스트펜', `${results[0].slice(0, 1023)}`)
290 - .addField('펜카페', `${results[1].slice(0, 1023)}`) 290 + // 펜카페 검색 결과
291 - // 블루블랙 검색 결과 291 + .addField('펜카페', `${results[1].slice(0, 1023)}`)
292 - .addField('블루블랙', `${results[2].slice(0, 1023)}`) 292 + // 블루블랙 검색 결과
293 - // 재팬나인 검색 결과 293 + .addField('블루블랙', `${results[2].slice(0, 1023)}`)
294 - .addField('재팬나인', `${results[3].slice(0, 1023)}`) 294 + // 재팬나인 검색 결과
295 + .addField('재팬나인', `${results[3].slice(0, 1023)}`);
296 +
295 msg.reply({ embeds: [Commands] }); 297 msg.reply({ embeds: [Commands] });
296 } else { 298 } else {
297 msg.reply("검색어가 없습니다. 검색어를 추가해서 다시 입력해주세요."); 299 msg.reply("검색어가 없습니다. 검색어를 추가해서 다시 입력해주세요.");
...@@ -300,8 +302,9 @@ exports.run = async (client, msg, args, prefix) => { ...@@ -300,8 +302,9 @@ exports.run = async (client, msg, args, prefix) => {
300 302
301 exports.config = { 303 exports.config = {
302 name: '문구', 304 name: '문구',
305 +
303 aliases: ['문구류', '가격비교', 'stationery', 'search'], 306 aliases: ['문구류', '가격비교', 'stationery', 'search'],
304 - category: ['stationery'], 307 + category: ['Stationery'],
305 des: ['채팅 내용에 대한 검색결과를 보여줍니다.'], 308 des: ['채팅 내용에 대한 검색결과를 보여줍니다.'],
306 use: ['!문구 <채팅>'] 309 use: ['!문구 <채팅>']
307 }; 310 };
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -11,7 +11,7 @@ client.once('ready', () => { ...@@ -11,7 +11,7 @@ client.once('ready', () => {
11 11
12 client.commands = new Discord.Collection(); 12 client.commands = new Discord.Collection();
13 client.aliases = new Discord.Collection(); 13 client.aliases = new Discord.Collection();
14 -client.category = ['example', 'stationery', 'translate', 'ocr']; 14 +client.category = ['Help', 'Stationery', 'Translate', 'Ocr'];
15 15
16 fs.readdirSync("./Commands/").forEach(dir => { 16 fs.readdirSync("./Commands/").forEach(dir => {
17 const Filter = fs.readdirSync(`./Commands/${dir}`).filter(f => f.endsWith(".js")); 17 const Filter = fs.readdirSync(`./Commands/${dir}`).filter(f => f.endsWith(".js"));
......