2023-11-20 01:37:55 +09:00
import fs from "node:fs/promises" ;
import { createWriteStream } from "node:fs" ;
import stream from "node:stream/promises" ;
import { Zip , ZipPassThrough } from "fflate" ;
2023-11-19 02:25:32 +09:00
import { Database } from "./database" ;
export type Book = {
id : number ;
platform : "dmm-books" | "google-play-books" ;
readerUrl : string ;
2023-11-20 22:56:09 +09:00
title : string ;
authors : Array < string > ;
2023-11-19 02:25:32 +09:00
} ;
export function createLibrary ( db : Database ) {
return {
2023-11-20 22:56:09 +09:00
async add ( readerUrlOrBook : string | Book ) {
2023-11-19 02:25:32 +09:00
const platform = "dmm-books" ;
2023-11-20 22:56:09 +09:00
if ( typeof readerUrlOrBook === "string" ) {
await db . run (
` insert into books(platform_id, reader_url) values((select id from platforms where name = ?), ?) ` ,
platform ,
readerUrlOrBook ,
) ;
return ;
}
2023-11-19 02:25:32 +09:00
await db . run (
2023-11-20 22:56:09 +09:00
` \
insert into books (
platform_id ,
reader_url ,
title ,
authors )
values ( ( select id from platforms where name = ? ) , ? , ? , ? )
on conflict ( reader_url )
do update set title = excluded . title , authors = excluded . authors
` ,
2023-11-19 02:25:32 +09:00
platform ,
2023-11-20 22:56:09 +09:00
readerUrlOrBook . readerUrl ,
readerUrlOrBook . title ,
JSON . stringify ( readerUrlOrBook . authors ) ,
2023-11-19 02:25:32 +09:00
) ;
2023-11-19 20:51:29 +09:00
} ,
async delete ( id : number ) {
await db . run ( ` delete from books where id = ? ` , id ) ;
2023-11-19 02:25:32 +09:00
} ,
2023-11-19 22:04:19 +09:00
async get ( id : number ) : Promise < Book | undefined > {
2023-11-20 22:56:09 +09:00
const row = await db . get (
` select books.id, platforms.name as platform, books.reader_url as readerUrl, books.title, books.authors from books left join platforms on books.platform_id = platforms.id where books.id = ? ` ,
2023-11-19 22:04:19 +09:00
id ,
) ;
2023-11-20 22:56:09 +09:00
const book : Book | undefined = row && {
. . . row ,
authors : JSON.parse ( row . authors ) ,
} ;
2023-11-19 22:04:19 +09:00
return book ;
} ,
2023-11-19 02:25:32 +09:00
async getBooks ( ) : Promise < Array < Book > > {
2023-11-20 22:56:09 +09:00
const rows = await db . all (
` select books.id, platforms.name as platform, books.reader_url as readerUrl, books.title, books.authors from books left join platforms on books.platform_id = platforms.id ` ,
2023-11-19 02:25:32 +09:00
) ;
2023-11-20 22:56:09 +09:00
const books : Array < Book > = rows . map ( ( row ) = > ( {
. . . row ,
authors : JSON.parse ( row . authors ) ,
} ) ) ;
2023-11-19 02:25:32 +09:00
return books ;
} ,
2023-11-20 01:37:55 +09:00
async archive ( dir : string ) {
const bookDirs = await fs . readdir ( dir , { withFileTypes : true } ) ;
for ( const bookDir of bookDirs ) {
if ( ! bookDir . isDirectory ( ) ) {
continue ;
}
const path = ` ${ bookDir . path } / ${ bookDir . name } ` ;
const out = createWriteStream ( ` ${ path } .cbz ` ) ;
const zip = new Zip ( function cb ( err , data , final ) {
if ( err ) {
out . destroy ( err ) ;
return ;
}
out [ final ? "end" : "write" ] ( data ) ;
} ) ;
const files = await fs . readdir ( path ) ;
for ( const file of files ) {
const data = new ZipPassThrough ( file ) ;
zip . add ( data ) ;
const buffer = await fs . readFile ( ` ${ path } / ${ file } ` ) ;
data . push ( buffer , true ) ;
}
zip . end ( ) ;
await stream . finished ( out ) ;
await fs . rm ( path , { recursive : true } ) ;
}
} ,
2023-11-19 02:25:32 +09:00
} ;
}