Unable to make websocket connection in django - python

I am trying to make a websocket connection
I am using the django's channels API.
For some reason the handshaking is not taking place. Maybe it has something to do with the url?
This is my main routing.py file
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter,URLRouter
import chat.routing
application = ProtocolTypeRouter({
'websocket':AuthMiddlewareStack(
URLRouter(
chat.routing.websocket_urlpatterns
)
),
})
This is my chat app routing.py
from django.urls import re_path,path
# from django.conf.urls import url
from . import consumers
websocket_urlpatterns = [
re_path(r'ws/chat/room/(?P<room_name>\w+)/(?P<username>\w+)/$',consumers.ChatRoomConsumer.as_asgi()),
]
This is my chat app consumers.py file
# import pytest
from accounts.models import Account
from .models import ChatRoom, Message
from channels.generic.websocket import AsyncWebsocketConsumer
import json
from channels.db import database_sync_to_async
import string
import random
# from asgiref.sync import sync_to_async
class ChatRoomConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name= 'chat_%s'%self.room_name
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self,close_code):
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
username = text_data_json['username']
room_name = text_data_json['room_name']
# print("[RECIEVED] "+room_name)
print("[receiving....]"+message)
await self.channel_layer.group_send(
self.room_group_name,
{
'type':'chatroom_message',
'message':message,
'username':username,
'room_name':room_name,
}
)
async def chatroom_message(self,event):
message = event['message']
username = event['username']
room_name = event['room_name']
print("[SENDING....]"+message)
room_obj = ChatRoom.objects.get(room_name=room_name)
sender = Account.objects.get(username=username)
await self.save_message(message=message,sender=sender,room_name=room_obj)
await self.send(text_data=json.dumps({
'message':message,
'username':username,
}))
#database_sync_to_async
def save_message(self,message,sender,room_name):
chat_id = ''.join(random.choices(string.ascii_uppercase+string.digits,k=10))
new_message = Message(message_id=chat_id,message=message,room_name=room_name,message_sender=sender)
new_message.save()
This is my JavaScript
{{room_name|json_script:"room-name"}}
{{username|json_script:"user_username"}}
{% if room_user_1_username %}
{{room_user_1_username|json_script:"room_user_1"}}
{% endif %}
{% if room_user_2_username %}
{{room_user_2_username|json_script:"room_user_2"}}
{% endif %}
<script>
const roomName = JSON.parse(document.getElementById('room-name').textContent);
const username = JSON.parse(document.getElementById('user_username').textContent);
const room_user_1 = JSON.parse(document.getElementById('room_user_1').textContent);
const room_user_2 = JSON.parse(document.getElementById('room_user_2').textContent);
var input_box = document.getElementById("input");
if(input_box.innerHTML==""){
document.getElementById("submit").style.visibility=false;
}
else{
document.getElementById("submit").style.visibility=true;
}
//for sending the message to websocket
document.getElementById("submit").onclick=function(e){
const messageInputDom = document.querySelector("#input");
const message = messageInputDom.value;
console.log("message: "+message);
console.log("username:"+username);
current_user = "{{request.user.username}}";
console.log("current_user: "+current_user);
if(username==room_user_1 || username==room_user_2){
if(messageInputDom.value!=""){
chatSocket.send(JSON.stringify({
'message':message,
'username':username,
'room_name':roomName,
}));
}
messageInputDom.value = '';
}
else{alert("Unauthorised access to a chat room");console.log("Message could not be sent!");}
messageInputDom.value='';
}
//setting up the websocket
const chatSocket = new WebSocket(
'ws://'+
window.location.host+
'/ws/chat/room/'+
roomName+
'/'+
username+
'/'
);
//getting messages from the websocket
chatSocket.onmessage = function(e){
const data = JSON.parse(e.data);
location.reload();//ON GETTING NEW MESSAGES
console.log("data: message->"+data.message+"\nusername->"+data.username);
$("#text-msg").val('\n'+data.username+": "+data.message+' (just now)');
alert(data.message);
}
</script>
It should show something like "CONNECT handshaking" on the cmd

Related

422 Unprocessable Entity

Here is my code:
from fastapi import (FastAPI, BackgroundTasks, UploadFile,
File, Form, Depends, HTTPException, status, Request)
from tortoise.contrib.fastapi import register_tortoise
from models import (User, Business, Product, user_pydantic, user_pydanticIn,
product_pydantic,product_pydanticIn, business_pydantic,
business_pydanticIn, user_pydanticOut)
# signals
from tortoise.signals import post_save
from typing import List, Optional, Type
from tortoise import BaseDBAsyncClient
from starlette.responses import JSONResponse
from starlette.requests import Request
#authentication and authorization
import jwt
from dotenv import dotenv_values
from fastapi.security import (
OAuth2PasswordBearer,
OAuth2PasswordRequestForm
)
# self packages
from emails import *
from authentication import *
from dotenv import dotenv_values
import math
# user image uploads
# pip install python-multipart
from fastapi import File, UploadFile
import secrets
# static files
from fastapi.staticfiles import StaticFiles
# pillow
from PIL import Image
# templates
from fastapi.templating import Jinja2Templates
# HTMLResponse
from fastapi.responses import HTMLResponse
config_credentials = dict(dotenv_values(".env"))
app = FastAPI()
# static files
# pip install aiofiles
app.mount("/static", StaticFiles(directory="static"), name="static")
# authorization configs
oath2_scheme = OAuth2PasswordBearer(tokenUrl = 'token')
# password helper functions
#app.post('/token')
async def generate_token(request_form: OAuth2PasswordRequestForm = Depends()):
token = await token_generator(request_form.username, request_form.password)
return {'access_token' : token, 'token_type' : 'bearer'}
# process signals here
#post_save(User)
async def create_business(
sender: "Type[User]",
instance: User,
created: bool,
using_db: "Optional[BaseDBAsyncClient]",
update_fields: List[str]) -> None:
if created:
business_obj = await Business.create(
business_name = instance.username, owner = instance)
await business_pydantic.from_tortoise_orm(business_obj)
# send email functionality
await send_email([instance.email], instance)
#app.post('/registration')
async def user_registration(user: user_pydanticIn):
user_info = user.dict(exclude_unset = True)
user_info['password'] = get_password_hash(user_info['password'])
user_obj = await User.create(**user_info)
new_user = await user_pydantic.from_tortoise_orm(user_obj)
return {"status" : "ok",
"data" :
f"Hello {new_user.username} thanks for choosing our services. Please check your email inbox and click on the link to confirm your registration."}
# template for email verification
templates = Jinja2Templates(directory="templates")
#app.get('/verification', response_class=HTMLResponse)
# make sure to import request from fastapi and HTMLResponse
async def email_verification(request: Request, token: str):
user = await verify_token(token)
if user and not user.is_verified:
user.is_verified = True
await user.save()
return templates.TemplateResponse("verification.html",
{"request": request, "username": user.username}
)
raise HTTPException(
status_code = status.HTTP_401_UNAUTHORIZED,
detail = "Invalid or expired token",
headers={"WWW-Authenticate": "Bearer"},
)
async def get_current_user(token: str = Depends(oath2_scheme)):
try:
payload = jwt.decode(token, config_credentials['SECRET'], algorithms = ['HS256'])
user = await User.get(id = payload.get("id"))
except:
raise HTTPException(
status_code = status.HTTP_401_UNAUTHORIZED,
detail = "Invalid username or password",
headers={"WWW-Authenticate": "Bearer"},
)
return await user
#app.post('/user/me')
async def user_login(user: user_pydantic = Depends(get_current_user)):
business = await Business.get(owner = user)
logo = business.logo
logo = "localhost:8000/static/images/"+logo
return {"status" : "ok",
"data" :
{
"username" : user.username,
"email" : user.email,
"verified" : user.is_verified,
"join_date" : user.join_date.strftime("%b %d %Y"),
"logo" : logo
}
}
#app.post("/products")
async def add_new_product(product: product_pydanticIn,
user: user_pydantic = Depends(get_current_user)):
product = product.dict(exclude_unset = True)
# to avoid division by zero error
if product['original_price'] > 0:
product["percentage_discount"] = ((product["original_price"] - product['new_price'] )/ product['original_price']) * 100
product_obj = await Product.create(**product, business = user)
product_obj = await product_pydantic.from_tortoise_orm(product_obj)
return {"status" : "ok", "data" : product_obj}
#app.get("/products")
async def get_products():
response = await product_pydantic.from_tortoise_orm(Product.all())
return {"status" : "ok", "data" : response}
#app.get("/products/{id}")
async def specific_product(id: int):
product = await Product.get(id = id)
business = await product.business
owner = await business.owner
response = await product_pydantic.from_queryset_single(Product.get(id = id))
print(type(response))
return {"status" : "ok",
"data" :
{
"product_details" : response,
"business_details" : {
"name" : business.business_name,
"city" : business.city,
"region" : business.region,
"description" : business.business_description,
"logo" : business.logo,
"owner_id" : owner.id,
"email" : owner.email,
"join_date" : owner.join_date.strftime("%b %d %Y")
}
}
}
#app.delete("/products/{id}")
async def delete_product(id: int, user: user_pydantic = Depends(get_current_user)):
product = await Product.get(id = id)
business = await product.business
owner = await business.owner
if user == owner:
product.delete()
else:
raise HTTPException(
status_code = status.HTTP_401_UNAUTHORIZED,
detail = "Not authenticated to perform this action",
headers={"WWW-Authenticate": "Bearer"},
)
return {"status" : "ok"}
# image upload
#app.post("/uploadfile/profile")
async def create_upload_file(file: UploadFile = File(...),
user: user_pydantic = Depends(get_current_user)):
FILEPATH = "./static/images/"
filename = file.filename
extension = filename.split(".")[1]
if extension not in ["jpg", "png"]:
return {"status" : "error", "detail" : "file extension not allowed"}
token_name = secrets.token_hex(10)+"."+extension
generated_name = FILEPATH + token_name
file_content = await file.read()
with open(generated_name, "wb") as file:
file.write(file_content)
# pillow
img = Image.open(generated_name)
img = img.resize(size = (200,200))
img.save(generated_name)
file.close()
business = await Business.get(owner = user)
owner = await business.owner
# check if the user making the request is authenticated
print(user.id)
print(owner.id)
if owner == user:
business.logo = token_name
await business.save()
else:
raise HTTPException(
status_code = status.HTTP_401_UNAUTHORIZED,
detail = "Not authenticated to perform this action",
headers={"WWW-Authenticate": "Bearer"},
)
file_url = "localhost:8000" + generated_name[1:]
return {"status": "ok", "filename": file_url}
#app.post("/uploadfile/product/{id}")
# check for product owner before making the changes.
async def create_upload_file(id: int, file: UploadFile = File(...),
user: user_pydantic = Depends(get_current_user)):
FILEPATH = "./static/images/"
filename = file.filename
extension = filename.split(".")[1]
if extension not in ["jpg", "png"]:
return {"status" : "error", "detail" : "file extension not allowed"}
token_name = secrets.token_hex(10)+"."+extension
generated_name = FILEPATH + token_name
file_content = await file.read()
with open(generated_name, "wb") as file:
file.write(file_content)
# pillow
img = Image.open(generated_name)
img = img.resize(size = (200,200))
img.save(generated_name)
file.close()
#get product details
product = await Product.get(id = id)
business = await product.business
owner = await business.owner
# check if the user making the request is authenticated
if owner == user:
product.product_image = token_name
await product.save()
else:
raise HTTPException(
status_code = status.HTTP_401_UNAUTHORIZED,
detail = "Not authenticated to perform this action",
headers={"WWW-Authenticate": "Bearer"},
)
file_url = "localhost:8000" + generated_name[1:]
return {"status": "ok", "filename": file_url}
register_tortoise(
app,
db_url='sqlite://database.sqlite3',
modules={'models': ['models']},
generate_schemas = True,
add_exception_handlers = True
)
When im opening up http://127.0.0.1:8000/docs and try the "/registration" request I get the error: Code: 422 Details: Error: Unprocessable Entity`
Response body:
{
"detail": [
{
"loc": [],
"msg": "UNIQUE constraint failed: user.username",
"type": "IntegrityError"
}
]
}
Response headers:
content-length: 95
content-type: application/json
date: Sun,04 Dec 2022 23:22:02 GMT
server: uvicorn
And in the console I get:
127.0.0.1:54566 - "POST /registration HTTP/1.1" 422 Unprocessable Entity
After some debugging I think that the line 86
user_obj = await User.create(**user_info)
Is causing problems, but I can't seem to be able to fix the issue. Feel free to ask for any additional information
UPD: I was followng Princekrampah's guide on youtube, the git link to the repo is: https://github.com/Princekrampah/learningFastAPI/tree/master/shoppingAPI

Warning discord.getaway "discord.gateway: Shard ID None heartbeat blocked for more than 10 seconds."

I tried to write a Discord bot that forwards messages from one server to another. But I get a warning that disconnects my connection to the discord gateway. I read that it is possible because of tyme.slep(), but without it, the connection is always interrupted. As I understand it, DDOS protection is activated due to a large number of requests.
import asyncio
import websocket
import json
from threading import Thread
import discord
import requests
from io import BytesIO
import time
from discord.ext import tasks
# Bot
bot_token = "anything"
user_token = "anything"
client = discord.Client(intents=discord.Intents.default())
# Channels list
f = open('channels.txt', 'r')
channels_file = f.read()
channels_array = channels_file.strip().split('\n')
# Connect func
def send_json_request(ws, request):
ws.send(json.dumps(request))
def receive_json_response(ws):
response = ws.recv()
if response:
return json.loads(response)
#WebSoket
def on_closed(ws):
ws.connect("wss://gateway.discord.gg/?v=6&encording=json")
ws = websocket.WebSocket(on_close=on_closed)
ws.connect("wss://gateway.discord.gg/?v=6&encording=json")
def receive_json_response(ws):
response = ws.recv()
if response:
return json.loads(response)
def get_attachment_media(media):
media_array = []
for i in media:
response = requests.get(i['url'])
im = BytesIO(response.content)
print(im)
media_array.append(discord.File(im))
return media_array
def get_channel(id):
for i in channels_array:
if i == id:
return True
return False
#Heartbeat
def heartbeat(interval):
print("Heartbeat begin")
while True:
time.sleep(interval)
heartbeatJSON = {
"op": 1,
"d": "null"
}
send_json_request(ws, heartbeatJSON)
print("Heartbeat sent")
#tasks.loop(seconds=0.5)
async def main():
channel = client.get_channel(anything)
event = receive_json_response(ws)
try:
if event['d']['author']['id'] == 'anything':
return
id_channel = event['d']['channel_id']
id_guild = event['d']['guild_id']
if get_channel(id_channel):
content = event['d']['content']
attachment_media = get_attachment_media(event['d']['attachments'])
await channel.send(content, files=attachment_media)
op_code = event('op')
if op_code == 11:
print('Heartbeat recieved')
except:
pass
#client.event
async def on_ready():
event = receive_json_response(ws)
heartbeat_interval = event['d']['heartbeat_interval'] / 1000
send_json_request(ws, {
"op": 2,
"d": {
"token": user_token,
"properties": {
"$os": 'linux',
"$browser": 'chrome',
"$device": 'pc'
}
}
})
main.start()
asyncio.run(heartbeat(heartbeat_interval))
client.run(bot_token)
I recommend you to check this answer and adjust it to your code.
However, if you are just trying to make your bot copy the contenet of the messages sent in one server and sending to another one, you can do it in a easier way using the on_message() event. This is the entire code, which should also prevent any warning (unless the bot tries to send too many messages in a short period of time):
import discord
intents = discord.Intents.default()
intents.message_content = True # You are missing the message_content intent! (needed to read the content of the guild's messages)
client = discord.Client(intents=intents)
TOKEN = "Your Token"
guild_id = 123456789 # The guild you want your bot to send the messages to
channel_id = 987654321 # The channel of the guild you want your bot to send the messages to
guild = None
channel = None
#client.event
async def on_ready():
global guild, channel, guild_id, channel_id
await client.wait_until_ready()
guild = client.get_guild(guild_id)
channel = guild.get_channel(channel_id)
print("Logged")
#client.event
async def on_message(message : discord.Message):
if message.author == client.user: # You don't want to send the own bot messages
return
if message.guild.id == guild_id: # You don't want to send the messages from the own guild your bot is sending the messages to
return
await channel.send(f"{message.author}: {message.content}") # Add attachments if you want
client.run(TOKEN)

Django Channels sending multiple messages to same channel

Referring to documentation here
I'm sending messages to the single fetched channel_name
I'm able to successfully send messages to the specific channel
Issues I'm facing
On the channels it's sending messages multiple times
For Example -
When I send first message, I receive 1 time.
On second message, I'm getting same messages twice.
On third message, I'm geting same message 3 times.
and so on...
class ChatConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
self.user_id = self.scope['url_route']['kwargs']['user_id']
await self.save_user_channel()
await self.accept()
async def disconnect(self, close_code):
await self.disconnect()
async def receive_json(self, text_data=None, byte_data=None):
message = text_data['message']
to_user = text_data['to_user']
to_user_channel, to_user_id = await self.get_user_channel(to_user)
channel_layer = get_channel_layer()
await channel_layer.send(
str(to_user_channel), {
'type': 'send.message',
'from_user': self.user_id,
'to_user': str(to_user_id),
'message': message,
}
)
await channel_layer.send(
str(self.channel_name), {
'type': 'send.message',
'from_user': self.user_id,
'to_user': str(to_user_id),
'message': message,
}
)
async def send_message(self, event):
from_user = event['from_user']
to_user = event['to_user']
message = event['message']
await self.send(text_data=json.dumps({
'from_user': from_user,
'to_user': to_user,
'message': message,
}))
#database_sync_to_async
def get_user_channel(self, to_user):
try:
self.send_user_channel = ChatParticipantsChannel.objects.filter(
user=to_user).latest('id')
channel_name = self.send_user_channel
user_id = self.send_user_channel.user.user_uid
except Exception as e:
self.send_user_channel = None
channel_name = None
return channel_name, user_id
#database_sync_to_async
def save_user_channel(self):
self.user = User.objects.get(user_uid=self.user_id)
ChatParticipantsChannel.objects.create(
user=self.user,
channel=self.channel_name
)
#database_sync_to_async
def delete_user_channel(self):
ChatParticipantsChannel.objects.filter(user=self.user).delete()

how to delete a previous message if we get new message in django channels

I want to broadcast the only latest message of Django-channel layer in a specific room. Right now I have created specific room names for specific users. Now I just want to send them only latest message or note, I don't want to show all the previous messages. Right now all the previous message are showing to user side.
# chat/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class ProjectConsumer(AsyncWebsocketConsumer):
async def connect(self):
parameter = self.scope['url_route']['kwargs']["project_key"]
print("url_parameter ",parameter)
self.room_name = parameter
# Join room group
await self.channel_layer.group_add(
self.room_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
# Leave room group
await self.channel_layer.group_discard(
self.room_name,
self.channel_name
)
# Receive message from WebSocket
async def receive(self, text_data):
text_data_json = json.loads(text_data)
instance_user = text_data_json['instance_user']
sender = text_data_json['sender']
receiver = text_data_json['receiver']
message = text_data_json['message']
object = {
'sender':sender,
'receiver':receiver,
'message':message,
}
# Send message to room group
await self.channel_layer.group_send(
self.room_name,
{
'type': 'sent', #function name as an event type
'object': object #function parameters as an event object
}
)
# Receive message from room group
async def sent(self, event):
sender = event['object']["sender"]
receiver = event['object']["receiver"]
message = event['object']["message"]
# Send message to WebSocket
await self.send(text_data=json.dumps({
'sender':sender,
'receiver':receiver,
'message':message,
}))
Channel_layer broadcasts only the available message, you are probably appending the message to a DOM element in your front-end

TypeError: Field 'id' expected a number but got <channels.auth.UserLazyObject object at 0x7f3e01742e90>

I'm deploying a chat application built with django channels. It is working on my localhost but IN production, the sockets connects at first but as soon as i send a message the following error shows up: WebSocket is already in CLOSING or CLOSED state. What could go wrong? Thanks in advance
My server logs are as follows:
Error logs
File "/home/ubuntu/django/virtualenv2/lib/python3.7/site-packages/django/db/models/fields/__init__.py", line 1774, in get_prep_value
return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'UserLazyObject'
File "/home/ubuntu/django/virtualenv2/lib/python3.7/site-packages/channels/generic/websocket.py", line 175, in websocket_connect
await self.connect()
File "./chat/consumers.py", line 179, in connect
File "./chat/managers.py", line 24, in by_user
threads = self.get_queryset().filter(thread_type="personal")
My consumers.py file and managers.py file are as follows.
Consumers.py file
from django.utils import timezone
import pytz, time, datetime
import json
from channels.layers import get_channel_layer
from chat.models import Message, Thread, Notification
from channels.consumer import SyncConsumer
from asgiref.sync import async_to_sync
from django.contrib.auth import get_user_model
from datetime import datetime
from django.dispatch import receiver
from django.db.models import signals
import asyncio
from asgiref.sync import async_to_sync, sync_to_async
from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncJsonWebsocketConsumer
from django.utils import timezone
User = get_user_model()
# ================== Chat consumer starts ==================
class ChatConsumer(SyncConsumer):
def websocket_connect(self, event):
my_slug = self.scope['path'][-8:]
me = User.objects.get(slug=my_slug)
other_user_slug = self.scope['url_route']['kwargs']['other_slug']
other_user = User.objects.get(slug=other_user_slug)
self.thread_obj = Thread.objects.get_or_create_personal_thread(
me, other_user)
self.room_name = 'personal_thread_{}'.format(self.thread_obj.id)
async_to_sync(self.channel_layer.group_add)(
self.room_name, self.channel_name)
self.send({
'type': 'websocket.accept',
})
#staticmethod
#receiver(signals.post_save, sender=Notification)
def order_offer_observer(sender, instance, **kwargs):
layer = get_channel_layer()
thread_id = instance.thread.id
return thread_id
def websocket_receive(self, event):
my_slug = self.scope['path'][-8:]
me = User.objects.get(slug=my_slug)
other_user_slug = self.scope['url_route']['kwargs']['other_slug']
other_user = User.objects.get(slug=other_user_slug)
text = json.loads(event.get('text'))
thread_obj = Thread.objects.get_or_create_personal_thread(
me, other_user)
obj = Thread.objects.get_or_create_personal_thread(me, other_user)
recent_threads_id = []
other_user_threads = Thread.objects.by_user(other_user.id).all()
for one_thread in other_user_threads:
if one_thread.message_set.all():
if (one_thread.users).first().email == other_user.email:
y = Notification.objects.get_notification_object(
thread=obj, user1=other_user, user2=(one_thread.users).last())
y = y.read
recent_threads_id.append(one_thread.id)
else:
y = Notification.objects.get_notification_object(
thread=obj, user1=other_user, user2=(one_thread.users).first())
y = y.read
recent_threads_id.append(one_thread.id)
else:
pass
if "message" in text:
notification = Notification.objects.get_notification_object(
thread=thread_obj, user1=me, user2=other_user)
notification.sender = me
print("notification.sender " , notification.sender)
current_thread_id = self.order_offer_observer(
sender=Notification, instance=Notification.objects.get_notification_object(thread=thread_obj, user1=me, user2=other_user))
obj.updated_at = int(round(time.time() *1000))
obj.save()
fmt = "%I:%M %p"
utctime = datetime.now()
utc = utctime.replace(tzinfo=pytz.UTC)
localtz = utc.astimezone(timezone.get_current_timezone())
sent_time = localtz.strftime(fmt)
message_text = text['message']
msg = json.dumps({
'text': message_text,
'user_slug': my_slug,
'thread_id': current_thread_id,
'sent_time' : sent_time
})
# Sending live notifications
threads_count = len(recent_threads_id)
if threads_count < 1:
async_to_sync(self.channel_layer.group_send)(
self.room_name,
{'type': 'websocket.message',
'text': msg})
else:
for one_id in range(threads_count):
if recent_threads_id[one_id] == current_thread_id:
async_to_sync(self.channel_layer.group_send)(
self.room_name,
{'type': 'websocket.message',
'text': msg})
else:
async_to_sync(self.channel_layer.group_send)(
'personal_thread_{}'.format(recent_threads_id[one_id]),
{'type': 'websocket.message',
'text': repr(current_thread_id)})
if notification:
notification.read = False
notification.save()
self.store_message(message_text, sent_time)
elif "chat_read" in text:
notification = Notification.objects.get_notification_object(
thread=thread_obj, user1=me, user2=other_user)
if notification.sender:
if 'user_slug' in text:
chat_opener_slug = text['user_slug']
if chat_opener_slug != notification.sender.slug:
notification.read = True
notification.save()
async_to_sync(self.channel_layer.group_send)(
'personal_thread_{}'.format(obj.id),
{'type':'websocket.message',
'text': json.dumps({'message_read': "yes"})})
def websocket_message(self, event):
self.send({
'type': 'websocket.send',
'text': event.get('text')
})
def websocket_disconnect(self, event):
my_slug = self.scope['path'][-8:]
me = User.objects.get(slug=my_slug)
other_user_slug = self.scope['url_route']['kwargs']['other_slug']
other_user = User.objects.get(slug=other_user_slug)
thread_obj = Thread.objects.get_or_create_personal_thread(me, other_user)
# Deleting thread if it has no messages
if len(thread_obj.message_set.all()) == 0:
thread_obj.delete()
def store_message(self, text):
my_slug = self.scope['path'][-8:]
me = User.objects.get(slug=my_slug)
Message.objects.create(
thread=self.thread_obj,
sender=me,
text=text,
)
# ================== Chat consumer ends ==================
class NotifyConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
await self.accept()
await self.channel_layer.group_add("gossip", self.channel_name)
if self.scope['path'][-8:]:
current_user_slug = self.scope['path'][-8:]
current_user = User.objects.get(slug=current_user_slug)
current_users_chats = sync_to_async(Thread.objects.by_user(current_user).order_by('updated_at'))
#staticmethod
#receiver(signals.post_save, sender=Message)
def announce_new_user(sender, instance, **kwargs):
sender = instance.sender
channel_layer = get_channel_layer()
if instance.thread.users.first() == sender:
me = instance.thread.users.last()
else:
me = instance.thread.users.first()
async_to_sync(channel_layer.group_send)(
"gossip",{
"type": "user.gossip",
"event": "New user",
"sender": me.slug,
"receiver": sender.slug
}
)
async def user_gossip(self, event):
await self.send_json(event)
async def disconnect(self, close_code):
await self.channel_layer.group_discard("gossip", self.channel_name)
```
----------------------- Managers.py file ------------------
from datetime import datetime
from django.db import models
from django.shortcuts import Http404
from django.db.models import Count
class ThreadManager(models.Manager):
def get_or_create_personal_thread(self, user1, user2):
threads = self.get_queryset().filter(thread_type="personal")
threads = threads.filter(users__in=[user1, user2])
threads = threads.annotate(u_count=Count('users')).filter(u_count=2)
if threads.exists():
return threads.first()
else:
if (user1 == user2):
raise Http404
else:
thread = self.create(thread_type="personal")
thread.users.add(user1)
thread.users.add(user2)
return thread
def by_user(self, user):
return self.get_queryset().filter(users__in=[user])
class MessageManager(models.Manager):
def message_by_user(self, user):
return self.get_queryset.filter(sender__in=[user])

Categories