Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@e-esakman
Copy link
Contributor

@e-esakman e-esakman commented Dec 15, 2025

Description

This PR updates the messaging system to allow users to send chat requests to others who have not yet unlocked their chat feature, improving the UX for making interactions more dynamic.

Issue

Previously, when searching for a user who hadn’t unlocked their chats, the “Message” button was unavailable. This led to a poor user experience, as there was no way to initiate communication.

Changes

"Request Chat” button has been added which sends an email notification to the recipient, allowing them to unlock their chats and respond if they wish.

Key changes

  • models.py — add ChatRequest model and slug field for User.
  • core.py — chat request creation logic.
  • user.py — update start_thread logic to handle new request flow.
  • search.html — change message box UI and button logic for messaging actions.

Testing

  1. Run the local server - poetry run daphne blt.asgi:application
  2. Email service - poetry run python -m smtpd -n -c DebuggingServer localhost:1025

Additionally , it fixes #3860 ensuring email initiation works both for locked and unlocked chat cases when a new user initiates a message.

Untitled.design.1.mp4

Summary by CodeRabbit

  • New Features

    • "Request Chat" button and "Request Sent" state for pending chat requests.
    • User profiles gain timezone support and unique profile slugs.
    • App category list expanded with Messaging, Gaming, Streaming, and Other.
  • Behavior Changes

    • Prevents rapid or duplicate chat requests with rate limiting and duplicate checks.
    • Locked recipients trigger a request flow and notification email instead of immediate chat.
    • Unified client-side flow for starting or requesting chats with improved UI feedback.
  • Tests

    • Added tests for chat requests, duplicate blocking, and rate limiting.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions
Copy link
Contributor

👋 Hi @e-esakman!

This pull request needs a peer review before it can be merged. Please request a review from a team member who is not:

  • The PR author
  • DonnieBLT
  • coderabbitai
  • copilot

Once a valid peer review is submitted, this check will pass automatically. Thank you!

@github-actions github-actions bot added files-changed: 5 PR changes 5 files needs-peer-review PR needs peer review migrations PR contains database migration files labels Dec 15, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 15, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Adds ChatRequest model and migration, adds slug and timezone to UserProfile with save logic, introduces Redis-backed rate limiting and a send_chat_request endpoint, updates start-thread flow for locked recipients, adjusts search UI/JS to request chats, adds route and tests.

Changes

Cohort / File(s) Summary
Database Migration
website/migrations/0264_add_slug_timezone_and_chatrequest.py
Adds slug and timezone fields to UserProfile; creates ChatRequest model with sender/receiver FKs, created_at, is_unlocked, email_sent, and unique_together on (sender, receiver).
Models
website/models.py
Adds UserProfile.slug and UserProfile.timezone and a UserProfile.save override to populate a unique slug; introduces ChatRequest model; expands BannedApp.APP_TYPES; removes Tag auto-slug save logic and Tag __str__.
Search UI / JS
website/templates/search.html
Replaces single "Message" button with "Request Chat" / "Request Sent" states; consolidates client JS to POST to start-thread endpoint, handle locked/success responses, and manage button state with CSRF-aware fetch.
Core Views / Chat Request Logic
website/views/core.py
Adds can_send_chat_request(sender_id, receiver_id) with Redis-backed rate limiting and send_chat_request POST view that prevents self-requests/duplicates, creates ChatRequest, attempts email notification, logs outcomes, and returns JSON; search flow prefetches badges/chat-request state and annotates has_pending_request.
Thread Initialization / User Views
website/views/user.py
Makes start_thread POST-only; when recipient lacks public_key creates/gets ChatRequest, sends unlock email if not already sent and returns locked status; for unlocked recipients finds/creates thread, optionally emails recipient, and returns thread_id.
Routing
blt/urls.py
Adds URL pattern chat/request/<int:receiver_id>/ mapped to send_chat_request.
Tests
website/tests/test_core.py
Adds ChatRequestTests with setup for sender/receiver and tests for duplicate-request blocking and Redis-backed rate limiting (expects 429 on limit violations).

Sequence Diagram(s)

sequenceDiagram
    participant Browser as Sender (browser)
    participant UI as Search UI (client JS)
    participant App as Django view (send_chat_request / start_thread)
    participant Redis as Redis (rate limiter)
    participant DB as Database (ChatRequest / Thread)
    participant Email as Email service

    Browser->>UI: Click "Request Chat" / "Message"
    UI->>App: POST /chat/request/{receiver_id} or /messaging/start-thread/{userId}/ (with CSRF)
    App->>Redis: check/increment rate limit for sender->receiver
    alt rate limit exceeded
        Redis-->>App: limit reached
        App-->>UI: 429 / {"error":"rate_limit"}
        UI->>Browser: show error / revert button
    else rate OK
        App->>DB: lookup existing ChatRequest
        alt existing record and locked
            DB-->>App: ChatRequest exists (locked/unlocked)
            App-->>UI: {"locked": true, "email_sent": ...}
        else create new ChatRequest
            App->>DB: create ChatRequest (sender, receiver)
            DB-->>App: ChatRequest created
            App->>Email: send unlock/notification email (if needed)
            Email-->>App: delivery status
            App->>DB: mark email_sent = true (if sent)
            App-->>UI: {"locked": true, "email_sent": true} or {"success": true, "thread_id": id}
            UI->>Browser: update button state or redirect to thread
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Inspect Redis key format, TTL, atomic increment and fallback path for Redis failures.
  • Check ChatRequest get/create handling for unique_together races (transactions or get_or_create).
  • Verify email sending paths mark email_sent reliably and handle delivery/failure without inconsistent DB state.
  • Review UserProfile.slug uniqueness logic and collision handling when deriving from usernames.
  • Validate search prefetch/select_related to avoid N+1 and correct has_pending_request annotation.
  • Confirm JS CSRF handling, response parsing, and UI state transitions.

Suggested labels

quality: medium

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Several changes appear tangential to the main objective: modifications to BannedApp.APP_TYPES and Tag model changes are unrelated to chat request functionality. Remove unrelated changes to BannedApp.APP_TYPES and Tag model modifications. Focus only on ChatRequest, UserProfile (slug/timezone), and email notification flow changes.
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature: enabling chat requests to locked users, which is the primary objective of this PR.
Linked Issues check ✅ Passed The PR implements the core requirement from issue #3860: sending email notifications to recipients when chat is initiated, supporting both locked and unlocked recipient states.

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 and usage tips.

@github-actions
Copy link
Contributor

📊 Monthly Leaderboard

Hi @e-esakman! Here's how you rank for December 2025:

Rank User PRs Reviews Comments Total
#6 @arnavkirti 4 12 27 142
#7 @e-esakman 4 3 15 82
#8 @swaparup36 3 6 10 74

Leaderboard based on contributions in December 2025. Keep up the great work! 🚀

@github-actions github-actions bot added the pre-commit: passed Pre-commit checks passed label Dec 15, 2025
@github-actions github-actions bot added the tests: failed Django tests failed label Dec 15, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 (3)
website/views/user.py (1)

1719-1794: start_thread flow looks correct; consider tightening a couple of edges

The locked/unlocked split, single-email behaviour via email_sent, and thread creation all look consistent with the new ChatRequest model and the front-end expectations.

Two non-blocking tweaks you may want to consider:

  • Add a cheap guard against self-chat to avoid weird UX like emailing a user to unlock their own chat with themselves:
@login_required
def start_thread(request, user_id):
    if request.method != "POST":
        return JsonResponse({"success": False, "error": "Invalid request"}, status=400)

    current_user = request.user
    other_user = get_object_or_404(User, id=user_id)
+
+    if other_user == current_user:
+        return JsonResponse({"success": False, "error": "Cannot start a thread with yourself"}, status=400)
  • If there’s any chance other_user.userprofile might be missing, you could defensively handle UserProfile.DoesNotExist instead of relying on the getattr shortcut; this is in line with other assumptions in this file though, so treat it as optional.
website/views/core.py (1)

49-77: User search + pending-request wiring is sound; small UX gaps you may want to close

The changes to search() correctly:

  • Load users with their UserProfile and scores.
  • Compute sent_requests via ChatRequest for the current user.
  • Attach has_pending_request and badges to each user object for the type='users' view, matching the template’s expectations.

Two minor UX details to consider (not blockers):

  1. type='all' search doesn’t reflect pending requests

    For the "all" search path, users is a plain queryset of User without the has_pending_request flag or badges attached. The template’s “Users” section still renders for that case and will therefore always show “Request Chat” instead of “Request Sent” even when a ChatRequest already exists.

    If you want consistent behaviour between "all" and "users" searches, you could reuse the same sent_requests/users_list construction for the "all" case (or refactor into a helper used by both paths).

  2. Distinguishing “request exists but no email was sent” (optional)

    has_pending_request is currently keyed purely on the presence of a ChatRequest. In the rare case where a request was created while receiver.email was empty, the UI will still show “Request Sent” later even though no email was ever delivered. If that distinction matters, you might drive the “Request Sent” label from email_sent (and potentially allow re-request if email_sent is still false).

Overall the logic is correct; these are UX-level refinements you can choose to defer.

Also applies to: 603-669

website/templates/search.html (1)

322-340: Unified Message / Request Chat UI matches backend; only nit is some dead class handling

The template + JS wiring lines up nicely with the new start_thread JSON API:

  • Correctly shows:
    • “Message” when user.userprofile.public_key exists.
    • Disabled “Request Sent” when user.has_pending_request is true.
    • “Request Chat” otherwise, using the same POST endpoint and relying on data.locked vs data.success to decide between “Request Sent” and redirect.
  • CSRF handling via getCookie("csrftoken") and POST is appropriate for this view.

One tiny clean-up you may want to make:

  • In the locked branch you call:

    this.classList.remove("bg-[#e74c3c]", "hover:bg-[#c0392b]");
    this.classList.add("bg-red-500", "cursor-not-allowed");

    but none of the current buttons use bg-[#e74c3c] or hover:bg-[#c0392b] anymore, so those removes are no-ops. You could either update the removals to match the current grey/indigo classes (if you want to normalise the visual state) or just drop the classList.remove call entirely to reduce noise.

Behaviour-wise everything is solid.

Also applies to: 785-848

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between cd7312d and 21ce883.

📒 Files selected for processing (5)
  • website/migrations/0264_add_slug_timezone_and_chatrequest.py (1 hunks)
  • website/models.py (4 hunks)
  • website/templates/search.html (2 hunks)
  • website/views/core.py (3 hunks)
  • website/views/user.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
website/views/user.py (2)
website/models.py (2)
  • ChatRequest (3089-3103)
  • Thread (3064-3069)
website/static/js/invite.js (1)
  • subject (75-75)
website/views/core.py (1)
website/models.py (2)
  • ChatRequest (3089-3103)
  • UserBadge (1682-1696)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run Tests
  • GitHub Check: docker-test
🔇 Additional comments (3)
website/models.py (3)

906-906: LGTM!

The slug field definition is appropriate. Using unique=True with null=True is valid in Django since NULL values are excluded from uniqueness checks.


935-935: LGTM!

The timezone field with max_length=50 and default "UTC" is appropriate for storing timezone identifiers.


3089-3103: LGTM!

The ChatRequest model is well-designed for the chat request feature:

  • Appropriate use of CASCADE on delete for user references
  • unique_together constraint correctly prevents duplicate requests between the same users
  • Clear status tracking with email_sent and is_unlocked fields

@github-project-automation github-project-automation bot moved this from Backlog to Ready in 📌 OWASP BLT Project Board Dec 15, 2025
@e-esakman e-esakman marked this pull request as draft December 15, 2025 13:02
@github-actions github-actions bot added the changes-requested PR has requested changes from a reviewer label Dec 15, 2025
@github-actions github-actions bot added tests: passed Django tests passed and removed tests: failed Django tests failed labels Dec 15, 2025
@e-esakman e-esakman marked this pull request as ready for review December 15, 2025 15:02
@github-actions github-actions bot removed the changes-requested PR has requested changes from a reviewer label Dec 15, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
website/models.py (1)

909-969: UserProfile.slug should be slugified and collision-safe (issue already raised previously)

UserProfile.slug is a SlugField(unique=True, …), but save() assigns self.user.username directly:

if not self.slug:
    self.slug = self.user.username

Django usernames can contain characters (@, ., +, etc.) that are invalid for SlugField validators and URL slug converters, and this also doesn’t handle collisions if you later derive slugs differently. This matches the concern in the earlier review comment that suggested using slugify() instead of raw username.

A safer implementation would mirror the slug logic used on Organization/Repo:

class UserProfile(models.Model):
@@
-    slug = models.SlugField(unique=True, blank=True, null=True)
+    slug = models.SlugField(unique=True, blank=True, null=True)
@@
-    def save(self, *args, **kwargs):
-        if not self.slug:
-            self.slug = self.user.username
-        super().save(*args, **kwargs)
+    def save(self, *args, **kwargs):
+        if not self.slug and self.user_id:
+            # Start from a slugified username
+            base_slug = slugify(self.user.username)
+            if not base_slug:
+                base_slug = f"user-{self.user_id}"
+
+            self.slug = base_slug
+            counter = 1
+            while UserProfile.objects.filter(slug=self.slug).exclude(pk=self.pk).exists():
+                self.slug = f"{base_slug}-{counter}"
+                counter += 1
+
+        super().save(*args, **kwargs)

This preserves existing custom slugs, ensures the value is a valid slug, and avoids collisions.

Check Django’s `SlugField` and `slugify` documentation to confirm valid characters for slugs and common patterns for generating unique slugs from usernames.
🧹 Nitpick comments (2)
website/models.py (2)

3092-3106: ChatRequest model is solid; optional CheckConstraint to prevent self-requests

The ChatRequest model structure (ForeignKeys to AUTH_USER_MODEL, unique_together = ("sender", "receiver"), and clear __str__) is well-designed.

If your domain requires preventing users from requesting a chat with themselves, you can add a DB-level check constraint:

class ChatRequest(models.Model):
     created_at = models.DateTimeField(auto_now_add=True)

     class Meta:
         unique_together = ("sender", "receiver")
+        constraints = [
+            models.CheckConstraint(
+                check=~models.Q(sender=models.F("receiver")),
+                name="chatrequest_sender_not_receiver",
+            ),
+        ]

Django 5.2.x fully supports this constraint pattern with F() expressions. Alternatively, add validation in the view/service layer if preferred.


909-909: Consider consolidating timezone handling between UserProfile and ReminderSettings

Both models define identical timezone = models.CharField(max_length=50, default="UTC") fields. However, ReminderSettings has proper validation via its save() method (which uses pytz.timezone()) and provides get_timezone_choices() returning pytz.common_timezones. UserProfile.timezone lacks this validation and integration. To avoid divergence, either reuse ReminderSettings' timezone approach in UserProfile or consolidate to a single timezone management pattern across both models.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 21ce883 and f99b001.

📒 Files selected for processing (3)
  • website/migrations/0264_add_slug_timezone_and_chatrequest.py (1 hunks)
  • website/models.py (5 hunks)
  • website/views/user.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • website/views/user.py
  • website/migrations/0264_add_slug_timezone_and_chatrequest.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run Tests
  • GitHub Check: docker-test

@github-actions github-actions bot added the changes-requested PR has requested changes from a reviewer label Dec 15, 2025
@github-actions github-actions bot added files-changed: 5 PR changes 5 files and removed files-changed: 7 PR changes 7 files labels Dec 16, 2025
@e-esakman e-esakman marked this pull request as ready for review December 16, 2025 08:52
@github-actions github-actions bot added tests: passed Django tests passed last-active: 0d PR last updated 0 days ago and removed tests: failed Django tests failed labels Dec 16, 2025
@github-actions
Copy link
Contributor

💬 Reminder: Unresolved Conversations

Hi @e-esakman!

This pull request has 1 unresolved conversation that need to be addressed.

Please review and resolve the pending discussions so we can move forward with merging this PR.

Thank you! 🙏

@github-actions github-actions bot added last-active: 1d PR last updated 1 day ago last-active: 2d PR last updated 2 days ago and removed last-active: 0d PR last updated 0 days ago last-active: 1d PR last updated 1 day ago labels Dec 20, 2025
@e-esakman
Copy link
Contributor Author

e-esakman commented Dec 22, 2025

@coderabbitai is there anything unresolved?

@github-actions github-actions bot removed the last-active: 2d PR last updated 2 days ago label Dec 22, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

Tip

For best results, initiate chat on the files or code changes.

@e-esakman Yes, there's one unresolved architectural issue:

The send_chat_request endpoint in core.py is defined but unused. The frontend currently routes both regular chats and chat requests through /messaging/start-thread/, so the rate limiting logic you implemented in send_chat_request (lines 938-940 in core.py) is never executed.

To resolve this, you can choose one of these approaches:

  1. Keep current behavior (recommended if it's working well): Remove the unused /chat/request/<receiver_id>/ endpoint and send_chat_request function from core.py, keeping all logic in start_thread in user.py

  2. Implement the architectural separation: Update the frontend .request-chat button to POST to /chat/request/${userId}/ instead of /messaging/start-thread/${userId}/, so your rate limiting takes effect

  3. Hybrid approach: Have start_thread call can_send_chat_request internally before creating ChatRequest objects to leverage the rate limiting logic

Which approach would you prefer? The current implementation works functionally, but having unused endpoints can be confusing for future maintainers.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the current frontend routing for request-chat button
echo "=== Frontend request-chat button routing ==="
rg -n "request-chat" website/templates/search.html -A 15 | grep -E "(fetch|POST|/messaging/|/chat/request/)" | head -20

echo -e "\n=== Check if send_chat_request endpoint still exists in core.py ==="
rg -n "def send_chat_request" website/views/core.py -A 5

echo -e "\n=== Check URL routing for chat/request ==="
rg -n "chat/request" blt/urls.py

echo -e "\n=== Check if start_thread calls can_send_chat_request ==="
rg -n "can_send_chat_request" website/views/user.py -B 2 -A 2

Length of output: 600


🏁 Script executed:

#!/bin/bash
# Check if the chat/request URL pattern and import were removed
echo "=== Check for send_chat_request in blt/urls.py ==="
rg -n "send_chat_request" blt/urls.py

echo -e "\n=== Check all URL patterns mentioning 'chat' in blt/urls.py ==="
rg -n "path.*chat" blt/urls.py -C 2

echo -e "\n=== Verify the imports from website.views.core in blt/urls.py ==="
rg -n "from website.views.core import" blt/urls.py -A 5

Length of output: 354


🏁 Script executed:

#!/bin/bash
# Check if can_send_chat_request is used anywhere in the codebase
echo "=== All usages of can_send_chat_request ==="
rg -n "can_send_chat_request" --type=py

echo -e "\n=== All usages of send_chat_request ==="
rg -n "send_chat_request" --type=py

echo -e "\n=== Check if these functions are tested ==="
rg -n "send_chat_request|can_send_chat_request" website/tests/test_core.py -C 2

Length of output: 536


@e-esakman Great progress! I can see you've removed the URL routing and import from blt/urls.py - that resolves the architectural concern about the unused endpoint. ✅

However, there's one small cleanup remaining:

Dead code in website/views/core.py:

  • send_chat_request() (line 928)
  • can_send_chat_request() (line 902)

Since these functions are no longer routed or called anywhere, they can be safely removed to keep the codebase clean.

Optional cleanup:
If you added tests in ChatRequestTests specifically for these endpoints, those can be removed too (though I don't see them in the current test file).


Summary:

  • ✅ Functional issue resolved - no unused endpoints exposed
  • 🧹 Cleanup needed - remove dead code functions

Would you like me to help remove these unused functions, or would you prefer to handle it yourself?

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

echo "=== 1. Check if send_chat_request endpoint exists in core.py ==="
rg -n "def send_chat_request" website/views/core.py -A 5

echo -e "\n=== 2. Check URL routing for send_chat_request ==="
rg -n "send_chat_request" blt/urls.py -B 2 -A 2

echo -e "\n=== 3. Check frontend routing for request-chat button ==="
rg -n "request-chat" website/templates/search.html -A 15 | head -30

echo -e "\n=== 4. Check if start_thread handles chat requests ==="
rg -n "ChatRequest" website/views/user.py -B 2 -A 5 | head -40

Length of output: 3357


🏁 Script executed:

#!/bin/bash

echo "=== Check for chat/request URL pattern in blt/urls.py ==="
rg -n "chat/request" blt/urls.py -B 3 -A 3

echo -e "\n=== Check all imports in blt/urls.py that mention send_chat_request ==="
rg -n "send_chat_request" blt/ --type=py

echo -e "\n=== Verify the complete imports section in blt/urls.py ==="
head -50 blt/urls.py | grep -A 5 -B 5 "from website.views"

Length of output: 190


🏁 Script executed:

#!/bin/bash

echo "=== Read the complete blt/urls.py file ==="
cat blt/urls.py

echo -e "\n=== Confirm send_chat_request function still exists in core.py ==="
rg -n "^def send_chat_request" website/views/core.py

echo -e "\n=== Check if send_chat_request is exported from core.py ==="
rg -n "send_chat_request" website/views/core.py | head -5

Length of output: 50229


@e-esakman Yes, there is one unresolved architectural issue:

The send_chat_request function in core.py (line 928) is dead code with no routing.

After checking the codebase:

  1. Function exists: send_chat_request is defined in website/views/core.py
  2. No URL routing: There is no URL pattern in blt/urls.py that maps to send_chat_request (I searched the entire 700+ line file)
  3. Frontend doesn't call it: Both .start-chat and .request-chat buttons POST to /messaging/start-thread/${userId}/ (line 797 in search.html)
  4. All logic flows through start_thread: The start_thread view in user.py handles ChatRequest creation (line 1729)

Impact:

  • The rate limiting logic you implemented in can_send_chat_request (line 934) is never executed
  • The send_chat_request endpoint is unused code that adds maintenance burden

Resolution options:

  1. Remove the dead code (simplest): Delete send_chat_request and can_send_chat_request from core.py since all functionality already works through start_thread

  2. Add the missing URL route and wire the frontend to use it:

    # In blt/urls.py
    from website.views.core import send_chat_request
    
    path("chat/request/<int:receiver_id>/", send_chat_request, name="send_chat_request"),

    Then update the .request-chat button to POST to this endpoint instead

Would you like me to help you implement either option?

@github-actions github-actions bot added last-active: 0d PR last updated 0 days ago last-active: 1d PR last updated 1 day ago last-active: 2d PR last updated 2 days ago and removed last-active: 0d PR last updated 0 days ago last-active: 1d PR last updated 1 day ago labels Dec 23, 2025
@github-actions github-actions bot added last-active: 0d PR last updated 0 days ago last-active: 2d PR last updated 2 days ago and removed last-active: 2d PR last updated 2 days ago last-active: 0d PR last updated 0 days ago labels Dec 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changes-requested PR has requested changes from a reviewer files-changed: 5 PR changes 5 files has-peer-review PR has received peer review last-active: 2d PR last updated 2 days ago migrations PR contains database migration files pre-commit: passed Pre-commit checks passed quality: high quality: medium tests: passed Django tests passed

Projects

Status: Ready

Development

Successfully merging this pull request may close these issues.

When someone starts an encrypted chat send the recipient an email with a link to open it

3 participants