В начале 2022 года Купер, как и многие компании, лишился привычных инструментов ноукод-автоматизаций. До этого мы активно использовали Workflow Builder, встроенный в Slack, в связке с Zapier и Google Apps Script. Одним из важных инструментов, созданных с помощью этого набора, была автоматизация рассылки уведомлений об инцидентах — как внутри компании, так и партнерам. Переезд в Mattermost оказался болезненным: рассылки по чатам, каналам и почте приходилось делать вручную, ведь отказаться от информирования мы не могли.

Как мы выкрутились из этой ситуации и дополнили сервис еще кучей полезных автоматизаций? Расскажу я, Алексей Глотов — руководитель группы разработки автоматизаций внутренних процесов отдела мониторинга.

Оглавление

  • Первое решение — Jarvis bot

  • Рождение комбайна — Harvester bot

  • Базовая настройка Harvester

  • Ключевые фичи: регистрация тикетов, обмен комментариями, манипуляции с тикетами из мессенджера, интерактивное меню, призыв дежурных, интеграция с умным чат-ботом

  • Дополнительные фичи

  • Итоги и план улучшений

Встречайте Jarvis bot

Когда стало понятно, что без автоматизации наша жизнь похожа на страдающее Средневековье, мы решили написать свой сервис, с помощью которого можно управлять рассылками прямо из Mattermost. Назвали его Jarvis bot.

Базовый функционал удалось реализовать довольно быстро, но почти сразу мы начали замечать те же проблемы, что и при старых автоматизациях. Сложнее всего техподдержке было правильно проставлять галочки, выбирая нужные каналы коммуникации и партнеров в зависимости от темы инцидента и его приоритета.

На первый взгляд ничего сложного, но когда инженер ведет несколько инцидентов одновременно, а каналов коммуникации больше двух десятков, внимание рассеивается — легко перепутать, что и куда отправлять.

Как решить проблему? Сделать так, чтобы сотруднику вообще не нужно было думать, какую информацию кому и куда отправлять. Первым делом пришла идея ввести компонент, по которому бот мог бы все определять самостоятельно.

Чтобы сократить время, мы решили найти готовое решение, подходящее на роль справочника таких компонентов. Важными условиями были:

  • простой и понятный интерфейс

  • возможность вносить изменения в справочник «на лету»

  • возможность предоставить доступ к редактированию справочника без лишних телодвижений другим пользователям (ответственным за процесс, не инженерам)

Наш запрос полностью закрыл инструмент Jira Assets. Отличная штука для управления активами, пусть и с не самым удобным API. Помимо справочника компонентов, мы создали справочники чатов и каналов в Telegram, каналов в Mattermost и списков почтовых адресов партнеров.

Мы разделили всю базу по типам (Telegram, Mattermost, email) и присвоили каждому элементу пороговый приоритет — начиная с него применяется соответствующая схема нотификации. Под схемой нотификации понимается элемент справочника с нужными чатами/каналами/почтами.

Дополнительно мы сделали справочник групп пользователей, на которых влияет инцидент (клиенты, партнеры, разработка и т. д.), а также справочник ранбуков со ссылками, чтобы коллегам не приходилось искать их вручную. Всю эту систему связали с компонентами, которые назвали по бизнес-функциям, чтобы инженеру не пришлось гадать, что выбрать: какая функциональность сломалась — такую и бери.

Выглядело многообещающе. Оставалось лишь научить бота со всем этим работать, чем мы и занялись.

Мы создали в проекте Jira поле, чьим источником стал справочник бизнес-функций, и настроили Automation, отправляющий боту выбранный компонент и остальные нужные атрибуты тикета для каждого инцидента. Мы определили, какие изменения в данных будут триггером для рассылки, и научили бота получать схемы нотификаций и остальные атрибуты бизнес-функции. Еще мы частично продублировали функционал Jira в Mattermost с помощью Interactive Dialogs и Interactive Messages, чтобы инженер мог не только зарегистрировать инцидент не отходя от кассы, но и заполнить его, параллельно управляя рассылками.

Jarvis превращается в комбайн

Со временем мы активно дописывали в Jarvis bot разный функционал. В основном фичи так или иначе касались инцидентов, но однажды команде продуктовой поддержки понадобилась автоматическая регистрация обращений в Jira из определенного канала Mattermost. Мы подумали: «Почему бы и нет?» — и добавили эту приколюху в бот.

Модуль получился очень маленьким, так что мы решили: ничего страшного, если Jarvis понемногу превратится в небольшой комбайн с разношерстным функционалом.

Дальше к нам пришли ребята из разработки, которые тоже в своем Mattermost-канале поддерживали пользователей своих сервисов. Их запрос был очень похож на то, что мы уже сделали для продуктовой поддержки, поэтому надо было просто переиспользовать имеющийся функционал с небольшими правками и унификацией.

Спустя еще некоторое время в ведение отдела мониторинга перешла первая линия поддержки инфраструктуры. Учитывая большой поток запросов, мы выделили новой команде отдельный сервисный проект в Jira, а в Mattermost-канале, где принимались и обрабатывались запросы, реализовали автоматизированную регистрацию тикетов через интерактивное меню. Автору запроса показывается интерактивное сообщение, и он должен выбрать категорию перед созданием тикета. В зависимости от выбранной категории тикету автоматически присваивается компонент в Jira, на основе которого (тоже автоматически) выставляется приоритет.

Новый модуль сразу умел:

  • работать в тредах с интерактивным меню в Mattermost;

  • регистрировать тикеты из Mattermost в Jira (как в сервисные, так и в Software-проекты);

  • назначать тикеты «на себя» прямо из тредов, где они зарегистрированы;

  • тегать в тредах дежурных из Grafana OnCall (это плагин для управления расписаниями дежурств и выполнения пошаговых автоматизаций по событиям);

  • тегать в тредах различные предустановленные команды;

  • транслировать комментарии (из треда в тикет и обратно);

  • закрывать или отклонять тикеты с помощью эмодзи на корневом сообщении треда.

Комбайн перестал быть таким уж небольшим, пришло время нового бота. Модуль, разработанный для поддержки инфраструктуры, прижился и стал отправной точкой для написания этого нового унифицированного сервиса для автоматизации обработки обращений.

Второй бот. Подключение каналов и управление автоматизациями

Разработка новенького «коллеги» началась с фундаментальных вопросов. Как с легкостью подключать каналы? Как хранить конфиги каждого канала? Как управлять набором автоматизаций для каждого канала отдельно? Какой набор автоматизаций потенциально может понадобиться в том или ином канале поддержки?

С неймингом справились проворно: раз комбайн — пусть и называется Harvester bot.

Нам было важно, чтобы всю настройку можно было делать через понятный интерфейс. Почему бы не использовать для этого интерактивные диалоги Mattermost? Опыт работы с ними у нас к тому моменту уже был, как я писал выше.

Мы накидали форму диалога и создали валидатор, который, например, не дает включить флаг интерактивного меню, если в конфиге не указан ID главного раздела, или не позволяет добавить кастомные поля абы как (требуется валидный JSON). В итоге мы получили возможность добавлять конфигурации каналов и управлять наборами автоматизаций для них «здесь и сейчас», не выходя из мессенджера.

Чтобы все летало, конфиги хранятся в базе данных в двух таблицах:

  1. Таблица базовой конфигурации каналов содержит настройки автоматизаций для канала: какой проект Jira, какие типы тикетов, кастомные поля и прочее;

  2. Таблица флагов хранит состояния (вкл/выкл) различных автоматизаций для канала.

Над функционалом долго думать не пришлось: кое-что уже было реализовано в Jarvis bot, в бэклоге лежало несколько фич-реквестов, да и многолетний опыт поддержки подсказывал, что может понадобиться. Плюс запросов накидали первые заказчики нового бота.

Далее — о ключевых возможностях Harvester.

Фича №1. Регистрация тикетов

Одной из важнейших функций бота стала регистрация тикетов из канала Mattermost в Jira. Регистрировать тикет вручную из чата — потеря времени и фокуса, ведь инженеру приходится переключаться между окнами. К тому же велик риск забыть про сам запрос; репортер огорчится, а потерянные тикеты не позволят отследить работу команды.

В автоматическом режиме регистрации все довольно просто. При появлении нового сообщения в канале (не в треде) Harvester берет по ID канала преднастроенный конфиг и согласно ему создает тикет в Jira или Jira Service Desk — используя соответствующий REST API.

Зачем усложнять, если инженер все равно будет работать с тикетом в Jira? Когда проект сервисный, репортер обычно получает доступ к тикету только через портал JSD. Чтобы репортер мог следить за статусом своего запроса, созданного через бота, и общаться с исполнителем, тикет нужно создавать через API сервиса от имени репортера.

При создании тикета мы подставляем в его summary шаблон вроде [mattermost] post from pupkin.va, в description — текст сообщения из канала, ссылку на тред в мессенджере и ссылки на файлы, если к сообщению что-то прикреплено. Для однозначной связи тикета с тредом мы сохраняем post_id и channel_id в issue property тикета.

Почти всегда в проектах при создании тикета есть обязательные поля, помимо стандартных. Для этого в конфиге канала предусмотрено поле для кастомных полей — JSON в том формате, которого ожидает Jira. При регистрации тикета мы берем этот JSON из конфига и подмешиваем к данным запроса перед вызовом API.

Если все прошло успешно, Harvester ответит репортеру в треде сообщением с номером тикета и ссылкой на него.

В случае автоматической регистрации в пределах одного канала мы всегда создаем тикеты в одном проекте и с одинаковым набором полей (который ограничен конфигом канала). Если использовать интерактивное меню, все получается гибче, так как у каждой кнопки могут быть свои значения. То есть для каждой отдельной кнопки, которая регистрирует тикет, можно задать свой проект, тип тикета/запроса и свой набор кастомных полей.

Фича №2. Обмен комментариями

Если мы создаем тикет из треда, неплохо бы и контекст переписки положить в Jira. Куда его класть? Конечно, в комментарии тикета.

После того как Harvester ловит новое сообщение в треде, он идет в Jira и выполняет JQL-запрос, пытаясь найти тикет по ID треда. Ранее упоминалось, что при регистрации тикета мы сохраняем post_id в свойство тикета. Если сделать это свойство индексируемым (тут помогают администраторы Jira), по нему можно искать через JQL.

Именно так мы и делаем. Если тикет находится, бот добавляет в него комментарий с текстом нового сообщения из треда. В текст комментария мы также добавляем ссылки на файлы, если они есть, и указываем автора сообщения. Кроме того, в свойствах комментария сохраняется email автора сообщения из треда, чтобы в дальнейшем это можно было использовать в других автоматизациях.

Обратный процесс — отправка комментариев из тикета в тред — реализован через Jira Automation. При добавлении публичного комментария в Jira автоматизация отправляет боту текст комментария, его автора, а также post_id и channel_id, которые мы сохранили в свойстве тикета при регистрации. Бот, получив эти данные, отправляет комментарий в соответствующий тред, обязательно указав автора.

Фича №3. Манипуляции с тикетами из мессенджера

После регистрации тикета из чата нам захотелось иметь возможность немного управлять тикетом прямо из треда.

В ответ на сообщение о создании тикета (где Harvester пишет номер тикета и ссылку) мы добавили вложение с кнопкой «Назначить на меня». Для этого использовали Interactive Messages Mattermost.

При нажатии на кнопку бот идет в тикет (его номер передается в контексте кнопки) и назначает ответственным того, кто нажал кнопку. После успешного нажатия кнопка прячется, а вместо нее вписывается имя ответственного.

Изредка случаются накладки: тикет забирает на себя не тот, кто хотел, а тот, кто его создал, и мы пока не придумали, как это побороть. Но такие случаи редки, поэтому мы не тратим на это много времени.

После назначения ответственного бот заглядывает в конфиг канала, где был зарегистрирован тикет, и берет оттуда ID перехода в статус In Progress. Если ID не указан — ничего не происходит.

Процесс работает и в обратную сторону, хотя для этого снова понадобится настройка автоматизации в Jira. Если тикет в Jira назначить ответственному (например, через сервис-деск), Jira отправит боту по настроенному правилу почту ответственного, post_id треда и channel_id. Бот найдет сообщение в треде, спрячет кнопку «Назначить на меня» и подставит туда имя назначенного ответственного.

Назначить ответственного на тикет можно и без кнопки. Отдельным флагом включаем автоматическое назначение на первого, кто оставит сообщение в треде. Harvester ловит сообщение и проверяет ряд условий:

  • это первое сообщение в треде;

  • автор сообщения — не сам Harvester;

  • сообщение не является ключевым словом для вызова какого-либо действия (о ключевых словах будет позже);

  • в треде действительно зарегистрирован тикет.

Если все сходится, бот делает то же самое, что и по кнопке «Назначить на меня».

Еще мы реализовали возможность двигать тикет в статусы Resolved, Canceled и Need Info (могут быть любые другие статусы). Если в конфиге канала указать ID переходов в Resolved и Canceled, то в том же сообщении треда с номером тикета Harvester прикрепит еще одно служебное вложение. Там будет написано, какие эмодзи нужно поставить на корневое сообщение треда, чтобы закрыть или отменить тикет. Для перехода в статус Need Info тоже зарезервирован эмодзи.

Некоторые команды практикуют назначение своей команды ответственной за тикет — как правило, чтобы тикет сразу попадал к ним на доску. Это снова реализовано через интерактивные сообщения.

При регистрации тикета Harvester может предложить репортеру назначить тикет на команду, если соответствующий флаг включен в конфиге. Перед тем как отправить в тред интерактивное сообщение с выпадающим списком команд, бот обращается к созданному тикету и запрашивает у Jira разрешенные значения для поля команды. Получив список вариантов, бот отправляет их опциями в выпадающем списке.

При выборе нужной команды бот проставит ее в тикете, а затем вернется в тред и тегнет эту команду, чтобы оповестить о новом запросе. Если же команду назначат на тикет со стороны Jira, автоматизация Jira пришлет боту post_id, channel_id и название команды, чтобы бот потегал ее в треде.

Фича №4. Интерактивное меню

Фактически Harvester изначально задумывался вокруг интерактивного меню. Требования были похожи на те, что мы предъявляли к справочнику компонентов в Jarvis bot:

  • меню должно строиться и изменяться «на лету»;

  • простой и понятный интерфейс для настройки;

  • никаких проблем с доступом к настройке меню.

Инструмент Jira Assets снова подошел под критерии.

Разделами меню стали типы объектов в ассетах, а сами объекты стали исполняемыми кнопками. Оставалось понять, как обработать вложенность типов объектов, чтобы меню могло иметь сколько угодно уровней.

Покрутив Jira Assets, мы выяснили, что если построить иерархическую структуру объектов, то через API можно получить список всех дочерних типов объектов. Структура ответа была так себе, но мы придумали, как ее обработать, чтобы выделять только следующий уровень вложенности типов и отсекать более глубокие уровни.

Самое сложное позади: мы получили конструктор интерактивного меню, не написав ни строчки своего UI-кода. Объектам (конечным кнопкам) мы добавили необходимые атрибуты, чтобы бот понимал, что нужно делать, и научили бота обрабатывать эти кнопки. В Mattermost для визуализации и интерактивности используем Interactive Messages.

Однако некоторые команды хотели меню, отличающееся от простого иерархического. Им требовалось разбить кнопки на панели с заголовками. Для таких случаев мы разделили объекты меню на три группы: Buttons (кнопки), Panels (панели с кнопками) и Boards (доски, они же уровни меню). Обработка навигации здесь оказалась проще: к доскам прикреплены панели, а к панелям — кнопки.

Набор возможных действий из интерактивного меню у нас получился следующий:

create_issue — зарегистрировать тикет. В случае интерактивного меню это не ограничено одним проектом по умолчанию: у каждой кнопки свой конфиг, заложенный в атрибуты объекта кнопки.

go_to_board — перейти к другому уровню меню с панелями.

mindhub_consult — запросить консультацию у внутреннего сервиса MindHub (о нем чуть позже).

mindhub_related_threads — найти похожие обращения (треды) в канале.

mindhub_release_unlock — разблокировать релиз-пайплайн во время заморозки.

no_action — ничего не делать (пустая заглушка).

on_call_schedule — призвать дежурных из расписания Grafana OnCall.

send_message — отправить сообщение.

team_tag — тегнуть определенную команду.

user_tag — тегнуть определенного пользователя.

Если кнопка не должна выполнять действие, а служит навигацией, ей присваивается действие go_to_board. Обрабатывая такое действие, бот берет ID связанной доски и открывает ее.

Добавить новые действия в бот не составляет особого труда.

Помимо самого меню, вторым вложением интерактивного сообщения мы прикрепляем две служебные кнопки:

  1. «Вернуться в начало» возвращает в начальный раздел меню;

  2. «Галя, у нас отмена!» закрывает меню, если оно больше не нужно.

Все интерактивные действия обрабатываются на стороне бота в рамках одного класса.

Фича №5. Призыв дежурных

В какой-то момент с командой Observability было принято решение реализовать в Jarvis bot интерфейс для получения текущих дежурных по ID расписания (для разных внутренних сервисов и автоматизаций).

Почему в Jarvis? Потому что Jarvis по своей природе — инструмент команды мониторинга. Harvester делает запрос в Jarvis с ID нужного расписания, Jarvis запрашивает дежурных у Grafana OnCall и возвращает ответ Harvester.

В Harvester реализовано два сценария призыва дежурных: автоматический и по кнопке интерактивного меню. Автоматический срабатывает при появлении нового сообщения в канале, а про кнопку, думаю, и так понятно.

Мы понимали, что по кнопке из меню и автоматически при новом сообщении может выполняться сразу несколько автоматизаций. Призыв дежурного может подразумеваться по этому флоу, но не быть обязательным шагом. Например, можно предложить репортеру сначала выполнить какие-то рекомендации, а если не поможет — позвать дежурного.

Мы добавили параметр OnCallType, который принимает два значения: auto и on_button. При первом значении бот сразу призовет дежурного — будь то автоматически или по нажатию кнопки меню. При втором значении он никого не позовет и просто отправит в тред дополнительное сообщение с кнопкой «Позвать дежурного».

Когда мы впервые включили эту функцию коллегам в канале, сразу получили запрос: проверять, отреагировал ли дежурный в треде, где его позвали. Логично. Мы условились считать реакцией дежурного его ответное сообщение. Добавили параметр OnCallDelay, куда заносим время в секундах, за которое, по мнению лида команды, дежурный должен отреагировать в треде. По истечении этого времени бот возвращается в тред (отложенная задача) и ищет сообщение от дежурного позже времени вызова. Не нашел — зовет всю команду.

Фича №6. Интеграция с MindHub

Интересное дополнение возникло, когда наши коллеги запустили ИИшный чат-бот, который умеет в RAG (Retrieval Augmented Generation) и может на естественном языке консультировать по внутренней документации компании.

Изначально MindHub консультировал только в личных сообщениях, но нам предложили заколлабиться и сделать API, позволяющее получать консультацию прямо в треде. Мы, конечно, не отказались — вместе веселее! С тех пор у Harvester появился боевой товарищ, который умеет давать консультации, если действие кнопки подразумевает такой запрос.

Разработчики MindHub на этом не остановились и предложили еще одну фичу — поиск похожих тредов в канале. Harvester может попросить MindHub найти в канале X похожих сообщений за Y последних дней. Вышло довольно интересно, потому что зачастую вопрос, который репортер хочет решить в треде, уже поднимался ранее в этом же чате. Репортер может перейти в найденный тред и посмотреть, как проблему решили раньше (ну или не решили).

Обе возможности могут работать как по кнопке из интерактивного меню, так и автоматически для каждого нового сообщения в канале.

Вишенки нашего торта

Кроме основных автоматизаций, Harvester имеет на борту несколько дополнений, которые делают его более гибким.

Ключевые слова

У бота есть три ключевых слова, на которые он особым образом реагирует в тредах.

harv.menu вызывает интерактивное меню в треде повторно. Полезно, если меню уже закрыто, а пользователю снова понадобились его функции.

harv.ticket создает тикет в треде, если ранее в этом треде тикет не создавался. Этим пользуются коллеги, у кого интерактивное меню не приводит к регистрации тикета, но тикет все же нужно создать. Harvester создаст тикет с атрибутами, указанными в конфиге канала.

harv.oncall призывает дежурных из расписания Grafana OnCall, указанного в конфиге канала.

Приветственное сообщение

Когда мы подключили бота в собственный канал для приема обращений, выяснилось, что к нам часто приходят коллеги «не по адресу». Чтобы репортер зря не нажимал кнопки меню, мы решили на входе отправлять приветственное сообщение, где четко написано, какая команда здесь работает и какие вопросы в этом чате решаются.

Позднее оказалось, что такая функция нужна не только нам. Так приветственное сообщение и прижилось.

Черный список

Понаблюдав за ботом, мы обратили внимание на то, что в чаты приходят (внезапно!) другие боты. Обычно это разные автоматизации, которые периодически или по событиям приносят командам полезную информацию. Наш Harvester исправно реагировал и на такие сообщения — предлагал понажимать кнопочки или призвать дежурного, хотя далеко не всегда это требуется.

Так родились заданные вручную для каждого канала списки ID пользователей Mattermost, которых нужно игнорировать.

Белый список

Где есть черные списки, появляются и белые. В одной команде процесс поддержки устроен не так, как мы ожидали. При поступлении запроса в чат репортеру показывается интерактивное меню для выбора категории запроса. Но пользоваться этим меню ему не положено: лидер команды приходит в тред и сам выбирает категорию для регистрации тикета.

Конечно, боту нужно знать, кому в канале разрешено нажимать кнопки. Для этого мы используем тег группы пользователей Mattermost. В конфиге канала указывается название группы, Harvester по нему собирает ID всех участников и проверяет, входит ли инициатор действия в этот список. Если не входит — действие не выполнится.

Загрузка линии

Еще на этапе разработки бота наш руководитель попросил, чтобы бот умел сообщать репортеру, что накопилась большая очередь нерешенных тикетов и придется подождать. Что ж, сделали. В конфиг добавили флаг, который включается вручную. При включенном флаге бот автоматически отправляет шаблонное сообщение.

Проверка рабочего времени

Мы сразу предусмотрели, что далеко не все команды оказывают поддержку круглосуточно. При поступлении сообщения бот смотрит в конфиг, где заданы рабочие часы, рабочие дни и информация о том, работает ли команда в праздники. Если сообщение пришло вне рабочего времени, бот сообщает об этом. При этом, в зависимости от настройки, бот может либо заблокировать выполнение автоматизаций, либо нет. То есть он может проинформировать, когда команда доступна, но все равно дать репортеру зарегистрировать тикет, или заблокировать регистрацию.

Нет предела совершенству

Запуская этот сервис, мы прежде всего хотели, чтобы он делал работу техподдержки легче. Мы этого добились: коллеги отмечают удобство, гибкость и полезный функционал бота. Harvester работает и собирает положительные отзывы.

Достаточно ли этого? Нет. Мы не можем подсчитать эффект от его работы, не видим, как срабатывают автоматизации.

Оперативно можно посчитать только три метрики: количество пользователей, количество подключенных каналов и количество созданных тикетов. Хотелось бы сильно расширить этот список, чтобы у владельцев каналов была полноценная аналитика, которая будет указывать на пробелы в процессах поддержки продукта, часто задаваемые вопросы и т. д. Пока это лишь планы, но мы уверенно движемся к реализации.

Пожелайте удачи в комментариях! А может быть, у вас появились еще идеи, как улучшить наш комбайн.

Комментарии (5)


  1. pinac
    05.11.2025 08:00

    Что с головой на фотографии?


  1. Lampadov
    05.11.2025 08:00

    Делаю множество заказов в Купер в течение нескольких лет, потом не пользуюсь сервисом примерно год. Приходит сообщение от Купер в стилистике "Тебя давно не было, вот тебе индивидуальный промокод на скидку 50 процентов". Делаю заказ, начинается его обработка, потом система сносит мой аккаунт, более зайти в него я не могу. Очевидно, что ложно сработал антифрод. Пишу в техническую поддержку с указанием всех деталей, где через 5 минут, вероятно, даже ни в чем не разобравшись, мне отвечают, что мол до свидания, восстановить ничего нельзя.
    Базово это всё, что нужно знать о технической поддержке сервиса в адрес активных пользователей - лояльность примерно околонулевая.


    1. Gnollface
      05.11.2025 08:00

      Это конечно всё печально, но как данный коммент относится к теме поста ?


      1. Lampadov
        05.11.2025 08:00

        Вероятно, так же напрямую, как связан Ваш аккаунт с Купером, раз регистрация была выполнена сразу после написания комментария


        1. Gnollface
          05.11.2025 08:00

          Так я и не отрицаю что в результате серии невероятных случайностей я сейчас каким-то образом связан с купером. Даже больше скажу, автора данной публикации я лично знаю.
          У меня тоже, как у клиента Купера, бывает много вопросов к ТП, особенно относительно времени реакции, тут я более чем солидарен. И чувство, что скрипты для ТП писали под веществами ... к сожалению это всё относится не только к Куперу.
          Но это всё не дает ответа как личная обида на конкретную ситуацию с конкретной компании относится к тому, что работники этой компании делятся личным опытом, технической информацией, показываю как надо (или не надо) или можно решать некоторые ситуации ?
          У меня была неприятная ситуация с яндексом, из-за которой я потерял около 1500р, но это не повод всех работников яндекса считать людьми на букву П., да даже компанию в целом.

          ЗЫ: относительно даты регистрации, к сожалению пролюбил свой акк от 2022г :( а тк пишу и делаю комменты редко, как и Вы, то ... ну и фиг с ним )