Initial commit

This commit is contained in:
Lucid Kobold
2025-02-19 10:12:42 -05:00
committed by GitHub
commit 15dd54cebd
37 changed files with 8132 additions and 0 deletions

102
src/server/index.ts Normal file
View File

@@ -0,0 +1,102 @@
import type { Bot } from '#root/bot/index.js'
import type { Config } from '#root/config.js'
import type { Logger } from '#root/logger.js'
import type { Env } from '#root/server/environment.js'
import { setLogger } from '#root/server/middlewares/logger.js'
import { requestId } from '#root/server/middlewares/request-id.js'
import { requestLogger } from '#root/server/middlewares/request-logger.js'
import { serve } from '@hono/node-server'
import { webhookCallback } from 'grammy'
import { Hono } from 'hono'
import { HTTPException } from 'hono/http-exception'
import { getPath } from 'hono/utils/url'
interface Dependencies {
bot: Bot
config: Config
logger: Logger
}
export function createServer(dependencies: Dependencies) {
const {
bot,
config,
logger,
} = dependencies
const server = new Hono<Env>()
server.use(requestId())
server.use(setLogger(logger))
if (config.isDebug)
server.use(requestLogger())
server.onError(async (error, c) => {
if (error instanceof HTTPException) {
if (error.status < 500)
c.var.logger.info(error)
else
c.var.logger.error(error)
return error.getResponse()
}
// unexpected error
c.var.logger.error({
err: error,
method: c.req.raw.method,
path: getPath(c.req.raw),
})
return c.json(
{
error: 'Oops! Something went wrong.',
},
500,
)
})
server.get('/', c => c.json({ status: true }))
if (config.isWebhookMode) {
server.post(
'/webhook',
webhookCallback(bot, 'hono', {
secretToken: config.botWebhookSecret,
}),
)
}
return server
}
export type Server = Awaited<ReturnType<typeof createServer>>
export function createServerManager(server: Server, options: { host: string, port: number }) {
let handle: undefined | ReturnType<typeof serve>
return {
start() {
return new Promise<{ url: string }>((resolve) => {
handle = serve(
{
fetch: server.fetch,
hostname: options.host,
port: options.port,
},
info => resolve({
url: info.family === 'IPv6'
? `http://[${info.address}]:${info.port}`
: `http://${info.address}:${info.port}`,
}),
)
})
},
stop() {
return new Promise<void>((resolve) => {
if (handle)
handle.close(() => resolve())
else
resolve()
})
},
}
}