Вход на сайт

Просмотр новости

Найдите то, что Вас интересует

Git в Telegram: как я избавился от JSON, победил Markdown и получил security by design

Дата публикации: 02-07-2026 09:39:00

Git в Telegram? Без JSON, с SQLite, победой над Markdown и security by design. Код, схема БД, факапы и ссылка на бота.— Читать дальше «Git в Telegram: как я избавился от JSON, победил Markdown и получил security by design»

Основное содержимое страницы с новостью.

В своём Telegram-канале я время от времени предлагаю подписчикам выбрать очередную «бредовую» идею для реализации. На этот раз победил Git в Telegram: чтобы можно было инитить проекты, пушить файлы, коммитить — и всё это прямо в мессенджере.

С практической точки зрения проект на**й не нужен. Есть GitHub, GitLab и куча нормальных инструментов. Но как эксперимент — почему бы и нет? Чисто посмотреть, можно ли заставить Telegram работать как VCS.

На старте я думал: «Положу всё в JSON, на кой мне база данных?» Проектов мало, пользователей немного, файлы текстовые — чего заморачиваться?

Подергал JSON туда-сюда пару дней и понял: не варик.

  1. Конкурентный доступ. Два юзера одновременно коммитят — один перезаписывает файл другого.
  2. Целостность данных. Если бот упал в середине записи — JSON остаётся в невалидном состоянии.
  3. Версионность. Хранить историю изменений в JSON — это просто перенести проблему из кода в структуру файла.

Вывод: JSON — для конфигов, а не для данных, которые меняются каждую секунду.

Выбор SQLite и схема БД

Выбрал SQLite, потому что:

  • Не надо поднимать отдельный сервер
  • Целостность данных на уровне движка (транзакции, foreign keys, rollback)
  • Всё в одном файле — скопировал и унёс

Сущности:

  • users — telegram_id, username, current_project_id
  • projects — owner_id, name, thread_id (каждый проект живёт в своём треде канала)
  • files — filename, current_version, флаг modified (файл изменился и готов к коммиту)
  • file_versions — мясо. Каждая версия файла с полным содержимым. Привязана к file_id и опционально к commit_id
  • commits — сообщение, время, ссылка на проект
  • commit_files — связка коммитов с версиями файлов (many-to-many, чтобы поддержать ветки)

Почему так: я хотел иметь возможность откатиться к любой версии любого файла. Да, база распухнет, но текстовые файлы — это не гигабайты видео. Плюс наличие file_versions и commit_files позволяет делать diff между версиями и смотреть историю изменений.

В коде вместо голых кортежей из SQL — датаклассы:

			python@dataclass
class Project:
    id: int
    name: str
    owner_id: int
    thread_id: Optional[int] = None
    created_at: Optional[datetime] = None
		

Маркдауновый ад

Казалось бы: взял код, обернул в тройные апострофы, кинул в Telegram. Telegram сам подсветит синтаксис, если указать язык. Красота. В теории.

На практике Telegram использует свой диалект Markdown, где куча служебных символов: _ * [ ] ( ) ~ > # + - = | { } . !

Попытка 1: заэкранировать всё подряд. Результат: код превращается в кашу. Вместо def __init__- получается def |_|_init|_|_ — уже не запустишь, и в канале выглядит как говно.

Попытка 2: не экранировать вообще. Telegram шлёт на**й с ошибкой «can't parse entities».

Попытка 3: экранировать только то, что реально ломает разметку. Выяснилось, что порядок важен. Сначала экранируем точки и подчеркивания, потом обратную косую черту. Но и это не панацея — последовательности типа \*

после экранирования превращаются в \\*, и Telegram снова недоволен.

Попытка 4: разбивать на части. Для больших файлов делаю превью (первые 50 строк), экранирую их, отправляю как код, а полную версию — файлом. И тут начался ад: Telegram находил ошибки в тех частях кода, которых в превью вообще не было. Оказывается, он всё равно парсил полный код, даже если отправлялась только его часть.

Попытка 5 (финал): забил на Markdown и перешёл на HTML. Telegram умеет его принимать. Да, он не такой красивый, но зато предсказуемый:

			pythondef safe_html(text: str) -> str:
    return (text.replace('&', '&')
            .replace('<', '<')
            .replace('>', '>'))

def format_code_html(filename: str, content: str) -> str:
    lang = get_language_from_filename(filename)
    content = safe_html(content)
    return f'<pre><code class="language-{lang}">{content}</code></pre>'
		

Никаких точек, подчеркиваний, обратных слешей. Просто экранируем три символа — и код летит как надо.

Security by design

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

			pythonif project.owner_id != user_id:
    await message.answer("❌ Это не твой проект")
    return
		

Добавил в /commit. Потом решил с другого аккаунта потестировать команды на чужих файлах. И тут бот на каждую команду стал выдавать «файл не найден» или «проект не найден». И я понял: безопасность уже работает. С самого начала. Из коробки. Без единой строчки кода.

Как так вышло? В таблице projects с самого начала было поле owner_id. При создании проекта я писал туда telegram_id владельца. Все запросы к БД фильтруются по этому полю:

			def get_user_projects(self, telegram_id):
    return self.execute(
        "SELECT * FROM projects WHERE owner_id = ?", 
        (telegram_id,)
    )
		

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

Команды: от семи до двух десятков

Изначально казалось, что команд будет немного. Но...

Жизнь рассудила иначе.

  • База: /start, /init, /use, /list, /ls, /commit, /log, /status
  • Удаление: /rm, /rmproject + подтверждение
  • Игнор: /ignore, /ignored, /unignore
  • Ветки: /branch, /branches, /checkout
  • Диффы и просмотр: /diff, /cat

Итого — уже под два десятка. И это не предел.

Простота &gt; абстракции

В моём коде нет абстрактных базовых классов. Совсем. Потому что они нужны только когда у тебя есть минимум две разные реализации одного и того же. В GitGram всё проще: один способ работать с БД, один способ шифровать, один способ парсить .gitignore.

Если завтра появится вторая реализация — тогда и буду делать интерфейс. А пока это просто оверхед.

В GitGram:

  • Хочешь понять, как работает add_file — идёшь в database.py и читаешь 10 строк кода.
  • Хочешь увидеть обработчик /commit — открываешь bot.py и смотришь.

Никаких AbstractMinerShieldEventProcessor, BaseGitGramManager, InterfaceProviderFactory.

Код должен быть тупым. Чем тупее — тем проще его читать и отлаживать.

Что дальше

В планах:

  • Докрутить коллаборацию (несколько человек над одним проектом)
  • Приватные репозитории
  • Кодспейс прямо в боте (да да знаю я сошёл с ума и бла бла бла..)

Итог

GitGram принимает файлы, режет их на куски если надо, постит в канал с подсветкой. Коммиты ходят, ветки переключаются, диффы показываются. Всё это в тредах, каждый проект отдельно.

На практике GitGram ни к чему. Но сама задумка — Git в Telegram — это же так прикольно. Просто посмотреть, можно ли такое вообще запилить.

Если хочешь поучаствовать

  • GitGram
  • Чат для хардкорных: @sandbox_hardcore — вся сырая разработка, факапы и обсуждения (без цензуры)

Подписывайся на мой TГ-канал — там я публикую все свои эксперименты, код и приглашаю к обсуждению. Только факты, мат и никакой политоты.

Схожие новости

#Наименование новостиТональностьИнформативностьДата публикации
1Вайб-кодинг в терминале: настраиваем OpenCode с Claude, GPT и Gemini0530-06-2026
2Как объединить инфраструктуру 35 продуктов в единую платформу данных0726-06-2026
3Почему классический CI/CD не справляется с LLM (и какие release gates мы построили, чтобы это исправить)0704-07-2026
4GitLab представила концепцию agentic infrastructure0525-06-2026
5Бесплатный WAF инструмент кибербезопасности, который я использую5801-07-2026
6Куда бежать с github?-2503-07-2026
7Как ограничить расходы на OpenAI API, чтобы ИИ-агенты не сожгли бюджет0804-07-2026
8Comment récupérer des messages Telegram supprimés 20240517-01-2026
9Pourquoi Telegram ne m’envoie-t-il pas de code ?0512-02-2026
10Кнопка «наверх» в Django: почему в проде это уже не три строки JavaScript0701-07-2026

Классификация: Мнения. Схожих патентов: 0. Схожих новостей: 10. Тональность: 5. Информативность: 7. Источник: tproger.ru.