summaryrefslogtreecommitdiffstats
path: root/src/services
diff options
context:
space:
mode:
authorVolpeon <git@volpeon.ink>2021-10-19 19:25:03 +0200
committerVolpeon <git@volpeon.ink>2021-10-19 19:25:03 +0200
commit163d8119c109c42e64ab37b01dec131f2cb5bf61 (patch)
treeee0abce3ce349482ca63b4064fcbebc0e5d2f4ff /src/services
parentCode improvements (diff)
downloadferalbot-163d8119c109c42e64ab37b01dec131f2cb5bf61.tar.gz
feralbot-163d8119c109c42e64ab37b01dec131f2cb5bf61.tar.bz2
feralbot-163d8119c109c42e64ab37b01dec131f2cb5bf61.zip
Code improvements, support a manual post queue
Diffstat (limited to 'src/services')
-rw-r--r--src/services/dedupe.ts65
-rw-r--r--src/services/jobs.ts22
-rw-r--r--src/services/postDatabase.ts86
3 files changed, 97 insertions, 76 deletions
diff --git a/src/services/dedupe.ts b/src/services/dedupe.ts
deleted file mode 100644
index 2eeb5ee..0000000
--- a/src/services/dedupe.ts
+++ /dev/null
@@ -1,65 +0,0 @@
1import fs from "fs/promises";
2import path from "path";
3import * as f from "fp-ts";
4import * as t from "io-ts";
5
6export const E926DedupeEntryC = t.type({
7 provider: t.literal("e926"),
8 id: t.number,
9});
10
11export const DedupeEntryC = E926DedupeEntryC;
12
13export type E926DedupeEntry = t.TypeOf<typeof E926DedupeEntryC>;
14
15export type DedupeEntry = t.TypeOf<typeof DedupeEntryC>;
16
17export 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
65export default new Dedupe(50, "dedupe.json");
diff --git a/src/services/jobs.ts b/src/services/jobs.ts
index cf3b894..354c66d 100644
--- a/src/services/jobs.ts
+++ b/src/services/jobs.ts
@@ -1,8 +1,18 @@
1import * as e621 from "../api/e621"; 1import * as e621 from "../api/e926";
2import * as mastodon from "../api/mastodon"; 2import * as mastodon from "../api/mastodon";
3import config from "../config"; 3import config from "../config";
4import Sharp from "sharp"; 4import Sharp from "sharp";
5 5
6export async function postSpecificPicture(id: number) {
7 console.log(`Fetching post ${id}...`);
8
9 const post = await e621.getPostById(id);
10
11 console.log(`Got ${post.id}`);
12
13 await handlePost(post);
14}
15
6export async function postRandomPicture() { 16export async function postRandomPicture() {
7 console.log("Fetching random post..."); 17 console.log("Fetching random post...");
8 18
@@ -15,16 +25,6 @@ export async function postRandomPicture() {
15 await handlePost(post); 25 await handlePost(post);
16} 26}
17 27
18export 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
28async function handlePost(post: e621.Post) { 28async function handlePost(post: e621.Post) {
29 const source = post.sources.length ? post.sources[0] : undefined; 29 const source = post.sources.length ? post.sources[0] : undefined;
30 const cws = config.cw.filter((w) => post.tags.general.includes(w)); 30 const cws = config.cw.filter((w) => post.tags.general.includes(w));
diff --git a/src/services/postDatabase.ts b/src/services/postDatabase.ts
new file mode 100644
index 0000000..e3be7bb
--- /dev/null
+++ b/src/services/postDatabase.ts
@@ -0,0 +1,86 @@
1import fs from "fs/promises";
2import path from "path";
3import * as f from "fp-ts";
4import * as t from "io-ts";
5
6export const PostDatabaseEntryC = t.type({
7 provider: t.literal("e926"),
8 id: t.number,
9});
10
11export type PostDatabaseEntry = t.TypeOf<typeof PostDatabaseEntryC>;
12
13export class PostDatabase {
14 private entries: PostDatabaseEntry[] = [];
15
16 private readonly filePath: string;
17
18 private isLoaded = false;
19
20 constructor(filename: string, private max?: number) {
21 this.filePath = path.join(process.cwd(), filename);
22 }
23
24 private async load() {
25 if (this.isLoaded) {
26 return;
27 }
28
29 try {
30 await fs.stat(this.filePath);
31 } catch {
32 await this.save();
33 }
34
35 const fileContent = await fs.readFile(this.filePath, "utf8");
36 const entries = t.array(PostDatabaseEntryC).decode(fileContent);
37
38 if (f.either.isRight(entries)) {
39 this.entries = this.max ? entries.right.slice(0, -1 * this.max) : entries.right;
40 }
41 }
42
43 private async save() {
44 await fs.writeFile(this.filePath, JSON.stringify(this.entries), "utf8");
45 }
46
47 async insertIfNotExists(entry: PostDatabaseEntry): Promise<boolean> {
48 await this.load();
49
50 const has = !!this.entries.find((e) => e.provider === entry.provider && e.id === entry.id);
51
52 if (!has) {
53 this.entries.push(entry);
54 await this.save();
55 }
56
57 return has;
58 }
59
60 async takeFirst(): Promise<PostDatabaseEntry | undefined> {
61 await this.load();
62 const entry = this.entries.shift();
63 await this.save();
64 return entry;
65 }
66
67 async remove(entry: PostDatabaseEntry): Promise<boolean> {
68 await this.load();
69 const i = this.entries.findIndex((e) => e.provider === entry.provider && e.id === entry.id);
70
71 if (i === -1) {
72 return false;
73 }
74
75 this.entries.splice(i, 1);
76 await this.save();
77 return true;
78 }
79
80 async getCount() {
81 await this.load();
82 return this.entries.length;
83 }
84}
85
86export default PostDatabase;