limiter.py 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on 2022-06-15
  4. ---------
  5. @summary: 限制器
  6. ---------
  7. @author: Dzr
  8. """
  9. from fastapi import FastAPI
  10. from slowapi import Limiter, _rate_limit_exceeded_handler
  11. from slowapi.errors import RateLimitExceeded
  12. from slowapi.util import get_remote_address
  13. import setting
  14. from services.robot import send_msg
  15. from services.utils import current_date
  16. LIMITER = Limiter(key_func=get_remote_address) # 创建限制器实例对象
  17. LM_COUNTER = 0 # 计数器
  18. LM_DATE = None # 当前日期
  19. LM_FORECAST_WARNING = True # 上限预告标识
  20. LM_EXCEEDED_WARNING = True # 超限告警标识
  21. MAX_LIMIT = setting.LIMITER_MAX_LIMIT # 最大访问次数
  22. """
  23. 参考:https://limits.readthedocs.io/en/latest/quickstart.html
  24. Examples:
  25. 1、10 per hour
  26. 2、10/hour
  27. 3、10/hour;100/day;2000 per year
  28. 4、100/day, 500/7days
  29. 5、5/minute
  30. """
  31. LM_VALUE = f"{MAX_LIMIT}/day" # 限制数量
  32. def register_limiter(app: FastAPI):
  33. app.state.limiter = LIMITER
  34. app.add_exception_handler(RateLimitExceeded, limit_exceeded_handler)
  35. def limit_exceeded_handler(*args, **kwargs):
  36. global LM_EXCEEDED_WARNING
  37. if LM_EXCEEDED_WARNING:
  38. msg = "今日接口调用次数已达上限!\n 继续使用请点击"
  39. send_msg("超级鹰", MAX_LIMIT, MAX_LIMIT, msg, allow_reset=True)
  40. LM_EXCEEDED_WARNING = False
  41. return _rate_limit_exceeded_handler(*args, **kwargs)
  42. def flush_limiter():
  43. global LM_COUNTER, LM_FORECAST_WARNING, LM_EXCEEDED_WARNING
  44. LM_COUNTER = 0
  45. LM_FORECAST_WARNING = True
  46. LM_EXCEEDED_WARNING = True
  47. def limiter_warring():
  48. global LM_DATE, LM_COUNTER, LM_FORECAST_WARNING
  49. curr_date = current_date()
  50. if curr_date != LM_DATE:
  51. if LM_DATE is not None:
  52. flush_limiter()
  53. LM_COUNTER += 1
  54. LM_DATE = curr_date
  55. val = '{:.2f}'.format(LM_COUNTER / MAX_LIMIT * 100)
  56. if float(val) > 80 and LM_FORECAST_WARNING:
  57. send_msg("超级鹰", MAX_LIMIT, LM_COUNTER, f"使用次数已超过{val}%")
  58. LM_FORECAST_WARNING = False