## Purpose Чтение публичных Telegram-каналов через Telethon (MTProto) для сбора новостей с метриками популярности. Дополняется поддержкой «своих» источников (own: true) — контент пользователя. ## ADDED Requirements ### Requirement: Источники своего контента Краулер MUST распознавать источники с `own: true` в sources.yaml и для их постов проставлять `is_own=1`, `is_own_canonical=1`. Для таких источников медиа MUST скачиваться (контент принадлежит пользователю). #### Scenario: Краулинг своего канала - **WHEN** источник slug=dedinit имеет own: true - **THEN** посты сохраняются с is_own=1 и is_own_canonical=1; медиа скачивается; инкрементальный обход и дедуп работают как обычно #### Scenario: Чужой форвард в своём канале - **WHEN** пост в своём канале — форвард из чужого канала - **THEN** пост сохраняется с is_own=1 (это пост пользователя, он его переслал) и с fwd_from_channel_id/fwd_from_post_id; медиа не скачивается (содержимое чужое), атрибуция оригинала сохраняется в fwd-полях ### Requirement: Канонический экземпляр своего контента Если пост пользователя (is_own=1) позже встречается во внешнем канале (тот же sha256/url), внешний экземпляр MUST сохраняться как «упоминание» с is_own=0; каноническим остаётся первичный (is_own_canonical=1). #### Scenario: Свой пост запостили в чужой канал - **WHEN** краулер находит в чужом канале пост с текстом, совпадающим с is_own-постом - **THEN** создаётся запись is_own=0 (упоминание) без дублирования контента; веб видит оба экземпляра, но кандидатом на публикацию считается канонический (is_own_canonical)