stream day 6
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
<div class="w-full h-[calc(100%-60px)] overflow-y-scroll pb-1"
|
<div class="w-full h-[calc(100%-60px)] overflow-y-scroll pb-1"
|
||||||
id="conversation-pane">
|
id="conversation-pane">
|
||||||
<div>
|
<div>
|
||||||
<div v-if="!conversation">
|
<div v-if="conversation.length === 0">
|
||||||
<p>No messages yet</p>
|
<p>No messages yet</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else
|
<div v-else
|
||||||
@@ -11,10 +11,23 @@
|
|||||||
<div class="message-container">
|
<div class="message-container">
|
||||||
<div>
|
<div>
|
||||||
<div class="message-sender-text">
|
<div class="message-sender-text">
|
||||||
<p :class="(message.userId == user.id) ? 'message-sender-you' : 'message-sender'">
|
<p class="mb-1.5 font-semibold">
|
||||||
{{ message.userId }}</p>
|
{{ message.creator.username }}
|
||||||
|
</p>
|
||||||
<p class="break-words max-w-full">{{ message.body }}</p>
|
<p class="break-words max-w-full">{{ message.body }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<div v-for="invite in message.invites">
|
||||||
|
<div class="w-6/12 bg-[hsl(223,6.9%,19.8%)] p-4 rounded-md shadow-md mr-2">
|
||||||
|
<p class="text-sm font-semibold">You've been invited</p>
|
||||||
|
<span class="text-xl font-bold capitalize">{{ invite.server.name }}</span>
|
||||||
|
<div class="flex w-full justify-end">
|
||||||
|
<button @click="joinServer(invite)"
|
||||||
|
class="font-semibold rounded px-4 py-2 bg-green-700 hover:bg-green-600 transition-colors">Join</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -22,7 +35,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="conversation-input w-[calc(100vw-88px-240px)]">
|
<div class="conversation-input w-[calc(100vw-88px-240px)]">
|
||||||
<form @submit.prevent="sendMessage"
|
<form @submit.prevent="sendMessage"
|
||||||
@keydown.enter="sendMessage"
|
@keydown.enter.exact.prevent="sendMessage"
|
||||||
class="relative px-4 w-full">
|
class="relative px-4 w-full">
|
||||||
<div id="textbox"
|
<div id="textbox"
|
||||||
class="px-4 rounded-md w-full h-[44px] bg-[hsl(218,calc(1*7.9%),27.3%)] placeholder:text-[hsl(218,calc(1*4.6%),46.9%)] flex flex-row">
|
class="px-4 rounded-md w-full h-[44px] bg-[hsl(218,calc(1*7.9%),27.3%)] placeholder:text-[hsl(218,calc(1*4.6%),46.9%)] flex flex-row">
|
||||||
@@ -55,52 +68,88 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { useGlobalStore } from '~/stores/store';
|
import { useGlobalStore } from '~/stores/store';
|
||||||
import { io } from 'socket.io-client'
|
import { io } from 'socket.io-client'
|
||||||
|
import { IChannel, IInviteCode, IMessage } from '~/types';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['server'],
|
props: ['server'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
user: useGlobalStore().user,
|
user: storeToRefs(useGlobalStore()).user,
|
||||||
messageContent: '',
|
messageContent: '',
|
||||||
conversation: this.server.messages
|
conversation: this.server.messages as IMessage[],
|
||||||
|
canSendNotifications: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const socket = io();
|
const socket = io();
|
||||||
|
|
||||||
|
Notification.requestPermission().then((result) => {
|
||||||
|
const permission = (result === 'granted') ? true : false
|
||||||
|
this.canSendNotifications = permission
|
||||||
|
});
|
||||||
|
|
||||||
const conversationDiv = document.getElementById('conversation-pane');
|
const conversationDiv = document.getElementById('conversation-pane');
|
||||||
if (!conversationDiv) throw new Error('wtf');
|
if (!conversationDiv) throw new Error('conversation div not found')
|
||||||
setTimeout(() => {
|
this.scrollToBottom()
|
||||||
conversationDiv.scrollTop = conversationDiv.scrollHeight;
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on('connect', () => {
|
socket.on(`message-${route.params.id}`, (ev) => {
|
||||||
// listen for messages from the server
|
const { message } = ev
|
||||||
socket.on(`message-${route.params.id}`, (ev) => {
|
if (message.creator.id === this.user.id) return;
|
||||||
const { message } = ev
|
if (!document.hasFocus()) {
|
||||||
console.log(message.userId, this.user.id, message, this.conversation)
|
new Notification(`Message from @${message.creator.username}`, { body: message.body, tag: message.serverId });
|
||||||
if (message.userId == this.user.id) return;
|
}
|
||||||
|
|
||||||
this.conversation.push(message)
|
this.conversation.push(message)
|
||||||
|
|
||||||
const lastElementChild = conversationDiv.children[0]?.lastElementChild
|
const lastElementChild = conversationDiv.children[0]?.lastElementChild
|
||||||
if (!lastElementChild) return;
|
if (!lastElementChild) return;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
console.log(conversationDiv.scrollTop, conversationDiv.scrollHeight, conversationDiv.clientHeight, lastElementChild.clientHeight, (conversationDiv.scrollHeight - conversationDiv.clientHeight) - lastElementChild.clientHeight)
|
if (conversationDiv.scrollTop + 11.2 < (conversationDiv.scrollHeight - conversationDiv.clientHeight) - lastElementChild.clientHeight) return;
|
||||||
if (conversationDiv.scrollTop + 11.2 < (conversationDiv.scrollHeight - conversationDiv.clientHeight) - lastElementChild.clientHeight) return;
|
conversationDiv.scrollTop = conversationDiv.scrollHeight;
|
||||||
conversationDiv.scrollTop = conversationDiv.scrollHeight;
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
// updated() {
|
||||||
|
// const route = useRoute()
|
||||||
|
// const socket = io();
|
||||||
|
|
||||||
|
// const conversationDiv = document.getElementById('conversation-pane');
|
||||||
|
// if (!conversationDiv) throw new Error('conversation div not found')
|
||||||
|
// this.scrollToBottom()
|
||||||
|
|
||||||
|
// socket.removeAllListeners('connect')
|
||||||
|
|
||||||
|
// socket.on('connect', () => {
|
||||||
|
// // listen for messages from the server
|
||||||
|
// socket.on(`message-${route.params.id}`, (ev) => {
|
||||||
|
// const { message } = ev
|
||||||
|
// console.log(message.userId, this.user.id, message, this.conversation)
|
||||||
|
// if (message.userId == this.user.id) return;
|
||||||
|
|
||||||
|
// this.conversation.push(message)
|
||||||
|
|
||||||
|
// const lastElementChild = conversationDiv.children[0]?.lastElementChild
|
||||||
|
// if (!lastElementChild) return;
|
||||||
|
|
||||||
|
// setTimeout(() => {
|
||||||
|
// console.log(conversationDiv.scrollTop, conversationDiv.scrollHeight, conversationDiv.clientHeight, lastElementChild.clientHeight, (conversationDiv.scrollHeight - conversationDiv.clientHeight) - lastElementChild.clientHeight)
|
||||||
|
// if (conversationDiv.scrollTop + 11.2 < (conversationDiv.scrollHeight - conversationDiv.clientHeight) - lastElementChild.clientHeight) return;
|
||||||
|
// conversationDiv.scrollTop = conversationDiv.scrollHeight;
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// });
|
||||||
|
// },
|
||||||
methods: {
|
methods: {
|
||||||
async sendMessage() {
|
async sendMessage() {
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
if (!this.messageContent) return;
|
if (!this.messageContent) return;
|
||||||
|
|
||||||
const { message } = await $fetch(`/api/channels/sendMessage`, { method: 'post', body: { body: this.messageContent, channelId: route.params.id } })
|
const message: IChannel = await $fetch(`/api/channels/sendMessage`, { method: 'post', body: { body: this.messageContent, channelId: route.params.id } })
|
||||||
|
|
||||||
|
if (!message) return;
|
||||||
|
if (this.conversation.includes(message)) return;
|
||||||
|
|
||||||
this.conversation.push(message)
|
this.conversation.push(message)
|
||||||
this.messageContent = '';
|
this.messageContent = '';
|
||||||
@@ -110,6 +159,18 @@ export default {
|
|||||||
conversationDiv.scrollTop = conversationDiv.scrollHeight;
|
conversationDiv.scrollTop = conversationDiv.scrollHeight;
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
async joinServer(invite: IInviteCode) {
|
||||||
|
const { server } = await $fetch('/api/guilds/joinGuild', { method: 'POST', body: { inviteId: invite.id } })
|
||||||
|
if (!server) return;
|
||||||
|
this.user.servers?.push(server)
|
||||||
|
},
|
||||||
|
scrollToBottom() {
|
||||||
|
const conversationDiv = document.getElementById('conversation-pane');
|
||||||
|
if (!conversationDiv) throw new Error('wtf');
|
||||||
|
setTimeout(() => {
|
||||||
|
conversationDiv.scrollTop = conversationDiv.scrollHeight;
|
||||||
|
})
|
||||||
|
}
|
||||||
// resizeTextarea() {
|
// resizeTextarea() {
|
||||||
// const textArea = document.getElementById('messageBox')
|
// const textArea = document.getElementById('messageBox')
|
||||||
// const textBox = document.getElementById('textBox')
|
// const textBox = document.getElementById('textBox')
|
||||||
|
|||||||
@@ -15,25 +15,66 @@
|
|||||||
<div class="w-full"
|
<div class="w-full"
|
||||||
v-else>
|
v-else>
|
||||||
<div class="flex p-4 border-b border-zinc-600/80">
|
<div class="flex p-4 border-b border-zinc-600/80">
|
||||||
<h4 class="text-lg font-semibold w-fit ">
|
<h4 class="text-lg font-semibold grid gap-1 grid-cols-[1fr_28px] w-full">
|
||||||
{{ server.name }}
|
<span>{{ server.name }}</span>
|
||||||
|
<button class="cursor-pointer p-1 hover:backdrop-brightness-110 transition-all">
|
||||||
|
<span class="h-fit w-[20px]">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24">
|
||||||
|
<path fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="m6 9l6 6l6-6" />
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-y-1.5 px-1.5 mt-2 flex-col">
|
<div class="flex gap-y-1.5 px-1.5 mt-2 flex-col">
|
||||||
<div class="flex text-center hover:bg-zinc-600/70 px-2 py-1.5 w-full transition-colors rounded drop-shadow-sm"
|
<button @click="createInvite"
|
||||||
|
v-if="userIsOwnerOrAdmin">make invite</button>
|
||||||
|
<button
|
||||||
|
class="flex text-center hover:bg-zinc-600/70 px-2 py-1.5 w-full transition-colors rounded drop-shadow-sm gap-1/5 cursor-pointer"
|
||||||
v-for="channel in server.channels"
|
v-for="channel in server.channels"
|
||||||
|
@click="openChannel(channel.id)"
|
||||||
:key="channel.id">
|
:key="channel.id">
|
||||||
<svg width="24"
|
<span>
|
||||||
height="24"
|
<svg class="text-zinc-300 my-auto"
|
||||||
viewBox="0 0 24 24">
|
width="20"
|
||||||
<path fill="none"
|
height="20"
|
||||||
stroke="currentColor"
|
viewBox="0 0 24 24">
|
||||||
stroke-linecap="round"
|
<path fill="none"
|
||||||
stroke-linejoin="round"
|
stroke="currentColor"
|
||||||
stroke-width="2"
|
stroke-linecap="round"
|
||||||
d="M5 9h14M5 15h14M11 4L7 20M17 4l-4 16" />
|
stroke-linejoin="round"
|
||||||
</svg> {{ channel.name }}
|
stroke-width="2"
|
||||||
</div>
|
d="M5 9h14M5 15h14M11 4L7 20M17 4l-4 16" />
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span>{{ channel.name }}</span>
|
||||||
|
</button>
|
||||||
|
<button v-if="userIsOwnerOrAdmin"
|
||||||
|
@click="openCreateChannelModel"
|
||||||
|
class="flex text-center hover:bg-zinc-600/70 px-2 py-1.5 w-full transition-colors rounded drop-shadow-sm cursor-pointer">
|
||||||
|
<span>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24">
|
||||||
|
<path fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M12 5v14m-7-7h14" />
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span>Add channel</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -64,10 +105,72 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-if="createChannelModelOpen"
|
||||||
|
class="absolute z-10 top-0 bottom-0 left-0 right-0">
|
||||||
|
<div class="bg-zinc-900/80 w-screen h-screen"
|
||||||
|
@click="createChannelModelOpen = false">
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="p-4 z-20 absolute bg-zinc-800 shadow-md rounded-md -translate-x-1/2 -translate-y-1/2 top-1/2 left-1/2 text-white">
|
||||||
|
<h2 class="font-semibold text-xl">
|
||||||
|
Create a channel:
|
||||||
|
</h2>
|
||||||
|
<div>
|
||||||
|
<form @submit.prevent="createChannel"
|
||||||
|
class="w-3/5">
|
||||||
|
<input v-model="channelName"
|
||||||
|
type="text"
|
||||||
|
class="py-2 px-3 rounded-md mb-2 bg-zinc-700 shadow-md border border-zinc-700/80"
|
||||||
|
placeholder="Channel name" />
|
||||||
|
<input type="submit"
|
||||||
|
class="py-2 px-3 rounded-md bg-zinc-700 shadow-md border border-zinc-700/80" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { IRole, IServer } from '~/types';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
createChannelModelOpen: false,
|
||||||
|
channelName: '',
|
||||||
|
userIsOwnerOrAdmin: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!this.server.roles) {
|
||||||
|
console.log(this.server)
|
||||||
|
throw new Error('server must be null');
|
||||||
|
}
|
||||||
|
this.userIsOwnerOrAdmin = this.server.roles.find((e: IRole) => e.users.some((el) => el.id === this.user.id)).owner ||
|
||||||
|
this.server.roles.find((e: IRole) => e.users.some((el) => el.id === this.user.id)).administrator
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
openCreateChannelModel() {
|
||||||
|
this.createChannelModelOpen = true;
|
||||||
|
},
|
||||||
|
async createChannel() {
|
||||||
|
const channel = await $fetch(`/api/guilds/${this.server.id}/addChannel`, { method: 'POST', body: { channelName: this.channelName } })
|
||||||
|
|
||||||
|
this.server.channels.push(channel)
|
||||||
|
this.createChannelModelOpen = false;
|
||||||
|
},
|
||||||
|
openChannel(id: string) {
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
router.push({ params: { id } })
|
||||||
|
},
|
||||||
|
async createInvite() {
|
||||||
|
const inviteCode = await $fetch(`/api/guilds/${this.server.id}/createInvite`, { method: 'POST' })
|
||||||
|
},
|
||||||
|
},
|
||||||
props: ['server', 'user']
|
props: ['server', 'user']
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -1,18 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="user.id" class="flex h-screen max-h-screen text-white">
|
<Suspense>
|
||||||
<Nav :user="user"/>
|
<div v-if="user.id"
|
||||||
<Sidebar :server="activeServer"
|
class="flex h-screen max-h-screen text-white">
|
||||||
:user="user" />
|
<Nav :user="user" />
|
||||||
<div class="w-[calc(100vw-88px-240px)] h-full">
|
<Sidebar :server="activeServer"
|
||||||
<slot />
|
:user="user" />
|
||||||
|
<div class="w-[calc(100vw-88px-240px)] h-full">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<template #fallback>
|
||||||
|
Loading...
|
||||||
|
</template>
|
||||||
|
</Suspense>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Nav, Sidebar } from '~/.nuxt/components'
|
import { Nav, Sidebar } from '~/.nuxt/components'
|
||||||
import { useGlobalStore } from '~/stores/store'
|
import { useGlobalStore } from '~/stores/store'
|
||||||
import { IUser } from '~/types'
|
import { SafeUser } from '~/types'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -26,7 +33,7 @@ export default {
|
|||||||
const userStore = useGlobalStore()
|
const userStore = useGlobalStore()
|
||||||
const sessionToken = useCookie('sessionToken')
|
const sessionToken = useCookie('sessionToken')
|
||||||
if (userStore.user.id === undefined && sessionToken.value) {
|
if (userStore.user.id === undefined && sessionToken.value) {
|
||||||
const user: IUser = await $fetch('/api/getCurrentUser')
|
const user: SafeUser = await $fetch('/api/getCurrentUser')
|
||||||
|
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,16 @@
|
|||||||
<MessagePane :server="server" />
|
<MessagePane :server="server" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script async setup lang="ts">
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const server: IChannel = await $fetch(`/api/channels/${route.params.id}`)
|
||||||
|
if (server) {
|
||||||
|
useGlobalStore().addDM(server);
|
||||||
|
useGlobalStore().setActive('dms', server.id);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { useGlobalStore } from '~/stores/store'
|
import { useGlobalStore } from '~/stores/store'
|
||||||
import { IChannel } from '~/types'
|
import { IChannel } from '~/types'
|
||||||
@@ -11,18 +21,6 @@ definePageMeta({
|
|||||||
})
|
})
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
async setup() {
|
|
||||||
const route = useRoute()
|
|
||||||
|
|
||||||
const server: IChannel = await $fetch(`/api/channels/${route.params.id}`)
|
|
||||||
if (!server) return;
|
|
||||||
useGlobalStore().addDM(server);
|
|
||||||
useGlobalStore().setActive('dms', server.id);
|
|
||||||
|
|
||||||
return {
|
|
||||||
server,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async updated() {
|
async updated() {
|
||||||
if (!useGlobalStore().activeServer == this.server) useGlobalStore().setActive('dms', this.server.id)
|
if (!useGlobalStore().activeServer == this.server) useGlobalStore().setActive('dms', this.server.id)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const route = useRoute()
|
|||||||
|
|
||||||
const server: IChannel = await $fetch(`/api/channels/${route.params.id}`)
|
const server: IChannel = await $fetch(`/api/channels/${route.params.id}`)
|
||||||
|
|
||||||
const realServer = useGlobalStore().user.servers.filter((e) => e.channels.some((el) => el.id == route.params.id))[0]
|
const realServer = useGlobalStore().user.servers?.filter((e) => e.channels.some((el) => el.id == route.params.id))[0]
|
||||||
|
|
||||||
if (realServer) {
|
if (realServer) {
|
||||||
useGlobalStore().addServer(realServer);
|
useGlobalStore().addServer(realServer);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { useGlobalStore } from '~/stores/store'
|
import { useGlobalStore } from '~/stores/store'
|
||||||
import { IUser } from '~/types';
|
import { SafeUser } from '~/types';
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: 'clean'
|
layout: 'clean'
|
||||||
@@ -43,7 +43,7 @@ export default {
|
|||||||
username: this.username,
|
username: this.username,
|
||||||
password: this.password
|
password: this.password
|
||||||
}
|
}
|
||||||
}) as { userId: string; token: string; user: IUser; }
|
}) as { userId: string; token: string; user: SafeUser; }
|
||||||
|
|
||||||
const userId = useCookie('userId')
|
const userId = useCookie('userId')
|
||||||
userId.value = user.userId
|
userId.value = user.userId
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { NuxtLink } from '~/.nuxt/components';
|
import { NuxtLink } from '~/.nuxt/components';
|
||||||
import { useGlobalStore } from '~/stores/store'
|
import { useGlobalStore } from '~/stores/store'
|
||||||
import { IUser } from '~/types';
|
import { SafeUser } from '~/types';
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: 'clean'
|
layout: 'clean'
|
||||||
@@ -55,7 +55,7 @@ export default {
|
|||||||
email: this.email,
|
email: this.email,
|
||||||
password: this.password
|
password: this.password
|
||||||
}
|
}
|
||||||
}) as { userId: string; token: string; user: IUser; }
|
}) as { userId: string; token: string; user: SafeUser; }
|
||||||
|
|
||||||
const userId = useCookie('userId')
|
const userId = useCookie('userId')
|
||||||
userId.value = user.userId
|
userId.value = user.userId
|
||||||
|
|||||||
@@ -13,17 +13,29 @@ model User {
|
|||||||
username String @unique
|
username String @unique
|
||||||
passwordhash String
|
passwordhash String
|
||||||
servers Server[]
|
servers Server[]
|
||||||
serverId String?
|
|
||||||
messages Message[]
|
messages Message[]
|
||||||
session Session[]
|
session Session[]
|
||||||
channels Channel[]
|
channels Channel[]
|
||||||
|
roles Role[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model Server {
|
model Server {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String
|
name String
|
||||||
participants User[]
|
participants User[]
|
||||||
channels Channel[]
|
channels Channel[]
|
||||||
|
roles Role[]
|
||||||
|
InviteCode InviteCode[]
|
||||||
|
}
|
||||||
|
|
||||||
|
model Role {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
name String
|
||||||
|
administrator Boolean @default(false)
|
||||||
|
owner Boolean @default(false)
|
||||||
|
users User[]
|
||||||
|
server Server? @relation(fields: [serverId], references: [id])
|
||||||
|
serverId String?
|
||||||
}
|
}
|
||||||
|
|
||||||
model Channel {
|
model Channel {
|
||||||
@@ -32,17 +44,29 @@ model Channel {
|
|||||||
server Server? @relation(fields: [serverId], references: [id])
|
server Server? @relation(fields: [serverId], references: [id])
|
||||||
serverId String?
|
serverId String?
|
||||||
messages Message[]
|
messages Message[]
|
||||||
DM Boolean?
|
DM Boolean @default(false)
|
||||||
dmParticipants User[]
|
dmParticipants User[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model Message {
|
model Message {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
body String
|
body String
|
||||||
channel Channel @relation(fields: [channelId], references: [id])
|
channel Channel @relation(fields: [channelId], references: [id])
|
||||||
creator User @relation(fields: [userId], references: [id])
|
creator User @relation(fields: [userId], references: [id])
|
||||||
userId String
|
userId String
|
||||||
channelId String
|
channelId String
|
||||||
|
invites InviteCode[]
|
||||||
|
}
|
||||||
|
|
||||||
|
model InviteCode {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
server Server @relation(fields: [serverId], references: [id])
|
||||||
|
expires Boolean @default(false)
|
||||||
|
expiryDate DateTime?
|
||||||
|
maxUses Int @default(0)
|
||||||
|
serverId String
|
||||||
|
Message Message? @relation(fields: [messageId], references: [id])
|
||||||
|
messageId String?
|
||||||
}
|
}
|
||||||
|
|
||||||
model Session {
|
model Session {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IChannel, IServer, IUser } from '../../../../types'
|
import { IChannel, IServer, SafeUser } from '../../../../types'
|
||||||
import { PrismaClient } from '@prisma/client'
|
import { PrismaClient } from '@prisma/client'
|
||||||
const prisma = new PrismaClient()
|
const prisma = new PrismaClient()
|
||||||
|
|
||||||
@@ -20,11 +20,47 @@ export default defineEventHandler(async (event) => {
|
|||||||
where: {
|
where: {
|
||||||
id: event.context.params.id
|
id: event.context.params.id
|
||||||
},
|
},
|
||||||
include: {
|
select: {
|
||||||
messages: true,
|
id: true,
|
||||||
dmParticipants: true
|
name: true,
|
||||||
|
server: {
|
||||||
|
select: {
|
||||||
|
id: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
messages: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
body: true,
|
||||||
|
creator: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
username: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
invites: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
server: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DM: true,
|
||||||
|
dmParticipants: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
username: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
serverId: true,
|
||||||
}
|
}
|
||||||
}) as IChannel
|
}) as IChannel | null;
|
||||||
|
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
event.node.res.statusCode = 404;
|
event.node.res.statusCode = 404;
|
||||||
@@ -39,11 +75,12 @@ export default defineEventHandler(async (event) => {
|
|||||||
id: channel.serverId
|
id: channel.serverId
|
||||||
},
|
},
|
||||||
include: {
|
include: {
|
||||||
participants: true
|
participants: true,
|
||||||
|
roles: true
|
||||||
}
|
}
|
||||||
}) as IServer
|
}) as IServer | null;
|
||||||
|
|
||||||
const userInServer: Array<IUser> = server.participants.filter((e: IUser) => e.id === event.context.user.id)
|
const userInServer: Array<SafeUser> | undefined = server?.participants.filter((e: SafeUser) => e.id === event.context.user.id)
|
||||||
|
|
||||||
if (!userInServer) {
|
if (!userInServer) {
|
||||||
event.node.res.statusCode = 401;
|
event.node.res.statusCode = 401;
|
||||||
|
|||||||
@@ -42,13 +42,25 @@ export default defineEventHandler(async (event) => {
|
|||||||
name: 'general',
|
name: 'general',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
roles: {
|
||||||
|
create: [
|
||||||
|
{
|
||||||
|
name: 'owner',
|
||||||
|
owner: true,
|
||||||
|
users: {
|
||||||
|
connect: [{ id: event.context.user.id }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
include: {
|
include: {
|
||||||
channels: true,
|
channels: true,
|
||||||
participants: true
|
participants: true,
|
||||||
|
roles: true
|
||||||
}
|
}
|
||||||
}) as IServer
|
}) as IServer;
|
||||||
|
|
||||||
return server
|
return server
|
||||||
})
|
})
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IChannel, IUser } from '~/types'
|
import { IChannel, SafeUser } from '~/types'
|
||||||
import { PrismaClient } from '@prisma/client'
|
import { PrismaClient } from '@prisma/client'
|
||||||
const prisma = new PrismaClient()
|
const prisma = new PrismaClient()
|
||||||
|
|
||||||
@@ -23,13 +23,13 @@ export default defineEventHandler(async (event) => {
|
|||||||
where: {
|
where: {
|
||||||
id: partnerId
|
id: partnerId
|
||||||
}
|
}
|
||||||
}) as IUser
|
}) as SafeUser | null;
|
||||||
|
|
||||||
const user = await prisma.user.findFirst({
|
const user = await prisma.user.findFirst({
|
||||||
where: {
|
where: {
|
||||||
id: event.context.user.id
|
id: event.context.user.id
|
||||||
}
|
}
|
||||||
}) as IUser
|
}) as SafeUser | null;
|
||||||
|
|
||||||
if (!partner) {
|
if (!partner) {
|
||||||
event.node.res.statusCode = 400;
|
event.node.res.statusCode = 400;
|
||||||
@@ -38,6 +38,10 @@ export default defineEventHandler(async (event) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
throw new Error('user not found?')
|
||||||
|
}
|
||||||
|
|
||||||
const preExistingServer = await prisma.channel.findFirst({
|
const preExistingServer = await prisma.channel.findFirst({
|
||||||
where: {
|
where: {
|
||||||
name: `${user.id}-${partner.id}`,
|
name: `${user.id}-${partner.id}`,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IChannel, IServer, IUser, IMessage } from '~/types'
|
import { IChannel, IServer, SafeUser, IMessage } from '~/types'
|
||||||
import { Server } from 'socket.io'
|
import { Server } from 'socket.io'
|
||||||
import { PrismaClient } from '@prisma/client'
|
import { PrismaClient } from '@prisma/client'
|
||||||
const prisma = new PrismaClient()
|
const prisma = new PrismaClient()
|
||||||
@@ -15,7 +15,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { body, channelId } = await readBody(event)
|
let { body, channelId } = await readBody(event)
|
||||||
|
|
||||||
if (!body || !channelId) {
|
if (!body || !channelId) {
|
||||||
event.node.res.statusCode = 400;
|
event.node.res.statusCode = 400;
|
||||||
@@ -43,9 +43,9 @@ export default defineEventHandler(async (event) => {
|
|||||||
}
|
}
|
||||||
}) as IServer
|
}) as IServer
|
||||||
|
|
||||||
const userInServer: Array<IUser> = server.participants.filter((e) => e.id === event.context.user.id)
|
const userInServer: SafeUser | undefined = server.participants.find((e: SafeUser) => e.id === event.context.user.id)
|
||||||
|
|
||||||
if (userInServer.length > 0) {
|
if (!userInServer) {
|
||||||
event.node.res.statusCode = 401;
|
event.node.res.statusCode = 401;
|
||||||
return {
|
return {
|
||||||
message: 'You must be in the server to send a message.'
|
message: 'You must be in the server to send a message.'
|
||||||
@@ -59,9 +59,9 @@ export default defineEventHandler(async (event) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const userInDM: Array<IUser> | undefined = channel.dmParticipants?.filter((e) => e.id === event.context.user.id)
|
const userInDM: SafeUser | undefined = channel.dmParticipants?.find((e) => e.id === event.context.user.id)
|
||||||
|
|
||||||
if (!userInDM || userInDM.length > 0) {
|
if (!userInDM) {
|
||||||
event.node.res.statusCode = 401;
|
event.node.res.statusCode = 401;
|
||||||
return {
|
return {
|
||||||
message: 'You must be in the DM to send a message.'
|
message: 'You must be in the DM to send a message.'
|
||||||
@@ -69,6 +69,21 @@ export default defineEventHandler(async (event) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const matches = body.match(/<&([a-z]|[0-9]){25}>/g);
|
||||||
|
|
||||||
|
let invites: { id: string; }[] = [];
|
||||||
|
if (matches) {
|
||||||
|
matches.forEach((e: string) => {
|
||||||
|
if (!e) return
|
||||||
|
const opBody = body;
|
||||||
|
body = body.split(e).join('')
|
||||||
|
if (opBody === body) return;
|
||||||
|
const id = e.split('<&')[1]?.split('>')[0];
|
||||||
|
if (!id) return;
|
||||||
|
invites.push({ id });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const message = await prisma.message.create({
|
const message = await prisma.message.create({
|
||||||
data: {
|
data: {
|
||||||
body,
|
body,
|
||||||
@@ -81,16 +96,34 @@ export default defineEventHandler(async (event) => {
|
|||||||
connect: {
|
connect: {
|
||||||
id: channelId
|
id: channelId
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
invites: {
|
||||||
|
connect: invites
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
include: {
|
select: {
|
||||||
creator: true
|
id: true,
|
||||||
|
body: true,
|
||||||
|
creator: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
username: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
invites: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
server: true,
|
||||||
|
expires: true,
|
||||||
|
expiryDate: true,
|
||||||
|
maxUses: true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}) as IMessage
|
}) as IMessage
|
||||||
|
|
||||||
|
|
||||||
global.io.emit(`message-${channel.id}`, { message });
|
global.io.emit(`message-${channel.id}`, { message });
|
||||||
|
|
||||||
return {
|
return message
|
||||||
message
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { PrismaClient } from '@prisma/client'
|
import { PrismaClient } from '@prisma/client'
|
||||||
import { IUser } from '../../types'
|
import { SafeUser } from '../../types'
|
||||||
const prisma = new PrismaClient()
|
const prisma = new PrismaClient()
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
@@ -42,13 +42,24 @@ export default defineEventHandler(async (event) => {
|
|||||||
id: true,
|
id: true,
|
||||||
username: true
|
username: true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
roles: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
administrator: true,
|
||||||
|
owner: true,
|
||||||
|
users: {
|
||||||
|
select: {
|
||||||
|
id: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}) as IUser
|
}) as SafeUser | null;
|
||||||
|
|
||||||
user.passwordhash = undefined;
|
|
||||||
|
|
||||||
return user
|
return user
|
||||||
})
|
})
|
||||||
67
server/api/guilds/[id]/addChannel.post.ts
Normal file
67
server/api/guilds/[id]/addChannel.post.ts
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import { IChannel, IServer, SafeUser } from '~/types'
|
||||||
|
import { PrismaClient } from '@prisma/client'
|
||||||
|
const prisma = new PrismaClient()
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
if (!event.context.user.authenticated) {
|
||||||
|
return {
|
||||||
|
message: 'You must be logged in to view a channel.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!event.context.params.id) {
|
||||||
|
event.node.res.statusCode = 400;
|
||||||
|
return {
|
||||||
|
message: 'A serverId is required'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { channelName } = await readBody(event)
|
||||||
|
|
||||||
|
const server = await prisma.server.findFirst({
|
||||||
|
where: {
|
||||||
|
id: event.context.params.id
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
participants: true,
|
||||||
|
channels: true,
|
||||||
|
roles: true
|
||||||
|
}
|
||||||
|
}) as IServer | null;
|
||||||
|
|
||||||
|
if (!server) {
|
||||||
|
event.node.res.statusCode = 404;
|
||||||
|
return {
|
||||||
|
message: `Server with id "${event.context.params.id}" not found`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const userInServer: Array<SafeUser> = server.participants.filter((e: SafeUser) => e.id === event.context.user.id)
|
||||||
|
|
||||||
|
if (!userInServer) {
|
||||||
|
event.node.res.statusCode = 401;
|
||||||
|
return {
|
||||||
|
message: `You must be in the server to access a channel in that server`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.channels?.find((e) => e.name === channelName)) {
|
||||||
|
event.node.res.statusCode = 409;
|
||||||
|
return {
|
||||||
|
message: `Channel with name "${channelName}" already exists in server with id "event.context.user.id"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const channel = await prisma.channel.create({
|
||||||
|
data: {
|
||||||
|
name: channelName,
|
||||||
|
server: {
|
||||||
|
connect: {
|
||||||
|
id: server.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) as IChannel
|
||||||
|
|
||||||
|
return channel
|
||||||
|
})
|
||||||
66
server/api/guilds/[id]/createInvite.post.ts
Normal file
66
server/api/guilds/[id]/createInvite.post.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { IChannel, IInviteCode, IServer, SafeUser } from '~/types'
|
||||||
|
import { PrismaClient } from '@prisma/client'
|
||||||
|
const prisma = new PrismaClient()
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
if (!event.context.user.authenticated) {
|
||||||
|
return {
|
||||||
|
message: 'You must be logged in to view a channel.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!event.context.params.id) {
|
||||||
|
event.node.res.statusCode = 400;
|
||||||
|
return {
|
||||||
|
message: 'A serverId is required'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let body = await readBody(event)
|
||||||
|
|
||||||
|
let expires = false;
|
||||||
|
// if (body.expiryDate) {
|
||||||
|
// expires = true;
|
||||||
|
// body.expiryDate = new Date(body.expiryDate).getUTCDate()
|
||||||
|
// }
|
||||||
|
|
||||||
|
const server = await prisma.server.findFirst({
|
||||||
|
where: {
|
||||||
|
id: event.context.params.id
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
participants: true,
|
||||||
|
channels: true,
|
||||||
|
roles: true
|
||||||
|
}
|
||||||
|
}) as IServer | null;
|
||||||
|
|
||||||
|
if (!server) {
|
||||||
|
event.node.res.statusCode = 404;
|
||||||
|
return {
|
||||||
|
message: `Server with id "${event.context.params.id}" not found`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const userInServerAndPermited: Array<SafeUser> = server.participants.filter((e: SafeUser) => e.id === event.context.user.id && e.roles?.some((el) => el.administer === true || el.owner === false))
|
||||||
|
|
||||||
|
if (!userInServerAndPermited) {
|
||||||
|
event.node.res.statusCode = 401;
|
||||||
|
return {
|
||||||
|
message: `You must be in the server or an admin/owner of that server to make an invite code`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const inviteCode = await prisma.inviteCode.create({
|
||||||
|
data: {
|
||||||
|
server: {
|
||||||
|
connect: {
|
||||||
|
id: server.id
|
||||||
|
}
|
||||||
|
},
|
||||||
|
maxUses: 0
|
||||||
|
}
|
||||||
|
}) as IInviteCode
|
||||||
|
|
||||||
|
return inviteCode
|
||||||
|
})
|
||||||
@@ -20,9 +20,10 @@ export default defineEventHandler(async (event) => {
|
|||||||
},
|
},
|
||||||
include: {
|
include: {
|
||||||
participants: true,
|
participants: true,
|
||||||
channels: true
|
channels: true,
|
||||||
|
roles: true
|
||||||
}
|
}
|
||||||
}) as IServer
|
}) as IServer | null;
|
||||||
|
|
||||||
if (!server) {
|
if (!server) {
|
||||||
event.node.res.statusCode = 404;
|
event.node.res.statusCode = 404;
|
||||||
65
server/api/guilds/joinGuild.post.ts
Normal file
65
server/api/guilds/joinGuild.post.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import { IServer } from '~/types'
|
||||||
|
import { PrismaClient } from '@prisma/client'
|
||||||
|
const prisma = new PrismaClient()
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
if (!event.context.user.authenticated) return {
|
||||||
|
message: 'You must be logged in to view a channel.'
|
||||||
|
}
|
||||||
|
|
||||||
|
const { inviteId } = await readBody(event);
|
||||||
|
|
||||||
|
if (!inviteId) {
|
||||||
|
event.node.res.statusCode = 400;
|
||||||
|
return {
|
||||||
|
message: 'A inviteId is required'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const invite = await prisma.inviteCode.findFirst({
|
||||||
|
where: {
|
||||||
|
id: inviteId
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
server: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!invite) {
|
||||||
|
event.node.res.statusCode = 404;
|
||||||
|
return {
|
||||||
|
message: `Invite with id "${inviteId}" not found`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check if invite is valid
|
||||||
|
|
||||||
|
const server = await prisma.server.update({
|
||||||
|
where: {
|
||||||
|
id: invite.server.id
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
participants: {
|
||||||
|
connect: [
|
||||||
|
{ id: event.context.user.id }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
participants: true,
|
||||||
|
channels: true,
|
||||||
|
roles: true
|
||||||
|
}
|
||||||
|
}) as IServer
|
||||||
|
|
||||||
|
if (!server) {
|
||||||
|
event.node.res.statusCode = 404;
|
||||||
|
return {
|
||||||
|
message: `Channel with id "${event.context.params.id}" not found`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
server
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import bcryptjs from "bcryptjs";
|
import bcryptjs from "bcryptjs";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import { PrismaClient } from '@prisma/client'
|
import { PrismaClient } from '@prisma/client'
|
||||||
import { IUser } from "../../types";
|
import { SafeUser } from "~/types";
|
||||||
const prisma = new PrismaClient()
|
const prisma = new PrismaClient()
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
@@ -25,7 +25,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}) as IUser
|
}) as SafeUser
|
||||||
|
|
||||||
if (preExistingUser) {
|
if (preExistingUser) {
|
||||||
event.node.res.statusCode = 409;
|
event.node.res.statusCode = 409;
|
||||||
@@ -42,7 +42,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
passwordhash,
|
passwordhash,
|
||||||
email: body.email
|
email: body.email
|
||||||
}
|
}
|
||||||
}) as IUser
|
}) as SafeUser
|
||||||
|
|
||||||
const token = uuidv4()
|
const token = uuidv4()
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
import { IUser } from '~/types'
|
|
||||||
import { PrismaClient } from '@prisma/client'
|
|
||||||
const prisma = new PrismaClient()
|
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
|
||||||
if (!event.context.user.authenticated) {
|
|
||||||
// event.node.res.statusCode = 401;
|
|
||||||
return {
|
|
||||||
message: "Unauthenticated"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const servers = await prisma.user.findFirst({
|
|
||||||
where: {
|
|
||||||
id: event.context.user.id
|
|
||||||
},
|
|
||||||
include: {
|
|
||||||
channels: true
|
|
||||||
}
|
|
||||||
}) as IUser
|
|
||||||
|
|
||||||
servers.passwordhash = undefined;
|
|
||||||
|
|
||||||
return servers
|
|
||||||
})
|
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
import { IUser, IServer, IChannel } from "../types";
|
import { Ref } from "vue";
|
||||||
|
import { SafeUser, IServer, IChannel } from "../types";
|
||||||
|
|
||||||
export const useGlobalStore = defineStore('global', {
|
export const useGlobalStore = defineStore('global', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
activeServer: {} as IServer | Record<string, unknown>,
|
activeServer: {} as IServer,
|
||||||
user: {} as IUser
|
user: {} as SafeUser
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setUser(user: IUser) {
|
setUser(user: SafeUser) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
},
|
},
|
||||||
addServer(server: IServer) {
|
addServer(server: IServer) {
|
||||||
@@ -19,17 +20,25 @@ export const useGlobalStore = defineStore('global', {
|
|||||||
},
|
},
|
||||||
setActive(type: string, serverId: string) {
|
setActive(type: string, serverId: string) {
|
||||||
if (serverId === '@me') {
|
if (serverId === '@me') {
|
||||||
this.activeServer = {}
|
this.activeServer = {} as IServer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
console.log(this.activeServer)
|
||||||
if (!this.user.channels || !this.user.servers) return;
|
if (!this.user.channels || !this.user.servers) return;
|
||||||
|
|
||||||
type = (type === 'dm') ? 'channels' : 'servers'
|
type = (type === 'dm') ? 'channels' : 'servers'
|
||||||
|
|
||||||
if (type !== 'channels' && type !== 'servers') return;
|
if (type !== 'channels' && type !== 'servers') return;
|
||||||
|
|
||||||
const searchableArray: IChannel[] | IServer[] = this["user"][type]
|
const searchableArray: IChannel[] | IServer[] | undefined = this["user"][type]
|
||||||
this.activeServer = searchableArray.find((e: IServer | IChannel) => e.id === serverId)
|
if (!searchableArray) return;
|
||||||
|
const activeServer = searchableArray.find((e: IServer | IChannel) => e.id === serverId)
|
||||||
|
console.log(searchableArray, this["user"], activeServer)
|
||||||
|
|
||||||
|
if (!activeServer) return;
|
||||||
|
|
||||||
|
this.activeServer = activeServer
|
||||||
|
console.log(this.activeServer)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,25 +2,29 @@ export interface IUser {
|
|||||||
id: string;
|
id: string;
|
||||||
email: string;
|
email: string;
|
||||||
username: string;
|
username: string;
|
||||||
passwordhash: string | undefined;
|
passwordhash: string;
|
||||||
servers: Array<IServer>;
|
servers?: Array<IServer>;
|
||||||
serverId?: string;
|
channels?: Array<IChannel>;
|
||||||
channels: Array<IChannel>;
|
roles?: Array<IRole>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SafeUser = Omit<Omit<IUser, 'passwordhash'>, 'email'>
|
||||||
|
|
||||||
export interface IServer {
|
export interface IServer {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
channels: Array<IChannel>;
|
channels?: Array<IChannel>;
|
||||||
participants: Array<IUser>;
|
participants: Array<IUser>;
|
||||||
|
roles?: Array<IRole>;
|
||||||
|
inviteCode?: Array<IInviteCode>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IChannel {
|
export interface IChannel {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
server?: IServer;
|
server?: IServer;
|
||||||
messages: Array<unknown>
|
messages?: Array<IMessage>
|
||||||
DM?: boolean;
|
DM: boolean;
|
||||||
dmParticipants?: Array<IUser>;
|
dmParticipants?: Array<IUser>;
|
||||||
serverId: string;
|
serverId: string;
|
||||||
}
|
}
|
||||||
@@ -28,8 +32,30 @@ export interface IChannel {
|
|||||||
export interface IMessage {
|
export interface IMessage {
|
||||||
id: string;
|
id: string;
|
||||||
body: string;
|
body: string;
|
||||||
creator: IUser;
|
creator: SafeUser;
|
||||||
channel: IChannel;
|
channel?: IChannel;
|
||||||
userId: string;
|
userId: string;
|
||||||
channelId: string;
|
channelId: string;
|
||||||
|
invites?: IInviteCode[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IInviteCode {
|
||||||
|
id: string;
|
||||||
|
server: IServer;
|
||||||
|
expires: boolean;
|
||||||
|
expiryDate: Date;
|
||||||
|
maxUses: number;
|
||||||
|
serverId: string;
|
||||||
|
Message: IMessage;
|
||||||
|
messageId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRole {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
administer: boolean;
|
||||||
|
owner: boolean;
|
||||||
|
users: IUser[];
|
||||||
|
server?: IServer;
|
||||||
|
serverId?: string;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user