dongnelibrary 0.2.9 → 0.2.10
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/package.json +1 -1
- package/src/cli.js +103 -133
- package/src/dongnelibrary.js +66 -109
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const Configstore = require("configstore");
|
|
3
|
-
const _ = require("lodash");
|
|
4
3
|
const colors = require("colors");
|
|
5
4
|
const figlet = require("figlet");
|
|
6
|
-
const fp = require("lodash/fp");
|
|
7
5
|
const inquirer = require("inquirer");
|
|
8
6
|
const program = require("commander");
|
|
9
7
|
const dl = require("./dongnelibrary");
|
|
@@ -11,11 +9,13 @@ const util = require("./util");
|
|
|
11
9
|
const pkg = require("../package.json");
|
|
12
10
|
|
|
13
11
|
const conf = new Configstore(pkg.name, {});
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
|
|
13
|
+
const config = {
|
|
14
|
+
getLibrary: () => conf.get("library"),
|
|
15
|
+
setLibrary: (name) => conf.set("library", name),
|
|
16
|
+
getTitle: () => conf.get("title") ?? "javascript",
|
|
17
|
+
setTitle: (title) => conf.set("title", title),
|
|
18
|
+
};
|
|
19
19
|
|
|
20
20
|
const introMessage = (msg) => {
|
|
21
21
|
console.log(
|
|
@@ -35,151 +35,121 @@ program
|
|
|
35
35
|
.option("-t, --title [title]", "a part of book title")
|
|
36
36
|
.parse(process.argv);
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
let result = "";
|
|
38
|
+
const cutTail = (str, tail) => {
|
|
40
39
|
const index = str.indexOf(tail);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
return index === -1 ? str : str.substring(0, index);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const MARKS = {
|
|
44
|
+
ok: "✓ ",
|
|
45
|
+
notOk: "✖ ",
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const printBooks = ({ booklist }) => {
|
|
49
|
+
for (const { libraryName, exist, title, bookUrl } of booklist) {
|
|
50
|
+
const mark = exist ? ` ${MARKS.ok} ` : ` ${colors.red(MARKS.notOk)} `;
|
|
51
|
+
console.log(`${cutTail(libraryName, "도서관")}${mark}${title}`);
|
|
52
|
+
if (bookUrl) {
|
|
53
|
+
console.log(` → ${colors.cyan(bookUrl)}`);
|
|
54
|
+
}
|
|
45
55
|
}
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const okMark = "✓ ";
|
|
50
|
-
const notokMark = "✖ ";
|
|
51
|
-
|
|
52
|
-
function printBooks(book) {
|
|
53
|
-
_.each(book.booklist, (book) => {
|
|
54
|
-
console.log(
|
|
55
|
-
cutTail(book.libraryName, "도서관") +
|
|
56
|
-
(book.exist ? " " + okMark + " " : " " + colors.red(notokMark) + " ") +
|
|
57
|
-
book.title +
|
|
58
|
-
" ",
|
|
59
|
-
);
|
|
60
|
-
});
|
|
61
|
-
}
|
|
56
|
+
};
|
|
62
57
|
|
|
63
|
-
|
|
58
|
+
const printAllLibraryNames = () => {
|
|
64
59
|
const libs = dl.getLibraryNames();
|
|
65
|
-
libs.forEach((name) =>
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const msg = `모두 ${libs.length} 개의 도서관`;
|
|
69
|
-
console.log(colors.green(msg));
|
|
70
|
-
}
|
|
60
|
+
libs.forEach((name) => console.log(name));
|
|
61
|
+
console.log(colors.green(`모두 ${libs.length} 개의 도서관`));
|
|
62
|
+
};
|
|
71
63
|
|
|
72
64
|
const getFullLibraryName = (str) =>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
function search(option, bookCallback, allBookCallback) {
|
|
76
|
-
dl.search(
|
|
77
|
-
{
|
|
78
|
-
title: option.title,
|
|
79
|
-
libraryName: getLibraries(option.libraryName),
|
|
80
|
-
},
|
|
81
|
-
(err, book) => {
|
|
82
|
-
if (err) {
|
|
83
|
-
err.msg = err.msg || "Unknown Error";
|
|
84
|
-
if (bookCallback) {
|
|
85
|
-
bookCallback(err);
|
|
86
|
-
}
|
|
87
|
-
} else {
|
|
88
|
-
if (bookCallback) {
|
|
89
|
-
bookCallback(null, book);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
(err, books) => {
|
|
94
|
-
if (err) {
|
|
95
|
-
err.msg = err.msg || "Unknown Error";
|
|
96
|
-
if (allBookCallback) {
|
|
97
|
-
allBookCallback(err);
|
|
98
|
-
}
|
|
99
|
-
} else {
|
|
100
|
-
if (allBookCallback) {
|
|
101
|
-
allBookCallback(null, books);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
);
|
|
106
|
-
}
|
|
65
|
+
dl.getLibraryNames().find((name) => name.includes(str));
|
|
107
66
|
|
|
108
67
|
const getBookCount = (results) =>
|
|
109
|
-
|
|
110
|
-
results,
|
|
111
|
-
(memo, book) =>
|
|
112
|
-
memo +
|
|
113
|
-
(book && book.booklist && book.booklist.length
|
|
114
|
-
? book.booklist.length
|
|
115
|
-
: 0),
|
|
116
|
-
0,
|
|
117
|
-
);
|
|
68
|
+
results.reduce((sum, book) => sum + (book?.booklist?.length ?? 0), 0);
|
|
118
69
|
|
|
119
|
-
const getLibraryFullNameList =
|
|
120
|
-
util
|
|
121
|
-
|
|
122
|
-
|
|
70
|
+
const getLibraryFullNameList = (libraryName) =>
|
|
71
|
+
util
|
|
72
|
+
.getArrayFromCommaSeparatedString(libraryName)
|
|
73
|
+
.filter((name) => getFullLibraryName(name));
|
|
123
74
|
|
|
124
75
|
const getLibraries = (libraryName) =>
|
|
125
76
|
libraryName ? getLibraryFullNameList(libraryName) : dl.getLibraryNames();
|
|
126
77
|
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
78
|
+
const searchLibraries = ({ title, libraryName }) =>
|
|
79
|
+
new Promise((resolve) => {
|
|
80
|
+
const results = [];
|
|
81
|
+
dl.search(
|
|
82
|
+
{ title, libraryName: getLibraries(libraryName) },
|
|
83
|
+
(err, book) => {
|
|
84
|
+
if (err) {
|
|
85
|
+
console.log(err.msg ?? "Unknown Error");
|
|
86
|
+
} else {
|
|
87
|
+
printBooks(book);
|
|
88
|
+
results.push(book);
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
(err, allBooks) => {
|
|
92
|
+
if (err) {
|
|
93
|
+
console.log("Error, Can't access detail information");
|
|
94
|
+
resolve([]);
|
|
95
|
+
} else {
|
|
96
|
+
resolve(allBooks);
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const printSearchSummary = (results) => {
|
|
103
|
+
const bookCount = getBookCount(results);
|
|
104
|
+
console.log(
|
|
105
|
+
colors.green(`${results.length} 개의 도서관에서 ${bookCount} 권 검색됨`),
|
|
106
|
+
);
|
|
133
107
|
};
|
|
134
108
|
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
),
|
|
143
|
-
|
|
144
|
-
|
|
109
|
+
const promptForSearchOptions = async () => {
|
|
110
|
+
introMessage("Dongne Library");
|
|
111
|
+
const { library, title } = await inquirer.prompt([
|
|
112
|
+
{
|
|
113
|
+
type: "list",
|
|
114
|
+
name: "library",
|
|
115
|
+
message: "도서관 이름은?",
|
|
116
|
+
choices: dl.getLibraryNames(),
|
|
117
|
+
default: config.getLibrary(),
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
type: "input",
|
|
121
|
+
name: "title",
|
|
122
|
+
message: "책 이름은?",
|
|
123
|
+
default: config.getTitle(),
|
|
124
|
+
},
|
|
125
|
+
]);
|
|
126
|
+
|
|
127
|
+
config.setLibrary(library);
|
|
128
|
+
config.setTitle(title);
|
|
129
|
+
|
|
130
|
+
return { libraryName: library, title };
|
|
145
131
|
};
|
|
146
132
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
133
|
+
const activate = async () => {
|
|
134
|
+
const { libraryList, interactive, libraryName, title } = program;
|
|
135
|
+
|
|
136
|
+
if (libraryList) {
|
|
137
|
+
printAllLibraryNames();
|
|
150
138
|
return;
|
|
151
139
|
}
|
|
152
140
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
choices: dl.getLibraryNames(),
|
|
162
|
-
default: getDefaultLibrary(),
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
type: "input",
|
|
166
|
-
name: "title",
|
|
167
|
-
message: "책 이름은?",
|
|
168
|
-
default: getDefaultTitle(),
|
|
169
|
-
},
|
|
170
|
-
])
|
|
171
|
-
.then((answers) => {
|
|
172
|
-
option.libraryName = answers["library"];
|
|
173
|
-
option.title = answers["title"];
|
|
174
|
-
setDefaultLibrary(option.libraryName);
|
|
175
|
-
setDefaultTitle(option.title);
|
|
176
|
-
if (option.libraryName && option.title) {
|
|
177
|
-
search(option, processOneLibrary, processLibraries);
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
} else if (option.libraryName && option.title) {
|
|
181
|
-
search(option, processOneLibrary, processLibraries);
|
|
141
|
+
let searchOptions;
|
|
142
|
+
|
|
143
|
+
if (interactive) {
|
|
144
|
+
searchOptions = await promptForSearchOptions();
|
|
145
|
+
} else if (libraryName && title) {
|
|
146
|
+
searchOptions = { libraryName, title };
|
|
147
|
+
} else {
|
|
148
|
+
return;
|
|
182
149
|
}
|
|
183
|
-
}
|
|
184
150
|
|
|
185
|
-
|
|
151
|
+
const results = await searchLibraries(searchOptions);
|
|
152
|
+
printSearchSummary(results);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
activate();
|
package/src/dongnelibrary.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const _ = require("lodash");
|
|
2
|
-
const fp = require("lodash/fp");
|
|
3
1
|
const gg = require("./library/gg");
|
|
4
2
|
const gunpo = require("./library/gunpo");
|
|
5
3
|
const hscity = require("./library/hscity");
|
|
@@ -7,134 +5,93 @@ const osan = require("./library/osan");
|
|
|
7
5
|
const snlib = require("./library/snlib");
|
|
8
6
|
const suwon = require("./library/suwon");
|
|
9
7
|
const yongin = require("./library/yongin");
|
|
10
|
-
const async = require("async");
|
|
11
8
|
const util = require("./util.js");
|
|
12
9
|
|
|
13
|
-
const
|
|
10
|
+
const LIBRARY_MODULES = [gg, gunpo, hscity, osan, snlib, suwon, yongin];
|
|
11
|
+
|
|
12
|
+
const libraryList = LIBRARY_MODULES.flatMap((module) =>
|
|
13
|
+
module.getLibraryNames().map((name) => ({
|
|
14
|
+
name,
|
|
15
|
+
search: module.search,
|
|
16
|
+
})),
|
|
17
|
+
);
|
|
14
18
|
|
|
15
19
|
const getLibraryNames = () => util.getLibraryNames(libraryList);
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
const UNKNOWN_LIBRARY = {
|
|
22
|
+
name: "Unknown",
|
|
23
|
+
search: (opt, getBook) => getBook?.({ msg: "Unknown library name" }),
|
|
24
|
+
};
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
libraryList.push({
|
|
23
|
-
name,
|
|
24
|
-
search: library.search,
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
}
|
|
26
|
+
const getLibraryFunction = (libraryName) =>
|
|
27
|
+
libraryList.find((lib) => lib.name === libraryName) ?? UNKNOWN_LIBRARY;
|
|
29
28
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
return found
|
|
33
|
-
? found
|
|
34
|
-
: {
|
|
35
|
-
search: (opt, getBook) => {
|
|
36
|
-
if (getBook) {
|
|
37
|
-
getBook({ msg: "Unknown library name" });
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
name: "Unknown",
|
|
41
|
-
};
|
|
42
|
-
};
|
|
29
|
+
const completeLibraryName = (str) =>
|
|
30
|
+
getLibraryNames().find((name) => name.includes(str)) ?? "";
|
|
43
31
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return found ? found : "";
|
|
47
|
-
}
|
|
32
|
+
const isValidLibraryName = (libraryName) =>
|
|
33
|
+
libraryList.some((lib) => lib.name === libraryName);
|
|
48
34
|
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
return
|
|
52
|
-
|
|
35
|
+
const getLibArray = (libraryName) => {
|
|
36
|
+
const names = Array.isArray(libraryName) ? libraryName : [libraryName];
|
|
37
|
+
return names
|
|
38
|
+
.map((name) => completeLibraryName(name))
|
|
39
|
+
.filter((fullName) => isValidLibraryName(fullName))
|
|
40
|
+
.map((fullName) => getLibraryFunction(fullName));
|
|
41
|
+
};
|
|
53
42
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return isValidLibraryName(fullName) ? getLibraryFunction(fullName) : null;
|
|
59
|
-
}),
|
|
60
|
-
_.compact,
|
|
61
|
-
])(Array.isArray(libraryName) ? libraryName : [libraryName]);
|
|
62
|
-
}
|
|
43
|
+
const getSortedBooks = (books) =>
|
|
44
|
+
books
|
|
45
|
+
.map(({ libraryName, title, exist, bookUrl }) => ({ libraryName, title, exist, bookUrl }))
|
|
46
|
+
.sort((a, b) => (a.exist === b.exist ? 0 : a.exist ? -1 : 1));
|
|
63
47
|
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
libraryName:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
48
|
+
const searchLibrary = (lib, title) =>
|
|
49
|
+
new Promise((resolve) => {
|
|
50
|
+
lib.search({ title, libraryName: lib.name }, (err, data) => {
|
|
51
|
+
if (err) {
|
|
52
|
+
resolve({ error: err });
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (!data?.booklist) {
|
|
56
|
+
resolve({ error: { msg: "invalid Data response" } });
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
resolve({
|
|
60
|
+
result: {
|
|
61
|
+
title,
|
|
62
|
+
libraryName: lib.name,
|
|
63
|
+
totalBookCount: data.totalBookCount,
|
|
64
|
+
startPage: data.startPage,
|
|
65
|
+
booklist: getSortedBooks(data.booklist),
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
|
72
70
|
|
|
73
|
-
|
|
71
|
+
const search = (opt, getBook, getAllBooks) => {
|
|
74
72
|
if (!opt || (!getBook && !getAllBooks)) {
|
|
75
73
|
console.log("invalid search options");
|
|
76
74
|
return;
|
|
77
75
|
}
|
|
78
76
|
|
|
79
|
-
const title = opt
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
_.each(getLibArray(opt.libraryName), (lib) => {
|
|
83
|
-
tasks.push((callback) => {
|
|
84
|
-
lib.search(
|
|
85
|
-
{
|
|
86
|
-
title: title,
|
|
87
|
-
libraryName: lib.name,
|
|
88
|
-
},
|
|
89
|
-
(err, data) => {
|
|
90
|
-
if (err) {
|
|
91
|
-
if (getBook) {
|
|
92
|
-
getBook(err);
|
|
93
|
-
}
|
|
94
|
-
callback(err);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
if (!data || !data.booklist) {
|
|
98
|
-
if (getBook) {
|
|
99
|
-
getBook({ msg: "invalid Data response" });
|
|
100
|
-
}
|
|
101
|
-
callback({ msg: "invalid Data response" });
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const bookObj = {
|
|
106
|
-
title: title,
|
|
107
|
-
libraryName: lib.name,
|
|
108
|
-
totalBookCount: data.totalBookCount,
|
|
109
|
-
startPage: data.startPage,
|
|
110
|
-
booklist: getSortedBooks(data.booklist),
|
|
111
|
-
};
|
|
77
|
+
const { title, libraryName } = opt;
|
|
78
|
+
const libraries = getLibArray(libraryName);
|
|
112
79
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
);
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
async.parallel(tasks, (err, results) => {
|
|
123
|
-
if (getAllBooks) {
|
|
124
|
-
if (err) {
|
|
125
|
-
getAllBooks(err);
|
|
126
|
-
} else {
|
|
127
|
-
getAllBooks(null, results);
|
|
128
|
-
}
|
|
80
|
+
const promises = libraries.map(async (lib) => {
|
|
81
|
+
const { error, result } = await searchLibrary(lib, title);
|
|
82
|
+
if (error) {
|
|
83
|
+
getBook?.(error);
|
|
84
|
+
return null;
|
|
129
85
|
}
|
|
86
|
+
getBook?.(null, result);
|
|
87
|
+
return result;
|
|
130
88
|
});
|
|
131
|
-
}
|
|
132
89
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
90
|
+
Promise.all(promises).then((results) => {
|
|
91
|
+
const validResults = results.filter(Boolean);
|
|
92
|
+
getAllBooks?.(null, validResults);
|
|
93
|
+
});
|
|
94
|
+
};
|
|
138
95
|
|
|
139
96
|
module.exports = {
|
|
140
97
|
search,
|