Skip to content

Add media-file forwarding by date range, plus two correctness fixes - #3

Merged
klept0 merged 2 commits into
mainfrom
feature/media-forward
Jul 1, 2026
Merged

klept0 merged 2 commits into
mainfrom
feature/media-forward

Conversation

@klept0

@klept0 klept0 commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • New "Forward Media Files (Files/Images)" menu option: forwards only messages carrying a file/photo/video from a source chat's history, optionally filtered by keyword, over a selected date range (single month, multi-month, or custom range — e.g. "all of June") — in the order the files were originally posted.
  • Dry-run preview reports the exact total file count, not an estimate.
  • Resumable: re-running the exact same source/date-range/keyword combination — whether the previous run finished or was interrupted — picks up right after the last file already forwarded instead of duplicating it. Clear Forward Progress Cache forces a full re-scan.
  • Extracted the shared month/date-range/timezone/dry-run prompts out of ForwardDialog/KeywordForwardDialog into a new DateRangeDialog mixin, reused by the new MediaForwardDialog (removes ~150 lines of duplication).

Bugs found and fixed while building this

The "forward in posting order" and "don't re-forward on rerun" requirements exposed two real correctness issues in the existing historical-forward code:

  1. Global forward order wasn't actually chronological. The old pagination walked backward from the newest message in fixed-size chunks and only reversed order within each chunk — so across chunk boundaries the sequence was [newest-chunk ascending], [next-older-chunk ascending], ..., not one ascending sequence. Fixed by fetching chunks directly in ascending order via Telethon's reverse=True, which also lets the scan stop as soon as it passes the configured end date.
  2. Re-running a completed range restarted from scratch. _load_progress only honored resume state for an interrupted ("in_progress") run, not a finished one, so re-running the same date range after it completed would re-forward everything. Since Telegram message IDs are never reused, it now resumes from the last processed ID for both statuses.

Test plan

  • ruff check / ruff format --check — clean
  • mypy source/ — clean
  • pytest tests/ — 21/21 pass, including new regression tests for: ascending order + early-stop, dry-run file counting, full media-forward end-to-end (only files forwarded, correct order), resume-without-duplicating, and progress_key mode separation/backward compatibility
  • Verified menu wiring manually (MainMenu instantiates with the new dialog/handler, options render in the expected order)

klept0 and others added 2 commits June 30, 2026 23:36
New "Forward Media Files (Files/Images)" menu option
(source/dialog/MediaForwardDialog.py, Telegram.forward_media_files):
forwards only messages carrying a file/photo/video from a source
chat's history, optionally filtered by keyword, over a selected date
range (single month, multi-month, or custom range) — in the order the
files were originally posted. Dry-run reports the exact total file
count. Reuses the same resumable progress-tracking machinery as
"Past Forward Messages" via Forward.history_handler, scoped with a
distinct progress key so it doesn't collide with a plain history run
over the same range.

Extracted the shared month/date-range/timezone/dry-run prompts out of
ForwardDialog and KeywordForwardDialog into source/dialog/DateRangeDialog.py,
a mixin reused by all three forwarding dialogs — removes ~150 lines of
duplication.

While building this, found and fixed two real bugs in the existing
historical-forward code that the new "forward files in posting order"
requirement depended on being correct:

- Forward._forward_chat_history paged backward from the newest message
  in chunks and only reversed order *within* each chunk, so the global
  forward order across chunk boundaries was NOT actually chronological
  (e.g. [newest-chunk ascending], [next-older-chunk ascending], ...).
  Fixed by fetching chunks directly in ascending order via Telethon's
  reverse=True, which also lets the scan stop as soon as it passes the
  configured end date instead of always paging until a short chunk.
- Re-running a forward over a source/date-range/mode that had already
  completed silently restarted from message 0 and could re-forward
  everything — _load_progress only resumed "in_progress" runs, not
  "completed" ones. Since Telegram message IDs are never reused, it now
  resumes from the last processed ID for both statuses, so re-running
  the same range (e.g. re-running all of June) picks up after what's
  already been sent instead of duplicating it.

Added regression tests for both fixes plus the new media-forward flow
(dry-run count, ordering, resume-without-duplicating).

Co-Authored-By: Claude <noreply@anthropic.com>
- Header toggle switches between light/dark; defaults to the browser's
  prefers-color-scheme when no explicit choice is stored yet, and
  remembers the user's choice in localStorage. Colors moved to CSS
  custom properties (web/static/style.css) so both themes share one
  set of component styles instead of duplicating rules.
- "Forwarding Configurations" and "Available Chats" are now collapsible
  via <details>/<summary>, so a long chat list doesn't push other
  controls off-screen. Visibility is controlled by an explicit CSS rule
  on a wrapper div rather than relying solely on the browser's native
  details/summary hiding behavior, which turned out to be inconsistent
  in at least one embedded browser environment during testing.
- Fixed GET /api/forwards returning a 500 on a fresh install (before
  any forward configs exist) — it called ForwardConfig.read()
  unconditionally instead of checking the file exists first, unlike
  the sibling /api/status endpoint.
- Documented the X-API-Key requirement and CLI-auth-first flow in
  web/README.md, which had never covered either.

Verified live via a preview server: theme toggle, system-preference
defaults for both light and dark, native details/summary click-to-toggle,
and the /api/forwards fix.

Co-Authored-By: Claude <noreply@anthropic.com>
@klept0
klept0 merged commit 4c6db9d into main Jul 1, 2026
7 checks passed
@klept0
klept0 deleted the feature/media-forward branch July 1, 2026 03:52
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.

1 participant