215 lines
7.1 KiB
Python
215 lines
7.1 KiB
Python
![]() |
from flask import Flask, request, jsonify
|
||
|
from dingding_attendance import DingTalkDocsFetcher # 你保存代码的文件名
|
||
|
from dingding_calendars import DingTalkHelper
|
||
|
import concurrent.futures
|
||
|
from dingding_wiki_team_file import get_access_token,get_unionid,create_wiki_client,list_workspaces,list_all_nodes,get_admin_userid,get_workspaces_details
|
||
|
from dingding_wiki_file import get_user_root_node_id,get_department_list,get_department_users
|
||
|
from DingConfig import APP_KEY, APP_SECRET
|
||
|
from flask import Blueprint
|
||
|
app_dingding = Blueprint("dingding", __name__)
|
||
|
def obj_to_dict(obj):
|
||
|
if isinstance(obj, list):
|
||
|
return [obj_to_dict(i) for i in obj]
|
||
|
if isinstance(obj, dict):
|
||
|
return {k: obj_to_dict(v) for k,v in obj.items()}
|
||
|
if hasattr(obj, 'to_map'):
|
||
|
return obj.to_map()
|
||
|
if hasattr(obj, '__dict__'):
|
||
|
return {k: obj_to_dict(v) for k, v in obj.__dict__.items() if not k.startswith('_')}
|
||
|
return obj
|
||
|
def to_dict(ws):
|
||
|
return {
|
||
|
"name": getattr(ws, "name", ""),
|
||
|
"workspace_id": getattr(ws, "workspace_id", ""),
|
||
|
"type": getattr(ws, "type", ""),
|
||
|
"url": getattr(ws, "url", ""),
|
||
|
}
|
||
|
|
||
|
#获取钉钉打卡信息
|
||
|
@app_dingding.route('/dingding_attendance', methods=['POST'])
|
||
|
def attendance():
|
||
|
data = request.json
|
||
|
app_key = APP_KEY
|
||
|
app_secret = APP_SECRET
|
||
|
date_from = data.get('date_from')
|
||
|
date_to = data.get('date_to')
|
||
|
|
||
|
if not all([date_from, date_to]):
|
||
|
return jsonify({"error": "date_from, date_to 均为必填参数"}), 400
|
||
|
|
||
|
token = DingTalkDocsFetcher.get_access_token(app_key, app_secret)
|
||
|
if not token:
|
||
|
return jsonify({"error": "获取AccessToken失败"}), 500
|
||
|
|
||
|
departments = DingTalkDocsFetcher.get_all_departments(token)
|
||
|
if not departments:
|
||
|
return jsonify({"error": "获取部门失败"}), 500
|
||
|
|
||
|
user_ids = list(DingTalkDocsFetcher.get_all_user_ids(token, departments))
|
||
|
if not user_ids:
|
||
|
return jsonify({"error": "没有获取到用户ID"}), 500
|
||
|
|
||
|
records = DingTalkDocsFetcher.get_attendance_records(token, user_ids, date_from, date_to)
|
||
|
if records is None:
|
||
|
return jsonify({"error": "获取打卡记录失败"}), 500
|
||
|
|
||
|
user_cache = {}
|
||
|
|
||
|
def fetch_user_detail(uid):
|
||
|
if uid in user_cache:
|
||
|
return uid, user_cache[uid]
|
||
|
detail = DingTalkDocsFetcher.get_user_detail(token, uid)
|
||
|
user_cache[uid] = detail
|
||
|
return uid, detail
|
||
|
|
||
|
user_ids_in_records = list({r.get("userId") for r in records if r.get("userId")})
|
||
|
|
||
|
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
|
||
|
futures = [executor.submit(fetch_user_detail, uid) for uid in user_ids_in_records]
|
||
|
for future in concurrent.futures.as_completed(futures):
|
||
|
uid, detail = future.result()
|
||
|
user_cache[uid] = detail
|
||
|
|
||
|
for r in records:
|
||
|
detail = user_cache.get(r.get("userId"))
|
||
|
r["user_name"] = detail.get("name", "") if detail else ""
|
||
|
r["user_unionid"] = detail.get("unionid", "") if detail else ""
|
||
|
|
||
|
return jsonify({
|
||
|
"departments_count": len(departments),
|
||
|
"users_count": len(user_ids),
|
||
|
"attendance_records_count": len(records),
|
||
|
"attendance_records": records
|
||
|
})
|
||
|
|
||
|
#获取钉钉日历日程信息
|
||
|
@app_dingding.route('/dingding_calendar', methods=['GET'])
|
||
|
def user_calendar():
|
||
|
app_key = APP_KEY
|
||
|
app_secret = APP_SECRET
|
||
|
|
||
|
|
||
|
token = DingTalkHelper.get_access_token(app_key, app_secret)
|
||
|
if not token:
|
||
|
return jsonify({"error": "获取AccessToken失败"}), 500
|
||
|
|
||
|
departments = DingTalkHelper.get_all_departments(token)
|
||
|
if not departments:
|
||
|
return jsonify({"error": "获取部门失败"}), 500
|
||
|
|
||
|
all_userids = set()
|
||
|
for dept in departments:
|
||
|
userids = DingTalkHelper.get_users_by_dept(token, dept["dept_id"])
|
||
|
all_userids.update(userids)
|
||
|
if not all_userids:
|
||
|
return jsonify({"error": "没有获取到用户ID"}), 500
|
||
|
|
||
|
calendar_client = DingTalkHelper.create_calendar_client()
|
||
|
|
||
|
user_cache = {}
|
||
|
|
||
|
def fetch_user_events(userid):
|
||
|
user_detail = DingTalkHelper.get_user_detail(token, userid)
|
||
|
if not user_detail:
|
||
|
return None
|
||
|
unionid = user_detail.get("unionid")
|
||
|
name = user_detail.get("name")
|
||
|
events = []
|
||
|
if unionid:
|
||
|
events = DingTalkHelper.get_user_calendar_events(calendar_client, token, unionid)
|
||
|
return {
|
||
|
"userid": userid,
|
||
|
"name": name,
|
||
|
"unionid": unionid,
|
||
|
"events": events
|
||
|
}
|
||
|
|
||
|
results = []
|
||
|
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
|
||
|
futures = [executor.submit(fetch_user_events, uid) for uid in all_userids]
|
||
|
for future in concurrent.futures.as_completed(futures):
|
||
|
res = future.result()
|
||
|
if res:
|
||
|
results.append(res)
|
||
|
|
||
|
# 转换 events
|
||
|
for user_data in results:
|
||
|
user_data['events'] = obj_to_dict(user_data.get('events', []))
|
||
|
|
||
|
return jsonify({
|
||
|
"departments_count": len(departments),
|
||
|
"users_count": len(all_userids),
|
||
|
"users": results
|
||
|
})
|
||
|
|
||
|
|
||
|
@app_dingding.route('/wiki_workspaces', methods=['POST'])
|
||
|
def wiki_workspaces():
|
||
|
data = request.json or {}
|
||
|
app_key = APP_KEY
|
||
|
app_secret = APP_SECRET
|
||
|
|
||
|
|
||
|
try:
|
||
|
token = get_access_token(app_key, app_secret)
|
||
|
|
||
|
userid = get_admin_userid(token)
|
||
|
operator_id = get_unionid(token, userid)
|
||
|
client = create_wiki_client()
|
||
|
|
||
|
workspaces_ids = list_workspaces(client, token, operator_id)
|
||
|
workspaces = get_workspaces_details(client, token, operator_id, workspaces_ids)
|
||
|
|
||
|
for ws in workspaces:
|
||
|
ws["nodes"] = list_all_nodes(client, operator_id, ws["root_node_id"], token)
|
||
|
|
||
|
workspaces_serializable = workspaces # 已经是字典列表
|
||
|
|
||
|
return jsonify({
|
||
|
"workspaces_count": len(workspaces_serializable),
|
||
|
"workspaces": workspaces_serializable
|
||
|
})
|
||
|
except Exception as e:
|
||
|
return jsonify({"error": str(e)}), 500
|
||
|
|
||
|
|
||
|
@app_dingding.route("/get_all_users_wiki", methods=["GET"])
|
||
|
def get_all_users_wiki():
|
||
|
app_key = APP_KEY
|
||
|
app_secret = APP_SECRET
|
||
|
|
||
|
|
||
|
try:
|
||
|
token = get_access_token(app_key, app_secret)
|
||
|
|
||
|
dept_ids = [1] + get_department_list(token)
|
||
|
all_users = set()
|
||
|
for dept_id in dept_ids:
|
||
|
all_users.update(get_department_users(token, dept_id))
|
||
|
|
||
|
client = create_wiki_client()
|
||
|
result = []
|
||
|
|
||
|
for userid in all_users:
|
||
|
operator_id = get_unionid(token, userid)
|
||
|
if not operator_id:
|
||
|
continue
|
||
|
|
||
|
root_node_id = get_user_root_node_id(client, token, operator_id)
|
||
|
if not root_node_id:
|
||
|
continue
|
||
|
|
||
|
nodes = list_all_nodes(client, operator_id, root_node_id, token)
|
||
|
result.append({
|
||
|
"userid": userid,
|
||
|
"operator_id": operator_id,
|
||
|
"root_node_id": root_node_id,
|
||
|
"nodes": nodes
|
||
|
})
|
||
|
|
||
|
return jsonify({"users": result, "total_users": len(result)})
|
||
|
except Exception as e:
|
||
|
return jsonify({"error": str(e)}), 500
|
||
|
|
||
|
|