{"size": 1212, "ext": "js", "max_stars_repo_path": "lib/rate-limit.js", "max_stars_repo_name": "DSaurus/NKU_online_judge_backend_private", "max_stars_repo_stars_event_min_datetime": "2018-05-08T05:57:38.000Z", "max_stars_repo_stars_event_max_datetime": "2021-02-28T14:07:52.000Z", "max_issues_repo_path": "lib/rate-limit.js", "max_issues_repo_name": "DSaurus/NKU_online_judge_backend_private", "max_issues_repo_issues_event_min_datetime": "2018-09-17T15:22:25.000Z", "max_issues_repo_issues_event_max_datetime": "2022-03-24T09:09:17.000Z", "max_forks_repo_path": "lib/rate-limit.js", "max_forks_repo_name": "DSaurus/NKU_online_judge_backend_private", "max_forks_repo_forks_event_min_datetime": "2018-07-07T14:20:22.000Z", "max_forks_repo_forks_event_max_datetime": "2021-04-20T14:32:51.000Z"}
{"max_stars_count": 13, "max_issues_count": 22, "max_forks_count": 16, "avg_line_length": 22.0363636364, "max_line_length": 96, "alphanum_fraction": 0.6080858086}
const {DB_RATE_LIMIT} = require('../config/redis')
const redis = require('./redis')(DB_RATE_LIMIT)

const handler = {
  get (target, name) {
    return name in target ? {ttl: target[name][0], times: target[name][1]} : {ttl: 1, times: 10}
  }
}

const r = {
  sendmail: [60, 1],
  post: [60, 1],
  sendmsg: [120, 2]
}

const rule = new Proxy(r, handler)

const limit = type => async (req, res, next) => {
  'use strict'
  const key = `limit:${req.ip}:${type}`
  const ret = await redis.incrAsync(key)
  const ttl = rule[type].ttl
  if (ret > rule[type].times) {
    res.set({'Retry-After': ttl})
    return res.fatal(429, {'Retry-After': ttl})
  }
  redis.expire(key, ttl)
  next()
}

const require_limit = type => async (req, res, next) => {
  'use strict'
  const key = `limit:${req.ip}:${type}`
  const ret = await redis.getAsync(key)
  const ttl = rule[type].ttl
  if (ret > rule[type].times) {
    res.set({'Retry-After': ttl})
    return res.fatal(429, {'Retry-After': ttl})
  }
  next()
}

const apply_limit = async (type, req) => {
  'use strict'
  const key = `limit:${req.ip}:${type}`
  redis.incr(key)
  redis.expire(key, rule[type].ttl)
}

module.exports = {
  limit,
  apply_limit,
  require_limit
}
