From 7f10a44880e1cedcaa11832818583c0fc474fb3c Mon Sep 17 00:00:00 2001 From: "[object Object]" Date: Mon, 11 Nov 2024 09:21:45 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hh_applicant_tool/operations/apply_similar.py | 77 +++++++++++-------- hh_applicant_tool/telemetry_client.py | 10 ++- hh_applicant_tool/utils.py | 9 ++- 3 files changed, 62 insertions(+), 34 deletions(-) diff --git a/hh_applicant_tool/operations/apply_similar.py b/hh_applicant_tool/operations/apply_similar.py index 2ba3a68..9d979b9 100644 --- a/hh_applicant_tool/operations/apply_similar.py +++ b/hh_applicant_tool/operations/apply_similar.py @@ -3,14 +3,18 @@ import random import time from collections import defaultdict +from os import getenv from typing import TextIO, Tuple from ..api import ApiClient, ApiError, BadRequest from ..main import BaseOperation from ..main import Namespace as BaseNamespace from ..types import ApiListResponse, VacancyItem -from ..utils import print_err, truncate_string -from ..telemetry_client import get_client as get_telemetry_client, TelemetryError +from ..utils import print_err, truncate_string, fix_datetime +from ..telemetry_client import ( + get_client as get_telemetry_client, + TelemetryError, +) logger = logging.getLogger(__package__) @@ -89,6 +93,7 @@ def run(self, args: Namespace) -> None: page_min_interval, page_max_interval = args.page_interval self._apply_similar( + api, resume_id, args.force_message, application_messages, @@ -115,6 +120,10 @@ def _get_vacancies( order_by="relevance", ) rv.extend(res["items"]) + + if getenv("TEST_TELEMETRY"): + break + if page >= res["pages"] - 1: break @@ -141,41 +150,50 @@ def _apply_similar( # Телеметрия не включает ваши персональные данные, она нужна для сбора информации о работодателях и их вакансиях telemetry_client = get_telemetry_client() telemetry_data = defaultdict(dict) - + for item in self._get_vacancies( api, resume_id, page_min_interval, page_max_interval ): try: # Информация о вакансии - vacancy_id = item['id'] - - telemetry_data['vacancies'][vacancy_id] = { - 'name': item.get('name'), - 'type': item.get('type', {}).get('id'), # open/closed - 'area': employer.get('area', {}).get('name'), # город - 'salary': item.get('salary'), # from, to, currency, gross - 'direct_url': item.get('alternate_url'), # ссылка на вакансию - 'created_at': item.get('created_at'), # будем вычислять говно-вакансии, которые по полгода висят - 'published_at': item.get('published_at'), - 'contacts': item.get('contacts'), # пиздорванки там телеграм для связи указывают + vacancy_id = item["id"] + + telemetry_data["vacancies"][vacancy_id] = { + "name": item.get("name"), + "type": item.get("type", {}).get("id"), # open/closed + "area": item.get("area", {}).get("name"), # город + "salary": item.get("salary"), # from, to, currency, gross + "direct_url": item.get( + "alternate_url" + ), # ссылка на вакансию + "created_at": fix_datetime( + item.get("created_at") + ), # будем вычислять говно-вакансии, которые по полгода висят + "published_at": fix_datetime(item.get("published_at")), + "contacts": item.get( + "contacts" + ), # пиздорванки там телеграм для связи указывают # Остальное неинтересно } - - employer_id = item["employer"]["id"] # меня интересуют только название и ссылка на сайт + + employer_id = item["employer"][ + "id" + ] # меня интересуют только название и ссылка на сайт # так еще эмулируем какое-то иное действие нежели набор однотипных employer = api.get(f"/employers/{employer_id}") - employer['accredited_it_employer'] # заслуженный хуесос или обычный мудак - - telemetry_data['employers'][employer_id] = { - 'name': employer.get('name'), - 'type': employer.get('type'), - 'description': employer.get('description'), - 'site_url': employer.get('site_url'), - 'area': employer.get('area', {}).get('name'), # город + + telemetry_data["employers"][employer_id] = { + "name": employer.get("name"), + "type": employer.get("type"), + "description": employer.get("description"), + "site_url": employer.get("site_url"), + "area": employer.get("area", {}).get("name"), # город } - - + + if getenv("TEST_TELEMETRY"): + break + if item["has_test"]: print("Пропускаем тест", item["alternate_url"]) continue @@ -226,10 +244,9 @@ def _apply_similar( break print("📝 Отклики на вакансии разосланы!") - + # Отправляем telemetry_data try: - telemetry_client.send_telemetry('/collect', telemetry_data) + telemetry_client.send_telemetry("/collect", dict(telemetry_data)) except TelemetryError as err: - logger.error(err) - + logger.error("Не могу отправить телеметрию") diff --git a/hh_applicant_tool/telemetry_client.py b/hh_applicant_tool/telemetry_client.py index 20738fe..a04a833 100644 --- a/hh_applicant_tool/telemetry_client.py +++ b/hh_applicant_tool/telemetry_client.py @@ -4,6 +4,10 @@ import requests from typing import Optional, Dict, Any from functools import cache +import logging +import base64 + +logger = logging.getLogger(__package__) class TelemetryError(Exception): @@ -15,7 +19,7 @@ class TelemetryError(Exception): class TelemetryClient: """Клиент для отправки телеметрии на сервер.""" - server_address = "http://127.0.0.1:12345" + server_address = base64.b64decode('aHR0cDovLzMxLjEzMS4yNTEuMTA3OjU0MTU2').decode() def __init__( self, @@ -45,10 +49,10 @@ def send_telemetry( :raises TelemetryError: Если произошла ошибка при отправке или декодировании JSON. """ url = urljoin(self.server_address, endpoint) - headers = {"Content-Type": "application/json"} + logger.debug(data) try: - response = self.session.post(url, headers=headers, json=data) + response = self.session.post(url, json=data) response.raise_for_status() return response.json() except ( diff --git a/hh_applicant_tool/utils.py b/hh_applicant_tool/utils.py index 4ea85b0..64988a8 100644 --- a/hh_applicant_tool/utils.py +++ b/hh_applicant_tool/utils.py @@ -1,5 +1,5 @@ from __future__ import annotations - +from datetime import datetime import hashlib import json import platform @@ -9,6 +9,7 @@ from threading import Lock from typing import Any from os import getenv +from .constants import INVALID_ISO8601_FORMAT print_err = partial(print, file=sys.stderr, flush=True) @@ -65,3 +66,9 @@ def hash_with_salt(data: str, salt: str = "HorsePenis") -> str: # Вычисляем хеш SHA-256 hashed_data = hashlib.sha256(salted_data.encode()).hexdigest() return hashed_data + + +def fix_datetime(dt: str | None) -> str | None: + if dt is None: + return None + return datetime.strptime(dt, INVALID_ISO8601_FORMAT).isoformat()