subscriptionRoutes.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. const express = require('express');
  2. const { Subscription } = require('../models');
  3. const MultiSubscriptionManager = require('../core/multiSubscriptionManager');
  4. const logger = require('../utils/logger');
  5. const router = express.Router();
  6. const subscriptionManager = new MultiSubscriptionManager();
  7. /**
  8. * 获取所有订阅列表
  9. */
  10. router.get('/subscriptions', async (req, res) => {
  11. try {
  12. const subscriptions = await Subscription.findAll({
  13. order: [['createdAt', 'DESC']]
  14. });
  15. res.json({
  16. success: true,
  17. data: subscriptions
  18. });
  19. } catch (error) {
  20. logger.error('获取订阅列表失败', { error: error.message });
  21. res.status(500).json({
  22. success: false,
  23. error: error.message
  24. });
  25. }
  26. });
  27. /**
  28. * 获取单个订阅详情
  29. */
  30. router.get('/subscriptions/:id', async (req, res) => {
  31. try {
  32. const subscription = await Subscription.findByPk(req.params.id);
  33. if (!subscription) {
  34. return res.status(404).json({
  35. success: false,
  36. error: '订阅不存在'
  37. });
  38. }
  39. res.json({
  40. success: true,
  41. data: subscription
  42. });
  43. } catch (error) {
  44. logger.error('获取订阅详情失败', { error: error.message });
  45. res.status(500).json({
  46. success: false,
  47. error: error.message
  48. });
  49. }
  50. });
  51. /**
  52. * 创建新订阅
  53. */
  54. router.post('/subscriptions', async (req, res) => {
  55. try {
  56. const { name, url, description, speedTestConfig, notifyConfig } = req.body;
  57. if (!name || !url) {
  58. return res.status(400).json({
  59. success: false,
  60. error: '订阅名称和URL不能为空'
  61. });
  62. }
  63. // 检查URL是否已存在
  64. const existingSubscription = await Subscription.findOne({
  65. where: { url }
  66. });
  67. if (existingSubscription) {
  68. return res.status(400).json({
  69. success: false,
  70. error: '该订阅URL已存在'
  71. });
  72. }
  73. const subscription = await Subscription.create({
  74. name,
  75. url,
  76. description,
  77. speedTestConfig: speedTestConfig || {
  78. testCount: 3,
  79. timeout: 10000,
  80. testUrls: ['https://www.google.com', 'https://www.youtube.com'],
  81. speedTestEnabled: true
  82. },
  83. notifyConfig: notifyConfig || {
  84. enabled: true,
  85. notifyOnSpeedTest: true,
  86. notifyOnNodeUpdate: true,
  87. webhookUrl: '',
  88. emailConfig: null
  89. }
  90. });
  91. logger.info('创建新订阅成功', {
  92. subscriptionId: subscription.id,
  93. subscriptionName: subscription.name
  94. });
  95. res.status(201).json({
  96. success: true,
  97. data: subscription
  98. });
  99. } catch (error) {
  100. logger.error('创建订阅失败', { error: error.message });
  101. res.status(500).json({
  102. success: false,
  103. error: error.message
  104. });
  105. }
  106. });
  107. /**
  108. * 更新订阅
  109. */
  110. router.put('/subscriptions/:id', async (req, res) => {
  111. try {
  112. const subscription = await Subscription.findByPk(req.params.id);
  113. if (!subscription) {
  114. return res.status(404).json({
  115. success: false,
  116. error: '订阅不存在'
  117. });
  118. }
  119. const { name, url, description, speedTestConfig, notifyConfig, isActive } = req.body;
  120. // 如果更新URL,检查是否与其他订阅冲突
  121. if (url && url !== subscription.url) {
  122. const existingSubscription = await Subscription.findOne({
  123. where: {
  124. url,
  125. id: { [require('sequelize').Op.ne]: req.params.id }
  126. }
  127. });
  128. if (existingSubscription) {
  129. return res.status(400).json({
  130. success: false,
  131. error: '该订阅URL已被其他订阅使用'
  132. });
  133. }
  134. }
  135. await subscription.update({
  136. name: name || subscription.name,
  137. url: url || subscription.url,
  138. description: description !== undefined ? description : subscription.description,
  139. speedTestConfig: speedTestConfig || subscription.speedTestConfig,
  140. notifyConfig: notifyConfig || subscription.notifyConfig,
  141. isActive: isActive !== undefined ? isActive : subscription.isActive
  142. });
  143. logger.info('更新订阅成功', {
  144. subscriptionId: subscription.id,
  145. subscriptionName: subscription.name
  146. });
  147. res.json({
  148. success: true,
  149. data: subscription
  150. });
  151. } catch (error) {
  152. logger.error('更新订阅失败', { error: error.message });
  153. res.status(500).json({
  154. success: false,
  155. error: error.message
  156. });
  157. }
  158. });
  159. /**
  160. * 删除订阅
  161. */
  162. router.delete('/subscriptions/:id', async (req, res) => {
  163. try {
  164. const subscription = await Subscription.findByPk(req.params.id);
  165. if (!subscription) {
  166. return res.status(404).json({
  167. success: false,
  168. error: '订阅不存在'
  169. });
  170. }
  171. await subscription.destroy();
  172. logger.info('删除订阅成功', {
  173. subscriptionId: subscription.id,
  174. subscriptionName: subscription.name
  175. });
  176. res.json({
  177. success: true,
  178. message: '订阅删除成功'
  179. });
  180. } catch (error) {
  181. logger.error('删除订阅失败', { error: error.message });
  182. res.status(500).json({
  183. success: false,
  184. error: error.message
  185. });
  186. }
  187. });
  188. /**
  189. * 手动更新所有订阅
  190. */
  191. router.post('/subscriptions/update-all', async (req, res) => {
  192. try {
  193. const result = await subscriptionManager.manualUpdate();
  194. if (result.success) {
  195. logger.info('手动更新所有订阅成功', { results: result.data });
  196. res.json({
  197. success: true,
  198. data: result.data
  199. });
  200. } else {
  201. logger.error('手动更新所有订阅失败', { error: result.error });
  202. res.status(500).json({
  203. success: false,
  204. error: result.error
  205. });
  206. }
  207. } catch (error) {
  208. logger.error('手动更新所有订阅失败', { error: error.message });
  209. res.status(500).json({
  210. success: false,
  211. error: error.message
  212. });
  213. }
  214. });
  215. /**
  216. * 手动更新单个订阅
  217. */
  218. router.post('/subscriptions/:id/update', async (req, res) => {
  219. try {
  220. const result = await subscriptionManager.manualUpdateSubscription(req.params.id);
  221. if (result.success) {
  222. logger.info('手动更新订阅成功', {
  223. subscriptionId: req.params.id,
  224. result: result.data
  225. });
  226. res.json({
  227. success: true,
  228. data: result.data
  229. });
  230. } else {
  231. logger.error('手动更新订阅失败', {
  232. subscriptionId: req.params.id,
  233. error: result.error
  234. });
  235. res.status(500).json({
  236. success: false,
  237. error: result.error
  238. });
  239. }
  240. } catch (error) {
  241. logger.error('手动更新订阅失败', { error: error.message });
  242. res.status(500).json({
  243. success: false,
  244. error: error.message
  245. });
  246. }
  247. });
  248. /**
  249. * 获取订阅状态
  250. */
  251. router.get('/subscriptions/status', async (req, res) => {
  252. try {
  253. const status = await subscriptionManager.getStatus();
  254. res.json({
  255. success: true,
  256. data: status
  257. });
  258. } catch (error) {
  259. logger.error('获取订阅状态失败', { error: error.message });
  260. res.status(500).json({
  261. success: false,
  262. error: error.message
  263. });
  264. }
  265. });
  266. /**
  267. * 启动自动更新
  268. */
  269. router.post('/subscriptions/start-auto-update', async (req, res) => {
  270. try {
  271. subscriptionManager.startAutoUpdate();
  272. logger.info('启动订阅自动更新成功');
  273. res.json({
  274. success: true,
  275. message: '订阅自动更新已启动'
  276. });
  277. } catch (error) {
  278. logger.error('启动订阅自动更新失败', { error: error.message });
  279. res.status(500).json({
  280. success: false,
  281. error: error.message
  282. });
  283. }
  284. });
  285. /**
  286. * 停止自动更新
  287. */
  288. router.post('/subscriptions/stop-auto-update', async (req, res) => {
  289. try {
  290. subscriptionManager.stopAutoUpdate();
  291. logger.info('停止订阅自动更新成功');
  292. res.json({
  293. success: true,
  294. message: '订阅自动更新已停止'
  295. });
  296. } catch (error) {
  297. logger.error('停止订阅自动更新失败', { error: error.message });
  298. res.status(500).json({
  299. success: false,
  300. error: error.message
  301. });
  302. }
  303. });
  304. module.exports = router;