-
Notifications
You must be signed in to change notification settings - Fork 245
feat: add group filter option #639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request adds a new --group-filter (-g) option to filter exported group conversations by their display names. The feature works independently or in conjunction with the existing --conversation-filter option, using set intersection when both are specified.
Key changes:
- New CLI option
--group-filterfor filtering group chats by name - Runtime logic to resolve group names to chat IDs and intersect with existing filters
- Comprehensive test coverage for various filter scenarios
- Documentation updates explaining the intersection behavior
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| imessage-exporter/src/main.rs | Adds call to resolve_filtered_groups() after handle resolution |
| imessage-exporter/src/app/options.rs | Defines new CLI option, integrates into validation logic, updates test data |
| imessage-exporter/src/app/runtime.rs | Implements group filter resolution logic, validation, and comprehensive tests |
| imessage-exporter/src/exporters/txt.rs | Fixes hardcoded home directory path in test to use environment variable |
| imessage-exporter/src/exporters/html.rs | Fixes hardcoded home directory path in test to use environment variable |
| imessage-exporter/README.md | Documents new option and intersection behavior with conversation filter |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| None => { | ||
| self.options | ||
| .query_context | ||
| .set_selected_chat_ids(matched_chat_ids.clone()); |
Copilot
AI
Jan 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The .clone() call on matched_chat_ids is necessary here since the variable is moved into set_selected_chat_ids. However, you could avoid this clone by restructuring the logic. Instead of matching on a reference and then calling the method separately, you could consume matched_chat_ids directly in both branches. For example, use if let Some(existing) = self.options.query_context.selected_chat_ids.take() and then set the result in both branches.
| #[test] | ||
| fn can_build_option_group_filter() { | ||
| let command = get_command(); | ||
| let args = command.get_matches_from(["imessage-exporter", "-g", "Family Chat", "-f", "txt"]); | ||
|
|
||
| let actual = Options::from_args(&args).unwrap(); | ||
| assert_eq!(actual.group_filter, Some(String::from("Family Chat"))); | ||
| } |
Copilot
AI
Jan 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test only validates the group_filter field. Consider testing the complete Options struct (like other tests in this module) to ensure all fields are set correctly when using the group filter option.
| "Sticker from Sample Contact: {sticker_path} (App: Free People) from Sample Contact", | ||
| sticker_path = sticker_path |
Copilot
AI
Jan 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sticker_path named parameter in the format! macro is redundant. The variable is already captured by name in the format string. Remove the explicit sticker_path = sticker_path parameter.
| "Sticker from Sample Contact: {sticker_path} (App: Free People) from Sample Contact", | |
| sticker_path = sticker_path | |
| "Sticker from Sample Contact: {sticker_path} (App: Free People) from Sample Contact" |
| "<img src=\"{sticker_path}\" loading=\"lazy\">\n<div class=\"sticker_name\">App: Free People</div> <div class=\"sticker_tapback\"> by Sample Contact</div>", | ||
| sticker_path = sticker_path |
Copilot
AI
Jan 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sticker_path named parameter in the format! macro is redundant. The variable is already captured by name in the format string. Remove the explicit sticker_path = sticker_path parameter.
| "<img src=\"{sticker_path}\" loading=\"lazy\">\n<div class=\"sticker_name\">App: Free People</div> <div class=\"sticker_tapback\"> by Sample Contact</div>", | |
| sticker_path = sticker_path | |
| "<img src=\"{sticker_path}\" loading=\"lazy\">\n<div class=\"sticker_name\">App: Free People</div> <div class=\"sticker_tapback\"> by Sample Contact</div>" |
| let parsed_group_filter = group_filter | ||
| .split(',') | ||
| .map(str::trim) | ||
| .filter(|token| !token.is_empty()) | ||
| .collect::<Vec<&str>>(); |
Copilot
AI
Jan 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parsing logic in resolve_filtered_groups includes .map(str::trim) and .filter(|token| !token.is_empty()), but the similar logic in resolve_filtered_handles (line 288) does not. Consider applying the same trimming and empty-token filtering to resolve_filtered_handles for consistency, or document why the difference is intentional.
|
Ignore copilot for now; I haven not yet decided if I want to include this feature yet. |
|
@ReagentX any update on this yet? |
|
Not yet |
This is based on the discussion here: #638