Visitar URL original
Add user profile pictures and refresh user info on login by noamokman · Pull Request #12 · noamokman/gate-bot · GitHub
Skip to content

Add user profile pictures and refresh user info on login - #12

Merged
noamokman merged 3 commits into
mainfrom
add-user-profile-pictures
Aug 10, 2026
Merged

noamokman merged 3 commits into
mainfrom
add-user-profile-pictures

Conversation

@noamokman

@noamokman noamokman commented Aug 9, 2026 •

Copy link
Copy Markdown
Owner

What

  • Telegram profile photos: fetch each user's profile photo via getUserProfilePhotos + getFileLink and store it on pending requests and allowed-user records. The admin panel (pending + users views) and the navbar now render it when available.
  • Navbar avatar: shows the signed-in Google user's picture.
  • Refresh user info on login: updateUser (new, db.ts) merges fresh profile data (name, email, picture, ...) into existing records — filling in new data while preserving existing fields — for both web and telegram users. Refreshes on Google login (auth.ts) and on every /open (in parallel with opening the gate, so no added latency).

Why

Users added before profile picture support had no pictures, and Google's ID token picture claim is not guaranteed to be present — the refresh-on-login backfills old users.

Notes

  • getTelegramProfilePhoto fails gracefully (returns undefined if no photo or error).
  • Non-allowed users are never auto-added by the refresh; updateUser only touches existing records.

Summary by CodeRabbit

  • New Features

    • Telegram profile pictures are retrieved and preserved during access requests, account openings, and approvals.
    • Admin user listings now display available Telegram profile pictures.
    • Available profile pictures appear beside signed-in users’ names in the navigation header.
    • User identity details are updated when signing in with Google.
  • Bug Fixes

    • Existing user records now retain and merge updated profile information without overwriting unrelated data.

- Fetch Telegram profile photos via getUserProfilePhotos and store them on
  pending requests and user records; show them in the admin panel
- Display the signed-in Google user's picture in the navbar
- Refresh stored user info (name, email, picture, etc.) on login using a
  merge that fills new data while preserving existing fields, for both
  web and telegram users
@coderabbitai

coderabbitai Bot commented Aug 9, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@noamokman, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 36 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f2c84781-e5de-4149-8bc7-1793f26eaaf9

📥 Commits

Reviewing files that changed from the base of the PR and between 67628cc and 33b659c.

📒 Files selected for processing (1)
  • src/services/telegramPhoto.ts
📝 Walkthrough

Walkthrough

Telegram profile photos are retrieved from Telegram and stored with Telegram users and pending requests. User updates merge source-specific identity data. Admin listings and the navigation header expose available pictures.

Changes

Telegram profile picture flow

Layer / File(s) Summary
Photo data and Telegram lookup
src/types.ts, src/services/telegramPhoto.ts
Telegram user and pending request types accept optional pictures. The photo service retrieves a profile image and returns a base64 JPEG data URI or undefined.
Authorization and user persistence
src/commands/requestAccess.ts, src/commands/open.ts, src/actions/allow.ts, src/services/db.ts, src/web/routes/auth.ts
Access requests and account opening retrieve profile photos. updateUser merges matching source-specific fields and persists existing users. Google OAuth uses updateUser.
Admin and navigation display
src/web/routes/admin.ts, src/web/views/partials/header.ejs
Admin flows preserve and expose Telegram pictures. The navigation header renders an available user picture with avatar styling.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TelegramUser
  participant requestAccess
  participant TelegramAPI
  participant Admin
  participant allow
  participant Database

  TelegramUser->>requestAccess: Request access
  requestAccess->>TelegramAPI: Retrieve profile photo
  TelegramAPI-->>requestAccess: Photo data or unavailable result
  requestAccess->>Database: Store pending request with picture
  Admin->>allow: Allow pending request
  allow->>Database: Create Telegram user with picture
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main changes: adding user profile pictures and refreshing user information during login.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-user-profile-pictures

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/services/telegramPhoto.ts`:
- Around line 12-14: Replace the getFileLink flow in the Telegram photo handling
function so it never returns or persists link.href. Store only photo.file_id or
an internal opaque avatar key, and update avatar rendering to use an
authenticated same-origin proxy or controlled storage instead of Telegram URLs;
rotate the currently exposed bot token.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d0caf2b-a7cc-470d-bdf0-da2395141939

📥 Commits

Reviewing files that changed from the base of the PR and between 7f480aa and d6fc81b.

📒 Files selected for processing (9)
  • src/actions/allow.ts
  • src/commands/open.ts
  • src/commands/requestAccess.ts
  • src/services/db.ts
  • src/services/telegramPhoto.ts
  • src/types.ts
  • src/web/routes/admin.ts
  • src/web/routes/auth.ts
  • src/web/views/partials/header.ejs

Comment thread src/services/telegramPhoto.ts Resolved
getFileLink returns a URL containing the bot token (file/bot<token>/...)
and Telegram file URLs expire after ~1h. Download the smallest profile
photo server-side and persist it as a data:image/jpeg;base64,... value so
the token is never stored or rendered, and avatars never expire.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/services/telegramPhoto.ts (1)

6-6: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Limit the profile-photo lookup to one photo.

getUserProfilePhotos(userId) defaults to 100 profile photos, but this function reads only photos[0]. Pass 0, 1 to avoid transferring and allocating unused photo groups on each refresh. The Telegraf 4.16.3 method supports (userId, offset?, limit?). (core.telegram.org)

Proposed change
-    const { photos } = await telegram.getUserProfilePhotos(userId);
+    const { photos } = await telegram.getUserProfilePhotos(userId, 0, 1);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/telegramPhoto.ts` at line 6, Update the getUserProfilePhotos
call in the profile-photo lookup to pass offset 0 and limit 1, while preserving
the existing photos[0] handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/services/telegramPhoto.ts`:
- Line 19: Update the photo download fetch in the Telegram photo handling flow
to use an application-level timeout via AbortSignal.timeout or an
AbortController, and ensure the /open path awaits both open(...) and the photo
promise before returning.
- Around line 21-23: Update the HTTP error branch in the Telegram photo request
function to consume or cancel response.body before returning undefined, ensuring
Undici releases the connection while preserving the existing successful-response
flow.

---

Nitpick comments:
In `@src/services/telegramPhoto.ts`:
- Line 6: Update the getUserProfilePhotos call in the profile-photo lookup to
pass offset 0 and limit 1, while preserving the existing photos[0] handling.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ec00217f-748c-423f-918a-962e165accbe

📥 Commits

Reviewing files that changed from the base of the PR and between d6fc81b and 67628cc.

📒 Files selected for processing (1)
  • src/services/telegramPhoto.ts

Comment thread src/services/telegramPhoto.ts Outdated
return undefined;
}

const response = await fetch(`https://api.telegram.org/file/bot${botToken}/${file.file_path}`);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Files matching telegramPhoto:\n'
fd -a 'telegramPhoto\.(ts|js)$' . || true

printf '\nFile outline:\n'
file="$(fd 'telegramPhoto\.(ts|js)$' . | head -n 1)"
if [ -n "${file:-}" ]; then
  ast-grep outline "$file" || true
  printf '\nFile contents with line numbers:\n'
  cat -n "$file"
fi

printf '\nSearch for request_access, open, telegramPhoto download:\n'
rg -n "request_access|/open|telegramPhoto|download_photo|getPhoto|file_path|new AbortController|AbortSignal|timeout|fetch\\(" . -S || true

printf '\nPackage/dependency clues:\n'
for f in package.json package-lock.json pnpm-lock.yaml yarn.lock bun.lockb; do
  [ -f "$f" ] && { echo "--- $f"; sed -n '1,220p' "$f"; }
done

Repository: noamokman/gate-bot

Length of output: 17169


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Command files:\n'
cat -n src/commands/open.ts
printf '\n--- requestAccess ---\n'
cat -n src/commands/requestAccess.ts

printf '\nRoute dashboard handlers context:\n'
sed -n '45,120p' src/web/routes/dashboard.ts | cat -n
printf '\nOpen/auth fetches:\n'
sed -n '1,160p' src/web/routes/auth.ts | cat -n

Repository: noamokman/gate-bot

Length of output: 12347


🌐 Web query:

Telegraf 4.16.3 node-fetch axios getUserProfilePhotos File download timeout abort

💡 Result:

In Telegraf 4.16.3, network operations (including getUserProfilePhotos and associated file downloads) are managed by an internal client that utilizes node-fetch and incorporates a hardcoded timeout value of 500,000 ms (500 seconds) for network requests [1][2]. If you are experiencing premature timeouts, aborts, or connectivity issues when downloading files or photos, consider the following technical factors: 1. Internal Client Timeout: The 500-second timeout is applied within src/core/network/client.ts for both API calls and media downloads [1][2]. This is separate from the handlerTimeout (default 90,000 ms or 90 seconds), which governs the maximum time a middleware/handler function can execute [3][4]. If your process hits the handlerTimeout first, the request will be aborted, potentially causing an unhandled promise rejection if not caught [3][5]. 2. Handler Timeout Configuration: If your code performs synchronous work or complex async chains while processing photos, you may need to increase the handlerTimeout in your Telegraf configuration to ensure the bot does not kill the process before the download completes [3]: const bot = new Telegraf(BOT_TOKEN, { handlerTimeout: 300_000 }); // Example: set to 5 minutes 3. Network and IPv6 Issues: Users running Telegraf on Node.js v20+ have reported ETIMEDOUT errors due to changes in how Node.js resolves IPv4/IPv6 addresses [6]. If you are encountering network-level timeouts, try disabling IPv6 or ensuring your environment correctly resolves the Telegram API endpoints [6]. 4. Implementation Pattern: To successfully retrieve a photo: - Call getUserProfilePhotos(userId) to obtain a file_id [7][8]. - Use getFile(fileId) to get the file_path [7][9]. - Construct the download URL using the bot token and the retrieved path [9][8]. - Ensure you are wrapping these calls in try/catch blocks, as getUserProfilePhotos will throw an error if the user has no photos or if the user_id is invalid [10][11]. If you find that the hardcoded 500s timeout is insufficient for your specific environment (e.g., extremely slow connections), it is a known limitation that the timeout cannot be easily overridden via standard configuration without modifying the client or using a custom proxy/agent [12][13].

Citations:


Add an application-level deadline around the photo download.

The fetch() at src/services/telegramPhoto.ts:19 has no deadline, so a stalled Telegram file stream can keep /open waiting until ctx.reply(). Use AbortSignal.timeout(...) / an explicit AbortController and set /open path handling to return only after both open(...) and the photo promise resolve.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/telegramPhoto.ts` at line 19, Update the photo download fetch in
the Telegram photo handling flow to use an application-level timeout via
AbortSignal.timeout or an AbortController, and ensure the /open path awaits both
open(...) and the photo promise before returning.

Comment thread src/services/telegramPhoto.ts Resolved
- Bound the profile-photo fetch with AbortSignal.timeout so it can never
  hang the /open command (the /open path already awaits both promises)
- Cancel the response body on non-OK responses to release the connection
- Request only the most recent photo set (offset 0, limit 1)
@noamokman
noamokman merged commit 8d8b9cb into main Aug 10, 2026
2 checks passed
@noamokman
noamokman deleted the add-user-profile-pictures branch August 10, 2026 05:03
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