import json import logging import uuid from dataclasses import dataclass from datetime import datetime, timedelta from json import JSONDecodeError from typing import Dict, Optional, List from urllib.parse import urljoin import requests from django.contrib.auth.models import User from django.db.utils import IntegrityError from company.models.company import Company from console.settings.base import NCIRCC_DOMAIN_NAME, NCIRCC_CERT_VERIFY from ncircc.models.comments import Comment from ncircc.models.notification import Notification from ncircc.serializers.comments import CommentRetrieveSerializer _log = logging.getLogger(__name__) @dataclass class CommentSuccessDataResponse: """Data for success comment created""" id: int incident_id: int comment: str user_id: int d_comment: datetime t_comment: str createdAt: datetime updatedAt: datetime to: str parent_id: Optional[int] workgroup_resolved: bool options: dict @dataclass class CommentGettingResponse: id: int incident_uuid: uuid.UUID text: str login: str incident_id: str create_time: datetime class CommentSenderService: """Send comment to notification.""" path = '/api/v2/comments' def __init__(self, message: str, notification_pk: int, user: User) -> None: self.user = user self.company = Company.objects.first() self.message = message notification = Notification.objects.get(pk=notification_pk) self.notification_uuid = str(notification.uuid) def get_headers(self) -> Dict[str, str]: """Return headers for sending.""" headers = { 'x-token': self.company.api_key, 'Content-Type': 'application/json', } return headers def get_payload(self) -> dict: data = { 'incident.uuid': self.notification_uuid, 'data': {'comment': self.message} } return data def _save(self, data: CommentSuccessDataResponse) -> Comment: comment = Comment( text=self.message, notification=Notification.objects.get(uuid=self.notification_uuid), id_in_ncircc=data.id, create_time=data.createdAt, login=str(self.user.username), is_read=True, from_console=True, ) comment.save() return CommentRetrieveSerializer(comment).data def send(self): url = urljoin(NCIRCC_DOMAIN_NAME, self.path) msg, status = 'Success', 200 headers = self.get_headers() payload = self.get_payload() try: response = requests.post(url, json=payload, headers=headers, verify=NCIRCC_CERT_VERIFY) except requests.exceptions.RequestException as err: _log.error(f'Error: {err}') return str(err), 400 try: data = response.json() except (JSONDecodeError, AttributeError) as err: _log.error(f'Error: {err}') return str(err), 400 if response.status_code == 200: data = self._save(CommentSuccessDataResponse(**data.get('data', {}))) return data, status else: return 'Error', 400 class CommentsUpdaterService: """Service for getting all comments and save it in db""" update_delta = timedelta(minutes=10) # todo после уточнения изменить company = None path = 'api/v2/incidents/comments' def __init__(self) -> None: self.company = Company.objects.first() def get_headers(self) -> Dict[str, str]: """Return headers for sending.""" headers = { 'x-token': self.company.api_key, 'Content-Type': 'application/json', } return headers def get_payload(self) -> tuple: data_value = datetime.now() - self.update_delta params = [ {"property": "create_time", "operator": "gte", "value": str(data_value.isoformat())}, {"property": "login", "operator": "endsWith", "value": "НКЦКИ"}] return ('filter', json.dumps(params),), def send(self): _log.debug('start1') url = urljoin(NCIRCC_DOMAIN_NAME, self.path) payload = self.get_payload() headers = self.get_headers() try: response = requests.get(url, headers=headers, params=payload, verify=NCIRCC_CERT_VERIFY) except requests.exceptions.RequestException as err: _log.error(f'Error: {err}') return 'Error', 400 try: data = response.json() except (JSONDecodeError, AttributeError) as err: _log.error(f'Error: {err}') return 'Error', 400 if response.status_code == 200: data = data.get('data', []) comment_list = [CommentGettingResponse(**self.clear_comments_request(comment)) for comment in data] self._save(comment_list) return 'Success', 200 else: _log.error(f'Error: {data}') return 'Error', 400 def clear_comments_request(self, data: dict) -> dict: """Clear json from ncircc.""" if 'incident.uuid' in data: data['incident_uuid'] = data.pop('incident.uuid') if 'incident.id' in data: data['incident_id'] = data.pop('incident.id') return data def _save(self, comments: List[CommentGettingResponse]) -> None: """bulk create comments in db""" incidents_uuid = [comment.incident_uuid for comment in comments] _log.debug(f'start bulk save: {incidents_uuid}') notifications = Notification.objects.filter(uuid__in=incidents_uuid) notifications_map = {str(notification.uuid): notification for notification in notifications} for comment in comments: if notifications_map.get(comment.incident_uuid): try: Comment.objects.create(text=comment.text, notification=notifications_map[comment.incident_uuid], create_time=comment.create_time, login=comment.login, id_in_ncircc=comment.id) except IntegrityError as err: _log.debug(f'Cannot save comment {comment.id}: {err}') _log.debug(f'Saved: {incidents_uuid}')