dongnelibrary 0.2.9 → 0.2.11

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 CHANGED
@@ -3,7 +3,7 @@
3
3
  "engines": {
4
4
  "node": ">=18.0.0"
5
5
  },
6
- "version": "0.2.9",
6
+ "version": "0.2.11",
7
7
  "description": "책을 빌릴 수 있는지 확인한다.",
8
8
  "main": "src/dongnelibrary.js",
9
9
  "bin": {
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
- const getDefaultLibrary = () => conf.get("library");
15
- const setDefaultLibrary = (name) => conf.set("library", name);
16
- const getDefaultTitle = () =>
17
- conf.get("title") === undefined ? "javascript" : conf.get("title");
18
- const setDefaultTitle = (title) => conf.set("title", title);
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,124 @@ program
35
35
  .option("-t, --title [title]", "a part of book title")
36
36
  .parse(process.argv);
37
37
 
38
- function cutTail(str, tail) {
39
- let result = "";
38
+ const cutTail = (str, tail) => {
40
39
  const index = str.indexOf(tail);
41
- if (index === -1) {
42
- result = str;
43
- } else {
44
- result = str.substring(0, index);
40
+ return index === -1 ? str : str.substring(0, index);
41
+ };
42
+
43
+ const MARKS = {
44
+ ok: "✓ ",
45
+ notOk: "✖ ",
46
+ };
47
+
48
+ const printBooks = ({ booklist, homeUrl }) => {
49
+ if (homeUrl) {
50
+ console.log(colors.yellow(`[${homeUrl}]`));
45
51
  }
46
- return result;
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
- }
52
+ for (const { libraryName, exist, title, bookUrl } of booklist) {
53
+ const mark = exist ? ` ${MARKS.ok} ` : ` ${colors.red(MARKS.notOk)} `;
54
+ console.log(`${cutTail(libraryName, "도서관")}${mark}${title}`);
55
+ if (bookUrl) {
56
+ console.log(` → ${colors.cyan(bookUrl)}`);
57
+ }
58
+ }
59
+ };
62
60
 
63
- function printAllLibraryName() {
61
+ const printAllLibraryNames = () => {
64
62
  const libs = dl.getLibraryNames();
65
- libs.forEach((name) => {
66
- console.log(name);
67
- });
68
- const msg = `모두 ${libs.length} 개의 도서관`;
69
- console.log(colors.green(msg));
70
- }
63
+ libs.forEach((name) => console.log(name));
64
+ console.log(colors.green(`모두 ${libs.length} 개의 도서관`));
65
+ };
71
66
 
72
67
  const getFullLibraryName = (str) =>
73
- _.find(dl.getLibraryNames(), (name) => name.indexOf(str) >= 0);
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
- }
68
+ dl.getLibraryNames().find((name) => name.includes(str));
107
69
 
108
70
  const getBookCount = (results) =>
109
- _.reduce(
110
- results,
111
- (memo, book) =>
112
- memo +
113
- (book && book.booklist && book.booklist.length
114
- ? book.booklist.length
115
- : 0),
116
- 0,
117
- );
71
+ results.reduce((sum, book) => sum + (book?.booklist?.length ?? 0), 0);
118
72
 
119
- const getLibraryFullNameList = _.flow([
120
- util.getArrayFromCommaSeparatedString,
121
- fp.filter((shortLibraryName) => getFullLibraryName(shortLibraryName)),
122
- ]);
73
+ const getLibraryFullNameList = (libraryName) =>
74
+ util
75
+ .getArrayFromCommaSeparatedString(libraryName)
76
+ .filter((name) => getFullLibraryName(name));
123
77
 
124
78
  const getLibraries = (libraryName) =>
125
79
  libraryName ? getLibraryFullNameList(libraryName) : dl.getLibraryNames();
126
80
 
127
- const processOneLibrary = (err, book) => {
128
- if (err) {
129
- console.log(err.msg);
130
- } else {
131
- printBooks(book);
132
- }
81
+ const searchLibraries = ({ title, libraryName }) =>
82
+ new Promise((resolve) => {
83
+ const results = [];
84
+ dl.search(
85
+ { title, libraryName: getLibraries(libraryName) },
86
+ (err, book) => {
87
+ if (err) {
88
+ console.log(err.msg ?? "Unknown Error");
89
+ } else {
90
+ printBooks(book);
91
+ results.push(book);
92
+ }
93
+ },
94
+ (err, allBooks) => {
95
+ if (err) {
96
+ console.log("Error, Can't access detail information");
97
+ resolve([]);
98
+ } else {
99
+ resolve(allBooks);
100
+ }
101
+ },
102
+ );
103
+ });
104
+
105
+ const printSearchSummary = (results) => {
106
+ const bookCount = getBookCount(results);
107
+ console.log(
108
+ colors.green(`${results.length} 개의 도서관에서 ${bookCount} 권 검색됨`),
109
+ );
133
110
  };
134
111
 
135
- const processLibraries = (err, results) => {
136
- if (err) {
137
- console.log("Error, Can't access detail information");
138
- } else {
139
- console.log(
140
- colors.green(
141
- `${results.length} 개의 도서관에서 ${getBookCount(results)} 권 검색됨`,
142
- ),
143
- );
144
- }
112
+ const promptForSearchOptions = async () => {
113
+ introMessage("Dongne Library");
114
+ const { library, title } = await inquirer.prompt([
115
+ {
116
+ type: "list",
117
+ name: "library",
118
+ message: "도서관 이름은?",
119
+ choices: dl.getLibraryNames(),
120
+ default: config.getLibrary(),
121
+ },
122
+ {
123
+ type: "input",
124
+ name: "title",
125
+ message: "책 이름은?",
126
+ default: config.getTitle(),
127
+ },
128
+ ]);
129
+
130
+ config.setLibrary(library);
131
+ config.setTitle(title);
132
+
133
+ return { libraryName: library, title };
145
134
  };
146
135
 
147
- function activate(option) {
148
- if (option.libraryList) {
149
- printAllLibraryName(option);
136
+ const activate = async () => {
137
+ const { libraryList, interactive, libraryName, title } = program;
138
+
139
+ if (libraryList) {
140
+ printAllLibraryNames();
150
141
  return;
151
142
  }
152
143
 
153
- if (option.interactive) {
154
- introMessage("Dongne Library");
155
- inquirer
156
- .prompt([
157
- {
158
- type: "list",
159
- name: "library",
160
- message: "도서관 이름은?",
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);
144
+ let searchOptions;
145
+
146
+ if (interactive) {
147
+ searchOptions = await promptForSearchOptions();
148
+ } else if (libraryName && title) {
149
+ searchOptions = { libraryName, title };
150
+ } else {
151
+ return;
182
152
  }
183
- }
184
153
 
185
- activate(program);
154
+ const results = await searchLibraries(searchOptions);
155
+ printSearchSummary(results);
156
+ };
157
+
158
+ activate();
@@ -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,95 @@ 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 libraryList = [];
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
+ homeUrl: module.homeUrl,
17
+ })),
18
+ );
14
19
 
15
20
  const getLibraryNames = () => util.getLibraryNames(libraryList);
16
21
 
17
- function makeLibraryList() {
18
- const library = [gg, gunpo, hscity, osan, snlib, suwon, yongin];
22
+ const UNKNOWN_LIBRARY = {
23
+ name: "Unknown",
24
+ search: (opt, getBook) => getBook?.({ msg: "Unknown library name" }),
25
+ };
19
26
 
20
- _.each(library, (library) => {
21
- _.each(library.getLibraryNames(), (name) => {
22
- libraryList.push({
23
- name,
24
- search: library.search,
25
- });
26
- });
27
- });
28
- }
27
+ const getLibraryFunction = (libraryName) =>
28
+ libraryList.find((lib) => lib.name === libraryName) ?? UNKNOWN_LIBRARY;
29
29
 
30
- const getLibraryFunction = (libraryName) => {
31
- const found = _.find(libraryList, (lib) => lib.name === libraryName);
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
- };
30
+ const completeLibraryName = (str) =>
31
+ getLibraryNames().find((name) => name.includes(str)) ?? "";
43
32
 
44
- function completeLibraryName(str) {
45
- const found = _.find(getLibraryNames(), (name) => name.indexOf(str) >= 0);
46
- return found ? found : "";
47
- }
33
+ const isValidLibraryName = (libraryName) =>
34
+ libraryList.some((lib) => lib.name === libraryName);
48
35
 
49
- function isValidLibraryName(libraryName) {
50
- const found = _.find(libraryList, (lib) => lib.name === libraryName);
51
- return found ? true : false;
52
- }
36
+ const getLibArray = (libraryName) => {
37
+ const names = Array.isArray(libraryName) ? libraryName : [libraryName];
38
+ return names
39
+ .map((name) => completeLibraryName(name))
40
+ .filter((fullName) => isValidLibraryName(fullName))
41
+ .map((fullName) => getLibraryFunction(fullName));
42
+ };
53
43
 
54
- function getLibArray(libraryName) {
55
- return _.flow([
56
- fp.map((name) => {
57
- const fullName = completeLibraryName(name);
58
- return isValidLibraryName(fullName) ? getLibraryFunction(fullName) : null;
59
- }),
60
- _.compact,
61
- ])(Array.isArray(libraryName) ? libraryName : [libraryName]);
62
- }
44
+ const getSortedBooks = (books) =>
45
+ books
46
+ .map(({ libraryName, title, exist, bookUrl }) => ({ libraryName, title, exist, bookUrl }))
47
+ .sort((a, b) => (a.exist === b.exist ? 0 : a.exist ? -1 : 1));
63
48
 
64
- const getSortedBooks = _.flow([
65
- fp.map((book) => ({
66
- libraryName: book.libraryName,
67
- title: book.title,
68
- exist: book.exist,
69
- })),
70
- fp.sortBy((book) => !book.exist),
71
- ]);
49
+ const searchLibrary = (lib, title) =>
50
+ new Promise((resolve) => {
51
+ lib.search({ title, libraryName: lib.name }, (err, data) => {
52
+ if (err) {
53
+ resolve({ error: err });
54
+ return;
55
+ }
56
+ if (!data?.booklist) {
57
+ resolve({ error: { msg: "invalid Data response" } });
58
+ return;
59
+ }
60
+ resolve({
61
+ result: {
62
+ title,
63
+ libraryName: lib.name,
64
+ homeUrl: lib.homeUrl,
65
+ totalBookCount: data.totalBookCount,
66
+ startPage: data.startPage,
67
+ booklist: getSortedBooks(data.booklist),
68
+ },
69
+ });
70
+ });
71
+ });
72
72
 
73
- function search(opt, getBook, getAllBooks) {
73
+ const search = (opt, getBook, getAllBooks) => {
74
74
  if (!opt || (!getBook && !getAllBooks)) {
75
75
  console.log("invalid search options");
76
76
  return;
77
77
  }
78
78
 
79
- const title = opt.title;
80
- const tasks = [];
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
- };
79
+ const { title, libraryName } = opt;
80
+ const libraries = getLibArray(libraryName);
112
81
 
113
- if (getBook) {
114
- getBook(null, bookObj);
115
- }
116
- callback(null, bookObj);
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
- }
82
+ const promises = libraries.map(async (lib) => {
83
+ const { error, result } = await searchLibrary(lib, title);
84
+ if (error) {
85
+ getBook?.(error);
86
+ return null;
129
87
  }
88
+ getBook?.(null, result);
89
+ return result;
130
90
  });
131
- }
132
91
 
133
- function activate() {
134
- makeLibraryList();
135
- }
136
-
137
- activate();
92
+ Promise.all(promises).then((results) => {
93
+ const validResults = results.filter(Boolean);
94
+ getAllBooks?.(null, validResults);
95
+ });
96
+ };
138
97
 
139
98
  module.exports = {
140
99
  search,
package/src/library/gg.js CHANGED
@@ -3,6 +3,8 @@ const jquery = require("jquery");
3
3
  const { get } = require("../http");
4
4
  const { JSDOM } = require("jsdom");
5
5
 
6
+ const homeUrl = "https://lib.goe.go.kr";
7
+
6
8
  const libraryList = [
7
9
  { code: "MA", name: "경기중앙교육도서관" },
8
10
  { code: "MB", name: "경기평택교육도서관" },
@@ -108,6 +110,7 @@ async function search(opt, getBook) {
108
110
 
109
111
  module.exports = {
110
112
  search,
113
+ homeUrl,
111
114
  getLibraryNames: function () {
112
115
  return getLibraryNames(libraryList);
113
116
  },
@@ -2,6 +2,8 @@ const { get } = require("../http");
2
2
  const _ = require("lodash");
3
3
  const getLibraryNames = require("../util.js").getLibraryNames;
4
4
 
5
+ const homeUrl = "https://www.gunpolib.go.kr";
6
+
5
7
  const libraryList = [
6
8
  { code: "1", name: "산본도서관" },
7
9
  { code: "2", name: "당동도서관" },
@@ -98,6 +100,7 @@ async function search(opt, getBook) {
98
100
 
99
101
  module.exports = {
100
102
  search,
103
+ homeUrl,
101
104
  getLibraryNames: function () {
102
105
  return getLibraryNames(libraryList);
103
106
  },
@@ -3,18 +3,20 @@ const jquery = require("jquery");
3
3
  const { post } = require("../http");
4
4
  const { JSDOM } = require("jsdom");
5
5
 
6
+ const homeUrl = "https://hscitylib.or.kr";
7
+
6
8
  const libraryList = [
7
9
  { code: "MA", name: "남양도서관" },
8
10
  { code: "MB", name: "태안도서관" },
9
11
  { code: "MC", name: "삼괴도서관" },
10
12
  { code: "MD", name: "병점도서관" },
11
13
  { code: "ME", name: "샘내도서관" },
12
- { code: "MF", name: "두빛나래도서관" },
14
+ { code: "MF", name: "두빛나래어린이도서관" },
13
15
  { code: "MG", name: "봉담도서관" },
14
- { code: "MH", name: "둥지나래도서관" },
16
+ { code: "MH", name: "둥지나래어린이도서관" },
15
17
  { code: "MI", name: "목동이음터도서관" },
16
18
  { code: "MJ", name: "기아행복마루도서관" },
17
- { code: "MK", name: "동탄복합문화센터도서관" },
19
+ { code: "MK", name: "화성동탄중앙도서관" },
18
20
  { code: "ML", name: "송산도서관" },
19
21
  { code: "MM", name: "정남도서관" },
20
22
  { code: "MN", name: "비봉도서관" },
@@ -30,7 +32,10 @@ const libraryList = [
30
32
  { code: "MX", name: "노을빛도서관" },
31
33
  { code: "MY", name: "서연이음터도서관" },
32
34
  { code: "MZ", name: "호연이음터도서관" },
35
+ { code: "NA", name: "향남복합문화센터도서관" },
36
+ { code: "NB", name: "봉담와우도서관" },
33
37
  { code: "TA", name: "늘봄이음터도서관" },
38
+ { code: "TB", name: "달빛나래어린이도서관" },
34
39
  ];
35
40
 
36
41
  function getLibraryCode(libraryName) {
@@ -116,6 +121,7 @@ async function search(opt, getBook) {
116
121
 
117
122
  module.exports = {
118
123
  search,
124
+ homeUrl,
119
125
  getLibraryNames: function () {
120
126
  return getLibraryNames(libraryList);
121
127
  },
@@ -2,6 +2,8 @@ const getLibraryNames = require("../util.js").getLibraryNames;
2
2
  const { get } = require("../http");
3
3
  const { JSDOM } = require("jsdom");
4
4
 
5
+ const homeUrl = "https://www.osanlibrary.go.kr";
6
+
5
7
  const libraryList = [
6
8
  { code: "MA", name: "오산중앙도서관" },
7
9
  { code: "MG", name: "꿈두레도서관" },
@@ -139,6 +141,7 @@ async function search(opt, getBook) {
139
141
 
140
142
  module.exports = {
141
143
  search,
144
+ homeUrl,
142
145
  getLibraryNames: function () {
143
146
  return getLibraryNames(libraryList);
144
147
  },
@@ -3,15 +3,19 @@ const jquery = require("jquery");
3
3
  const { get } = require("../http");
4
4
  const { JSDOM } = require("jsdom");
5
5
 
6
+ const homeUrl = "https://www.snlib.go.kr";
7
+
6
8
  const libraryList = [
7
9
  { code: "BF", name: "논골도서관" },
8
10
  { code: "CK", name: "중원어린이도서관" },
9
11
  { code: "MA", name: "성남중앙도서관" },
10
12
  { code: "MB", name: "분당도서관" },
13
+ { code: "MD", name: "고등도서관" },
11
14
  { code: "MG", name: "구미도서관" },
12
15
  { code: "MH", name: "해오름도서관" },
13
16
  { code: "MJ", name: "중원도서관" },
14
17
  { code: "MM", name: "무지개도서관" },
18
+ { code: "MO", name: "수내도서관" },
15
19
  { code: "MP", name: "판교도서관" },
16
20
  { code: "MR", name: "위례도서관" },
17
21
  { code: "MS", name: "수정도서관" },
@@ -118,6 +122,7 @@ async function search(opt, getBook) {
118
122
 
119
123
  module.exports = {
120
124
  search,
125
+ homeUrl,
121
126
  getLibraryNames: function () {
122
127
  return getLibraryNames(libraryList);
123
128
  },
@@ -1,6 +1,8 @@
1
1
  const getLibraryNames = require("../util.js").getLibraryNames;
2
2
  const { createSession } = require("../http");
3
3
 
4
+ const homeUrl = "https://www.suwonlib.go.kr";
5
+
4
6
  const libraryList = [
5
7
  { code: "141025", name: "선경도서관" },
6
8
  { code: "141024", name: "수원중앙도서관" },
@@ -143,6 +145,7 @@ async function search(opt, getBook) {
143
145
 
144
146
  module.exports = {
145
147
  search,
148
+ homeUrl,
146
149
  getLibraryNames: function () {
147
150
  return getLibraryNames(libraryList);
148
151
  },
@@ -2,6 +2,8 @@ const getLibraryNames = require("../util.js").getLibraryNames;
2
2
  const { get } = require("../http");
3
3
  const { JSDOM } = require("jsdom");
4
4
 
5
+ const homeUrl = "https://lib.yongin.go.kr";
6
+
5
7
  const libraryList = [
6
8
  // Public libraries (시립도서관)
7
9
  { code: "MB", name: "수지도서관" },
@@ -176,6 +178,7 @@ async function search(opt, getBook) {
176
178
 
177
179
  module.exports = {
178
180
  search,
181
+ homeUrl,
179
182
  getLibraryNames: function () {
180
183
  return getLibraryNames(libraryList);
181
184
  },