Last active
February 10, 2025 13:23
-
-
Save anpigon/546325e2c44ce978a925e9bb0077e3fa to your computer and use it in GitHub Desktop.
옵시디언 quickAdd 플러그인: yes24 도서 검색 매크로
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const notice = (msg) => new Notice(msg, 5000); | |
| const parseDOMFormString = (html) => { | |
| return new DOMParser().parseFromString(html, "text/html"); | |
| }; | |
| const requestHtmlDoc = async (url) => { | |
| const response = await request({ url }); | |
| return parseDOMFormString(response); | |
| }; | |
| const searchBooks = async (keyword) => { | |
| try { | |
| const html = await requestHtmlDoc( | |
| "https://m.yes24.com/Search?domain=ALL&query=" + encodeURI(keyword) | |
| ); | |
| const findBookList = html.querySelectorAll("ul#yesSchGList > li.item"); | |
| return Array.from(findBookList) | |
| .map((item) => { | |
| const type = item.querySelector(".gd_res").innerText; | |
| if (!/도서|eBook|외서/i.test(type)) { | |
| return null; | |
| } | |
| const linkItem = item.querySelector("a.lnk_item") | |
| const title = linkItem.innerText.replace(/(\s이동)$/gi, ""); | |
| const link = linkItem.getAttribute("href"); | |
| return { | |
| type, | |
| title, | |
| link, | |
| author: item.querySelector(".info_auth")?.innerText?.trim(), | |
| publisher: item.querySelector(".info_pub")?.innerText?.trim(), | |
| }; | |
| }) | |
| .filter(Boolean); | |
| } catch (err) { | |
| console.log(err); | |
| } | |
| return ""; | |
| }; | |
| const getBookInfo = async (bookUrl) => { | |
| try { | |
| const infoLink = "https://m.yes24.com" + bookUrl; | |
| const doc = await requestHtmlDoc(infoLink); | |
| const title = doc | |
| .querySelector(".gName > .name") | |
| .innerText.replace(":", ":") | |
| .replace("?", "?") | |
| .trim(); | |
| const subtitle = doc | |
| .querySelector(".etc > .nameE") | |
| .innerText.replace(":", ":") | |
| .replace("?", "?") | |
| .trim(); | |
| const authors = Array.from(doc.querySelectorAll(".authPub > .auth")).map((val) => | |
| val.innerText.trim().replace(/\s(저|역)$/g, '') | |
| ); | |
| const publisher = doc.querySelector(".authPub > .pub").innerText.trim(); | |
| const publishedDate = moment(doc.querySelector(".authPub > .date").innerText.trim(), "yyyy.MM.DD.").format("yyyy-MM-DD"); | |
| const thumbnail = doc.querySelector(".img_bdr > img").getAttribute("src"); | |
| const smallThumbnail = thumbnail.replace("/XL", "/S"); | |
| const mediumThumbnail = thumbnail.replace("/XL", "/M"); | |
| const largeThumbnail = thumbnail.replace("/XL", "/L"); | |
| const categories = [ | |
| ...new Set( | |
| Array.from(doc.querySelectorAll("#RelatedCategory ul > li > a")) | |
| .map((val) => val.innerText.trim()) | |
| .filter((val) => !/선물|위로|응원/.test(val)) | |
| ), | |
| ]; | |
| const rating = doc.querySelector("#dBotRevw em.rating_num:first-of-type").innerText.trim(); | |
| const totalPage = | |
| parseInt( | |
| Array.from(doc.querySelectorAll("#GoodsBasicInfo dl > dd")) | |
| .map((dd) => /\d+쪽/.exec(dd.innerText)?.[0]) | |
| .find((e) => e) || '0', | |
| 10 | |
| ) || 0; | |
| const isbn = doc | |
| .querySelector("#GoodsBasicInfo dl:last-of-type > dd") | |
| ?.innerText.match(/(?<isbn13>\w{13})?[^]*(?<isbn10>\w{10})?/)?.groups || { | |
| isbn10: "", | |
| isbn13: "", | |
| }; | |
| const results = { | |
| title, | |
| subtitle, | |
| authors, | |
| categories, | |
| totalPage, | |
| publisher, | |
| publishedDate, | |
| thumbnail, | |
| smallThumbnail, | |
| mediumThumbnail, | |
| largeThumbnail, | |
| infoLink, | |
| rating, | |
| ...isbn, | |
| }; | |
| console.log(results) | |
| return results; | |
| } catch (err) { | |
| console.log(err); | |
| } | |
| return {}; | |
| }; | |
| const replaceIllegalFileNameCharactersInString = (str) => { | |
| return str | |
| .replace(/[\\,#%&\{\}\/*<>?$\'\":@\[\]\|]*/g, "") | |
| .replace(/\s{2,}/g, " "); | |
| }; | |
| module.exports = async (plugin) => { | |
| console.log("Starting..."); | |
| const query = await plugin.quickAddApi.inputPrompt( | |
| "제목, 저자, 출판사, ISBN 검색" | |
| ); | |
| if (query) { | |
| const books = await searchBooks(query); | |
| if (!books) { | |
| return notice(`"${query}" was not found`); | |
| } | |
| const pickedBook = await plugin.quickAddApi.suggester( | |
| ({ type, title, author, publisher }) => | |
| `${type} ${title}\n${author}, ${publisher}`, | |
| books | |
| ); | |
| const book = await getBookInfo(pickedBook.link); | |
| console.log(book); | |
| plugin.variables = { | |
| ...book, | |
| fileName: replaceIllegalFileNameCharactersInString(book.title), | |
| author: book.authors[0], | |
| category: book.categories[1], | |
| }; | |
| } | |
| }; |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
min님 의견 주셔서 감사합니다. 😊