Some checks failed
Published content check / validate (push) Failing after 17s
git.zapret.moe в России заблокирован по имени, как и wiki.zapret.moe. Ссылки на Forgejo во всех заметках, футерах, wizard.html и главной заменены на git2.zapret.moe (включая закодированные адреса значков shields.io). Какое имя рабочее, теперь решают реестры хоста /etc/zapret-*-domains.conf через zapret-site-names: pre-commit хук vault отклоняет добавленные строки с заблокированным именем, сборка Quartz сама переводит ссылки и baseUrl на рабочие имена. Правило в AGENTS.md переписано под этот механизм. scripts/wiki-stats.py: переходы с любых имён вики и git (wikiN, gitN) больше не считаются внешними сайтами. content-check: проверка зеркал сторонних проектов узнаёт любое имя git. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
267 lines
32 KiB
Markdown
267 lines
32 KiB
Markdown
---
|
||
date: 2026-06-16
|
||
tags:
|
||
- zapret
|
||
- zapret2
|
||
- gui
|
||
- preset
|
||
- profile
|
||
- troubleshooting
|
||
aliases:
|
||
- Профиль
|
||
- Профиль пресета
|
||
- Профиль Zapret 2
|
||
- Что такое профиль
|
||
- Профили пресета
|
||
- Мультипрофиль
|
||
- Чем профиль отличается от пресета
|
||
- Перепробовал все пресеты
|
||
description: "Что такое профиль в Zapret 2: чем отличается от пресета, какие фильтры выбирают трафик, что делает стратегия, почему важен порядок и где профили в GUI."
|
||
---
|
||
|
||
> [!mirror] Резервное зеркало
|
||
> Актуальная версия этой страницы — на основной вики: [wiki2.zapret.moe/Zapret2/profile](https://wiki2.zapret.moe/Zapret2/profile)
|
||
|
||
# 🧩 Что такое профиль в Zapret 2 и чем он отличается от пресета
|
||
|
||
> [!info] О чём заметка
|
||
> Что такое профиль в [[Zapret2|Zapret 2]], из каких частей он состоит и почему настраивать обход нужно именно в профилях, а не перебором целых [[preset|пресетов]]. Подробные справочники по отдельным флагам — [[filter]], [[payload]], [[out-range]], [[desync]], [[blob]]; как создать свой профиль в GUI — [[add-profile]].
|
||
|
||
> [!tip] TL;DR
|
||
> - **Пресет** — весь файл настроек: общая шапка и десятки профилей подряд.
|
||
> - **Профиль** — один блок внутри пресета, отделённый строкой `--new`. Он отвечает за свою часть трафика: интерфейс YouTube, голос Discord, Telegram, сеть Cloudflare.
|
||
> - Профиль состоит из **фильтров**, которые решают, какие соединения ему достаются, и **стратегии обхода**, которая решает, что с ними делать.
|
||
> - Каждое соединение достаётся **одному** профилю — первому сверху, чьи фильтры совпали. Поэтому порядок профилей важен.
|
||
> - Если не работает один сайт, меняют стратегию в его профиле, а не весь пресет.
|
||
|
||
## Что делает Zapret 2 и где здесь профиль
|
||
|
||
Когда вы открываете сайт по HTTPS, браузер в первом же сообщении соединения (TLS ClientHello) открытым текстом называет имя сайта. Это поле называется SNI (Server Name Indication). Оборудование провайдера — DPI (Deep Packet Inspection, глубокий анализ трафика), в России это ТСПУ, — читает его и рвёт или замедляет соединения с запрещёнными именами.
|
||
|
||
Zapret 2 перехватывает исходящие пакеты до того, как они уйдут в сеть, и меняет их так, чтобы DPI не смог прочитать имя сайта, а настоящий сервер получил данные без искажений. Такие приёмы называют стратегиями обхода, или дурением (desync); каталог стратегий — в [[desync]].
|
||
|
||
Разные сайты блокируют по-разному, и одна стратегия на весь трафик не годится: то, что пробивает YouTube, может сломать банк или игру. Поэтому настройки делят на части. Каждая часть говорит: «вот эти соединения обрабатывай вот так». Такая часть и есть профиль, а файл, в котором профили лежат по порядку вместе с общими настройками, — пресет.
|
||
|
||
## Пресет и профиль — в чём разница
|
||
|
||
| Понятие | Что это | Пример |
|
||
|---|---|---|
|
||
| **Пресет** ([[preset]]) | Один `.txt`-файл: общая шапка и набор профилей | `Default v1 (game filter)` |
|
||
| **Профиль** | Один блок внутри пресета, до следующего `--new` | `youtube.com (интерфейс)`, `Telegram`, `Cloudflare UDP` |
|
||
|
||
В файле пресет выглядит как длинный список флагов, где профили идут друг за другом и разделяются строкой `--new`:
|
||
|
||
```
|
||
( шапка пресета: --lua-init, --blob, --wf-tcp-out … )
|
||
|
||
--name=youtube.com (интерфейс) ← профиль конкретного сайта
|
||
--filter-tcp=80,443
|
||
--hostlist=lists/youtube.txt
|
||
--lua-desync=multisplit:...
|
||
--new ← разделитель
|
||
--name=Исключения айпи (RU сайты) ← профиль-исключение
|
||
--filter-tcp=80,443-65535
|
||
--ipset=lists/ipset-ru.txt
|
||
--lua-desync=pass
|
||
--new ← разделитель
|
||
--name=Cloudflare TCP ← широкий профиль по сети CDN
|
||
--filter-tcp=80,443-65535
|
||
--ipset=lists/ipset-cloudflare.txt
|
||
--lua-desync=hostfakesplit:...
|
||
...
|
||
```
|
||
|
||
Пресет сам ничего не решает: это контейнер, который хранит профили по порядку. Успех обхода конкретного сайта зависит от того, какой профиль забрал его соединения и какая стратегия в этом профиле стоит.
|
||
|
||
## Анатомия профиля
|
||
|
||
![[wiki-anim-z2-profile.svg|Анимация: флаги профиля делятся на три роли — какие соединения достаются, к каким пакетам применять, что делать]]
|
||
|
||
Профиль — это несколько флагов до следующего `--new`. Разберём реальный блок из пресета `Default v1 (game filter)` (версия пресета 2.40, август 2026):
|
||
|
||
```
|
||
--name=youtube.com (интерфейс)
|
||
--filter-tcp=80,443
|
||
--hostlist=lists/youtube.txt
|
||
--out-range=-d8
|
||
--payload=tls_client_hello
|
||
--lua-desync=multisplit:pos=1,host+2,sld+2,sld+5,sniext+1,sniext+2,endhost-2:seqovl=1
|
||
```
|
||
|
||
Читается так: «профиль `youtube.com (интерфейс)` забирает TCP-соединения на порты 80 и 443 к доменам из `youtube.txt`. В этих соединениях на TLS ClientHello среди первых восьми пакетов с данными выполняется стратегия [[multisplit]]: сообщение режется на части в нескольких местах вокруг имени сайта, а к первой части добавляется перекрытие в 1 байт (seqovl)».
|
||
|
||
Флаги здесь делятся на три роли, и путать их нельзя: от роли зависит, что происходит, когда условие не выполнено.
|
||
|
||
### Фильтры профиля: какие соединения ему достаются
|
||
|
||
| Флаг | Что проверяет | В примере | Подробнее |
|
||
|---|---|---|---|
|
||
| `--filter-tcp` / `--filter-udp` | Транспорт и порты. Если задан только TCP, UDP-трафик этому профилю не достаётся, и наоборот | TCP `80,443` | [[filter]] |
|
||
| `--filter-l7` | Протокол приложения: `http`, `tls`, `quic`, `wireguard`, `discord`, `stun`, `mtproto` и другие | не задан | [[filter]] |
|
||
| `--hostlist` / `--hostlist-exclude` | Имя сайта (из SNI или заголовка Host) по списку доменов; поддомены учитываются автоматически | домены из `lists/youtube.txt` | [[Zapret/hostlist\|hostlist]] |
|
||
| `--ipset` / `--ipset-exclude` | IP-адрес сервера по списку адресов и подсетей | не задан | [[Zapret/ipset\|ipset]] |
|
||
|
||
Все фильтры профиля действуют вместе: соединение достаётся профилю, только если совпали и порт, и протокол, и списки. Если не совпало хоть что-то, движок проверяет следующий профиль. Как именно идёт этот перебор — ниже, в разделе про порядок.
|
||
|
||
### Внутрипрофильные условия: к каким пакетам применять стратегию
|
||
|
||
| Флаг | Что ограничивает | В примере | Подробнее |
|
||
|---|---|---|---|
|
||
| `--out-range` / `--in-range` | На каких по счёту пакетах соединения работать. `d` — пакеты с данными, `n` — все пакеты; `-d8` — с начала по восьмой пакет с данными | `-d8` | [[out-range]] |
|
||
| `--payload` | На какой тип содержимого реагировать: `tls_client_hello`, `http_req`, `quic_initial`, `all`. На уровне профиля по умолчанию `all`; многие стратегии дополнительно сами берут только известные типы (`known`) | `tls_client_hello` | [[payload]] |
|
||
|
||
Эти флаги **не участвуют в выборе профиля**. Официальная документация zapret2 называет их внутрипрофильными фильтрами: они действуют на идущие после них вызовы `--lua-desync` внутри уже выбранного профиля. Если пакет не подошёл под `--payload` или `--out-range`, соединение не уходит к другому профилю: оно остаётся в этом, просто стратегия к этому пакету не применяется. Поэтому их место в профиле важно — они должны стоять перед `--lua-desync`, к которому относятся, см. [[последовательность аргументов]].
|
||
|
||
### Стратегия: что делать с пакетами
|
||
|
||
`--lua-desync` вызывает функцию обхода: [[fake]], [[multisplit]], [[multidisorder]], [[hostfakesplit]] и другие. Строк `--lua-desync` может быть несколько, они выполняются по очереди для одного и того же пакета. Такие связки встречаются во многих профилях стоковых пресетов, например:
|
||
|
||
```
|
||
--lua-desync=send:repeats=2
|
||
--lua-desync=syndata:blob=stun_pat
|
||
--lua-desync=tls_multisplit_sni:seqovl=652:seqovl_pattern=tls_google
|
||
```
|
||
|
||
Это одна стратегия одного профиля. Смешать стратегии двух разных профилей на одном соединении нельзя — подробнее в [[profile-independence]]. Что делает каждая функция — в [[desync]].
|
||
|
||
`--name` — просто подпись профиля в GUI и в логах, на трафик она не влияет.
|
||
|
||
### Профиль-исключение: pass
|
||
|
||
Стратегия `--lua-desync=pass` ничего не делает: профиль забирает соединение и отправляет его как есть. Так оформляют исключения. В стоковых пресетах есть профили «Исключения айпи (RU сайты)» и «Исключения домены (RU сайты)» (до обновления пресетов в августе 2026 был один общий профиль по IP): они намеренно не трогают российские сайты, чтобы обход не сломал им соединение. В `Default v1 (game filter)` они стоят после профилей конкретных сайтов вроде YouTube, но выше широких профилей по сетям (Cloudflare, Hetzner, Amazon и другие). Поэтому соединения российских сайтов забирают исключения, и до широких профилей с обходом эти соединения не доходят. Чем `pass`-профиль отличается от exclude-списков и какие у исключений подводные камни — в [[exclusions]].
|
||
|
||
## Полный профиль целиком: разбор по строкам
|
||
|
||
Короткий пример выше показывает по одной строке каждого вида. Ниже — профиль «GitHub» целиком, как он записан в том же пресете `Default v1 (game filter)` (версия 2.40, август 2026). В нём есть всё сразу: подпись, фильтры выбора, внутрипрофильные условия и цепочка из трёх стратегий.
|
||
|
||
```
|
||
--name=GitHub
|
||
--filter-tcp=443
|
||
--hostlist=lists/github.txt
|
||
--out-range=-d8
|
||
--payload=tls_client_hello
|
||
--lua-desync=send:repeats=2
|
||
--lua-desync=syndata:blob=stun_pat
|
||
--lua-desync=tls_multisplit_sni:seqovl=652:seqovl_pattern=stun_pat
|
||
```
|
||
|
||
| Строка | Роль | Что делает |
|
||
|---|---|---|
|
||
| `--name=GitHub` | подпись | Имя профиля в GUI и в логах. На трафик не влияет |
|
||
| `--filter-tcp=443` | фильтр выбора | Только TCP на порт 443 (HTTPS). Соединения по QUIC (UDP 443) к GitHub этот профиль не получает |
|
||
| `--hostlist=lists/github.txt` | фильтр выбора | Только домены GitHub из списка и их поддомены. Профиль выбирается, когда движок узнаёт имя сайта из ClientHello |
|
||
| `--out-range=-d8` | внутрипрофильное условие | Стратегии ниже работают с начала соединения по восьмой пакет с данными |
|
||
| `--payload=tls_client_hello` | внутрипрофильное условие | …и только на TLS ClientHello — сообщении, в котором браузер называет имя сайта |
|
||
| `--lua-desync=send:repeats=2` | стратегия | Отправляет две дополнительные копии текущего пакета (ClientHello) без изменений; сам пакет не блокирует |
|
||
| `--lua-desync=syndata:blob=stun_pat` | стратегия | Задумана как подмешивание данных в первый пакет соединения (SYN). В этом профиле не срабатывает — см. ниже |
|
||
| `--lua-desync=tls_multisplit_sni:…` | стратегия | Функция из библиотеки GUI (`custom_funcs.lua`): режет ClientHello примерно в 17 местах вокруг имени сайта и отправляет части в обратном порядке; `seqovl=652` просит добавить перекрытие в 652 байта с шаблоном `stun_pat` |
|
||
|
||
Как это выглядит для одного соединения с `github.com`:
|
||
|
||
1. Браузер отправляет SYN — первый пакет установки соединения. Имени сайта в нём нет, поэтому профиль «GitHub» с хостлистом в выборе ещё не участвует, и SYN достаётся другому подходящему профилю или проходит без обработки.
|
||
2. Браузер отправляет TLS ClientHello с именем `github.com`. Движок узнаёт имя, заново перебирает профили сверху вниз и отдаёт соединение профилю «GitHub» (если выше нет другого профиля, который тоже подходит).
|
||
3. На этом ClientHello по очереди выполняются стратегии профиля: `send` отправляет две копии пакета, `syndata` пропускает его (это не SYN), `tls_multisplit_sni` режет его на части и отправляет их в обратном порядке, а оригинал блокирует.
|
||
4. Дальнейшие пакеты соединения идут без изменений: стратегиям нужен только ClientHello.
|
||
|
||
> [!warning] Две строки этого профиля на деле не работают так, как записаны
|
||
> Проверено на стенде (сентябрь 2026, `nfqws2` на Linux, та же Lua-библиотека, что в GUI):
|
||
> - **`syndata` не срабатывает.** Ей нужен SYN, а SYN до этого профиля не доходит: пока имя сайта неизвестно, профиль с хостлистом не выбирается. Вдобавок `--payload=tls_client_hello` отсекает SYN, потому что в нём нет данных. На стенде SYN уходил пустым и в профиле с хостлистом, и в профиле с одним только `--payload=tls_client_hello`; данные в SYN появлялись только в профиле без хостлиста и без фильтра payload. Чтобы `syndata` работала, её ставят в профиль, который выбирается с первого пакета (по портам или по [[Zapret/ipset|ipset]]), и не ограничивают `--payload` перед ней. Подробнее — в [[syndata]] и [[profile-independence#Оговорка: профиль может смениться посреди соединения|оговорке о смене профиля]].
|
||
> - **`seqovl=652` часто отменяется.** `tls_multisplit_sni` отбрасывает перекрытие, если оно не меньше позиции первого разреза, а первый разрез стоит у начала имени сайта. На стенде имя начиналось со 151-го байта ClientHello, и в логе было `seqovl cancelled, too large` — части ушли без перекрытия. Chrome перемешивает порядок расширений ClientHello, поэтому у него имя может оказаться и дальше 652-го байта, и тогда перекрытие сработает; значит, на части соединений оно будет, на части нет.
|
||
>
|
||
> Профиль при этом рабочий: основную работу делает разрез `tls_multisplit_sni`. Просто две строки из него ничего не добавляют, и при подборе своей стратегии на них не стоит рассчитывать.
|
||
|
||
Проще говоря: читая профиль, проверяйте не только, что написано в каждой строке, но и дойдёт ли до неё нужный пакет. Фильтры выбора решают, попадёт ли соединение в профиль и с какого момента, `--payload` и `--out-range` — какие пакеты увидят стратегии, а сами стратегии срабатывают только на тех пакетах, для которых написаны.
|
||
|
||
## Порядок профилей важен
|
||
|
||
![[wiki-anim-z2-profilepick.svg|Анимация: четыре соединения ищут свой профиль сверху вниз; первый совпавший побеждает, если не подошёл ни один — скрытый no_action]]
|
||
|
||
Для каждого нового соединения движок перебирает профили сверху вниз и отдаёт соединение первому, у которого совпали все фильтры. Остальные профили это соединение не обрабатывают. Сравнение идёт не для каждого пакета: выбранный профиль запоминается для соединения и пересматривается, только когда становятся известны протокол или имя сайта. Подробно — в [[exclusions#Как движок выбирает профиль: три факта, без которых исключения не понять|разборе выбора профиля]].
|
||
|
||
Из этого три практических следствия:
|
||
|
||
- Исключения (`pass`) ставят выше широких профилей с обходом, иначе соединения российских сайтов заберёт широкий профиль.
|
||
- Узкий профиль конкретного сайта ставят выше широкого профиля (например, по всей сети Cloudflare или по всем портам), иначе широкий заберёт соединения сайта раньше.
|
||
- Если после включения нового профиля сломался другой сайт, скорее всего, новый профиль забирает чужие соединения. Как это найти и исправить — в [[profile-independence]].
|
||
|
||
В GUI порядок меняет кнопка «Порядок в пресете».
|
||
|
||
## Шапка пресета: общие настройки
|
||
|
||
Над профилями идёт общая часть, которая действует на весь пресет и к профилям не относится:
|
||
|
||
```
|
||
# Preset: Default v1 (game filter) ← метаданные для GUI: имя
|
||
# BuiltinVersion: 2.40 ← версия встроенного пресета
|
||
# IconColor: #a8c5ff ← цвет иконки
|
||
|
||
--lua-init=@lua/zapret-lib.lua ; подключение Lua-библиотек со стратегиями
|
||
--lua-init=@lua/zapret-antidpi.lua
|
||
--lua-init=@lua/custom_funcs.lua ; …и ещё несколько библиотек, в том числе функции самого GUI
|
||
--ctrack-disable=0 ; отслеживание соединений (conntrack) включено
|
||
--ipcache-hostname=0
|
||
--wf-tcp-out=80,443,1080,2053,2083,2087,2096,5050,8443,8080,45631 ; какой TCP-трафик перехватывать (WinDivert)
|
||
--wf-udp-out=443-65535
|
||
--wf-raw-part=@windivert.filter/windivert_part.discord_media.txt ; дополнительные фильтры WinDivert
|
||
--blob=tls_google:@bin/tls_clienthello_www_google_com.bin ; именованные заготовки пакетов
|
||
```
|
||
|
||
- `--lua-init` загружает библиотеки, в которых написаны функции обхода; без них `--lua-desync` в профилях вызывать нечего.
|
||
- `--blob` объявляет именованные заготовки данных, на которые стратегии ссылаются через `blob=имя` (подробнее — [[blob]]).
|
||
- `--wf-tcp-out` и `--wf-udp-out` — фильтры [[wf|WinDivert]]: какой трафик Windows вообще передаст программе. Это отбор до профилей: соединение, которое сюда не попало, не увидит ни один профиль.
|
||
|
||
## Где найти профили в GUI
|
||
|
||
Профили находятся в левом меню Zapret 2: «Настройки Запрета» → «Профили пресета». Откроется экран «Настройка пресета: …» со списком профилей активного пресета:
|
||
|
||
![[profili-preseta-gui.png]]
|
||
|
||
Профили сгруппированы по категориям (`YouTube 4`, `Discord 6`, `Мессенджеры 4`, `Соцсети 5` — число показывает, сколько профилей в группе). Сверху — быстрые фильтры `Все / TCP / UDP / Discord / Voice / Games` и поиск по имени.
|
||
|
||
В каждой строке:
|
||
|
||
- слева — иконка ресурса, имя профиля (`--name`), тип (`TCP`, `UDP`, `Voice`) и порты;
|
||
- метка `Hostlist` или `IPset` — по списку доменов или по списку адресов профиль отбирает соединения;
|
||
- справа — имя стратегии: `Split Position`, `alt v9`, `fake_2_n2`, `hostfakesplit_multi`, `MultiDisorder Complex`, `pass (ничего не делает)` и другие;
|
||
- статус `Не добавлен` (серая точка) — профиль есть в списке, но в активный пресет не включён.
|
||
|
||
Кнопка «Что это такое?» открывает встроенную подсказку, «Порядок в пресете» меняет очерёдность профилей, `+` добавляет новый профиль — пошагово в [[add-profile]].
|
||
|
||
## Профиль, категория и списки — кто есть кто
|
||
|
||
Эти три понятия легко спутать:
|
||
|
||
- **Хостлист** ([[Zapret/hostlist|hostlist]]) и **ipset** ([[Zapret/ipset|ipset]]) — файлы со списками доменов и IP-адресов.
|
||
- **Категория** — набор адресов конкретного ресурса (игры, сайта), собранный в такие файлы; как собрать — [[Zapret/Создание своей категории|Создание своей категории]].
|
||
- **Профиль** связывает всё вместе: берёт списки, добавляет фильтр портов и стратегию и говорит движку, что делать с этими соединениями.
|
||
|
||
## Почему настраивать нужно профили, а не перебирать пресеты
|
||
|
||
В готовом пресете у каждого профиля уже выбрана стратегия. Эти стратегии подбирали под чьих-то провайдеров, а DPI у разных провайдеров и в разных регионах настроен по-разному. Отсюда типичная картина: на одном пресете открывается YouTube, но не работает Discord, на другом — наоборот. Перебирать пресеты целиком в такой ситуации бесполезно: каждый раз меняются стратегии сразу во всех профилях, и починка одного сайта ломает другой.
|
||
|
||
Работает другой порядок. Возьмите пресет, на котором работает больше всего нужного, как основу. Найдите профиль, в который попадает неработающий сайт (как определить — в [[find-domain-owner]] и [[find-site-domains]]). И перебирайте стратегии только в нём, проверяя каждую новым соединением по [[verify-strategy]]. Фильтры и списки популярных ресурсов уже собраны и поддерживаются, их обычно трогать не нужно: от провайдера к провайдеру меняется в основном то, какая стратегия обманывает его DPI.
|
||
|
||
Режим, в котором стратегии меняют у отдельных профилей, в GUI исторически называется «Прямой запуск» (`Настройки → Прямой запуск`, подробнее — [[guide]] и [[Как пользоваться Zapret]]). Название сложилось давно и немного вводит в заблуждение: это не особый способ обхода, а просто возможность настраивать профили по одному.
|
||
|
||
> [!note] «Запрет перестал работать» — обычно симптом
|
||
> Если после обновления провайдером DPI сайт перестал открываться, чаще всего устарела стратегия одного-двух профилей, а сама программа исправна: остальные сайты ведь открываются. Как отличить это от настоящей неисправности (антивирус, конфликт с VPN, DNS) и что делать — в [[symptom-not-cause]] и [[zapret_not_working|Что делать, если Запрет не работает]].
|
||
|
||
## 📚 См. также
|
||
|
||
- [[preset]] — что такое пресет и как устроен его файл
|
||
- [[add-profile|Как добавить свой профиль]] — пошаговое создание профиля в GUI
|
||
- [[profile-independence|Одно соединение — один профиль]] — почему профили не смешиваются, но конкурируют за соединения
|
||
- [[exclusions|Исключения]] — профиль `pass` и exclude-списки
|
||
- [[filter]] — все фильтры профиля: порты, протокол, hostlist, ipset
|
||
- [[payload]] · [[out-range]] — внутрипрофильные условия для стратегий
|
||
- [[последовательность аргументов]] — какие флаги действуют на весь профиль, а какие только на следующие вызовы
|
||
- [[desync]] — стратегии обхода
|
||
- [[blob]] — заготовки данных для фейков
|
||
- [[wf]] — фильтры WinDivert в шапке пресета
|
||
- [[find-site-domains|Как найти домены сайта через F12]] · [[find-domain-owner|Как узнать CDN домена]] — как понять, в какой профиль попадает сайт
|
||
- [[changelog-21.0.0-dev-june-2026|Changelog 21.0.0]] — пользовательские профили в `settings.json`, редактор списков
|
||
|
||
---
|
||
|
||
> [!quote] 🤖 Эти статьи открыты — можно обучать на них ИИ
|
||
> При желании вы можете натренировать ИИ на наших статьях. Исходное форматирование доступно в Forgejo: [исходник этой заметки](https://git2.zapret.moe/zapretdiscordyoutube/todo/src/branch/main/Zapret2/profile.md) · [скачать весь репозиторий одним zip-архивом](https://git2.zapret.moe/zapretdiscordyoutube/todo/archive/main.zip).
|