#!/usr/bin/env python3 """Получение списка заявок из ServiceDesk Plus с 20 июля 2026. Экспорт: Группа, Описание, Назначено, Категория в JSONL.""" import asyncio import httpx import json import urllib3 from datetime import datetime, timezone from html import unescape import re import sys import os # Добавляем путь к конфигу sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) # Локальный Service Desk (для выгрузки данных) LOCAL_SD_URL = "https://192.168.1.237:8080" LOCAL_SD_API_KEY = "062CE056-C1F5-490C-A6DF-FD2C653A71DD" # По умолчанию с 20 июля, но можно передать как аргумент DEFAULT_FROM_DATE = "2026-07-20" def get_ts(req): ct = req.get("created_time", {}) if isinstance(ct, dict): v = ct.get("value", "0") return int(v) if v else 0 return 0 def clean_html(text): if not text: return "" text = re.sub(r'<[^>]+>', '', text) text = unescape(text) return text.strip() def get_name(obj): """Извлечь имя из объекта группы/техника/категории.""" if not obj: return "" if isinstance(obj, dict): return obj.get("name", "") or obj.get("display_value", "") return str(obj) async def fetch_ticket_detail(client, req_id): try: resp = await client.get( f"{LOCAL_SD_URL}/api/v3/requests/{req_id}", headers={"authtoken": LOCAL_SD_API_KEY, "Accept": "application/vnd.manageengine.sdp.v3+json"}, timeout=15.0 ) data = resp.json() return data.get("request", data) except Exception as e: return {} async def list_tickets(from_date=DEFAULT_FROM_DATE): url = f"{LOCAL_SD_URL}/api/v3/requests" headers = {"authtoken": LOCAL_SD_API_KEY, "Accept": "application/vnd.manageengine.sdp.v3+json"} # Вычисляем timestamp с указанной даты date_obj = datetime.strptime(from_date, "%Y-%m-%d") from_date_ms = int(date_obj.replace(tzinfo=timezone.utc).timestamp() * 1000) async with httpx.AsyncClient(verify=False, timeout=30.0) as client: resp = await client.get(url, headers=headers) data = resp.json() all_reqs = data.get("requests", []) from_date_reqs = [r for r in all_reqs if get_ts(r) >= from_date_ms] # Получаем детали для каждой заявки tasks = [fetch_ticket_detail(client, r.get("request_id", r.get("id", "?"))) for r in from_date_reqs] details = await asyncio.gather(*tasks) rows = [] for req, detail in zip(from_date_reqs, details): # Группа — из списка group = req.get("group", {}) group_name = get_name(group) # Описание — из детального запроса desc = detail.get("description", "") desc_clean = clean_html(desc) # Назначено (специалист) — из детального запроса tech = detail.get("technician", {}) assignee = get_name(tech) # Категория — из детального запроса cat = detail.get("category", {}) category = get_name(cat) rows.append({ "group": group_name, "description": desc_clean, "assignee": assignee, "category": category }) # Выводим JSONL for row in rows: print(json.dumps(row, ensure_ascii=False)) if __name__ == "__main__": urllib3.disable_warnings() from_date = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_FROM_DATE asyncio.run(list_tickets(from_date))