import { Hono } from 'hono' import type { Variables , WithAuth } from './middlewares.ts' // 配置信息 const IM_APP_ID = Deno.env.get('IM_APP_ID'); const IM_APP_KEY = Deno.env.get('IM_APP_KEY'); const IM_APP_SIGN = Deno.env.get('IM_APP_SIGN'); const RTC_APP_ID = Deno.env.get('RTC_APP_ID') const RTC_APP_KEY = Deno.env.get('RTC_APP_KEY') const hex = (buffer: ArrayBuffer): string => { const hexCodes = []; const view = new DataView(buffer); for (let i = 0; i < view.byteLength; i += 4) { const value = view.getUint32(i); const stringValue = value.toString(16); const padding = '00000000'; const paddedValue = (padding + stringValue).slice(-padding.length); hexCodes.push(paddedValue); } return hexCodes.join(''); }; const generateRTCToken = async ( channelId: string, userId: string ): Promise<{ token: string; timestamp: number; }> => { const timestamp = Math.floor(Date.now() / 1000) + 3600 * 3; const encoder = new TextEncoder(); const data = encoder.encode(`${RTC_APP_ID}${RTC_APP_KEY}${channelId}${userId}${timestamp}`); const hash = await crypto.subtle.digest('SHA-256', data); const token = hex(hash); return { token, timestamp } }; const generateImToken = async (userId: string, role: string): Promise<{ nonce: string; token: string; timestamp: number; }> => { const nonce = 'AK_4'; const timestamp = Math.floor(Date.now() / 1000) + 3600 * 3; const pendingShaStr = `${IM_APP_ID}${IM_APP_KEY}${userId}${nonce}${timestamp}${role}`; const encoder = new TextEncoder(); const data = encoder.encode(pendingShaStr); const hash = await crypto.subtle.digest('SHA-256', data); const token = hex(hash); return { nonce, token, timestamp } }; export function createClassRoomRoutes(withAuth: WithAuth) { const tokenRoutes = new Hono<{ Variables: Variables }>() // 生成IM Token tokenRoutes.post('/im_token', withAuth, async (c) => { try { const { role } = await c.req.json() const user = c.get('user') if (!user || typeof user !== 'object' || !('id' in user)) { return c.json({ error: '用户信息无效' }, 401) } // 生成Token const { nonce, token , timestamp } = await generateImToken(user.id.toString(), role); return c.json({ nonce, token, timestamp, appId: IM_APP_ID, appSign: IM_APP_SIGN, }) } catch (error) { console.error('生成IM Token失败:', error) return c.json({ error: '生成IM Token失败' }, 500) } }) // 生成RTC Token tokenRoutes.post('/rtc_token', withAuth, async (c) => { try { const { channelId } = await c.req.json() const user = c.get('user') if (!user || typeof user !== 'object' || !('id' in user)) { return c.json({ error: '用户信息无效' }, 401) } if (!RTC_APP_ID || !RTC_APP_KEY) { return c.json({ error: '服务配置不完整' }, 500) } // 生成Token const { token , timestamp } = await generateRTCToken(channelId, user.id.toString()); return c.json({ token, timestamp, appId: RTC_APP_ID, }) } catch (error) { console.error('生成RTC Token失败:', error) return c.json({ error: '生成RTC Token失败' }, 500) } }) return tokenRoutes }