Browse Source

all linted and on road to a working chat

master
nicolas-arnaud 2 years ago
parent
commit
f9b7d453e4
  1. 107
      back/volume/src/chat/chat.controller.ts
  2. 32
      back/volume/src/chat/chat.gateway.ts
  3. 2
      back/volume/src/chat/chat.module.ts
  4. 30
      back/volume/src/chat/chat.service.ts
  5. 1
      back/volume/src/chat/dto/create-channel.dto.ts
  6. 2
      back/volume/src/chat/entity/channel.entity.ts
  7. 8
      back/volume/src/chat/entity/connection.entity.ts
  8. 3
      back/volume/src/users/entity/user.entity.ts
  9. 49
      back/volume/src/users/users.controller.ts
  10. 1
      back/volume/src/users/users.module.ts
  11. 6
      back/volume/src/users/users.service.ts
  12. 2
      front/volume/src/Auth.ts
  13. 24
      front/volume/src/components/Channels.svelte
  14. 361
      front/volume/src/components/Chat.svelte
  15. 6
      front/volume/src/components/Friends.svelte
  16. 6
      front/volume/src/components/MatchHistory.svelte
  17. 6
      front/volume/src/components/NavBar.svelte
  18. 2
      front/volume/src/components/Pong/Pong.svelte
  19. 2
      front/volume/src/socket.ts

107
back/volume/src/chat/chat.controller.ts

@ -33,31 +33,34 @@ export class ChatController {
@Post(':id/invite')
async addUser (
@Param('id', ParseIntPipe) id: number,
@Body() target: IdDto,
@Profile42() profile: Profile
@Body() target: IdDto,
@Profile42() profile: Profile
): Promise<void> {
const channel = await this.channelService.getFullChannel(id)
const user: User | null = await this.usersService.findUser(target.id)
if (user == null)
if (user == null) {
throw new NotFoundException(`User #${target.id} not found`)
}
if (!(await this.channelService.isUser(channel.id, +profile.id))) {
throw new BadRequestException(
'You are not allowed to invite users to this channel'
)
}
if (await this.channelService.isUser(channel.id, target.id))
if (await this.channelService.isUser(channel.id, target.id)) {
throw new BadRequestException('User is already in this channel')
if (await this.channelService.isBanned(channel.id, target.id))
}
if (await this.channelService.isBanned(channel.id, target.id)) {
throw new BadRequestException('User is banned from this channel')
}
channel.users.push(user)
this.channelService.save(channel)
await this.channelService.save(channel)
}
@Delete(':id/kick')
async removeUser (
@Param('id', ParseIntPipe) id: number,
@Body() target: IdDto,
@Profile42() profile: Profile
@Body() target: IdDto,
@Profile42() profile: Profile
): Promise<void> {
const channel = await this.channelService.getFullChannel(id)
if (!(await this.channelService.isAdmin(channel.id, +profile.id))) {
@ -65,118 +68,136 @@ export class ChatController {
'You are not allowed to kick users from this channel'
)
}
if (!(await this.channelService.isUser(channel.id, target.id)))
if (!(await this.channelService.isUser(channel.id, target.id))) {
throw new BadRequestException('User is not in this channel')
if (await this.channelService.isOwner(channel.id, target.id))
}
if (await this.channelService.isOwner(channel.id, target.id)) {
throw new BadRequestException('You cannot kick the owner of the channel')
}
channel.users = channel.users.filter((usr: User) => {
return usr.ftId !== target.id
})
this.channelService.save(channel)
await this.channelService.save(channel)
}
@Post(':id/admin')
async addAdmin (
@Param('id', ParseIntPipe) id: number,
@Body() target: IdDto,
@Profile42() profile: Profile
@Body() target: IdDto,
@Profile42() profile: Profile
): Promise<void> {
const channel = await this.channelService.getFullChannel(id)
const user: User | null = await this.usersService.findUser(target.id)
if (user == null)
if (user == null) {
throw new NotFoundException(`User #${target.id} not found`)
if (!(await this.channelService.isOwner(channel.id, +profile.id)))
}
if (!(await this.channelService.isOwner(channel.id, +profile.id))) {
throw new BadRequestException('You are not the owner of this channel')
if (!(await this.channelService.isUser(channel.id, target.id)))
}
if (!(await this.channelService.isUser(channel.id, target.id))) {
throw new BadRequestException('User is not in this channel')
if (await this.channelService.isAdmin(channel.id, target.id))
}
if (await this.channelService.isAdmin(channel.id, target.id)) {
throw new BadRequestException('User is already an admin of this channel')
}
channel.admins.push(user)
this.channelService.save(channel)
await this.channelService.save(channel)
}
@Delete(':id/admin')
async removeAdmin (
@Param('id', ParseIntPipe) id: number,
@Body() target: IdDto,
@Profile42() profile: Profile
@Body() target: IdDto,
@Profile42() profile: Profile
): Promise<void> {
const channel = await this.channelService.getFullChannel(id)
if (!(await this.channelService.isOwner(channel.id, +profile.id)))
if (!(await this.channelService.isOwner(channel.id, +profile.id))) {
throw new BadRequestException('You are not the owner of this channel')
if (!(await this.channelService.isAdmin(channel.id, target.id)))
}
if (!(await this.channelService.isAdmin(channel.id, target.id))) {
throw new BadRequestException('User is not an admin of this channel')
}
channel.admins = channel.admins.filter((usr: User) => {
return usr.ftId !== target.id
})
this.channelService.save(channel)
await this.channelService.save(channel)
}
@Post(':id/ban')
async addBan (
@Param('id', ParseIntPipe) id: number,
@Body() target: IdDto,
@Profile42() profile: Profile
):Promise<void> {
@Body() target: IdDto,
@Profile42() profile: Profile
): Promise<void> {
const channel = await this.channelService.getFullChannel(id)
const user: User | null = await this.usersService.findUser(target.id)
if (user == null)
if (user == null) {
throw new NotFoundException(`User #${target.id} not found`)
}
if (!(await this.channelService.isAdmin(channel.id, +profile.id))) {
throw new BadRequestException(
'You are not allowed to ban users from this channel'
)
}
if (await this.channelService.isOwner(channel.id, target.id))
if (await this.channelService.isOwner(channel.id, target.id)) {
throw new BadRequestException('You cannot ban the owner of the channel')
if (await this.channelService.isBanned(channel.id, target.id))
}
if (await this.channelService.isBanned(channel.id, target.id)) {
throw new BadRequestException('User is already banned from this channel')
}
channel.banned.push(user)
this.channelService.save(channel)
await this.channelService.save(channel)
}
@Post(':id/mute')
async addMute (
@Param('id', ParseIntPipe) id: number,
@Body() mute: MuteDto, // [userId, duration]
@Profile42() profile: Profile
@Body() mute: MuteDto, // [userId, duration]
@Profile42() profile: Profile
): Promise<void> {
const channel = await this.channelService.getFullChannel(id)
const user: User | null = await this.usersService.findUser(mute.data[0])
if (user == null)
if (user == null) {
throw new NotFoundException(`User #${mute.data[0]} not found`)
}
if (!(await this.channelService.isAdmin(channel.id, +profile.id))) {
throw new BadRequestException(
'You are not allowed to mute users from this channel'
)
}
if (await this.channelService.isOwner(channel.id, mute.data[0]))
if (await this.channelService.isOwner(channel.id, mute.data[0])) {
throw new BadRequestException('You cannot mute the owner of the channel')
if (await this.channelService.getMuteDuration(channel.id, mute.data[0]) > 0)
}
if (
(await this.channelService.getMuteDuration(channel.id, mute.data[0])) > 0
) {
throw new BadRequestException('User is already muted from this channel')
}
const newMute: number[] = [mute.data[0], Date.now() + mute.data[1] * 1000]
channel.muted.push(newMute)
this.channelService.save(channel)
await this.channelService.save(channel)
}
@Delete(':id')
async deleteChannel (
@Profile42() profile: Profile,
@Param('id', ParseIntPipe) id: number
@Profile42() profile: Profile,
@Param('id', ParseIntPipe) id: number
): Promise<void> {
if (!(await this.channelService.isOwner(id, +profile.id)))
if (!(await this.channelService.isOwner(id, +profile.id))) {
throw new BadRequestException('You are not the owner of this channel')
}
await this.channelService.removeChannel(id)
}
@Post(':id/password')
async updatePassword (
@Profile42() profile: Profile,
@Param('id', ParseIntPipe) id: number,
@Body() data: PasswordDto
@Profile42() profile: Profile,
@Param('id', ParseIntPipe) id: number,
@Body() data: PasswordDto
): Promise<void> {
if (await this.channelService.isOwner(id, +profile.id))
if (await this.channelService.isOwner(id, +profile.id)) {
throw new BadRequestException('You are not the owner of this channel')
}
await this.channelService.updatePassword(id, data.password)
}

32
back/volume/src/chat/chat.gateway.ts

@ -4,7 +4,7 @@ import {
SubscribeMessage,
WebSocketGateway,
WebSocketServer,
WsException,
WsException
} from '@nestjs/websockets'
import { Socket, Server } from 'socket.io'
// import { User } from 'users/user.entity';
@ -20,7 +20,6 @@ import { Repository } from 'typeorm'
import ConnectedUser from './entity/connection.entity'
import { ConnectionDto } from './dto/connection.dto'
@WebSocketGateway({
cors: { origin: /^(http|ws):\/\/localhost(:\d+)?$/ }
})
@ -36,7 +35,9 @@ export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
private readonly connectedUserRepository: Repository<ConnectedUser>
) {}
async handleConnection (socket: Socket): Promise<void> {}
async handleConnection (socket: Socket): Promise<void> {
console.log('Client connected: ' + socket.id)
}
handleDisconnect (socket: Socket): void {
socket.disconnect()
@ -44,20 +45,25 @@ export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
@SubscribeMessage('joinChannel')
async onJoinChannel (socket: Socket, connect: ConnectionDto): Promise<void> {
const channel = await this.chatService.getChannel(connect.ChannelId)
if (channel.banned.find((ban) => ban.id === connect.UserId) !== null)
console.log(connect.ChannelId, connect.UserId, connect.pwd)
const channel = await this.chatService.getFullChannel(connect.ChannelId)
if (channel.banned.find((ban) => ban.id === connect.UserId) !== null) {
throw new WsException('You are banned from entering this channel')
}
const user = (await this.userService.findUser(connect.UserId)) as User
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// We don't need to verify if the user is already in imo
//
//if (
// if (
// channel.users.find((usr) => usr.id === user.id) == null &&
// channel.password !== ''
//) {
if (channel.password !== '' && !(await bcrypt.compare(channel.password, connect.pwd)))
throw new WsException('Wrong password')
else await this.chatService.addUserToChannel(channel, user)
// ) {
if (
channel.password !== '' &&
!(await bcrypt.compare(channel.password, connect.pwd))
) {
throw new WsException('Wrong password')
} else await this.chatService.addUserToChannel(channel, user)
{
const conUser = new ConnectedUser()
@ -67,8 +73,10 @@ export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
await this.connectedUserRepository.save(conUser)
}
const messages =
await this.messageService.findMessagesInChannelForUser(channel, user)
const messages = await this.messageService.findMessagesInChannelForUser(
channel,
user
)
this.server.to(socket.id).emit('messages', messages)
await socket.join(channel.name)
}

2
back/volume/src/chat/chat.module.ts

@ -1,4 +1,4 @@
import { forwardRef, Module } from '@nestjs/common'
import { Module } from '@nestjs/common'
import { TypeOrmModule } from '@nestjs/typeorm'
import { AuthModule } from 'src/auth/auth.module'

30
back/volume/src/chat/chat.service.ts

@ -32,7 +32,7 @@ export class ChatService {
return await this.ChannelRepository.save(newChannel)
}
async updatePassword (id: number, password: string) {
async updatePassword (id: number, password: string): Promise<void> {
const channel: Channel | null = await this.ChannelRepository.findOneBy({
id
})
@ -89,7 +89,7 @@ export class ChatService {
async getFullChannel (id: number): Promise<Channel> {
const channel = await this.ChannelRepository.findOne({
where: { id },
relations: ['users', 'admins', 'banned', 'muted', 'owner']
relations: ['users', 'admins', 'banned', 'owner']
})
if (channel == null) {
throw new NotFoundException(`Channel #${id} not found`)
@ -97,15 +97,15 @@ export class ChatService {
return channel
}
async update (channel: Channel) {
async update (channel: Channel): Promise<void> {
await this.ChannelRepository.update(channel.id, channel)
}
async save (channel: Channel) {
async save (channel: Channel): Promise<void> {
await this.ChannelRepository.save(channel)
}
async removeChannel (channelId: number) {
async removeChannel (channelId: number): Promise<void> {
await this.ChannelRepository.delete(channelId)
}
@ -114,7 +114,7 @@ export class ChatService {
where: { id },
relations: { owner: true }
})
if (channel == null) {
if (channel === null) {
throw new NotFoundException(`Channel #${id} not found`)
}
return channel.owner.ftId === userId
@ -125,10 +125,10 @@ export class ChatService {
where: { id },
relations: { admins: true }
})
if (channel == null) {
if (channel === null) {
throw new NotFoundException(`Channel #${id} not found`)
}
return channel.admins.findIndex((user) => user.ftId === userId) != -1
return channel.admins.findIndex((user) => user.ftId === userId) !== -1
}
async isUser (id: number, userId: number): Promise<boolean> {
@ -136,10 +136,10 @@ export class ChatService {
where: { id },
relations: { users: true }
})
if (channel == null) {
if (channel === null) {
throw new NotFoundException(`Channel #${id} not found`)
}
return channel.users.findIndex((user) => user.ftId === userId) != -1
return channel.users.findIndex((user) => user.ftId === userId) !== -1
}
async isBanned (id: number, userId: number): Promise<boolean> {
@ -147,10 +147,10 @@ export class ChatService {
where: { id },
relations: { banned: true }
})
if (channel == null) {
if (channel === null) {
throw new NotFoundException(`Channel #${id} not found`)
}
return channel.banned.findIndex((user) => user.ftId === userId) != -1
return channel.banned.findIndex((user) => user.ftId === userId) !== -1
}
async getMuteDuration (id: number, userId: number): Promise<number> {
@ -158,16 +158,14 @@ export class ChatService {
where: { id },
relations: { muted: true }
})
if (channel == null) {
if (channel === null) {
throw new NotFoundException(`Channel #${id} not found`)
}
const mutation: number[] | undefined = channel.muted.find(
(mutation) => mutation[0] === userId
)
if (mutation == null) {
return 0
}
if (mutation == null) return 0
return mutation[1]
}
}

1
back/volume/src/chat/dto/create-channel.dto.ts

@ -1,7 +1,6 @@
import { Transform } from 'class-transformer'
import {
IsPositive,
IsAlpha,
IsString,
IsOptional,
IsNumber,

2
back/volume/src/chat/entity/channel.entity.ts

@ -28,7 +28,7 @@ export default class Channel {
password: string
@BeforeInsert()
async hashPassword () {
async hashPassword (): Promise<void> {
if (this.password === '') return
this.password = await bcrypt.hash(
this.password,

8
back/volume/src/chat/entity/connection.entity.ts

@ -1,10 +1,4 @@
import {
Column,
Entity,
JoinColumn,
OneToOne,
PrimaryGeneratedColumn
} from 'typeorm'
import { Entity, JoinColumn, OneToOne, PrimaryGeneratedColumn } from 'typeorm'
import Channel from './channel.entity'
import User from 'src/users/entity/user.entity'

3
back/volume/src/users/entity/user.entity.ts

@ -2,13 +2,10 @@ import {
Entity,
PrimaryGeneratedColumn,
Column,
OneToMany,
ManyToMany,
JoinTable
} from 'typeorm'
import Message from 'src/chat/entity/message.entity'
import Channel from 'src/chat/entity/channel.entity'
import Result from 'src/pong/entity/result.entity'
@Entity()

49
back/volume/src/users/users.controller.ts

@ -11,16 +11,16 @@ import {
Res,
StreamableFile,
BadRequestException,
Redirect
Redirect,
Delete
} from '@nestjs/common'
import { FileInterceptor } from '@nestjs/platform-express'
import { diskStorage } from 'multer'
import { type User } from "./entity/user.entity";
import { UsersService } from "./users.service";
import { UserDto, AvatarUploadDto } from "./dto/user.dto";
import { PongService } from "src/pong/pong.service";
import { type User } from './entity/user.entity'
import { UsersService } from './users.service'
import { UserDto, AvatarUploadDto } from './dto/user.dto'
import { AuthenticatedGuard } from 'src/auth/42-auth.guard'
import { Profile42 } from 'src/auth/42.decorator'
@ -35,24 +35,33 @@ import { join } from 'path'
export class UsersController {
constructor (private readonly usersService: UsersService) {}
@Post('block/:id')
@Get('block/:id')
@UseGuards(AuthenticatedGuard)
@Post("block/:id")
async blockUser(@Profile42() profile :Profile, @Param('id') id:number) {
const user = await this.usersService.findUser(id) as User
user.blocked.push((await this.usersService.findUser(+profile.id)) as User)
this.usersService.save(user)
async blockUser (
@Profile42() profile: Profile,
@Param('id') id: number
): Promise<void> {
const user = await this.usersService.findUser(profile.id)
const target = await this.usersService.findUser(id)
if (user === null || target === null) {
throw new BadRequestException('User not found')
}
user.blocked.push(target)
await this.usersService.save(user)
}
@Post('unblock/:id')
@Delete('block/:id')
@UseGuards(AuthenticatedGuard)
@Post("unblock/:id")
async unblockUser(@Profile42() profile :Profile, @Param('id') id:number) {
const user = await this.usersService.findUser(id) as User
user.blocked = user.blocked.filter((usr: User) => {
async unblockUser (
@Profile42() profile: Profile,
@Param('id') id: number
): Promise<void> {
const user = await this.usersService.findUser(profile.id)
if (user === null) throw new BadRequestException('User not found')
user.blocked = user.blocked.filter((usr: User) => {
return usr.id !== id
})
this.usersService.save(user)
await this.usersService.save(user)
}
@Get('all')
@ -100,10 +109,10 @@ export class UsersController {
}
})
)
@ApiConsumes("multipart/form-data")
@ApiConsumes('multipart/form-data')
@ApiBody({
description: "A new avatar for the user",
type: AvatarUploadDto,
description: 'A new avatar for the user',
type: AvatarUploadDto
})
async changeAvatar (
@Profile42() profile: Profile,

1
back/volume/src/users/users.module.ts

@ -4,7 +4,6 @@ import { User } from './entity/user.entity'
import { UsersController } from './users.controller'
import { UsersService } from './users.service'
import { PongModule } from 'src/pong/pong.module'
import { ChatModule } from 'src/chat/chat.module'
@Module({
imports: [forwardRef(() => PongModule), TypeOrmModule.forFeature([User])],

6
back/volume/src/users/users.service.ts

@ -46,7 +46,7 @@ export class UsersService {
})
}
})
this.getLeaderboard()
await this.getLeaderboard()
}
async findUser (ftId: number): Promise<User | null> {
@ -125,7 +125,9 @@ export class UsersService {
let r = 0
ret.forEach((usr) => {
usr.rank = r++
this.usersRepository.save(usr)
this.usersRepository.save(usr).catch((err) => {
console.log(err)
})
usr.socketKey = ''
})
return ret

2
front/volume/src/Auth.ts

@ -11,7 +11,7 @@ export const API_URL = `http://${import.meta.env.VITE_HOST}:${
import.meta.env.VITE_BACK_PORT
}`;
export async function getUser(bypass: boolean = false) {
export async function getUser() {
const res = await fetch(API_URL + "/users", {
method: "get",
mode: "cors",

24
front/volume/src/components/Channels.svelte

@ -14,10 +14,13 @@
<script lang="ts">
//--------------------------------------------------------------------------------/
let channelMode = "";
const channelOptions = ['public','private','direct'];
const channelOptions = ["public", "private", "direct"];
const joinChannel = async (id: number) => {
socket.emit("joinChannel", id, $store.ftId);
socket.emit("joinChannel", {
UserId: $store.ftId,
ChannelId: id,
});
};
let channels: Array<ChannelsType> = [];
@ -46,7 +49,7 @@
const name = prompt("Enter a name for the new channel:");
if (name) {
let password = "";
if (channelMode !== 'direct')
if (channelMode !== "direct")
password = prompt("Enter a password for the new channel:");
const response = await fetch(API_URL + "/channels", {
credentials: "include",
@ -166,13 +169,16 @@
<p>No channels available</p>
{/if}
<div>
<select bind:value={channelMode} >
<select bind:value={channelMode}>
{#each channelOptions as option}
<option value={option} selected={channelMode === option}>{option}</option>
<option value={option} selected={channelMode === option}
>{option}</option
>
{/each}
</select>
{#if channelMode!= ''}
<button class="button" on:click={createChannel}>Create Channel</button>
{#if channelMode != ""}
<button class="button" on:click={createChannel}>Create Channel</button
>
{/if}
</div>
</div>
@ -223,7 +229,7 @@
}
button {
background-color: #6B8E23;
background-color: #6b8e23;
color: #ffffff;
border: none;
border-radius: 5px;
@ -248,7 +254,7 @@
}
.button {
background-color: #6B8E23;
background-color: #6b8e23;
color: #ffffff;
border: none;
border-radius: 5px;

361
front/volume/src/components/Chat.svelte

@ -1,29 +1,28 @@
<script lang="ts" context="module">
export interface chatMessagesType {
id: number;
author: string;
text: string;
}
import { createEventDispatcher, onDestroy, onMount } from "svelte";
import { store, API_URL } from "../Auth";
import { socket } from "../socket"
import type { ChannelsType } from "./Channels.svelte";
import type User from "./Profile.svelte";
export interface chatMessagesType {
id: number;
author: string;
text: string;
}
import { createEventDispatcher, onDestroy, onMount } from "svelte";
import { store, API_URL } from "../Auth";
import { socket } from "../socket";
import type { ChannelsType } from "./Channels.svelte";
import type User from "./Profile.svelte";
</script>
<script lang="ts">
let blockedUsers: Array<User> = [];
let chatMembers: Array<User> = [];
let chatMessages: Array<chatMessagesType> = [];
export let channel: ChannelsType;
let newText = "";
onMount(async () => {
let res = await fetch(API_URL + "/users/" + $store.ftId + "/blocked", {
credentials: "include",
mode: "cors",
});
if (res.ok) blockedUsers = await res.json();
let blockedUsers: Array<User> = [];
let chatMembers: Array<User> = [];
let chatMessages: Array<chatMessagesType> = [];
export let channel: ChannelsType;
let newText = "";
onMount(async () => {
let res = await fetch(API_URL + "/users/block/" + $store.ftId, {
credentials: "include",
mode: "cors",
});
if (res.ok) blockedUsers = await res.json();
socket.on("messages", (msgs: Array<chatMessagesType>) => {
chatMessages = msgs;
@ -42,11 +41,13 @@ import type User from "./Profile.svelte";
const sendMessage = () => {
if (newText !== "") {
/*
const newMessage = {
id: chatMessages.length + 1,
author: $store.username,
text: newText,
};
*/
chatMessages = [...chatMessages.slice(-5 + 1)];
socket.emit("addMessage", channel.id, $store.ftId, newText);
newText = "";
@ -83,111 +84,154 @@ import type User from "./Profile.svelte";
//--------------------------------------------------------------------------------/
const blockUser = async (username: string) => {
const res1 = await fetch(API_URL + "/users/" + username + "/byname", {
credentials: "include",
mode: "cors",
});
const data1 = await res1.json();
const res2 = await fetch(API_URL + "/users/block/" + data1.ftId, {
let response = await fetch(API_URL + "/users/" + username + "/byname", {
credentials: "include",
method: "POST",
mode: "cors",
});
if (res2.ok) {
alert("User blocked");
} else {
alert("Failed to block user");
if (response.ok) {
const target = await response.json();
response = await fetch(API_URL + "/users/" + target.ftId + "/block", {
credentials: "include",
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ id: target.ftId }),
});
}
if (response.ok) alert("User blocked");
else alert("Failed to block user");
};
//--------------------------------------------------------------------------------/
const unblockUser = async (username: string) => {
const res1 = await fetch(API_URL + "/users/" + username + "/byname", {
credentials: "include",
mode: "cors",
});
const data1 = await res1.json();
const res2 = await fetch(API_URL + "/users/unblock/" + data1.ftId, {
let response = await fetch(API_URL + "/users/" + username + "/byname", {
credentials: "include",
method: "DELETE",
mode: "cors",
});
if (res2.ok) {
alert("User unblocked");
} else {
alert("Failed to unblock user");
if (response.ok) {
const target = await response.json();
response = await fetch(API_URL + "/users/" + target.ftId + "/block", {
credentials: "include",
method: "DELETE",
mode: "cors",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ id: target.ftId }),
});
}
if (response.ok) alert("User blocked");
else alert("Failed to block user");
};
//--------------------------------------------------------------------------------/
const banUser = async (username: string) => {
const prompt = window.prompt("Enter ban duration in seconds");
const res1 = await fetch(API_URL + "/users/" + username + "/byname", {
let response = await fetch(API_URL + "/users/" + username + "/byname", {
credentials: "include",
mode: "cors",
});
const data1 = await res1.json();
const res2 = await fetch(API_URL + "/channels/" + data1.ftId + "/ban", {
if (response.ok) {
const target = await response.json();
response = await fetch(API_URL + "/channels/" + channel.id + "/ban", {
credentials: "include",
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ id: target.ftId }),
});
socket.emit("kickUser", channel.id, $store.ftId, target.ftId);
}
if (response.ok) {
alert("User banned");
} else alert("Failed to ban user");
};
//--------------------------------------------------------------------------------/
const unbanUser = async (username: string) => {
let response = await fetch(API_URL + "/users/" + username + "/byname", {
credentials: "include",
method: "POST",
mode: "cors",
});
if (res2.ok) {
socket.emit("kickUser", channel.id, $store.ftId, data1.ftId);
alert("User banned");
} else {
alert("Failed to ban user");
if (response.ok) {
const target = await response.json();
response = await fetch(API_URL + "/channels/" + channel.id + "/ban", {
credentials: "include",
method: "DELETE",
mode: "cors",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ id: target.ftId }),
});
}
if (response.ok) alert("User unbanned");
else alert("Failed to unban user");
};
//--------------------------------------------------------------------------------/
const kickUser = async (username: string) => {
const res = await fetch(API_URL + "/users/" + username + "/byname", {
const response = await fetch(API_URL + "/users/" + username + "/byname", {
credentials: "include",
mode: "cors",
});
const kickedUser = await res.json();
socket.emit("kickUser", channel.id, $store.ftId, kickedUser.ftId);
if (response.ok) {
const target = await response.json();
socket.emit("kickUser", channel.id, $store.ftId, target.ftId);
}
};
//--------------------------------------------------------------------------------/
const muteUser = async (username: string) => {
const prompt = window.prompt("Enter mute duration in seconds");
const res1 = await fetch(API_URL + "/users/" + username + "/byname", {
let response = await fetch(API_URL + "/users/" + username + "/byname", {
credentials: "include",
mode: "cors",
});
const data1 = await res1.json();
const res2 = await fetch(API_URL + "/channels/" + data1.ftId + "/mute", {
credentials: "include",
method: "POST",
mode: "cors",
});
if (res2.ok) {
alert("User muted");
} else {
alert("Failed to mute user");
const target = await response.json();
if (response.ok) {
response = await fetch(API_URL + "/channels/" + channel.id + "/mute", {
credentials: "include",
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ data: [target.ftId, +prompt] }),
});
}
if (response.ok) alert("User muted");
else alert("Failed to mute user");
};
//--------------------------------------------------------------------------------/
const adminUser = async (username: string) => {
const res1 = await fetch(API_URL + "/users/" + username + "/byname", {
let response = await fetch(API_URL + "/users/" + username + "/byname", {
credentials: "include",
mode: "cors",
});
const data1 = await res1.json();
const res2 = await fetch(API_URL + "/channels/" + data1.ftId + "/admin", {
credentials: "include",
method: "POST",
mode: "cors",
});
if (res2.ok) {
if (response.ok) {
const target = await response.json();
response = await fetch(API_URL + "/channels/" + channel.id + "/admin", {
credentials: "include",
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ id: target.ftId }),
});
}
if (response.ok) {
alert("User admined");
} else {
alert("Failed to admin user");
@ -197,99 +241,124 @@ import type User from "./Profile.svelte";
//--------------------------------------------------------------------------------/
const removeAdminUser = async (username: string) => {
const res1 = await fetch(API_URL + "/users/" + username + "/byname", {
let response = await fetch(API_URL + "/users/" + username + "/byname", {
credentials: "include",
mode: "cors",
});
const data1 = await res1.json();
const res2 = await fetch(API_URL + "/channels/" + data1.ftId + "/admin", {
credentials: "include",
method: "DELETE",
mode: "cors",
});
if (res2.ok) {
alert("User admin removed");
if (response.ok) {
const target = await response.json();
response = await fetch(API_URL + "/channels/" + channel.id + "/admin", {
credentials: "include",
method: "DELETE",
mode: "cors",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ id: target.ftId }),
});
}
if (response.ok) {
alert("User admined");
} else {
alert("Failed to remove admin user");
alert("Failed to admin user");
}
};
//--------------------------------------------------------------------------------/
</script>
<div class="overlay" >
<div class="overlay">
<div class="chat" on:click|stopPropagation on:keydown|stopPropagation>
<div class="messages" >
{ #each chatMessages as message }
<p class="message" >
{ #if !blockedUsers.filter((user) => user.username == message.author).length }
<span
class="message-name"
on:click = {() => openProfile(message.author)}
on:keydown = {() => openProfile(message.author)}
style = "cursor: pointer;"
>
{ message.author }
</span>: {message.text}
<div class="messages">
{#each chatMessages as message}
<p class="message">
{#if !blockedUsers.filter((user) => user.username == message.author).length}
<span
class="message-name"
on:click={() => openProfile(message.author)}
on:keydown={() => openProfile(message.author)}
style="cursor: pointer;"
>
{message.author}
</span>: {message.text}
{/if}
</p>
{/each}
</div>
{ #if showProfileMenu }
<div
class="profile-menu"
on:click|stopPropagation
on:keydown|stopPropagation
>
<ul>
<li>
<button on:click = {() => dispatch("send-message", selectedUser)}> Send Message </button>
</li>
<li>
<button on:click = {() => dispatch("view-profile", selectedUser)}> View Profile </button>
</li>
<li>
<button on:click = {() => dispatch("add-friend", selectedUser)}> Add Friend </button>
</li>
<li>
<button on:click = {() => dispatch("invite-to-game", selectedUser)}> Invite to Game </button>
</li>
<li>
{ #if !blockedUsers.filter((user) => user.username = selectedUser).length }
<button on:click = {() => blockUser(selectedUser)}> Block User </button>
{:else }
<button on:click = {() => unblockUser(selectedUser)}> Unblock User </button>
{/if}
</li>
<li> <button on:click = { closeProfileMenu } > Close </button></li >
</ul>
</div>
{#if showProfileMenu}
<div
class="profile-menu"
on:click|stopPropagation
on:keydown|stopPropagation
>
<ul>
<li>
<button on:click={() => dispatch("send-message", selectedUser)}>
Send Message
</button>
</li>
<li>
<button on:click={() => dispatch("view-profile", selectedUser)}>
View Profile
</button>
</li>
<li>
<button on:click={() => dispatch("add-friend", selectedUser)}>
Add Friend
</button>
</li>
<li>
<button on:click={() => dispatch("invite-to-game", selectedUser)}>
Invite to Game
</button>
</li>
<li>
{#if !blockedUsers.filter((user) => (user.username = selectedUser)).length}
<button on:click={() => blockUser(selectedUser)}>
Block User
</button>
{:else}
<button on:click={() => unblockUser(selectedUser)}>
Unblock User
</button>
{/if}
</li>
<li><button on:click={closeProfileMenu}> Close </button></li>
</ul>
</div>
{/if}
<form on:submit|preventDefault={ sendMessage }>
<input type="text" placeholder = "Type a message..." bind:value={ newText } />
<button>
<img src="img/send.png" alt = "send" />
</button>
<form on:submit|preventDefault={sendMessage}>
<input type="text" placeholder="Type a message..." bind:value={newText} />
<button>
<img src="img/send.png" alt="send" />
</button>
</form>
<button on:click|stopPropagation={ toggleChatMembers } on:keydown|stopPropagation > Chat Members </button>
{ #if showChatMembers }
<button
on:click|stopPropagation={toggleChatMembers}
on:keydown|stopPropagation
>
Chat Members
</button>
{#if showChatMembers}
<div
class="chatMembers"
on:click|stopPropagation
on:keydown|stopPropagation
>
</div>
/>
<ul>
{ #each chatMembers as member }
{#each chatMembers as member}
<li>
<p>
{ member.username }
<button on:click = {() => banUser(member.username)}> ban </button>
<button on:click = {() => kickUser(member.username)}> kick </button>
<button on:click = {() => muteUser(member.username)}> mute </button>
<button on:click = {() => adminUser(member.username)}> promote </button>
<button on:click = {() => removeAdminUser(member.username)}> demote </button>
{member.username}
<button on:click={() => banUser(member.username)}> ban </button>
<button on:click={() => kickUser(member.username)}> kick </button>
<button on:click={() => muteUser(member.username)}> mute </button>
<button on:click={() => adminUser(member.username)}>
promote
</button>
<button on:click={() => removeAdminUser(member.username)}>
demote
</button>
</p>
</li>
{/each}
@ -351,7 +420,7 @@ import type User from "./Profile.svelte";
}
button {
background-color: #6B8E23;
background-color: #6b8e23;
color: #ffffff;
border: none;
border-radius: 5px;

6
front/volume/src/components/Friends.svelte

@ -123,7 +123,8 @@
color: #e8e6e3;
}
h2, h3 {
h2,
h3 {
color: #e8e6e3;
}
@ -133,7 +134,8 @@
max-height: 200px;
}
input[type="text"], button {
input[type="text"],
button {
background-color: #198754;
border: none;
color: #e8e6e3;

6
front/volume/src/components/MatchHistory.svelte

@ -14,12 +14,6 @@
import { onMount } from "svelte";
export let username: string = "Global";
function formatDate(str: string) {
const splitT = str.split("T");
const splitDate = splitT[0].split("-");
const splitDot = splitT[1].split(".");
return `${splitDate[1]}/${splitDate[2]}-${splitDot[0]}`;
}
let page: number = 1;
let data: Array<Match> = [];
let newBatch: Array<Match> = [];

6
front/volume/src/components/NavBar.svelte

@ -1,5 +1,9 @@
<script lang="ts">
let api = "http://" + import.meta.env.VITE_HOST + ":" + import.meta.env.VITE_BACK_PORT;
let api =
"http://" +
import.meta.env.VITE_HOST +
":" +
import.meta.env.VITE_BACK_PORT;
export let links = [
{ text: "Home" },

2
front/volume/src/components/Pong/Pong.svelte

@ -22,7 +22,7 @@
export let appState: string;
export let setAppState: (newState: APPSTATE | string) => void;
const SERVER_URL = `ws://${import.meta.env.VITE_HOST}:${
const SERVER_URL = `http://${import.meta.env.VITE_HOST}:${
import.meta.env.VITE_BACK_PORT
}`;

2
front/volume/src/socket.ts

@ -1,3 +1,3 @@
import { io } from "socket.io-client";
import { io, Socket } from "socket.io-client";
export const socket: Socket = io("http://localhost:3001");

Loading…
Cancel
Save