From c3eb90e983bb5b36fa6858a5b7c51b4d82bbc669 Mon Sep 17 00:00:00 2001 From: codecanna Date: Thu, 1 Jan 2026 00:03:58 -0700 Subject: [PATCH 01/14] Added a way to change the rating --- main.ts | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/main.ts b/main.ts index 147ea6a..558ee9d 100644 --- a/main.ts +++ b/main.ts @@ -11,8 +11,10 @@ import { createDatabase } from "./db/utils/createDb.ts"; import { getUserByTelegramId as getUserByTelegramId, insertUser as insertUser, + updateRating, userExists as userExists, } from "./models/user.ts"; +import { DB_FILE } from "./constants/strings.ts"; if (import.meta.main) { try { @@ -73,6 +75,37 @@ if (import.meta.main) { await ctx.conversation.enter("edit_blacklist"); }); + yiffBot.command("rating", async (ctx) => { + switch (ctx.match) { + case "s": + case "q": + case "e": + case "safe": + case "questionable": + case "explicit": { + try { + updateRating(ctx.from?.id!, encodeURIComponent(`rating:${ctx.match}`), DB_FILE); + await ctx.reply(`Updated your rating to ${ctx.match}.`, { + parse_mode: "HTML", + }); + } catch (err) { + console.error( + `Failed to update rating setting for user ${ctx.from?.id}: ${err}`, + ); + } + + break; + } + default: { + await ctx.reply( + `Invalid rating: ${ctx.match}! The rating must be s (safe), q (questionable), or e (explicit).`, + { parse_mode: "HTML" }, + ); + break; + } + } + }); + yiffBot.command("help", async (ctx) => { await ctx.reply(strings.helpString, { parse_mode: "HTML" }); }); @@ -188,7 +221,10 @@ if (import.meta.main) { yiffBot.on("inline_query", async (ctx) => { // Create new user if not exists if (!userExists(ctx.from.id, strings.DB_FILE)) { - insertUser({ telegramId: ctx.from.id, blacklist: [] }, strings.DB_FILE); + insertUser( + { telegramId: ctx.from.id, blacklist: [], rating: "" }, + strings.DB_FILE, + ); } const user = getUserByTelegramId(ctx.from.id, strings.DB_FILE); @@ -219,10 +255,10 @@ if (import.meta.main) { urlBuilder.page = page; - console.log(`Current URL: ${urlBuilder.buildUrl()}`); + console.log(`Current URL: ${urlBuilder.buildUrl(user?.rating!)}`); // Grab our data - const request = await yiffBot.sendRequest(urlBuilder.buildUrl()); + const request = await yiffBot.sendRequest(urlBuilder.buildUrl(user?.rating!)); const requestJson = await request.json(); const postsJson = requestJson.posts; // An array of 50 posts From e881002bf0fc086247bbf3e7e8ef431612a1e39f Mon Sep 17 00:00:00 2001 From: codecanna Date: Thu, 1 Jan 2026 00:04:23 -0700 Subject: [PATCH 02/14] added an optional rating parameter to buildUrl() --- interfaces.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interfaces.ts b/interfaces.ts index 74c407f..a7a28c6 100644 --- a/interfaces.ts +++ b/interfaces.ts @@ -3,7 +3,7 @@ export interface E621UrlBuilder { limit?: number; page?: number; endpoint: string; - buildUrl(): string; + buildUrl(rating?: string): string; } export interface Pool { From b10a38a1c2d35aeae089aa06931d063258e20b8f Mon Sep 17 00:00:00 2001 From: codecanna Date: Thu, 1 Jan 2026 00:05:25 -0700 Subject: [PATCH 03/14] removed check for rating keywords --- classes/E621Bot.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/classes/E621Bot.ts b/classes/E621Bot.ts index 32d232d..c55b180 100644 --- a/classes/E621Bot.ts +++ b/classes/E621Bot.ts @@ -85,10 +85,10 @@ export class E621Bot extends Bot { continue; } - if (/(safe|questionable|explicit)/.test(queryTags[tag])) { - urlBuilder.rating = encodeURIComponent(`rating:${queryTags[tag]}`); - continue; - } + // if (/(safe|questionable|explicit)/.test(queryTags[tag])) { + // urlBuilder.rating = encodeURIComponent(`rating:${queryTags[tag]}`); + // continue; + // } if (/(score|favcount|random|hot)/.test(queryTags[tag])) { urlBuilder.order = encodeURIComponent(`order:${queryTags[tag]}`); @@ -99,6 +99,11 @@ export class E621Bot extends Bot { urlBuilder.fileType = encodeURIComponent(`type:${queryTags[tag]}`); continue; } + + // // Ignore ratings in the query since we are pulling the rating from the db + // if (/(rating:(s|safe)|rating:(q|questionable)|rating:(e|explicit))/.test(queryTags[tag])) { + // continue; + // } parsedTags.push(queryTags[tag]); } urlBuilder.tags = parsedTags; From 609bcb6b8641d9a0c999f3b62d2864bec1bb648c Mon Sep 17 00:00:00 2001 From: codecanna Date: Thu, 1 Jan 2026 00:05:44 -0700 Subject: [PATCH 04/14] added rating to the output URL --- classes/E621UrlBuilderPosts.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/E621UrlBuilderPosts.ts b/classes/E621UrlBuilderPosts.ts index 6d591b5..408d24d 100644 --- a/classes/E621UrlBuilderPosts.ts +++ b/classes/E621UrlBuilderPosts.ts @@ -71,8 +71,8 @@ export class E621UrlBuilderPosts implements E621UrlBuilder { * Returns a URL built fromt he current state of the builder itself and a base URL * @returns string URL built from the current state of the builder */ - buildUrl() { - return `${this.baseUrl}${this.endpoint}${this.tagString()}&page=${this.page}&limit=${this.limit}`; + buildUrl(rating: string) { + return `${this.baseUrl}${this.endpoint}${this.tagString()}+${rating}&page=${this.page}&limit=${this.limit}`; } /** From c5091bd34a30678012031c75f4e82c34461a4a36 Mon Sep 17 00:00:00 2001 From: codecanna Date: Thu, 1 Jan 2026 00:06:06 -0700 Subject: [PATCH 05/14] added ratings field --- db/migration.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/migration.ts b/db/migration.ts index d2ef88b..95a547a 100644 --- a/db/migration.ts +++ b/db/migration.ts @@ -1,14 +1,14 @@ import { PathLike } from "node:fs"; import { DatabaseSync } from "node:sqlite"; -export function createBlacklistDb(dbFile: PathLike) { +export function createUserDb(dbFile: PathLike) { try { const db = new DatabaseSync(dbFile); - db.prepare(` CREATE TABLE IF NOT EXISTS user_db ( id INTEGER PRIMARY KEY AUTOINCREMENT, telegram_id BIGINT NOT NULL UNIQUE, + rating TEXT DEFAULT 's', -- Default rating for the bot for now will be s (safe) blacklist TEXT DEFAULT 'gore,scat,watersports,young,loli,shota' -- Default blacklist for every user on e621 ); `).run(); From b1f5f6b276fd662f9e3a2fec24d343148092c0de Mon Sep 17 00:00:00 2001 From: codecanna Date: Thu, 1 Jan 2026 00:06:26 -0700 Subject: [PATCH 06/14] ranamed updateUser to updateBlacklist() --- models/user.ts | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/models/user.ts b/models/user.ts index 8b728a6..0c8067c 100644 --- a/models/user.ts +++ b/models/user.ts @@ -31,7 +31,7 @@ export function insertUser(user: User, dbFile: PathLike) { * @param dbFile * @returns StatementResultingChanges */ -export function updateUser(user: User, dbFile: PathLike) { +export function updateBlacklist(user: User, dbFile: PathLike) { try { const db = new DatabaseSync(dbFile); const queryResult = db.prepare( @@ -47,6 +47,32 @@ export function updateUser(user: User, dbFile: PathLike) { } } +/** + * + * @param rating Rating the user picked + * @param id Telegram Id of user + * @param dbFile Path to DB file + * @returns StatementResultingChanges + */ +export function updateRating(id: number, rating: string, dbFile: PathLike) { + try { + const db = new DatabaseSync(dbFile); + const queryResult = db.prepare( + `UPDATE OR FAIL user_db SET rating = ? WHERE telegram_id = ?;`, + ).run( + rating, + id, + ); + db.close(); + return queryResult; + } catch (err) { + console.error( + `Failed to update rating for user ${id}: ${err}`, + ); + throw err; + } +} + /** * Delete a user from the db * @param telegramId Id attatched to blacklist @@ -90,6 +116,7 @@ export function getUserByTelegramId( return { id: Number(queryResult.id), telegramId: Number(queryResult.telegram_id), + rating: String(queryResult.rating), blacklist: String(queryResult.blacklist).split(",") || defaultBlacklist.split(","), }; From ac24bad799e8030ed89e598288160c99bb8488cf Mon Sep 17 00:00:00 2001 From: codecanna Date: Thu, 1 Jan 2026 00:06:59 -0700 Subject: [PATCH 07/14] changed createBlacklistDb to createUserDb --- db/utils/createDb.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/utils/createDb.ts b/db/utils/createDb.ts index 0b7ad71..b683a95 100644 --- a/db/utils/createDb.ts +++ b/db/utils/createDb.ts @@ -1,9 +1,9 @@ import { PathLike } from "node:fs"; -import { createBlacklistDb } from "../migration.ts"; +import { createUserDb } from "../migration.ts"; export function createDatabase(dbFile: PathLike): boolean { try { - createBlacklistDb(dbFile); + createUserDb(dbFile); return true; } catch (err) { console.error(`Failed to create Database: ${dbFile}: ${err}`); From 4c0c5b4c01306a19551b0033a95567da5a3320ee Mon Sep 17 00:00:00 2001 From: codecanna Date: Thu, 1 Jan 2026 00:07:20 -0700 Subject: [PATCH 08/14] changed name of function --- handlers/edit_blacklist.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/handlers/edit_blacklist.ts b/handlers/edit_blacklist.ts index 668d3f3..a07adaf 100644 --- a/handlers/edit_blacklist.ts +++ b/handlers/edit_blacklist.ts @@ -1,7 +1,7 @@ import { Conversation } from "@grammyjs/conversations"; import { Context } from "grammy"; import { User } from "../types/Blacklist.ts"; -import { getUserByTelegramId, updateUser } from "../models/user.ts"; +import { getUserByTelegramId, updateBlacklist } from "../models/user.ts"; import { DB_FILE } from "../constants/strings.ts"; /** @@ -30,11 +30,12 @@ export async function edit_blacklist(conversation: Conversation, ctx: Context) { const newUserData: User = { telegramId: ctx.from?.id!, + rating: "", blacklist: blacklist, }; try { - updateUser(newUserData, DB_FILE); + updateBlacklist(newUserData, DB_FILE); } catch (err) { console.error( `Failed to save blacklist for ${ctx.from?.first_name} id ${ctx.from?.id}: ${err}`, From 36aa71a84899b90f2a3bdc4c116cf6fcd39dae82 Mon Sep 17 00:00:00 2001 From: codecanna Date: Thu, 1 Jan 2026 00:07:43 -0700 Subject: [PATCH 09/14] added rating field to User --- types/Blacklist.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/types/Blacklist.ts b/types/Blacklist.ts index e529c33..96f236d 100644 --- a/types/Blacklist.ts +++ b/types/Blacklist.ts @@ -1,5 +1,6 @@ export type User = { id?: number; telegramId: number; + rating: string, blacklist: string[]; }; From 4e5d8ea8d0ca359ae3c163117f1fea4ec285eba6 Mon Sep 17 00:00:00 2001 From: codecanna Date: Thu, 1 Jan 2026 00:08:03 -0700 Subject: [PATCH 10/14] All tests are passing --- tests/migration_tests.ts | 4 +- tests/parse_inline_query_tests.ts | 78 +++++++++++++++---------------- tests/url_builder_tests.ts | 3 +- tests/user_tests.ts | 49 ++++++++++++------- 4 files changed, 73 insertions(+), 61 deletions(-) diff --git a/tests/migration_tests.ts b/tests/migration_tests.ts index dab9f54..ddc640d 100644 --- a/tests/migration_tests.ts +++ b/tests/migration_tests.ts @@ -1,6 +1,6 @@ import { assertEquals } from "@std/assert/equals"; import { DatabaseSync } from "node:sqlite"; -import { createBlacklistDb } from "../db/migration.ts"; +import { createUserDb } from "../db/migration.ts"; import { assertNotEquals } from "@std/assert/not-equals"; import { TEST_DB_FILE } from "../constants/strings.ts"; import { existsSync } from "node:fs"; @@ -10,7 +10,7 @@ if (!existsSync("db/test_db")) { } Deno.test(function testCreateBlacklistDb() { - createBlacklistDb(TEST_DB_FILE); + createUserDb(TEST_DB_FILE); // Get table const db = new DatabaseSync(TEST_DB_FILE); diff --git a/tests/parse_inline_query_tests.ts b/tests/parse_inline_query_tests.ts index b8557f4..00704f5 100644 --- a/tests/parse_inline_query_tests.ts +++ b/tests/parse_inline_query_tests.ts @@ -10,8 +10,8 @@ import * as numbers from "../constants/numbers.ts"; */ Deno.test(function parseInlineQueryTest() { const testBot = new E621Bot( - Deno.env.get("TELEGRAM_BOT_KEY") || "", - Deno.env.get("E621_API_KEY") || "", + "TELEGRAM_BOT_KEY", + "E621_API_KEY", ); // Create our test queries @@ -21,9 +21,9 @@ Deno.test(function parseInlineQueryTest() { const dateQuery = "dragons 2024-10-10"; // Rating query - const safeQuery = "dragons safe"; - const questionableQuery = "dragons questionable"; - const explicitQuery = "dragons explicit"; // e621 is Explicit by default + const safeQuery = "dragons"; + const questionableQuery = "dragons"; + const explicitQuery = "dragons"; // e621 is Explicit by default // Order query const scoreQuery = "dragons score"; @@ -41,7 +41,7 @@ Deno.test(function parseInlineQueryTest() { // Mixed search queries const mixedSearchQuery1 = "dragons today mp4"; const mixedSearchQuery2 = "dragons random gif"; - const mixedSearchQuery3 = "dragons questionable favcount"; + const mixedSearchQuery3 = "dragons favcount"; // Create test URL builders with processPosts() // Date Urlbuilders @@ -131,11 +131,11 @@ Deno.test(function parseInlineQueryTest() { // Date urls const todayUrl = - `${postsUrl}dragons+${urls.date.today}&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.date.today}+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; const yesterdayUrl = - `${postsUrl}dragons+${urls.date.yesterday}&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.date.yesterday}+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; const dateUrl = - `${postsUrl}dragons+${urls.date.byDate}2024-10-10&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.date.byDate}2024-10-10+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; // Rating urls const safeUrl = @@ -147,61 +147,61 @@ Deno.test(function parseInlineQueryTest() { // Order urls const scoreUrl = - `${postsUrl}dragons+${urls.order.score}&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.order.score}+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; const favcountUrl = - `${postsUrl}dragons+${urls.order.favcount}&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.order.favcount}+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; const randomUrl = - `${postsUrl}dragons+${urls.order.random}&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.order.random}+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; const hotUrl = - `${postsUrl}dragons+${urls.order.hot}&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.order.hot}+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; // File urls const jpgUrl = - `${postsUrl}dragons+${urls.fileType.jpg}&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.fileType.jpg}+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; const pngUrl = - `${postsUrl}dragons+${urls.fileType.png}&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.fileType.png}+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; const gifUrl = - `${postsUrl}dragons+${urls.fileType.gif}&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.fileType.gif}+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; const mp4Url = - `${postsUrl}dragons+${urls.fileType.mp4}&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.fileType.mp4}+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; const webmUrl = - `${postsUrl}dragons+${urls.fileType.webm}&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.fileType.webm}+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; // Mixed search urls const mixedSearchUrl1 = - `${postsUrl}dragons+${urls.date.today}+${urls.fileType.mp4}&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.date.today}+${urls.fileType.mp4}+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; const mixedSearchUrl2 = - `${postsUrl}dragons+${urls.fileType.gif}+${urls.order.random}&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.fileType.gif}+${urls.order.random}+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; const mixedSearchUrl3 = - `${postsUrl}dragons+${urls.rating.questionable}+${urls.order.favcount}&page=1&limit=${numbers.API_PAGE_SIZE}`; + `${postsUrl}dragons+${urls.order.favcount}+${urls.rating.safe}&page=1&limit=${numbers.API_PAGE_SIZE}`; // Date asserts - assertEquals(todayUrlBuilder.buildUrl(), todayUrl); - assertEquals(yesterdayUrlBuilder.buildUrl(), yesterdayUrl); - assertEquals(dateUrlBuilder.buildUrl(), dateUrl); + assertEquals(todayUrlBuilder.buildUrl(urls.rating.safe), todayUrl); + assertEquals(yesterdayUrlBuilder.buildUrl(urls.rating.safe), yesterdayUrl); + assertEquals(dateUrlBuilder.buildUrl(urls.rating.safe), dateUrl); // Rating asserts - assertEquals(safeUrlBuilder.buildUrl(), safeUrl); - assertEquals(questionableUrlBuilder.buildUrl(), questionableUrl); - assertEquals(explicitUrlBuilder.buildUrl(), explicitUrl); + assertEquals(safeUrlBuilder.buildUrl(urls.rating.safe), safeUrl); + assertEquals(questionableUrlBuilder.buildUrl(urls.rating.questionable), questionableUrl); + assertEquals(explicitUrlBuilder.buildUrl(urls.rating.explicit), explicitUrl); // Order asserts - assertEquals(scoreUrlBuilder.buildUrl(), scoreUrl); - assertEquals(favcountUrlBuilder.buildUrl(), favcountUrl); - assertEquals(randomUrlBuilder.buildUrl(), randomUrl); - assertEquals(hotUrlBuilder.buildUrl(), hotUrl); + assertEquals(scoreUrlBuilder.buildUrl(urls.rating.safe), scoreUrl); + assertEquals(favcountUrlBuilder.buildUrl(urls.rating.safe), favcountUrl); + assertEquals(randomUrlBuilder.buildUrl(urls.rating.safe), randomUrl); + assertEquals(hotUrlBuilder.buildUrl(urls.rating.safe), hotUrl); // Filetype asserts - assertEquals(jpgUrlBuilder.buildUrl(), jpgUrl); - assertEquals(pngUrlBuilder.buildUrl(), pngUrl); - assertEquals(gifUrlBuilder.buildUrl(), gifUrl); - assertEquals(mp4UrlBuilder.buildUrl(), mp4Url); - assertEquals(webmUrlBuilder.buildUrl(), webmUrl); + assertEquals(jpgUrlBuilder.buildUrl(urls.rating.safe), jpgUrl); + assertEquals(pngUrlBuilder.buildUrl(urls.rating.safe), pngUrl); + assertEquals(gifUrlBuilder.buildUrl(urls.rating.safe), gifUrl); + assertEquals(mp4UrlBuilder.buildUrl(urls.rating.safe), mp4Url); + assertEquals(webmUrlBuilder.buildUrl(urls.rating.safe), webmUrl); // Mixed search asserts - assertEquals(mixedSearchUrlBuilder1.buildUrl(), mixedSearchUrl1); - assertEquals(mixedSearchUrlBuilder2.buildUrl(), mixedSearchUrl2); - assertEquals(mixedSearchUrlBuilder3.buildUrl(), mixedSearchUrl3); + assertEquals(mixedSearchUrlBuilder1.buildUrl(urls.rating.safe), mixedSearchUrl1); + assertEquals(mixedSearchUrlBuilder2.buildUrl(urls.rating.safe), mixedSearchUrl2); + assertEquals(mixedSearchUrlBuilder3.buildUrl(urls.rating.safe), mixedSearchUrl3); }); /** diff --git a/tests/url_builder_tests.ts b/tests/url_builder_tests.ts index d0bb695..2c0e1fe 100644 --- a/tests/url_builder_tests.ts +++ b/tests/url_builder_tests.ts @@ -7,8 +7,7 @@ Deno.test(function buildUrlPostsTest() { `https://e621.net/posts.json?tags=dragon+rating:safe&page=1&limit=${API_PAGE_SIZE}`; const testUrlBuilder = new E621UrlBuilderPosts(); testUrlBuilder.tags = ["dragon"]; - testUrlBuilder.rating = "rating:safe"; - assertEquals(testUrlBuilder.buildUrl(), testUrl); + assertEquals(testUrlBuilder.buildUrl("rating:safe"), testUrl); }); Deno.test(function buildUrlPoolsTest() { diff --git a/tests/user_tests.ts b/tests/user_tests.ts index a72d0ca..000e445 100644 --- a/tests/user_tests.ts +++ b/tests/user_tests.ts @@ -1,20 +1,22 @@ import { existsSync } from "node:fs"; import { TEST_DB_FILE } from "../constants/strings.ts"; -import { createBlacklistDb } from "../db/migration.ts"; +import { createUserDb } from "../db/migration.ts"; import { deleteUser, getUserByTelegramId as getUserByTelegramId, insertUser, - updateUser, + updateBlacklist, + updateRating, userExists, } from "../models/user.ts"; import { User } from "../types/Blacklist.ts"; import { assertEquals } from "@std/assert/equals"; import { assertObjectMatch } from "@std/assert/object-match"; -const testBlacklist: User = { +const testUser: User = { id: 1, telegramId: 12345, + rating: "s", blacklist: [ "gore", "scat", @@ -30,35 +32,46 @@ if (!existsSync("db/test_db")) { } Deno.test(function testInsertBlacklist() { - createBlacklistDb(TEST_DB_FILE); + createUserDb(TEST_DB_FILE); - const queryResult = insertUser(testBlacklist, TEST_DB_FILE); + const queryResult = insertUser(testUser, TEST_DB_FILE); assertEquals(queryResult?.changes, 1); assertEquals(queryResult?.lastInsertRowid, 1); Deno.removeSync(TEST_DB_FILE); }); Deno.test(function testGetUserByTelegramId() { - createBlacklistDb(TEST_DB_FILE); - insertUser(testBlacklist, TEST_DB_FILE); + createUserDb(TEST_DB_FILE); + insertUser(testUser, TEST_DB_FILE); const user = getUserByTelegramId(12345, TEST_DB_FILE); - console.log(user); + assertObjectMatch(user!, testUser); + Deno.removeSync(TEST_DB_FILE); +}); + +Deno.test(function testUpdateRating() { + createUserDb(TEST_DB_FILE); + insertUser(testUser, TEST_DB_FILE); + + const updatedUser = testUser; + updatedUser.rating = "e"; - assertObjectMatch(user!, testBlacklist); + const queryResults = updateRating(12345, "e", TEST_DB_FILE); + assertEquals(queryResults.changes, 1); + assertEquals(queryResults.lastInsertRowid, 0); Deno.removeSync(TEST_DB_FILE); }); Deno.test(function testUpdateUser() { - createBlacklistDb(TEST_DB_FILE); - insertUser(testBlacklist, TEST_DB_FILE); + createUserDb(TEST_DB_FILE); + insertUser(testUser, TEST_DB_FILE); - const updatedBlacklist = testBlacklist; + const updatedBlacklist = testUser; updatedBlacklist.blacklist.push("test", "tags"); - const queryResult = updateUser(updatedBlacklist, TEST_DB_FILE); + const queryResult = updateBlacklist(updatedBlacklist, TEST_DB_FILE); assertEquals(queryResult?.changes, 1); assertEquals(queryResult?.lastInsertRowid, 0); @@ -66,18 +79,18 @@ Deno.test(function testUpdateUser() { }); Deno.test(function testDeleteUser() { - createBlacklistDb(TEST_DB_FILE); - insertUser(testBlacklist, TEST_DB_FILE); + createUserDb(TEST_DB_FILE); + insertUser(testUser, TEST_DB_FILE); - const queryResult = deleteUser(testBlacklist.telegramId, TEST_DB_FILE); + const queryResult = deleteUser(testUser.telegramId, TEST_DB_FILE); assertEquals(queryResult?.changes, 1); assertEquals(queryResult?.lastInsertRowid, 0); Deno.removeSync(TEST_DB_FILE); }); Deno.test(function testUserExist() { - createBlacklistDb(TEST_DB_FILE); - insertUser(testBlacklist, TEST_DB_FILE); + createUserDb(TEST_DB_FILE); + insertUser(testUser, TEST_DB_FILE); const result1 = userExists(12345, TEST_DB_FILE); assertEquals(result1, true); From 7a4aed26ac2db5f61af02f6f189de393b6daee1d Mon Sep 17 00:00:00 2001 From: codecanna Date: Thu, 1 Jan 2026 00:09:17 -0700 Subject: [PATCH 11/14] code cleanup --- classes/E621Bot.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/classes/E621Bot.ts b/classes/E621Bot.ts index c55b180..b3e1dc3 100644 --- a/classes/E621Bot.ts +++ b/classes/E621Bot.ts @@ -85,11 +85,6 @@ export class E621Bot extends Bot { continue; } - // if (/(safe|questionable|explicit)/.test(queryTags[tag])) { - // urlBuilder.rating = encodeURIComponent(`rating:${queryTags[tag]}`); - // continue; - // } - if (/(score|favcount|random|hot)/.test(queryTags[tag])) { urlBuilder.order = encodeURIComponent(`order:${queryTags[tag]}`); continue; @@ -99,11 +94,6 @@ export class E621Bot extends Bot { urlBuilder.fileType = encodeURIComponent(`type:${queryTags[tag]}`); continue; } - - // // Ignore ratings in the query since we are pulling the rating from the db - // if (/(rating:(s|safe)|rating:(q|questionable)|rating:(e|explicit))/.test(queryTags[tag])) { - // continue; - // } parsedTags.push(queryTags[tag]); } urlBuilder.tags = parsedTags; From 5b573418b4f667b38e18cce7f8f20f060fc5aeac Mon Sep 17 00:00:00 2001 From: codecanna Date: Thu, 1 Jan 2026 00:09:32 -0700 Subject: [PATCH 12/14] Deno fmt --- README.md | 23 +++++++++++++++++++---- main.ts | 10 ++++++++-- models/user.ts | 1 - tests/parse_inline_query_tests.ts | 20 ++++++++++++++++---- types/Blacklist.ts | 2 +- 5 files changed, 44 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 82195cf..04d8784 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,11 @@ match the key words and the tags in any way you like! ## Commands -E621Bot comes with a number of commands. These commands must be used in a direct chat with the bot. As this bot is mostly an inline bot, you mostly interact with it by typing `@e621bot your query here` while in another chat to interact with it. To use commands open a direct message chat with the bot, and from there you can use slash commands (`/command`). e621Bot currently has 6 commands. +E621Bot comes with a number of commands. These commands must be used in a direct +chat with the bot. As this bot is mostly an inline bot, you mostly interact with +it by typing `@e621bot your query here` while in another chat to interact with +it. To use commands open a direct message chat with the bot, and from there you +can use slash commands (`/command`). e621Bot currently has 6 commands. - `/start` Starts the bot - `/help` Show a help message @@ -56,11 +60,19 @@ E621Bot comes with a number of commands. These commands must be used in a direc ## Blacklist -e621 has a **LOT** of tags, you may not be comfortable with all of them. That's where your blacklist comes in! You can use the blacklist to filter posts out with tags that you don't want to see. e621 itself [has default blacklist settings](https://e621.net/help/blacklist) in place for all guest users, this is the same default blacklist the bot will start you out with when you first use the bot. +e621 has a **LOT** of tags, you may not be comfortable with all of them. That's +where your blacklist comes in! You can use the blacklist to filter posts out +with tags that you don't want to see. e621 itself +[has default blacklist settings](https://e621.net/help/blacklist) in place for +all guest users, this is the same default blacklist the bot will start you out +with when you first use the bot. ## Editing your blacklist -You can edit this default list by using `/edit_blacklist`, you will be sent your current blacklist which you can copy and paste into the chat. From there you can edit it, and send it back to the bot. The bot will save your blacklist, and display the updated blacklist so you can verify the changes. +You can edit this default list by using `/edit_blacklist`, you will be sent your +current blacklist which you can copy and paste into the chat. From there you can +edit it, and send it back to the bot. The bot will save your blacklist, and +display the updated blacklist so you can verify the changes. ## How do I setup the bot? @@ -69,10 +81,13 @@ If you want to run you own version of the bot you can download the source code. ### Make sure you have all dependencies #### Dependencies: + - Deno 2.X - Sqlite3 -Once you download the source code and you have [Deno](https://deno.com/) installed you should get sqlite3 +Once you download the source code and you have [Deno](https://deno.com/) +installed you should get sqlite3 + - Ubuntu: `sudo apt install sqlite3` - Arch: `` diff --git a/main.ts b/main.ts index 558ee9d..5230ae1 100644 --- a/main.ts +++ b/main.ts @@ -84,7 +84,11 @@ if (import.meta.main) { case "questionable": case "explicit": { try { - updateRating(ctx.from?.id!, encodeURIComponent(`rating:${ctx.match}`), DB_FILE); + updateRating( + ctx.from?.id!, + encodeURIComponent(`rating:${ctx.match}`), + DB_FILE, + ); await ctx.reply(`Updated your rating to ${ctx.match}.`, { parse_mode: "HTML", }); @@ -258,7 +262,9 @@ if (import.meta.main) { console.log(`Current URL: ${urlBuilder.buildUrl(user?.rating!)}`); // Grab our data - const request = await yiffBot.sendRequest(urlBuilder.buildUrl(user?.rating!)); + const request = await yiffBot.sendRequest( + urlBuilder.buildUrl(user?.rating!), + ); const requestJson = await request.json(); const postsJson = requestJson.posts; // An array of 50 posts diff --git a/models/user.ts b/models/user.ts index 0c8067c..b25cfa2 100644 --- a/models/user.ts +++ b/models/user.ts @@ -48,7 +48,6 @@ export function updateBlacklist(user: User, dbFile: PathLike) { } /** - * * @param rating Rating the user picked * @param id Telegram Id of user * @param dbFile Path to DB file diff --git a/tests/parse_inline_query_tests.ts b/tests/parse_inline_query_tests.ts index 00704f5..f438a21 100644 --- a/tests/parse_inline_query_tests.ts +++ b/tests/parse_inline_query_tests.ts @@ -182,7 +182,10 @@ Deno.test(function parseInlineQueryTest() { // Rating asserts assertEquals(safeUrlBuilder.buildUrl(urls.rating.safe), safeUrl); - assertEquals(questionableUrlBuilder.buildUrl(urls.rating.questionable), questionableUrl); + assertEquals( + questionableUrlBuilder.buildUrl(urls.rating.questionable), + questionableUrl, + ); assertEquals(explicitUrlBuilder.buildUrl(urls.rating.explicit), explicitUrl); // Order asserts @@ -199,9 +202,18 @@ Deno.test(function parseInlineQueryTest() { assertEquals(webmUrlBuilder.buildUrl(urls.rating.safe), webmUrl); // Mixed search asserts - assertEquals(mixedSearchUrlBuilder1.buildUrl(urls.rating.safe), mixedSearchUrl1); - assertEquals(mixedSearchUrlBuilder2.buildUrl(urls.rating.safe), mixedSearchUrl2); - assertEquals(mixedSearchUrlBuilder3.buildUrl(urls.rating.safe), mixedSearchUrl3); + assertEquals( + mixedSearchUrlBuilder1.buildUrl(urls.rating.safe), + mixedSearchUrl1, + ); + assertEquals( + mixedSearchUrlBuilder2.buildUrl(urls.rating.safe), + mixedSearchUrl2, + ); + assertEquals( + mixedSearchUrlBuilder3.buildUrl(urls.rating.safe), + mixedSearchUrl3, + ); }); /** diff --git a/types/Blacklist.ts b/types/Blacklist.ts index 96f236d..a6a8c4a 100644 --- a/types/Blacklist.ts +++ b/types/Blacklist.ts @@ -1,6 +1,6 @@ export type User = { id?: number; telegramId: number; - rating: string, + rating: string; blacklist: string[]; }; From a9da2f9b4dde7a6a774e7ce05f630ea218c51dfb Mon Sep 17 00:00:00 2001 From: codecanna Date: Thu, 1 Jan 2026 00:10:52 -0700 Subject: [PATCH 13/14] bumped version number --- deno.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deno.json b/deno.json index c4db627..ea33ad2 100644 --- a/deno.json +++ b/deno.json @@ -1,5 +1,5 @@ { - "version": "0.1.0", + "version": "0.2.0", "tasks": { "dev": "deno run --allow-write --allow-net --allow-env --allow-read --watch main.ts", "test": "deno test --allow-write --allow-net --allow-env --allow-read ./tests/*", From 9951ca6b42b92f139050855f614536623a31efc6 Mon Sep 17 00:00:00 2001 From: codecanna Date: Thu, 1 Jan 2026 00:21:28 -0700 Subject: [PATCH 14/14] commented out a console.log --- classes/E621Bot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/E621Bot.ts b/classes/E621Bot.ts index b3e1dc3..e5e49be 100644 --- a/classes/E621Bot.ts +++ b/classes/E621Bot.ts @@ -240,7 +240,7 @@ export class E621Bot extends Bot { }); const tags = tagMatrix.flat(); - console.log(this.buildBlacklistRegex(blacklistedTags)); + // console.log(this.buildBlacklistRegex(blacklistedTags)); // Check for blacklisted tags for (const tag in tags) {