from typing import List, Dict from flask import Flask, request, jsonify import requests app = Flask(__name__) # ------------------ 工具函数 ------------------ # 获取 token def get_access_token(corpid: str, corpsecret: str) -> str: url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken" params = { "corpid": corpid, "corpsecret": corpsecret } response = requests.get(url, params=params, timeout=5) data = response.json() if data.get("errcode") != 0: raise Exception(f"获取 access_token 失败: {data}") return data["access_token"] # 获取企业所有员工 def get_userid_list(access_token: str, limit: int = 10000) -> list: url = "https://qyapi.weixin.qq.com/cgi-bin/user/list_id" members = [] cursor = "" while True: payload = { "cursor": cursor, "limit": limit } response = requests.post(url, params={"access_token": access_token}, json=payload, timeout=5) data = response.json() if data.get("errcode") != 0: raise Exception(f"获取成员列表失败: {data}") members.extend(data.get("userid_list", [])) cursor = data.get("next_cursor") if not cursor: break return members # 获取打卡记录 def get_checkin_data(access_token: str, starttime: int, endtime: int, useridlist: List[str], opencheckindatatype: int = 3) -> List[Dict]: url = "https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckindata" payload = { "opencheckindatatype": opencheckindatatype, "starttime": starttime, "endtime": endtime, "useridlist": useridlist } response = requests.post(url, params={"access_token": access_token}, json=payload, timeout=10) data = response.json() if data.get("errcode") != 0: raise Exception(f"获取打卡记录失败: {data}") return data.get("checkindata", []) # 获取文件列表(递归) def get_file_list_recursive(access_token, spaceid, fatherid=None, sort_type=1): all_files = [] start = 0 limit = 100 while True: url = f"https://qyapi.weixin.qq.com/cgi-bin/wedrive/file_list?access_token={access_token}" payload = { "spaceid": spaceid, "fatherid": fatherid if fatherid else spaceid, "sort_type": sort_type, "start": start, "limit": limit } resp = requests.post(url, json=payload) resp.raise_for_status() data = resp.json() if data.get("errcode") != 0: raise Exception(f"获取文件列表失败: {data}") files = data.get("items", []) all_files.extend(files) next_start = data.get("next_start", 0) if next_start == 0: break start = next_start all_recursive_files = [] for f in all_files: all_recursive_files.append(f) if f.get("type") == 1: # 文件夹 sub_files = get_file_list_recursive(access_token, spaceid, f["fileid"], sort_type) all_recursive_files.extend(sub_files) return all_recursive_files # ------------------ Flask 接口 ------------------ @app.route("/checkin_records", methods=["POST"]) def checkin_records(): """ 输入参数: { "corpid": "xxx", "corpsecret": "xxx", # 打卡应用的 secret "usersecret": "xxx", # 通讯录 secret "starttime": 1234567890, "endtime": 1234569999 } """ try: data = request.json corpid = data["corpid"] corpsecret = data["corpsecret"] usersecret = data["usersecret"] starttime = data["starttime"] endtime = data["endtime"] user_token = get_access_token(corpid, usersecret) access_token = get_access_token(corpid, corpsecret) userids = get_userid_list(user_token) records = get_checkin_data(access_token, starttime, endtime, userids) return jsonify({"status": "success", "count": len(records), "records": records}) except Exception as e: return jsonify({"status": "error", "message": str(e)}), 500 @app.route("/file_list", methods=["POST"]) def file_list(): """ 输入参数: { "corpid": "xxx", "corpsecret": "xxx", # 微盘应用的 secret "spaceid": "123456" } """ try: data = request.json corpid = data["corpid"] corpsecret = data["corpsecret"] spaceid = data["spaceid"] access_token = get_access_token(corpid, corpsecret) files = get_file_list_recursive(access_token, spaceid) return jsonify({"status": "success", "count": len(files), "files": files}) except Exception as e: return jsonify({"status": "error", "message": str(e)}), 500 # ------------------ 启动 ------------------ if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True)