sfbr inline query fix and refactoring
This commit is contained in:
parent
e847cf5af8
commit
84efb90a22
@ -6,7 +6,6 @@ import { Database } from "../../repo/exports.ts";
|
|||||||
import { CompiledConfig } from "../../cfg/config.ts";
|
import { CompiledConfig } from "../../cfg/config.ts";
|
||||||
import { checkUser, checkUserOnNewChatMember, onMemberLeftChat, checkUserOnStart } from "./user_managment.ts";
|
import { checkUser, checkUserOnNewChatMember, onMemberLeftChat, checkUserOnStart } from "./user_managment.ts";
|
||||||
import { checkCaptchaSolution, initUserCaptcha } from "./captcha.ts";
|
import { checkCaptchaSolution, initUserCaptcha } from "./captcha.ts";
|
||||||
import { getSafebooruPosts } from "../../external/safebooru.ts";
|
|
||||||
import { handleSafebooruQuery } from "./safebooru.ts";
|
import { handleSafebooruQuery } from "./safebooru.ts";
|
||||||
|
|
||||||
interface ChatMemberUpdateStatus {
|
interface ChatMemberUpdateStatus {
|
||||||
@ -79,7 +78,5 @@ export const init = (bot: Bot<Ctx>, db: Kysely<Database>, cfg: CompiledConfig) =
|
|||||||
await next()
|
await next()
|
||||||
})
|
})
|
||||||
|
|
||||||
bot.inlineQuery(/sfbr */, async ctx => {
|
bot.inlineQuery(/sfbr */, async ctx => { await handleSafebooruQuery(ctx) })
|
||||||
await handleSafebooruQuery(ctx, getSafebooruPosts)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,35 @@
|
|||||||
import { InlineQueryResultBuilder, type InlineQueryContext } from "https://deno.land/x/grammy/mod.ts";
|
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 { InlineQueryResult } from "https://deno.land/x/grammy_types/inline.ts";
|
||||||
import type { Ctx } from "../ctx.ts";
|
import type { Ctx } from "../ctx.ts";
|
||||||
import type { GetSafebooruPostsFunc } from "../../external/safebooru.ts";
|
import { SfbrPostsReqQueryBuilder } from "../../external/safebooru.ts";
|
||||||
|
import type { SafebooruPostData } from "../../external/safebooru.ts";
|
||||||
import { SAFEBOORU_HOST } from "../../external/safebooru.ts";
|
import { SAFEBOORU_HOST } from "../../external/safebooru.ts";
|
||||||
|
|
||||||
export const DEFAULT_POSTS_LIMIT = 30
|
export const DEFAULT_POSTS_LIMIT = 30
|
||||||
export const DEFAULT_START_PAGE_ID = 0
|
|
||||||
|
|
||||||
export const handleSafebooruQuery = async (
|
export const handleSafebooruQuery = async (
|
||||||
ctx: InlineQueryContext<Ctx>,
|
ctx: InlineQueryContext<Ctx>,
|
||||||
getPosts: GetSafebooruPostsFunc
|
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
// Remove the safebooru refix
|
|
||||||
const query = ctx.inlineQuery.query.slice("sfbr".length)
|
const query = ctx.inlineQuery.query.slice("sfbr".length)
|
||||||
const tags = query.split(" ")
|
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 reqURL = new SfbrPostsReqQueryBuilder()
|
||||||
|
.setPostsLimit(DEFAULT_POSTS_LIMIT)
|
||||||
|
.setPageID(1).setTags(tags).getReqURL()
|
||||||
|
|
||||||
|
const resp = await fetch(reqURL)
|
||||||
|
if (!resp.ok) {
|
||||||
|
console.log(`Error response from safebooru. URL: ${reqURL} Status: ${resp.status} ${resp.text}`)
|
||||||
|
const results: InlineQueryResult[] = []
|
||||||
|
await ctx.api.answerInlineQuery(ctx.inlineQuery.id, results, { cache_time: 1 })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const posts: SafebooruPostData[] = await resp.json()
|
||||||
|
if (posts.length === 0) {
|
||||||
|
console.log(`Empty response body from safebooru. URL: ${reqURL}`)
|
||||||
|
await ctx.api.answerInlineQuery(ctx.inlineQuery.id, [], { cache_time: 1 })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const results: InlineQueryResult[] = []
|
const results: InlineQueryResult[] = []
|
||||||
posts.map((post) => {
|
posts.map((post) => {
|
||||||
@ -25,6 +39,5 @@ export const handleSafebooruQuery = async (
|
|||||||
parse_mode: "MarkdownV2",
|
parse_mode: "MarkdownV2",
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
// await ctx.answerInlineQuery(results, { cache_time: 0 })
|
|
||||||
await ctx.api.answerInlineQuery(ctx.inlineQuery.id, results, { cache_time: 1 })
|
await ctx.api.answerInlineQuery(ctx.inlineQuery.id, results, { cache_time: 1 })
|
||||||
}
|
}
|
||||||
|
70
external/safebooru.ts
vendored
70
external/safebooru.ts
vendored
@ -2,8 +2,7 @@ import { ReqUrlBuilder } from "../utils/url_builder.ts";
|
|||||||
|
|
||||||
export const SAFEBOORU_HOST = "safebooru.org"
|
export const SAFEBOORU_HOST = "safebooru.org"
|
||||||
|
|
||||||
export type GetSafebooruPostsFunc = (limit: number, pageId: number, tags: string[]) => Promise<SafebooruPostData[]>
|
export interface SafebooruPostData {
|
||||||
interface SafebooruPostData {
|
|
||||||
preview_url: string;
|
preview_url: string;
|
||||||
sample_url: string;
|
sample_url: string;
|
||||||
file_url: string;
|
file_url: string;
|
||||||
@ -28,41 +27,38 @@ interface SafebooruPostData {
|
|||||||
comment_count: number;
|
comment_count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://safebooru.org/index.php?page=help&topic=dapi
|
||||||
const tagsArrToUrlParam = (tags: string[]): string => {
|
export class SfbrPostsReqQueryBuilder extends ReqUrlBuilder {
|
||||||
if (tags.length > 0) {
|
override host = SAFEBOORU_HOST
|
||||||
let hasNonEmpty = false
|
override path = "/index.php"
|
||||||
for (let i = 0; i < tags.length; i++) {
|
override params = {
|
||||||
if (tags[i].length > 0) {
|
"page": "dapi",
|
||||||
hasNonEmpty = true
|
"s": "post",
|
||||||
break
|
"q": "index",
|
||||||
}
|
"json": "1",
|
||||||
}
|
}
|
||||||
if (!hasNonEmpty) return ""
|
|
||||||
|
setPostsLimit(limit: number) {
|
||||||
let param: string = "tags="
|
this.setParams({ "limit": limit.toString() })
|
||||||
tags.forEach((tag, i) => {
|
return this
|
||||||
if (i != 0) { param += " " }
|
}
|
||||||
param += tag
|
setPageID(pid: number) {
|
||||||
})
|
this.setParams({ "pid": pid.toString() })
|
||||||
return param
|
return this
|
||||||
|
}
|
||||||
|
setTags(tags: string[]) {
|
||||||
|
if (tags.length > 0) {
|
||||||
|
let hasNonEmpty = false
|
||||||
|
for (let i = 0; i < tags.length; i++) {
|
||||||
|
if (tags[i].length > 0) {
|
||||||
|
hasNonEmpty = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasNonEmpty) return this
|
||||||
|
this.setParams({ "tags:": tags.join(" ") })
|
||||||
|
}
|
||||||
|
return this
|
||||||
}
|
}
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
const mkPostsLimitParam = (limit: number): string => `limit=${limit}`
|
|
||||||
const mkPageIdParam = (pid: number): string => `pid=${pid}`
|
|
||||||
|
|
||||||
|
|
||||||
export const getSafebooruPosts = async (limit: number, pageId: number, tags: string[]): Promise<SafebooruPostData[]> => {
|
|
||||||
const reqURL = new ReqUrlBuilder(`${SAFEBOORU_HOST}`).setProtocol("https").setPath("/index.php")
|
|
||||||
.setParams("page=dapi", "s=post", "q=index", "json=1") // Default for safebooru API
|
|
||||||
.setParams(mkPostsLimitParam(limit), mkPageIdParam(pageId))
|
|
||||||
.setParams(tagsArrToUrlParam(tags)).getReqURL()
|
|
||||||
|
|
||||||
const resp = await fetch(reqURL)
|
|
||||||
if (!resp.ok) { return [] }
|
|
||||||
const respData = await resp.text()
|
|
||||||
if (respData.length < 3) return []
|
|
||||||
const posts: SafebooruPostData[] = JSON.parse(respData)
|
|
||||||
return posts
|
|
||||||
}
|
|
||||||
|
@ -1,62 +1,58 @@
|
|||||||
export class ReqUrlBuilder {
|
export class ReqUrlBuilder {
|
||||||
protected protocol: string = "https";
|
protected protocol: string = "https";
|
||||||
protected host: string = "";
|
protected host: string = "";
|
||||||
protected path: string = "";
|
protected path: string = "";
|
||||||
protected params: { [key: string]: string } = {};
|
protected params: { [key: string]: string } = {};
|
||||||
|
|
||||||
constructor(url: string) {
|
constructor(url?: string) {
|
||||||
const [protocol, host] = url.split("://");
|
const [protocol, host] = url ? url.split("://") : [this.host];
|
||||||
if (host) {
|
if (host) {
|
||||||
this.protocol = protocol
|
this.protocol = protocol
|
||||||
this.host = host
|
|
||||||
} else {
|
|
||||||
this.host = protocol // Default to https if no protocol provided
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setProtocol(protocol: string): ReqUrlBuilder {
|
|
||||||
this.protocol = protocol.replace("://", "")
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
setHost(host: string): ReqUrlBuilder {
|
|
||||||
this.host = host
|
this.host = host
|
||||||
return this
|
} else {
|
||||||
|
this.host = protocol // Default to https if no protocol provided
|
||||||
}
|
}
|
||||||
setPath(path: string): ReqUrlBuilder {
|
}
|
||||||
this.path = path.startsWith("/") ? path : `/${path}`
|
|
||||||
return this
|
setProtocol(protocol: string): ReqUrlBuilder {
|
||||||
}
|
this.protocol = protocol.replace("://", "")
|
||||||
|
return this
|
||||||
private addParam(key: string, value: string): ReqUrlBuilder {
|
}
|
||||||
|
setHost(host: string): ReqUrlBuilder {
|
||||||
|
this.host = host
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
setPath(path: string): ReqUrlBuilder {
|
||||||
|
this.path = path.startsWith("/") ? path : `/${path}`
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
setParamsStr(...params: string[]): ReqUrlBuilder {
|
||||||
|
params.forEach((param) => {
|
||||||
|
const [key, value] = param.split("=")
|
||||||
if (key && value) {
|
if (key && value) {
|
||||||
this.params[key] = value;
|
this.params[key] = value
|
||||||
}
|
}
|
||||||
return this
|
})
|
||||||
}
|
return this
|
||||||
|
}
|
||||||
setParams(...params: string[]): ReqUrlBuilder {
|
|
||||||
params.forEach((param) => {
|
setParams(params: { [key: string]: string }): ReqUrlBuilder {
|
||||||
const [key, value] = param.split("=")
|
Object.entries(params).forEach(([key, value]) => {
|
||||||
if (key && value) {
|
this.params[key] = value
|
||||||
this.addParam(key, value)
|
})
|
||||||
}
|
return this
|
||||||
})
|
}
|
||||||
return this
|
|
||||||
}
|
deleteParam(name: string) {
|
||||||
|
delete this.params[name]
|
||||||
setQueryParams(queryParams: { [key: string]: string }): ReqUrlBuilder {
|
}
|
||||||
Object.entries(queryParams).forEach(([key, value]) => {
|
|
||||||
this.addParam(key, value)
|
getReqURL(): string {
|
||||||
})
|
let queryString = Object.keys(this.params)
|
||||||
return this
|
.map((key) => `${key}=${encodeURIComponent(this.params[key])}`)
|
||||||
}
|
.join("&")
|
||||||
|
queryString = queryString ? "?" + queryString : ""
|
||||||
getReqURL(): string {
|
return this.protocol+`://`+this.host+this.path+queryString
|
||||||
const queryString = Object.keys(this.params)
|
}
|
||||||
.map((key) => `${key}=${encodeURIComponent(this.params[key])}`)
|
|
||||||
.join("&")
|
|
||||||
return `${this.protocol}://${this.host}${this.path}${
|
|
||||||
queryString ? "?" + queryString : ""
|
|
||||||
}`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user