{"contents":"# -*- coding: utf-8 -*-#\n# -------------------------------------------------------------------------------\n# Name: messages.py\n# Description: 消息查询与媒体服务\n# -------------------------------------------------------------------------------\nimport os\nimport shutil\nfrom urllib.parse import quote, unquote\nfrom typing import List, Optional\n\nfrom fastapi import APIRouter, Response, Body, Request\nfrom starlette.responses import StreamingResponse, FileResponse\n\nfrom wxdump_linux.db import DBHandler\nfrom wxdump_linux.db.utils import download_file, dat2img\nfrom ..response import ReJson\nfrom ..decorators import error9999, asyncError9999\nfrom ..config import gc\n\nmessages_router = APIRouter()\n\n\n@messages_router.post('/msg_count')\n@error9999\ndef msg_count(wxids: Optional[List[str]] = Body(..., embed=True)):\n \"\"\"\n 获取联系人的聊天记录数量\n :return:\n \"\"\"\n my_wxid = gc.get_conf(gc.at, \"last\")\n if not my_wxid: return ReJson(1001, body=\"my_wxid is required\")\n db_config = gc.get_db_config()\n db = DBHandler(db_config, my_wxid=my_wxid)\n count = db.get_msgs_count(wxids)\n return ReJson(0, count)\n\n\n@messages_router.api_route('/msg_list', methods=[\"GET\", 'POST'])\n@error9999\ndef get_msgs(wxid: str = Body(...), start: int = Body(...), limit: int = Body(...)):\n \"\"\"\n 获取联系人的聊天记录\n :return:\n \"\"\"\n my_wxid = gc.get_conf(gc.at, \"last\")\n if not my_wxid: return ReJson(1001, body=\"my_wxid is required\")\n db_config = gc.get_conf(my_wxid, \"db_config\")\n\n db = DBHandler(db_config, my_wxid=my_wxid)\n msgs, users = db.get_msgs(wxids=wxid, start_index=start, page_size=limit)\n return ReJson(0, {\"msg_list\": msgs, \"user_list\": users})\n\n\n@messages_router.get('/imgsrc')\n@asyncError9999\nasync def get_imgsrc(request: Request):\n \"\"\"\n 获取图片,\n 1. 从网络获取图片,主要功能只是下载图片,缓存到本地\n 2. 读取本地图片\n :return:\n \"\"\"\n imgsrc = unquote(str(request.query_params).replace(\"src=\", \"\", 1))\n if not imgsrc:\n return ReJson(1002)\n if imgsrc.startswith(\"FileStorage\"): # 如果是本地图片文件则调用get_img\n my_wxid = gc.get_conf(gc.at, \"last\")\n if not my_wxid: return ReJson(1001, body=\"my_wxid is required\")\n wx_path = gc.get_conf(my_wxid, \"wx_path\")\n\n img_path = imgsrc.replace(\"\\\\\\\\\", \"\\\\\")\n\n img_tmp_path = os.path.join(gc.work_path, my_wxid, \"img\")\n original_img_path = os.path.join(wx_path, img_path)\n if os.path.exists(original_img_path):\n rc, fomt, md5, out_bytes = dat2img(original_img_path)\n if not rc:\n return ReJson(1001, body=original_img_path)\n imgsavepath = os.path.join(str(img_tmp_path), img_path + \"_\" + \"\".join([md5, fomt]))\n if os.path.exists(imgsavepath):\n return FileResponse(imgsavepath)\n if not os.path.exists(os.path.dirname(imgsavepath)):\n os.makedirs(os.path.dirname(imgsavepath))\n with open(imgsavepath, \"wb\") as f:\n f.write(out_bytes)\n return Response(content=out_bytes, media_type=\"image/jpeg\")\n else:\n return ReJson(1001, body=f\"{original_img_path} not exists\")\n elif imgsrc.startswith(\"http://\") or imgsrc.startswith(\"https://\"):\n my_wxid = gc.get_conf(gc.at, \"last\")\n if not my_wxid: return ReJson(1001, body=\"my_wxid is required\")\n\n img_tmp_path = os.path.join(gc.work_path, my_wxid, \"imgsrc\")\n if not os.path.exists(img_tmp_path):\n os.makedirs(img_tmp_path)\n file_name = imgsrc.replace(\"http://\", \"\").replace(\"https://\", \"\").replace(\"/\", \"_\").replace(\"?\", \"_\")\n file_name = file_name + \".jpg\"\n if len(file_name) \u003e 255:\n file_name = file_name[:255] + \"/\" + file_name[255:]\n\n img_path_all = os.path.join(str(img_tmp_path), file_name)\n if os.path.exists(img_path_all):\n return FileResponse(img_path_all)\n else:\n proxies = None\n download_file(imgsrc, img_path_all, proxies=proxies)\n if os.path.exists(img_path_all):\n return FileResponse(img_path_all)\n else:\n return ReJson(4004, body=imgsrc)\n else:\n return ReJson(1002, body=imgsrc)\n\n\n@messages_router.api_route('/video', methods=[\"GET\", 'POST'])\ndef get_video(request: Request):\n \"\"\"\n 获取视频\n :return:\n \"\"\"\n videoPath = unquote(str(request.query_params).replace(\"src=\", \"\", 1))\n if not videoPath:\n return ReJson(1002)\n my_wxid = gc.get_conf(gc.at, \"last\")\n if not my_wxid: return ReJson(1001, body=\"my_wxid is required\")\n wx_path = gc.get_conf(my_wxid, \"wx_path\")\n\n videoPath = videoPath.replace(\"\\\\\\\\\", \"\\\\\")\n\n video_tmp_path = os.path.join(gc.work_path, my_wxid, \"video\")\n original_img_path = os.path.join(wx_path, videoPath)\n if not os.path.exists(original_img_path):\n return ReJson(5002)\n assert isinstance(video_tmp_path, str)\n video_save_path = os.path.join(video_tmp_path, videoPath)\n if not os.path.exists(os.path.dirname(video_save_path)):\n os.makedirs(os.path.dirname(video_save_path))\n if os.path.exists(video_save_path):\n return FileResponse(path=video_save_path)\n shutil.copy(original_img_path, video_save_path)\n return FileResponse(path=video_save_path)\n\n\n@messages_router.api_route('/audio', methods=[\"GET\", 'POST'])\ndef get_audio(request: Request):\n \"\"\"\n 获取语音\n :return:\n \"\"\"\n savePath = unquote(str(request.query_params).replace(\"src=\", \"\", 1)).replace(\"audio\\\\\", \"\", 1)\n if not savePath:\n return ReJson(1002)\n my_wxid = gc.get_conf(gc.at, \"last\")\n if not my_wxid: return ReJson(1001, body=\"my_wxid is required\")\n db_config = gc.get_conf(my_wxid, \"db_config\")\n\n savePath = os.path.join(gc.work_path, my_wxid, \"audio\", savePath)\n if os.path.exists(savePath):\n assert isinstance(savePath, str)\n return FileResponse(path=savePath, media_type='audio/mpeg')\n\n MsgSvrID = savePath.split(\"_\")[-1].replace(\".wav\", \"\")\n if not savePath:\n return ReJson(1002)\n\n if not os.path.exists(os.path.dirname(savePath)):\n os.makedirs(os.path.dirname(savePath))\n\n db = DBHandler(db_config, my_wxid=my_wxid)\n wave_data = db.get_audio(MsgSvrID, is_play=False, is_wave=True, save_path=savePath, rate=24000)\n if not wave_data:\n return ReJson(1001, body=\"wave_data is required\")\n\n if os.path.exists(savePath):\n assert isinstance(savePath, str)\n return FileResponse(path=savePath, media_type='audio/mpeg')\n else:\n return ReJson(4004, body=savePath)\n\n\n@messages_router.api_route('/file_info', methods=[\"GET\", 'POST'])\ndef get_file_info(file_path: str = Body(..., embed=True)):\n if not file_path:\n return ReJson(1002)\n\n my_wxid = gc.get_conf(gc.at, \"last\")\n if not my_wxid: return ReJson(1001, body=\"my_wxid is required\")\n wx_path = gc.get_conf(my_wxid, \"wx_path\")\n\n all_file_path = os.path.join(wx_path, file_path)\n if not os.path.exists(all_file_path):\n return ReJson(5002)\n file_name = os.path.basename(all_file_path)\n file_size = os.path.getsize(all_file_path)\n return ReJson(0, {\"file_name\": file_name, \"file_size\": str(file_size)})\n\n\n@messages_router.get('/file')\ndef get_file(request: Request):\n \"\"\"\n 获取文件\n :return:\n \"\"\"\n file_path = unquote(str(request.query_params).replace(\"src=\", \"\", 1))\n if not file_path:\n return ReJson(1002)\n my_wxid = gc.get_conf(gc.at, \"last\")\n if not my_wxid: return ReJson(1001, body=\"my_wxid is required\")\n wx_path = gc.get_conf(my_wxid, \"wx_path\")\n\n all_file_path = os.path.join(wx_path, file_path)\n if not os.path.exists(all_file_path):\n return ReJson(5002)\n\n def file_iterator(file_path, chunk_size=8192):\n with open(file_path, \"rb\") as f:\n while True:\n chunk = f.read(chunk_size)\n if not chunk:\n break\n yield chunk\n\n headers = {\n \"Content-Disposition\": f'attachment; filename*=UTF-8\\'\\'{quote(os.path.basename(all_file_path))}',\n }\n return StreamingResponse(file_iterator(all_file_path), media_type=\"application/octet-stream\", headers=headers)\n","is_binary":false,"path":"wxdump_linux/api/routes/messages.py","ref":""}