routes_classroom.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import { Hono } from 'hono'
  2. import type { Variables } from './app.tsx'
  3. import type { WithAuth } from './app.tsx'
  4. // 配置信息
  5. const IM_APP_ID = '4c2ab5e1b1b0';
  6. const IM_APP_KEY = '314bb5eee5b623549e8a41574ba3ff32';
  7. const IM_APP_SIGN = 'H4sIAAAAAAAE/wCQAG//zguHB+lYCilkv7diSkk4GmcvLuds+InRu9vFOFebMwm/jEgsK5bBT85Z0owObMxG58uXHyPFlPEBEDQm9FswNJ+KmX0VDYkcfdPPWkafA6Hc0B6F+p5De9yJfPEfHzwo/DHMaygbHfLmBgUtmKveq421sJr/gNBz9D04Ewsg39us+ao0NegzLt7xtXvFXXXJAAAA//8BAAD//yoav6aQAAAA';
  8. const RTC_APP_ID = 'a5842c2a-d94a-43be-81de-1fdb712476e1';
  9. const RTC_APP_KEY = 'b71d65f4f84c450f6f058f4ad507bd42';
  10. // const IM_APP_ID = Deno.env.get('IM_APP_ID');
  11. // const IM_APP_KEY = Deno.env.get('IM_APP_KEY');
  12. // const IM_APP_SIGN = Deno.env.get('IM_APP_SIGN');
  13. // const RTC_APP_ID = Deno.env.get('RTC_APP_ID')
  14. // const RTC_APP_KEY = Deno.env.get('RTC_APP_KEY')
  15. const hex = (buffer: ArrayBuffer): string => {
  16. const hexCodes = [];
  17. const view = new DataView(buffer);
  18. for (let i = 0; i < view.byteLength; i += 4) {
  19. const value = view.getUint32(i);
  20. const stringValue = value.toString(16);
  21. const padding = '00000000';
  22. const paddedValue = (padding + stringValue).slice(-padding.length);
  23. hexCodes.push(paddedValue);
  24. }
  25. return hexCodes.join('');
  26. };
  27. const generateRTCToken = async (
  28. channelId: string,
  29. userId: string
  30. ): Promise<{
  31. token: string;
  32. timestamp: number;
  33. }> => {
  34. const timestamp = Math.floor(Date.now() / 1000) + 3600 * 3;
  35. const encoder = new TextEncoder();
  36. const data = encoder.encode(`${RTC_APP_ID}${RTC_APP_KEY}${channelId}${userId}${timestamp}`);
  37. const hash = await crypto.subtle.digest('SHA-256', data);
  38. const token = hex(hash);
  39. return {
  40. token,
  41. timestamp
  42. }
  43. };
  44. const generateImToken = async (userId: string, role: string): Promise<{
  45. nonce: string;
  46. token: string;
  47. timestamp: number;
  48. }> => {
  49. const nonce = 'AK_4';
  50. const timestamp = Math.floor(Date.now() / 1000) + 3600 * 3;
  51. const pendingShaStr = `${IM_APP_ID}${IM_APP_KEY}${userId}${nonce}${timestamp}${role}`;
  52. const encoder = new TextEncoder();
  53. const data = encoder.encode(pendingShaStr);
  54. const hash = await crypto.subtle.digest('SHA-256', data);
  55. const token = hex(hash);
  56. return {
  57. nonce,
  58. token,
  59. timestamp
  60. }
  61. };
  62. export function createClassRoomRoutes(withAuth: WithAuth) {
  63. const tokenRoutes = new Hono<{ Variables: Variables }>()
  64. // 生成IM Token
  65. tokenRoutes.post('/im_token', withAuth, async (c) => {
  66. try {
  67. const { role } = await c.req.json()
  68. const user = c.get('user')
  69. if (!user || typeof user !== 'object' || !('id' in user)) {
  70. return c.json({ error: '用户信息无效' }, 401)
  71. }
  72. // 生成Token
  73. const { nonce, token , timestamp } = await generateImToken(user.id.toString(), role);
  74. return c.json({
  75. nonce,
  76. token,
  77. timestamp,
  78. appId: IM_APP_ID,
  79. appSign: IM_APP_SIGN,
  80. })
  81. } catch (error) {
  82. console.error('生成IM Token失败:', error)
  83. return c.json({ error: '生成IM Token失败' }, 500)
  84. }
  85. })
  86. // 生成RTC Token
  87. tokenRoutes.post('/rtc_token', withAuth, async (c) => {
  88. try {
  89. const { channelId } = await c.req.json()
  90. const user = c.get('user')
  91. if (!user || typeof user !== 'object' || !('id' in user)) {
  92. return c.json({ error: '用户信息无效' }, 401)
  93. }
  94. if (!RTC_APP_ID || !RTC_APP_KEY) {
  95. return c.json({ error: '服务配置不完整' }, 500)
  96. }
  97. // 生成Token
  98. const { token , timestamp } = await generateRTCToken(channelId, user.id.toString());
  99. return c.json({
  100. token,
  101. timestamp,
  102. appId: RTC_APP_ID,
  103. })
  104. } catch (error) {
  105. console.error('生成RTC Token失败:', error)
  106. return c.json({ error: '生成RTC Token失败' }, 500)
  107. }
  108. })
  109. return tokenRoutes
  110. }