### Install Dependencies and Setup Environment Source: https://github.com/fanout/django-eventstream/blob/master/examples/time/README.md Installs necessary Python packages, sets up a virtual environment, and prepares the Django project. Ensure you have Python 3 installed. ```sh virtualenv --python=python3 venv . venv/bin/activate pip install -r requirements.txt touch .env python manage.py migrate ``` -------------------------------- ### Start Chat Client Web Server Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat-restframework/README.md Starts a simple HTTP server to serve the chat client files on port 9000. Access the chat application by opening http://localhost:9000/ in your browser. ```sh python -m http.server 9000 ``` -------------------------------- ### HTTP GET Request Example Source: https://github.com/fanout/django-eventstream/blob/master/README.md Example of an HTTP GET request from a client to an EventStream endpoint. ```http GET /events/ HTTP/1.1 Host: example.com Accept: text/event-stream ``` -------------------------------- ### Install Django EventStream and Daphne Source: https://github.com/fanout/django-eventstream/blob/master/README.md Install the necessary packages for Django EventStream and the Daphne ASGI server. ```sh pip install django-eventstream daphne ``` -------------------------------- ### Run with Pushpin Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat/README.md Starts Pushpin with routing rules and then runs the Django development server. Access the application via http://localhost:7999/. ```sh pushpin --route="* localhost:8000" ``` ```sh python manage.py runserver ``` -------------------------------- ### Install redis module Source: https://github.com/fanout/django-eventstream/blob/master/README.md Install the redis module using pip. This is required for Redis integration. ```sh pip install redis ``` -------------------------------- ### Run with Fanout Cloud and Ngrok Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat/README.md Starts the development server with ngrok for local tunneling to Fanout Cloud. This command automatically configures ngrok as the origin server. ```sh ngrok http 8000 ``` ```sh python manage.py runserver_ngrok ``` -------------------------------- ### Run Django Development Server Source: https://github.com/fanout/django-eventstream/blob/master/examples/time/README.md Starts the Django development server to serve the application. Access the stream via http://localhost:8000/ in your browser. ```sh python manage.py runserver ``` -------------------------------- ### Nginx configuration for Pushpin Source: https://github.com/fanout/django-eventstream/blob/master/README.md Example Nginx configuration to forward requests to Pushpin. This setup assumes Pushpin is running on port 7999. ```nginx location /api/ { proxy_pass http://localhost:7999 } ``` -------------------------------- ### HTTP Server-Sent Events Response Example Source: https://github.com/fanout/django-eventstream/blob/master/README.md Example of a streaming HTTP response with Server-Sent Events content. ```http HTTP/1.1 200 OK Transfer-Encoding: chunked Connection: Transfer-Encoding Content-Type: text/event-stream event: message data: {"foo": "bar"} event: message data: {"bar": "baz"} ... ``` -------------------------------- ### Install Django EventStream with DRF Support Source: https://github.com/fanout/django-eventstream/blob/master/README.md Install Django EventStream with optional dependencies for Django REST Framework support. ```sh pip install django-eventstream[drf] daphne ``` -------------------------------- ### Get Events Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat-restframework/README.md Establishes a Server-Sent Events (SSE) stream for real-time updates in a chat room. ```APIDOC ## GET /rooms/{room-id}/events/ ### Description Establishes a Server-Sent Events (SSE) stream for real-time updates in a chat room. ### Method GET ### Endpoint /rooms/{room-id}/events/ ### Parameters #### Path Parameters - **room-id** (string) - Required - The ID of the chat room. ### Response #### Success Response (200) - **SSE Stream** - A stream of events. ### Response Example (This endpoint returns a stream of Server-Sent Events, not a JSON object. Example event format): `event: message data: {"user": "Charlie", "text": "Real-time update!", "room": "general"} ` ``` -------------------------------- ### Get Events Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat/README.md Establishes a Server-Sent Events (SSE) stream to receive real-time chat events. ```APIDOC ## GET /rooms/{room-id}/events/ ### Description Establishes a Server-Sent Events (SSE) stream to receive real-time chat events for a specific room. You can optionally specify an event ID to start reading from. ### Method GET ### Endpoint /rooms/{room-id}/events/ ### Parameters #### Path Parameters - **room-id** (string) - Required - The ID of the chat room. #### Query Parameters - **lastEventId** (string) - Optional - The event ID to start reading events from. If not provided, the stream starts from the most recent events. ### Response #### Success Response (200) - Returns a Server-Sent Events (SSE) stream. Each event in the stream represents a chat message or other relevant activity. #### Response Example (SSE Stream Format) ``` id: event-id-4 data: {"from": "user3", "text": "New message incoming!", "timestamp": "2023-10-27T10:10:00Z"} ``` ``` -------------------------------- ### Send Event using send_event Source: https://github.com/fanout/django-eventstream/blob/master/README.md Example of sending a custom event to a specified channel with event data. The data is JSON-encoded. ```python from django_eventstream import send_event # send_event(, , ) send_event("test", "message", {"text": "hello world"}) ``` -------------------------------- ### Django URL Routes for EventStream Channels Source: https://github.com/fanout/django-eventstream/blob/master/README.md Configure Django URL patterns to include event stream channels. Examples show fixed channel lists, dynamic channels based on view keywords, and client-side channel selection via URL path or query parameters. ```python from django.urls import path, include import django_eventstream # specify fixed list of channels path('foo/events/', include(django_eventstream.urls), {'channels': ['foo']}) ``` ```python # specify a list of dynamic channels using formatting based on view keywords path('objects//events/', include(django_eventstream.urls), {'format-channels': ['object-{obj_id}']}) ``` ```python # client selects a single channel using a path component path('events//', include(django_eventstream.urls)) ``` ```python # client selects one or more channels using query parameters path('events/', include(django_eventstream.urls)) ``` -------------------------------- ### Get Past Messages Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat-restframework/README.md Retrieves a list of past messages for a specified chat room. ```APIDOC ## GET /rooms/{room-id}/messages/ ### Description Retrieves a list of past messages for a specified chat room. ### Method GET ### Endpoint /rooms/{room-id}/messages/ ### Parameters #### Path Parameters - **room-id** (string) - Required - The ID of the chat room. ### Response #### Success Response (200) - **messages** (array) - A list of message objects. - **user** (string) - The name of the user who sent the message. - **text** (string) - The content of the message. - **room** (string) - The ID of the room the message belongs to. #### Response Example { "messages": [ { "user": "Alice", "text": "Hello!", "room": "general" } ] } ``` -------------------------------- ### Get Past Messages Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat/README.md Retrieves a list of the most recent messages for a given chat room. ```APIDOC ## GET /rooms/{room-id}/messages/ ### Description Retrieves a list of the most recent messages for a given chat room, ordered by time in descending order. ### Method GET ### Endpoint /rooms/{room-id}/messages/ ### Parameters #### Path Parameters - **room-id** (string) - Required - The ID of the chat room. ### Response #### Success Response (200) - **messages** (array) - A list of the most recent messages. - **last-event-id** (string) - The ID of the last event, useful for subsequent event fetching. #### Response Example ```json { "messages": [ { "id": "event-id-1", "from": "user1", "text": "Hello!", "timestamp": "2023-10-27T10:00:00Z" }, { "id": "event-id-2", "from": "user2", "text": "Hi there!", "timestamp": "2023-10-27T10:01:00Z" } ], "last-event-id": "event-id-2" } ``` ``` -------------------------------- ### Register event viewsets with DRF router Source: https://github.com/fanout/django-eventstream/blob/master/README.md Register event viewsets with a Django REST Framework router. This example shows registration by both function and class. ```python from django.urls import path, include from django_eventstream.viewsets import EventsViewSet, configure_events_view_set router = DefaultRouter() # register by function router.register( "events1", configure_events_view_set(channels=["channel1", "channel2"], messages_types=["message", "info"]), basename="events1") # register by class router.register( "events2", EventsViewSet(channels=["channel1", "channel2"]), basename="events2") urlpatterns = [ ... path("", include(router.urls)), ] ``` -------------------------------- ### Custom Channel Manager Authorization Source: https://github.com/fanout/django-eventstream/blob/master/README.md Implement a custom channel manager to define authorization logic for reading channels. This example requires authentication for channels prefixed with '_'. ```python from django_eventstream.channelmanager import DefaultChannelManager class MyChannelManager(DefaultChannelManager): def can_read_channel(self, user, channel): # require auth for prefixed channels if channel.startswith('_') and user is None: return False return True ``` ```python EVENTSTREAM_CHANNELMANAGER_CLASS = 'myapp.channelmanager.MyChannelManager' ``` -------------------------------- ### Run Django REST API Server Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat-restframework/README.md Starts the Django REST API server on all available network interfaces, port 8000. This server handles chat messages and events. ```sh python manage.py runserver 0.0.0.0:8000 ``` -------------------------------- ### Get Chat Events Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat-restframework/README.md Retrieves a Server-Sent Events (SSE) stream for a specific chat room. This stream provides real-time updates for the room. ```http GET /rooms/{room-id}/events/ ``` -------------------------------- ### Get Past Chat Messages Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat-restframework/README.md Retrieves a list of past messages for a specific chat room. This endpoint returns a JSON object containing the messages. ```http GET /rooms/{room-id}/messages/ ``` -------------------------------- ### Deploy with Daphne ASGI Server Source: https://github.com/fanout/django-eventstream/blob/master/README.md Launch an ASGI server like Daphne for production deployment instead of Django's development server. ```sh daphne your_project.asgi:application ``` -------------------------------- ### Configure Fanout Cloud Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat/README.md Sets the GRIP_URL environment variable for integration with Fanout Cloud. Replace placeholders with your actual realm ID and key. ```sh GRIP_URL=https://api.fanout.io/realm/{realm-id}?iss={realm-id}&key=base64:{realm-key} ``` -------------------------------- ### Configure GripMiddleware and GRIP_URL Source: https://github.com/fanout/django-eventstream/blob/master/README.md Add GripMiddleware to your Django settings and set the GRIP_URL to reference Pushpin's private control port. This is necessary for Pushpin integration. ```python MIDDLEWARE = [ "django_grip.GripMiddleware", ... ] ``` ```python GRIP_URL = 'http://localhost:5561' ``` -------------------------------- ### Configure Pushpin Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat/README.md Sets the GRIP_URL environment variable for integration with Pushpin. Ensure Pushpin is running and configured to route requests. ```sh GRIP_URL=http://localhost:5561 ``` -------------------------------- ### Initialize Chat Application with EventStream Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat-restframework/chat-client/index.html This script initializes the chat application by dynamically loading necessary CSS and JavaScript files. It sets up event listeners for joining a chat room, including fetching available rooms and handling user nickname input. Ensure jQuery is loaded before this script. ```javascript document.addEventListener('DOMContentLoaded', function() { var hostname = window.location.hostname; var port8000 = ':8000'; var port9000 = ':9000'; var link = document.createElement('link'); link.rel = 'stylesheet'; link.href = `http://${hostname}${port8000}/static/rest_framework/css/bootstrap.min.css `; document.head.appendChild(link); var script = document.createElement('script'); script.src = `http://${hostname}${port9000}/static/js/jquery-3.2.1.min.js `; script.onload = function() { $(function () { var baseUrl = `http://${window.location.hostname}:8000 `; $.get( `${baseUrl}/rooms/ `, function(data) { if (data.length === 0) { $.post( `${baseUrl}/rooms/ `, {eid: 'general'}, function(data) { $('#room-select').append( ` `); }); } data.forEach(function(room) { $('#room-select').append( ` `); }); }); $('#join-button').on('click', function () { var user = $('#nick-input').val(); var roomID = $('#room-select').val(); if(user && roomID) { sessionStorage.setItem('user', user); sessionStorage.setItem('roomID', roomID); window.location = '/chat.html'; } }); $('#nick-input').focus(); }); }; document.head.appendChild(script); }); ``` -------------------------------- ### Run database migrations for event storage Source: https://github.com/fanout/django-eventstream/blob/master/README.md Run Django migrations to set up the necessary database tables for event storage. This is required before enabling event persistence. ```sh python manage.py migrate ``` -------------------------------- ### Add Django EventStream Apps to settings.py Source: https://github.com/fanout/django-eventstream/blob/master/README.md Configure Django settings to include the 'daphne' and 'django_eventstream' applications. ```python INSTALLED_APPS = [ ... "daphne", "django_eventstream", ] ``` -------------------------------- ### Configure ASGI Application in settings.py Source: https://github.com/fanout/django-eventstream/blob/master/README.md Set the ASGI_APPLICATION setting in Django's settings.py to point to your project's ASGI application. ```python ASGI_APPLICATION = "your_project.asgi.application" ``` -------------------------------- ### Configure Pushpin routes Source: https://github.com/fanout/django-eventstream/blob/master/README.md Configure Pushpin's routes file to direct requests to your Django application. Replace localhost:8000 with your app's actual host and port. ```conf * localhost:8000 ``` -------------------------------- ### Listen for events in the browser Source: https://github.com/fanout/django-eventstream/blob/master/README.md Use ReconnectingEventSource to establish a connection and listen for 'message' and 'stream-reset' events in the browser. The '/events/' path is the default endpoint. ```javascript var es = new ReconnectingEventSource('/events/'); es.addEventListener('message', function (e) { console.log(e.data); }, false); es.addEventListener('stream-reset', function (e) { // ... client fell behind, reinitialize ... }, false); ``` -------------------------------- ### Include client libraries for browser reception Source: https://github.com/fanout/django-eventstream/blob/master/README.md Include the provided JavaScript client libraries in your frontend HTML to enable receiving Server-Sent Events (SSE). ```html ``` -------------------------------- ### Initialize Chat Application and Load Messages Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat-restframework/chat-client/chat.html This JavaScript code initializes the chat application by setting up event listeners, loading historical messages, and establishing a connection to the event stream. It requires jQuery and several JavaScript libraries for EventSource functionality. ```javascript document.addEventListener('DOMContentLoaded', function () { var hostname = window.location.hostname; var port8000 = ':8000'; var port9000 = ':9000'; var bootstrapCSS = document.createElement('link'); bootstrapCSS.rel = 'stylesheet'; bootstrapCSS.href = `http://${hostname}${port8000}/static/rest_framework/css/bootstrap.min.css`; document.head.appendChild(bootstrapCSS); var jQueryScript = document.createElement('script'); jQueryScript.src = `http://${hostname}${port9000}/static/js/jquery-3.2.1.min.js`; jQueryScript.onload = function() { executeJQueryDependentCode(); }; document.head.appendChild(jQueryScript); var scripts = [ '/static/django_eventstream/json2.js', '/static/django_eventstream/eventsource.min.js', '/static/django_eventstream/reconnecting-eventsource.js' ]; scripts.forEach(function(path) { var script = document.createElement('script'); script.src = `http://${hostname}${port8000}${path}`; document.head.appendChild(script); }); }); function executeJQueryDependentCode() { $(function () { var user = sessionStorage.getItem('user'); var roomID = sessionStorage.getItem('roomID'); var baseUrl = `http://${window.location.hostname}:8000`; if (user == null || roomID == null) { window.location.href = `http://${window.location.hostname}:9000/`; } function loadOldMessages() { $.ajax({ type: "GET", url: `${baseUrl}/rooms/${roomID}/messages/`, success: function(data) { data.forEach(function(message) { addMessage(`${message.user}: ${message.text}`); }); }, error: function() { alert('Erreur lors de la récupération des messages.'); } }); } loadOldMessages(); $('#user-label').text(user || 'Anonyme'); $('#room-label').text('#' + (roomID || 'defaultRoom')); var es = new ReconnectingEventSource(`${baseUrl}/rooms/${encodeURIComponent(roomID)}/events/`); es.onmessage = function(event) { var data = JSON.parse(event.data); var messageContent = `
${data.from}: ${data.text}
`; $('#chat-log').append(messageContent); }; es.onerror = function() { console.log('Erreur de connexion au stream des événements.'); }; $('#send-form').submit(function(e) { e.preventDefault(); var messageText = $('#chat-input').val(); if (messageText.length > 0) { $.ajax({ type: "POST", url: `${baseUrl}/rooms/${roomID}/messages/`, data: JSON.stringify({ user: user, text: messageText, room: roomID }), contentType: "application/json", success: function() { $('#chat-input').val(''); }, error: function() { alert('Erreur lors de l\'envoi du message.'); } }); } }); function addMessage(message) { var log = $('#chat-log'); log.append(`
${message}
`); log.scrollTop(log.prop('scrollHeight')); } }); } ``` -------------------------------- ### Configure Redis in settings.py Source: https://github.com/fanout/django-eventstream/blob/master/README.md Configure the Redis connection details in your Django settings.py file. This enables the send_event function to use Redis for event publishing. ```python EVENTSTREAM_REDIS = { 'host': 'redis', 'port': 6379, 'db': 0, } ``` -------------------------------- ### Configure event storage class Source: https://github.com/fanout/django-eventstream/blob/master/README.md Set the EVENTSTREAM_STORAGE_CLASS in settings.py to 'django_eventstream.storage.DjangoModelStorage' to enable event persistence. Events will be stored in the database for 24 hours. ```python EVENTSTREAM_STORAGE_CLASS = 'django_eventstream.storage.DjangoModelStorage' ``` -------------------------------- ### Initialize ReconnectingEventSource Source: https://github.com/fanout/django-eventstream/blob/master/examples/time/timeapp/templates/timeapp/home.html Connects to the event stream using ReconnectingEventSource. Handles initial connection and reconnection logic. Use this to establish a connection to the server-sent events. ```javascript var logMessage = function (s) { var outputDiv = document.getElementById('output'); outputDiv.innerHTML = outputDiv.innerHTML + s + '
'; }; var start = function () { logMessage('connecting...'); {% if last_id %} var es = new ReconnectingEventSource('{{ url|safe }}', { lastEventId: '{{ last_id }}' }); {% else %} var es = new ReconnectingEventSource('{{ url|safe }}'); {% endif %} es.onopen = function () { logMessage('connected'); }; es.onerror = function () { logMessage('connection error'); }; es.addEventListener('stream-reset', function (e) { e = JSON.parse(e.data); logMessage('stream reset: ' + JSON.stringify(e.channels)); }, false); es.addEventListener('stream-error', function (e) { // hard stop es.close(); e = JSON.parse(e.data); logMessage('stream error: ' + e.condition + ': ' + e.text); }, false); es.addEventListener('message', function (e) { logMessage('message: ' + e.data); }, false); }; ``` -------------------------------- ### Configure DRF renderers for EventStream Source: https://github.com/fanout/django-eventstream/blob/master/README.md Set DEFAULT_RENDERER_CLASSES in settings.py to include SSEEventRenderer and optionally BrowsableAPIEventStreamRenderer. Ensure they are placed after JSONRenderer and BrowsableAPIRenderer. ```python REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': [ 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', 'django_eventstream.renderers.SSEEventRenderer', 'django_eventstream.renderers.BrowsableAPIEventStreamRenderer' # Add other renderers as needed ] } ``` -------------------------------- ### Join Room Form Submission Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat/chat/templates/chat/join.html Handles the submission of the join form. Redirects to the room URL with the user's name. Ensure the user input is not empty before redirecting. ```html {% load static %} {% block content %}
{% endblock %} {% block extra_js %} {% endblock %} ``` -------------------------------- ### Send Message Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat/README.md Sends a new message to a specified chat room. ```APIDOC ## POST /rooms/{room-id}/messages/ ### Description Sends a new message to a specified chat room. ### Method POST ### Endpoint /rooms/{room-id}/messages/ ### Parameters #### Path Parameters - **room-id** (string) - Required - The ID of the chat room. #### Query Parameters - **from** (string) - Required - The name of the user sending the message. - **text** (string) - Required - The content of the message. ### Response #### Success Response (200) - Returns a JSON object representing the sent message. #### Response Example ```json { "id": "event-id-3", "from": "user1", "text": "This is a new message.", "timestamp": "2023-10-27T10:05:00Z" } ``` ``` -------------------------------- ### Send Message Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat-restframework/README.md Sends a new message to a specified chat room. ```APIDOC ## POST /rooms/{room-id}/messages/ ### Description Sends a new message to a specified chat room. ### Method POST ### Endpoint /rooms/{room-id}/messages/ ### Parameters #### Path Parameters - **room-id** (string) - Required - The ID of the chat room. #### Query Parameters - **user** (string) - Required - The name of the user sending the message. - **text** (string) - Required - The content of the message. - **room** (string) - Required - The room ID. ### Response #### Success Response (200) - **message** (object) - The message object that was sent. - **user** (string) - The name of the user who sent the message. - **text** (string) - The content of the message. - **room** (string) - The ID of the room the message belongs to. #### Response Example { "message": { "user": "Bob", "text": "Hi Alice!", "room": "general" } } ``` -------------------------------- ### Django Template for Chat Interface Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat/chat/templates/chat/chat.html This Django template renders the chat interface, including message display and input fields. It loads static files and iterates over existing messages. ```django {% load static %} Chat {{ user }} #{{ room_id }} [code](https://github.com/fanout/django-eventstream/tree/master/examples/chat) {% for msg in messages %} **{{ msg.from }}**: {{ msg.text }} {% endfor %} ``` -------------------------------- ### CORS Headers Configuration Source: https://github.com/fanout/django-eventstream/blob/master/README.md Configure Cross-Origin Resource Sharing (CORS) headers using Django settings. `EVENTSTREAM_ALLOW_HEADERS` accepts only a single string value. ```python EVENTSTREAM_ALLOW_ORIGINS = ['http://example.com', 'https://example.com'] ``` ```python EVENTSTREAM_ALLOW_CREDENTIALS = True ``` ```python EVENTSTREAM_ALLOW_HEADERS = 'Authorization' ``` -------------------------------- ### JavaScript for Real-time Chat Functionality Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat/chat/templates/chat/chat.html This JavaScript code handles the real-time aspects of the chat, including connecting to the event stream, displaying new messages, and sending messages. It uses ReconnectingEventSource for robust connections. ```javascript var msg_ids = [{% for msg in messages %}{% if not forloop.first %},{% endif %}{{ msg.id }}{% endfor %}]; var escapeHtml = function (s) { var tagsToReplace = { '&': '&', '<': '<', '>': '>' }; return s.replace(/[\[&<>]]/g, function(tag) { return tagsToReplace[tag] || tag; }); }; var scrollToBottom = function (e) { e.scrollTop(e.height()); $('html, body').scrollTop($('#chat-elements').height()); }; var tryScrollToBottom = function (e, threshold) { var el = e.get(0); if(el.scrollTop + el.clientHeight + threshold > el.scrollHeight) { scrollToBottom(e); } }; var appendLog = function (s) { var log = $('#chat-log'); log.append(s + '
'); tryScrollToBottom($('#chat-elements'), 50); }; var startChat = function (user) { console.log('user=[' + user + ']'); // smooth scroll should be off when this first scroll is called scrollToBottom($('#chat-elements')); $('html, body').scrollTop($('#chat-elements').height()); // now we can turn it on $('#chat-elements').css('scroll-behavior', 'smooth'); var uri = '/rooms/' + encodeURIComponent('{{ room_id }}') + '/events/'; var es = new ReconnectingEventSource(uri, { lastEventId: '{{ last_id }}' }); var firstConnect = true; es.onopen = function () { if(!firstConnect) { appendLog('*** connected'); } firstConnect = false; }; es.onerror = function () { appendLog('*** connection lost, reconnecting...'); }; es.addEventListener('stream-reset', function () { appendLog('*** client too far behind, please refresh'); }, false); es.addEventListener('stream-error', function (e) { // hard stop es.close(); e = JSON.parse(e.data); appendLog('*** stream error: ' + e.condition + ': ' + e.text); }, false); es.addEventListener('message', function (e) { console.log('event: ' + e.data); msg = JSON.parse(e.data); // if an event arrives that was already in the initial pageload, // ignore it if($.inArray(msg.id, msg_ids) != -1) { return; } appendLog('' + escapeHtml(msg.from) + ': ' + escapeHtml(msg.text)); }, false); $('#send-form').submit(function () { var text = $('#chat-input').val(); if(text.length == 0) { return false } $('#chat-input').attr('disabled', 'true'); $('#chat-send-button').attr('disabled', 'true'); $('#chat-send-button').text('Sending...'); $.post('/rooms/{{ room_id }}/messages/', { from: user, text: text } ).done(function (data) { $('#chat-input').val(''); console.log('send response: ' + JSON.stringify(data)); }).fail(function () { alert('failed to send message'); }).always(function () { $('#chat-input').removeAttr('disabled'); $('#chat-input').focus(); $('#chat-send-button').text('Send'); $('#chat-send-button').removeAttr('disabled'); }); return false; }); $('#chat-input').focus(); }; $(function () { startChat('{{ user|escapejs }}'); }); ``` -------------------------------- ### Include EventStream URLs in urls.py Source: https://github.com/fanout/django-eventstream/blob/master/README.md Add the Django EventStream URLs to your project's urls.py, specifying the channels to use. ```python from django.urls import path, include import django_eventstream urlpatterns = [ ... path("events/", include(django_eventstream.urls), {"channels": ["test"]}), ] ``` -------------------------------- ### Notify Channel Permission Changes Source: https://github.com/fanout/django-eventstream/blob/master/README.md Call `channel_permission_changed` to disconnect clients if their permissions for a channel have changed. Ensure the user and channel are correctly specified. ```python from django_eventstream import channel_permission_changed channel_permission_changed(user, '_mychannel') ``` -------------------------------- ### Send Chat Message Source: https://github.com/fanout/django-eventstream/blob/master/examples/chat-restframework/README.md Sends a new message to a specific chat room. Requires parameters for the user, message text, and room ID. Returns a JSON object of the sent message. ```http POST /rooms/{room-id}/messages/ ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.