Skip to content

Commit

Permalink
added booru classes, booru type selector, server select, cors update …
Browse files Browse the repository at this point in the history
…on server change, custom posts interface
  • Loading branch information
Venipa committed Jun 4, 2021
1 parent 2b26b5f commit 43401fd
Show file tree
Hide file tree
Showing 14 changed files with 282 additions and 144 deletions.
123 changes: 50 additions & 73 deletions src/api/BooruInterface.ts
Original file line number Diff line number Diff line change
@@ -1,82 +1,22 @@
import { BooruPostState } from "@/store/posts/posts.store";
import { BooruServer } from "@/store/servers/servers.model";
import { filter } from "rxjs/operators";
import { App, ComponentCustomProperties, Plugin } from "vue";
import { VueAxiosInstance } from "./vue-axios/axios-typings";
import { createAxiosInstance } from "./vue-axios/axiosInstace";
import { Booru, BooruContext, BooruHttp } from "./booru/Booru";
import { DanbooruHostV2 } from "./booru/DanbooruOriginal";
import { DanbooruHostPHP } from "./booru/DanbooruPHP";

export interface BooruOptions {
auth: { login: string; password: string };
}
export class Booru {
protected _options: BooruOptions;
private _vue!: App<any>;
private _httpClient: VueAxiosInstance;
get baseUrl() {
return this.httpClient.defaults.baseURL;
}
get options() {
return this._options;
}
protected get httpClient(): VueAxiosInstance {
return this._httpClient;
}
constructor(baseUrl: string, options?: Partial<BooruOptions>) {
this._options = options as any;
this._httpClient = createAxiosInstance({ baseURL: baseUrl });
}

setCustomUrl(url: string) {
if (!url.startsWith("http")) throw new Error("Invalid Uri Format");
this.httpClient.defaults.baseURL = url;
}
injectVue(app: App<any>) {
this._vue = app;
}
}

export class DanbooruHost extends Booru {
static readonly defaultParams: { [key: string]: any } = {
page: "dapi",
json: 1,
s: "post",
q: "index",
};
constructor(url: string, options?: Partial<BooruOptions>) {
super(url, options);
}

get(page: number = 1) {
return this.httpClient
.$get(`/index.php`, {
params: {
...DanbooruHost.defaultParams,
pid: page,
},
})
.then((x) => {
if (x?.length > 0) {
return x.map((y: any) => {
y.imageId = y.image.match(/^(.*)\./)[1];
if (y.imageId) {
y.thumbnail = `https://safebooru.org/thumbnails/${y.directory}/thumbnail_${y.imageId}.jpg`;
y.sample = `https://safebooru.org/samples/${y.directory}/sample_${y.imageId}.jpg`;
y.source = `https://safebooru.org/images/${y.directory}/${y.image}`;
}
return y;
});
}
return x;
});
}
}
const BOORU_CLASSES = [DanbooruHostPHP, DanbooruHostV2];
function useBooru<T extends Booru>(BooruBase: T) {
return (app: App<any>) => {
BooruBase.injectVue(app);
BooruBase.vue = app;
return BooruBase;
};
}

declare module "@vue/runtime-core" {
interface ComponentCustomProperties {
$booru: { [key: string]: Booru };
$booru: { active(): BooruHttp };
}
}
export const installBooru: Plugin = {
Expand All @@ -88,9 +28,46 @@ export const installBooru: Plugin = {
debug: boolean;
}>
) {
app.config.globalProperties.$booru = {} as any;
app.config.globalProperties.$booru["safebooru"] = useBooru(
new DanbooruHost("https://safebooru.org")
)(app);
app.config.globalProperties.$akita.queries.serversQuery.selectAll().subscribe((configs: BooruServer[]) => {
window.ipcRenderer.send("cors:allow-booru", configs.map(x => new URL(x.url)?.origin).filter(x => !!x));
})
app.config.globalProperties.$akita.queries.serversQuery
.selectActive()
.pipe(
filter(
(config: BooruServer) =>
!!BOORU_CLASSES.find((x) => x.typeName === config?.meta?.type)
)
)
.subscribe((config: BooruServer) => {
const BOORU_CLASS = BOORU_CLASSES.find(
(x) => x.typeName === config.meta.type
);
const booruInstance: BooruContext & BooruHttp = new BOORU_CLASS(
config.url,
{
...(config.auth
? {
auth: {
login: config.auth.login,
password: config.auth.pass,
},
}
: {}),
}
);

const booru = useBooru(booruInstance)(app);
app.config.globalProperties.$booru["_instances"][config.name] = booru;
});
app.config.globalProperties.$booru = {
_instances: {},
active() {
const config: BooruServer = app.config.globalProperties.$akita.queries.serversQuery.getActive();
return app.config.globalProperties.$booru["_instances"][
config.name
] as BooruHttp;
},
} as any;
},
};
34 changes: 34 additions & 0 deletions src/api/booru/Booru.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { BooruPostState } from "@/store/posts/posts.store";
import { App } from "vue";
import { VueAxiosInstance } from "../vue-axios/axios-typings";
import { createAxiosInstance } from "../vue-axios/axiosInstace";
export type BooruType = 'danbooru_v2' | 'danbooru_php';
export interface BooruHttpOptions {
[key: string]: any;
}
export interface BooruContext {
options: BooruOptions;
vue: App<any>;
httpClient: VueAxiosInstance;
}
export interface BooruHttp {
get(
page: number,
options?: BooruHttpOptions
): Promise<BooruPostState[]>;
}
export interface BooruOptions {
auth?: { login: string; password: string };
origin?: string;
}
export class Booru implements BooruContext {
options: any;
vue: App<any>;
httpClient: VueAxiosInstance;
constructor(url: string, options?: Partial<BooruOptions>) {
this.options = { ...(options || {}), origin: new URL(url).origin };
this.httpClient = createAxiosInstance({
baseURL: url,
});
}
}
51 changes: 51 additions & 0 deletions src/api/booru/DanbooruOriginal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { BooruPostState } from "@/store/posts/posts.store";
import { Booru, BooruHttp, BooruHttpOptions, BooruOptions, BooruType } from "./Booru";

export class DanbooruHostV2 extends Booru {
static typeName: BooruType = "danbooru_v2";
constructor(url: string, options?: Partial<BooruOptions>) {
super(url, options);
}

async get(page: number = 1, args: BooruHttpOptions) {
return await this.httpClient
.$get(`/posts.json`, {
params: {
[`search[name_matches]`]: args?.q || "*",
page,
},
})
.then((x) => {
if (x?.length > 0) {
return x.map(
({
id,
image_height: height,
image_width: width,
md5: hash,
score,
tags_string: tags,
file_url: image,
large_file_url: sample,
preview_file_url: thumbnail
}: any) => {
const next: BooruPostState = {
id,
height,
width,
hash,
score,
tags: tags?.split(" "),
image,
sample,
thumbnail,
source: image
};
return next;
}
);
}
return [];
});
}
}
60 changes: 60 additions & 0 deletions src/api/booru/DanbooruPHP.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { BooruPostState } from "@/store/posts/posts.store";
import { Booru, BooruContext, BooruOptions, BooruType } from "./Booru";

export class DanbooruHostPHP extends Booru {
static typeName: BooruType = "danbooru_php";
readonly defaultParams: { [key: string]: any } = {
page: "dapi",
json: 1,
s: "post",
q: "index",
};
constructor(url: string, options?: Partial<BooruOptions>) {
super(url, options);
}

async get(page: number = 1): Promise<BooruPostState[]> {
return await this.httpClient
.$get(`/index.php`, {
params: {
...this.defaultParams,
pid: page,
},
})
.then((x) => {
if (x?.length > 0) {
return x.map(
({
id,
height,
width,
directory,
hash,
score,
tags,
image,
}: any) => {
const next: any = {
id,
directory,
height,
width,
hash,
score,
tags: tags?.split(" "),
image,
};
next.imageId = image.match(/^(.*)\./)[1];
if (next.imageId) {
next.thumbnail = `${this.options.origin}/thumbnails/${directory}/thumbnail_${next.imageId}.jpg`;
next.sample = `${this.options.origin}/samples/${directory}/sample_${next.imageId}.jpg`;
next.source = `${this.options.origin}/images/${directory}/${image}`;
}
return next as BooruPostState[];
}
);
}
return x;
});
}
}
72 changes: 37 additions & 35 deletions src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
ipcMain,
ipcRenderer,
session,
Filter,
} from "electron";
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
import installExtension, { VUEJS_DEVTOOLS } from "electron-devtools-installer";
Expand Down Expand Up @@ -48,6 +49,40 @@ async function createWindow() {
// Load the index.html when not in development
win.loadURL("app://./index.html");
}

ipcMain.on("cors:allow-booru", (ev, ...[mapping]: [string[]]) => {
const corsFilter: Filter = {
urls: [...mapping.map((x) => `${x.replace(/\/$/, "")}/*`)],
};
console.log(corsFilter.urls);
win.webContents.session.webRequest.onBeforeSendHeaders(
corsFilter,
(details, callback) => {
const uri = new URL(details.url);
if (
uri &&
uri.origin &&
mapping.findIndex((x) => x.match(uri.origin)) !== -1
) {
details.requestHeaders["origin"] = `${uri.origin}`;
details.requestHeaders["referer"] = `${uri.origin}/`;
}
details.requestHeaders[
"User-Agent"
] = `Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0 BooruDesktop/${appVersion}`;
callback({ requestHeaders: details.requestHeaders });
}
);
win.webContents.session.webRequest.onHeadersReceived(
corsFilter,
(details, callback) => {
if (details.responseHeaders)
details.responseHeaders["Access-Control-Allow-Origin"] = ["*"];
callback({ responseHeaders: details.responseHeaders });
}
);
});
return win;
}

// Quit when all windows are closed.
Expand Down Expand Up @@ -94,42 +129,9 @@ if (isDevelopment) {
});
}
}
ipcMain.on("cors:allow-booru", (ev, ...[mapping]: [string[]]) => {
console.log(mapping);
const corsFilter = {
urls: [...mapping.map((x) => `${x.replace(/\/$/, "")}/*`)],
};
session.defaultSession.webRequest.onBeforeSendHeaders(
corsFilter,
(details, callback) => {
const uri = new URL(details.url);
if (
uri &&
uri.origin &&
mapping.findIndex((x) => x.match(uri.origin)) !== -1
) {
details.requestHeaders["origin"] = `${uri.origin}`;
details.requestHeaders["referer"] = `${uri.origin}/`;
}
details.requestHeaders[
"User-Agent"
] = `Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0 BooruDesktop/${appVersion}`;
callback({ requestHeaders: details.requestHeaders });
}
);
session.defaultSession.webRequest.onHeadersReceived(
corsFilter,
(details, callback) => {
if (details.responseHeaders)
details.responseHeaders["Access-Control-Allow-Origin"] = ["*"];
callback({ responseHeaders: details.responseHeaders });
}
);
});


ipcMain.on("app.quit", (ev) => {
console.log("quit");
BrowserWindow.getAllWindows().forEach(x => x.close());
BrowserWindow.getAllWindows().forEach((x) => x.close());
app.quit();
});
});
Loading

0 comments on commit 43401fd

Please sign in to comment.