List.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. const API = require('../../../../lib/API')
  2. const db = require('../../../../plugin/DataBase/db')
  3. const AccessControl = require('../../../../lib/AccessControl')
  4. const { BaseStdResponse } = require('../../../../BaseStdResponse')
  5. const path = require('path')
  6. const ipSearcher = require('../../../../plugin/ip2region')
  7. let searcher = null
  8. function getSearcher() {
  9. if (searcher) return searcher
  10. searcher = ipSearcher.newWithFileOnly(path.join(__dirname, '../../../../plugin/ip2region/ip2region.xdb'))
  11. return searcher
  12. }
  13. function isIpv4(host) {
  14. return /^(\d{1,3}\.){3}\d{1,3}$/.test(String(host || '').trim())
  15. }
  16. class List extends API {
  17. constructor() {
  18. super()
  19. this.setPath('/Admin/Lepao/Proxy/List')
  20. this.setMethod('get')
  21. }
  22. async onRequest(req, res) {
  23. let { uuid, session, pagesize, current, is_active, host } = req.query
  24. if ([uuid, session, pagesize, current].some((v) => v === '' || v === null || v === undefined)) {
  25. return res.json({ ...BaseStdResponse.MISSING_PARAMETER })
  26. }
  27. if (isNaN(pagesize) || Number(pagesize) <= 0 || Number(pagesize) > 100) {
  28. return res.json({ ...BaseStdResponse.ERR, msg: '参数错误' })
  29. }
  30. if (isNaN(current) || Number(current) <= 0) {
  31. return res.json({ ...BaseStdResponse.ERR, msg: '参数错误' })
  32. }
  33. if (!await AccessControl.checkSession(uuid, session)) {
  34. return res.status(401).json({ ...BaseStdResponse.ACCESS_DENIED })
  35. }
  36. const permission = await AccessControl.getPermission(uuid)
  37. if (!permission.includes('admin') && !permission.includes('service')) {
  38. return res.json({ ...BaseStdResponse.PERMISSION_DENIED })
  39. }
  40. const offset = (Number(current) - 1) * Number(pagesize)
  41. const where = ['1 = 1']
  42. const params = []
  43. const countParams = []
  44. if (is_active !== undefined && is_active !== null && String(is_active) !== '') {
  45. where.push('p.is_active = ?')
  46. params.push(Number(is_active) === 1 ? 1 : 0)
  47. countParams.push(Number(is_active) === 1 ? 1 : 0)
  48. }
  49. if (host) {
  50. where.push('p.host LIKE ?')
  51. params.push(`%${host}%`)
  52. countParams.push(`%${host}%`)
  53. }
  54. const whereSql = where.join(' AND ')
  55. const listSql = `
  56. SELECT
  57. p.*,
  58. (SELECT COUNT(*) FROM lepao_account a WHERE a.assigned_proxy_id = p.id) AS account_count
  59. FROM lepao_proxy_pool p
  60. WHERE ${whereSql}
  61. ORDER BY p.id DESC
  62. LIMIT ? OFFSET ?
  63. `
  64. params.push(String(pagesize), String(offset))
  65. const countSql = `
  66. SELECT COUNT(*) AS total
  67. FROM lepao_proxy_pool p
  68. WHERE ${whereSql}
  69. `
  70. const rows = await db.query(listSql, params)
  71. const countResult = await db.query(countSql, countParams)
  72. if (!rows || !countResult) {
  73. return res.json({ ...BaseStdResponse.DATABASE_ERR, msg: '查询失败' })
  74. }
  75. const s = getSearcher()
  76. for (const row of rows) {
  77. row.ip_location = '未知'
  78. if (!isIpv4(row.host)) {
  79. row.ip_location = '非IPv4/域名'
  80. continue
  81. }
  82. try {
  83. const info = await s.search(row.host)
  84. row.ip_location = info?.region || '未知'
  85. } catch {
  86. row.ip_location = '未知'
  87. }
  88. }
  89. return res.json({
  90. ...BaseStdResponse.OK,
  91. data: rows,
  92. pagination: {
  93. current: Number(current),
  94. pagesize: Number(pagesize),
  95. total: countResult[0].total
  96. }
  97. })
  98. }
  99. }
  100. module.exports.List = List