Commit Graph

835 Commits

Author SHA1 Message Date
088dbbf3da feat: replace global thread pool with per-user executor pools in ChannelMessageService
Remove the module-level `executor` variable and introduce instance-level `_executor_pools` dict with `get_or_create_executor` method that creates a `ThreadPoolExecutor(max_workers=5)` per user UID. Update all `run_in_executor` calls in `render_message` and `render_message_edit` to use the per-user executor instead of the shared global one, improving isolation and resource control across concurrent user requests.
2025-09-07 22:59:11 +00:00
8d4511a2bf fix: prevent avatar anchor from being overwritten by later matches in message-list.js
The loop iterating over avatar elements now only assigns the first matching anchor to `lastElement`, ensuring the scroll target remains the earliest occurrence instead of being overwritten by subsequent matches.
2025-09-07 00:42:47 +00:00
77d7186c86 fix: add debug print before socket deletion in RPCView error handlers
Add a debug print statement in the `send` method's exception handler to log the exception message before deleting the socket, and update the existing debug print in the message processing loop to include a distinctive prefix for easier log filtering.
2025-08-31 01:41:41 +00:00
86b0ae6db4 fix: correct indentation of user_availability_service method in socket.py
The method definition was incorrectly placed at module level instead of being properly indented as a member of the SocketService class. This fix moves the async def user_availability_service declaration one level deeper to align with the class body, restoring correct Python scoping and preventing AttributeError or runtime import failures when the service attempts to register or invoke this method.
2025-08-31 01:27:47 +00:00
7984feeb6d chore: add debug logging to user availability service loop
Add detailed debug-level log statements throughout the
user_availability_service method to trace execution flow, including
entry into the main loop, socket iteration, connection status checks,
user update decisions, database save operations, and sleep intervals.
2025-08-31 01:25:26 +00:00
50e800e5f2 fix: offload Jinja2 template rendering and sanitization to thread pool executor to avoid blocking async event loop 2025-08-31 01:22:00 +00:00
f8670d8a38 feat: implement modal editor with vim-like modes and command-line interface
Replace the basic contenteditable editor with a full modal editor supporting insert, normal, and visual modes. Add a command-line interface at the bottom for executing commands like :w, :q, and :wq. Introduce mode-specific cursor styling, selection highlighting, and keyboard-driven navigation. The editor now tracks mode state, handles mode transitions via Escape and i/v keys, and displays the current mode in a status bar.
2025-08-06 13:33:13 +00:00
c9673b7744 fix: copy user socket list before iteration to avoid mutation during send 2025-08-06 12:18:01 +00:00
791ef0bc13 feat: add sentry-sdk dependency and initialize sentry in main function
- Added sentry-sdk to project dependencies in pyproject.toml
- Imported and initialized sentry_sdk with DSN in main() function
- Added graceful fallback with print message if sentry_sdk import fails
2025-08-06 09:51:58 +00:00
448034e03e feat: disable login requirement for ChannelAttachmentView to allow public access to attachments 2025-08-03 01:31:08 +00:00
01a14370c9 fix: remove random sleep before rpc call in websocket message handler 2025-08-01 00:06:20 +00:00
dbc34cebb1 fix: reduce randomized sleep range in websocket RPC handler from 0.1-0.4s to 0.01-0.1s 2025-07-31 23:59:23 +00:00
b760fdd22b fix: add random sleep before RPC message processing in websocket handler
- Imported `random` module to support randomized delay
- Inserted `await asyncio.sleep(random.uniform(0.1, 0.4))` before `await rpc(msg.json())` in the websocket message loop
- This introduces a jitter of 100-400ms to desynchronize concurrent RPC processing from multiple clients
2025-07-31 23:57:18 +00:00
2cc616c8aa fix: move endOfMessages.after call before scroll check in MessageList
The `endOfMessages.after(message)` call was placed after the `isScrolledToBottom()` check, causing the scroll position to be evaluated before the new message was inserted into the DOM. This resulted in incorrect scroll behavior when messages were added, as the scroll check would not account for the newly inserted element. Moving the insertion before the scroll check ensures the scroll position is evaluated after the DOM has been updated with the new message.
2025-07-30 12:49:16 +00:00
32ed12f3db fix: correct missing closing parenthesis in upsertMessage condition check 2025-07-30 12:46:10 +00:00
1f89849c9a fix: correct conditional grouping in upsertMessage to remove stale messages
The diff shows a fix in the `upsertMessage` method of the `MessageList` class in `src/snek/static/message-list.js`. The original condition `(message && data.is_final) || !data.message` was incorrectly grouping the logical OR, causing messages to be removed only when `data.is_final` was true alongside a message, or when `data.message` was falsy regardless of message existence. The fix wraps the entire condition in parentheses: `(message && (data.is_final || !data.message))`, ensuring that a message is removed only if it exists AND either `data.is_final` is true or `data.message` is falsy. A comment `// TO force insert` was added to clarify the intent of nullifying the message reference after removal.
2025-07-30 12:44:25 +00:00
77802883fe fix: skip upsert for empty messages and clear stale entries in MessageList 2025-07-30 12:41:23 +00:00
aa3d00243f fix: remove stale message from DOM only when is_final flag is set
Previously, the upsertMessage method removed any existing message element from the DOM whenever a message with the same uid was received, regardless of whether the update represented a final version. This caused premature removal of messages that were still being streamed or updated incrementally. Now the removal is gated on the `data.is_final` property, ensuring that only completed messages are replaced in the DOM while in-progress messages remain visible until their final state arrives.
2025-07-30 12:36:56 +00:00
9bad9a78ed feat: add HEAD route and lock-checking middleware to WebDAV handler 2025-07-30 01:25:36 +00:00
c5df9e6463 feat: add MS-Author-Via header to WebDAV OPTIONS response and fix semicolons in message-list.js
- Add "MS-Author-Via: DAV" header to WebDAV OPTIONS handler for Microsoft WebDAV client compatibility
- Fix missing semicolons in message-list.js (LONG_TIME constant, ReplyEvent constructor)
- Remove trailing whitespace in import statement formatting
2025-07-30 00:51:26 +00:00
299f617988 fix: re-enable iframe elements in sanitize_html by commenting out removal logic 2025-07-26 21:56:24 +00:00
942098583d feat: add XSS sanitization to channel message rendering and refactor sanitize_html with BeautifulSoup
Add sanitize_html calls in ChannelMessageService for both render and save paths to strip script, iframe, object, embed tags and event handler attributes from rendered HTML templates. Refactor sanitize_html in template.py to use BeautifulSoup for tag removal and attribute cleaning, replacing the previous bleach-only implementation with a new sanitize_html2 function retained for compatibility.
2025-07-25 15:17:45 +00:00
8762e592d0 fix: remove whitelist_attributes call from message template rendering in ChannelMessageService
The whitelist_attributes filter was applied to the rendered HTML output in both
the get_by_uid and save methods of ChannelMessageService. This filter was
stripping allowed HTML attributes from the message content, which could break
formatting or functionality in rendered messages. The fix removes the filter
call, allowing the full rendered template output to be stored and returned
without attribute sanitization.
2025-07-25 15:10:03 +00:00
0a45ef2b8f fix: move whitelist_attributes call to post-render in channel message service 2025-07-25 15:05:41 +00:00
bc924f4f85 fix: reduce default star count from 100 to 50 in StarField constructor and instantiation 2025-07-24 11:48:22 +00:00
5e92d9ce77 feat: add once option to event listeners and implement removeEventListener method
Extend EventHandler.addEventListener to accept an optional `once` parameter that auto-removes the handler after first invocation. Implement removeEventListener method to support manual removal of specific handlers and cleanup of empty subscriber arrays. Update Socket.call method to use the new once option for one-shot RPC response listeners.
2025-07-24 21:36:50 +00:00
BordedDev
3ea97f1e97 fix: remove unused isVisible method and fix sibling tracking in message rendering
- Remove the unused `isVisible()` method from `MessageElement` class to clean up dead code
- Fix `siblingGenerated` tracking logic: change from boolean to storing the actual next sibling reference, ensuring proper re-evaluation when DOM changes occur
- Move `endOfMessages` element creation before the observer loop to ensure it's observed for intersection events
2025-07-24 14:14:51 +00:00
BordedDev
3aaad348d0 feat: add once option to addEventListener and implement removeEventListener method
- Extend addEventListener to accept an optional `{ once: true }` parameter that auto-removes the handler after first invocation
- Add removeEventListener method to EventHandler class for explicit handler removal
- Clean up empty subscriber arrays by deleting the type key when last handler is removed
- Refactor Socket.call to use the new once option instead of manual handler management
2025-07-24 13:59:17 +00:00
4e31728de4 fix: move whitelist_attributes call before template render to prevent xss in channel messages 2025-07-23 23:46:34 +00:00
d015e81069 feat: add is_dm property to ChannelModel and auto-join dm channels for members 2025-07-23 23:07:33 +00:00
BordedDev
6bddaeb6a4 fix: strip embed links and media from reply text and trigger change event on reply insertion 2025-07-20 01:38:18 +00:00
BordedDev
e0a253521a refactor: replace click-based reply delegation with custom ReplyEvent in message-list
Replace the global click delegation on `messagesContainer` that checked for anchor tags with `href="#reply"` by introducing a dedicated `ReplyEvent` class. The event is now dispatched from within `MessageElement` when the reply link is clicked, carrying the message text target directly. This moves the reply logic from a fragile DOM traversal to a composed, bubbling custom event, improving encapsulation and maintainability.
2025-07-19 23:11:05 +00:00
BordedDev
b4e67834d1 fix: guard against null parentElement and missing _originalChildren in message upsert 2025-07-19 21:31:23 +00:00
BordedDev
1f187c616c fix: invert scrolled-to-bottom guard in scrollToBottom to always scroll when not at bottom 2025-07-18 22:13:06 +00:00
BordedDev
c09c8acc93 fix: correct double-g scroll target to last message element
The double-g press handler was incorrectly scrolling to the first child of the messages container instead of the last element, causing the viewport to jump to the top of the conversation rather than the most recent message. Changed the selector from `.message:first-child` to `lastElementChild` to properly scroll to the latest message before triggering `loadExtra()`.
2025-07-18 22:00:29 +00:00
BordedDev
58f53ee252 fix: prevent cross-channel message updates and fix reply click handler with instant scroll
- Guard update_message_text handler to only upsert messages already in the local map, avoiding cross-channel text updates
- Add delegated click listener on messagesContainer for #reply links, extracting message text for reply input
- Change scrollToBottom default behavior from 'smooth' to 'instant' for immediate positioning
- Fix loadExtra to use lastElementChild and reverse fetched messages for correct prepend order
- Correct isScrolledPastHalf logic to use absolute scrollTop value for reliable detection
2025-07-18 21:57:41 +00:00
0d5b91b6b4 fix: replace async iteration with sync find and add exception handling in ChannelMessageService.maintenance
Refactor the maintenance method to iterate over channel messages using synchronous `self.mapper.db["channel_message"].find()` instead of the async `self.find()` generator, wrapping each message processing in a try-except block that catches exceptions, prints them, and sleeps for 0.1 seconds before continuing.
2025-07-18 21:20:46 +00:00
4e66c895a6 fix: ensure message is fetched before save when html lacks chat-message tag 2025-07-18 15:49:01 +00:00
b6afdca6d3 fix: replace redundant fetch-save pattern with direct save call in channel message service 2025-07-18 15:44:45 +00:00
56f313c88e feat: add request statistics middleware with time-series tracking and stats endpoint
- Import and register stats_middleware in the application middleware stack
- Add prepare_stats startup hook to initialize stats data structure
- Register /stats.html GET route with stats_handler for viewing statistics
- Create new snek/system/stats.py module with time-series data collection and SVG chart generation
- Integrate websocket statistics tracking in RPC view by calling update_websocket_stats before and after method execution
2025-07-17 22:43:37 +00:00
BordedDev
04ea146221 fix: prevent terminal scroll jump on blur by deferring input reset and aligning scroll anchor
The blur handler in chat-input.js now calls updateFromInput with the current value and isFinal=true before resetting, ensuring the live-typing send uses the correct isFinal flag to avoid premature message dispatch. In message-list.js, scrollToBottom anchors to block 'start' instead of 'end' to keep the terminal view stable when new messages arrive. The app.html keydown listener also receives the event parameter to properly handle Escape key detection.
2025-07-17 21:21:15 +00:00
BordedDev
ccd443055b refactor: replace inline message template with custom chat-message web component and reverse message order
The diff replaces the static message HTML template with a custom `<chat-message>` web component, reverses message rendering order in the template, updates CSS to use `column-reverse` for chat layout, and adjusts scroll logic to append new messages at the end instead of prepending at the beginning.
2025-07-17 00:22:47 +00:00
5bdf00fdd0 feat: add uploadResponses tracking array and reset after publish in file upload grid
The uploadResponses array is initialized in the component constructor to collect file upload results. The reset() call is moved inside the conditional block that fires when all uploads are complete, ensuring the component state is cleared only after the 'file-uploads-done' event has been published with the full response data. A console.info log is added for debugging the collected responses.
2025-07-14 17:11:46 +00:00
7af32a5036 feat: migrate forum queries to async generators and replace find_one with get method
- Convert ForumModel.get_threads and ThreadModel.get_posts from returning lists to async generators yielding individual records
- Replace deprecated `_order_by` and `_offset` parameters with `order_by` string syntax in service queries
- Add `get_timestamp` helper and `save` method to BaseModel for direct persistence
- Refactor ForumView endpoints to use `services.forum.get` and `services.thread.get` instead of `find_one`
- Inject request reference into app context via `setattr(self, "request", request)` in view handlers
- Restructure forum HTML template to extend app layout with breadcrumb navigation and dark theme styling
2025-07-12 18:58:19 +00:00
b6240803ab feat: add uuid generation and public notify method to BaseForumService, fix WebSocket handler method name
- Add `generate_uid` method using uuid4 to BaseForumService
- Expose public `notify` method for external event dispatching
- Rename `websocket_handler` to `get` in ForumWebSocketView for proper routing
- Fix WebSocket ID generation to use forum service instance instead of generic services
2025-07-12 01:01:39 +00:00
91249ff2a1 feat: integrate forum sub-application with models, mappers, services, and WebSocket support
Add complete forum feature including ForumApplication sub-app mounted on parent, new ForumModel/ThreadModel/PostModel/PostLikeModel entities, corresponding mappers and services, event notification dispatch system, and WebSocket endpoint for real-time updates. Refactor service registry to use dynamic registration pattern.
2025-07-12 00:41:57 +00:00
9493c63396 feat: add PROPGET, PROPSET, PROPDEL routes and property file management to WebDAV handler
Implement three new WebDAV property routes (PROPGET, PROPSET, PROPDEL) alongside property file lifecycle management: delete properties on file removal and move properties on file rename via shutil.
2025-07-10 01:25:40 +00:00
ae6ae150fc fix: remove Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers from CORS middleware 2025-07-08 21:54:28 +00:00
879148bc2c feat: add Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers to CORS middleware
Add `Cross-Origin-Opener-Policy: same-origin` and `Cross-Origin-Embedder-Policy: credentialless` headers to the `cors_middleware` response in `src/snek/system/middleware.py`, with a commented-out alternative for `require-corp` to support cross-origin isolation configuration.
2025-07-08 21:35:31 +00:00
BordedDev
36cf5d8109 feat: prioritize secure_url over url for og:image and og:video in embed_url
Reorder the fallback chain for Open Graph image and video extraction in
`src/snek/system/template.py` to check `secure_url` before `url` and `image`/`video`,
ensuring HTTPS resources are preferred when available for embedded player support.
2025-07-05 16:00:58 +00:00
b90079e858 fix: set fallback Content-Type to application/octet-stream for untyped file downloads
When a file has an unknown or empty MIME type (original_format is None or empty string),
the response now defaults to "application/octet-stream" instead of sending an empty
Content-Type header, which caused browsers to mishandle the download.
2025-07-04 20:29:58 +00:00
27bca9c295 feat: add time_cache decorator to block_code method and import time_cache
- Import time_cache alongside existing time_cache_async from app.cache
- Apply @time_cache with 60-minute timeout to block_code method in MarkdownRenderer
- Fix minor whitespace formatting issues in markdown.py
2025-07-04 08:38:08 +00:00
f2c67c02d0 fix: remove async semaphore and executor wrapping from BaseMapper execute method
The synchronous _execute call replaces the previous async pattern that used a semaphore
and run_in_executor, simplifying the execution path and removing unnecessary async overhead
for database operations that are already synchronous in nature.
2025-07-04 07:32:03 +00:00
9f578f1534 refactor: move semaphore to class level and simplify run_in_executor retry logic
The semaphore is now a class-level attribute shared across all instances, and the retry loop with exponential backoff is removed in favor of a single execution path that always acquires the semaphore. The commit call is conditionally performed only when use_semaphore is True, and the template's live-type attribute is flipped from "false" to "true" to enable live chat functionality.
2025-07-04 07:29:03 +00:00
1cca195b76 fix: correct variable shadowing and add async/await in service worker push handler
- Renamed shadowed `clients` variable to `matchedClients` in `isClientOpen` function to avoid conflict with global `clients` API
- Changed push event listener to async and added `await` before `isClientOpen` call to properly handle the returned promise
2025-07-04 04:03:53 +00:00
52f14b7c0f fix: comment out patchConsole call in sandbox StarField initialization 2025-07-04 03:50:54 +00:00
3fe014c9e8 fix: suppress push notification display when client window is already focused 2025-07-04 03:40:19 +00:00
bd643b63e6 fix: disable live-type attribute on chat-input component in web template 2025-07-04 03:16:56 +00:00
BordedDev
64f86fa778 fix: fallback to application/octet-stream for untyped attachment downloads 2025-07-01 23:03:09 +00:00
9220bd36f5 fix: correct typo in UserService.search method from kwarggs to kwargs 2025-07-01 08:43:15 +00:00
763fd9aabe fix: replace punctuated text assignment with space in STTButton typing simulation 2025-06-29 19:13:30 +00:00
0e6b01a468 fix: replace empty string with space in STTButton simulateTypingWithEvents call
The change modifies the simulateTypingWithEvents call in the STTButton class to pass a single space character instead of an empty string, ensuring the typing simulation triggers proper input event handling for interim speech-to-text results.
2025-06-29 19:10:57 +00:00
3b659e0db1 fix: restore empty simulateTypingWithEvents call in STTButton interim handler 2025-06-29 19:09:03 +00:00
acdeaaa980 fix: replace interim text replacement with direct sendMessage call in STTButton
The diff modifies the speech-to-text button handler in `src/snek/static/stt.js` to change behavior when interim speech recognition results are received. Previously, the code replaced the input element's value with an empty string and then simulated typing events to insert the interim text. The new implementation sets the input element's value directly to the interim text and calls `document.querySelector('chat-input').sendMessage(interim)` to immediately send the recognized speech as a chat message, bypassing the typing simulation entirely. The old typing simulation logic is commented out.
2025-06-29 19:06:27 +00:00
f1d49a285d fix: remove interim text display and set typing delay to zero in STTButton
The diff modifies two key behaviors in the speech-to-text button component. First, the typing simulation delay parameter is changed from 1 to 0 in the `simulateTypingWithEvents` call within the finalize path, eliminating artificial typing delay when inserting punctuated text. Second, the interim speech recognition handling is refactored: instead of displaying interim text in the input field, both contenteditable and regular input elements now clear the previous interim text by setting their value to an empty string, while the commented-out `simulateTypingWithEvents` call for interim text is uncommented and activated to handle interim updates through the typing simulation mechanism instead of direct value assignment.
2025-06-29 19:03:33 +00:00
4ac19ef558 chore: refactor STTButton event handling and CSS formatting in stt.js 2025-06-29 18:56:44 +00:00
1ec7ac8327 chore: fix indentation and formatting in STTButton simulateTypingWithEvents method 2025-06-29 18:34:25 +00:00
4d908acac0 feat: conditionally skip TTS speech when speaker is disabled in web UI
Add a check for the `snek-speaker` element's enabled state before calling `speak()`. When the speaker is disabled, fall back to playing the message sound instead of attempting speech synthesis. This prevents silent failures and ensures consistent audio feedback based on user preference.
2025-06-29 18:16:15 +00:00
09fdaeb45f feat: add SnekSpeaker custom element with speech synthesis toggle and voice selection
Introduce a new `snek-speaker` web component that wraps the Web Speech API. The element provides `speak()`, `toggle()`, `stop()`, and `enable()`/`disable()` methods, along with an `enabled` property. Voice selection defaults to the first male English voice found, with asynchronous voice loading handled via the `onvoiceschanged` event.
2025-06-29 18:08:13 +00:00
3708156acf feat: integrate TTS playback and wire snek-speaker into chat input and message flow
Add snek-speaker element to chat-input.js, attach click handler on ttsButton to enable speaker, and include tts.js module in app.html. In web.html, trigger snek-speaker.speak() on final channel messages to enable text-to-speech output for incoming messages.
2025-06-29 17:58:40 +00:00
e047e5ecb3 feat: make simulateTypingWithEvents return a promise and finalize chat message after typing
Refactor simulateTypingWithEvents to return a Promise that resolves when typing completes, enabling callers to chain actions after the typing simulation finishes. Update the speech recognition result handler to await this promise and call finalizeMessage() on the chat-input element, replacing the previous triggerEvent('keyup', "Enter") approach. Also add line breaks after punctuation in the committed text before typing simulation.
2025-06-29 15:39:32 +00:00
2c6a3ddf00 feat: add youtube shorts support and refactor embed metadata extraction
Add "/shorts" path to allowed YouTube URL patterns in embed_youtube function. Extract metadata retrieval logic into reusable get_element_options helper that queries twitter, ograph, meta, and element tags from head_info with fallback priority.
2025-06-29 14:24:33 +00:00
735abf80d0 feat: add login_required flag to views and fix BaseService.get uid handling
Add `login_required = True` to ChannelDriveApiView, ChannelAttachmentView, ChannelAttachmentUploadView, ChannelView, ContainerView, DriveView, BareRepoNavigator, StatsView, StatusView, ThreadsView, UploadView, and UserView to enforce authentication on these endpoints. Set `login_required = False` on RegisterFormView to allow unauthenticated registration. Refactor `BaseService.get` to accept positional args for uid and only filter deleted_at when not explicitly provided. Remove the deprecated `DriveView222` class entirely.
2025-06-29 14:19:53 +00:00
f8bd028569 fix: replace Enter keydown with keyup and reduce typing delay to 1ms in stt.js 2025-06-28 22:12:07 +00:00
fa50562726 feat: add simulateTypingWithEvents method and fix punctuation insertion in STTButton 2025-06-28 22:04:42 +00:00
93ceda2286 fix: scope image src extraction to text container in message rendering
The previous implementation incorrectly queried all images within the entire message div, causing duplicate or out-of-context image source concatenation. This change restricts the querySelectorAll to only images nested inside the `.text` element, ensuring each message's image sources are appended exactly once and only from the relevant content area.
2025-06-27 15:38:35 +00:00
02945616e0 feat: strip markdown image syntax from replied image URLs in web template
Remove the '![Replied image]()' wrapper around image sources when constructing reply text in the web chat template, leaving only the raw URL to prevent broken markdown rendering in non-markdown contexts.
2025-06-27 15:36:27 +00:00
e5ca3df33e feat: add image source to reply text when generating reply link in web template 2025-06-27 15:33:23 +00:00
BordedDev
0eeec72acb feat: add /shorts path support to youtube embed url detection
Extend the allowed path prefixes in embed_youtube to include "/shorts",
enabling embedding of YouTube Shorts videos alongside regular watch and
embed URLs.
2025-06-27 10:10:16 +00:00
aaf6b7241d fix: replace activeElement target with textarea query for speech-to-text input
The speech-to-text component previously used `document.activeElement` to determine the target element for transcription output, which failed when no input was focused. Changed the `targetEl` getter to query for a `textarea` element instead, ensuring consistent target availability. Also updated the DOM update logic to call `.focus()` on the target and assign directly to `.value` instead of using `setAttribute("value", ...)`, enabling proper text insertion into the textarea.
2025-06-25 20:46:07 +00:00
9dbbcccf15 feat: add speech-to-text button component and integrate into chat input
- Create new STTButton web component in src/snek/static/stt.js with shadow DOM, speech recognition API integration, and pulsing visual feedback during listening state
- Add stt.js script import to app.html template to register the custom element globally
- Instantiate and append stt-button element inside ChatInputComponent constructor in chat-input.js
- Add CSS class "chat-input-textarea" to the textarea element for styling hooks
- Attach change event listener on textarea to sync value and trigger updateFromInput on manual edits
2025-06-25 20:41:55 +00:00
564362ead9 fix: remove no_save context and simplify message update validation in RPCView
The update_message_text method in RPCView was refactored to remove the no_save context wrapper and streamline validation logic. The commented-out time-based restriction check was also removed, allowing message updates without the previous 8-second window limitation.
2025-06-25 19:38:26 +00:00
75e658d310 feat: add unique uid index to channel_message and remove time-limit check in RPC message update
Add a unique index on the `uid` field in the `channel_message` collection to enforce document uniqueness at the database level. In the RPC message update handler, remove the 8-second time-limit check and instead validate that the message is not marked as final or deleted before allowing edits.
2025-06-25 19:23:31 +00:00
9fdda81fcc feat: add composite and single-field indexes to channel_message collection on save
Add lazy index creation for `['is_final','user_uid','channel_uid']` and `['deleted_at']` fields in `ChannelMessageService.save()` method, guarded by a `_configured_indexes` flag to ensure indexes are created only once per service instance.
2025-06-25 19:17:37 +00:00
8b8d5ac862 fix: filter out deleted and finalized messages in RPC message retrieval
- Added `deleted_at=None` filter to `check_message` query in `send_message` to exclude soft-deleted messages from finalization queue
- Added `is_final=False` and `deleted_at=None` filters to `get_message` in `update_message` to prevent editing finalized or deleted messages
- Added early return with error response when message is not found after applying new filters
- Added conditional finalization logic: only queue finalization for non-final messages, cancel existing finalization task for already final messages
2025-06-25 18:59:22 +00:00
9e5fd33927 fix: replace fixed 7-second sleep with cancellable per-second loop in _finalize_message_task
The previous implementation used a single `await asyncio.sleep(7)` which could not be interrupted
mid-wait when the finalize task was cancelled. The new approach loops 7 times with 1-second sleeps,
checking `self._finalize_task` after each second and returning early if the task reference is cleared,
plus catching `CancelledError` to handle explicit cancellation gracefully.
2025-06-25 16:22:16 +00:00
45d8707fe7 fix: add early return guard for empty message in RPCView message handler
When message is empty after processing check messages, the handler now returns early
instead of proceeding to send an empty message through the chat service. This prevents
unnecessary API calls and potential errors from sending blank content.
2025-06-25 16:11:16 +00:00
0c3474da05 fix: replace scrollTop assignment with scrollIntoView and fix empty message display logic
- Comment out direct scrollTop assignment in scrollToBottom method and use scrollIntoView on the bottom anchor element instead
- Change display toggle from messageDiv to textElement in updateMessage to correctly hide empty text content while preserving message container layout
2025-06-25 16:07:11 +00:00
dbb219e469 fix: correct empty message hiding logic and improve message finalization flow
- Move display toggle from textElement to messageDiv in message-list.js to properly hide entire message container when text is empty
- Remove is_final=False filter in _finalize_message_task to allow retrieval of already finalized messages
- Add early return when message is already finalized to prevent duplicate finalization attempts
- Strip whitespace from incoming message in send_message to handle empty/whitespace-only inputs
- Remove unused variable assignment for is_final in send_message non-final branch
2025-06-25 15:54:12 +00:00
ee2ede2e2d fix: invert live-type attribute check and remove expiry timer from chat input
Remove the unused `expiryTimer` property and its related clearTimeout calls from ChatInputComponent. Fix the `liveType` boolean assignment by changing the comparison operator from `!==` to `==` so that the attribute value `"true"` correctly enables live typing behavior. Make `finalizeMessage` synchronous by removing the `await` keyword from the RPC call and the method declaration. Remove the early return guard for empty message values in `sendMessage` to allow empty strings to be sent. Add server-side logic for finalizing messages after a 7-second delay via a new `_finalize_message_task` coroutine, with cancellation support through `_queue_finalize_message`. Re-enable the previously commented-out logic in `send_message` that checks for an existing non-final message from the same user and updates it instead of creating a new one.
2025-06-25 15:31:49 +00:00
ca62f75042 feat: add /leet and /l33t commands with text-to-leet conversion in chat input 2025-06-25 07:10:27 +00:00
BordedDev
328c2d840c fix: replace global eventBus with component subscription and fix file attachment URL building 2025-06-22 22:41:09 +00:00
fe7568336b fix: update signup button link from /register to /register.html
The href attribute of the "Sign Up" anchor element in the index.html template was changed from "/register" to "/register.html" to align with the static HTML routing convention used elsewhere on the site, ensuring consistent URL resolution for the registration page.
2025-06-21 21:48:52 +00:00
79babcc294 feat: add music.youtube.com to embed hostnames and skip links with data-noembed attribute
- Extend embed_youtube hostname check to include music.youtube.com subdomain
- Skip anchor elements containing data-noembed attribute in embed_url to prevent unwanted embedding
2025-06-19 12:37:17 +00:00
e283bf1302 feat: add history_start field to channel model and implement channel clear method with no_save context manager 2025-06-19 07:33:17 +00:00
BordedDev
90971bcb20 chore: remove title from SAFE_ATTRIBUTES set in template.py
The title attribute was removed from the SAFE_ATTRIBUTES dictionary
in src/snek/system/template.py, likely to tighten security by
preventing arbitrary title attributes in sanitized HTML output.
2025-06-19 07:33:05 +00:00
BordedDev
96f0c09cda fix: add target, rel, referrerpolicy, controls, frameborder, allow, allowfullscreen, and title to SAFE_ATTRIBUTES whitelist in template.py
Also fix string interpolation syntax in embed_url function where double quotes were incorrectly nested inside f-string, changing outer quotes from double to single to resolve syntax error.
2025-06-19 07:30:33 +00:00
BordedDev
deb7a84082 feat: add get_element_options helper and improve embed dedup with height/width support
Extract repeated meta-tag lookup logic into reusable get_element_options function that accepts fallback priority chain (twitter, og, meta, elem). Enhance embed_url to skip already-processed URLs via attachment key check, and extend embed payload with optional height/width attributes from og:image:width/height or twitter:image:width/height. Refine site name selection to prefer og:site_name over twitter:site, falling back to title tag.
2025-06-19 07:10:31 +00:00
35023a47c4 feat: add history_start filter to channel queries and implement no_save context manager for draft messages
Add `history_start` field to ChannelModel to support filtering messages by creation date, implement `clear` method in ChannelService to set history cutoff, and introduce `no_save` async context manager in Application that patches channel_message save to only update cache. Refactor ChatService to reuse existing non-final messages when updating drafts, and fix UserService search to filter out deleted users.
2025-06-19 06:23:14 +00:00
BordedDev
79528abcb5 feat: add music.youtube.com to allowed hosts and skip links with data-noembed attribute
Extend the embed_youtube function's hostname whitelist to include "music.youtube.com" for YouTube Music URL support. Also update embed_url to skip anchor elements that have a "data-noembed" attribute, preventing unwanted embedding of explicitly excluded links.
2025-06-19 06:11:27 +00:00