Skip to content

feat: add /export command for saving articles as Markdown#7

Open
AminSS99 wants to merge 1 commit intomainfrom
feature/export-saved-articles-1546818674479366800
Open

feat: add /export command for saving articles as Markdown#7
AminSS99 wants to merge 1 commit intomainfrom
feature/export-saved-articles-1546818674479366800

Conversation

@AminSS99
Copy link
Owner

@AminSS99 AminSS99 commented Mar 6, 2026

I have successfully added the /export command!

Summary of changes:

  • Added an /export command handler in functions/telegram_bot.py.
  • It queries the user's saved articles, formats them into a neat .md file in-memory, and sends it directly back as a document.
  • Fully integrated with the localization system (functions/translations.py) for English and Russian.
  • Registered the new command in the bot's native menu and /help command text.
  • Followed guidelines to reuse existing components (like get_saved_articles) and ensure no new dependencies were required.

This small, robust enhancement should be very useful for users wanting to archive their saved links into tools like Notion or Obsidian!


PR created automatically by Jules for task 1546818674479366800 started by @AminSS99

…rkdown document.

This feature enables users to easily extract their curated articles from the bot without lock-in.
It queries the user's saved articles from storage, dynamically generates a Markdown file containing the links and metadata, and sends the file to the user via Telegram's `reply_document` functionality. It handles translations and adds the command to the bot's help menu and native commands list.

Co-authored-by: AminSS99 <139346033+AminSS99@users.noreply.github.com>
@google-labs-jules
Copy link
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new /export command, enabling users to effortlessly retrieve all their saved articles from the bot as a Markdown file. This enhancement significantly improves data portability, allowing users to archive their content for seamless integration with external applications like Notion or Obsidian, thereby enriching the overall user experience.

Highlights

  • New /export command: A new /export command handler was added to allow users to export their saved articles.
  • Markdown Export Functionality: The command queries user's saved articles, formats them into an in-memory Markdown file, and sends it as a document.
  • Localization Support: The new feature is fully integrated with the existing localization system, supporting both English and Russian.
  • Command Registration: The /export command has been registered in the bot's native menu and its /help command text.
Changelog
  • functions/telegram_bot.py
    • Added the export_command asynchronous function to handle the new /export command, including logic for fetching articles, formatting Markdown, and sending the file.
    • Registered the export_command with the bot's application to make it accessible.
    • Updated the bot's command list for both English and Russian to include the new /export command.
  • functions/translations.py
    • Added the /export command description to the English and Russian help texts.
    • Introduced new translation keys (export_loading, export_ready, export_empty) for the export feature in both English and Russian.
Activity
  • The pull request was automatically created by Jules for a task started by @AminSS99.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a useful /export command for saving articles to a Markdown file. The implementation is well-structured and integrates with existing systems like localization. I've identified a few areas for improvement to enhance robustness and maintainability:

  • A correctness issue where unescaped content could corrupt the exported Markdown file.
  • Opportunities to improve maintainability by centralizing duplicated code and translating hardcoded strings.
  • A suggestion to refine error handling to be more secure and user-friendly.

Overall, this is a solid feature addition that will be even better with these adjustments.

Comment on lines +742 to +746
md_lines.append(f"### {i}. {emoji} {title}")
md_lines.append(f"- **URL:** [Link]({url})" if url else "- **URL:** None")
if source:
md_lines.append(f"- **Source:** {source}")
md_lines.append(f"- **Category:** {category.capitalize()}")

Choose a reason for hiding this comment

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

high

The title and source variables are used to build a Markdown string without being escaped. If these strings contain characters with special meaning in Markdown (e.g., *, _, [), it could corrupt the formatting of the exported file. You should escape these variables to ensure the generated Markdown is always valid.

            from .security_utils import escape_markdown_v1
            md_lines.append(f"### {i}. {emoji} {escape_markdown_v1(title)}")
            md_lines.append(f"- **URL:** [Link]({url})" if url else "- **URL:** None")
            if source:
                md_lines.append(f"- **Source:** {escape_markdown_v1(source)}")
            md_lines.append(f"- **Category:** {category.capitalize()}")

Comment on lines +707 to +713
md_lines = [
f"# LensAI Saved Articles Export",
f"*Generated on {date_str}*",
"",
f"**Total articles:** {len(articles)}",
"---",
""

Choose a reason for hiding this comment

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

medium

The header of the generated Markdown file contains hardcoded English strings ("LensAI Saved Articles Export", "Generated on", "Total articles:"). Since the bot supports multiple languages, these strings should be translated using the t() function to provide a localized experience in the exported file as well. You would need to add corresponding keys to functions/translations.py.

Suggested change
md_lines = [
f"# LensAI Saved Articles Export",
f"*Generated on {date_str}*",
"",
f"**Total articles:** {len(articles)}",
"---",
""
md_lines = [
f"# {t('export_md_title', user_lang)}",
f"*{t('export_md_generated_on', user_lang)} {date_str}*",
"",
f"**{t('export_md_total', user_lang)}:** {len(articles)}",
"---",
""
]

Comment on lines +717 to +720
cat_emoji = {
'ai': '🤖', 'security': '🔒', 'crypto': '💰', 'startups': '🚀',
'hardware': '💻', 'software': '📱', 'tech': '🔧'
}

Choose a reason for hiding this comment

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

medium

This cat_emoji dictionary is also defined in the saved_command function. To improve maintainability and ensure consistency, you should extract this dictionary into a constant at the module level. This will make it easier to update the emojis in one place for both commands.

Comment on lines +768 to +769
print(f"Export error: {e}")
error_text = f"❌ Error: {str(e)[:100]}"

Choose a reason for hiding this comment

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

medium

Catching a broad Exception is acceptable for resilience, but exposing parts of the raw exception message to the user via str(e)[:100] can leak internal implementation details. It's better to log the full exception with user context for debugging and show a generic, translated error message to the user.

        print(f"Export error for user {update.effective_user.id}: {e}")
        error_text = "❌ An unexpected error occurred during export." # Consider using a translation key

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 15779bd371

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


try:
# Fetch a large number of saved articles (limit 1000)
articles = get_saved_articles(telegram_id, limit=1000)

Choose a reason for hiding this comment

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

P2 Badge Remove hard 1000-item cap from /export

The /export handler promises to export all saved articles, but this query silently truncates results to 1000 entries. In Firestore mode, save_article does not enforce a maximum saved-article count, so users with more than 1000 saved links will receive incomplete exports without any warning. Consider paginating through all documents (or explicitly communicating a limit) so exports are not silently partial.

Useful? React with 👍 / 👎.

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