├── .gitattributes
├── .github
├── dependabot.yml
└── workflows
│ ├── node.js.yml
│ └── zip.yml
├── .gitignore
├── README.md
├── client
├── .babelrc
├── .gitignore
├── package.json
├── public
│ ├── electron.js
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo192_notif.png
│ ├── manifest.json
│ ├── preload.js
│ └── robots.txt
├── src
│ ├── App.js
│ ├── Components.js
│ ├── components
│ │ ├── AccountOptionsDialog.js
│ │ ├── AccountStatusDialog.js
│ │ ├── AddFriendsDialog.js
│ │ ├── ChannelHeader.js
│ │ ├── ChannelOptionsDialog.js
│ │ ├── ChannelSelector.js
│ │ ├── Chat.js
│ │ ├── CopiedIDDialog.js
│ │ ├── CreateChannelDialog.js
│ │ ├── CreateEmoteDialog.js
│ │ ├── CreateServerDialog.js
│ │ ├── CropImageDialog.js
│ │ ├── EditAccountDialog.js
│ │ ├── EditChannelDialog.js
│ │ ├── EditServerDialog.js
│ │ ├── ForgottenPasswordDialog.js
│ │ ├── ImageDialog.js
│ │ ├── InviteFriendsDialog.js
│ │ ├── LoginForm.js
│ │ ├── MessageOptionsDialog.js
│ │ ├── PinnedMessagesDialog.js
│ │ ├── ProfileDialog.js
│ │ ├── ProfileOptionsDialog.js
│ │ ├── RegisterForm.js
│ │ ├── SearchMessagesDialog.js
│ │ ├── Send.js
│ │ ├── ServerDiscoveryDialog.js
│ │ ├── ServerOptionsDialog.js
│ │ ├── SetCustomStatusDialog.js
│ │ ├── SettingsDialog.js
│ │ └── index.js
│ ├── index.js
│ ├── public
│ │ ├── fonts
│ │ │ └── uwuFont.woff
│ │ ├── icon.ico
│ │ └── scripts
│ │ │ ├── API.js
│ │ │ ├── Constants.js
│ │ │ ├── DateFormatter.js
│ │ │ ├── ElementBuilder.js
│ │ │ ├── Functions.js
│ │ │ ├── MessageFormatter.js
│ │ │ └── SizeFormatter.js
│ └── style.css
├── webpack.config.js
└── yarn.lock
└── server
├── package-lock.json
├── package.json
├── scripts
├── data
│ ├── db_add.js
│ ├── db_delete.js
│ ├── db_edit.js
│ ├── db_fetch.js
│ └── db_manager.js
├── endpoints
│ ├── acceptFriendRequest.js
│ ├── addToDMChannel.js
│ ├── auth_blizzard.js
│ ├── auth_discord.js
│ ├── auth_gh.js
│ ├── auth_osu.js
│ ├── auth_reddit.js
│ ├── auth_spotify.js
│ ├── auth_twitch.js
│ ├── cloneChannel.js
│ ├── createChannel.js
│ ├── createEmote.js
│ ├── createInvite.js
│ ├── createServer.js
│ ├── declineFriendRequest.js
│ ├── deleteChannel.js
│ ├── deleteEmote.js
│ ├── deleteMessage.js
│ ├── deleteServer.js
│ ├── editChannel.js
│ ├── editMessage.js
│ ├── editNote.js
│ ├── editServer.js
│ ├── editUser.js
│ ├── fetchChannel.js
│ ├── fetchChannelMessages.js
│ ├── fetchChannels.js
│ ├── fetchDMChannels.js
│ ├── fetchDefaultEmotes.js
│ ├── fetchEmote.js
│ ├── fetchFriendRequest.js
│ ├── fetchFriendRequests.js
│ ├── fetchInvite.js
│ ├── fetchNote.js
│ ├── fetchNotes.js
│ ├── fetchServer.js
│ ├── fetchServers.js
│ ├── fetchUser.js
│ ├── joinServer.js
│ ├── joinVoiceChannel.js
│ ├── kickFromServer.js
│ ├── leaveServer.js
│ ├── leaveVoiceChannel.js
│ ├── login.js
│ ├── logout.js
│ ├── message.js
│ ├── register.js
│ ├── removeConnection.js
│ ├── removeFriend.js
│ ├── removeFromDMChannel.js
│ ├── sendFriendRequest.js
│ ├── updateAvatar.js
│ ├── updateServerAvatar.js
│ ├── updateServerBanner.js
│ ├── upload.js
│ ├── voiceTransports_connect.js
│ ├── voiceTransports_consume.js
│ ├── voiceTransports_create.js
│ └── voiceTransports_produce.js
├── util.js
└── utils
│ ├── epFunc.js
│ └── mediaFunc.js
├── server.js
└── yarn.lock
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "npm"
9 | directory: "/client"
10 | open-pull-requests-limit: 99
11 | schedule:
12 | interval: "daily"
13 |
14 | - package-ecosystem: "npm"
15 | directory: "/server"
16 | open-pull-requests-limit: 99
17 | schedule:
18 | interval: "daily"
19 |
--------------------------------------------------------------------------------
/.github/workflows/node.js.yml:
--------------------------------------------------------------------------------
1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3 |
4 | name: Node.js CI
5 |
6 | on:
7 | push:
8 | branches: [ master ]
9 | pull_request:
10 | branches: [ master ]
11 |
12 | jobs:
13 | build:
14 |
15 | runs-on: ubuntu-latest
16 |
17 | strategy:
18 | matrix:
19 | node-version: [14.x]
20 |
21 | steps:
22 | - uses: actions/checkout@v2
23 | - name: Use Node.js ${{ matrix.node-version }}
24 | uses: actions/setup-node@v1
25 | with:
26 | node-version: ${{ matrix.node-version }}
27 | - run: cd client && yarn && CI=false npm run build
28 |
--------------------------------------------------------------------------------
/.github/workflows/zip.yml:
--------------------------------------------------------------------------------
1 | name: Create Web Release
2 | on: [push]
3 | jobs:
4 | build:
5 | runs-on: ubuntu-latest
6 | strategy:
7 | matrix:
8 | node-version: [14.x]
9 | steps:
10 | - uses: actions/checkout@v2
11 | - name: Create Web Release
12 | uses: liquidchat-devs/liquidchat-web-action@master
13 | with:
14 | directory: 'client'
15 | filename: 'build.zip'
16 | - name: Upload build.zip
17 | uses: actions/upload-artifact@v2
18 | with:
19 | name: build.zip
20 | path: client/build/build.zip
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | client/build
2 | client/dist
3 | client/node_modules
4 |
5 | server/node_modules
6 | server/data/config_persistent.txt
7 | server/keys
8 |
9 | icon/
10 | database.json
11 | .vscode
12 | *.dat
13 | .VSCodeCounter/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
54 |
55 | case 17:
56 | return
57 |
58 | case 18:
59 | return
60 |
61 | case 19:
62 | return
63 |
64 | case 20:
65 | return
66 |
67 | case 21:
68 | return
69 |
70 | case 22:
71 | return
72 |
73 | case 23:
74 | return
75 |
76 | case 24:
77 | return
78 |
79 | case 25:
80 | return
81 |
82 | case 26:
83 | return
84 |
85 | default:
86 | return null;
87 | }
88 | }
89 | }
--------------------------------------------------------------------------------
/client/src/components/AccountOptionsDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class AccountOptionsDialog extends React.Component {
4 | render() {
5 | const user = this.props.functions.getUser(this.props.state.session.userID)
6 |
7 | return (
8 |
9 |
{ this.props.functions.switchDialogState(0); }} style={{ opacity: 0.3 }}>
10 |
11 | {this.props.elements.getContextButton("Profile", (e) => { this.props.functions.setSelectedUser(user.id); this.props.functions.switchDialogState(5); })}
12 | {this.props.elements.getContextButton("Logout", (e) => { this.props.API.endpoints["logout"]({}); }, "var(--color8)")}
13 | {this.props.elements.getContextButton("Copy ID", (e) => { this.props.functions.copyID(this.props.state.session.userID); })}
14 |
15 |
16 | );
17 | }
18 | }
--------------------------------------------------------------------------------
/client/src/components/AccountStatusDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class AccountStatusDialog extends React.Component {
4 | render() {
5 | const user = this.props.functions.getUser(this.props.state.session.userID)
6 |
7 | return (
8 |
9 |
{ this.props.functions.switchDialogState(0); }} style={{ opacity: 0.3 }}>
10 |
11 |
{ this.props.API.endpoints["updateStatus"]({ status: 1 }); this.props.functions.switchDialogState(-1); }}>
12 |
13 |
Online
14 |
15 |
{ this.props.API.endpoints["updateStatus"]({ status: 2 }); this.props.functions.switchDialogState(-1); }}>
16 |
17 |
Idle
18 |
19 |
{ this.props.API.endpoints["updateStatus"]({ status: 3 }); this.props.functions.switchDialogState(-1); }}>
20 |
21 |
Do not Disturb
22 |
23 |
{ this.props.API.endpoints["updateStatus"]({ status: 0 }); this.props.functions.switchDialogState(-1); }}>
24 |
25 |
Offline
26 |
27 |
{ this.props.functions.switchDialogState(23); }}>
28 |
29 |
{ user.customStatus === undefined ? "Change Status" : user.customStatus }
30 |
31 |
32 |
33 | );
34 | }
35 | }
--------------------------------------------------------------------------------
/client/src/components/AddFriendsDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class AddFriendsDialog extends React.Component {
4 | state = {
5 | friendUsername: "",
6 | friendRequestResult: 0
7 | };
8 |
9 | handleChange = e => {
10 | this.setState({
11 | [e.target.name]: e.target.value,
12 | });
13 | }
14 |
15 | handleSubmit = async e => {
16 | e.preventDefault();
17 | const res = await this.props.API.endpoints["sendFriendRequestByUsername"]({ target: { username: this.state.friendUsername }});
18 | this.setState({
19 | friendRequestResult: res,
20 | });
21 |
22 | if(res === 1) { this.props.functions.switchDialogState(-1); }
23 | return true;
24 | }
25 |
26 | getErrorText(code) {
27 | switch(code) {
28 | case -1:
29 | return "You already sent a request to this user-";
30 |
31 | case -2:
32 | return "Nobody with this username found-";
33 |
34 | case -3:
35 | return "You can't send friend requests to yourself-";
36 |
37 | default:
38 | return "";
39 | }
40 | }
41 |
42 | render() {
43 | return (
44 |
45 |
{ this.props.functions.switchDialogState(0) }}>
46 |
47 |
Add a friend-
48 |
51 |
Send request!
52 | {
53 | (this.getErrorText(this.state.friendRequestResult).length > 0 ?
54 |
55 | {this.getErrorText(this.state.friendRequestResult)}
56 |
57 | : "")
58 | }
59 |
60 |
61 | );
62 | }
63 | }
--------------------------------------------------------------------------------
/client/src/components/ChannelHeader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class ChannelHeader extends React.Component {
4 | state = {
5 | searchResult: -1,
6 | searches: -1,
7 | searchTerm: ""
8 | }
9 |
10 | handleChange = e => {
11 | let term = e.target.value;
12 | this.setState({
13 | searchTerm: term
14 | })
15 | }
16 |
17 | handleSubmit = async e => {
18 | e.preventDefault();
19 |
20 | var res = await this.props.API.endpoints["searchMessages"]({ id: this.props.state.currentChannel, filters: { term: this.state.searchTerm }});
21 | if(isNaN(res) || res.length === 0) {
22 | this.props.functions.setSearches(res);
23 | this.props.functions.setSearchedTerm(this.state.searchTerm);
24 | } else {
25 | this.setState({
26 | searchResult: res,
27 | });
28 | }
29 | }
30 |
31 | render() {
32 | let server = this.props.functions.getServer(this.props.state.selectedServer)
33 | let channel = this.props.functions.getChannel(this.props.state.currentChannel)
34 | if(channel === undefined || (server !== undefined && server.channels.includes(channel.id) === false) || (channel.type !== 2 && server === undefined)) {
35 | return null;
36 | }
37 |
38 | let tip = -1;
39 | let messages = -1;
40 | switch(channel.type) {
41 | case 0:
42 | case 2:
43 | messages = channel.messages === undefined ? [] : channel.messages;
44 | tip = "#" + channel.name + " (" + messages.length + ")";
45 | break;
46 |
47 | case 1:
48 | tip = "." + channel.name + " " + (this.props.state.currentVoiceGroup !== -1 ? this.props.state.currentVoiceGroup.users.length : "Connecting...");
49 | break;
50 |
51 | default:
52 | break;
53 | }
54 |
55 | switch(channel.type) {
56 | default:
57 | return (
58 |
59 |
60 |
{tip}
61 | {
62 | channel.description !== undefined ?
63 |
- {channel.description}
64 | : ""
65 | }
66 |
67 |
68 |
{ this.props.functions.switchDialogState(26); }}>
69 |
72 |
73 |
74 |
{ this.props.functions.switchDialogState(25); }}>
75 |
76 |
77 |
78 |
79 | );
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/client/src/components/ChannelOptionsDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class ChannelOptionsDialog extends React.Component {
4 | state = {
5 | channelDeletionResult: 0,
6 | channelCloneResult: 0
7 | };
8 |
9 | handleDelete = async e => {
10 | e.preventDefault();
11 | const res = await this.props.API.endpoints["deleteChannel"]({ id: this.props.state.selectedChannel });
12 | this.setState({
13 | channelDeletionResult: res,
14 | });
15 |
16 | if(res === 1) { this.props.functions.switchDialogState(-1); }
17 | return true;
18 | }
19 |
20 | handleClone = async e => {
21 | e.preventDefault();
22 | const res = await this.props.API.endpoints["cloneChannel"]({ id: this.props.state.selectedChannel });
23 | this.setState({
24 | channelCloneResult: res,
25 | });
26 |
27 | if(res === 1) { this.props.functions.switchDialogState(-1); }
28 | return true;
29 | }
30 |
31 | render() {
32 | const channel = this.props.functions.getChannel(this.props.state.selectedChannel)
33 | if(channel === undefined) { return null; }
34 |
35 | return (
36 |
37 |
{ this.props.functions.switchDialogState(0); }} style={{ opacity: 0.3 }}>
38 |
39 | {
40 | channel.author.id === this.props.state.session.userID ?
41 |
42 | {this.props.elements.getContextButton("Edit Channel", (e) => { this.props.functions.switchDialogState(11); })}
43 | {channel.type === 2 ? this.props.elements.getContextButton("Add Friends", (e) => { this.props.functions.switchDialogState(12); }) : ""}
44 | {this.props.elements.getContextButton("Clone Channel", (e) => { this.handleClone(e); })}
45 | {this.props.elements.getContextButton("Delete Channel", (e) => { this.handleDelete(e); }, "var(--color8)")}
46 |
:
47 | ""
48 | }
49 | {this.props.elements.getContextButton("Copy ID", (e) => { this.props.functions.copyID(this.props.state.selectedChannel); })}
50 |
51 |
52 | );
53 | }
54 | }
--------------------------------------------------------------------------------
/client/src/components/CopiedIDDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class CopiedIDDialog extends React.Component {
4 | componentDidMount() {
5 | setTimeout(() => { this.props.functions.switchDialogState(-1); }, 3000)
6 | }
7 |
8 | render() {
9 | return (
10 |
11 |
12 |
13 |
Copied {this.props.state.copiedID}!
14 |
15 |
16 |
17 | );
18 | }
19 | }
--------------------------------------------------------------------------------
/client/src/components/CreateChannelDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class CreateChannelDialog extends React.Component {
4 | state = {
5 | channelName: "",
6 | channelDescription: undefined,
7 | channelType: 0,
8 | isNSFW: false,
9 | channelCreationResult: 0
10 | };
11 |
12 | handleChange = e => {
13 | this.setState({
14 | [e.target.name]: e.target.value,
15 | });
16 | }
17 |
18 | handleChangeType = val => {
19 | this.setState({
20 | channelType: val,
21 | });
22 | }
23 |
24 | handleSwitchNSFW = () => {
25 | this.setState({
26 | isNSFW: !this.state.isNSFW,
27 | });
28 | }
29 |
30 | handleSubmit = async e => {
31 | e.preventDefault();
32 | const res = await this.props.API.endpoints["createChannel"]({
33 | server: { id: this.props.state.selectedServer },
34 | name: this.state.channelName,
35 | type: this.state.channelType,
36 | description: this.state.channelDescription,
37 | nsfw: this.state.isNSFW
38 | });
39 | this.setState({
40 | channelCreationResult: res,
41 | });
42 |
43 | if(isNaN(res)) { this.props.functions.switchDialogState(-1); }
44 | return true;
45 | }
46 |
47 | getErrorText(code) {
48 | switch(code) {
49 | case -1:
50 | return "Channel name is too short-";
51 |
52 | default:
53 | return "";
54 | }
55 | }
56 |
57 | render() {
58 | return (
59 |
60 |
{ this.props.functions.switchDialogState(0) }}>
61 |
62 |
Create new channel-
63 |
88 |
91 | {
92 | (this.getErrorText(this.state.channelCreationResult).length > 0 ?
93 |
94 | {this.getErrorText(this.state.channelCreationResult)}
95 |
96 | : "")
97 | }
98 |
99 |
100 | );
101 | }
102 | }
--------------------------------------------------------------------------------
/client/src/components/CreateEmoteDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class CreateEmoteDialog extends React.Component {
4 | state = {
5 | emoteName: "",
6 | emoteAvatar: "defaultAvatar.png",
7 | emoteCreationResult: 0
8 | };
9 |
10 | handleAvatar = async (box, e) => {
11 | if(e.target.files.length < 1) { return; }
12 |
13 | var file = e.target.files[0];
14 | e.target.value = ""
15 | this.setState({
16 | emoteAvatar: file,
17 | });
18 |
19 | var reader = new FileReader();
20 | reader.onload = function(e) {
21 | box.refs["emoteImage"].src = e.target.result;
22 | }
23 | reader.readAsDataURL(file);
24 | }
25 |
26 | handleChange = e => {
27 | this.setState({
28 | [e.target.name]: e.target.value,
29 | });
30 | }
31 |
32 | handleSubmit = async e => {
33 | e.preventDefault();
34 |
35 | let res = -1;
36 | switch(this.props.type) {
37 | case 1:
38 | res = await this.props.API.endpoints["createEmote"](this.state.emoteAvatar, {}, { emoteName: this.state.emoteName, type: 1 });
39 | break;
40 |
41 | case 0:
42 | res = await this.props.API.endpoints["createServerEmote"](this.state.emoteAvatar, {}, { emoteName: this.state.emoteName, serverID: this.props.state.selectedServer, type: 0 });
43 | break;
44 |
45 | default:
46 | break;
47 | }
48 |
49 | this.setState({
50 | emoteCreationResult: res,
51 | });
52 |
53 | if(isNaN(res)) {
54 | this.props.functions.switchDialogState(-1);
55 | return true;
56 | } else {
57 | this.setState({
58 | emoteCreationResult: res,
59 | });
60 | }
61 | }
62 |
63 | getErrorText(code) {
64 | switch(code) {
65 | case -1:
66 | return "Emote name is too short-";
67 |
68 | default:
69 | return "";
70 | }
71 | }
72 |
73 | render() {
74 | return (
75 |
76 |
{ this.props.functions.switchDialogState(0) }}>
77 |
78 |
Create new{this.props.type === 0 ? " server" : ""} emote-
79 |
89 |
92 | {
93 | (this.getErrorText(this.state.emoteCreationResult).length > 0 ?
94 |
95 | {this.getErrorText(this.state.emoteCreationResult)}
96 |
97 | : "")
98 | }
99 |
100 |
101 | );
102 | }
103 | }
--------------------------------------------------------------------------------
/client/src/components/CreateServerDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class CreateServerDialog extends React.Component {
4 | state = {
5 | serverName: "",
6 | serverAvatar: "defaultAvatar.png",
7 | serverCreationResult: 0
8 | };
9 |
10 | handleAvatar = async (box, e) => {
11 | if(e.target.files.length < 1) { return; }
12 |
13 | var file = e.target.files[0];
14 | e.target.value = ""
15 | this.setState({
16 | serverAvatar: file,
17 | });
18 |
19 | var reader = new FileReader();
20 | reader.onload = function(e) {
21 | box.refs["serverImage"].src = e.target.result;
22 | }
23 | reader.readAsDataURL(file);
24 | }
25 |
26 | handleChange = e => {
27 | this.setState({
28 | [e.target.name]: e.target.value,
29 | });
30 | }
31 |
32 | handleSubmit = async e => {
33 | e.preventDefault();
34 | let res = await this.props.API.endpoints["createServer"]({ name: this.state.serverName });
35 | this.setState({
36 | serverCreationResult: res,
37 | });
38 |
39 | if(isNaN(res)) {
40 | if(this.state.serverAvatar !== -1) {
41 | res = await this.props.API.endpoints["updateServerAvatar"](this.state.serverAvatar, {}, { serverID: res.id })
42 | this.setState({
43 | serverCreationResult: res,
44 | });
45 | }
46 | }
47 |
48 | if(isNaN(res)) {
49 | this.props.functions.switchDialogState(-1);
50 | return true;
51 | } else {
52 | this.setState({
53 | serverCreationResult: res,
54 | });
55 | }
56 | }
57 |
58 | getErrorText(code) {
59 | switch(code) {
60 | case -1:
61 | return "Server name is too short-";
62 |
63 | default:
64 | return "";
65 | }
66 | }
67 |
68 | render() {
69 | return (
70 |
71 |
{ this.props.functions.switchDialogState(0) }}>
72 |
73 |
Create new server-
74 |
87 |
90 | {
91 | (this.getErrorText(this.state.serverCreationResult).length > 0 ?
92 |
93 | {this.getErrorText(this.state.serverCreationResult)}
94 |
95 | : "")
96 | }
97 |
98 |
99 | );
100 | }
101 | }
--------------------------------------------------------------------------------
/client/src/components/CropImageDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class CropImageDialog extends React.Component {
4 | componentDidMount = () => {
5 | if(typeof this.props.state.selectedAvatar !== "string") {
6 | var reader = new FileReader();
7 | reader.onload = function(e) {
8 | this.refs["serverImage"].src = e.target.result;
9 | }.bind(this);
10 |
11 | reader.readAsDataURL(this.props.state.selectedAvatar);
12 | }
13 | }
14 |
15 | render() {
16 | return (
17 |
18 |
{ this.props.functions.switchDialogState(0) }}>
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | );
27 | }
28 | }
--------------------------------------------------------------------------------
/client/src/components/EditAccountDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class EditAccountDialog extends React.Component {
4 | state = {
5 | email: "",
6 | accountEditResult: 0
7 | };
8 |
9 | handleChange = e => {
10 | this.setState({
11 | [e.target.name]: e.target.value,
12 | });
13 | }
14 |
15 | handleSubmit = async e => {
16 | e.preventDefault();
17 | const res = await this.props.API.endpoints["editUser"]({ email: this.state.email });
18 | this.setState({
19 | accountEditResult: res,
20 | });
21 |
22 | if(res === 1) { this.props.functions.switchDialogState(-1); }
23 | return true;
24 | }
25 |
26 | getErrorText(code) {
27 | switch(code) {
28 | default:
29 | return "";
30 | }
31 | }
32 |
33 | render() {
34 | return (
35 |
36 |
{ this.props.functions.switchDialogState(0) }}>
37 |
38 |
Manage Account-
39 |
42 |
Edit!
43 | {
44 | (this.getErrorText(this.state.accountEditResult).length > 0 ?
45 |
46 | {this.getErrorText(this.state.accountEditResult)}
47 |
48 | : "")
49 | }
50 |
51 |
52 | );
53 | }
54 | }
--------------------------------------------------------------------------------
/client/src/components/EditChannelDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class EditChannelDialog extends React.Component {
4 | state = {
5 | channelName: "",
6 | channelDescription: undefined,
7 | isNSFW: false,
8 | channelEditResult: 0
9 | };
10 |
11 | componentDidMount = () => {
12 | const channel = this.props.functions.getChannel(this.props.state.selectedChannel);
13 | if(channel !== undefined) {
14 | this.setState({
15 | channelName: channel.name,
16 | channelDescription: channel.description,
17 | isNSFW: channel.nsfw
18 | })
19 | }
20 | }
21 |
22 | handleChange = e => {
23 | this.setState({
24 | [e.target.name]: e.target.value,
25 | });
26 | }
27 |
28 | handleSwitchNSFW = () => {
29 | this.setState({
30 | isNSFW: !this.state.isNSFW,
31 | });
32 | }
33 |
34 | handleSubmit = async e => {
35 | e.preventDefault();
36 | const res = await this.props.API.endpoints["editChannel"]({
37 | id: this.props.state.selectedChannel,
38 | name: this.state.channelName,
39 | description: this.state.channelDescription,
40 | nsfw: this.state.isNSFW
41 | });
42 | this.setState({
43 | channelEditResult: res,
44 | });
45 |
46 | if(res === 1) { this.props.functions.switchDialogState(-1); }
47 | return true;
48 | }
49 |
50 | getErrorText(code) {
51 | switch(code) {
52 | case -2:
53 | return "You're not this channel's author-";
54 |
55 | case -3:
56 | return "Channel name is too short-";
57 |
58 | default:
59 | return "";
60 | }
61 | }
62 |
63 | render() {
64 | const channel = this.props.functions.getChannel(this.props.state.selectedChannel)
65 |
66 | return (
67 |
68 |
{ this.props.functions.switchDialogState(0) }}>
69 |
70 |
Edit channel-
71 |
87 |
90 | {
91 | (this.getErrorText(this.state.channelEditResult).length > 0 ?
92 |
93 | {this.getErrorText(this.state.channelEditResult)}
94 |
95 | : "")
96 | }
97 |
98 |
99 | );
100 | }
101 | }
--------------------------------------------------------------------------------
/client/src/components/EditServerDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class EditServerDialog extends React.Component {
4 | state = {
5 | serverName: "",
6 | serverAvatar: -1,
7 | serverEditResult: 0,
8 | avatarChangeResult: 0,
9 | deletingEmotesEnabled: false
10 | };
11 |
12 | componentDidMount = () => {
13 | const server = this.props.functions.getServer(this.props.state.selectedServer);
14 | if(server !== undefined) {
15 | this.setState({
16 | serverName: server.name
17 | })
18 | }
19 | }
20 |
21 | handleAvatar = async (box, e) => {
22 | if(e.target.files.length < 1) { return; }
23 |
24 | var file = e.target.files[0];
25 | e.target.value = ""
26 | this.setState({
27 | serverAvatar: file,
28 | });
29 |
30 | var reader = new FileReader();
31 | reader.onload = function(e) {
32 | box.refs["serverImage"].src = e.target.result;
33 | }
34 | reader.readAsDataURL(file);
35 | }
36 |
37 | handleBanner = async (box, e) => {
38 | if(e.target.files.length < 1) { return; }
39 |
40 | var file = e.target.files[0];
41 | e.target.value = ""
42 | this.setState({
43 | serverBanner: file,
44 | });
45 |
46 | var reader = new FileReader();
47 | reader.onload = function(e) {
48 | box.refs["serverBannerImage"].src = e.target.result;
49 | }
50 | reader.readAsDataURL(file);
51 | }
52 |
53 | handleChange = e => {
54 | this.setState({
55 | [e.target.name]: e.target.value,
56 | });
57 | }
58 |
59 | handleSubmit = async e => {
60 | e.preventDefault();
61 | let res = await this.props.API.endpoints["editServer"]({ id: this.props.state.selectedServer, name: this.state.serverName });
62 | this.setState({
63 | serverEditResult: res,
64 | });
65 |
66 | if(isNaN(res)) {
67 | if(this.state.serverAvatar !== -1) {
68 | res = await this.props.API.endpoints["updateServerAvatar"](this.state.serverAvatar, {}, { serverID: this.props.state.selectedServer });
69 | this.setState({
70 | serverEditResult: res,
71 | });
72 | }
73 | }
74 |
75 | if(isNaN(res)) {
76 | if(this.state.serverBanner !== -1) {
77 | res = await this.props.API.endpoints["updateServerBanner"](this.state.serverBanner, {}, { serverID: this.props.state.selectedServer });
78 | this.setState({
79 | serverEditResult: res,
80 | });
81 | }
82 | }
83 |
84 | if(isNaN(res)) {
85 | this.props.functions.switchDialogState(-1);
86 | return true;
87 | } else {
88 | this.setState({
89 | serverEditResult: res,
90 | });
91 | }
92 | }
93 |
94 | getErrorText(code) {
95 | switch(code) {
96 | case -2:
97 | return "You're not this server's author-";
98 |
99 | case -3:
100 | return "Server name is too short-";
101 |
102 | default:
103 | return "";
104 | }
105 | }
106 |
107 | render() {
108 | const server = this.props.functions.getServer(this.props.state.selectedServer);
109 | if(server === undefined) {
110 | return null;
111 | }
112 |
113 | let emotes = []
114 | server.emotes.forEach(emoteID => {
115 | if(this.props.state.emotes.has(emoteID)) {
116 | emotes.push(this.props.state.emotes.get(emoteID));
117 | }
118 | })
119 |
120 | let emoteList = emotes.map((emote, i) => {
121 | return { if(this.state.deletingEmotesEnabled) { this.props.API.endpoints["deleteEmote"]({ id: emote.id }); } }}>
122 |
123 | {this.state.deletingEmotesEnabled ?
124 |
127 | : ""}
128 |
:{emote.name}:
129 |
130 | }, "")
131 |
132 | return (
133 |
134 |
{ this.props.functions.switchDialogState(0) }}>
135 |
136 |
Edit server-
137 |
151 |
Server Emotes ({emotes.length})
152 |
153 | {emoteList}
154 |
{ this.props.functions.switchDialogState(21); }}>
155 | +
156 |
157 |
{ this.setState({ deletingEmotesEnabled: !this.state.deletingEmotesEnabled }) }}>
158 | -
159 |
160 |
161 |
Server Banner
162 |
177 |
180 | {
181 | (this.getErrorText(this.state.serverEditResult).length > 0 ?
182 |
183 | {this.getErrorText(this.state.serverEditResult)}
184 |
185 | : "")
186 | }
187 |
188 |
189 | );
190 | }
191 | }
--------------------------------------------------------------------------------
/client/src/components/ForgottenPasswordDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class ForgottenPasswordDialog extends React.Component {
4 | state = {
5 | state: 0,
6 | code: "",
7 | passwordRecoveryResult: 0
8 | };
9 |
10 | handleChange = e => {
11 | this.setState({
12 | [e.target.name]: e.target.value,
13 | });
14 | }
15 |
16 | handleSubmit = async e => {
17 | e.preventDefault();
18 | /*const res = await this.props.API.endpoints["editUser"]({ email: this.state.email });
19 | this.setState({
20 | accountEditResult: res,
21 | });
22 |
23 | if(res === 1) { this.props.functions.switchDialogState(-1); }*/
24 | return true;
25 | }
26 |
27 | getErrorText(code) {
28 | switch(code) {
29 | default:
30 | return "";
31 | }
32 | }
33 |
34 | render() {
35 | return (
36 |
37 |
{ this.props.functions.switchDialogState(0) }}>
38 |
39 |
Password Recovery
40 | {this.state.state === 1 ?
41 |
42 |
45 |
Enter-
46 | {
47 | (this.getErrorText(this.state.passwordRecoveryResult).length > 0 ?
48 |
49 | {this.getErrorText(this.state.passwordRecoveryResult)}
50 |
51 | : "")
52 | }
53 |
54 | :
55 |
56 |
57 |
{ this.props.functions.switchDialogState(14); }}>To recover your account enter a code that was sent to your email-
58 |
59 |
{ this.setState({ state: 1 }) }}>I'm ready!
60 | {
61 | (this.getErrorText(this.state.passwordRecoveryResult).length > 0 ?
62 |
63 | {this.getErrorText(this.state.passwordRecoveryResult)}
64 |
65 | : "")
66 | }
67 |
68 | }
69 |
70 |
71 | );
72 | }
73 | }
--------------------------------------------------------------------------------
/client/src/components/ImageDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class ImageDialog extends React.Component {
4 | render() {
5 | return (
6 |
7 |
{ this.props.functions.switchDialogState(0) }}>
8 |
{ this.props.functions.switchDialogState(9); this.props.functions.setBox(e.pageX, e.pageY); e.preventDefault(); }}
11 | onClick={(e) => { this.props.functions.switchDialogState(8); e.preventDefault(); }}
12 | />
13 | {this.props.isMenuOpen === true ?
14 |
15 | {this.props.elements.getContextButton("Copy Link", (e) => { this.props.functions.copyID(this.props.state.fileEndpoint + "/" + this.props.state.selectedImage.name); })}
16 | {this.props.elements.getContextButton("Open Link", (e) => { window.open(this.props.state.fileEndpoint + "/" + this.props.state.selectedImage.name); })}
17 |
18 | : ""
19 | }
20 |
21 | );
22 | }
23 | }
--------------------------------------------------------------------------------
/client/src/components/InviteFriendsDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class InviteFriendsDialog extends React.Component {
4 | state = {
5 | invitationResult: 0,
6 | pendingInvitations: []
7 | };
8 |
9 | inviteUser = async (id, userID, type) => {
10 | let res = -1;
11 | switch(type) {
12 | case 0:
13 | res = await this.props.API.endpoints["addToDMChannel"]({ channel: id, user: userID });
14 | break;
15 |
16 | case 1:
17 | res = await this.props.API.endpoints["createInvite"]({ server: { id: id }});
18 | if(isNaN(res)) {
19 | res = await this.props.API.endpoints["sendDM"]({ user: { id: userID }, text: 'http://nekonetwork.net/invite/' + res.id });
20 | this.setState({
21 | invitationResult: res,
22 | });
23 | }
24 |
25 | if(isNaN(res)) {
26 | let newPending = this.state.pendingInvitations;
27 | newPending.push(userID);
28 | this.setState({
29 | pendingInvitations: newPending
30 | });
31 |
32 | return true;
33 | } else {
34 | this.setState({
35 | invitationResult: res,
36 | });
37 | }
38 | break;
39 |
40 | default:
41 | break;
42 | }
43 |
44 | return true;
45 | }
46 |
47 | render() {
48 | let loggedUser = this.props.functions.getUser(this.props.state.session.userID);
49 | let server = this.props.functions.getServer(this.props.state.selectedServer);
50 | let channel = this.props.functions.getChannel(this.props.state.selectedChannel);
51 | let target = channel === undefined || channel.members === undefined ? server : channel;
52 | let type = channel === undefined || channel.members === undefined ? 1 : 0;
53 |
54 | const friendList = loggedUser.friends.map((friendID, i) => {
55 | const friend = this.props.functions.getUser(friendID);
56 | if(friend === undefined) {
57 | return null;
58 | }
59 |
60 | return (
61 | { this.props.functions.setSelectedUser(friend.id); this.props.functions.setBox(e.pageX, e.pageY); this.props.functions.switchDialogState(6); e.preventDefault(); e.stopPropagation(); } }>
62 |
63 |
64 |
65 |
66 | {friend.username}
67 |
68 | {
69 | target.members.includes(friend.id) ?
70 |
Joined!
71 | : (this.state.pendingInvitations.includes(friend.id) ?
72 |
Invited!
:
73 |
{ this.inviteUser(target.id, friend.id, type); e.preventDefault(); } }>Invite
74 | )
75 | }
76 |
77 |
78 |
79 | )
80 | });
81 |
82 | return (
83 |
84 |
{ this.props.functions.switchDialogState(0) }}>
85 |
86 |
{type === 0 ? "> Add Friends-" : "> Invite Friends-"}
87 | {friendList}
88 |
89 |
90 | );
91 | }
92 | }
--------------------------------------------------------------------------------
/client/src/components/LoginForm.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class LoginForm extends React.Component {
4 | state = {
5 | username: "",
6 | password: "",
7 | clicked: false,
8 | loginResult: 0
9 | };
10 |
11 | componentDidMount = async() => {
12 | const res = await this.props.API.endpoints["login"]({ username: this.state.username, password: this.state.password, authType: "autologin" });
13 | this.setState({
14 | loginResult: res,
15 | });
16 | }
17 |
18 | handleChange = e => {
19 | this.setState({
20 | [e.target.name]: e.target.value,
21 | });
22 | }
23 |
24 | handleSubmit = async e => {
25 | e.preventDefault();
26 | const res = await this.props.API.endpoints["login"]({ username: this.state.username, password: this.state.password, authType: "default" });
27 | this.setState({
28 | loginResult: res,
29 | });
30 | }
31 |
32 | getErrorText(code) {
33 | switch(code) {
34 | case -3:
35 | return "Session expired-";
36 |
37 | case -2:
38 | return "User not found-";
39 |
40 | case -1:
41 | return "Invalid password-";
42 |
43 | case 0:
44 | default:
45 | return "";
46 | }
47 | }
48 |
49 | getSuccessText(code) {
50 | const user = this.props.functions.getUser(this.props.state.session.userID)
51 | switch(code) {
52 | case 0:
53 | case -3:
54 | case -2:
55 | case -1:
56 | return "";
57 |
58 | default:
59 | return "Logging in as " + (user !== undefined ? user.username : "Loading") + "...";
60 | }
61 | }
62 |
63 | render() {
64 | const form = (
65 |
69 | );
70 | return (
71 |
72 |
73 |
74 |
75 |
76 |
77 |
Login
78 |
79 | {form}
80 |
83 |
84 |
{ this.props.functions.switchFormState(); }}>Register?
85 | {
86 | (this.getErrorText(this.state.loginResult).length > 0 ?
87 |
88 | {this.getErrorText(this.state.loginResult)}
89 |
90 | : (this.getSuccessText(this.state.loginResult).length > 0 ?
91 |
92 | {this.getSuccessText(this.state.loginResult)}
93 |
94 | :
95 | ""))
96 | }
97 |
98 |
99 |
100 | );
101 | }
102 | }
--------------------------------------------------------------------------------
/client/src/components/MessageOptionsDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class MessageOptionsDialog extends React.Component {
4 | state = {
5 | messageDeletionResult: 0
6 | };
7 |
8 | handleDelete = async e => {
9 | e.preventDefault();
10 | const res = await this.props.API.endpoints["deleteMessage"]({ id: this.props.state.selectedMessage.id });
11 | this.setState({
12 | messageDeletionResult: res,
13 | });
14 |
15 | if(res === 1) { this.props.functions.switchDialogState(-1); }
16 | return true;
17 | }
18 |
19 | handleEdit = async e => {
20 | e.preventDefault();
21 | const res = 1
22 | this.props.functions.setEditedMessage(this.props.state.selectedMessage.text == null ? "" : this.props.state.selectedMessage.text);
23 | this.props.functions.startEditingMessage(this.props.state.selectedMessage);
24 |
25 | if(res === 1) { this.props.functions.switchDialogState(-1); }
26 | return true;
27 | }
28 |
29 | render() {
30 | return (
31 |
32 |
{ this.props.functions.switchDialogState(0); }} style={{ opacity: 0.3 }}>
33 |
34 | {this.props.state.selectedMessage.author.id === this.props.state.session.userID ? this.props.elements.getContextButton("Delete", (e) => { this.handleDelete(e); }, "var(--color8)") : "" }
35 | {this.props.state.selectedMessage.author.id === this.props.state.session.userID ? this.props.elements.getContextButton("Edit", (e) => { this.handleEdit(e); }) : ""}
36 | {this.props.state.selectedMessage.file == null ? "" : this.props.elements.getContextButton("Copy link to file", (e) => { this.props.functions.copyID(this.props.state.fileEndpoint + "/" + this.props.state.selectedMessage.file.name); })}
37 | {this.props.state.selectedMessage.file == null ? "" : this.props.elements.getContextButton("Open link to file", (e) => { window.open(this.props.state.fileEndpoint + "/" + this.props.state.selectedMessage.file.name, -1); })}
38 | {this.props.elements.getContextButton("Copy ID", (e) => { this.props.functions.copyID(this.props.state.selectedMessage.id); })}
39 |
40 |
41 | );
42 | }
43 | }
--------------------------------------------------------------------------------
/client/src/components/PinnedMessagesDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class PinnedMessagesDialog extends React.Component {
4 | render() {
5 | return (
6 |
7 |
{ this.props.functions.switchDialogState(0) }}>
8 |
9 |
10 |
Pinned Messages
11 |
12 |
13 |
14 | );
15 | }
16 | }
--------------------------------------------------------------------------------
/client/src/components/ProfileOptionsDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class ProfileOptionsDialog extends React.Component {
4 | sendFriendRequest(id) {
5 | this.props.API.endpoints["sendFriendRequest"]({ id: id });
6 | }
7 |
8 | removeFriend(id) {
9 | this.props.API.endpoints["removeFriend"]({ id: id });
10 | }
11 |
12 | removeFromDMChannel(channelID, userID) {
13 | this.props.API.endpoints["removeFromDMChannel"]({ channel: { id: channelID }, user: { id: userID } });
14 | }
15 |
16 | removeFromServer(serverID, userID) {
17 | this.props.API.endpoints["kickFromServer"]({ server: { id: serverID }, user: { id: userID }});
18 | }
19 |
20 | async dmUser(id) {
21 | var channel = await this.props.API.endpoints["getSuitableDMChannel"](id);
22 | if(channel !== undefined) {
23 | this.props.functions.switchDialogState(0);
24 | this.props.functions.switchChannelTypes(1);
25 | this.props.functions.switchChannel(channel.id);
26 | }
27 | }
28 |
29 | render() {
30 | let loggedUser = this.props.functions.getUser(this.props.state.session.userID);
31 | let selectedUser = this.props.functions.getUser(this.props.state.selectedUser);
32 | let currentChannel = this.props.functions.getChannel(this.props.state.currentChannel)
33 | let currentServer = this.props.functions.getServer(this.props.state.selectedServer)
34 |
35 | return (
36 |
37 |
{ this.props.functions.switchDialogState(0); }} style={{ opacity: 0.3 }}>
38 |
39 | {this.props.elements.getContextButton("Profile", (e) => { this.props.functions.switchDialogState(5); })}
40 | {loggedUser.friends.includes(selectedUser.id) === true ? this.props.elements.getContextButton("Message", (e) => { this.dmUser(selectedUser.id); }) : ""}
41 | {selectedUser.id !== loggedUser.id && loggedUser.friends.includes(selectedUser.id) === false ? this.props.elements.getContextButton("Add Friend", (e) => { this.sendFriendRequest(selectedUser.id); }) : ""}
42 | {loggedUser.friends.includes(selectedUser.id) === true ? this.props.elements.getContextButton("Remove Friend", (e) => { this.removeFriend(selectedUser.id); }, "var(--color8)") : ""}
43 | {currentChannel !== undefined && currentChannel.type === 2 && currentChannel.author.id === loggedUser.id && selectedUser.id !== loggedUser.id ? this.props.elements.getContextButton("Remove from group", (e) => { this.removeFromDMChannel(currentChannel.id , selectedUser.id); }, "var(--color8)") : ""}
44 | {currentServer !== undefined && currentServer.author.id === loggedUser.id && selectedUser.id !== loggedUser.id ? this.props.elements.getContextButton("Kick from server", (e) => { this.removeFromServer(currentServer.id, selectedUser.id); }, "var(--color8)") : ""}
45 | {this.props.elements.getContextButton("Copy ID", (e) => { this.props.functions.copyID(selectedUser.id); })}
46 |
47 |
48 | );
49 | }
50 | }
--------------------------------------------------------------------------------
/client/src/components/RegisterForm.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class RegisterForm extends React.Component {
4 | state = {
5 | username: "",
6 | password: "",
7 | password2: "",
8 | clicked: false,
9 | registerResult: 0
10 | };
11 |
12 | handleChange = e => {
13 | this.setState({
14 | [e.target.name]: e.target.value,
15 | });
16 | }
17 |
18 | handleSubmit = async e => {
19 | e.preventDefault();
20 | const res = await this.props.API.endpoints["register"]({ username: this.state.username, password: this.state.password, password2: this.state.password2 });
21 | this.setState({
22 | registerResult: res,
23 | });
24 | }
25 |
26 | getErrorText(code) {
27 | switch(code) {
28 | case -4:
29 | return "Password is too short, atleast 8 characters.";
30 |
31 | case -3:
32 | return "Username is too short, atleast 3 characters.";
33 |
34 | case -2:
35 | return "Passwords don't match-";
36 |
37 | case -1:
38 | return "Username already taken-";
39 |
40 | case 0:
41 | default:
42 | return "";
43 | }
44 | }
45 |
46 | getSuccessText(code) {
47 | const user = this.props.functions.getUser(this.props.state.session.userID)
48 | switch(code) {
49 | case 0:
50 | case -4:
51 | case -3:
52 | case -2:
53 | case -1:
54 | return "";
55 |
56 | default:
57 | return "Registering as " + (user !== undefined ? user.username : "Loading") + "...";
58 | }
59 | }
60 |
61 | render(){
62 | const form = (
63 |
68 | );
69 | return (
70 |
71 |
72 |
73 |
74 |
75 |
76 |
Register
77 |
78 | {form}
79 |
82 |
83 |
{ this.props.functions.switchFormState(); }}>Login?
84 | {
85 | (this.getErrorText(this.state.registerResult).length > 0 ?
86 |
87 | {this.getErrorText(this.state.registerResult)}
88 |
89 | : "")
90 | }
91 | {
92 | (this.getSuccessText(this.state.registerResult).length > 0 ?
93 |
94 | {this.getSuccessText(this.state.registerResult)}
95 |
96 | : "")
97 | }
98 |
99 |
100 |
101 | );
102 | }
103 | }
--------------------------------------------------------------------------------
/client/src/components/SearchMessagesDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class SearchMessagesDialog extends React.Component {
4 | state = {
5 | currentFace: this.getRandomFace()
6 | }
7 |
8 | render() {
9 | let channel = this.props.functions.getChannel(this.props.state.currentChannel)
10 | var searches = this.props.state.searches === -1 ? null : this.props.state.searches.map((message, i) => {
11 | let messageHTML = this.props.functions.getFormattedMessage(this, message);
12 | return (
13 |
14 | {messageHTML}
15 |
16 | )
17 | });
18 |
19 | return (
20 |
21 |
{ this.props.functions.switchDialogState(0); this.props.functions.setSearches(-1); }}>
22 |
23 |
24 |
Search:
25 |
{this.props.state.searchedTerm.length === 0 ? this.state.currentFace : this.props.state.searchedTerm}
26 |
in #{channel.name}
27 |
{this.props.state.searches === -1 ? "" : " (" + this.props.state.searches.length + ")"}
28 |
29 |
30 | {searches}
31 |
32 |
33 |
34 | );
35 | }
36 |
37 | getRandomFace() {
38 | let array = [
39 | ">w<",
40 | ">~<",
41 | ">.<",
42 | ">..<",
43 | ">//<",
44 | ">v<",
45 | ">o<",
46 | ">x<",
47 | ">-<"
48 | ]
49 |
50 | return array[Math.floor(Math.random() * array.length)];
51 | }
52 | }
--------------------------------------------------------------------------------
/client/src/components/ServerDiscoveryDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class ServerDiscoveryDialog extends React.Component {
4 | state = {
5 | serverName: "",
6 | serverAvatar: "defaultAvatar.png",
7 | serverCreationResult: 0
8 | };
9 |
10 | handleAvatar = async (box, e) => {
11 | if(e.target.files.length < 1) { return; }
12 |
13 | var file = e.target.files[0];
14 | e.target.value = ""
15 | this.setState({
16 | serverAvatar: file,
17 | });
18 |
19 | var reader = new FileReader();
20 | reader.onload = function(e) {
21 | box.refs["serverImage"].src = e.target.result;
22 | }
23 | reader.readAsDataURL(file);
24 | }
25 |
26 | handleChange = e => {
27 | this.setState({
28 | [e.target.name]: e.target.value,
29 | });
30 | }
31 |
32 | handleSubmit = async e => {
33 | e.preventDefault();
34 | let res = await this.props.API.endpoints["createServer"]({ name: this.state.serverName });
35 | this.setState({
36 | serverCreationResult: res,
37 | });
38 |
39 | if(isNaN(res)) {
40 | if(this.state.serverAvatar !== -1) {
41 | res = await this.props.API.endpoints["updateServerAvatar"](this.state.serverAvatar, {}, { serverID: res.id })
42 | this.setState({
43 | serverCreationResult: res,
44 | });
45 | }
46 | }
47 |
48 | if(isNaN(res)) {
49 | this.props.functions.switchDialogState(-1);
50 | return true;
51 | } else {
52 | this.setState({
53 | serverCreationResult: res,
54 | });
55 | }
56 | }
57 |
58 | getErrorText(code) {
59 | switch(code) {
60 | case -1:
61 | return "Server name is too short-";
62 |
63 | default:
64 | return "";
65 | }
66 | }
67 |
68 | render() {
69 | return (
70 |
71 |
{ this.props.functions.switchDialogState(0) }}>
72 |
73 |
Server Discovery
74 |
85 |
86 |
87 | );
88 | }
89 | }
--------------------------------------------------------------------------------
/client/src/components/ServerOptionsDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class ServerOptionsDialog extends React.Component {
4 | state = {
5 | serverDeletionResult: 0
6 | };
7 |
8 | handleDelete = async e => {
9 | e.preventDefault();
10 | const res = await this.props.API.endpoints["deleteServer"]({ id: this.props.state.selectedServer });
11 | this.setState({
12 | serverDeletionResult: res,
13 | });
14 |
15 | if(res === 1) { this.props.functions.switchDialogState(-1); }
16 | return true;
17 | }
18 |
19 | render() {
20 | const server = this.props.functions.getServer(this.props.state.selectedServer)
21 | if(server === undefined) { return null; }
22 |
23 | return (
24 |
25 |
{ this.props.functions.switchDialogState(0); }} style={{ opacity: 0.3 }}>
26 |
27 | {
28 | server.author.id === this.props.state.session.userID ?
29 |
30 | {this.props.elements.getContextButton("Edit Server", (e) => { this.props.functions.switchDialogState(18); })}
31 | {this.props.elements.getContextButton("Invite Friends", (e) => { this.props.functions.switchDialogState(12); })}
32 |
:
33 | ""
34 | }
35 | {this.props.elements.getContextButton("Leave Server", (e) => { this.props.API.endpoints["leaveServer"]({ id: server.id }); }, "var(--color8)")}
36 | {server.author.id === this.props.state.session.userID ? this.props.elements.getContextButton("Delete Server", (e) => { this.handleDelete(e); }, "var(--color8)") : "" }
37 | {this.props.elements.getContextButton("Copy ID", (e) => { this.props.functions.copyID(server.id); })}
38 |
39 |
40 | );
41 | }
42 | }
--------------------------------------------------------------------------------
/client/src/components/SetCustomStatusDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class SetCustomStatusDialog extends React.Component {
4 | state = {
5 | status: "",
6 | statusChangeResult: 0
7 | };
8 |
9 | componentDidMount = () => {
10 | const user = this.props.functions.getUser(this.props.state.session.userID);
11 | if(user !== undefined) {
12 | this.setState({
13 | status: user.customStatus
14 | })
15 | }
16 | }
17 |
18 | handleChange = e => {
19 | this.setState({
20 | [e.target.name]: e.target.value,
21 | });
22 | }
23 |
24 | handleSubmit = async e => {
25 | e.preventDefault();
26 | const res = await this.props.API.endpoints["updateCustomStatus"]({ customStatus: this.state.status });
27 | this.setState({
28 | statusChangeResult: res,
29 | });
30 |
31 | if(isNaN(res)) { this.props.functions.switchDialogState(-1); }
32 | return true;
33 | }
34 |
35 | getErrorText(code) {
36 | switch(code) {
37 | case -1:
38 | return "Status is too short-";
39 |
40 | default:
41 | return "";
42 | }
43 | }
44 |
45 | render() {
46 | return (
47 |
48 |
{ this.props.functions.switchDialogState(0) }}>
49 |
50 |
Set a custom status
51 |
56 |
59 | {
60 | (this.getErrorText(this.state.statusChangeResult).length > 0 ?
61 |
62 | {this.getErrorText(this.state.statusChangeResult)}
63 |
64 | : "")
65 | }
66 |
67 |
68 | );
69 | }
70 | }
--------------------------------------------------------------------------------
/client/src/components/index.js:
--------------------------------------------------------------------------------
1 | export {default as AccountOptionsDialog} from './AccountOptionsDialog'
2 | export {default as AccountStatusDialog} from './AccountStatusDialog'
3 | export {default as AddFriendsDialog} from './AddFriendsDialog'
4 | export {default as ChannelHeader} from './ChannelHeader'
5 | export {default as ChannelOptionsDialog} from './ChannelOptionsDialog'
6 | export {default as ChannelSelector} from './ChannelSelector'
7 | export {default as Chat} from './Chat'
8 | export {default as CopiedIDDialog} from './CopiedIDDialog'
9 | export {default as CreateChannelDialog} from './CreateChannelDialog'
10 | export {default as CreateEmoteDialog} from './CreateEmoteDialog'
11 | export {default as CreateServerDialog} from './CreateServerDialog'
12 | export {default as CropImageDialog} from './CropImageDialog'
13 | export {default as EditAccountDialog} from './EditAccountDialog'
14 | export {default as EditChannelDialog} from './EditChannelDialog'
15 | export {default as EditServerDialog} from './EditServerDialog'
16 | export {default as ForgottenPasswordDialog} from './ForgottenPasswordDialog'
17 | export {default as ImageDialog} from './ImageDialog'
18 | export {default as InviteFriendsDialog} from './InviteFriendsDialog'
19 | export {default as LoginForm} from './LoginForm'
20 | export {default as MessageOptionsDialog} from './MessageOptionsDialog'
21 | export {default as ProfileDialog} from './ProfileDialog'
22 | export {default as ProfileOptionsDialog} from './ProfileOptionsDialog'
23 | export {default as RegisterForm} from './RegisterForm'
24 | export {default as Send} from './Send'
25 | export {default as ServerOptionsDialog} from './ServerOptionsDialog'
26 | export {default as SetCustomStatusDialog} from './SetCustomStatusDialog'
27 | export {default as SettingsDialog} from './SettingsDialog'
28 | export {default as ServerDiscoveryDialog} from './ServerDiscoveryDialog'
29 | export {default as PinnedMessagesDialog} from './PinnedMessagesDialog'
30 | export {default as SearchMessagesDialog} from './SearchMessagesDialog'
--------------------------------------------------------------------------------
/client/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './style.css';
4 | import App from './App';
5 |
6 | ReactDOM.render(
7 | /**/
8 |
9 | /* */,
10 | document.getElementById('root')
11 | );
--------------------------------------------------------------------------------
/client/src/public/fonts/uwuFont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liquidchat-devs/liquidchat/871569e152fa374889306897fd59c71e45be68c7/client/src/public/fonts/uwuFont.woff
--------------------------------------------------------------------------------
/client/src/public/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liquidchat-devs/liquidchat/871569e152fa374889306897fd59c71e45be68c7/client/src/public/icon.ico
--------------------------------------------------------------------------------
/client/src/public/scripts/Constants.js:
--------------------------------------------------------------------------------
1 | export default class Constants {
2 | constructor(_main) {
3 | this.mainClass = _main;
4 | }
5 |
6 | getStatusColor(status) {
7 | switch(status) {
8 | case 0:
9 | return "#676767";
10 |
11 | case 1:
12 | return "#3baf3b";
13 |
14 | case 2:
15 | return "#ec9c24";
16 |
17 | case 3:
18 | return "#ff6161";
19 |
20 | case 4:
21 | return "#6b61ff";
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/client/src/public/scripts/DateFormatter.js:
--------------------------------------------------------------------------------
1 | function formatDate(timestamp) {
2 | const date = new Date(timestamp)
3 | const curr = new Date()
4 |
5 | var i = date.getDay() === curr.getDay() ? 1 : (date.getDay() === curr.getDay() - 1 ? 2 : 3)
6 | var i2 = i === 1 ? "Today" : "Yesterday"
7 | switch(i) {
8 | case 1:
9 | case 2:
10 | return i2 + " at " +
11 | (date.getHours() < 10 ? "0" + date.getHours() : date.getHours())
12 | + ":" +
13 | (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes())
14 |
15 | case 3:
16 | return date.toUTCString()
17 |
18 | default:
19 | return timestamp
20 | }
21 | }
22 |
23 | function formatDuration(timestamp, timestamp2) {
24 | var time = timestamp2 - timestamp;
25 | var timeString = "";
26 | var timeLeft = time;
27 |
28 | var ms = timeLeft % 1000;
29 | timeLeft = (timeLeft - ms) / 1000;
30 | var secs = timeLeft % 60;
31 | timeLeft = (timeLeft - secs) / 60;
32 | var mins = timeLeft % 60;
33 | timeLeft = (timeLeft - mins) / 60;
34 | var hrs = timeLeft % 24;
35 | timeLeft = (timeLeft - hrs) / 24;
36 | var days = timeLeft % 30;
37 | timeLeft = (timeLeft - days) / 30;
38 | var months = timeLeft % 12;
39 | timeLeft = (timeLeft - months) / 12;
40 | var years = timeLeft;
41 |
42 | if(years > 0) { timeString += years + "y "; }
43 | if(months > 0) { timeString += months + "mon "; }
44 | if(days > 0) { timeString += days + "d "; }
45 | if(hrs > 0) { timeString += hrs + "h "; }
46 | if(mins > 0) { timeString += mins + "m "; }
47 | if(secs > 0) { timeString += secs + "s "; }
48 |
49 | timeString = timeString.substring(0, timeString.length - 1);
50 | return timeString;
51 | }
52 |
53 | function formatDuration2(time) {
54 | var timeString = "";
55 | var timeLeft = time;
56 |
57 | var ms = timeLeft % 1000;
58 | timeLeft = (timeLeft - ms) / 1000;
59 | var secs = timeLeft % 60;
60 | timeLeft = (timeLeft - secs) / 60;
61 | var mins = timeLeft % 60;
62 | timeLeft = (timeLeft - mins) / 60;
63 | var hrs = timeLeft % 24;
64 | timeLeft = (timeLeft - hrs) / 24;
65 | var days = timeLeft;
66 |
67 | timeString = (secs < 10 ? "0" + secs : secs) + ":" + timeString;
68 | if(mins > 0) { timeString = (mins < 10 ? "0" + mins : mins) + ":" + timeString; } else { timeString = "0:" + timeString }
69 | if(hrs > 0) { timeString = (hrs < 10 ? "0" + hrs : hrs) + ":" + timeString; }
70 | if(days > 0) { timeString = (days < 10 ? "0" + days : days) + ":" + timeString; }
71 |
72 | timeString = timeString.substring(0, timeString.length - 1);
73 | return timeString;
74 | }
75 |
76 | export { formatDate, formatDuration, formatDuration2 }
--------------------------------------------------------------------------------
/client/src/public/scripts/ElementBuilder.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class ElementBuilder {
4 | constructor(_main) {
5 | this.mainClass = _main;
6 | }
7 |
8 | getContextButton(text, callback, color) {
9 | return { callback(e); }}>
10 |
> {text}
11 |
12 | }
13 | }
--------------------------------------------------------------------------------
/client/src/public/scripts/SizeFormatter.js:
--------------------------------------------------------------------------------
1 | function formatBytes(bytes, appendSize) {
2 | var k = 1024;
3 | var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
4 | if(appendSize === undefined) { appendSize = false; }
5 | if(bytes === 0) { return bytes + (appendSize ? ' ' + sizes[0] : '') }
6 |
7 | var i = Math.floor(Math.log(bytes) / Math.log(k));
8 | var result = parseFloat((bytes / (k ** i)).toFixed(2));
9 | return result + (appendSize ? ' ' + sizes[i] : '');
10 | }
11 |
12 | export { formatBytes }
--------------------------------------------------------------------------------
/client/webpack.config.js:
--------------------------------------------------------------------------------
1 | const HtmlWebPackPlugin = require("html-webpack-plugin");
2 |
3 | module.exports = {
4 | module: {
5 | rules: [
6 | {
7 | test: /\.(js|jsx)$/,
8 | exclude: /node_modules/,
9 | use: {
10 | loader: "babel-loader"
11 | }
12 | },
13 | {
14 | test: /\.html$/,
15 | use: [
16 | {
17 | loader: "html-loader"
18 | }
19 | ]
20 | }
21 | ]
22 | },
23 | plugins: [
24 | new HtmlWebPackPlugin({
25 | template: "./src/index.html",
26 | filename: "./index.html"
27 | })
28 | ]
29 | };
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "server",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "server.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "nodemon server.js"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "axios": "^0.21.1",
15 | "bcrypt": "^5.0.0",
16 | "body-parser": "^1.19.0",
17 | "compression": "^1.7.4",
18 | "cookie": "^0.4.1",
19 | "cookie-parser": "^1.4.5",
20 | "cors": "^2.8.5",
21 | "express": "^4.17.1",
22 | "formidable": "^1.2.2",
23 | "fs-extra": "^9.0.1",
24 | "mysql2": "^2.1.0",
25 | "socket.io": "^3.1.0",
26 | "websocket": "^1.0.32"
27 | },
28 | "devDependencies": {
29 | "nodemon": "^2.0.4"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/server/scripts/data/db_add.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | addServer(db, server) {
3 | if(db.DEBUG) {
4 | console.log(" - [db] Adding Server(id: " + server.id + ") into the database...");
5 | }
6 |
7 | var query = "INSERT IGNORE INTO servers (id, name, createdAt, authorID, avatar, channels, members, invites, emotes) VALUES" + db.contructQuestionMarks(9);
8 | db.sqlConn.promise().execute(query, [ server.id, db.escapeString(server.name), server.createdAt, server.author.id, server.avatar, server.channels.join(","), server.members.join(","), server.invites.join(","), server.emotes.join(",") ])
9 | .then((result, err) => {
10 | if(err) { throw err; }
11 | });
12 | },
13 |
14 | addUser(db, user) {
15 | if(db.DEBUG) {
16 | console.log(" - [db] Adding User(id: " + user.id + ") into the database...");
17 | }
18 |
19 | var query0 = "(id, username, createdAt, avatar, password, friends, dmChannels, servers, userStatus, badges, emotes" + (user.customStatus == null ? ")" : ", customStatus)")
20 | var query1 = [ user.id, db.escapeString(user.username), user.createdAt, user.avatar, user.password, user.friends.join(","), user.dmChannels.join(","), user.servers.join(","), user.userStatus, user.badges.join(","), user.emotes.join(",") ]
21 | if(user.customStatus != null) { query1.push(user.customStatus); }
22 |
23 | var query = "INSERT IGNORE INTO users " + query0 + " VALUES " + db.contructQuestionMarks(query1.length);
24 | db.sqlConn.promise().execute(query, query1)
25 | .then((result, err) => {
26 | if(err) { throw err; }
27 | });
28 | },
29 |
30 | addChannel(db, channel) {
31 | if(db.DEBUG) {
32 | console.log(" - [db] Adding Channel(id: " + channel.id + ") into the database...");
33 | }
34 |
35 | var query0 = "(id, name, type, nsfw, createdAt, authorID" + (channel.position == null ? "" : ", position") + (channel.members == null ? "" : ", members") + (channel.description == null ? "" : ", description") + (channel.server == null ? ")" : ", serverID)")
36 | var query1 = [ channel.id, db.escapeString(channel.name), channel.type, channel.nsfw, channel.createdAt, channel.author.id ]
37 | if(channel.position != null) { query1.push(channel.position) }
38 | if(channel.members != null) { query1.push(channel.members.join(",")) }
39 | if(channel.description != null) { query1.push(channel.description) }
40 | if(channel.server != null) { query1.push(channel.server.id) }
41 |
42 | var query = "INSERT IGNORE INTO channels " + query0 + " VALUES" + db.contructQuestionMarks(query1.length);
43 | db.sqlConn.promise().execute(query, query1)
44 | .then((result, err) => {
45 | if(err) { throw err; }
46 | });
47 | },
48 |
49 | addMessage(db, message) {
50 | if(db.DEBUG) {
51 | console.log(" - [db] Adding Message(id: " + message.id + ") into the database...");
52 | }
53 |
54 | var query0 = "(id, createdAt, channelID, edited, type" + (message.text == null ? "" : ", text") + (message.author == null ? "" : ", authorID") + (message.file == null ? ")" : ", fileName, fileSize)")
55 | var query1 = [ message.id, message.createdAt, message.channel.id, message.edited, message.type ]
56 | if(message.text != null) { query1.push(db.escapeString(message.text)) }
57 | if(message.author != null) { query1.push(message.author.id) }
58 | if(message.file != null) { query1.push(db.escapeString(message.file.name), message.file.size) }
59 |
60 | var query = "INSERT IGNORE INTO messages " + query0 + " VALUES" + db.contructQuestionMarks(query1.length);
61 | db.sqlConn.promise().execute(query, query1)
62 | .then((result, err) => {
63 | if(err) { throw err; }
64 | });
65 | },
66 |
67 | addFriendRequest(db, friendRequest) {
68 | if(db.DEBUG) {
69 | console.log(" - [db] Adding FriendRequest(id: " + friendRequest.id + ") into the database...");
70 | }
71 |
72 | var query = "INSERT IGNORE INTO friendrequests (id, authorID, targetID, createdAt) VALUES('" + friendRequest.id + "', '" + friendRequest.author.id + "', '" + friendRequest.target.id + "', " + friendRequest.createdAt + ")";
73 | db.sqlConn.promise().query(query)
74 | .then((result, err) => {
75 | if(err) { throw err; }
76 | });
77 | },
78 |
79 | addInvite(db, invite) {
80 | if(db.DEBUG) {
81 | console.log(" - [db] Adding Invite(id: " + invite.id + ") into the database...");
82 | }
83 |
84 | var query = "INSERT IGNORE INTO invites (id, authorID, serverID, createdAt) VALUES('" + invite.id + "', '" + invite.author.id + "', '" + invite.server.id + "', " + invite.createdAt + ")";
85 | db.sqlConn.promise().query(query)
86 | .then((result, err) => {
87 | if(err) { throw err; }
88 | });
89 | },
90 |
91 | addEmote(db, emote) {
92 | if(db.DEBUG) {
93 | console.log(" - [db] Adding Emote(id: " + emote.id + ") into the database...");
94 | }
95 |
96 | var query0 = "(id, name, createdAt, authorID, file, type" + (emote.server == null ? ")" : ", serverID)")
97 | var query1 = [ emote.id, emote.name, emote.createdAt, emote.author.id, emote.file, emote.type ]
98 | if(emote.server != null) { query1.push(db.escapeString(emote.server.id)) }
99 |
100 | var query = "INSERT IGNORE INTO emotes " + query0 + " VALUES" + db.contructQuestionMarks(query1.length);
101 | db.sqlConn.promise().execute(query, query1)
102 | .then((result, err) => {
103 | if(err) { throw err; }
104 | });
105 | },
106 |
107 | addNote(db, note) {
108 | if(db.DEBUG) {
109 | console.log(" - [db] Adding Note(id: " + note.id + ") into the database...");
110 | }
111 |
112 | var query = "INSERT IGNORE INTO notes (id, authorID, targetID, createdAt, text) VALUES('" + note.id + "', '" + note.author.id + "', '" + note.target.id + "', " + note.createdAt + ", '" + db.escapeString(note.text) + "')";
113 | db.sqlConn.promise().query(query)
114 | .then((result, err) => {
115 | if(err) { throw err; }
116 | });
117 | }
118 | }
--------------------------------------------------------------------------------
/server/scripts/data/db_delete.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | deleteServer(db, id) {
3 | if(db.DEBUG) {
4 | console.log(" - [db] Deleting Server(id: " + id + ") from the database...");
5 | }
6 |
7 | var query = "DELETE FROM servers WHERE id='" + id + "'";
8 | db.sqlConn.promise().query(query)
9 | .then((result, err) => {
10 | if(err) { throw err; }
11 | });
12 | },
13 |
14 | deleteUser(db, id) {
15 | if(db.DEBUG) {
16 | console.log(" - [db] Deleting User(id: " + id + ") from the database...");
17 | }
18 |
19 | var query = "DELETE FROM users WHERE id='" + id + "'";
20 | db.sqlConn.promise().query(query)
21 | .then((result, err) => {
22 | if(err) { throw err; }
23 | });
24 | },
25 |
26 | deleteChannel(db, id) {
27 | if(db.DEBUG) {
28 | console.log(" - [db] Deleting Channel(id: " + id + ") from the database...");
29 | }
30 |
31 | var query = "DELETE FROM channels WHERE id='" + id + "'";
32 | db.sqlConn.promise().query(query)
33 | .then((result, err) => {
34 | if(err) { throw err; }
35 | });
36 | },
37 |
38 | deleteMessage(db, id) {
39 | if(db.DEBUG) {
40 | console.log(" - [db] Deleting Message(id: " + id + ") from the database...");
41 | }
42 |
43 | var query = "DELETE FROM messages WHERE id='" + id + "'";
44 | db.sqlConn.promise().query(query)
45 | .then((result, err) => {
46 | if(err) { throw err; }
47 | });
48 | },
49 |
50 | deleteFriendRequest(db, id) {
51 | if(db.DEBUG) {
52 | console.log(" - [db] Deleting FriendRequest(id: " + id + ") from the database...");
53 | }
54 |
55 | var query = "DELETE FROM friendrequests WHERE id='" + id + "'";
56 | db.sqlConn.promise().query(query)
57 | .then((result, err) => {
58 | if(err) { throw err; }
59 | });
60 | },
61 |
62 | deleteInvite(db, id) {
63 | if(db.DEBUG) {
64 | console.log(" - [db] Deleting Invite(id: " + id + ") from the database...");
65 | }
66 |
67 | var query = "DELETE FROM invites WHERE id='" + id + "'";
68 | db.sqlConn.promise().query(query)
69 | .then((result, err) => {
70 | if(err) { throw err; }
71 | });
72 | },
73 |
74 | deleteEmote(db, id) {
75 | if(db.DEBUG) {
76 | console.log(" - [db] Deleting Emote(id: " + id + ") from the database...");
77 | }
78 |
79 | var query = "DELETE FROM emotes WHERE id='" + id + "'";
80 | db.sqlConn.promise().query(query)
81 | .then((result, err) => {
82 | if(err) { throw err; }
83 | });
84 | },
85 |
86 | deleteAllData(db) {
87 | if(db.DEBUG) {
88 | console.log(" - [db] Deleting all data from the database...");
89 | }
90 |
91 | var query = "DELETE FROM users";
92 | db.sqlConn.promise().query(query)
93 | .then((result, err) => {
94 | if(err) { throw err; }
95 | });
96 | query = "DELETE FROM channels";
97 | db.sqlConn.promise().query(query)
98 | .then((result, err) => {
99 | if(err) { throw err; }
100 | });
101 | query = "DELETE FROM messages";
102 | db.sqlConn.promise().query(query)
103 | .then((result, err) => {
104 | if(err) { throw err; }
105 | });
106 | query = "DELETE FROM friendrequests";
107 | db.sqlConn.promise().query(query)
108 | .then((result, err) => {
109 | if(err) { throw err; }
110 | });
111 | query = "DELETE FROM invites";
112 | db.sqlConn.promise().query(query)
113 | .then((result, err) => {
114 | if(err) { throw err; }
115 | });
116 | query = "DELETE FROM emotes";
117 | db.sqlConn.promise().query(query)
118 | .then((result, err) => {
119 | if(err) { throw err; }
120 | });
121 | query = "DELETE FROM notes";
122 | db.sqlConn.promise().query(query)
123 | .then((result, err) => {
124 | if(err) { throw err; }
125 | });
126 | }
127 | }
--------------------------------------------------------------------------------
/server/scripts/data/db_edit.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | editServer(db, server) {
3 | if(db.DEBUG) {
4 | console.log(" - [db] Editing Server(id: " + server.id + ") in the database...");
5 | }
6 |
7 | var query0 = "name=?, avatar=?, channels=?, members=?, emotes=?" + (server.banner == null ? "" : ", banner=?")
8 | var query1 = [ db.escapeString(server.name), server.avatar, server.channels.join(","), server.members.join(","), server.emotes.join(",") ]
9 | if(server.banner != null) { query1.push(server.banner); }
10 |
11 | var query = "UPDATE servers SET " + query0 + " WHERE id='" + server.id + "'";
12 | db.sqlConn.promise().execute(query, query1)
13 | .then((result, err) => {
14 | if(err) { throw err; }
15 | });
16 | },
17 |
18 | editUser(db, user) {
19 | if(db.DEBUG) {
20 | console.log(" - [db] Editing User(id: " + user.id + ") in the database...");
21 | }
22 |
23 | var query0 = "username=?, avatar=?, friends=?, dmChannels=?, servers=?, userStatus=?, badges=?, emotes=?" + (user.email == null ? "" : ", email=?") + (user.password == null ? "" : ", password=?") + (user.customStatus == null || user.customStatus.length < 1 ? "" : ", customStatus=?")
24 | + (user.gh_username == null ? "" : ", gh_username=?") + (user.gh_token == null ? "" : ", gh_token=?") + (user.reddit_username == null ? "" : ", reddit_username=?") + (user.reddit_token == null ? "" : ", reddit_token=?")
25 | + (user.osu_username == null ? "" : ", osu_username=?") + (user.osu_token == null ? "" : ", osu_token=?") + (user.twitch_username == null ? "" : ", twitch_username=?") + (user.twitch_token == null ? "" : ", twitch_token=?")
26 | + (user.blizzard_username == null ? "" : ", blizzard_username=?") + (user.blizzard_token == null ? "" : ", blizzard_token=?") + (user.spotify_username == null ? "" : ", spotify_username=?") + (user.spotify_token == null ? "" : ", spotify_token=?")
27 | + (user.discord_username == null ? "" : ", discord_username=?") + (user.discord_token == null ? "" : ", discord_token=?")
28 | var query1 = [ db.escapeString(user.username), user.avatar, user.friends.join(","), user.dmChannels.join(","), user.servers.join(","), user.userStatus, user.badges.join(","), user.emotes.join(",") ]
29 | if(user.email != null) { query1.push(db.escapeString(user.email)); }
30 | if(user.password != null) { query1.push(user.password); }
31 | if(user.customStatus != null) { if(user.customStatus.length < 1) { this.clearUserStatus(db, user); } else { query1.push(user.customStatus); } }
32 | if(user.gh_username != null) { query1.push(user.gh_username); }
33 | if(user.gh_token != null) { query1.push(user.gh_token); }
34 | if(user.reddit_username != null) { query1.push(user.reddit_username); }
35 | if(user.reddit_token != null) { query1.push(user.reddit_token); }
36 | if(user.osu_username != null) { query1.push(user.osu_username); }
37 | if(user.osu_token != null) { query1.push(user.osu_token); }
38 | if(user.twitch_username != null) { query1.push(user.twitch_username); }
39 | if(user.twitch_token != null) { query1.push(user.twitch_token); }
40 | if(user.blizzard_username != null) { query1.push(user.blizzard_username); }
41 | if(user.blizzard_token != null) { query1.push(user.blizzard_token); }
42 | if(user.spotify_username != null) { query1.push(user.spotify_username); }
43 | if(user.spotify_token != null) { query1.push(user.spotify_token); }
44 | if(user.discord_username != null) { query1.push(user.discord_username); }
45 | if(user.discord_token != null) { query1.push(user.discord_token); }
46 |
47 | var query = "UPDATE users SET " + query0 + " WHERE id='" + user.id + "'";
48 | db.sqlConn.promise().execute(query, query1)
49 | .then((result, err) => {
50 | if(err) { throw err; }
51 | });
52 | },
53 |
54 | clearUserStatus(db, user) {
55 | db.sqlConn.promise().query("UPDATE users SET customStatus=NULL WHERE id='" + user.id + "'")
56 | .then((result, err) => {
57 | if(err) { throw err; }
58 | });
59 | },
60 |
61 | removeUserConnection(db, user, type) {
62 | db.sqlConn.promise().query("UPDATE users SET " + db.escapeString(type) + "_token=NULL, " + db.escapeString(type) + "_username=NULL WHERE id='" + user.id + "'")
63 | .then((result, err) => {
64 | if(err) { throw err; }
65 | });
66 | },
67 |
68 | editMessage(db, message) {
69 | if(db.DEBUG) {
70 | console.log(" - [db] Editing Message(id: " + message.id + ") in the database...");
71 | }
72 |
73 | var query0 = "edited=?, type=?" + (message.text == null ? "" : ", text=?") + (message.file == null ? "" : ", fileName=?, fileSize=?")
74 | var query1 = [ message.edited, message.type ]
75 | if(message.text != null) { query1.push(db.escapeString(message.text)); }
76 | if(message.file != null) { query1.push(db.escapeString(message.file.name), message.file.size); }
77 |
78 | var query = "UPDATE messages SET " + query0 + " WHERE id='" + message.id + "'";
79 | db.sqlConn.promise().execute(query, query1)
80 | .then((result, err) => {
81 | if(err) { throw err; }
82 | });
83 | },
84 |
85 | editChannel(db, channel) {
86 | if(db.DEBUG) {
87 | console.log(" - [db] Editing Channel(id: " + channel.id + ") in the database...");
88 | }
89 |
90 | var query0 = "name=?, nsfw=?" + (channel.position == null ? "" : ", position=?") + (channel.members == null ? "" : ", members=?") + (channel.description == null ? "" : ", description=?")
91 | var query1 = [ db.escapeString(channel.name), channel.nsfw ]
92 | if(channel.position != null) { query1.push(channel.position); }
93 | if(channel.members != null) { query1.push(channel.members.join(",")); }
94 | if(channel.description != null) { query1.push(channel.description); }
95 |
96 | var query = "UPDATE channels SET " + query0 + " WHERE id='" + channel.id + "'";
97 | db.sqlConn.promise().execute(query, query1)
98 | .then((result, err) => {
99 | if(err) { throw err; }
100 | });
101 | },
102 |
103 | editNote(db, note) {
104 | if(db.DEBUG) {
105 | console.log(" - [db] Editing Note(id: " + note.id + ") in the database...");
106 | }
107 |
108 | var query0 = "text=?"
109 | var query1 = [ db.escapeString(note.text) ]
110 |
111 | var query = "UPDATE notes SET " + query0 + " WHERE id='" + note.id + "'";
112 | db.sqlConn.promise().execute(query, query1)
113 | .then((result, err) => {
114 | if(err) { throw err; }
115 | });
116 | }
117 | }
--------------------------------------------------------------------------------
/server/scripts/data/db_manager.js:
--------------------------------------------------------------------------------
1 | class DatabaseManager {
2 | constructor(_app, _sql, _conn) {
3 | this.sql = _sql
4 | this.sqlConn = _conn;
5 | this.app = _app;
6 |
7 | this.db_add = require('./db_add');
8 | this.db_edit = require('./db_edit');
9 | this.db_delete = require('./db_delete');
10 | this.db_fetch = require('./db_fetch');
11 | this.DEBUG = true;
12 |
13 | if(process.argv.includes("-rd")) {
14 | this.db_delete.deleteAllData(this);
15 | }
16 | }
17 |
18 | contructQuestionMarks(i) {
19 | let str = "(";
20 | for(let i2 = 0; i2 < i; i2++) {
21 | str += "?,"
22 | }
23 | str = str.substring(0, str.length - 1) + ")"
24 |
25 | return str;
26 | }
27 |
28 | escapeString(str) {
29 | return str;
30 | }
31 | }
32 |
33 | module.exports = DatabaseManager;
--------------------------------------------------------------------------------
/server/scripts/endpoints/acceptFriendRequest.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/acceptFriendRequest', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.app.epFunc.processFriendRequest(req, res, req.body, true)
11 | console.log("> accepted friend request - " + req.body.id)
12 | }).bind(this));
13 | }
14 | }
15 |
16 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/addToDMChannel.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/addToDMChannel', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.addToDMChannel(req, res, req.body)
11 | console.log("> added to dm channel - " + req.body.channel.id + "/" + req.body.user.id)
12 | }).bind(this));
13 | }
14 |
15 | async addToDMChannel(req, res, _data) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, _data.channel.id);
19 | var targetUser = await this.app.db.db_fetch.fetchUser(this.app.db, _data.user.id);
20 |
21 | if(channel === undefined) {
22 | res.send(JSON.stringify({ status: -1 }))
23 | return;
24 | } else if(targetUser === undefined) {
25 | res.send(JSON.stringify({ status: -2 }))
26 | return;
27 | } else if(channel.author.id !== user.id) {
28 | res.send(JSON.stringify({ status: -3 }))
29 | return;
30 | } else if(channel.members.includes(targetUser.id) === true) {
31 | res.send(JSON.stringify({ status: -4 }))
32 | return;
33 | } else {
34 | res.sendStatus(200);
35 | }
36 |
37 | channel.members.push(targetUser.id);
38 | channel.members.forEach(id => {
39 | this.app.epFunc.emitToUser(id, "updateChannel", channel)
40 | });
41 |
42 | targetUser.dmChannels.push(channel.id);
43 | this.app.epFunc.emitToUser(targetUser.id, "createChannel", channel);
44 |
45 | await this.app.db.db_edit.editChannel(this.app.db, channel);
46 | await this.app.db.db_edit.editUser(this.app.db, targetUser);
47 | this.app.epFunc.sendSystemMessage({ channel: { id: channel.id }, text: "<@" + targetUser.id + "> was added by <@" + user.id + ">", type: 1 })
48 | }
49 | }
50 |
51 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/auth_blizzard.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/auth_blizzard', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | var session = this.app.sessions.get(req.cookies['sessionID']);
10 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
11 | var data = req.query;
12 |
13 | //https://us.battle.net/oauth/authorize?client_id=24428d45ed4b42448c9a33f1161585c5&redirect_uri=https://nekonetwork.net:8080/auth_blizzard&response_type=code&scope=openid
14 | this.app.axios.post("https://us.battle.net/oauth/token",
15 | "code=" + data.code + "&grant_type=authorization_code&redirect_uri=https://nekonetwork.net:8080/auth_blizzard&scope=openid",
16 | {
17 | headers: {
18 | "Content-Type": "application/x-www-form-urlencoded",
19 | "Authorization": "Basic " + Buffer.from(this.app.config["auth_blizzard_id"] + ":" + this.app.config["auth_blizzard_token"]).toString("base64"),
20 | }
21 | }).then(res1 => {
22 | if(res1.data["access_token"] !== undefined) {
23 | this.app.axios.get("https://us.battle.net/oauth/userinfo", {
24 | headers: {
25 | "Authorization": "Bearer " + res1.data["access_token"]
26 | }
27 | }).then(res2 => {
28 | this.app.epFunc.editUser(req, res, { "blizzard_token": res1.data["access_token"], "blizzard_username": res2.data["battletag"] });
29 | });
30 | } else {
31 | res.sendStatus(401)
32 | }
33 | });
34 | }).bind(this));
35 | }
36 | }
37 |
38 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/auth_discord.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/auth_discord', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | var session = this.app.sessions.get(req.cookies['sessionID']);
10 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
11 | var data = req.query;
12 |
13 | //https://discord.com/api/oauth2/authorize?client_id=803587850762453072&redirect_uri=https://nekonetwork.net:8080/auth_discord&response_type=code&scope=identify
14 | this.app.axios.post("https://discord.com/api/v6/oauth2/token",
15 | "client_id=" + this.app.config["auth_discord_id"] + "&client_secret=" + this.app.config["auth_discord_token"] + "&code=" + data.code + "&grant_type=authorization_code&redirect_uri=https://nekonetwork.net:8080/auth_discord&scope=identify",
16 | {
17 | headers: {
18 | "Content-Type": "application/x-www-form-urlencoded",
19 | }
20 | }).then(res1 => {
21 | if(res1.data["access_token"] !== undefined) {
22 | this.app.axios.get("https://discord.com/api/v6/users/@me", {
23 | headers: {
24 | "Authorization": "Bearer " + res1.data["access_token"]
25 | }
26 | }).then(res2 => {
27 | this.app.epFunc.editUser(req, res, { "discord_token": res1.data["access_token"], "discord_username": res2.data["username"] });
28 | });
29 | } else {
30 | res.sendStatus(401)
31 | }
32 | });
33 | }).bind(this));
34 | }
35 | }
36 |
37 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/auth_gh.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/auth_gh', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | var session = this.app.sessions.get(req.cookies['sessionID']);
10 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
11 | var data = req.query;
12 |
13 | //https://github.com/login/oauth/authorize?client_id=91bcd730211830731d9a
14 | this.app.axios.post("https://github.com/login/oauth/access_token?client_id=" + this.app.config["auth_gh_id"] + "&client_secret=" + this.app.config["auth_gh_token"] + "&code=" + data.code, {},
15 | {
16 | headers: { "Accept": "application/json" }
17 | }).then(res1 => {
18 | if(res1.data["access_token"] !== undefined) {
19 | this.app.axios.get("https://api.github.com/user", {
20 | headers: { "Authorization": "token " + res1.data["access_token"] }
21 | }).then(res2 => {
22 | this.app.epFunc.editUser(req, res, { "gh_token": res1.data["access_token"], "gh_username": res2.data.login });
23 | });
24 | } else {
25 | res.sendStatus(401)
26 | }
27 | });
28 | }).bind(this));
29 | }
30 | }
31 |
32 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/auth_osu.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/auth_osu', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | var session = this.app.sessions.get(req.cookies['sessionID']);
10 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
11 | var data = req.query;
12 |
13 | //https://osu.ppy.sh/oauth/authorize?client_id=4883&redirect_uri=https://nekonetwork.net:8080/auth_osu&response_type=code&scope=public
14 | this.app.axios.post("https://osu.ppy.sh/oauth/token",
15 | "client_id=" + this.app.config["auth_osu_id"] + "&client_secret=" + this.app.config["auth_osu_token"] + "&code=" + data.code + "&grant_type=authorization_code&redirect_uri=https://nekonetwork.net:8080/auth_osu",
16 | {
17 | headers: { "Accept": "application/json" }
18 | }).then(res1 => {
19 | if(res1.data["access_token"] !== undefined) {
20 | this.app.axios.get("https://osu.ppy.sh/api/v2/me", {
21 | headers: { "Authorization": "Bearer " + res1.data["access_token"] }
22 | }).then(res2 => {
23 | this.app.epFunc.editUser(req, res, { "osu_token": res1.data["access_token"], "osu_username": res2.data.username });
24 | });
25 | } else {
26 | res.sendStatus(401)
27 | }
28 | });
29 | }).bind(this));
30 | }
31 | }
32 |
33 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/auth_reddit.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/auth_reddit', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | var session = this.app.sessions.get(req.cookies['sessionID']);
10 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
11 | var data = req.query;
12 |
13 | //https://www.reddit.com/api/v1/authorize?client_id=g8QfIB742iwMKw&response_type=code&state=a&redirect_uri=https://nekonetwork.net:8080/auth_reddit&duration=permanent&scope=identity
14 | this.app.axios.post("https://www.reddit.com/api/v1/access_token",
15 | "grant_type=authorization_code&code=" + data.code + "&redirect_uri=https://nekonetwork.net:8080/auth_reddit",
16 | {
17 | headers: {
18 | "Content-Type": "application/x-www-form-urlencoded",
19 | "Authorization": "Basic " + Buffer.from(this.app.config["auth_reddit_id"] + ":" + this.app.config["auth_reddit_token"]).toString("base64"),
20 | }
21 | }).then(res1 => {
22 | if(res1.data["access_token"] !== undefined) {
23 | this.app.axios.get("https://oauth.reddit.com/api/v1/me", {
24 | headers: { "Authorization": "bearer " + res1.data["access_token"] }
25 | }).then(res2 => {
26 | this.app.epFunc.editUser(req, res, { "reddit_token": res1.data["access_token"], "reddit_username": res2.data.name });
27 | });
28 | } else {
29 | res.sendStatus(401)
30 | }
31 | });
32 | }).bind(this));
33 | }
34 | }
35 |
36 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/auth_spotify.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/auth_spotify', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | var session = this.app.sessions.get(req.cookies['sessionID']);
10 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
11 | var data = req.query;
12 |
13 | //https://accounts.spotify.com/authorize?client_id=d10fc3159d9c4c3ea3c307df4b04ca43&redirect_uri=https://nekonetwork.net:8080/auth_spotify&response_type=code
14 | this.app.axios.post("https://accounts.spotify.com/api/token",
15 | "code=" + data.code + "&grant_type=authorization_code&redirect_uri=https://nekonetwork.net:8080/auth_spotify&scope=openid",
16 | {
17 | headers: {
18 | "Content-Type": "application/x-www-form-urlencoded",
19 | "Authorization": "Basic " + Buffer.from(this.app.config["auth_spotify_id"] + ":" + this.app.config["auth_spotify_token"]).toString("base64"),
20 | }
21 | }).then(res1 => {
22 | if(res1.data["access_token"] !== undefined) {
23 | this.app.axios.get("https://api.spotify.com/v1/me", {
24 | headers: {
25 | "Authorization": "Bearer " + res1.data["access_token"]
26 | }
27 | }).then(res2 => {
28 | this.app.epFunc.editUser(req, res, { "spotify_token": res1.data["access_token"], "spotify_username": res2.data["display_name"] });
29 | });
30 | } else {
31 | res.sendStatus(401)
32 | }
33 | });
34 | }).bind(this));
35 | }
36 | }
37 |
38 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/auth_twitch.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/auth_twitch', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | var session = this.app.sessions.get(req.cookies['sessionID']);
10 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
11 | var data = req.query;
12 |
13 | //https://id.twitch.tv/oauth2/authorize?client_id=3oxkg8rjxqox7kkx4qu9b7d441mzse&redirect_uri=https://nekonetwork.net:8080/auth_twitch&response_type=code&scope=user:read:email
14 | this.app.axios.post("https://id.twitch.tv/oauth2/token",
15 | "client_id=" + this.app.config["auth_twitch_id"] + "&client_secret=" + this.app.config["auth_twitch_token"] + "&code=" + data.code + "&grant_type=authorization_code&redirect_uri=https://nekonetwork.net:8080/auth_twitch",
16 | {
17 | headers: { "Accept": "application/json" }
18 | }).then(res1 => {
19 | if(res1.data["access_token"] !== undefined) {
20 | this.app.axios.get("https://api.twitch.tv/helix/users", {
21 | headers: {
22 | "Authorization": "Bearer " + res1.data["access_token"],
23 | "Client-Id": this.app.config["auth_twitch_id"]
24 | }
25 | }).then(res2 => {
26 | this.app.epFunc.editUser(req, res, { "twitch_token": res1.data["access_token"], "twitch_username": res2.data.data[0]["login"] });
27 | });
28 | } else {
29 | res.sendStatus(401)
30 | }
31 | });
32 | }).bind(this));
33 | }
34 | }
35 |
36 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/cloneChannel.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/cloneChannel', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.cloneChannel(req, res, req.body)
11 | console.log("> cloned channel - " + req.body.id)
12 | }).bind(this));
13 | }
14 |
15 | async cloneChannel(req, res, _channel) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, _channel.id);
19 | if(channel === undefined) {
20 | res.send(JSON.stringify({ status: -1 }))
21 | return;
22 | } else if(channel.type === 2) {
23 | res.send(JSON.stringify({ status: -2 }))
24 | return;
25 | }
26 |
27 | channel.id = this.app.crypto.randomBytes(16).toString("hex");
28 | channel.createdAt = Date.now();
29 | channel.author = { id: user.id };
30 |
31 | switch(channel.type) {
32 | case 0:
33 | case 1:
34 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, channel.server.id);
35 | if(server === undefined) {
36 | res.send(JSON.stringify({ status: -3 }))
37 | return;
38 | } else if(server.author.id !== user.id) {
39 | res.send(JSON.stringify({ status: -4 }))
40 | return;
41 | }
42 |
43 | channel.position = server.channels.length;
44 | server.channels.push(channel.id)
45 | server.members.forEach(id => {
46 | this.app.epFunc.emitToUser(id, "createChannel", channel);
47 | this.app.epFunc.emitToUser(id, "updateServer", server);
48 | });
49 |
50 | await this.app.db.db_edit.editServer(this.app.db, server);
51 | break;
52 | }
53 |
54 | await this.app.db.db_add.addChannel(this.app.db, channel);
55 | res.send(JSON.stringify(channel))
56 | }
57 | }
58 |
59 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/createChannel.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/createChannel', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.createChannel(req, res, req.body)
11 | console.log("> created channel - " + req.body.name)
12 | }).bind(this));
13 | }
14 |
15 | async createChannel(req, res, _channel) {
16 | if(_channel.name.length < 1) {
17 | res.send(JSON.stringify({ status: -1 }))
18 | return;
19 | }
20 |
21 | var session = this.app.sessions.get(req.cookies['sessionID']);
22 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
23 | var channel = {
24 | id: this.app.crypto.randomBytes(16).toString("hex"),
25 | name: _channel.name,
26 | description: _channel.description,
27 | nsfw: _channel.nsfw === undefined ? false : _channel.nsfw,
28 | type: _channel.type,
29 | createdAt: Date.now(),
30 | author: {
31 | id: user.id
32 | }
33 | }
34 |
35 | switch(_channel.type) {
36 | case 0:
37 | case 1:
38 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, _channel.server.id);
39 | if(server === undefined) {
40 | res.send(JSON.stringify({ status: -2 }))
41 | return;
42 | } else if(server.author.id !== user.id) {
43 | res.send(JSON.stringify({ status: -4 }))
44 | return;
45 | }
46 |
47 | channel.server = { id: _channel.server.id };
48 | channel.position = server.channels.length;
49 | server.channels.push(channel.id)
50 | server.members.forEach(id => {
51 | this.app.epFunc.emitToUser(id, "createChannel", channel);
52 | this.app.epFunc.emitToUser(id, "updateServer", server);
53 | });
54 |
55 | await this.app.db.db_edit.editServer(this.app.db, server);
56 | break;
57 |
58 | case 2:
59 | channel.members = _channel.members;
60 | channel.members.forEach(async(id) => {
61 | var user2 = await this.app.db.db_fetch.fetchUser(this.app.db, id);
62 | user2.dmChannels.push(channel.id);
63 | this.app.db.db_edit.editUser(this.app.db, user2);
64 |
65 | this.app.epFunc.emitToUser(user2.id, "createChannel", channel);
66 | this.app.epFunc.emitToUser(user2.id, "updateUser", user2);
67 | });
68 | break;
69 | }
70 |
71 | await this.app.db.db_add.addChannel(this.app.db, channel);
72 | res.send(JSON.stringify(channel))
73 | }
74 | }
75 |
76 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/createEmote.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/createEmote', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.createEmote(req, res, req.query.emoteName, req.query.serverID, req.query.type);
11 | console.log("> created emote - " + req.query.emoteName + "/" + req.query.serverID + "/" + req.query.type);
12 | }).bind(this));
13 | }
14 |
15 | async createEmote(req, res, emoteName, serverID, type) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var form = this.app.formidable({ multiples: true });
19 |
20 | var emote = {
21 | id: this.app.crypto.randomBytes(16).toString("hex"),
22 | createdAt: Date.now(),
23 | author: {
24 | id: user.id
25 | },
26 | name: emoteName,
27 | type: parseInt(type)
28 | }
29 |
30 | switch(emote.type) {
31 | case 0:
32 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, serverID);
33 |
34 | if(server === undefined) {
35 | res.send(JSON.stringify({ status: -1 }))
36 | return;
37 | } else if (server.author.id !== user.id) {
38 | res.send(JSON.stringify({ status: -2 }))
39 | return;
40 | }
41 |
42 | form.uploadDir = this.app.filesStorage;
43 | form.keepExtensions = true;
44 |
45 | var fileName = req.query.fileName;
46 | var fileID = this.app.crypto.randomBytes(16).toString("hex");
47 | var fileID2 = fileID + (fileName.substring(fileName.lastIndexOf(".")))
48 | console.log("> received emote - " + fileName)
49 |
50 | form.parse(req, async function(err, fields, files) {
51 | this.app.fs.rename(files.fileUploaded.path, this.app.filesStorage + fileID2, function(err) {
52 | if (err) { throw err; }
53 | });
54 |
55 | emote.file = fileID2;
56 | emote.server = { id: serverID }
57 |
58 | await this.app.db.db_add.addEmote(this.app.db, emote);
59 | server.emotes.push(emote.id)
60 | await this.app.epFunc.updateServer(server, true)
61 |
62 | res.send(JSON.stringify(emote));
63 | }.bind(this));
64 | break;
65 |
66 | case 1:
67 | form.uploadDir = this.app.filesStorage;
68 | form.keepExtensions = true;
69 |
70 | var fileName = req.query.fileName;
71 | var fileID = this.app.crypto.randomBytes(16).toString("hex");
72 | var fileID2 = fileID + (fileName.substring(fileName.lastIndexOf(".")))
73 | console.log("> received emote - " + fileName)
74 |
75 | form.parse(req, async function(err, fields, files) {
76 | this.app.fs.rename(files.fileUploaded.path, this.app.filesStorage + fileID2, function(err) {
77 | if (err) { throw err; }
78 | });
79 |
80 | emote.file = fileID2;
81 |
82 | await this.app.db.db_add.addEmote(this.app.db, emote);
83 | user.emotes.push(emote.id)
84 | await this.app.epFunc.updateUser(user, true)
85 |
86 | res.send(JSON.stringify(emote));
87 | }.bind(this));
88 | break;
89 |
90 | case 2:
91 | if (user.badges.includes("2")) {
92 | res.send(JSON.stringify({ status: -2 }))
93 | return;
94 | }
95 |
96 | form.uploadDir = this.app.filesStorage;
97 | form.keepExtensions = true;
98 |
99 | var fileName = req.query.fileName;
100 | var fileID = this.app.crypto.randomBytes(16).toString("hex");
101 | var fileID2 = fileID + (fileName.substring(fileName.lastIndexOf(".")))
102 | console.log("> received emote - " + fileName)
103 |
104 | form.parse(req, async function(err, fields, files) {
105 | this.app.fs.rename(files.fileUploaded.path, this.app.filesStorage + fileID2, function(err) {
106 | if (err) { throw err; }
107 | });
108 |
109 | emote.file = fileID2;
110 |
111 | await this.app.db.db_add.addEmote(this.app.db, emote);
112 |
113 | res.send(JSON.stringify(emote));
114 | }.bind(this));
115 | break;
116 | }
117 | }
118 | }
119 |
120 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/createInvite.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/createInvite', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.createInvite(req, res, req.body)
11 | console.log("> created invite - " + req.body.server.id)
12 | }).bind(this));
13 | }
14 |
15 | async createInvite(req, res, _invite) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, _invite.server.id);
19 |
20 | if(server === undefined) {
21 | res.send(JSON.stringify({ status: -1 }))
22 | return;
23 | } else if (server.author.id !== user.id) {
24 | res.send(JSON.stringify({ status: -2 }))
25 | return;
26 | }
27 |
28 | var invite = {
29 | id: this.app.crypto.randomBytes(16).toString("hex"),
30 | createdAt: Date.now(),
31 | server: {
32 | id: _invite.server.id
33 | },
34 | author: {
35 | id: user.id
36 | }
37 | }
38 |
39 | server.invites.push(invite);
40 | server.members.forEach(async(id) => {
41 | this.app.epFunc.emitToUser(id, "updateServer", server);
42 | });
43 |
44 | await this.app.db.db_add.addInvite(this.app.db, invite);
45 | res.send(JSON.stringify(invite))
46 | }
47 | }
48 |
49 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/createServer.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/createServer', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.createServer(req, res, req.body)
11 | console.log("> created server - " + req.body.name)
12 | }).bind(this));
13 | }
14 |
15 | async createServer(req, res, _server) {
16 | if(_server.name.length < 1) {
17 | res.send(JSON.stringify({ status: -1 }))
18 | return;
19 | }
20 |
21 | var socket = this.app.sessionSockets.get(req.cookies['sessionID']);
22 | var session = this.app.sessions.get(req.cookies['sessionID']);
23 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
24 | var server = {
25 | id: this.app.crypto.randomBytes(16).toString("hex"),
26 | name: _server.name,
27 | avatar: "defaultAvatar.png",
28 | createdAt: Date.now(),
29 | author: {
30 | id: user.id
31 | },
32 | channels: [],
33 | members: [ user.id ],
34 | invites: [],
35 | emotes: []
36 | }
37 |
38 | server.members.forEach(async(id) => {
39 | var user2 = await this.app.db.db_fetch.fetchUser(this.app.db, id);
40 | user2.servers.push(server.id);
41 | this.app.db.db_edit.editUser(this.app.db, user2);
42 |
43 | this.app.epFunc.emitToUser(user2.id, "createServer", server);
44 | this.app.epFunc.emitToUser(user2.id, "updateUser", user2);
45 | });
46 |
47 | await this.app.db.db_add.addServer(this.app.db, server);
48 | res.send(JSON.stringify(server))
49 | }
50 | }
51 |
52 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/declineFriendRequest.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/declineFriendRequest', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.app.epFunc.processFriendRequest(req, res, req.body, false)
11 | console.log("> declined friend request - " + req.body.id)
12 | }).bind(this));
13 | }
14 | }
15 |
16 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/deleteChannel.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/deleteChannel', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.deleteChannel(req, res, req.body)
11 | console.log("> deleted channel - " + req.body.id)
12 | }).bind(this));
13 | }
14 |
15 | async deleteChannel(req, res, _channel) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, _channel.id);
19 |
20 | if(channel === undefined) {
21 | res.send(JSON.stringify({ status: -1 }))
22 | return;
23 | } else if(channel.author.id !== user.id) {
24 | res.send(JSON.stringify({ status: -2 }))
25 | return;
26 | }
27 |
28 | switch(channel.type) {
29 | case 0:
30 | case 1:
31 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, channel.server.id);
32 | if(server.channels.includes(channel.id) === false) {
33 | res.send(JSON.stringify({ status: -3 }))
34 | return;
35 | }
36 |
37 | server.channels.splice(server.channels.indexOf(channel.id), 1)
38 | server.members.forEach(id => {
39 | this.app.epFunc.emitToUser(id, "deleteChannel", channel)
40 | });
41 |
42 | await this.app.db.db_edit.editServer(this.app.db, server);
43 | break;
44 |
45 | case 2:
46 | channel.members = channel.members;
47 | channel.members.forEach(async(id) => {
48 | var user2 = await this.app.db.db_fetch.fetchUser(this.app.db, id);
49 | user2.dmChannels.splice(user2.dmChannels.indexOf(channel.id), 1);
50 | this.app.db.db_edit.editUser(this.app.db, user2);
51 |
52 | this.app.epFunc.emitToUser(user2.id, "deleteChannel", channel);
53 | this.app.epFunc.emitToUser(user2.id, "updateUser", user2);
54 | });
55 | break;
56 | }
57 |
58 | res.sendStatus(200);
59 | await this.app.db.db_delete.deleteChannel(this.app.db, channel.id);
60 | }
61 | }
62 |
63 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/deleteEmote.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/deleteEmote', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.deleteEmote(req, res, req.body)
11 | console.log("> deleted emote - " + req.body.id)
12 | }).bind(this));
13 | }
14 |
15 | async deleteEmote(req, res, _emote) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var emote = await this.app.db.db_fetch.fetchEmote(this.app.db, _emote.id);
19 |
20 | if(emote === undefined) {
21 | res.send(JSON.stringify({ status: -1 }))
22 | return;
23 | } else if(emote.author.id !== user.id) {
24 | res.send(JSON.stringify({ status: -2 }))
25 | return;
26 | }
27 |
28 | switch(emote.type) {
29 | case 0:
30 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, emote.server.id);
31 | if(server.emotes.includes(emote.id) === false) {
32 | res.send(JSON.stringify({ status: -3 }))
33 | return;
34 | }
35 |
36 | server.emotes.splice(server.emotes.indexOf(emote.id), 1)
37 | server.members.forEach(id => {
38 | this.app.epFunc.emitToUser(id, "deleteEmote", emote)
39 | });
40 |
41 | await this.app.db.db_edit.editServer(this.app.db, server);
42 | break;
43 |
44 | case 1:
45 | var user2 = await this.app.db.db_fetch.fetchUser(this.app.db, emote.author.id);
46 | user2.emotes.splice(user2.emotes.indexOf(emote.id), 1);
47 | this.app.db.db_edit.editUser(this.app.db, user2);
48 |
49 | this.app.epFunc.emitToUser(user2.id, "deleteEmote", emote);
50 | this.app.epFunc.emitToUser(user2.id, "updateUser", user2);
51 | break;
52 | }
53 |
54 | res.sendStatus(200);
55 | await this.app.db.db_delete.deleteEmote(this.app.db, emote.id);
56 | }
57 | }
58 |
59 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/deleteMessage.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/deleteMessage', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.deleteMessage(req, res, req.body)
11 | console.log("> deleted message - " + req.body.id)
12 | }).bind(this));
13 | }
14 |
15 | async deleteMessage(req, res, _message) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var message = await this.app.db.db_fetch.fetchMessage(this.app.db, _message.id);
19 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, message.channel.id);
20 |
21 | if(message === undefined) {
22 | res.send(JSON.stringify({ status: -1 }))
23 | return;
24 | } else if(message.author.id !== user.id) {
25 | res.send(JSON.stringify({ status: -2 }))
26 | return;
27 | } else {
28 | res.sendStatus(200);
29 | }
30 |
31 | switch(channel.type) {
32 | case 0:
33 | case 1:
34 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, channel.server.id);
35 | server.members.forEach(id => {
36 | this.app.epFunc.emitToUser(id, "deleteMessage", message)
37 | });
38 | break;
39 |
40 | case 2:
41 | channel.members.forEach(async(id) => {
42 | this.app.epFunc.emitToUser(id, "deleteMessage", message);
43 | });
44 | break;
45 | }
46 |
47 | await this.app.db.db_delete.deleteMessage(this.app.db, message.id);
48 | }
49 | }
50 |
51 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/deleteServer.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/deleteServer', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.deleteServer(req, res, req.body)
11 | console.log("> deleted server - " + req.body.id)
12 | }).bind(this));
13 | }
14 |
15 | async deleteServer(req, res, _server) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, _server.id);
19 |
20 | if(server === undefined) {
21 | res.send(JSON.stringify({ status: -1 }))
22 | return;
23 | } else if(server.author.id !== user.id) {
24 | res.send(JSON.stringify({ status: -2 }))
25 | return;
26 | } else {
27 | res.sendStatus(200);
28 | }
29 |
30 | server.members.forEach(async(id) => {
31 | var user2 = await this.app.db.db_fetch.fetchUser(this.app.db, id);
32 | user2.servers.splice(user2.servers.indexOf(server.id), 1);
33 | this.app.db.db_edit.editUser(this.app.db, user2);
34 | });
35 |
36 | this.app.sessionSockets.forEach(socket => {
37 | if(socket.connected) {
38 | socket.emit("deleteServer", JSON.stringify(server))
39 | }
40 | })
41 |
42 | await this.app.db.db_delete.deleteServer(this.app.db, server.id);
43 | }
44 | }
45 |
46 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/editChannel.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/editChannel', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.editChannel(req, res, req.body)
11 | console.log("> edited channel - " + req.body.id)
12 | }).bind(this));
13 | }
14 |
15 | async editChannel(req, res, _channel) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, _channel.id);
19 |
20 | if(channel === undefined) {
21 | res.send(JSON.stringify({ status: -1 }))
22 | return;
23 | } else if(channel.author.id !== user.id) {
24 | res.send(JSON.stringify({ status: -2 }))
25 | return;
26 | } else if(_channel.name !== undefined && _channel.name.length < 1) {
27 | res.send(JSON.stringify({ status: -3 }))
28 | return;
29 | }
30 |
31 | //Make sure client doesn't overwrite something he's not allowed to
32 | channel.name = _channel.name !== undefined ? _channel.name : channel.name;
33 | channel.description = _channel.description !== undefined ? _channel.description : channel.description;
34 | channel.nsfw = _channel.nsfw !== undefined ? _channel.nsfw : channel.nsfw;
35 |
36 | switch(channel.type) {
37 | case 0:
38 | case 1:
39 | channel.position = _channel.position !== undefined ? _channel.position : channel.position;
40 |
41 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, channel.server.id);
42 | server.members.forEach(id => {
43 | this.app.epFunc.emitToUser(id, "updateChannel", channel)
44 | });
45 | break;
46 |
47 | case 2:
48 | channel.members.forEach(async(id) => {
49 | this.app.epFunc.emitToUser(id, "updateChannel", channel)
50 | });
51 | break;
52 | }
53 |
54 | await this.app.db.db_edit.editChannel(this.app.db, channel);
55 | res.send(JSON.stringify(channel))
56 | }
57 | }
58 |
59 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/editMessage.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/editMessage', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.editMessage(req, res, req.body)
11 | console.log("> received message edit - " + req.body.text)
12 | }).bind(this));
13 | }
14 |
15 | async editMessage(req, res, _message) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var message = await this.app.db.db_fetch.fetchMessage(this.app.db, _message.id);
19 |
20 | if(message === undefined) {
21 | res.send(JSON.stringify({ status: -1 }))
22 | return;
23 | } else if(message.author.id !== user.id) {
24 | res.send(JSON.stringify({ status: -2 }))
25 | return;
26 | }
27 |
28 | //Make sure client doesn't overwrite something he's not allowed to
29 | message.text = _message.text;
30 | message.edited = true;
31 |
32 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, message.channel.id);
33 | switch(channel.type) {
34 | case 0:
35 | case 1:
36 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, channel.server.id);
37 | server.members.forEach(id => {
38 | this.app.epFunc.emitToUser(id, "editMessage", message)
39 | });
40 | break;
41 |
42 | case 2:
43 | channel.members.forEach(async(id) => {
44 | this.app.epFunc.emitToUser(id, "editMessage", message)
45 | });
46 | break;
47 | }
48 |
49 | await this.app.db.db_edit.editMessage(this.app.db, message);
50 | res.send(JSON.stringify(message))
51 | }
52 | }
53 |
54 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/editNote.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/editNote', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.app.epFunc.editNote(req, res, req.body);
11 | console.log("> received note update - " + req.body.text);
12 | }).bind(this));
13 | }
14 | }
15 |
16 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/editServer.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/editServer', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.editServer(req, res, req.body);
11 | console.log("> received server update - " + req.body.id);
12 | }).bind(this));
13 | }
14 |
15 | async editServer(req, res, _server) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, _server.id);
19 |
20 | if(server === undefined) {
21 | res.send(JSON.stringify({ status: -1 }))
22 | return;
23 | } else if(server.author.id !== user.id) {
24 | res.send(JSON.stringify({ status: -2 }))
25 | return;
26 | } else if(_server.name !== undefined && _server.name.length < 1) {
27 | res.send(JSON.stringify({ status: -3 }))
28 | return;
29 | }
30 |
31 | //Make sure client doesn't overwrite something he's not allowed to
32 | server.name = _server.name !== undefined ? _server.name : server.name;
33 |
34 | server.members.forEach(id => {
35 | this.app.epFunc.emitToUser(id, "updateServer", server)
36 | });
37 |
38 | await this.app.db.db_edit.editServer(this.app.db, server);
39 | res.send(JSON.stringify(server))
40 | }
41 | }
42 |
43 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/editUser.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/editUser', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.app.epFunc.editUser(req, res, req.body);
11 | console.log("> received user update - " + req.body.email);
12 | }).bind(this));
13 | }
14 | }
15 |
16 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/fetchChannel.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/fetchChannel', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | const data = req.query;
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
12 |
13 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, data.id);
14 | if(channel === undefined) {
15 | res.send(JSON.stringify({ status: -1 }))
16 | } else {
17 | res.send(JSON.stringify(channel))
18 | }
19 | }).bind(this));
20 | }
21 | }
22 |
23 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/fetchChannelMessages.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/fetchChannelMessages', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | const data = req.body;
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
12 |
13 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, data.id);
14 | var messages = await this.app.db.db_fetch.fetchMessages(this.app.db, data.id);
15 | if(channel === undefined) {
16 | res.send(JSON.stringify({ status: -1 }))
17 | } else if(channel.type === 2) {
18 | if(channel.members.includes(user.id) === false) {
19 | res.send(JSON.stringify({ status: -2 }))
20 | } else {
21 | messages = this.filterMessages(messages, data.filters);
22 | res.send(JSON.stringify(messages));
23 | }
24 | } else {
25 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, channel.server.id);
26 | if(server.members.includes(user.id) === false) {
27 | res.send(JSON.stringify({ status: -2 }))
28 | } else {
29 | messages = this.filterMessages(messages, data.filters);
30 | res.send(JSON.stringify(messages));
31 | }
32 | }
33 | }).bind(this));
34 | }
35 |
36 | filterMessages(messages, filters) {
37 | if(filters !== undefined) {
38 | if(filters.term !== undefined) {
39 | messages = messages.filter(m => { return m.text.includes(filters.term); })
40 | }
41 | }
42 |
43 | return messages;
44 | }
45 | }
46 |
47 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/fetchChannels.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/fetchChannels', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | const data = req.query;
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
12 |
13 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, data.id);
14 | var channels = await this.app.db.db_fetch.fetchChannels(this.app.db, data.id);
15 | if(server === undefined) {
16 | res.send(JSON.stringify({ status: -1 }))
17 | } else if(server.members.includes(user.id) === false) {
18 | res.send(JSON.stringify({ status: -2 }))
19 | } else {
20 | res.send(JSON.stringify(channels));
21 | }
22 | }).bind(this));
23 | }
24 | }
25 |
26 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/fetchDMChannels.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/fetchDMChannels', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | const data = req.query;
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
12 |
13 | var channels = [];
14 | for(var i = 0; i < user.dmChannels.length; i++) {
15 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, user.dmChannels[i]);
16 | channels.push(channel);
17 | }
18 | res.send(JSON.stringify(channels));
19 | }).bind(this));
20 | }
21 | }
22 |
23 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/fetchDefaultEmotes.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/fetchDefaultEmotes', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | const data = req.query;
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
12 |
13 | var emotes = await this.app.db.db_fetch.fetchDefaultEmotes(this.app.db, data.id);
14 | if(emotes === undefined) {
15 | res.send(JSON.stringify({ status: -1 }))
16 | } else {
17 | res.send(JSON.stringify(emotes))
18 | }
19 | }).bind(this));
20 | }
21 | }
22 |
23 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/fetchEmote.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/fetchEmote', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | const data = req.query;
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
12 |
13 | var emote = await this.app.db.db_fetch.fetchEmote(this.app.db, data.id);
14 | if(emote === undefined) {
15 | res.send(JSON.stringify({ status: -1 }))
16 | } else {
17 | res.send(JSON.stringify(emote))
18 | }
19 | }).bind(this));
20 | }
21 | }
22 |
23 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/fetchFriendRequest.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/fetchFriendRequest', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | const data = req.query;
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
12 |
13 | var friendRequest = await this.app.db.db_fetch.fetchFriendRequest(this.app.db, data.id);
14 | if(friendRequest === undefined) {
15 | res.send(JSON.stringify({ status: -1 }))
16 | } else if(friendRequest.author.id !== user.id && friendRequest.target.id !== user.id) {
17 | res.send(JSON.stringify({ status: -2 }))
18 | } else {
19 | res.send(JSON.stringify(friendRequest));
20 | }
21 | }).bind(this));
22 | }
23 | }
24 |
25 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/fetchFriendRequests.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/fetchFriendRequests', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | const data = req.query;
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
12 |
13 | var friendRequestsOut = await this.app.db.db_fetch.fetchFriendRequests(this.app.db, user.id, 0);
14 | var friendRequestsIn = await this.app.db.db_fetch.fetchFriendRequests(this.app.db, user.id, 1);
15 | var friendRequests = friendRequestsOut.concat(friendRequestsIn);
16 | res.send(JSON.stringify(friendRequests));
17 | }).bind(this));
18 | }
19 | }
20 |
21 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/fetchInvite.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/fetchInvite', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | const data = req.query;
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
12 |
13 | var invite = await this.app.db.db_fetch.fetchInvite(this.app.db, data.id);
14 | if(invite === undefined) {
15 | res.send(JSON.stringify({ status: -1 }))
16 | } else {
17 | res.send(JSON.stringify(invite))
18 | }
19 | }).bind(this));
20 | }
21 | }
22 |
23 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/fetchNote.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/fetchNote', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | const data = req.query;
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
12 |
13 | var note = await this.app.db.db_fetch.fetchNote(this.app.db, data.id);
14 | if(note === undefined) {
15 | res.send(JSON.stringify({ status: -1 }))
16 | } else if(note.author.id !== user.id) {
17 | res.send(JSON.stringify({ status: -2 }))
18 | } else {
19 | res.send(JSON.stringify(note))
20 | }
21 | }).bind(this));
22 | }
23 | }
24 |
25 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/fetchNotes.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/fetchNotes', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | const data = req.query;
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
12 |
13 | var notes = await this.app.db.db_fetch.fetchNotes(this.app.db, user.id);
14 | res.send(JSON.stringify(notes));
15 | }).bind(this));
16 | }
17 | }
18 |
19 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/fetchServer.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/fetchServer', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | const data = req.query;
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
12 |
13 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, data.id);
14 | if(server === undefined) {
15 | res.send(JSON.stringify({ status: -1 }))
16 | } else {
17 | res.send(JSON.stringify(server))
18 | }
19 | }).bind(this));
20 | }
21 | }
22 |
23 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/fetchServers.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/fetchServers', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | const data = req.query;
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
12 |
13 | var servers = [];
14 | for(var i = 0; i < user.servers.length; i++) {
15 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, user.servers[i]);
16 | servers.push(server);
17 | }
18 | res.send(JSON.stringify(servers));
19 | }).bind(this));
20 | }
21 | }
22 |
23 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/fetchUser.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.get('/fetchUser', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 | const data = req.query;
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, data.id, data.containSensitive && session.userID === data.id);
12 |
13 | if(user === undefined) {
14 | res.send(JSON.stringify({ status: -1 }))
15 | } else {
16 | res.send(JSON.stringify(user))
17 | }
18 | }).bind(this));
19 | }
20 | }
21 |
22 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/joinServer.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/joinServer', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.joinServer(req, res, req.body)
11 | console.log("> added to server - " + req.body.id)
12 | }).bind(this));
13 | }
14 |
15 | async joinServer(req, res, _data) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, _data.id);
19 |
20 | if(server === undefined) {
21 | res.send(JSON.stringify({ status: -1 }))
22 | return;
23 | } else if(server.members.includes(user.id) === true) {
24 | res.send(JSON.stringify({ status: -2 }))
25 | return;
26 | } else {
27 | res.sendStatus(200);
28 | }
29 |
30 | user.servers.push(server.id);
31 | this.app.epFunc.emitToUser(user.id, "createServer", server);
32 | this.app.epFunc.emitToUser(user.id, "updateUser", user);
33 |
34 | server.members.push(user.id);
35 | server.members.forEach(id => {
36 | this.app.epFunc.emitToUser(id, "updateServer", server)
37 | });
38 |
39 | await this.app.db.db_edit.editServer(this.app.db, server);
40 | await this.app.db.db_edit.editUser(this.app.db, user);
41 | if(server.channels.length > 0) { this.app.epFunc.sendSystemMessage({ channel: { id: server.channels[0] }, text: "<@" + user.id + "> joined the server!", type: 3 }) }
42 | }
43 | }
44 |
45 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/joinVoiceChannel.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/joinVoiceChannel', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.joinVoiceChannel(req, res, req.body)
11 | console.log("> received voice connection - " + req.body.channel.id)
12 | }).bind(this));
13 | }
14 |
15 | async joinVoiceChannel(req, res, connection) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, connection.channel.id);
19 | connection.author = { id: user.id }
20 |
21 | if(channel === undefined) {
22 | res.send(JSON.stringify({ status: -1 }))
23 | return;
24 | }
25 |
26 | var voiceGroup = -1;
27 | if(this.app.voiceGroups.has(channel.id) === false) {
28 | //Create Mediasoup Router
29 | const mediaCodecs = [
30 | {
31 | kind : "audio",
32 | mimeType : "audio/opus",
33 | clockRate : 48000,
34 | channels : 2
35 | },
36 | {
37 | kind : "video",
38 | mimeType : "video/H264",
39 | clockRate : 90000,
40 | parameters :
41 | {
42 | "packetization-mode" : 1,
43 | "profile-level-id" : "42e01f",
44 | "level-asymmetry-allowed" : 1
45 | }
46 | }];
47 |
48 | let router = await this.app.mediaWorkers[0].createRouter({ mediaCodecs });
49 | this.app.voiceGroupRouters.set(channel.id, router);
50 | this.app.voiceGroupTransports.set(channel.id, { consumer: new Map(), producer: new Map() })
51 |
52 | //Create Voice Group
53 | voiceGroup = {
54 | id: channel.id,
55 | createdAt: Date.now(),
56 | author: {
57 | id: user.id
58 | },
59 | users: [ user.id ],
60 | rtpCapabilities: router.rtpCapabilities
61 | }
62 |
63 | this.app.voiceGroups.set(channel.id, voiceGroup);
64 | } else {
65 | voiceGroup = this.app.voiceGroups.get(channel.id)
66 | if(voiceGroup.users.includes(user.id) === false) {
67 | voiceGroup.users.push(user.id);
68 | }
69 | }
70 |
71 | res.send(JSON.stringify(voiceGroup));
72 | voiceGroup.users.forEach(id => {
73 | this.app.epFunc.emitToUser(id, "updateVoiceGroup", voiceGroup)
74 | });
75 | }
76 | }
77 |
78 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/kickFromServer.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/kickFromServer', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.kickFromServer(req, res, req.body)
11 | console.log("> kicked from server - " + req.body.server.id + "/" + req.body.user.id)
12 | }).bind(this));
13 | }
14 |
15 | async kickFromServer(req, res, _data) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, _data.server.id);
19 | var targetUser = await this.app.db.db_fetch.fetchUser(this.app.db, _data.user.id);
20 |
21 | if(server === undefined) {
22 | res.send(JSON.stringify({ status: -1 }))
23 | return;
24 | } else if(targetUser === undefined) {
25 | res.send(JSON.stringify({ status: -2 }))
26 | return;
27 | } else if(server.author.id !== user.id) {
28 | res.send(JSON.stringify({ status: -3 }))
29 | return;
30 | } else if(server.members.includes(user.id) === false) {
31 | res.send(JSON.stringify({ status: -4 }))
32 | return;
33 | } else {
34 | res.sendStatus(200);
35 | }
36 |
37 | server.members.splice(server.members.indexOf(targetUser.id), 1);
38 | server.members.forEach(id => {
39 | this.app.epFunc.emitToUser(id, "updateServer", server)
40 | });
41 |
42 | targetUser.servers.splice(targetUser.servers.indexOf(server.id), 1);
43 | this.app.epFunc.emitToUser(targetUser.id, "deleteServer", server);
44 |
45 | await this.app.db.db_edit.editServer(this.app.db, server);
46 | await this.app.db.db_edit.editUser(this.app.db, targetUser);
47 | if(server.channels.length > 0) { this.app.epFunc.sendSystemMessage({ channel: { id: server.channels[0] }, text: "<@" + user.id + "> left the server!", type: 4 }) }
48 | }
49 | }
50 |
51 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/leaveServer.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/leaveServer', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.leaveServer(req, res, req.body)
11 | console.log("> removed from server - " + req.body.id)
12 | }).bind(this));
13 | }
14 |
15 | async leaveServer(req, res, _data) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, _data.id);
19 |
20 | if(server === undefined) {
21 | res.send(JSON.stringify({ status: -1 }))
22 | return;
23 | } else if(server.members.includes(user.id) === false) {
24 | res.send(JSON.stringify({ status: -2 }))
25 | return;
26 | } else {
27 | res.sendStatus(200);
28 | }
29 |
30 | server.members.splice(server.members.indexOf(user.id), 1);
31 | server.members.forEach(id => {
32 | this.app.epFunc.emitToUser(id, "updateServer", server)
33 | });
34 |
35 | user.servers.splice(user.servers.indexOf(server.id), 1);
36 | this.app.epFunc.emitToUser(user.id, "deleteServer", server);
37 |
38 | await this.app.db.db_edit.editServer(this.app.db, server);
39 | await this.app.db.db_edit.editUser(this.app.db, user);
40 | if(server.channels.length > 0) { this.app.epFunc.sendSystemMessage({ channel: { id: server.channels[0] }, text: "<@" + user.id + "> left the server!", type: 4 }) }
41 | }
42 | }
43 |
44 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/leaveVoiceChannel.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/leaveVoiceChannel', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.leaveVoiceChannel(req, res, req.body)
11 | console.log("> received voice disconnection - " + req.body.channel.id)
12 | }).bind(this));
13 | }
14 |
15 | async leaveVoiceChannel(req, res, connection) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, connection.channel.id);
19 |
20 | if(channel === undefined) {
21 | res.send(JSON.stringify({ status: -1 }))
22 | return;
23 | }
24 |
25 | var voiceGroup = -1;
26 | if(this.app.voiceGroups.has(channel.id) === false) {
27 | res.send(JSON.stringify({ status: -2 }))
28 | return;
29 | } else {
30 | voiceGroup = this.app.voiceGroups.get(channel.id)
31 | if(voiceGroup.users.includes(user.id) === false) {
32 | res.send(JSON.stringify({ status: -3 }))
33 | return;
34 | }
35 |
36 | voiceGroup.users = voiceGroup.users.filter(u => { return u.id !== user.id; });
37 | }
38 |
39 | res.sendStatus(200);
40 | voiceGroup.users.forEach(id => {
41 | this.app.epFunc.emitToUser(id, "updateVoiceGroup", voiceGroup)
42 | });
43 | }
44 | }
45 |
46 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/login.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/login', (async(req, res) => {
8 | const data = req.body;
9 | switch(data.authType) {
10 | case "autologin":
11 | if(!this.app.sessions.has(req.cookies["sessionID"])) {
12 | res.send(JSON.stringify({ status: -3 }))
13 | } else {
14 | res.send(JSON.stringify(this.app.sessions.get(req.cookies["sessionID"])));
15 | }
16 | break;
17 |
18 | case "default":
19 | var user = await this.app.db.db_fetch.fetchUserByUsername(this.app.db, data.username, true, true);
20 |
21 | if(user === undefined) {
22 | res.send(JSON.stringify({ status: -2 }))
23 | } else if(this.app.bcrypt.compareSync(data.password, user.password.toString()) == false) {
24 | res.send(JSON.stringify({ status: -1 }))
25 | } else {
26 | const sessionID = this.app.crypto.randomBytes(16).toString("hex");
27 | const session = {
28 | id: sessionID,
29 | userID: user.id
30 | }
31 |
32 | this.app.sessions.set(sessionID, session);
33 | if(this.app.userSessions.has(user.id)) {
34 | this.app.userSessions.get(user.id).push(sessionID);
35 | } else {
36 | this.app.userSessions.set(user.id, [ sessionID ]);
37 | }
38 |
39 | res.cookie("sessionID", session.id, {
40 | sameSite: "None", secure: true
41 | });
42 | res.send(JSON.stringify(session));
43 | }
44 | break;
45 | }
46 | }).bind(this))
47 | }
48 | }
49 |
50 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/logout.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/logout', (async(req, res) => {
8 | res.clearCookie("sessionID");
9 | res.sendStatus(200);
10 | }).bind(this))
11 | }
12 | }
13 |
14 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/message.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/message', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.app.epFunc.sendMessage(req, res, req.body)
11 | console.log("> received message - " + req.body.text)
12 | }).bind(this));
13 | }
14 | }
15 |
16 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/register.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/register', (async(req, res) => {
8 | const data = req.body;
9 | var user = await this.app.db.db_fetch.fetchUserByUsername(this.app.db, data.username);
10 |
11 | if(user !== undefined) {
12 | res.send(JSON.stringify({ status: -1 }))
13 | } else if(data.password !== data.password2) {
14 | res.send(JSON.stringify({ status: -2 }))
15 | } else if(data.username.length < 3) {
16 | res.send(JSON.stringify({ status: -3 }))
17 | } else if(data.password.length < 8) {
18 | res.send(JSON.stringify({ status: -4 }))
19 | } else {
20 | const userID = this.app.crypto.randomBytes(16).toString("hex");
21 | const sessionID = this.app.crypto.randomBytes(16).toString("hex");
22 | const passwordHash = this.app.bcrypt.hashSync(data.password, 10)
23 |
24 | const session = {
25 | id: sessionID,
26 | userID: userID
27 | }
28 |
29 | const user = {
30 | id: userID,
31 | username: data.username,
32 | createdAt: Date.now(),
33 | avatar: "defaultAvatar.png",
34 | password: passwordHash,
35 | friends: [],
36 | dmChannels: [],
37 | servers: [],
38 | badges: [],
39 | emotes: [],
40 | status: 0
41 | }
42 |
43 | await this.app.db.db_add.addUser(this.app.db, user);
44 |
45 | this.app.sessions.set(sessionID, session);
46 | if(this.app.userSessions.has(user.id)) {
47 | this.app.userSessions.get(user.id).push(sessionID);
48 | } else {
49 | this.app.userSessions.set(user.id, [ sessionID ]);
50 | }
51 |
52 | res.cookie("sessionID", session.id, {
53 | sameSite: "None", secure: true
54 | });
55 | res.send(JSON.stringify(session));
56 | }
57 | }).bind(this))
58 | }
59 | }
60 |
61 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/removeConnection.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/removeConnection', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | var session = this.app.sessions.get(req.cookies['sessionID']);
11 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
12 | this.app.db.db_edit.removeUserConnection(this.app.db, user, req.body.type);
13 |
14 | var newUser = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
15 | this.app.epFunc.emitToUser(newUser.id, "updateUser", newUser);
16 | }).bind(this));
17 | }
18 | }
19 |
20 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/removeFriend.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/removeFriend', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.removeFriend(req, res, req.body)
11 | console.log("> removed friend - " + req.body.target.id)
12 | }).bind(this));
13 | }
14 |
15 | async removeFriend(req, res, _removalRequest) {
16 | var socket = this.app.sessionSockets.get(req.cookies['sessionID']);
17 | var session = this.app.sessions.get(req.cookies['sessionID']);
18 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
19 |
20 | if(user.friends.includes(_removalRequest.target.id) === false) {
21 | res.send(JSON.stringify({ status: -1 }))
22 | return;
23 | } else {
24 | res.sendStatus(200);
25 | }
26 |
27 | var targetUser = await this.app.db.db_fetch.fetchUser(this.app.db, _removalRequest.target.id);
28 | user.friends.splice(user.friends.indexOf(targetUser.id), 1);
29 | targetUser.friends.splice(targetUser.friends.indexOf(user.id), 1);
30 |
31 | await this.app.db.db_edit.editUser(this.app.db, user);
32 | await this.app.db.db_edit.editUser(this.app.db, targetUser);
33 |
34 | if(socket.connected) {
35 | socket.emit("updateUser", JSON.stringify(user))
36 | this.app.epFunc.emitToUser(targetUser.id, "updateUser", targetUser);
37 | }
38 | }
39 | }
40 |
41 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/removeFromDMChannel.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/removeFromDMChannel', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.removeFromDMChannel(req, res, req.body)
11 | console.log("> removed from dm channel - " + req.body.channel.id + "/" + req.body.user.id)
12 | }).bind(this));
13 | }
14 |
15 | async removeFromDMChannel(req, res, _data) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, _data.channel.id);
19 | var targetUser = await this.app.db.db_fetch.fetchUser(this.app.db, _data.user.id);
20 |
21 | if(channel === undefined) {
22 | res.send(JSON.stringify({ status: -1 }))
23 | return;
24 | } else if(targetUser === undefined) {
25 | res.send(JSON.stringify({ status: -2 }))
26 | return;
27 | } else if(channel.author.id !== user.id) {
28 | res.send(JSON.stringify({ status: -3 }))
29 | return;
30 | } else if(channel.members.includes(targetUser.id) === false) {
31 | res.send(JSON.stringify({ status: -4 }))
32 | return;
33 | } else {
34 | res.sendStatus(200);
35 | }
36 |
37 | channel.members.splice(channel.members.indexOf(targetUser.id), 1);
38 | channel.members.forEach(id => {
39 | this.app.epFunc.emitToUser(id, "updateChannel", channel)
40 | });
41 |
42 | targetUser.dmChannels.splice(targetUser.dmChannels.indexOf(channel.id), 1);
43 | this.app.epFunc.emitToUser(targetUser.id, "deleteChannel", channel);
44 |
45 | await this.app.db.db_edit.editChannel(this.app.db, channel);
46 | await this.app.db.db_edit.editUser(this.app.db, targetUser);
47 | this.app.epFunc.sendSystemMessage({ channel: { id: channel.id }, text: "<@" + targetUser.id + "> was removed by <@" + user.id + ">", type: 2 })
48 | }
49 | }
50 |
51 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/sendFriendRequest.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/sendFriendRequest', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.sendFriendRequest(req, res, req.body)
11 | console.log("> sent friend request - " + req.body.target.username + " (id: " + req.body.target.id + ")")
12 | }).bind(this));
13 | }
14 |
15 | async sendFriendRequest(req, res, _friendRequest) {
16 | var socket = this.app.sessionSockets.get(req.cookies['sessionID']);
17 | var session = this.app.sessions.get(req.cookies['sessionID']);
18 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
19 |
20 | var targetUser = -1;
21 | if(_friendRequest.target.id !== undefined) {
22 | targetUser = await this.app.db.db_fetch.fetchUser(this.app.db, _friendRequest.target.id);
23 | } else {
24 | targetUser = await this.app.db.db_fetch.fetchUserByUsername(this.app.db, _friendRequest.target.username);
25 | }
26 |
27 | if(targetUser === undefined) {
28 | res.send(JSON.stringify({ status: -2 }))
29 | return;
30 | }
31 |
32 | var friendRequest = await this.app.db.db_fetch.fetchFriendRequestByTarget(this.app.db, targetUser.id);
33 | if(friendRequest !== undefined) {
34 | res.send(JSON.stringify({ status: -1 }))
35 | return;
36 | } else if(user.id === targetUser.id) {
37 | res.send(JSON.stringify({ status: -3 }))
38 | return;
39 | } else {
40 | res.sendStatus(200);
41 | }
42 |
43 | var friendRequest = {
44 | id: this.app.crypto.randomBytes(16).toString("hex"),
45 | author: {
46 | id: user.id
47 | },
48 | target: {
49 | id: targetUser.id
50 | },
51 | createdAt: Date.now()
52 | }
53 |
54 | await this.app.db.db_add.addFriendRequest(this.app.db, friendRequest);
55 |
56 | if(socket.connected) {
57 | var friendRequestsOut = await this.app.db.db_fetch.fetchFriendRequests(this.app.db, user.id, 0);
58 | var friendRequestsIn = await this.app.db.db_fetch.fetchFriendRequests(this.app.db, user.id, 1);
59 | var friendRequests = friendRequestsOut.concat(friendRequestsIn);
60 |
61 | socket.emit("updateFriendRequests", JSON.stringify(friendRequests))
62 |
63 | friendRequestsOut = await this.app.db.db_fetch.fetchFriendRequests(this.app.db, targetUser.id, 0);
64 | friendRequestsIn = await this.app.db.db_fetch.fetchFriendRequests(this.app.db, targetUser.id, 1);
65 | friendRequests = friendRequestsOut.concat(friendRequestsIn);
66 |
67 | this.app.epFunc.emitToUser(targetUser.id, "updateUser", targetUser);
68 | this.app.epFunc.emitToUser(targetUser.id, "updateFriendRequests", friendRequests);
69 | }
70 | }
71 | }
72 |
73 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/updateAvatar.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/updateAvatar', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.updateAvatar(req, res);
11 | console.log("> received avatar update - " + req.query.fileName);
12 | }).bind(this));
13 | }
14 |
15 | async updateAvatar(req, res) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var form = this.app.formidable({ multiples: true });
19 | form.uploadDir = this.app.filesStorage;
20 | form.keepExtensions = true;
21 |
22 | var fileName = req.query.fileName;
23 | var fileID = this.app.crypto.randomBytes(16).toString("hex");
24 | var fileID2 = fileID + (fileName.substring(fileName.lastIndexOf(".")))
25 | console.log("> received avatar - " + fileName)
26 |
27 | form.parse(req, async function(err, fields, files) {
28 | this.app.fs.rename(files.fileUploaded.path, this.app.filesStorage + fileID2, function(err) {
29 | if (err) { throw err; }
30 | });
31 |
32 | user.avatar = fileID2
33 | await this.app.epFunc.updateUser(user, true)
34 | res.sendStatus(200);
35 | }.bind(this));
36 | }
37 | }
38 |
39 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/updateServerAvatar.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/updateServerAvatar', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.updateServerAvatar(req, res, req.query.serverID);
11 | console.log("> received server avatar update - " + req.query.serverID);
12 | }).bind(this));
13 | }
14 |
15 | async updateServerAvatar(req, res, serverID) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var form = this.app.formidable({ multiples: true });
19 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, serverID);
20 |
21 | if(server === undefined) {
22 | res.send(JSON.stringify({ status: -1 }))
23 | return;
24 | } else if (server.author.id !== user.id) {
25 | res.send(JSON.stringify({ status: -2 }))
26 | return;
27 | }
28 |
29 | form.uploadDir = this.app.filesStorage;
30 | form.keepExtensions = true;
31 |
32 | var fileName = req.query.fileName;
33 | var fileID = this.app.crypto.randomBytes(16).toString("hex");
34 | var fileID2 = fileID + (fileName.substring(fileName.lastIndexOf(".")))
35 | console.log("> received avatar - " + fileName)
36 |
37 | form.parse(req, async function(err, fields, files) {
38 | this.app.fs.rename(files.fileUploaded.path, this.app.filesStorage + fileID2, function(err) {
39 | if (err) { throw err; }
40 | });
41 |
42 | server.avatar = fileID2
43 | await this.app.epFunc.updateServer(server, true)
44 | res.sendStatus(200);
45 | }.bind(this));
46 | }
47 | }
48 |
49 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/updateServerBanner.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/updateServerBanner', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.updateServerBanner(req, res, req.query.serverID);
11 | console.log("> received server banner update - " + req.query.serverID);
12 | }).bind(this));
13 | }
14 |
15 | async updateServerBanner(req, res, serverID) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var form = this.app.formidable({ multiples: true });
19 | var server = await this.app.db.db_fetch.fetchServer(this.app.db, serverID);
20 |
21 | if(server === undefined) {
22 | res.send(JSON.stringify({ status: -1 }))
23 | return;
24 | } else if (server.author.id !== user.id) {
25 | res.send(JSON.stringify({ status: -2 }))
26 | return;
27 | }
28 |
29 | form.uploadDir = this.app.filesStorage;
30 | form.keepExtensions = true;
31 |
32 | var fileName = req.query.fileName;
33 | var fileID = this.app.crypto.randomBytes(16).toString("hex");
34 | var fileID2 = fileID + (fileName.substring(fileName.lastIndexOf(".")))
35 | console.log("> received banner - " + fileName)
36 |
37 | form.parse(req, async function(err, fields, files) {
38 | this.app.fs.rename(files.fileUploaded.path, this.app.filesStorage + fileID2, function(err) {
39 | if (err) { throw err; }
40 | });
41 |
42 | server.banner = fileID2
43 | await this.app.epFunc.updateServer(server, true)
44 | res.sendStatus(200);
45 | }.bind(this));
46 | }
47 | }
48 |
49 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/upload.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/upload', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.uploadFile(req, res)
11 | console.log("> received file - " + req.query.fileName)
12 | }).bind(this))
13 | }
14 |
15 | async uploadFile(req, res) {
16 | var socket = this.app.sessionSockets.get(req.cookies['sessionID']);
17 | var form = this.app.formidable({ multiples: true, maxFileSize: 1024 * 1024 * 100 });
18 | form.uploadDir = this.app.filesStorage;
19 | form.keepExtensions = true;
20 |
21 | var fileName = req.query.fileName;
22 | var fileSize = -1;
23 | var sentStartPacket = false;
24 |
25 | var fileID = this.app.crypto.randomBytes(16).toString("hex");
26 | var fileID2 = fileID + (fileName.substring(fileName.lastIndexOf(".")))
27 | console.log("> received file - " + fileName)
28 |
29 | form.on('progress', function(bytesReceived, bytesExpected) {
30 | if(!sentStartPacket) {
31 | sentStartPacket = true;
32 | fileSize = bytesExpected;
33 | socket.emit("uploadStart", fileID, fileName);
34 |
35 | //File size check
36 | if (fileSize >= (1024 * 1024 * 100)) {
37 | form.emit('error', new Error(`File is too big-`));
38 | socket.emit("uploadFail", fileID, fileName, fileSize);
39 | return;
40 | }
41 | }
42 |
43 | //File size check
44 | if (fileSize >= (1024 * 1024 * 100)) {
45 | return false;
46 | } else {
47 | socket.emit("uploadProgress", fileID, fileName, bytesReceived, bytesExpected);
48 | }
49 | }.bind(this));
50 |
51 | form.parse(req, async function(err, fields, files) {
52 | if(files.fileUploaded === undefined) { return; }
53 | this.app.fs.rename(files.fileUploaded.path, this.app.filesStorage + fileID2, function(err) {
54 | if (err) { throw err; }
55 | });
56 |
57 | socket.emit("uploadFinish", fileID, fileName);
58 |
59 | var message = {
60 | text: fields.text,
61 | channel: {
62 | id: fields["channel.id"]
63 | },
64 | file: {
65 | name: fileID2,
66 | size: fileSize
67 | }
68 | }
69 |
70 | await this.app.epFunc.sendMessage(req, res, message)
71 | }.bind(this));
72 | }
73 | }
74 |
75 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/voiceTransports_connect.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/connectVoiceTransports', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.connectVoiceTransports(req, res, req.body)
11 | console.log("> received voice transport connection - " + req.body.channel.id);
12 | }).bind(this));
13 | }
14 |
15 | async connectVoiceTransports(req, res, connection) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, connection.channel.id);
19 |
20 | var transports = this.app.voiceGroupTransports.get(channel.id);
21 | var consumer = transports.consumer.get(user.id);
22 | var producer = transports.producer.get(user.id);
23 | consumer.connect({ dtlsParameters: connection.consumerDTLS });
24 | producer.connect({ dtlsParameters: connection.producerDTLS });
25 |
26 | res.sendStatus(200);
27 | }
28 | }
29 |
30 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/voiceTransports_consume.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/consumeVoiceTransports', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.consumeVoiceTransports(req, res, req.body)
11 | console.log("> received voice transport consume - " + req.body.channel.id);
12 | }).bind(this));
13 | }
14 |
15 | async consumeVoiceTransports(req, res, connection) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, connection.channel.id);
19 |
20 | var transports = this.app.voiceGroupTransports.get(channel.id);
21 | var consumer = transports.consumer.get(user.id);
22 | var a = await consumer.consume({ producerId: connection.producerID, rtpCapabilities: connection.rtpCapabilities });
23 | var b = {
24 | producerID: connection.producerID,
25 | id: a.id,
26 | kind: a.kind,
27 | rtpParameters: a.rtpParameters,
28 | type: a.type,
29 | producerPaused: a.producerPaused
30 | }
31 |
32 | res.send(JSON.stringify(b));
33 | }
34 | }
35 |
36 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/voiceTransports_create.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/createVoiceTransports', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.createVoiceTransports(req, res, req.body)
11 | console.log("> received voice transport creation - " + req.body.channel.id);
12 | }).bind(this));
13 | }
14 |
15 | async createVoiceTransports(req, res, connection) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, connection.channel.id);
19 |
20 | var consumer = await this.app.mediaFunc.createMediaTransport(channel.id);
21 | var producer = await this.app.mediaFunc.createMediaTransport(channel.id);
22 | var transports = this.app.voiceGroupTransports.get(channel.id);
23 | transports.consumer.set(user.id, consumer);
24 | transports.producer.set(user.id, producer);
25 |
26 | res.send(JSON.stringify({
27 | consumerData: {
28 | id: consumer.id,
29 | iceParameters: consumer.iceParameters,
30 | iceCandidates: consumer.iceCandidates,
31 | dtlsParameters: consumer.dtlsParameters
32 | },
33 | producerData: {
34 | id: producer.id,
35 | iceParameters: producer.iceParameters,
36 | iceCandidates: producer.iceCandidates,
37 | dtlsParameters: producer.dtlsParameters
38 | }
39 | }));
40 | }
41 | }
42 |
43 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/endpoints/voiceTransports_produce.js:
--------------------------------------------------------------------------------
1 | class Endpoint {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | handle() {
7 | this.app.post('/produceVoiceTransports', (async(req, res) => {
8 | if(!this.app.isSessionValid(this.app, req, res)) { return; }
9 |
10 | await this.produceVoiceTransports(req, res, req.body)
11 | console.log("> received voice transport produce - " + req.body.channel.id);
12 | }).bind(this));
13 | }
14 |
15 | async produceVoiceTransports(req, res, connection) {
16 | var session = this.app.sessions.get(req.cookies['sessionID']);
17 | var user = await this.app.db.db_fetch.fetchUser(this.app.db, session.userID);
18 | var channel = await this.app.db.db_fetch.fetchChannel(this.app.db, connection.channel.id);
19 | var voiceGroup = this.app.voiceGroups.get(channel.id);
20 |
21 | var transports = this.app.voiceGroupTransports.get(channel.id);
22 | var producer = transports.producer.get(user.id);
23 | var a = await producer.produce({ kind: connection.kind, rtpParameters : connection.rtpParameters });
24 | var b = { channel: { id: channel.id }, id: a.id };
25 |
26 | res.send(JSON.stringify(b));
27 | voiceGroup.users.forEach(id => {
28 | this.app.epFunc.emitToUser(id, "newProducer", b)
29 | });
30 | }
31 | }
32 |
33 | module.exports = Endpoint;
--------------------------------------------------------------------------------
/server/scripts/utils/mediaFunc.js:
--------------------------------------------------------------------------------
1 | class Endpoint2 {
2 | constructor(app) {
3 | this.app = app;
4 | }
5 |
6 | async createMediaWorker() {
7 | var worker = await this.app.mediasoup.createWorker();
8 | worker.on('died', () => {
9 | console.error('[MEDIASOUP] Media worker(pid: ' + worker.pid + ') died!');
10 | });
11 |
12 | this.app.mediaWorkers.push(worker);
13 | return worker;
14 | }
15 |
16 | async createMediaTransport(channelID) {
17 | var router = this.app.voiceGroupRouters.get(channelID);
18 | var transport = await router.createWebRtcTransport({
19 | listenIps: [ { ip: "::", announcedIp: "35.189.74.206" } ]
20 | });
21 |
22 | return transport;
23 | }
24 | }
25 |
26 | module.exports = Endpoint2;
--------------------------------------------------------------------------------
/server/server.js:
--------------------------------------------------------------------------------
1 | //Import modules
2 | const express = require('express');
3 | const app = express();
4 |
5 | //Setup server
6 | const Util = require("./scripts/util")
7 | const util = new Util(app, express)
8 | util.setupApp()
9 | util.setupRoutes()
10 | util.setupSocketServer()
--------------------------------------------------------------------------------