Skip to content

Commit 7f2cf2e

Browse files
committed
feat: metadata file with book files
1 parent da25bc4 commit 7f2cf2e

File tree

9 files changed

+55
-23
lines changed

9 files changed

+55
-23
lines changed

cli.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,12 @@ const Command = yargs(hideBin(process.argv))
7171

7272
const downloadHelper = async (book: Audiobook) => {
7373
logger.info(`Downloading: ${book.title}`);
74-
const [path, zippedPaths] = await client.downloadBook(
74+
const filepath = await client.downloadBook(
7575
book,
7676
argv.overwrite,
7777
argv.keepZip
7878
);
79-
if (path) {
79+
if (filepath) {
8080
logger.info(`Downloaded ${book.title}`);
8181
count++;
8282
} else {

docker-compose.yml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
services:
2-
libro-client:
2+
libro:
33
build:
44
context: .
55
dockerfile: Dockerfile
6+
container_name: libro
67
develop:
78
watch:
89
- action: sync
@@ -13,10 +14,7 @@ services:
1314
- action: rebuild
1415
path: package.json
1516
volumes:
16-
- data:/app/data/
17+
- ./data:/app/data/
1718
- ${PWD}/downloads:/app/downloads/
1819
env_file:
1920
- .env
20-
21-
volumes:
22-
data:

libro

53 MB
Binary file not shown.

package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
{
22
"name": "libro-client",
3-
"version": "0.0.5",
3+
"version": "0.0.6",
44
"module": "cli.ts",
55
"type": "module",
66
"description": "Library for downloading Libro.fm audiobooks",
77
"author": "[email protected]",
8-
"repository": "github:jedwards1230/libro-client",
8+
"repository": {
9+
"url": "git+https://github.com/jedwards1230/libro-client.git"
10+
},
911
"license": "MIT",
1012
"bin": {
1113
"libro": "cli.ts"
@@ -16,8 +18,10 @@
1618
},
1719
"scripts": {
1820
"start": "bun run cli.ts",
21+
"service": "bun run service.ts",
1922
"build:cli": "bun build ./cli.ts --compile --minify --sourcemap --outfile libro",
2023
"build:docker": "docker build . -t jedwards1230/libro:latest",
24+
"push:cli": "npm publish",
2125
"push:docker": "docker push jedwards1230/libro:latest"
2226
},
2327
"devDependencies": {

service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ const downloadBooks = async (newBooks: Audiobook[]) => {
3838
if (book) {
3939
console.log(`Downloading: ${book.title}`);
4040
try {
41-
const [path, zippedPaths] = await client.downloadBook(
41+
const filepath = await client.downloadBook(
4242
book,
4343
overwrite,
4444
keepZip
4545
);
46-
if (path) {
46+
if (filepath) {
4747
console.log(`Downloaded ${book.title}`);
4848
return book;
4949
} else {

src/LibroFmClient.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export default class LibroFmClient {
7878
book: Audiobook,
7979
overwrite: boolean = false,
8080
keepZip: boolean = false
81-
): Promise<[string, string[] | false]> {
81+
): Promise<string> {
8282
if (!this.config.authToken) throw new Error("Not logged in");
8383
const authToken = this.config.authToken;
8484

@@ -97,27 +97,34 @@ export default class LibroFmClient {
9797
logger.verbose("Skipping download", {
9898
fn: "LibroFmClient.downloadBook",
9999
});
100-
return ["", false];
100+
return "";
101101
}
102102
}
103103

104104
try {
105-
const bookPath = `${book.authors}`;
105+
if (!book.authors) throw new Error("No authors found");
106+
const filename =
107+
typeof book.authors === "string"
108+
? book.authors
109+
: book.authors.join(", ");
110+
106111
const [path, zipped_files] = await DownloadCLient.downloadFiles(
107-
bookPath,
112+
filename,
108113
urls,
109114
authToken,
110115
keepZip
111116
);
112117

118+
await DownloadCLient.saveMetadata(book, path);
119+
113120
this.state.addBook({
114121
book,
115122
path,
116123
meta: metadata,
117124
...(zipped_files && { zippedPaths: zipped_files }),
118125
});
119126

120-
return [`./${bookPath}`, zipped_files];
127+
return filename;
121128
} catch (error) {
122129
logger.error({ error, fn: "LibroFmClient.downloadBook" });
123130
throw new Error("Failed to download books");

src/lib/DownloadClient.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export default class DownloadCLient {
1717
* */
1818
@LogMethod({ scope, message: "Downloading files..." })
1919
static async downloadFiles(
20-
filenamePrefix: string,
20+
filename: string,
2121
urls: string[],
2222
authToken: string,
2323
keepZip = false
@@ -29,22 +29,34 @@ export default class DownloadCLient {
2929
keepZip &&
3030
(await Promise.all(
3131
buffers.map((buffer, idx) =>
32-
DownloadCLient.save(buffer, `/${filenamePrefix}-${idx}.zip`)
32+
DownloadCLient.save(buffer, `/${filename}-${idx}.zip`)
3333
)
3434
));
3535

3636
const paths = await Promise.all(
3737
buffers.map((buffer, idx) =>
38-
DownloadCLient.unzip(buffer, `/${filenamePrefix}-${idx}`)
38+
DownloadCLient.unzip(buffer, `/${filename}-${idx}`)
3939
)
4040
);
4141

42-
const finalPath = path.join(DOWNLOAD_DIR, filenamePrefix);
42+
const finalPath = path.join(DOWNLOAD_DIR, filename);
4343
await DownloadCLient.mergeDirectories(paths, finalPath);
4444

4545
return [finalPath, zipped_files];
4646
}
4747

48+
/**
49+
* Save Audiobook object as JSON file alongside the downloaded files.
50+
*/
51+
@LogMethod({ scope, message: "Saving metadata..." })
52+
static async saveMetadata(
53+
book: Audiobook,
54+
filepath: string
55+
): Promise<void> {
56+
const metadataPath = path.join(filepath, "metadata.json");
57+
fs.writeFileSync(metadataPath, JSON.stringify(book, null, 2));
58+
}
59+
4860
/** Downloads a file from a URL and returns the data as a Uint8Array */
4961
@LogMethod({ scope, message: "Downloading file..." })
5062
private static async download(

src/lib/Logger.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ if (fs.existsSync(LOGS_DIR)) {
1010
});
1111
}
1212

13-
const logFile = path.join(LOGS_DIR, "silly.log");
13+
const sillyLogFile = path.join(LOGS_DIR, "silly.log");
14+
const debugLogFile = path.join(LOGS_DIR, "debug.log");
1415

1516
const DEBUG_MODE = process.env.DEBUG === "true";
1617

@@ -69,9 +70,19 @@ const logger = createLogger({
6970
format.timestamp(),
7071
getFormat(true)
7172
),
72-
filename: logFile,
73+
filename: sillyLogFile,
7374
level: "silly",
7475
}),
76+
new transports.File({
77+
format: format.combine(
78+
format.errors({ stack: true }),
79+
format.splat(),
80+
format.timestamp(),
81+
getFormat(true)
82+
),
83+
filename: debugLogFile,
84+
level: "debug",
85+
}),
7586
],
7687
});
7788

src/types.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type StateDataMap = {
1616
interface Audiobook {
1717
isbn: string;
1818
title: string;
19-
authors?: string[];
19+
authors?: string | string[];
2020
cover_url?: string;
2121
catalog_info?: {
2222
bookseller_pick?: boolean;

0 commit comments

Comments
 (0)