Skip to content

Instantly share code, notes, and snippets.

@nillpo
Last active April 21, 2023 16:16
Show Gist options
  • Save nillpo/ae0604d291574012d0ca76b02da4d90f to your computer and use it in GitHub Desktop.
Save nillpo/ae0604d291574012d0ca76b02da4d90f to your computer and use it in GitHub Desktop.
Kindleの購入書籍リストを出力するやつ
// https://read.amazon.co.jp/ 開いて実行
function generateMangaCollectionSearchQuery(pagination = "") {
const sortType = {
acquisition_desc: "acquisition_desc",
acquisition_asc: "acquisition_asc",
};
const query = {
querySize: 50,
sortType: sortType.acquisition_desc,
};
return new URLSearchParams(
pagination === "" ? query : { ...query, paginationToken: pagination }
);
}
function generateBookListSearchQuery(pagination = 0) {
const sortType = {
title: "title",
acquisition_desc: "acquisition_desc",
acquisition_asc: "acquisition_asc",
author: "author",
recency: "recency",
};
const query = {
query: "",
libraryType: "BOOKS",
sortType: sortType.recency,
querySize: 50, //最大50
};
return new URLSearchParams(
pagination === 0 ? query : { ...query, paginationToken: pagination }
);
}
async function* fetchList(config) {
const searchURL = new URL(config.url);
let currentPagination = config.initial;
let isPaginationExist = true;
while (isPaginationExist) {
searchURL.search = config.searchParamFunc(currentPagination);
const res = await fetch(searchURL);
if (!res.ok) throw new Error("おかしい");
const json = await res.json();
const items = json.itemsList;
if (
Object.hasOwn(json, "paginationToken") &&
typeof json.paginationToken === "string"
) {
currentPagination = json.paginationToken;
yield {
items,
nextPagination: currentPagination,
};
} else {
isPaginationExist = false;
yield {
items,
};
}
}
}
function wait() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("ok");
}, 1000);
});
}
async function getList(config) {
let array = [];
for await (const { items } of fetchList(config)) {
console.info(`fetch: ${items.length}`);
array = [...array, ...items];
await wait();
}
return array;
}
function getBookListConfig() {
return {
url: new URL("https://read.amazon.co.jp/kindle-library/search"),
searchParamFunc: generateBookListSearchQuery,
initial: 0,
};
}
function getMangaCollectionConfig() {
return {
url: new URL("https://read.amazon.co.jp/kindle-library/api/collection"),
searchParamFunc: generateMangaCollectionSearchQuery,
initial: "",
};
}
async function downloadList(type) {
let config;
let fileName;
switch (type) {
case "books": {
config = getBookListConfig();
fileName = "BookList";
break;
}
case "collections": {
config = getMangaCollectionConfig();
fileName = "CollectionList";
break;
}
default: {
throw new Error(`${config} is unknown`);
}
}
const books = await getList(config);
const blob = new Blob([JSON.stringify(books)], { type: "text/plain" });
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.download = `Kindle${fileName}_${Date.now()}.json`;
link.href = url;
document.body.appendChild(link);
link.click();
window.URL.revokeObjectURL(link.href);
document.body.removeChild(link);
}
downloadList("books");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment