Skip to content

Keep channel attribution on forwarded messages - #182

Merged
chigwell merged 2 commits into
chigwell:mainfrom
aazimin:feat/forward-attribution
Aug 5, 2026
Merged

Keep channel attribution on forwarded messages#182
chigwell merged 2 commits into
chigwell:mainfrom
aazimin:feat/forward-attribution

Conversation

@aazimin

@aazimin aazimin commented Aug 5, 2026

Copy link
Copy Markdown

Problem

message_to_dict reads only two fields off fwd_from:

fdate = getattr(fwd, "date", None)
fname = getattr(fwd, "from_name", None)

Telegram populates from_name only when the original author hides their profile. For an ordinary forward from a channel the origin lives in fwd_from.from_id, which is never read — so the MCP output is just:

"forwarded": {"date": "2026-07-15T12:01:02+00:00"}

Everything the client displays as "Forwarded from …" is lost, and that is the common case rather than an edge one. An agent consuming this cannot tell which channel a forwarded post came from, or link back to it.

Change

Also read Telethon's msg.forward wrapper. It resolves the forward peer from entities already present in the same response, so this adds no extra API call and stays synchronous.

New keys inside forwarded, each omitted when absent, matching the file's existing style:

Key From
from_chat channel/group title, or the user's full name
from_username public @username of the origin
from_chat_id numeric peer id
from_user sender name, for user-to-user forwards
channel_post fwd_from.channel_post
post_author fwd_from.post_author
post_link built permalink, see below

post_link is https://t.me/<username>/<post> for a public channel and the members-only https://t.me/c/<internal_id>/<post> form otherwise.

Same message as above, after the change:

"forwarded": {
  "date": "2026-07-15T12:01:02+00:00",
  "from_chat": "Полезный Парфун",
  "from_username": "ParfunA",
  "from_chat_id": -1001626974925,
  "channel_post": 6279,
  "post_link": "https://t.me/ParfunA/6279"
}

from_name is still emitted exactly as before, so hidden-profile forwards keep working unchanged. Names go through sanitize_name, consistent with the rest of the function.

Tests

tests/test_forward_attribution.py covers public-channel, private-channel, user-to-user, hidden-profile and non-forward messages. Full suite: 118 passed. black and the pre-commit flake8 selection are clean.

Verified against

A real forward fetched through get_history — the post_link above resolves to the original post.

🤖 Generated with Claude Code

message_to_dict read only fwd_from.date and fwd_from.from_name. Telegram
populates from_name solely when the original author hides their profile,
so an ordinary channel forward — where the origin sits in fwd_from.from_id
— lost everything the client shows as "Forwarded from ...".

Also read Telethon's msg.forward wrapper, which resolves that peer from
entities already present in the same response, so this costs no extra API
call. Adds from_chat, from_username, from_chat_id, from_user, channel_post
and post_author, plus a post_link built from them: t.me/<username>/<post>
for a public channel, the members-only t.me/c/<id>/<post> form otherwise.

from_name is still emitted, so hidden-profile forwards are unaffected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment thread telegram_mcp/tools/messages.py Outdated
# only resolves for members.
if post_id is not None:
if finfo.get("from_username"):
finfo["post_link"] = f"https://t.me/{finfo['from_username']}/{post_id}"

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct me if I'm wrong, but t.me no longer works.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked before changing anything — t.me is up. It serves 200 right now from two different networks, and whois reports the domain ACTIVE (no serverHold):

$ curl -sI https://t.me/ParfunA/6279   → HTTP/2 200
$ whois t.me | grep -i status          → status: ACTIVE

The outage behind your concern was real though: on 2026-07-13 the .me registry put t.me on serverHold over an OFAC listing — a sanctioned entity had used a Telegram channel as a contact address — and every t.me link on earth broke for roughly a day. It was restored on 2026-07-14. During the outage telegram.me kept resolving.

For what it's worth, the repo already emits t.me links elsewhere — tools/profile.py:266 builds f"https://t.me/{ch_username}", and get_message_link is documented as exporting a t.me/... link (via ExportMessageLinkRequest, where Telegram itself formats the result).

Still, your instinct holds: one registry decision can take every permalink down at once, and hardcoding the domain in a new place makes that worse. So I've pushed a follow-up that stops hardcoding it:

LINK_DOMAIN = os.getenv("TELEGRAM_LINK_DOMAIN", "t.me")

Default is unchanged, and anyone who needs telegram.me (or whatever comes next) can switch without a code change. Covered by a test that overrides the domain.

Happy to drop post_link entirely if you'd rather not have a built URL in the payload at all — the raw parts (from_username, from_chat_id, channel_post) are all there for a caller to assemble. Just say the word.

Addresses review feedback that t.me may not be reliable.

t.me resolves and serves 200 today, and whois reports the domain ACTIVE;
the outage behind that concern was 2026-07-13, when the .me registry put
it on serverHold over an OFAC listing and every t.me link broke for about
a day. It was restored on 2026-07-14, but the incident is a fair warning
that one registry decision can take every permalink down at once.

So the domain is no longer hardcoded: LINK_DOMAIN defaults to t.me and can
be overridden with TELEGRAM_LINK_DOMAIN — telegram.me kept resolving
throughout that outage and works as a drop-in.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@chigwell
chigwell merged commit cc61ccd into chigwell:main Aug 5, 2026
4 checks passed
KiaroSama pushed a commit to KiaroSama/telegram-mcp that referenced this pull request Aug 25, 2026
Keep channel attribution on forwarded messages
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants