diff options
| author | Volpeon <git@volpeon.ink> | 2021-10-19 18:14:00 +0200 |
|---|---|---|
| committer | Volpeon <git@volpeon.ink> | 2021-10-19 18:14:00 +0200 |
| commit | a1de58f364ef04c97ecad380427e6181f3bf707d (patch) | |
| tree | ba3c8df7a209081b858b423674e5c42ffec37ebe /src/services | |
| parent | Code improvements (diff) | |
| download | feralbot-a1de58f364ef04c97ecad380427e6181f3bf707d.tar.gz feralbot-a1de58f364ef04c97ecad380427e6181f3bf707d.tar.bz2 feralbot-a1de58f364ef04c97ecad380427e6181f3bf707d.zip | |
Code improvements
Diffstat (limited to 'src/services')
| -rw-r--r-- | src/services/dedupe.ts | 65 | ||||
| -rw-r--r-- | src/services/jobs.ts | 54 |
2 files changed, 119 insertions, 0 deletions
diff --git a/src/services/dedupe.ts b/src/services/dedupe.ts new file mode 100644 index 0000000..2eeb5ee --- /dev/null +++ b/src/services/dedupe.ts | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | import fs from "fs/promises"; | ||
| 2 | import path from "path"; | ||
| 3 | import * as f from "fp-ts"; | ||
| 4 | import * as t from "io-ts"; | ||
| 5 | |||
| 6 | export const E926DedupeEntryC = t.type({ | ||
| 7 | provider: t.literal("e926"), | ||
| 8 | id: t.number, | ||
| 9 | }); | ||
| 10 | |||
| 11 | export const DedupeEntryC = E926DedupeEntryC; | ||
| 12 | |||
| 13 | export type E926DedupeEntry = t.TypeOf<typeof E926DedupeEntryC>; | ||
| 14 | |||
| 15 | export type DedupeEntry = t.TypeOf<typeof DedupeEntryC>; | ||
| 16 | |||
| 17 | export class Dedupe { | ||
| 18 | private entries: DedupeEntry[] = []; | ||
| 19 | |||
| 20 | private readonly filePath: string; | ||
| 21 | |||
| 22 | private isLoaded = false; | ||
| 23 | |||
| 24 | constructor(private max: number, filename: string) { | ||
| 25 | this.filePath = path.join(process.cwd(), filename); | ||
| 26 | } | ||
| 27 | |||
| 28 | private async load() { | ||
| 29 | if (this.isLoaded) { | ||
| 30 | return; | ||
| 31 | } | ||
| 32 | |||
| 33 | try { | ||
| 34 | await fs.stat(this.filePath); | ||
| 35 | } catch { | ||
| 36 | await this.save(); | ||
| 37 | } | ||
| 38 | |||
| 39 | const fileContent = await fs.readFile(this.filePath, "utf8"); | ||
| 40 | const entries = t.array(DedupeEntryC).decode(fileContent); | ||
| 41 | |||
| 42 | if (f.either.isRight(entries)) { | ||
| 43 | this.entries = entries.right; | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | private async save() { | ||
| 48 | await fs.writeFile(this.filePath, JSON.stringify(this.entries ?? []), "utf8"); | ||
| 49 | } | ||
| 50 | |||
| 51 | async check(entry: DedupeEntry) { | ||
| 52 | await this.load(); | ||
| 53 | |||
| 54 | const has = !!this.entries.find((e) => e.provider === entry.provider && e.id === entry.id); | ||
| 55 | |||
| 56 | if (!has) { | ||
| 57 | this.entries.push(entry); | ||
| 58 | await this.save(); | ||
| 59 | } | ||
| 60 | |||
| 61 | return has; | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | export default new Dedupe(50, "dedupe.json"); | ||
diff --git a/src/services/jobs.ts b/src/services/jobs.ts new file mode 100644 index 0000000..cf3b894 --- /dev/null +++ b/src/services/jobs.ts | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | import * as e621 from "../api/e621"; | ||
| 2 | import * as mastodon from "../api/mastodon"; | ||
| 3 | import config from "../config"; | ||
| 4 | import Sharp from "sharp"; | ||
| 5 | |||
| 6 | export async function postRandomPicture() { | ||
| 7 | console.log("Fetching random post..."); | ||
| 8 | |||
| 9 | const queryIndex = Math.floor(Math.random() * config.e621.queries.length); | ||
| 10 | const query = config.e621.queries[queryIndex]; | ||
| 11 | const post = await e621.getRandomPost(query); | ||
| 12 | |||
| 13 | console.log(`Got ${post.id} via query ${queryIndex}`); | ||
| 14 | |||
| 15 | await handlePost(post); | ||
| 16 | } | ||
| 17 | |||
| 18 | export async function postSpecificPicture(id: number) { | ||
| 19 | console.log(`Fetching post ${id}...`); | ||
| 20 | |||
| 21 | const post = await e621.getPostById(id); | ||
| 22 | |||
| 23 | console.log(`Got ${post.id}`); | ||
| 24 | |||
| 25 | await handlePost(post); | ||
| 26 | } | ||
| 27 | |||
| 28 | async function handlePost(post: e621.Post) { | ||
| 29 | const source = post.sources.length ? post.sources[0] : undefined; | ||
| 30 | const cws = config.cw.filter((w) => post.tags.general.includes(w)); | ||
| 31 | |||
| 32 | console.log(`Downloading image...`); | ||
| 33 | |||
| 34 | let file = await e621.client.get(post.file.url).buffer(); | ||
| 35 | |||
| 36 | if (Buffer.byteLength(file) > 1024 * 1024 * 9) { | ||
| 37 | console.log(`Compressing...`); | ||
| 38 | |||
| 39 | file = await Sharp(file) | ||
| 40 | .resize(1800, 1800, { fit: "inside", withoutEnlargement: true }) | ||
| 41 | .jpeg({ quality: 80, mozjpeg: true }) | ||
| 42 | .toBuffer(); | ||
| 43 | } | ||
| 44 | |||
| 45 | console.log(`Uploading...`); | ||
| 46 | |||
| 47 | const attachment = await mastodon.upload(file, post.id.toString(10)); | ||
| 48 | |||
| 49 | console.log(`Posting status...`); | ||
| 50 | |||
| 51 | const status = await mastodon.createStatus(`https://e926.net/posts/${post.id}`, source, cws, attachment.id); | ||
| 52 | |||
| 53 | console.log(`Done! ${status.url}`); | ||
| 54 | } | ||
