main.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. from fastapi import FastAPI, Form, UploadFile, File, HTTPException, Request, Response
  2. import uvicorn
  3. from fastapi.middleware.cors import CORSMiddleware
  4. from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
  5. from fastapi.middleware.trustedhost import TrustedHostMiddleware
  6. from datetime import datetime
  7. from fastapi.staticfiles import StaticFiles
  8. from datetime import datetime
  9. from fastapi.responses import RedirectResponse
  10. import logging
  11. from logging.handlers import TimedRotatingFileHandler
  12. from urllib.parse import unquote
  13. import requests as r
  14. param = 'QHLPQyttnL'
  15. result = r.get('http://cmm.ai:3001/api/push/' + param + '?status=up&msg=OK&ping=')
  16. # http://cmm.ai:3001/api/push/cDJyD2r3ae?status=up&msg=OK&ping=
  17. log_folder = 'log'
  18. log_file = f'{log_folder}/app.log'
  19. # 日志格式
  20. log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
  21. date_format = '%Y-%m-%d %H:%M:%S'
  22. class URLDecodingFormatter(logging.Formatter):
  23. def format(self, record):
  24. # 使用父类的 format 方法获取原始的日志消息
  25. original_message = super().format(record)
  26. # 解码 URL 编码部分
  27. decoded_message = unquote(original_message)
  28. return decoded_message
  29. # 清除所有默认处理器
  30. for handler in logging.root.handlers[:]:
  31. logging.root.removeHandler(handler)
  32. # 创建日志处理器
  33. file_handler = TimedRotatingFileHandler(
  34. log_file,
  35. when='midnight',
  36. interval=1,
  37. backupCount=14 # 保留14天的日志
  38. )
  39. file_handler.setFormatter(URLDecodingFormatter(log_format, datefmt=date_format))
  40. # 获取根日志对象并添加处理器
  41. logger = logging.getLogger()
  42. logger.setLevel(logging.INFO)
  43. logger.addHandler(file_handler)
  44. app = FastAPI()
  45. # app.add_middleware(HTTPSRedirectMiddleware)
  46. # app.add_middleware(TrustedHostMiddleware)
  47. app.add_middleware(
  48. CORSMiddleware,
  49. allow_origins=["*"],
  50. allow_credentials=True,
  51. allow_methods=["*"],
  52. allow_headers=["*"],
  53. )
  54. app.mount("/static", StaticFiles(directory="static"), name="static")
  55. # 根目錄導向docs
  56. @app.get("/")
  57. async def root():
  58. logging.info("Root endpoint was called")
  59. return RedirectResponse(url="/docs#")
  60. from api.tts_router import ttsRouter
  61. from api.db_router import dbRouter
  62. from api.tendent_router import tendentRouter
  63. # from api.speech2text import router
  64. # from api.tts_try import ttsTryRouter
  65. app.include_router(ttsRouter, prefix="", tags=["文字轉語音"])
  66. app.include_router(dbRouter, prefix="", tags=["supa 操作相關"])
  67. app.include_router(tendentRouter, prefix="", tags=["天燈"])
  68. # app.include_router(router, prefix='/speech2text', tags=["speech2text"])
  69. # app.include_router(ttsTryRouter, prefix='/ttsTry', tags=["測試本地端tts"])
  70. @app.get("/ad")
  71. def read_root(language :str = "ch"):
  72. message = {}
  73. if language == "ch" :
  74. message = {
  75. "type": "store",
  76. "body": {
  77. "cover_img": "https://cmm.ai:9101/static/ad_img/ad-img.png",
  78. "title": "台北101國際貴賓卡",
  79. "description":"國際貴賓卡專屬禮遇\n●即日起來台北101,提供2024年特別禮遇-申辦台北101國際貴賓卡,可享用國際旅客限定專屬三重好禮:\n●購物-品牌9折起特別優惠\n●禮遇-Welcome Pack+ NTD300現金折抵券\n●退稅-消費2000元以上提供5%快速退稅服務\n<a href='https://stage.taipei101mall.com.tw/join-member/AIsystem' class='ar-link mt-3' target='_blank'>立即申辦</a>",
  80. "date": "即日起",
  81. "price": "",
  82. "original_price": "",
  83. "website_url": "",
  84. "store_info_url": "",
  85. "included": [],
  86. "branch": [],
  87. "location" : ""
  88. },
  89. }
  90. else :
  91. message = {
  92. "type": "store",
  93. "body": {
  94. "cover_img": "https://cmm.ai:9101/static/ad_img/ad-img.png",
  95. "title": "Taipei 101 International VIP Card",
  96. "description":"TOURIST CARD Exclusive Privileges\nStarting today at Taipei 101, we are offering special privileges for the year 2024 - apply for the Taipei 101 Tourist Card and enjoy exclusive triple benefits reserved for international travelers.\n● Shopping - Special offers starting from 10% off brand items.\n● PRIVILEGES-Welcome Pack + NTD300 cash voucher.\n● TAX REFUND- Offering 5% expedited processing service.\n<a href='https://stage.taipei101mall.com.tw/join-member/AIsystem' class='ar-link mt-3' target='_blank'>Apply now</a>",
  97. "date": "Starting from today",
  98. "price": "",
  99. "original_price": "",
  100. "website_url": "",
  101. "store_info_url": "",
  102. "included": [],
  103. "branch": [],
  104. "location" : ""
  105. },
  106. }
  107. return {"data": message}
  108. from api.image_operate import remove_background,detect_face
  109. @app.post("/image_check")
  110. async def image_check(image_file : UploadFile):
  111. currentDateAndTime = datetime.now()
  112. imgname = currentDateAndTime.strftime("%m-%d-%H-%M-%S")+ "-" + image_file.filename
  113. with open(f"/home/mia/101/static/image/{imgname}","wb") as save_img :
  114. contents = await image_file.read()
  115. save_img.write(contents)
  116. # await remove_background(f"/home/mia/101/static/image/{imgname}",f"/home/mia/101/static/image/remove/{imgname}")
  117. result = await detect_face(f"/home/mia/101/static/image/{imgname}")
  118. return result
  119. from fastapi.responses import FileResponse
  120. @app.get("/stream.m3u8")
  121. async def get_m3u8():
  122. return FileResponse("static/stream/stream.m3u8")
  123. # @app.get("/segment/{segment_name}")
  124. # async def get_segment(segment_name: str):
  125. # return FileResponse(f"/home/mia/101/static/stream/segment_{segment_name}")
  126. app.mount("/segment", StaticFiles(directory="static/stream"), name="stream")
  127. from pathlib import Path
  128. import os
  129. from apscheduler.schedulers.background import BackgroundScheduler
  130. scheduler = BackgroundScheduler()
  131. TS_DIRECTORY = Path("/home/mia/101/static/stream")
  132. MP3_DIRECTORY = Path("/home/mia/101/static/mp3")
  133. def clean_old_files():
  134. ts_files = list(TS_DIRECTORY.glob("segment_*.ts"))
  135. ts_files.sort(key=lambda f: f.stat().st_mtime) # 按文件名排序,最旧的文件在前
  136. if len(ts_files) > 20:
  137. files_to_delete = ts_files[:len(ts_files) - 20] # 超过 20 个的文件需要删除
  138. for file in files_to_delete:
  139. try:
  140. os.remove(file)
  141. print(f"Deleted old file: {file}")
  142. except Exception as e:
  143. print(f"Error deleting file {file}: {e}")
  144. mp3_files = list(MP3_DIRECTORY.glob("recording_*.mp3"))
  145. mp3_files.sort(key=lambda f: f.stat().st_mtime) # 按文件名排序,最旧的文件在前
  146. if len(mp3_files) > 20:
  147. files_to_delete = mp3_files[:len(mp3_files) - 20] # 超过 20 个的文件需要删除
  148. for file in files_to_delete:
  149. try:
  150. os.remove(file)
  151. print(f"Deleted old file: {file}")
  152. except Exception as e:
  153. print(f"Error deleting file {file}: {e}")
  154. # 添加定时任务
  155. scheduler.add_job(clean_old_files, 'interval', minutes=1)
  156. scheduler.start()
  157. @app.on_event("shutdown")
  158. def shutdown_event():
  159. scheduler.shutdown()
  160. from starlette.responses import JSONResponse
  161. @app.get("/health") # 使用網址給 kuma 監測
  162. async def health_check():
  163. return JSONResponse(content={"status": "ok"}, status_code=200)
  164. if __name__ == "__main__":
  165. uvicorn.run("main:app", host="0.0.0.0", port=9101, reload=False, log_config=None)