Skip to content
Back to skills

Mymeet Snapshot

ASecurity

Настроить/починить зеркало расшифровок встреч mymeet.ai и загрузку записи в облако на транскрибацию: "тянет чужие встречи", "api-ключ mymeet". Офлайн без облака - `local-transcription`.

  • 8 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 29, 2026
developmentpythonbashapibackend

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 3, 2026

npx -y skills add dewil/claude-toolkit --skill mymeet-snapshot --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Mymeet Snapshot?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Mymeet Snapshot
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/dewil-mymeet-snapshot/badge)](https://www.skillsdirectory.com/skills/dewil-mymeet-snapshot)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: mymeet-snapshot
description: Настроить/починить зеркало расшифровок встреч mymeet.ai и загрузку записи в облако на транскрибацию: "тянет чужие встречи", "api-ключ mymeet". Офлайн без облака - `local-transcription`.
---

# mymeet-snapshot

Скилл для первой настройки или починки локального snapshot расшифровок встреч из mymeet.ai через REST API. Скрипт тянет MD-отчеты проектных встреч и раскладывает по папкам `Встречи/` - для чтения, написания `.summary.md` и работы без захода в web-UI mymeet.

Скрипт-эталон лежит в каноне в `scripts/mymeet-snapshot.py` (top-level папка `scripts/`, не внутри папки скилла). `.AI` bootstrap типа management копирует его в `scripts/` в корне проекта - оттуда же, где его ожидает запуск (`python3 scripts/mymeet-snapshot.py`).

Архитектура повторяет `telegram-snapshot` / `redmine-snapshot`: общий секрет на устройстве, проектные указатели - в репозитории проекта.

## Когда применять

- Пользователь впервые настраивает `scripts/mymeet-snapshot.py` на новом устройстве.
- Подключается новый проект - нужно создать `.mymeet-snapshot.json` и проверить, что общая авторизация на устройстве уже есть.
- Скрипт тянет чужие (непроектные) встречи или кладет встречи не в ту папку - надо настроить правила `rules`.
- Первый запуск падает на авторизации (401) или на неизвестных полях ответа.

## Когда НЕ применять

- Обычный регулярный pull новых встреч - это просто Bash-команда (`python3 scripts/mymeet-snapshot.py --all`), отдельный скилл не нужен. Без флага скрипт только печатает справку и ничего не качает - не принимай это за выполненный pull.
- Анализ самих расшифровок - они уже лежат `.md` в `Встречи/`, читай напрямую.
- Чтение истории чатов - это `telegram-snapshot`. Задачи - `redmine-snapshot`.

## Что делает скрипт (модель)

1. `GET /api/workspaces/active/all-meetings` (пагинация `page`/`perPage`) - список встреч аккаунта.
2. Аккаунт mymeet общий, встреч много и не только этого проекта. Фильтр - **whitelist по правилам**: title встречи матчится подстроками из `rules[].match`; первое подошедшее правило задает папку (`rules[].dest`).
3. Подошла под правило + готовый статус (см. ниже) + есть дата -> качает MD (`GET /api/storage/download?format=md`) в `<meetings_root>/<dest>/ГГГГ-ММ-ДД.md` (коллизия в один день -> `-2`, `-3`).
4. НЕ подошла ни под одно правило -> в review-файл (`<meetings_root>/_mymeet-review.txt`) строкой `meeting_id | дата | title`. Человек глазами решает: проектную - добавить паттерн / дернуть вручную, чужую - игнорировать.
5. Что уже видел - помнит в `<meetings_root>/_mymeet-index.json`, повторно не качает.

JSON-отчет по умолчанию НЕ качается (для рутины хватает MD, на объемах JSON - оверхед). По требованию: `python3 scripts/mymeet-snapshot.py --json <meeting_id>` - положит `.json` рядом с MD этой встречи. Отдельного `-deltas` скрипта нет: новые встречи = то, что прогон только что скачал (печатается в конце), а не diff мутирующего файла, как у telegram/redmine.

Режимы (основной - точечный по id; аккаунт mymeet общий на проекты, поэтому балк по умолчанию выключен):
- `--pull <ID|URL>` - **основной режим**: точечно скачать одну встречу по правилам. Принимает и голый `meeting_id`, и URL встречи целиком (id берется из адреса - его видно в адресной строке mymeet). Рабочий цикл: пользователь правит имена спикеров на mymeet -> дает id/URL -> `--pull`.
- `--json <ID|URL>` - добрать JSON конкретной встречи (тоже принимает URL).
- `--list` - dry-run: что нашлось бы и куда легло, без скачивания.
- `--seed` - baseline: отметить все текущие встречи аккаунта как виденные, ничего не качая. Нужен на старте, если история уже скачана вручную: иначе балк создаст дубли существующих файлов (`-2`/`-3`).
- `--all` - балк: забрать ВСЕ новые проектные встречи разом (имена сырые, как распознал mymeet). По умолчанию НЕ запускается - голый прогон без аргументов печатает справку, чтобы на общем мульти-проектном аккаунте случайный запуск не нагреб чужое.

В `--pull` и `--all` статус берется из списка встреч сервиса. Только `processed` и `new` готовы. Любой другой или отсутствующий статус пропускается без скачивания и без ошибки. В stdout печатается `не готова: <id>, статус <статус>`; при отсутствии статуса выводится `нет статуса`.

Итог `--all` печатается в stdout:
- `OK:`, код 0 - все подходящие готовые встречи скачаны, включая прогон без новых встреч.
- `ЧАСТИЧНО:` со списком нескачанных id или ошибкой чтения списка, код 1 - есть ошибки скачивания или пагинации; успешные встречи сохраняются в индексе.
- Код 2 - ошибка конфига или авторизации (HTTP 401/403), если ничего не скачано. Если часть встреч скачана, ошибки авторизации дают `ЧАСТИЧНО:` и код 1.

Формат ответа API (подтверждено живым прогоном 2026-06-25): список - `GET all-meetings` -> `{followups: [...], total}`; у встречи поля `id`, `name` (title), `status` (`new`/`processed`/...), `date` в RFC 2822 (`"Thu, 25 Jun 2026 12:02:06 GMT"`). Скрипт читает их толерантно (перебор `*_KEYS`), дату парсит и ISO, и RFC 2822, и epoch.

## Алгоритм настройки

### Шаг 1. Проверить общую авторизацию устройства

```bash
ls ~/.config/mymeet-snapshot/
```

Должен быть `auth.json` (api_key, опционально base_url) с правами 600. Если файла нет - шаг 2.

### Шаг 2. Получить API-ключ mymeet

1. Залогиниться в mymeet.ai.
2. Settings -> API key (`https://app.mymeet.ai/ru/settings/api-key`).
3. Скопировать ключ. Доступно на тарифах Lite, Pro, Business.

### Шаг 3. Заполнить auth.json

```bash
mkdir -p ~/.config/mymeet-snapshot
chmod 700 ~/.config/mymeet-snapshot
```

Содержимое `~/.config/mymeet-snapshot/auth.json`:
```json
{
  "api_key": "<ключ из шага 2>",
  "base_url": "https://backend.mymeet.ai",
  "use_curl": true
}
```

- `base_url` можно опустить - дефолт `https://backend.mymeet.ai`.
- `use_curl` - поднять в `true`, если Python падает на SSL (`CERTIFICATE_VERIFY_FAILED`). Сборка python.org на macOS не имеет CA-бандла и не проверяет даже валидный публичный сертификат `backend.mymeet.ai`; curl берет сертификат из системного хранилища. На практике на macOS нужен `true`.

```bash
chmod 600 ~/.config/mymeet-snapshot/auth.json
```

### Шаг 4. Подключить проект (.mymeet-snapshot.json)

В корне проекта - `.mymeet-snapshot.json`:
```json
{
  "meetings_root": "Встречи",
  "rules": [
    { "match": ["синк", "заказчик"], "dest": "с заказчиком/{YYYY}/{MM}" },
    { "match": ["дейли", "дейлик", "команд"], "dest": "с командой/{YYYY}/{MM}" },
    { "match": ["1-1", "one-on-one"], "dest": "1-1/_inbox" }
  ],
  "review_file": "Встречи/_mymeet-review.txt"
}
```

- `meetings_root` - корневая папка встреч относительно корня проекта.

  **В проекте с несколькими направлениями** (клиент-зонтик, `rules/client-umbrella.md`) единой папки встреч нет: встречи направления живут внутри него (`rules/artifacts-structure.md`). Тогда `meetings_root` - корень проекта (`"."`), а полный путь несет `dest` каждого правила:

  ```json
  { "match": ["ShopHack"], "dest": "2026-07 Agent/Встречи/с командой/{YYYY}/{MM}" },
  { "match": ["Харитонов"], "dest": "Встречи/1-1/Харитонов Евгений" }
  ```

  Индекс `_mymeet-index.json` всегда лежит относительно `meetings_root`, поэтому при смене корня **перенеси существующий индекс руками** в новое место: на пустом индексе следующий прогон посчитает все старые встречи новыми и скачает их повторно. `review_file` - отдельный ключ (по умолчанию тоже относительно `meetings_root`); при `"."` задай его явно, иначе review осядет в корне.

- `rules` - список `{match: [подстроки title], dest: путь-шаблон}`. Первое правило, чья подстрока нашлась в title (регистронезависимо), задает папку. `dest` поддерживает `{YYYY}`/`{MM}`/`{DD}` из даты встречи.
- `review_file` - куда писать непроектные/нераспознанные встречи.

Файл - **не секрет** (ключа нет), коммитится.

> **Важно про title.** mymeet галлюцинирует в шапке (путает имена/стороны), поэтому матчинг по title не стопроцентный. Это осознанный компромисс: вместо тихого пропуска все непонятное падает в review-файл, где видно глазами. Не вылизывай правила до идеала - расширяй по мере того, как реальные встречи попадают в review. 1-1 по title в папку конкретного сотрудника не развести - кладем в `1-1/_inbox`, дальше руками.

### Шаг 5. Dry-run, потом первый pull

Сначала **всегда** `--list` - покажет, что API реально отдает и куда ляжет, ничего не качая:

```bash
cd <project-root>
python3 scripts/mymeet-snapshot.py --list
```

Сверь: проектные встречи распознались и нацелены в верные папки, чужое ушло бы в review. Если поля даты/title/id читаются неверно (видно по "дата?" или пустым title) - см. "Типичные ошибки". Когда раскладка верная:

```bash
python3 scripts/mymeet-snapshot.py --all
```

Флаг обязателен: голый запуск печатает справку и ничего не качает. История уже скачана вручную - вместо `--all` сначала `--seed`, иначе балк создаст дубли. Дальше рабочий цикл - точечный `--pull <ID|URL>`. Зависимостей нет - чистый stdlib (`urllib`).

### Шаг 6. Типичные ошибки

**`ssl.SSLCertVerificationError: CERTIFICATE_VERIFY_FAILED`.** Python не видит CA-бандл (типично для python.org-сборки на macOS). В `~/.config/mymeet-snapshot/auth.json` выставить `"use_curl": true` - запросы пойдут через curl, который берет сертификат из системного хранилища. Перезапустить.

**`401 Unauthorized`.** Неверный/просроченный api_key - перевыпустить (шаг 2). Проверить тариф (нужен Lite/Pro/Business).

**В `--list` у всех "дата?".** В ответе списка поле даты названо не так, как перебирает скрипт (`DATE_KEYS`). Посмотреть сырой ответ: `curl -H "X-API-KEY: <ключ>" "https://backend.mymeet.ai/api/workspaces/active/all-meetings?page=0&perPage=5"`, найти ключ с датой, добавить его первым в `DATE_KEYS` в скрипте (и оформить как upstream-правку в канон).

**Пустые title / не тот id.** Аналогично - проверить реальные имена полей в сыром ответе и поправить `TITLE_KEYS` / `ID_KEYS`.

**Все ушло в review, хотя встречи проектные.** Правила `rules[].match` не совпали с реальными title - расширить подстроки под то, как mymeet называет встречи (видно в review-файле).

**Перенес уже забранные встречи в другую папку.** Поправь у них в `_mymeet-index.json` поля `dest` и `file`: индекс хранит, куда файл лег, и точечный `--pull` этой встречи идет по записанному пути. Со старым путем будет одно из двух - если там пусто, приедет второй экземпляр рядом с перенесенным; если место уже занято другим документом, скрипт его перезапишет (прежнее содержимое уедет в `<имя>.prev.md`, в stderr будет предупреждение с путем и размерами).

**В файле шапка mymeet (супер краткое содержание, саммари, задачи).** Скрипт режет ее сам по маркеру `**Транскрипт:**` - если шапка на месте, значит маркера не нашлось (сменился формат) и в stderr было предупреждение. Файл сохранен целиком намеренно: резать по догадке нельзя, потеряется транскрипт. Убрать шапку вручную, а расхождение формата - оформить upstream-правкой в канон. Почему шапку не храним - `rules/meeting-transcripts.md`.

**MD пришел пустой / это JSON.** `download?format=md` мог вернуть не файл, а JSON со ссылкой на storage - скрипт это обрабатывает (следует по `url`/`download_url`/`link`). Если формат ответа иной - глянуть сырой ответ download и поправить `download_md`.

## Загрузка записи на транскрибацию

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

```bash
python3 scripts/mymeet-snapshot.py --upload звонок.mp3 --title "2026-08-04 Клиент - созвон"
python3 scripts/mymeet-snapshot.py --upload запись.m4a --template one-to-one --speakers 2 --wait
python3 scripts/mymeet-snapshot.py --status <meeting_id>
```

- `--title` - имя встречи. **Задавать сразу и по проектной конвенции**: под правило матчинга попадает имя, и запись с именем "voice_2026.m4a" осядет в review-списке вместо своей папки.
- `--template` - шаблон отчета сервиса (`default-meeting`, `one-to-one`, `hr-interview`, `lecture-notes`, `protocol` и др.; полный список в скрипте).
- `--speakers N` - число участников, если известно.
- `--wait` - дождаться обработки (поллинг статуса) и сразу забрать расшифровку по правилам конфига. Без флага скрипт печатает `meeting_id` и команду проверки статуса; транскрибация занимает минуты.
- Файл читается и шлется чанками, поэтому длинная запись не съедает память.

**Агент не запускает `--upload` без явного "ок" пользователя на конкретный файл.** Отдельного dry-run-гейта у команды нет намеренно (в отличие от `telegram-send`, где агент сочиняет текст сам): файл называет пользователь, и удваивать рутину подтверждением флага незачем. Но действие необратимо и платно, поэтому подтверждение остается - на уровне поведения, а не флага.

**Загрузка расходует минуты аккаунта** и создает встречу в общем workspace. Тестовые прогоны оставляют мусорные встречи, которые видны всем проектам, использующим этот аккаунт, - удалять через веб-интерфейс (API удаления скрипт не трогает).

### Грабли протокола

- **`localTime` на финализирующем чанке.** В OpenAPI 1.1.0 поле не помечено обязательным. 2026-07-28 без него финализация отдавала **голый 500 от nginx** (`text/html`, не JSON; `error_format=json` на такой ответ не действует) - в проекте-источнике это восемь дней принимали за поломку сервиса и писали в поддержку. На проверке 2026-08-04 сервер принял финализацию и без поля: вендор починил молча. Скрипт шлет поле всегда и сам - полагаться на негарантированное поведение нельзя.
- **Отсюда общий прием:** при интеграции сверяйся с **эталонной реализацией вендора**, а не только со спекой. Расхождение "в спеке поле необязательное, в примере кода оно есть в каждом запросе" - сигнал; проявляется оно не валидационной ошибкой, а 500, который читается как поломка чужой стороны.
- **Поле `file` обязательно даже у пустого финализирующего маркера** - без самого поля приходит 400.
- Коды ответа говорят по делу: `402` кончились минуты, `422` загрузка битая или вытеснена более новой попыткой (бывает при параллельных заливках одного файла), `426` не хватает минут на файл такой длины, `432` больше 1 ГБ нужен тариф выше, `433` запись короче 30 секунд, `414` больше 3 ГБ, `415` формат.

## Жесткие правила

1. **auth.json - НЕ в проектную папку.** Проект на Yandex.Disk; утечка api_key в облако недопустима. Только `~/.config/mymeet-snapshot/` (локально на устройство).
2. **api_key - секрет.** В `.mymeet-snapshot.json`, который коммитится, ключа быть не должно.
3. **Whitelist, не pull-all.** Аккаунт общий; качать все подряд нельзя. Непроектное - в review, не на диск.
4. **JSON - по требованию.** Рутинно держим только MD. JSON (`--json`) - точечно, когда нужна программная обработка (`word_timings`/`chapters`).
5. **Выгруженный JSON - технический артефакт: место ему вне синкаемой папки, а не под ignore после факта** (`rules/docs-maintenance.md`, раздел "Технические артефакты в синкаемой папке"): исключение защищает следующий файл, уже созданный оно не возвращает. Заметки встреч - наоборот, содержимое: они остаются в проекте. Исходных записей это не касается - у них жизненный цикл строже: после проверенной транскрибации запись из проекта убирается совсем (`rules/meetings.md`, "Записи: в проекте не храним"), а не остается лежать под ignore.

## Связанные файлы

- `scripts/mymeet-snapshot.py` в корне проекта - pull MD проектных встреч по whitelist, `--list` (dry-run), `--json <id>` (добор JSON).
- `~/.config/mymeet-snapshot/auth.json` - локальные credentials на устройство (api_key, base_url). Не в проекте.
- `.mymeet-snapshot.json` в корне проекта - проектные указатели `{meetings_root, rules, review_file}`. Не секрет.
- `<meetings_root>/_mymeet-index.json` - реестр уже скачанных встреч (что не качать повторно).
- `<meetings_root>/_mymeet-review.txt` - очередь непроектных/нераспознанных встреч на ручное решение.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.