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 { 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 {
|
||||
@ -79,7 +78,5 @@ export const init = (bot: Bot<Ctx>, db: Kysely<Database>, cfg: CompiledConfig) =
|
||||
await next()
|
||||
})
|
||||
|
||||
bot.inlineQuery(/sfbr */, async ctx => {
|
||||
await handleSafebooruQuery(ctx, getSafebooruPosts)
|
||||
})
|
||||
bot.inlineQuery(/sfbr */, async ctx => { await handleSafebooruQuery(ctx) })
|
||||
}
|
||||
|
@ -1,21 +1,35 @@
|
||||
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 { SfbrPostsReqQueryBuilder } from "../../external/safebooru.ts";
|
||||
import type { SafebooruPostData } 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<Ctx>,
|
||||
getPosts: GetSafebooruPostsFunc
|
||||
): Promise<void> => {
|
||||
// Remove the safebooru refix
|
||||
const query = ctx.inlineQuery.query.slice("sfbr".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 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[] = []
|
||||
posts.map((post) => {
|
||||
@ -25,6 +39,5 @@ export const handleSafebooruQuery = async (
|
||||
parse_mode: "MarkdownV2",
|
||||
}))
|
||||
})
|
||||
// await ctx.answerInlineQuery(results, { cache_time: 0 })
|
||||
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 type GetSafebooruPostsFunc = (limit: number, pageId: number, tags: string[]) => Promise<SafebooruPostData[]>
|
||||
interface SafebooruPostData {
|
||||
export interface SafebooruPostData {
|
||||
preview_url: string;
|
||||
sample_url: string;
|
||||
file_url: string;
|
||||
@ -28,41 +27,38 @@ interface SafebooruPostData {
|
||||
comment_count: number;
|
||||
}
|
||||
|
||||
|
||||
const tagsArrToUrlParam = (tags: string[]): 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 ""
|
||||
|
||||
let param: string = "tags="
|
||||
tags.forEach((tag, i) => {
|
||||
if (i != 0) { param += " " }
|
||||
param += tag
|
||||
})
|
||||
return param
|
||||
// https://safebooru.org/index.php?page=help&topic=dapi
|
||||
export class SfbrPostsReqQueryBuilder extends ReqUrlBuilder {
|
||||
override host = SAFEBOORU_HOST
|
||||
override path = "/index.php"
|
||||
override params = {
|
||||
"page": "dapi",
|
||||
"s": "post",
|
||||
"q": "index",
|
||||
"json": "1",
|
||||
}
|
||||
|
||||
setPostsLimit(limit: number) {
|
||||
this.setParams({ "limit": limit.toString() })
|
||||
return this
|
||||
}
|
||||
setPageID(pid: number) {
|
||||
this.setParams({ "pid": pid.toString() })
|
||||
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 {
|
||||
protected protocol: string = "https";
|
||||
protected host: string = "";
|
||||
protected path: string = "";
|
||||
protected params: { [key: string]: string } = {};
|
||||
protected protocol: string = "https";
|
||||
protected host: string = "";
|
||||
protected path: string = "";
|
||||
protected params: { [key: string]: string } = {};
|
||||
|
||||
constructor(url: string) {
|
||||
const [protocol, host] = url.split("://");
|
||||
if (host) {
|
||||
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 {
|
||||
constructor(url?: string) {
|
||||
const [protocol, host] = url ? url.split("://") : [this.host];
|
||||
if (host) {
|
||||
this.protocol = protocol
|
||||
this.host = host
|
||||
return this
|
||||
}
|
||||
setPath(path: string): ReqUrlBuilder {
|
||||
this.path = path.startsWith("/") ? path : `/${path}`
|
||||
return this
|
||||
} else {
|
||||
this.host = protocol // Default to https if no protocol provided
|
||||
}
|
||||
}
|
||||
|
||||
private addParam(key: string, value: string): ReqUrlBuilder {
|
||||
setProtocol(protocol: string): ReqUrlBuilder {
|
||||
this.protocol = protocol.replace("://", "")
|
||||
return this
|
||||
}
|
||||
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) {
|
||||
this.params[key] = value;
|
||||
this.params[key] = value
|
||||
}
|
||||
return this
|
||||
}
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
setParams(...params: string[]): ReqUrlBuilder {
|
||||
params.forEach((param) => {
|
||||
const [key, value] = param.split("=")
|
||||
if (key && value) {
|
||||
this.addParam(key, value)
|
||||
}
|
||||
})
|
||||
return this
|
||||
}
|
||||
setParams(params: { [key: string]: string }): ReqUrlBuilder {
|
||||
Object.entries(params).forEach(([key, value]) => {
|
||||
this.params[key] = value
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
setQueryParams(queryParams: { [key: string]: string }): ReqUrlBuilder {
|
||||
Object.entries(queryParams).forEach(([key, value]) => {
|
||||
this.addParam(key, value)
|
||||
})
|
||||
return this
|
||||
}
|
||||
deleteParam(name: string) {
|
||||
delete this.params[name]
|
||||
}
|
||||
|
||||
getReqURL(): string {
|
||||
const queryString = Object.keys(this.params)
|
||||
.map((key) => `${key}=${encodeURIComponent(this.params[key])}`)
|
||||
.join("&")
|
||||
return `${this.protocol}://${this.host}${this.path}${
|
||||
queryString ? "?" + queryString : ""
|
||||
}`
|
||||
}
|
||||
getReqURL(): string {
|
||||
let queryString = Object.keys(this.params)
|
||||
.map((key) => `${key}=${encodeURIComponent(this.params[key])}`)
|
||||
.join("&")
|
||||
queryString = queryString ? "?" + queryString : ""
|
||||
return this.protocol+`://`+this.host+this.path+queryString
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user