diff --git a/fetch_tickets.py b/fetch_tickets.py new file mode 100644 index 0000000..1a87767 --- /dev/null +++ b/fetch_tickets.py @@ -0,0 +1,95 @@ +#!/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 + +BASE_URL = "https://192.168.1.237:8080" +API_TOKEN = "062CE056-C1F5-490C-A6DF-FD2C653A71DD" + +FROM_DATE_MS = int(datetime(2026, 7, 20, 0, 0, 0, tzinfo=timezone.utc).timestamp() * 1000) + +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"{BASE_URL}/api/v3/requests/{req_id}", + headers={"authtoken": API_TOKEN, "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(): + url = f"{BASE_URL}/api/v3/requests" + headers = {"authtoken": API_TOKEN, "Accept": "application/vnd.manageengine.sdp.v3+json"} + + 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_20 = [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_20] + details = await asyncio.gather(*tasks) + + rows = [] + for req, detail in zip(from_20, details): + group = req.get("group", {}) + group_name = get_name(group) + + desc = detail.get("description", "") + desc_clean = clean_html(desc) + + # Назначено (специалист) + tech = req.get("technician", {}) + assignee = get_name(tech) + + # Категория + cat = req.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() + asyncio.run(list_tickets())