# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
def subscribed
# Subscribe to a specific room
room = Room.find(params[:room_id])
<%# Append is also broadcast from the model; this response scrolls the author's view %>
<%= turbo_stream.append "messages" do %>
<%= render partial: "messages/message", locals: { message: @message } %>
<% end %>
<turbo-stream action="scroll_to" target="<%= dom_id(@message) %>" behavior="smooth" block="end">
const { WebSocketServer } = require('ws');
const crypto = require('crypto');
const wss = new WebSocketServer({ port: 8080 });
function broadcast(payload, except) {
import { startOfDay, isToday, isYesterday, format } from 'date-fns';
export interface ChatMessage {
id: string;
senderId: string;
senderName: string;
class TypingPresence
EXPIRE_AFTER = 6 # seconds
def initialize(room, redis: Redis.current)
@room = room
@redis = redis
import asyncio
from collections import defaultdict
from fastapi import WebSocket
<?php
use App\Models\Conversation;
use App\Models\User;
use Illuminate\Support\Facades\Broadcast;