From 07704dbaff1b5c2de3b1bf44be6546d120e5ceab Mon Sep 17 00:00:00 2001 From: Dmitry Anderson <4nd3r5z0n@gmail.com> Date: Sat, 26 Oct 2024 18:21:50 +0200 Subject: [PATCH] Safebooru functionality added --- README.md | 2 +- bot/normal_mode/init.ts | 6 + bot/normal_mode/safebooru.ts | 30 ++++ deno.lock | 274 ++++++++++++++++------------------- external/safebooru.ts | 2 - 5 files changed, 165 insertions(+), 149 deletions(-) create mode 100644 bot/normal_mode/safebooru.ts diff --git a/README.md b/README.md index 3077f6b..874f080 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ When new user starts the bot it sends him a captcha. After passing the captcha u ### Safebooru image search To search images via safebooru just type in your message prompt
-`@mental_illness_center_bot safebooru `
+`@mental_illness_center_bot sfbr `
and it will find images for you. ## TODO: diff --git a/bot/normal_mode/init.ts b/bot/normal_mode/init.ts index eace69e..878821b 100644 --- a/bot/normal_mode/init.ts +++ b/bot/normal_mode/init.ts @@ -6,6 +6,8 @@ import { Database } from "../../repo/exports.ts"; import { CompiledConfig } from "../../cfg/config.ts"; import { checkUser, checkUserOnNewChatMember, onMemberLeftChat, checkUserOnStart } from "./user_managment.ts"; import { checkCaptchaSolution, initUserCaptcha } from "./captcha.ts"; +import { getSafebooruPosts } from "../../external/safebooru.ts"; +import { handleSafebooruQuery } from "./safebooru.ts"; interface ChatMemberUpdateStatus { joined: boolean, @@ -76,4 +78,8 @@ export const init = (bot: Bot, db: Kysely, cfg: CompiledConfig) = } await next() }) + + bot.inlineQuery(/sfbr */, async ctx => { + await handleSafebooruQuery(ctx, getSafebooruPosts) + }) } diff --git a/bot/normal_mode/safebooru.ts b/bot/normal_mode/safebooru.ts new file mode 100644 index 0000000..c8e3765 --- /dev/null +++ b/bot/normal_mode/safebooru.ts @@ -0,0 +1,30 @@ +import { InlineQueryResultBuilder, type InlineQueryContext } from "https://deno.land/x/grammy/mod.ts"; +import type { InlineQueryResult } from "https://deno.land/x/grammy_types/inline.ts"; +import type { Ctx } from "../ctx.ts"; +import type { GetSafebooruPostsFunc } from "../../external/safebooru.ts"; +import { SAFEBOORU_HOST } from "../../external/safebooru.ts"; + +export const DEFAULT_POSTS_LIMIT = 30 +export const DEFAULT_START_PAGE_ID = 0 + +export const handleSafebooruQuery = async ( + ctx: InlineQueryContext, + getPosts: GetSafebooruPostsFunc +): Promise => { + // Remove the safebooru refix + const query = ctx.inlineQuery.query.slice("safebooru".length) + const tags = query.split(" ") + // So we make a request, get some posts in a structure + const posts = await getPosts(DEFAULT_POSTS_LIMIT, DEFAULT_START_PAGE_ID, tags) + + const results: InlineQueryResult[] = [] + posts.map((post) => { + results.push(InlineQueryResultBuilder.photo(`id-${post.id}`, post.file_url, { + thumbnail_url: post.preview_url, + caption: `[source](https://${SAFEBOORU_HOST}/index.php?page=post&s=view&id=${post.id})`, + parse_mode: "MarkdownV2", + })) + }) + // await ctx.answerInlineQuery(results, { cache_time: 0 }) + await ctx.api.answerInlineQuery(ctx.inlineQuery.id, results, { cache_time: 1 }) +} diff --git a/deno.lock b/deno.lock index eaeda38..4625ceb 100644 --- a/deno.lock +++ b/deno.lock @@ -1,156 +1,138 @@ { - "version": "3", - "packages": { - "specifiers": { - "jsr:@std/path": "jsr:@std/path@1.0.6", - "npm:@types/node": "npm:@types/node@18.16.19", - "npm:@types/pg": "npm:@types/pg@8.11.10", - "npm:kysely": "npm:kysely@0.27.4", - "npm:pg": "npm:pg@8.13.0" + "version": "4", + "specifiers": { + "jsr:@std/path@*": "1.0.6", + "npm:@types/node@*": "18.16.19", + "npm:@types/pg@*": "8.11.10", + "npm:kysely@*": "0.27.4", + "npm:pg@*": "8.13.0" + }, + "jsr": { + "@std/path@1.0.6": { + "integrity": "ab2c55f902b380cf28e0eec501b4906e4c1960d13f00e11cfbcd21de15f18fed" + } + }, + "npm": { + "@types/node@18.16.19": { + "integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==" }, - "jsr": { - "@std/path@1.0.6": { - "integrity": "ab2c55f902b380cf28e0eec501b4906e4c1960d13f00e11cfbcd21de15f18fed" - } + "@types/pg@8.11.10": { + "integrity": "sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==", + "dependencies": [ + "@types/node", + "pg-protocol", + "pg-types@4.0.2" + ] }, - "npm": { - "@types/node@18.16.19": { - "integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==", - "dependencies": {} - }, - "@types/pg@8.11.10": { - "integrity": "sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==", - "dependencies": { - "@types/node": "@types/node@18.16.19", - "pg-protocol": "pg-protocol@1.7.0", - "pg-types": "pg-types@4.0.2" - } - }, - "kysely@0.27.4": { - "integrity": "sha512-dyNKv2KRvYOQPLCAOCjjQuCk4YFd33BvGdf/o5bC7FiW+BB6snA81Zt+2wT9QDFzKqxKa5rrOmvlK/anehCcgA==", - "dependencies": {} - }, - "obuf@1.1.2": { - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dependencies": {} - }, - "pg-cloudflare@1.1.1": { - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "dependencies": {} - }, - "pg-connection-string@2.7.0": { - "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==", - "dependencies": {} - }, - "pg-int8@1.0.1": { - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "dependencies": {} - }, - "pg-numeric@1.0.2": { - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dependencies": {} - }, - "pg-pool@3.7.0_pg@8.13.0": { - "integrity": "sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==", - "dependencies": { - "pg": "pg@8.13.0" - } - }, - "pg-protocol@1.7.0": { - "integrity": "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==", - "dependencies": {} - }, - "pg-types@2.2.0": { - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dependencies": { - "pg-int8": "pg-int8@1.0.1", - "postgres-array": "postgres-array@2.0.0", - "postgres-bytea": "postgres-bytea@1.0.0", - "postgres-date": "postgres-date@1.0.7", - "postgres-interval": "postgres-interval@1.2.0" - } - }, - "pg-types@4.0.2": { - "integrity": "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==", - "dependencies": { - "pg-int8": "pg-int8@1.0.1", - "pg-numeric": "pg-numeric@1.0.2", - "postgres-array": "postgres-array@3.0.2", - "postgres-bytea": "postgres-bytea@3.0.0", - "postgres-date": "postgres-date@2.1.0", - "postgres-interval": "postgres-interval@3.0.0", - "postgres-range": "postgres-range@1.1.4" - } - }, - "pg@8.13.0": { - "integrity": "sha512-34wkUTh3SxTClfoHB3pQ7bIMvw9dpFU1audQQeZG837fmHfHpr14n/AELVDoOYVDW2h5RDWU78tFjkD+erSBsw==", - "dependencies": { - "pg-cloudflare": "pg-cloudflare@1.1.1", - "pg-connection-string": "pg-connection-string@2.7.0", - "pg-pool": "pg-pool@3.7.0_pg@8.13.0", - "pg-protocol": "pg-protocol@1.7.0", - "pg-types": "pg-types@2.2.0", - "pgpass": "pgpass@1.0.5" - } - }, - "pgpass@1.0.5": { - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "dependencies": { - "split2": "split2@4.2.0" - } - }, - "postgres-array@2.0.0": { - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "dependencies": {} - }, - "postgres-array@3.0.2": { - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dependencies": {} - }, - "postgres-bytea@1.0.0": { - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "dependencies": {} - }, - "postgres-bytea@3.0.0": { - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dependencies": { - "obuf": "obuf@1.1.2" - } - }, - "postgres-date@1.0.7": { - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "dependencies": {} - }, - "postgres-date@2.1.0": { - "integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==", - "dependencies": {} - }, - "postgres-interval@1.2.0": { - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "dependencies": { - "xtend": "xtend@4.0.2" - } - }, - "postgres-interval@3.0.0": { - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dependencies": {} - }, - "postgres-range@1.1.4": { - "integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==", - "dependencies": {} - }, - "split2@4.2.0": { - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dependencies": {} - }, - "xtend@4.0.2": { - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dependencies": {} - } + "kysely@0.27.4": { + "integrity": "sha512-dyNKv2KRvYOQPLCAOCjjQuCk4YFd33BvGdf/o5bC7FiW+BB6snA81Zt+2wT9QDFzKqxKa5rrOmvlK/anehCcgA==" + }, + "obuf@1.1.2": { + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "pg-cloudflare@1.1.1": { + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==" + }, + "pg-connection-string@2.7.0": { + "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==" + }, + "pg-int8@1.0.1": { + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-numeric@1.0.2": { + "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==" + }, + "pg-pool@3.7.0_pg@8.13.0": { + "integrity": "sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==", + "dependencies": [ + "pg" + ] + }, + "pg-protocol@1.7.0": { + "integrity": "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==" + }, + "pg-types@2.2.0": { + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": [ + "pg-int8", + "postgres-array@2.0.0", + "postgres-bytea@1.0.0", + "postgres-date@1.0.7", + "postgres-interval@1.2.0" + ] + }, + "pg-types@4.0.2": { + "integrity": "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==", + "dependencies": [ + "pg-int8", + "pg-numeric", + "postgres-array@3.0.2", + "postgres-bytea@3.0.0", + "postgres-date@2.1.0", + "postgres-interval@3.0.0", + "postgres-range" + ] + }, + "pg@8.13.0": { + "integrity": "sha512-34wkUTh3SxTClfoHB3pQ7bIMvw9dpFU1audQQeZG837fmHfHpr14n/AELVDoOYVDW2h5RDWU78tFjkD+erSBsw==", + "dependencies": [ + "pg-cloudflare", + "pg-connection-string", + "pg-pool", + "pg-protocol", + "pg-types@2.2.0", + "pgpass" + ] + }, + "pgpass@1.0.5": { + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": [ + "split2" + ] + }, + "postgres-array@2.0.0": { + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + }, + "postgres-array@3.0.2": { + "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==" + }, + "postgres-bytea@1.0.0": { + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==" + }, + "postgres-bytea@3.0.0": { + "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", + "dependencies": [ + "obuf" + ] + }, + "postgres-date@1.0.7": { + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" + }, + "postgres-date@2.1.0": { + "integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==" + }, + "postgres-interval@1.2.0": { + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": [ + "xtend" + ] + }, + "postgres-interval@3.0.0": { + "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==" + }, + "postgres-range@1.1.4": { + "integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==" + }, + "split2@4.2.0": { + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" + }, + "xtend@4.0.2": { + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" } }, "redirects": { "https://deno.land/x/grammy/mod.ts": "https://deno.land/x/grammy@v1.30.0/mod.ts", + "https://deno.land/x/grammy_types/inline.ts": "https://deno.land/x/grammy_types@v3.14.0/inline.ts", "https://deno.land/x/grammy_types/manage.ts": "https://deno.land/x/grammy_types@v3.14.0/manage.ts" }, "remote": { diff --git a/external/safebooru.ts b/external/safebooru.ts index 4da2ba5..9ac410d 100644 --- a/external/safebooru.ts +++ b/external/safebooru.ts @@ -1,7 +1,5 @@ import { ReqUrlBuilder } from "../utils/url_builder.ts"; -export const DEFAULT_POSTS_LIMIT = 30 -export const DEFAULT_START_PAGE_ID = 0 export const SAFEBOORU_HOST = "safebooru.org" export type GetSafebooruPostsFunc = (limit: number, pageId: number, tags: string[]) => Promise