server.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import express from 'express';
  2. import { readFileSync } from 'node:fs';
  3. const cors = require('cors');
  4. import { createTikHubCustomizeRoutes } from './modules/fmode-tikhub-server/src/mod';
  5. import { createFeishuRoutes } from './api/module/feishu';
  6. import { createFeishuRouter } from './modules/fmode-feishu-api/src/index';
  7. // import { createPinterestRouter } from './modules/fmode-brightdata-server/src/index';
  8. const Parse = require('parse/node');
  9. Parse.initialize('hb-voc');
  10. Parse.serverURL = 'https://partyvoc.com/parse';
  11. Parse.masterKey = 'hb2026pallt';
  12. // @ts-ignore
  13. globalThis.Parse = Parse;
  14. // 获取配置
  15. function getConfig() {
  16. try {
  17. const configPath = process.env.NODE_ENV === 'test' ? './config.test.json' : './config.json';
  18. const configContent = readFileSync(configPath, 'utf-8');
  19. return JSON.parse(configContent);
  20. } catch (error: unknown) {
  21. const errorMessage = error instanceof Error ? error.message : 'Unknown error';
  22. console.warn('Config file not found, using defaults:', errorMessage);
  23. return {
  24. parse: {
  25. port: 3000,
  26. appId: 'hb-voc',
  27. serverURL: 'https://partyvoc.com/parse'
  28. }
  29. };
  30. }
  31. }
  32. // 初始化 Express 应用
  33. const app = express();
  34. // 中间件配置
  35. app.use(cors());
  36. app.use(express.json());
  37. app.use(express.urlencoded({ extended: true }));
  38. // 日志中间件
  39. app.use((req: any, res: any, next: () => void) => {
  40. console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);
  41. next();
  42. });
  43. // 健康检查端点
  44. app.get('/health', (req: any, res: any) => {
  45. res.json({
  46. status: 'healthy',
  47. timestamp: new Date().toISOString(),
  48. uptime: process.uptime()
  49. });
  50. });
  51. // 根路由
  52. app.get('/', (req: any, res: any) => {
  53. res.json({
  54. message: 'Fmode Server - Gongzuo API',
  55. version: '1.0.0',
  56. timestamp: new Date().toISOString(),
  57. endpoints: ['/api', '/health', '/api/tikhub', '/api/feishu', '/api/feishu-v2']
  58. });
  59. });
  60. // 挂载 TikHub 模块路由
  61. app.use('/api/tikhub', createTikHubCustomizeRoutes({
  62. serverURL: 'https://server.fmode.cn/thapi/v1',
  63. apiKey: 'tKIbAsEM8X+GmE2vHqGW7D/ICwK1Q5V4viKFrWiPB6HholGdLFqZJmmyNw=='
  64. }));
  65. // 挂载飞书模块路由(旧版)
  66. app.use('/api/feishu', createFeishuRoutes());
  67. // 挂载飞书模块路由(新版 fmode-feishu-api)
  68. app.use('/api/feishu-v2', createFeishuRouter({
  69. 'cli_a9253658eef99cd2': {
  70. appId: 'cli_a9253658eef99cd2',
  71. appSecret: '9ci7yeo4bA81ew63gC1OHhbhVWlNb2yx',
  72. company: 'test_company',
  73. enabled: true,
  74. environment: 'development'
  75. }
  76. }));
  77. // 挂载 Pinterest 模块路由
  78. // app.use('/api/pinterest', createPinterestRouter());
  79. // 404 处理
  80. app.use((req: any, res: any) => {
  81. res.status(404).json({
  82. message: 'Not Found',
  83. path: req.path,
  84. method: req.method
  85. });
  86. });
  87. // 错误处理中间件
  88. app.use((err: any, req: any, res: any, next: any) => {
  89. console.error('Error:', err);
  90. res.status(500).json({
  91. message: 'Internal Server Error',
  92. error: err.message
  93. });
  94. });
  95. // 启动服务器
  96. async function startServer() {
  97. const config = getConfig();
  98. const PORT = process.env.PORT || config.parse?.port || 3000;
  99. app.listen(PORT, () => {
  100. console.log('\n' + '='.repeat(60));
  101. console.log('🚀 Fmode Server - HB Started');
  102. console.log('='.repeat(60));
  103. console.log(`Timestamp: ${new Date().toISOString()}`);
  104. console.log('='.repeat(60) + '\n');
  105. });
  106. }
  107. // 优雅关闭
  108. process.on('SIGTERM', () => {
  109. console.log('\n📛 SIGTERM signal received: closing HTTP server');
  110. process.exit(0);
  111. });
  112. process.on('SIGINT', () => {
  113. console.log('\n📛 SIGINT signal received: closing HTTP server');
  114. process.exit(0);
  115. });
  116. // 启动服务器
  117. startServer().catch(err => {
  118. console.error('Failed to start server:', err);
  119. process.exit(1);
  120. });