Skip to content

Commit

Permalink
feat(OPDS): automatic import of catalog of feeds from ENV variable (PR
Browse files Browse the repository at this point in the history
…#1564 Fixes #274)
  • Loading branch information
panaC authored Oct 15, 2021
1 parent 445f73c commit b282b11
Show file tree
Hide file tree
Showing 17 changed files with 361 additions and 196 deletions.
3 changes: 2 additions & 1 deletion src/common/api/interface/httpBrowser.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
// ==LICENSE-END==

import { THttpGetBrowserResultView } from "readium-desktop/common/views/browser";
import { SagaGenerator } from "typed-redux-saga";

export interface IHttpBrowserApi {
browse: (
url: string,
) => Promise<THttpGetBrowserResultView>;
) => SagaGenerator<THttpGetBrowserResultView>;
}

export interface IHttpBrowserModuleApi {
Expand Down
11 changes: 6 additions & 5 deletions src/common/api/interface/opdsApi.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,29 @@ import { OpdsFeed } from "readium-desktop/common/models/opds";
import {
IOpdsFeedView, IOpdsLinkView,
} from "readium-desktop/common/views/opds";
import { SagaGenerator } from "typed-redux-saga";

// quite useless
export type TOpdsLinkSearch = Required<Pick<IOpdsLinkView, "url">>;

export interface IOpdsApi {
getFeed: (
identifier: string,
) => Promise<IOpdsFeedView>;
) => SagaGenerator<IOpdsFeedView>;
deleteFeed: (
identifier: string,
) => Promise<void>;
) => SagaGenerator<void>;
findAllFeeds: (
) => Promise<IOpdsFeedView[]>;
) => SagaGenerator<IOpdsFeedView[]>;
addFeed: (
data: OpdsFeed,
) => Promise<IOpdsFeedView>;
) => SagaGenerator<IOpdsFeedView>;
// updateFeed: (
// data: OpdsFeed,
// ) => Promise<IOpdsFeedView>;
getUrlWithSearchLinks: (
searchLink: TOpdsLinkSearch[] | TOpdsLinkSearch,
) => Promise<string | undefined>;
) => SagaGenerator<string | undefined>;
}

export interface IOpdsModuleApi {
Expand Down
2 changes: 2 additions & 0 deletions src/common/views/opds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export interface IOpdsPublicationView {
languages?: string[];
publishedAt?: string; // ISO8601
entryLinks?: IOpdsLinkView[];
catalogLinkView: IOpdsLinkView[];
buyLinks?: IOpdsLinkView[];
borrowLinks?: IOpdsLinkView[];
subscribeLinks?: IOpdsLinkView[];
Expand Down Expand Up @@ -71,6 +72,7 @@ export interface IOpdsResultView {
facets?: IOpdsFacetView[];
groups?: IOpdsGroupView[];
auth?: IOpdsAuthView;
catalogs?: IOpdsPublicationView[];
}

export interface IOpdsGroupView {
Expand Down
96 changes: 0 additions & 96 deletions src/main/api/browser.ts

This file was deleted.

75 changes: 0 additions & 75 deletions src/main/api/opds.ts

This file was deleted.

21 changes: 9 additions & 12 deletions src/main/cli/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ export async function cliImport(filePath: string[] | string) {
debug("cliImport", filePath);

// import a publication from local path
let returnValue = true;
const filePathArray = Array.isArray(filePath) ? filePath : [filePath];

const sagaMiddleware = diMainGet("saga-middleware");
Expand All @@ -63,28 +62,26 @@ export async function cliImport(filePath: string[] | string) {
const pubViews = await sagaMiddleware.run(pubApi.importFromFs, fp).toPromise<PublicationView[]>();

if (!pubViews && pubViews.length === 0) {
returnValue = false;
return false;
}
}
return returnValue;
return true;
}

export async function cliOpds(title: string, url: string) {
// save an opds feed with title and url in the db
const hostname = (new URL(url)).hostname;
if (hostname) {

const opdsRepository = diMainGet("opds-feed-repository");
const sagaMiddleware = diMainGet("saga-middleware");
const opdsApi = diMainGet("opds-api");

// ensures no duplicates (same URL ... but may be different titles)
const opdsFeeds = await opdsRepository.findAll();
const found = opdsFeeds.find((o) => o.url === url);
if (found) {
return true;
const opdsViews = await sagaMiddleware.run(opdsApi.addFeed, { title, url }).toPromise<PublicationView[]>();

if (!opdsViews && opdsViews.length === 0) {
return false;
}

const opdsFeedDocument = await opdsRepository.save({ title, url });
return !!opdsFeedDocument;
}
return false;
return true;
}
17 changes: 17 additions & 0 deletions src/main/converter/opds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,18 @@ export class OpdsFeedViewConverter {
],
}),
);
const catalogLinkView = fallback(
this.convertFilterLinksToView(baseUrl, r2OpdsPublication.Links, {
type: ["application/atom+xml;profile=opds-catalog;kind=acquisition", ContentType.Opds2],
rel: "http://opds-spec.org/catalog",
}),
this.convertFilterLinksToView(baseUrl, r2OpdsPublication.Links, {
type: [
ContentType.AtomXml,
ContentType.Opds2,
],
}),
);

const revokeLoanLinkView = this.convertFilterLinksToView(baseUrl, r2OpdsPublication.Links, {
rel: ["http://librarysimplified.org/terms/rel/revoke"],
Expand Down Expand Up @@ -377,6 +389,7 @@ export class OpdsFeedViewConverter {
revokeLoanLinks: revokeLoanLinkView,
duration,
nbOfTracks,
catalogLinkView,
};
}
public convertOpdsAuthToView(r2OpdsAuth: OPDSAuthenticationDoc, baseUrl: string): IOpdsResultView {
Expand Down Expand Up @@ -535,6 +548,9 @@ export class OpdsFeedViewConverter {
r2OpdsFeed.Metadata.CurrentPage,
}
: undefined;
const catalogs = r2OpdsFeed.Catalogs?.map(
(item) =>
this.convertOpdsPublicationToView(item, baseUrl));

return {
title,
Expand All @@ -545,6 +561,7 @@ export class OpdsFeedViewConverter {
groups,
facets,
auth: undefined,
catalogs,
};
}
}
13 changes: 6 additions & 7 deletions src/main/di.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { Translator } from "readium-desktop/common/services/translator";
import { ok } from "readium-desktop/common/utils/assert";
import { CatalogApi } from "readium-desktop/main/api/catalog";
import { LcpApi } from "readium-desktop/main/api/lcp";
import { OpdsApi } from "readium-desktop/main/api/opds";
import { LocatorViewConverter } from "readium-desktop/main/converter/locator";
import { OpdsFeedViewConverter } from "readium-desktop/main/converter/opds";
import { PublicationViewConverter } from "readium-desktop/main/converter/publication";
Expand Down Expand Up @@ -46,10 +45,10 @@ import { SagaMiddleware } from "redux-saga";
import { KeyboardApi } from "./api/keyboard";
import { ReaderApi } from "./api/reader";
import { SessionApi } from "./api/session";
import { publicationApi } from "./redux/sagas/api";
import { httpBrowserApi, publicationApi } from "./redux/sagas/api";
import { RootState } from "./redux/states";
import { OpdsService } from "./services/opds";
import { HttpBrowserApi } from "./api/browser";
import { opdsApi } from "./redux/sagas/api/opds";

// import { streamer } from "readium-desktop/main/streamerHttp";
// import { Server } from "@r2-streamer-js/http/server";
Expand Down Expand Up @@ -328,9 +327,9 @@ container.bind<CatalogApi>(diSymbolTable["catalog-api"]).to(CatalogApi).inSingle
// container.bind<PublicationApi>(diSymbolTable["publication-api"]).to(PublicationApi).inSingletonScope();

container.bind(diSymbolTable["publication-api"]).toConstantValue(publicationApi);
container.bind(diSymbolTable["opds-api"]).toConstantValue(opdsApi);
container.bind(diSymbolTable["httpbrowser-api"]).toConstantValue(httpBrowserApi);

container.bind<OpdsApi>(diSymbolTable["opds-api"]).to(OpdsApi).inSingletonScope();
container.bind<HttpBrowserApi>(diSymbolTable["httpbrowser-api"]).to(HttpBrowserApi).inSingletonScope();
container.bind<KeyboardApi>(diSymbolTable["keyboard-api"]).to(KeyboardApi).inSingletonScope();
container.bind<LcpApi>(diSymbolTable["lcp-api"]).to(LcpApi).inSingletonScope();
container.bind<ReaderApi>(diSymbolTable["reader-api"]).to(ReaderApi).inSingletonScope();
Expand Down Expand Up @@ -378,8 +377,8 @@ interface IGet {
(s: "lcp-manager"): LcpManager;
(s: "catalog-api"): CatalogApi;
(s: "publication-api"): typeof publicationApi;
(s: "opds-api"): OpdsApi;
(s: "httpbrowser-api"): HttpBrowserApi;
(s: "opds-api"): typeof opdsApi;
(s: "httpbrowser-api"): typeof httpBrowserApi;
(s: "keyboard-api"): KeyboardApi;
(s: "lcp-api"): LcpApi;
(s: "reader-api"): ReaderApi;
Expand Down
5 changes: 5 additions & 0 deletions src/main/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@ export type TOpdsAuthenticationChannel = [doc: OPDSAuthenticationDoc, baseUrl: s
const opdsAuthenticationChannel = channel<TOpdsAuthenticationChannel>();

export const getOpdsAuthenticationChannel = () => opdsAuthenticationChannel;

const opdsNewCatalogsStringUrlChannel = channel<string>();

export const getOpdsNewCatalogsStringUrlChannel = () => opdsNewCatalogsStringUrlChannel;

Loading

0 comments on commit b282b11

Please sign in to comment.