2 Commits

Author SHA1 Message Date
42287d4a86 J'ai fais n'imp 2023-12-16 12:06:05 +01:00
a7826040d6 back to the past bcb072f7d9f5f7817d949837219231232160ff11; Chatte 2023-12-16 11:58:50 +01:00
50 changed files with 371 additions and 943 deletions

View File

@ -22,17 +22,17 @@ pip install -r requirements.txt
``` ```
- Setup database - Setup database
``` ```
<<<<<<< HEAD
python manage.py runserver makemigrations profiles
python manage.py migrate profiles
=======
python manage.py makemigrations games python manage.py makemigrations games
python manage.py makemigrations profiles python manage.py makemigrations profiles
python manage.py makemigrations chat python manage.py runserver makemigrations chat
python manage.py migrate python manage.py migrate
>>>>>>> d03f90367f1fd075e79f4a69d31c5a49b9e53d01
``` ```
- Start the developpement server - Start the developpement server
``` ```
python manage.py runserver 0.0.0.0:8000 python manage.py runserver 0.0.0.0:8000
``` ```
coc nvim
```
pip install django-stubs
```

View File

@ -15,4 +15,4 @@ class LoggedView(APIView):
def get(self, request: HttpRequest): def get(self, request: HttpRequest):
if (request.user.is_authenticated): if (request.user.is_authenticated):
return Response({'id': request.user.pk}, status=status.HTTP_200_OK) return Response({'id': request.user.pk}, status=status.HTTP_200_OK)
return Response('false', status=status.HTTP_200_OK) return Response('false', status=status.HTTP_200_OK)

View File

@ -15,4 +15,4 @@ class RegisterView(APIView):
if user: if user:
login(request, user) login(request, user)
return Response("user created", status=status.HTTP_201_CREATED) return Response("user created", status=status.HTTP_201_CREATED)
return Response(status=status.HTTP_400_BAD_REQUEST) return Response(status=status.HTTP_400_BAD_REQUEST)

View File

@ -1,6 +1,3 @@
from django.contrib import admin from django.contrib import admin
from .models import ChannelModel, MemberModel, MessageModel
admin.site.register(ChannelModel) # Register your models here.
admin.site.register(MemberModel)
admin.site.register(MessageModel)

View File

@ -1,25 +1,10 @@
import json import json
from channels.generic.websocket import WebsocketConsumer from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync from asgiref.sync import async_to_sync
from .models import MemberModel, MessageModel
from profiles.models import BlockModel
import time
class ChatConsumer(WebsocketConsumer): class ChatConsumer(WebsocketConsumer):
def connect(self): def connect(self):
channel_id : str = self.scope['path'].split('/')[3] self.room_group_name = 'test'
self.room_group_name = 'chat' + channel_id
user = self.scope["user"]
if (user.is_anonymous or not user.is_authenticated):
return
if MemberModel.objects.filter(member_id=user.pk, channel_id=int(channel_id)).count() != 1:
return
if (self.channel_layer == None):
return
async_to_sync(self.channel_layer.group_add)( async_to_sync(self.channel_layer.group_add)(
self.room_group_name, self.room_group_name,
@ -29,66 +14,31 @@ class ChatConsumer(WebsocketConsumer):
self.accept() self.accept()
def receive(self, text_data=None, bytes_data=None): def receive(self, text_data):
if text_data == None:
return
text_data_json = json.loads(text_data) text_data_json = json.loads(text_data)
message = text_data_json['message'] message = text_data_json['message']
receivers_id = text_data_json['receivers_id']
print(text_data)
channel_id : int = int(self.scope['path'].split('/')[3])
user = self.scope["user"] user = self.scope["user"]
if (user.is_anonymous or not user.is_authenticated): if user.is_anonymous:
return return;
if MemberModel.objects.filter(member_id=user.pk, channel_id=channel_id).count() != 1:
return
if (self.channel_layer == None):
return
message_time : int = int(time.time() * 1000)
if (len(receivers_id) == 1 and
BlockModel.objects.filter(blocker=user.pk, blocked=receivers_id[0]) or
BlockModel.objects.filter(blocker=receivers_id[0], blocked=user.pk)
):
return
async_to_sync(self.channel_layer.group_send)( async_to_sync(self.channel_layer.group_send)(
self.room_group_name, self.room_group_name,
{ {
'type':'chat_message', 'type':'chat_message',
'author_id':user.pk, 'username':user.username,
'content':message, 'message':message
'time':message_time,
} }
) )
new_message = MessageModel()
new_message.channel_id = channel_id
new_message.author_id = user.pk
new_message.content = message
new_message.time = message_time
new_message.save()
def chat_message(self, event): def chat_message(self, event):
channel_id : int = int(self.scope['path'].split('/')[3])
user = self.scope["user"] user = self.scope["user"]
if (user.is_anonymous or not user.is_authenticated): if user.is_anonymous:
return return;
if MemberModel.objects.filter(member_id=user.pk, channel_id=channel_id).count() != 1:
return
self.send(text_data=json.dumps({ self.send(text_data=json.dumps({
'type':'chat', 'type':'chat',
'author_id':event['author_id'], 'username':event['username'],
'content':event['content'], 'message':event['message']
'time': event['time'],
})) }))

View File

@ -1,7 +1,6 @@
from django.db import models from django.db import models
from django.db.models import IntegerField from django.db.models import IntegerField
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib import admin
# Create your models here. # Create your models here.
class ChannelModel(models.Model): class ChannelModel(models.Model):
@ -11,14 +10,8 @@ class MemberModel(models.Model):
member_id = IntegerField(primary_key=False) member_id = IntegerField(primary_key=False)
channel_id = IntegerField(primary_key=False) channel_id = IntegerField(primary_key=False)
def __str__(self):
return "member_id: " + str(self.member_id) + ", channel_id: " + str(self.channel_id)
class MessageModel(models.Model): class MessageModel(models.Model):
channel_id = IntegerField(primary_key=False) channel_id = IntegerField(primary_key=False)
author_id = IntegerField(primary_key=False) author_id = IntegerField(primary_key=False)
content = models.CharField(max_length=255) content = models.CharField(max_length=255)
time = IntegerField(primary_key=False) time = models.DateField()
def __str__(self):
return "author_id: " + str(self.author_id) + ", channel_id: " + str(self.channel_id) + ", content: " + self.content

View File

@ -2,5 +2,5 @@ from django.urls import re_path
from . import consumers from . import consumers
websocket_urlpatterns = [ websocket_urlpatterns = [
re_path(r'ws/chat/(?P<chat_id>\d+)/$', consumers.ChatConsumer.as_asgi()) re_path(r'ws/socket-server/', consumers.ChatConsumer.as_asgi())
] ]

View File

@ -6,5 +6,4 @@ from . import views
urlpatterns = [ urlpatterns = [
path("<int:pk>", views.ChatView.as_view(), name="chat_page"), path("<int:pk>", views.ChatView.as_view(), name="chat_page"),
path("", views.ChatsView.as_view(), name="chats_page"),
] ]

View File

@ -1,79 +1,29 @@
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework import authentication, permissions, status from rest_framework import authentication, permissions
from rest_framework.authentication import SessionAuthentication from rest_framework.authentication import SessionAuthentication
from .models import ChannelModel, MemberModel, MessageModel from .models import ChannelModel, MemberModel, MessageModel
from django.core import serializers
class ChatView(APIView): class ChatView(APIView):
permission_classes = (permissions.IsAuthenticated,) permission_classes = (permissions.IsAuthenticated,)
authentication_classes = (SessionAuthentication,) authentication_classes = (SessionAuthentication,)
def get(self, request, pk): def post(self, request, pk):
if (ChannelModel.objects.filter(pk=pk)): if (ChannelModel.objects.filter(pk = pk)):
return Response({'channel_id': pk}, status=status.HTTP_200_OK) return Response("Channel already exist")
else:
return Response("Channel doesn't exist", status=status.HTTP_404_NOT_FOUND)
def delete(self, request, pk):
ChannelModel.objects.filter(pk=pk).delete()
MessageModel.objects.filter(pk=pk).delete()
MemberModel.objects.filter(pk=pk).delete()
return Response({'channel_id': pk}, status=status.HTTP_200_OK)
class ChatsView(APIView):
def post(self, request):
data: dict = request.data data: dict = request.data
users_id = request.data.get("users_id", []) users_id = request.data.get("users_id", [])
if len(users_id) < 2: if len(users_id) < 2:
return Response('Not enought members to create the channel', status=status.HTTP_400_BAD_REQUEST) return Response("Not enought members to create the channel")
if users_id[0] == users_id[1]:
return Response('Same member', status=status.HTTP_400_BAD_REQUEST)
for user_id1 in users_id:
for member1 in MemberModel.objects.filter(member_id=user_id1):
for user_id2 in users_id:
if user_id1 == user_id2:
continue
for member2 in MemberModel.objects.filter(member_id=user_id2):
if (member1.channel_id == member2.channel_id):
messages = MessageModel.objects.filter(channel_id=member1.channel_id).order_by("time")
messages = serializers.serialize("json", messages)
return Response({'channel_id': member1.channel_id, 'messages':messages}, status=status.HTTP_200_OK)
new_channel = ChannelModel() new_channel = ChannelModel()
new_channel.save() new_channel.save()
for user_id in users_id: for user_id in users_id:
new_member = MemberModel() new_member = MemberModel()
new_member.channel_id = new_channel.pk new_member.channel_id = new_channel.pk
new_member.member_id = user_id new_member.member_id = user_id
new_member.save() new_member.save()
return Response({'channel_id': new_channel.pk}, status=status.HTTP_201_CREATED) return Response("Channel created")
def delete(self, request):
data: dict = request.data
users_id = request.data.get("users_id", [])
#print(list(MemberModel.objects.all()))
for user_id1 in users_id:
for member1 in MemberModel.objects.filter(member_id=user_id1):
for user_id2 in users_id:
if user_id1 == user_id2:
break
for member2 in MemberModel.objects.filter(member_id=user_id2):
if (member1.channel_id == member2.channel_id):
MessageModel.objects.filter(channel_id=member1.channel_id).delete()
member1.delete()
member2.delete()
ChannelModel.objects.get(pk=member1.channel_id).delete()
return Response("Channel removed", status=status.HTTP_200_OK)
return Response("Channel doesn't exist", status=status.HTTP_404_NOT_FOUND)

View File

@ -9,4 +9,4 @@
margin-right: auto; margin-right: auto;
margin-top: 90px; margin-top: 90px;
border: 15px black solid; border: 15px black solid;
} }

View File

@ -9,4 +9,4 @@
margin-right: auto; margin-right: auto;
margin-top: 90px; margin-top: 90px;
border: 15px black solid; border: 15px black solid;
} }

View File

@ -1,8 +1,7 @@
body { body {
margin: 0.5em; margin: 10;
font-family: 'Quicksand', sans-serif; font-family: 'Quicksand', sans-serif;
font-size: 30px; font-size: 18px;
} }
a { a {

View File

@ -1,18 +1,19 @@
#app #main .account #app .account
{ {
background-color: red; background-color: red;
} }
#app #main #app .account, #app .profile
{ {
width: 60%; width: 60%;
display: flex; display: flex;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
flex-direction: column; flex-direction: column;
flex-wrap: wrap;
} }
#app #main .profile #app .profile
{ {
background-color: green; background-color: green;
} }

View File

@ -1,20 +0,0 @@
#app #avatar
{
height: 100px;
width: 100px;
}
#app #username
{
font-size: 0.8em;
}
#app #block {
cursor: pointer;
font-size: 0.7em;
text-decoration: underline;
}
#app {
margin-top: 20px;
}

View File

@ -0,0 +1,11 @@
#app #avatar
{
height: 100px;
width: 100px;
}
#app #username
{
height: 100px;
width: 100px;
}

View File

@ -0,0 +1,11 @@
#app .item img
{
height: 100px;
width: 100px;
}
#app .item a
{
height: 100px;
width: 100px;
}

View File

@ -1,104 +1,17 @@
#app img #app img
{ {
max-height: 3em; max-height: 100px;
max-width: 3em; max-width: 100px;
} }
#app ul #app ul
{ {
font-size: 0.75em; margin: 5px 0 0 0;
margin: 0.25em 0 0 0;
padding: 0 0 0 0; padding: 0 0 0 0;
list-style-type: none; list-style-type: none;
max-height: 80vh;
overflow: auto;
} }
#app li #app li
{ {
margin: 0.25em 0.25em 0 0; margin: 10px 10px 0 0;
}
#app #chats {
overflow: hidden;
display: flex;
text-align: left;
}
#app #users {
margin: 0em 1.0em 0em 0.05em;
}
#app #chat {
position: relative;
max-height: 100vh;
width: 100vh;
/*border: 2px solid green;*/
overflow: hidden;
}
#app #members {
font-size: 1em;
}
#app #add_chat_off {
text-decoration: underline;
cursor: pointer;
}
#app #add_chat_on {
cursor: pointer;
}
#app #messages {
max-height: 60vh;
overflow: scroll;
overflow-y: scroll;
overflow-x: hidden;
font-size: 0.75em;
}
#app #input_user{
color: green;
width: 8.5em;
height: 1.1em;
font-size: 0.65em;
border: none;
outline: none;
border-bottom: 0.15em solid green;
}
#app #input_chat{
position: sticky;
bottom: 0;
/*width: calc(100% - 8px);*/
width: 100%;
border: none;
outline: none;
border-bottom: 0.2em solid green;
caret-color: green;
color: green;
font-size: 16px;
}
#app #you {
text-align: left;
position: relative;
max-width: 48%;
left: 0.5em;
margin: 0.5em 0 0 0;
color: green;
word-wrap: break-word;
}
#app #other {
text-align: right;
position: relative;
max-width: 48%;
margin: 0.5em 0 0 auto;
right: 0.5em;
color: red;
/* permet le retour à la ligne à la place de dépasser*/
word-wrap: break-word;
} }

View File

@ -1,19 +0,0 @@
import { Profile } from "./profile.js";
class MyProfile extends Profile
{
async change_avatar(form_data)
{
let response = await this.client._patch_file(`/api/profiles/me`, form_data);
let response_data = await response.json()
return response_data;
}
async init()
{
super.init("me");
}
}
export {MyProfile}

View File

@ -1,15 +1,7 @@
import { Client } from "./client.js";
class Account class Account
{ {
/**
* @param {Client} client
*/
constructor (client) constructor (client)
{ {
/**
* @type {Client} client
*/
this.client = client; this.client = client;
} }
@ -36,6 +28,7 @@ class Account
this.client._logged = false; this.client._logged = false;
return null; return null;
} }
console.log(response_data)
if (response_data == "user deleted") if (response_data == "user deleted")
this.client._logged = false; this.client._logged = false;
return response_data; return response_data;
@ -62,7 +55,7 @@ class Account
if (JSON.stringify(response_data) == JSON.stringify({'detail': 'Authentication credentials were not provided.'})) if (JSON.stringify(response_data) == JSON.stringify({'detail': 'Authentication credentials were not provided.'}))
{ {
this.client._; this.client._logged = false;
return null; return null;
} }
return response_data; return response_data;

View File

@ -1,78 +1,9 @@
import {Message} from "./message.js"
class Channel { class Channel {
constructor(client, channel_id, members_id, messages, reload) { constructor(id, members, messages) {
this.client = client; this.id = id;
this.channel_id = channel_id; this.members = members;
this.members_id = members_id; this.messages = messages;
this.messages = [];
if (messages != undefined)
this.updateMessages(messages);
this.connect(reload);
} }
// reload = function to use when we receive a message
async connect(reload) {
let url = `ws://${window.location.host}/ws/chat/${this.channel_id}/`;
this.chatSocket = new WebSocket(url);
this.chatSocket.onmessage = (event) =>{
let data = JSON.parse(event.data)
this.messages.push(new Message(
this.channel_id,
data.author_id,
data.content,
data.time,
));
reload();
};
}
async disconnect() {
this.chatSocket.close();
}
updateMessages(messages) {
messages = JSON.parse(messages);
let new_messages = [];
messages.forEach((message) => {
message = message["fields"];
new_messages.push(new Message(
message["channel_id"],
message["author_id"],
message["content"],
message["time"],
));
});
//console.log(new_messages);
this.messages = new_messages;
return new_messages;
}
async sendMessageChannel(message, receivers_id) {
if (this.chatSocket == undefined)
return;
this.chatSocket.send(JSON.stringify({
'message':message,
'receivers_id':receivers_id,
}));
}
async deleteChannel() {
let response = await this.client._delete("/api/chat/" + this.channel_id, {
});
let data = await response.json();
return data;
}
} }
export {Channel} export {Channel}

View File

@ -1,46 +1,19 @@
import {Channel} from "./channel.js"
import {Message} from "./message.js"
class Channels { class Channels {
constructor(client) { constructor(client) {
this.client = client; this.client = client;
} }
async createChannel(users_id, reload) { async createChannel(users_id) {
console.log(users_id);
let null_id = false;
users_id.forEach(user_id => {
if (user_id == null)
null_id = true;
});
if (null_id)
return console.log(users_id, "createChannel error, null id;");
let response = await this.client._post("/api/chat/", { let response = await this.client._post("/api/chat/", {
users_id:users_id users_id:users_id
}); });
let data = await response.json(); let data = await response.json();
let exit_code = await response.status; if (data == "Channel already exist")
if (exit_code >= 300) return null;
return undefined;
let messages = undefined;
if (exit_code == 200)
messages = data.messages;
return new Channel(this.client, data.channel_id, users_id, messages, reload);
}
async deleteChannel(users_id) {
let response = await this.client._delete("/api/chat/", {
users_id:users_id
});
let data = await response.json();
console.log(response.status)
return data; return data;
} }
} }
export {Channels} export {Channels}

View File

@ -1,10 +0,0 @@
class Message {
constructor(channel_id, author_id, content, time) {
this.channel_id = channel_id;
this.author_id = author_id;
this.content = content;
this.time = time;
}
}
export {Message}

View File

@ -1,8 +1,7 @@
import { Account } from "./account.js"; import { Account } from "./account.js";
import { MatchMaking } from "./matchmaking.js"; import { MatchMaking } from "./matchmaking.js";
import { Profile } from "./profile.js";
import { Profiles } from "./profiles.js"; import { Profiles } from "./profiles.js";
import { Channels } from './chat/channels.js';
import { MyProfile } from "./MyProfile.js";
function getCookie(name) function getCookie(name)
{ {
@ -23,9 +22,6 @@ class Client
this.profiles = new Profiles(this); this.profiles = new Profiles(this);
this.matchmaking = new MatchMaking(this); this.matchmaking = new MatchMaking(this);
this._logged = undefined; this._logged = undefined;
this.channels = new Channels(this);
this.channel = undefined;
} }
async isAuthentificate() async isAuthentificate()
@ -35,11 +31,10 @@ class Client
return this.logged; return this.logged;
} }
async _get(uri, data) async _get(uri)
{ {
let response = await fetch(this._url + uri, { let response = await fetch(this._url + uri, {
method: "GET", method: "GET",
body: JSON.stringify(data),
}); });
return response; return response;
} }
@ -95,23 +90,15 @@ class Client
return response; return response;
} }
async _update_logged(state)
{
if (!this.logged && state)
{
this.me = new MyProfile(this);
await this.me.init();
}
this.logged = state;
}
async login(username, password) async login(username, password)
{ {
let response = await this._post("/api/accounts/login", {username: username, password: password}) let response = await this._post("/api/accounts/login", {username: username, password: password})
let data = await response.json(); let data = await response.json();
if (data.id != undefined) if (data.id != undefined)
{ {
await this._update_logged(true); this.me = new Profile(this)
await this.me.init(data.id)
this.logged = true;
return null; return null;
} }
return data; return data;
@ -120,7 +107,7 @@ class Client
async logout() async logout()
{ {
await this._get("/api/accounts/logout"); await this._get("/api/accounts/logout");
await this._update_logged(false); this.logged = false;
} }
async _test_logged() async _test_logged()
@ -129,7 +116,10 @@ class Client
let data = await response.json(); let data = await response.json();
if (data.id !== undefined) if (data.id !== undefined)
await this._update_logged(true); {
this.me = new Profile(this)
await this.me.init(data.id)
}
return data.id !== undefined; return data.id !== undefined;
} }
} }

View File

@ -1,9 +1,9 @@
import { Client } from "./client.js"; import { client, navigateTo } from "../index.js"
class MatchMaking class MatchMaking
{ {
/** /**
* @param {Client} client * @param {client} client
*/ */
constructor(client) constructor(client)
{ {

View File

@ -1,20 +1,11 @@
import { Client } from "./client.js";
class Profile class Profile
{ {
/**
* @param {Client} client
*/
constructor (client, username = undefined, avatar_url = undefined, user_id = undefined) constructor (client, username = undefined, avatar_url = undefined, user_id = undefined)
{ {
/**
* @type {Client} client
*/
this.client = client; this.client = client;
this.username = username; this.username = username;
this.avatar_url = avatar_url; this.avatar_url = avatar_url
this.user_id = user_id; this.user_id = user_id
this.isBlocked = false;
} }
async init(user_id) async init(user_id)
@ -22,24 +13,23 @@ class Profile
let response = await this.client._get(`/api/profiles/${user_id}`); let response = await this.client._get(`/api/profiles/${user_id}`);
let response_data = await response.json(); let response_data = await response.json();
this.user_id = response_data.user_id; this.user_id = user_id;
this.username = response_data.username; this.username = response_data.username;
this.avatar_url = response_data.avatar_url; this.avatar_url = response_data.avatar_url;
}
let block_response = await this.client._get("/api/profiles/block"); async change_avatar(form_data)
{
let response = await this.client._patch_file(`/api/profiles/${this.user_id}`, form_data);
let response_data = await response.json()
if (block_response.status == 404) return response_data;
return }
let block_data = await block_response.json(); async setData (data)
let block_list = JSON.parse(block_data); {
block_list.forEach(block => {
let blocker = block.fields.blocker;
let blocked = block.fields.blocked;
if (blocker == this.client.me.user_id && blocked == user_id)
return this.isBlocked = true;
});
} }
} }
export {Profile} export {Profile}

View File

@ -2,14 +2,8 @@ import { Profile } from "./profile.js";
class Profiles class Profiles
{ {
/**
* @param {Client} client
*/
constructor (client) constructor (client)
{ {
/**
* @type {Client} client
*/
this.client = client this.client = client
} }
@ -31,34 +25,6 @@ class Profiles
await profile.init(user_id); await profile.init(user_id);
return profile; return profile;
} }
async block(user_id) {
// blocker & blocked
let response = await this.client._post("/api/profiles/block", {
users_id:[this.client.me.user_id, user_id],
});
let data = await response.json();
console.log(response.status);
console.log(data);
return data;
}
async deblock(user_id) {
// blocker & blocked
let response = await this.client._delete("/api/profiles/block", {
users_id:[this.client.me.user_id, user_id],
});
let data = await response.json();
console.log(response.status);
console.log(data);
return data;
}
} }
export {Profiles} export {Profiles}

View File

@ -3,6 +3,7 @@ import { Client } from "./api/client.js";
import LoginView from "./views/accounts/LoginView.js"; import LoginView from "./views/accounts/LoginView.js";
import Dashboard from "./views/Dashboard.js"; import Dashboard from "./views/Dashboard.js";
import Search from "./views/Search.js"; import Search from "./views/Search.js";
import Chat from "./views/Chat.js";
import HomeView from "./views/HomeView.js"; import HomeView from "./views/HomeView.js";
import RegisterView from "./views/accounts/RegisterView.js"; import RegisterView from "./views/accounts/RegisterView.js";
import LogoutView from "./views/accounts/LogoutView.js"; import LogoutView from "./views/accounts/LogoutView.js";
@ -10,9 +11,9 @@ import GameView from "./views/Game.js"
import PageNotFoundView from './views/PageNotFoundView.js' import PageNotFoundView from './views/PageNotFoundView.js'
import AbstractRedirectView from "./views/abstracts/AbstractRedirectView.js"; import AbstractRedirectView from "./views/AbstractRedirectView.js";
import MeView from "./views/MeView.js"; import MeView from "./views/MeView.js";
import ProfilePageView from "./views/ProfilePageView.js"; import ProfilePageView from "./views/profiles/ProfilePageView.js";
import MatchMakingView from "./views/MatchMakingView.js"; import MatchMakingView from "./views/MatchMakingView.js";
let client = new Client(location.protocol + "//" + location.host) let client = new Client(location.protocol + "//" + location.host)
@ -43,6 +44,7 @@ const router = async (uri) => {
{ path: "/logout", view: LogoutView }, { path: "/logout", view: LogoutView },
{ path: "/register", view: RegisterView }, { path: "/register", view: RegisterView },
{ path: "/search", view: Search }, { path: "/search", view: Search },
{ path: "/chat", view: Chat },
{ path: "/home", view: HomeView }, { path: "/home", view: HomeView },
{ path: "/me", view: MeView }, { path: "/me", view: MeView },
{ path: "/matchmaking", view: MatchMakingView }, { path: "/matchmaking", view: MatchMakingView },
@ -79,7 +81,6 @@ const router = async (uri) => {
lastView = view; lastView = view;
await client.isAuthentificate();
let content = await view.getHtml(); let content = await view.getHtml();
if (content == null) if (content == null)
return 1; return 1;

View File

@ -1,18 +0,0 @@
function clear(property_name, elements_id)
{
elements_id.forEach(element_id => {
let element = document.getElementById(element_id)
element[property_name] = ""
});
}
function fill_errors(errors, property_name)
{
Object.keys(errors).forEach(error_field =>
{
let element = document.getElementById(error_field);
element[property_name] = errors[error_field];
});
}
export {fill_errors, clear}

View File

@ -1,4 +1,4 @@
import { client, navigateTo } from "../../index.js"; import { client, navigateTo } from "../index.js";
import AbstractRedirectView from "./AbstractRedirectView.js"; import AbstractRedirectView from "./AbstractRedirectView.js";
export default class extends AbstractRedirectView{ export default class extends AbstractRedirectView{

View File

@ -1,4 +1,4 @@
import { client, navigateTo } from "../../index.js"; import { client, navigateTo } from "../index.js";
import AbstractRedirectView from "./AbstractRedirectView.js"; import AbstractRedirectView from "./AbstractRedirectView.js";
export default class extends AbstractRedirectView{ export default class extends AbstractRedirectView{

View File

@ -1,4 +1,4 @@
import { navigateTo } from "../../index.js"; import { navigateTo } from "../index.js";
import AbstractView from "./AbstractView.js"; import AbstractView from "./AbstractView.js";
export default class extends AbstractView{ export default class extends AbstractView{

View File

@ -0,0 +1,56 @@
import AbstractView from "./AbstractView.js";
export default class extends AbstractView {
constructor(params) {
super(params, "Chat");
let url = `ws://${window.location.host}/ws/socket-server/`
this.chatSocket = new WebSocket(url)
this.chatSocket.onmessage = function(e){
let data = JSON.parse(e.data)
console.log('Data:', data)
if (data.type === 'chat') {
let messages = document.getElementById('messages')
let username = data.username === null || data.username.length <= 0 ? "NoName" : data.username;
messages.insertAdjacentHTML('beforeend', `
<div><p>${username}: ${data.message}</p></div>
`)
}
}
}
async postInit() {
let form = document.getElementById('form')
form.addEventListener('submit', (e)=> {
e.preventDefault()
let message = e.target.message.value
this.chatSocket.send(JSON.stringify({
'message':message
}))
form.reset()
})
}
async leavePage() {
this.chatSocket.close();
}
async getHtml() {
return `
<h1>Chat</h1>
<form id="form">
<input type="text" name="message" placeholder="message"/>
</form>
<div id="messages">
</div>
`;
}
}

View File

@ -1,4 +1,4 @@
import AbstractView from "./abstracts/AbstractView.js"; import AbstractView from "./AbstractView.js";
export default class extends AbstractView { export default class extends AbstractView {
constructor(params) { constructor(params) {
@ -16,4 +16,4 @@ export default class extends AbstractView {
</p> </p>
`; `;
} }
} }

View File

@ -1,4 +1,4 @@
import AbstractView from "./abstracts/AbstractView.js"; import AbstractView from './AbstractView.js'
export default class extends AbstractView { export default class extends AbstractView {
constructor(params) { constructor(params) {

View File

@ -1,4 +1,4 @@
import AbstractAuthentificateView from "./abstracts/AbstractAuthentifiedView.js"; import AbstractAuthentificateView from "./AbstractAuthentifiedView.js";
export default class extends AbstractAuthentificateView { export default class extends AbstractAuthentificateView {
constructor(params) { constructor(params) {
@ -15,4 +15,4 @@ export default class extends AbstractAuthentificateView {
<a href="/logout" class="nav__link" data-link>Logout</a> <a href="/logout" class="nav__link" data-link>Logout</a>
`; `;
} }
} }

View File

@ -1,5 +1,5 @@
import { client, navigateTo } from "../index.js"; import { client, navigateTo } from "../index.js";
import AbstractView from "./abstracts/AbstractView.js"; import AbstractView from "./AbstractView.js";
function game_found(game_id) function game_found(game_id)
{ {
@ -26,4 +26,4 @@ export default class extends AbstractView {
{ {
await client.matchmaking.stop(); await client.matchmaking.stop();
} }
} }

View File

@ -1,6 +1,5 @@
import { client, navigateTo } from "../index.js"; import { client, navigateTo } from "../index.js";
import { clear, fill_errors } from "../utils/formUtils.js"; import AbstractAuthentificateView from "./AbstractAuthentifiedView.js";
import AbstractAuthentificateView from "./abstracts/AbstractAuthentifiedView.js";
export default class extends AbstractAuthentificateView export default class extends AbstractAuthentificateView
{ {
@ -11,40 +10,29 @@ export default class extends AbstractAuthentificateView
async postInit() async postInit()
{ {
document.getElementById("save-account-button").onclick = this.save_account; if (this.fill() === null)
document.getElementById("delete-account-button").onclick = this.delete_account; return;
document.getElementById("save-profile-button").onclick = this.save_profile; document.getElementById("save-account-button").onclick = this.acccount_save;
document.getElementById("delete-account-button").onclick = this.account_delete_accounts;
} }
async delete_account() async fill()
{ {
let current_password = document.getElementById("current_password-input").value; let data = await client.account.get();
let response_data = await client.account.delete(current_password); if (data === null)
console.log(await client.isAuthentificate())
if (response_data === null || response_data === "user deleted")
{ {
navigateTo("/login"); navigateTo("/login")
return; return;
} }
clear("innerHTML", ["current_password-input"]) document.getElementById("username").value = data.username;
fill_errors({"current_password-input": response_data["password"]}, "innerHTML")
} }
async save_account() async delete_accounts()
{ {
let username = document.getElementById("username-input").value; let current_password = document.getElementById("current_password").value;
let new_password = document.getElementById("new_password-input").value;
let current_password = document.getElementById("current_password-input").value; let response_data = await client.account.delete(current_password);
let data = {};
data.username = username;
if (new_password.length != 0)
data.new_password = new_password;
let response_data = await client.account.update(data, current_password);
if (response_data === null) if (response_data === null)
{ {
@ -52,54 +40,92 @@ export default class extends AbstractAuthentificateView
return; return;
} }
if (response_data === "data has been alterate") ["delete", "current_password"].forEach(error_field => {
response_data = {"save-account": "saved"} let error_display = document.getElementById(`error_${error_field}`);
if (error_display != null)
error_display.innerHTML = "";
});
clear("innerHTML", ["username", "new_password", "current_password", "save-account", "delete-account"]) if (response_data === "user deleted")
fill_errors(response_data, "innerHTML") {
document.getElementById(`error_delete`).innerHTML = "OK";
navigateTo("/login")
return;
}
document.getElementById("error_current_password").innerHTML = response_data["password"]
} }
async save_profile() async save()
{ {
let avatar = document.getElementById("avatar-input"); let username = document.getElementById("username").value;
let new_password = document.getElementById("new_password").value;
let current_password = document.getElementById("current_password").value;
let data = {};
data.username = username;
if (new_password.length != 0)
data.new_password = new_password;
let response_data = await client.account.update(data, current_password);
if (response_data === null)
{
navigateTo("/login");
return;
}
else if (response_data === "data has been alterate")
{
navigateTo("/me");
return;
}
["username", "new_password", "current_password"].forEach(error_field => {
let error_display = document.getElementById(`error_${error_field}`);
if (error_display != null)
error_display.innerHTML = "";
});
Object.keys(response_data).forEach(error_field => {
let error_display = document.getElementById(`error_${error_field}`);
if (error_display != null)
error_display.innerHTML = response_data[error_field];
});
let avatar = document.getElementById("avatar");
if (avatar.files[0] !== undefined) if (avatar.files[0] !== undefined)
{ {
let form_data = new FormData(); let form_data = new FormData();
form_data.append("file", avatar.files[0]); form_data.append("file", avatar.files[0]);
await client.me.change_avatar(form_data); await client.me.change_avatar(form_data)
} }
document.getElementById("save-profile").innerHTML = "Saved";
} }
async getHtml() async getHtml()
{ {
return ` return `
<link rel="stylesheet" href="/static/css/me.css"> <link rel="stylesheet" href="static/css/me.css">
<h1>ME</h1> <h1>ME</h1>
<div id="main"> <div class="account">
<div class="account"> <h3>Account</h3>
<h3>Account</h3> <input type="text" placeholder="username" id="username">
<input type="text" placeholder="username" id="username-input" text=${client.me.username}> <span id="error_username"></span>
<span id="username"></span> <input type=password placeholder="new password" id="new_password">
<input type=password placeholder="new_password" id="new_password-input"> <span id="error_new_password"></span>
<span id="new_password"></span> <input type=password placeholder="current password" id="current_password">
<input type=password placeholder="current_password" id="current_password-input"> <span id="error_current_password"></span>
<span id="current_password"></span> <input type="button" value="Save Credentials" id="save-account-button">
<span id="error_save"></span>
<input type="button" value="Save Credentials" id="save-account-button"> <input type="button" value="Delete Account" id="delete-account-button">
<span id="save-account"></span> <span id="error_delete"></span>
<input type="button" value="Delete Account" id="delete-account-button">
<span id="delete-account"></span>
</div>
<div class="profile">
<h3>Profile</h3>
<input type="file" id="avatar-input" accept="image/png, image/jpeg">
<input type="button" value="Save profile" id="save-profile-button">
<span id="save-profile"></span>
</div>
<a href="/logout" class="nav__link" data-link>Logout</a>
</div> </div>
<div class="profile">
<h3>Profile</h3>
<input type="file" id="avatar" accept="image/png, image/jpeg">
<input type="button" value="Save profile" id="save-profile-button">
<span id="error_save"></span>
</div>
<a href="/logout" class="nav__link" data-link>Logout</a>
`; `;
} }
} }

View File

@ -1,4 +1,4 @@
import AbstractView from "./abstracts/AbstractView.js"; import AbstractView from "./AbstractView.js";
export default class extends AbstractView { export default class extends AbstractView {
constructor(params) { constructor(params) {

View File

@ -1,62 +0,0 @@
import AbstractView from "./abstracts/AbstractView.js";
import { client } from "../index.js"
export default class extends AbstractView {
constructor(params) {
super(params, "Profile ");
this.user_id = params.id;
}
async postInit()
{
this.profile = await client.profiles.getProfile(this.user_id);
this.info = document.getElementById("info");
// Username
let username = document.createElement("a");
username.id = "username";
username.appendChild(document.createTextNode(this.profile.username));
this.info.appendChild(username);
this.info.appendChild(document.createElement("br"));
// Avatar
let avatar = document.createElement("img");
avatar.id = "avatar";
avatar.src = this.profile.avatar_url;
this.info.appendChild(avatar);
await this.blockButton();
}
async blockButton() {
// Block option
if (client.me.user_id != this.user_id) {
let block = document.getElementById("block") || document.createElement("a");
block.id = "block";
block.innerText = "";
block.onclick = async () => {
if (!this.profile.isBlocked)
await client.profiles.block(this.user_id);
else
await client.profiles.deblock(this.user_id);
this.profile = await client.profiles.getProfile(this.user_id);
this.blockButton();
};
if (this.profile.isBlocked)
block.appendChild(document.createTextNode("Deblock"));
else
block.appendChild(document.createTextNode("Block"));
this.info.appendChild(block);
}
}
async getHtml() {
return `
<link rel="stylesheet" href="/static/css/profile.css">
<div id="info">
</div>
`;
}
}

View File

@ -1,6 +1,5 @@
import AbstractView from "./abstracts/AbstractView.js"; import AbstractView from "./AbstractView.js";
import {client} from "../index.js"; import {client} from "../index.js";
import {Message} from "../api/chat/message.js"
export default class extends AbstractView { export default class extends AbstractView {
constructor(params) { constructor(params) {
@ -9,21 +8,16 @@ export default class extends AbstractView {
async postInit() { async postInit() {
let search = document.getElementById("input_user"); let search = document.getElementById("form");
search.oninput = this.users; search.addEventListener("input", this.users)
let chat_input = document.getElementById("input_chat");
//chat_input.addEventListener("keydown", this.chat_manager)
this.last_add_chat = undefined;
this.users(); this.users();
this.chat();
} }
async users() { async users() {
let search = document.getElementById("input_user").value.toLowerCase(); let search = document.getElementById("form").value;
let logged = await client.isAuthentificate(); let logged = await client.isAuthentificate();
@ -31,13 +25,7 @@ export default class extends AbstractView {
let list_users = document.getElementById('list_users'); let list_users = document.getElementById('list_users');
list_users.innerHTML = ""; list_users.innerHTML = "";
users.filter(user => user.username.toLowerCase().startsWith(search) == true).forEach((user) => { users.filter(user => user.username.startsWith(search) == true).forEach((user) => {
if (user.user_id == null) {
console.log("list User one with id null;");
return;
}
var new_user = document.createElement("li"); var new_user = document.createElement("li");
// username // username
@ -50,37 +38,20 @@ export default class extends AbstractView {
new_user.appendChild(document.createTextNode(" ")); new_user.appendChild(document.createTextNode(" "));
// chat // chat
if (logged && client.me.user_id != user.user_id) { if (logged) {
let add_chat = document.createElement("a"); let chat = document.createElement("a");
add_chat.id = "add_chat_off"; let array = [
add_chat.onclick = async () => { client.me.user_id,
if (client.channel != undefined) { user.user_id,
client.channel.members_id.forEach((member_id) => { ];
if (member_id == user.user_id) console.log(client.me.id);
client.channel = undefined; chat.addEventListener("click", async function(){
}); console.log("click");
await client.channels.createChannel([client.me.user_id , user.user_id]);
if (client.channel == undefined) { });
add_chat.id = "add_chat_off"; //chat.href = `/chat`
this.last_add_chat = undefined; chat.appendChild(document.createTextNode("Chat"));
return this.hideChat(); new_user.appendChild(chat);
}
client.channel.disconnect();
}
client.channel = await client.channels.createChannel([client.me.user_id , user.user_id], this.chat);
this.chat();
if (this.last_add_chat != undefined)
this.last_add_chat.id = "add_chat_off";
this.last_add_chat = add_chat;
add_chat.id = "add_chat_on";
};
add_chat.appendChild(document.createTextNode("Chat"));
new_user.appendChild(add_chat);
new_user.appendChild(document.createTextNode(" "));
} }
// break line // break line
@ -98,130 +69,17 @@ export default class extends AbstractView {
} }
async chat() {
let users = await client.profiles.all();
let logged = await client.isAuthentificate();
/*let reload = document.getElementById("messages");
if (reload != null)
reload.remove();*/
let reload = document.getElementById("members");
if (reload != null)
reload.remove();
if (client.channel == undefined || !logged)
return ;
let chats = document.getElementById("chats");
if (document.getElementById("chat") == null) {
let chat = document.createElement("div");
chat.id = "chat";
chats.appendChild(chat);
}
// div des messages
let messages = document.getElementById("messages");
if (messages == null) {
messages = document.createElement("div");
messages.id = "messages";
if (document.getElementById("input_chat") == null)
chat.appendChild(messages);
else
document.getElementById("input_chat").before(messages);
}
// les messages, réecriture seulement du dernier
let i = 0;
client.channel.messages.forEach((message) => {
if (messages.children[i] == null || message.content != messages.children[i].innerText) {
let text = document.createElement("p");
text.appendChild(document.createTextNode(message.content));
if (message.author_id == client.me.user_id)
text.id = "you";
else
text.id = "other";
messages.appendChild(text);
}
i++;
});
// Input pour rentrer un message
if (document.getElementById("input_chat") == null) {
let chat_input = document.createElement("input");
chat_input.id="input_chat";
chat_input.type="text";
chat_input.name="message";
chat_input.placeholder="message bozo";
chat_input.maxLength=255;
chat.appendChild(chat_input);
chat_input.onkeydown = async () => {
if (event.keyCode == 13 && client.channel != undefined) {
//let chat_input = document.getElementById("input_chat");
let chat_text = chat_input.value;
let receivers_id = [];
client.channel.members_id.forEach((member_id) => {
if (member_id != client.me.user_id)
receivers_id.push(users.filter(user => user.user_id == member_id)[0].user_id);
});
await client.channel.sendMessageChannel(chat_text, receivers_id)
// Reset
chat_input.value = "";
}
};
}
// nom des membres du chat
let members = document.createElement("h2");
members.id = "members";
let usernames = "";
client.channel.members_id.forEach((member_id) => {
if (member_id != client.me.user_id) {
if (usernames.length > 0)
usernames += ", ";
usernames += (users.filter(user => user.user_id == member_id)[0].username);
}
});
members.appendChild(document.createTextNode(usernames));
messages.before(members);
// Scroll to the bottom of messages
messages.scrollTop = messages.scrollHeight;
}
async hideChat() {
let close = document.getElementById("chat");
if (close != null)
close.remove();
}
async leavePage() {
if (client.channel != undefined)
client.channel.disconnect();
client.channel = undefined
}
async getHtml() { async getHtml() {
return ` return `
<link rel="stylesheet" href="/static/css/search.css"> <link rel="stylesheet" href="/static/css/search.css">
<div id="chats"> <input id="form" type="text" name="message" placeholder="userbozo"/>
<div id="users">
<input id="input_user" type="text" name="message" placeholder="userbozo"/> <div id="users">
<ul id="list_users"> <ul id="list_users">
</ul> </ul>
</div>
</div> </div>
`; `;
} }
} }

View File

@ -1,11 +1,10 @@
import { client, navigateTo } from "../../index.js"; import { client, navigateTo } from "../../index.js";
import { clear, fill_errors } from "../../utils/formUtils.js"; import AbstractNonAuthentifiedView from "../AbstractNonAuthentified.js";
import AbstractNonAuthentifiedView from "../abstracts/AbstractNonAuthentified.js";
async function login() async function login()
{ {
let username = document.getElementById("username-input").value; let username = document.getElementById("username").value;
let password = document.getElementById("password-input").value; let password = document.getElementById("password").value;
let response_data = await client.login(username, password); let response_data = await client.login(username, password);
@ -15,8 +14,17 @@ async function login()
return; return;
} }
clear("innerHTML", ["username", "user", "password"]); ["username", "user", "password"].forEach(error_field => {
fill_errors(response_data, "innerHTML"); let error_display = document.getElementById(`error_${error_field}`);
if (error_display != null)
error_display.innerHTML = "";
});
Object.keys(response_data).forEach(error_field => {
let error_display = document.getElementById(`error_${error_field}`);
if (error_display != null)
error_display.innerHTML = response_data[error_field];
});
} }
export default class extends AbstractNonAuthentifiedView { export default class extends AbstractNonAuthentifiedView {
@ -26,22 +34,22 @@ export default class extends AbstractNonAuthentifiedView {
async postInit() async postInit()
{ {
document.getElementById("login-button").onclick = login; document.getElementById("button").onclick = login;
} }
async getHtml() { async getHtml() {
return ` return `
<div class=form> <div class=form>
<label>Login</label> <label>Login</label>
<link rel="stylesheet" href="/static/css/accounts/login.css"> <link rel="stylesheet" href="static/css/accounts/login.css">
<input type="text" id="username-input" placeholder="username"> <input type="text" id="username" placeholder="username">
<span id="username"></span> <span id="error_username"></span>
<input type="password" id="password-input" placeholder="password"> <input type="password" id="password" placeholder="password">
<span id="password"></span> <span id="error_password"></span>
<input type="button" value="Login" id="login-button"> <input type="button" value="login" id="button">
<span id="user"></span> <span id="error_user"></span>
<a href="/register" class="nav__link" data-link>Register</a> <a href="/register" class="nav__link" data-link>Register</a>
</div> </div>
`; `;
} }
} }

View File

@ -1,5 +1,5 @@
import { client, navigateTo } from "../../index.js"; import { client, navigateTo } from "../../index.js";
import AbstractAuthentifiedView from "../abstracts/AbstractAuthentifiedView.js"; import AbstractAuthentifiedView from "../AbstractAuthentifiedView.js";
export default class extends AbstractAuthentifiedView export default class extends AbstractAuthentifiedView
{ {
@ -8,4 +8,4 @@ export default class extends AbstractAuthentifiedView
client.logout(); client.logout();
navigateTo("/login") navigateTo("/login")
} }
} }

View File

@ -1,11 +1,10 @@
import { client, navigateTo } from "../../index.js"; import { client, navigateTo } from "../../index.js";
import { clear, fill_errors } from "../../utils/formUtils.js"; import AbstractNonAuthentifiedView from "../AbstractNonAuthentified.js";
import AbstractNonAuthentifiedView from "../abstracts/AbstractNonAuthentified.js";
async function register() async function register()
{ {
let username = document.getElementById("username-input").value; let username = document.getElementById("username").value;
let password = document.getElementById("password-input").value; let password = document.getElementById("password").value;
let response_data = await client.account.create(username, password); let response_data = await client.account.create(username, password);
@ -15,8 +14,17 @@ async function register()
return; return;
} }
clear("innerHTML", ["username", "user", "password"]); ["username", "user", "password"].forEach(error_field => {
fill_errors(response_data, "innerHTML"); let error_display = document.getElementById(`error_${error_field}`);
if (error_display != null)
error_display.innerHTML = "";
});
Object.keys(response_data).forEach(error_field => {
let error_display = document.getElementById(`error_${error_field}`);
if (error_display != null)
error_display.innerHTML = response_data[error_field];
});
} }
export default class extends AbstractNonAuthentifiedView { export default class extends AbstractNonAuthentifiedView {
@ -26,20 +34,20 @@ export default class extends AbstractNonAuthentifiedView {
async postInit() async postInit()
{ {
document.getElementById("register-button").onclick = register; document.getElementById("button").onclick = register;
} }
async getHtml() { async getHtml() {
return ` return `
<div class=form> <div class=form>
<label>Register</label> <label>Register</label>
<link rel="stylesheet" href="/static/css/accounts/register.css"> <link rel="stylesheet" href="static/css/accounts/register.css">
<input type="text" id="username-input" placeholder="username"> <input type="text" id="username" placeholder="username">
<span id="username"></span> <span id="error_username"></span>
<input type="password" id="password-input" placeholder="password"> <input type="password" id="password" placeholder="password">
<span id="password"></span> <span id="error_password"></span>
<input type="button" value="Register" id="register-button"> <input type="button" value="register" id="button">
<span id="user"></span> <span id="error_user"></span>
<a href="/login" class="nav__link" data-link>Login</a> <a href="/login" class="nav__link" data-link>Login</a>
</div> </div>
`; `;

View File

@ -0,0 +1,29 @@
import AbstractView from "../AbstractView.js";
import { client } from "../../index.js"
export default class extends AbstractView {
constructor(params) {
super(params, "Profile ");
this.user_id = params.id;
}
async postInit()
{
let profile = await client.profiles.getProfile(this.user_id);
let username_element = document.getElementById("username");
username_element.href = `/profiles/${this.user_id}`;
username_element.appendChild(document.createTextNode(profile.username));
let avatar_element = document.getElementById("avatar");
avatar_element.src = profile.avatar_url;
}
async getHtml() {
return `
<link rel="stylesheet" href="/static/css/profiles/profile.css">
<img id="avatar"/>
<a id="username"></a>
`;
}
}

View File

@ -1,7 +1,6 @@
from django.contrib import admin from django.contrib import admin
from .models import ProfileModel, BlockModel from .models import ProfileModel
# Register your models here. # Register your models here.
admin.site.register(ProfileModel) admin.site.register(ProfileModel)
admin.site.register(BlockModel)

View File

@ -4,7 +4,6 @@ from django.contrib.auth.models import User
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
from django.conf import settings from django.conf import settings
from django.db.models import IntegerField
def upload_to(instance, filename: str): def upload_to(instance, filename: str):
return f"./profiles/static/avatars/{instance.pk}.{filename.split('.')[1]}" return f"./profiles/static/avatars/{instance.pk}.{filename.split('.')[1]}"
@ -18,11 +17,4 @@ class ProfileModel(models.Model):
def on_user_created(sender, instance, created, **kwargs): def on_user_created(sender, instance, created, **kwargs):
if created: if created:
profile: ProfileModel = ProfileModel.objects.create(pk = instance.pk, user = instance) profile: ProfileModel = ProfileModel.objects.create(pk = instance.pk, user = instance)
profile.save() profile.save()
class BlockModel(models.Model):
blocker = IntegerField(primary_key=False)
blocked = IntegerField(primary_key=False)
def __str__(self):
return "blocker_id: " + str(self.blocker) + ", blocked_id: " + str(self.blocked)

View File

@ -3,13 +3,9 @@ from django.conf import settings
from django.conf.urls.static import static from django.conf.urls.static import static
from . import viewsets from . import viewsets
from . import views
urlpatterns = [ urlpatterns = [
path("me", viewsets.MyProfileViewSet.as_view({'patch': 'partial_update', 'get': 'retrieve'}), name="my_profile_page"), path("<int:pk>", viewsets.ProfileViewSet.as_view({'get': 'retrieve', 'patch': 'partial_update'}), name="profile_page"),
path("<int:pk>", viewsets.ProfileViewSet.as_view({'get': 'retrieve'}), name="profile_page"),
path("", viewsets.ProfileViewSet.as_view({'get': 'list'}), name="profiles_list"), path("", viewsets.ProfileViewSet.as_view({'get': 'list'}), name="profiles_list"),
path("block", views.BlocksView.as_view(), name="block_page"), #path("me", viewsets.ProfileViewSet.as_view(), name="my_profile_page"),
path("block/<int:pk>", views.BlockView.as_view(), name="block_page"), ] + static("/static/avatars/", document_root="./avatars")
] + static("/static/avatars/", document_root="./avatars")

View File

@ -1,66 +0,0 @@
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions, status
from rest_framework.authentication import SessionAuthentication
from rest_framework.renderers import JSONRenderer
from django.core import serializers
from .models import BlockModel
class BlockView(APIView):
permission_classes = (permissions.IsAuthenticated,)
authentication_classes = (SessionAuthentication,)
def get(self, request, pk):
block = BlockModel.objects.filter(pk=pk)
if (block):
return Response(serializers.serialize("json", block), status=status.HTTP_200_OK)
else:
return Response("Not Found", status=status.HTTP_404_NOT_FOUND)
class BlocksView(APIView):
permission_classes = (permissions.IsAuthenticated,)
authentication_classes = (SessionAuthentication,)
def get(self, request):
blocks = BlockModel.objects.filter(blocker=request.user.pk)
if (blocks):
return Response(serializers.serialize("json", BlockModel.objects.filter(blocker=request.user.pk)), status=status.HTTP_200_OK)
else:
return Response({}, status=status.HTTP_404_NOT_FOUND)
def post(self, request):
data: dict = request.data
users_id = request.data.get("users_id", None)
if (users_id == None):
return Response({"Error"}, status=status.HTTP_400_BAD_REQUEST)
if (BlockModel.objects.filter(blocker=users_id[0], blocked=users_id[1])):
return Response({"Already Exist"}, status=status.HTTP_409_CONFLICT)
new_block = BlockModel()
new_block.blocker = users_id[0]
new_block.blocked = users_id[1]
new_block.save()
return Response({"block_id": new_block.pk}, status=status.HTTP_201_CREATED)
def delete(self, request):
data: dict = request.data
users_id = request.data.get("users_id", None)
if (users_id == None):
return Response({"Error"}, status=status.HTTP_400_BAD_REQUEST)
block = BlockModel.objects.filter(blocker=users_id[0], blocked=users_id[1])
print(list(block))
if (block.count() > 1):
return Response("Not normal >:[", status=status.HTTP_500_INTERNAL_SERVER_ERROR)
if (not block):
return Response("Don't exist", status=status.HTTP_404_NOT_FOUND)
block.delete()
return Response("Deleted", status=status.HTTP_200_OK)

View File

@ -3,7 +3,6 @@ from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework import permissions, status from rest_framework import permissions, status
from rest_framework import viewsets from rest_framework import viewsets
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.authentication import SessionAuthentication
from django.http import HttpRequest from django.http import HttpRequest
from django.db.models import QuerySet from django.db.models import QuerySet
@ -18,9 +17,7 @@ class ProfileViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,) permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
def retrieve(self, request: HttpRequest, pk=None): def retrieve(self, request: HttpRequest, pk=None):
if (not self.queryset().filter(pk=pk).exists()): instance = ProfileModel.objects.get(pk=pk)
return Response({"detail": "Profile not found."}, status=status.HTTP_404_NOT_FOUND)
instance = self.queryset().get(pk=pk)
instance.avatar_url.name = instance.avatar_url.name[instance.avatar_url.name.find("static") - 1:] instance.avatar_url.name = instance.avatar_url.name[instance.avatar_url.name.find("static") - 1:]
return Response(self.serializer_class(instance).data, return Response(self.serializer_class(instance).data,
status=status.HTTP_200_OK) status=status.HTTP_200_OK)
@ -34,28 +31,14 @@ class ProfileViewSet(viewsets.ModelViewSet):
def perform_create(self, serializer): def perform_create(self, serializer):
serializer.save(user=self.request.user) serializer.save(user=self.request.user)
class MyProfileViewSet(viewsets.ModelViewSet): def perform_update(self, serializer):
query: QuerySet = ProfileModel.objects.filter(pk=self.request.user.pk)
permission_classes = (permissions.IsAuthenticated,) if (not query.exists()):
authentication_classes = (SessionAuthentication,) return Response("profile not found", status=status.HTTP_400_BAD_REQUEST)
serializer_class = ProfileSerializer profile: ProfileModel = ProfileModel.objects.get(pk=self.request.user.pk)
queryset = ProfileModel.objects.all
def get_object(self):
obj = self.queryset().get(pk=self.request.user.pk)
return obj
def perform_update(self, serializer, pk=None):
profile: ProfileModel = self.get_object()
avatar = self.request.data.get("file", None) avatar = self.request.data.get("file", None)
if (avatar is not None): if (avatar is not None):
if (profile.avatar_url.name != "./profiles/static/avatars/default.avif"): if (profile.avatar_url.name != "./profiles/static/avatars/default.avif"):
profile.avatar_url.storage.delete(profile.avatar_url.name) profile.avatar_url.storage.delete(profile.avatar_url.name)
profile.avatar_url = avatar profile.avatar_url = avatar
profile.save() profile.save()
def retrieve(self, request: HttpRequest, pk=None):
instance: ProfileModel = self.get_object()
instance.avatar_url.name = instance.avatar_url.name[instance.avatar_url.name.find("static") - 1:]
return Response(self.serializer_class(instance).data,
status=status.HTTP_200_OK)