├── .gitattributes
├── .github
├── FUNDING.yml
└── workflows
│ └── docker.yml
├── .gitignore
├── .idea
├── .name
├── dcts.iml
├── modules.xml
├── php.xml
├── vcs.xml
└── workspace.xml
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── badges
├── 170494918551
├── dev.png
├── staff.png
└── verified.png
├── check.sh
├── clear.bat
├── config.example.json
├── docker
└── docker-compose.yml
├── docs
├── Getting started.html
├── Getting started.md
├── assets
│ ├── image-20250201122217494.png
│ └── image-20250201122427341.png
├── network
│ ├── Reverse Proxy Setup.html
│ └── Reverse Proxy Setup.md
├── plugins
│ ├── Plugin System.html
│ └── Plugin System.md
├── sql
│ ├── Configurating SQL.html
│ ├── Configurating SQL.md
│ └── errors
│ │ ├── SQL Tables and Columns not setting up automatically.html
│ │ └── SQL Tables and Columns not setting up automatically.md
└── ssl
│ └── errors
│ ├── Cant access cert files.html
│ └── Cant access cert files.md
├── example-plugin
├── Checkout docs folder
├── functions
│ ├── info.mjs
│ └── plugin_onLoad.mjs
├── sockets
│ └── test.mjs
└── web
│ └── main.js
├── index.mjs
├── modules
├── functions
│ ├── chat
│ │ ├── formatting.mjs
│ │ ├── helper.mjs
│ │ ├── main.mjs
│ │ └── template.mjs
│ ├── http.mjs
│ ├── io.mjs
│ ├── logger.mjs
│ ├── main.mjs
│ └── mysql
│ │ ├── helper.mjs
│ │ └── mysql.mjs
└── sockets
│ ├── 1. template.mjs
│ ├── account
│ ├── setPFP.mjs
│ ├── setStatus.mjs
│ └── setUsername.mjs
│ ├── addRoleToChannel.mjs
│ ├── addRoleToGroup.mjs
│ ├── addUserToRole.mjs
│ ├── banUser.mjs
│ ├── checkChannelPermission.mjs
│ ├── checkMediaUrlCache.mjs
│ ├── checkPermission.mjs
│ ├── createCategory.mjs
│ ├── createChannel.mjs
│ ├── createGroup.mjs
│ ├── createRole.mjs
│ ├── deleteCategory.mjs
│ ├── deleteChannel.mjs
│ ├── deleteEmoji.mjs
│ ├── deleteGroup.mjs
│ ├── deleteMessage.mjs
│ ├── deleteRole.mjs
│ ├── fileUpload.mjs
│ ├── getAllRoles.mjs
│ ├── getBans.mjs
│ ├── getChannelInfo.mjs
│ ├── getChannelTree.mjs
│ ├── getChatlog.mjs
│ ├── getCurrentChannel.mjs
│ ├── getEmojis.mjs
│ ├── getGroupBanner.mjs
│ ├── getGroupChannels.mjs
│ ├── getGroupInfo.mjs
│ ├── getGroupList.mjs
│ ├── getGroupStats.mjs
│ ├── getMemberList.mjs
│ ├── getMemberProfile.mjs
│ ├── getPluginList.mjs
│ ├── getServerInfo.mjs
│ ├── getServerRoles.mjs
│ ├── getUserFromId.mjs
│ ├── isTyping.mjs
│ ├── kickUser.mjs
│ ├── messageSend.mjs
│ ├── muteUser.mjs
│ ├── pow.mjs
│ ├── redeemKey.mjs
│ ├── removeRoleFromChannel.mjs
│ ├── removeRoleFromGroup.mjs
│ ├── removeUserFromRole.mjs
│ ├── reports
│ ├── createReport.mjs
│ ├── deleteMessageInReport.mjs
│ ├── deleteReport.mjs
│ └── fetchReports.mjs
│ ├── resolveMember.mjs
│ ├── saveChannelPermissions.mjs
│ ├── saveMediaSettings.mjs
│ ├── saveRateSettings.mjs
│ ├── saveRolePermissions.mjs
│ ├── searchTenorGif.mjs
│ ├── setDefaultChannel.mjs
│ ├── setRoom.mjs
│ ├── stoppedTyping.mjs
│ ├── unbanUser.mjs
│ ├── unmuteUser.mjs
│ ├── updateChannelHierarchy.mjs
│ ├── updateChannelName.mjs
│ ├── updateChannelTreeSorting.mjs
│ ├── updateEmoji.mjs
│ ├── updateGroupBanner.mjs
│ ├── updateGroupIcon.mjs
│ ├── updateGroupName.mjs
│ ├── updateGroupPermissions.mjs
│ ├── updateRoleAppearance.mjs
│ ├── updateRoleHierarchy.mjs
│ ├── updateServerDesc.mjs
│ ├── updateServerName.mjs
│ ├── userConnected.mjs
│ ├── userLogin.mjs
│ └── voip.mjs
├── package-lock.json
├── package.json
├── public
├── .idea
│ ├── .name
│ ├── modules.xml
│ ├── public.iml
│ ├── vcs.xml
│ └── workspace.xml
├── audioplayer
│ ├── audioplayer.css
│ └── audioplayer.js
├── chat.js
├── css
│ ├── channeltree.css
│ ├── emoji-autocomplete.css
│ ├── groups
│ │ └── groupHomeDisplay.css
│ └── themes
│ │ └── default.css
├── emojis
│ ├── emoji_109468018712_confusedlol.webp
│ ├── emoji_123503693162_nice.png
│ ├── emoji_140051899224_chuchu.jpg
│ ├── emoji_152067959921_stare.jpg
│ └── emoji_171207581436_catto.gif
├── highlight.css
├── img
│ ├── back.png
│ ├── broken.jpg
│ ├── default_banner.png
│ ├── default_icon.png
│ ├── default_pfp.png
│ ├── delete.png
│ ├── down.png
│ ├── emoji.png
│ ├── error.png
│ ├── error_banner.png
│ ├── hashtag.png
│ ├── info.png
│ ├── loading.gif
│ ├── sandwich.png
│ ├── save.png
│ ├── settings.png
│ ├── success.png
│ └── up.png
├── index.html
├── js
│ ├── alerts.js
│ ├── core
│ │ ├── AdminActions.js
│ │ ├── Channeltree.js
│ │ ├── ChatManager.js
│ │ ├── ContextMenu.js
│ │ ├── CookieManager.js
│ │ ├── ModActions.js
│ │ ├── ModView.js
│ │ ├── UserManager.js
│ │ ├── UserReports.js
│ │ └── template.js
│ ├── emojis.js
│ ├── hover.js
│ ├── prompts.js
│ ├── sysmsg.js
│ ├── tooltips.js
│ ├── tooltips
│ │ └── dialogs
│ │ │ ├── accountOnboarding.js
│ │ │ ├── banUser.js
│ │ │ ├── createChannel.js
│ │ │ └── muteUser.js
│ └── upload.js
├── notify.js
├── plugins
│ └── loader.js
├── settings
│ ├── account
│ │ ├── index.html
│ │ ├── page
│ │ │ └── profile
│ │ │ │ ├── profile.css
│ │ │ │ ├── profile.html
│ │ │ │ └── profile.js
│ │ └── settings.js
│ ├── channel
│ │ ├── index.html
│ │ ├── page
│ │ │ ├── channel-info
│ │ │ │ ├── channel-info.css
│ │ │ │ ├── channel-info.html
│ │ │ │ └── channel-info.js
│ │ │ └── channel-permissions
│ │ │ │ ├── channel-permissions.css
│ │ │ │ ├── channel-permissions.html
│ │ │ │ └── channel-permissions.js
│ │ └── settings.js
│ ├── group
│ │ ├── index.html
│ │ ├── page
│ │ │ ├── group-info
│ │ │ │ ├── group-info.css
│ │ │ │ ├── group-info.html
│ │ │ │ └── group-info.js
│ │ │ └── group-permissions
│ │ │ │ ├── group-permissions.css
│ │ │ │ ├── group-permissions.html
│ │ │ │ └── group-permissions.js
│ │ └── settings.js
│ └── server
│ │ ├── index.html
│ │ ├── page
│ │ ├── about
│ │ │ ├── about.css
│ │ │ ├── about.html
│ │ │ └── about.js
│ │ ├── banlist
│ │ │ ├── banlist.css
│ │ │ ├── banlist.html
│ │ │ └── banlist.js
│ │ ├── channeltree-sorting
│ │ │ ├── channeltree-sorting.css
│ │ │ ├── channeltree-sorting.html
│ │ │ └── channeltree-sorting.js
│ │ ├── easter
│ │ │ ├── easter.css
│ │ │ ├── easter.html
│ │ │ └── easter.js
│ │ ├── emojis
│ │ │ ├── emojis.css
│ │ │ ├── emojis.html
│ │ │ └── emojis.js
│ │ ├── file-uploads
│ │ │ ├── file-uploads.css
│ │ │ ├── file-uploads.html
│ │ │ └── file-uploads.js
│ │ ├── planned-features
│ │ │ ├── planned-features.css
│ │ │ ├── planned-features.html
│ │ │ └── planned-features.js
│ │ ├── rate-limit
│ │ │ ├── rate-limit.css
│ │ │ ├── rate-limit.html
│ │ │ └── rate-limit.js
│ │ ├── roles
│ │ │ ├── roles.css
│ │ │ ├── roles.html
│ │ │ └── roles.js
│ │ ├── server-info
│ │ │ ├── server-info.css
│ │ │ ├── server-info.html
│ │ │ └── server-info.js
│ │ ├── support
│ │ │ ├── support.css
│ │ │ ├── support.html
│ │ │ └── support.js
│ │ └── whats-new
│ │ │ ├── whats-new.css
│ │ │ ├── whats-new.html
│ │ │ └── whats-new.js
│ │ └── settings.js
├── sounds
│ ├── message.mp3
│ └── normal.mp3
├── style.css
└── webrtc
│ └── rtc.js
├── settings
├── account
│ ├── index.html
│ ├── page
│ │ └── profile
│ │ │ ├── profile.css
│ │ │ ├── profile.html
│ │ │ └── profile.js
│ └── settings.js
├── channel
│ ├── index.html
│ ├── page
│ │ ├── channel-info
│ │ │ ├── channel-info.css
│ │ │ ├── channel-info.html
│ │ │ └── channel-info.js
│ │ └── channel-permissions
│ │ │ ├── channel-permissions.css
│ │ │ ├── channel-permissions.html
│ │ │ └── channel-permissions.js
│ └── settings.js
├── group
│ ├── index.html
│ ├── page
│ │ ├── group-info
│ │ │ ├── group-info.css
│ │ │ ├── group-info.html
│ │ │ └── group-info.js
│ │ └── group-permissions
│ │ │ ├── group-permissions.css
│ │ │ ├── group-permissions.html
│ │ │ └── group-permissions.js
│ └── settings.js
└── server
│ ├── index.html
│ ├── page
│ ├── about
│ │ ├── about.css
│ │ ├── about.html
│ │ └── about.js
│ ├── banlist
│ │ ├── banlist.css
│ │ ├── banlist.html
│ │ └── banlist.js
│ ├── channeltree-sorting
│ │ ├── channeltree-sorting.css
│ │ ├── channeltree-sorting.html
│ │ └── channeltree-sorting.js
│ ├── easter.html
│ ├── emojis
│ │ ├── emojis.css
│ │ ├── emojis.html
│ │ └── emojis.js
│ ├── file-uploads
│ │ ├── file-uploads.css
│ │ ├── file-uploads.html
│ │ └── file-uploads.js
│ ├── planned-features
│ │ ├── planned-features.css
│ │ ├── planned-features.html
│ │ └── planned-features.js
│ ├── rate-limit
│ │ ├── rate-limit.css
│ │ ├── rate-limit.html
│ │ └── rate-limit.js
│ ├── roles
│ │ ├── roles.css
│ │ ├── roles.html
│ │ └── roles.js
│ ├── server-info
│ │ ├── server-info.css
│ │ ├── server-info.html
│ │ └── server-info.js
│ ├── support
│ │ ├── support.css
│ │ ├── support.html
│ │ └── support.js
│ └── whats-new
│ │ ├── whats-new.css
│ │ ├── whats-new.html
│ │ └── whats-new.js
│ └── settings.js
├── sounds
├── message.mp3
└── normal.mp3
├── start.sh
├── supervisor.conf.example
├── update.sh
└── version
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: #shydevil
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: shydevil
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
14 |
--------------------------------------------------------------------------------
/.github/workflows/docker.yml:
--------------------------------------------------------------------------------
1 | name: Docker Image CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - name: Checkout repository
14 | uses: actions/checkout@v3
15 |
16 | - name: Set up Docker Buildx
17 | uses: docker/setup-buildx-action@v3
18 |
19 | - name: Cache Docker layers
20 | uses: actions/cache@v3
21 | with:
22 | path: /tmp/.buildx-cache
23 | key: ${{ runner.os }}-buildx-${{ github.sha }}
24 | restore-keys: |
25 | ${{ runner.os }}-buildx-
26 |
27 | - name: Log in to GitHub Container Registry
28 | uses: docker/login-action@v3
29 | with:
30 | registry: ghcr.io
31 | username: ${{ github.actor }}
32 | password: ${{ secrets.GITHUB_TOKEN }}
33 |
34 | - name: Build and push Docker image
35 | uses: docker/build-push-action@v3
36 | with:
37 | context: .
38 | push: true
39 | tags: ghcr.io/${{ github.repository }}:latest
40 |
41 | - name: Build Docker image
42 | run: docker build -t ghcr.io/${{ github.repository }}:latest .
43 |
44 | - name: Push Docker image
45 | run: docker push ghcr.io/${{ github.repository }}:latest
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /logs
2 | /node_modules
3 | /config_backups
4 | /chats
5 | config.json
6 | /public/uploads/
7 | /plugins
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | config.json
--------------------------------------------------------------------------------
/.idea/dcts.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/php.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:21-alpine
2 |
3 | RUN mkdir -p /app
4 | WORKDIR /app
5 |
6 | COPY package.json package-lock.json ./
7 |
8 | RUN npm install
9 |
10 | COPY . .
11 |
12 | EXPOSE 2052
13 |
14 | CMD ["node", "."]
15 |
--------------------------------------------------------------------------------
/badges/170494918551:
--------------------------------------------------------------------------------
1 | {
2 | "platform_developer": {
3 | "display": "Platform Developer",
4 | "icon": "dev"
5 | },
6 | "platform_staff": {
7 | "display": "Staff",
8 | "icon": "staff"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/badges/dev.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/badges/dev.png
--------------------------------------------------------------------------------
/badges/staff.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/badges/staff.png
--------------------------------------------------------------------------------
/badges/verified.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/badges/verified.png
--------------------------------------------------------------------------------
/check.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #echo "Starting DCTS Check Script"
3 |
4 | sleep 4
5 | if ! screen -list | grep -q "dcts"; then
6 | echo "is not running"
7 | sh /home/dcts/start.sh
8 | fi
--------------------------------------------------------------------------------
/clear.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | rmdir chats /S /Q
4 | rmdir logs /S /Q
5 | rmdir config_backups /S /Q
6 | rmdir node_modules /S /Q
7 |
8 | del config.json
9 | copy config.example.json config.json
10 |
--------------------------------------------------------------------------------
/docker/docker-compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 | dcts:
3 | image: ghcr.io/hackthedev/dcts-shipping
4 | restart: always
5 | volumes:
6 | - dcts:/app/dcts # Named volume
7 | - uploads:/app/public/uploads # Named volume
8 | - ./config.json:/app/config.json # Bind mount
9 | - ./chats:/app/chats # Bind mount
10 | - ./logs:/app/logs # Bind mount
11 | ports:
12 | - '8080:2052' # Port mapping
13 |
14 | volumes:
15 | dcts: # Named volume
16 | uploads: # Named volume
17 |
--------------------------------------------------------------------------------
/docs/assets/image-20250201122217494.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/docs/assets/image-20250201122217494.png
--------------------------------------------------------------------------------
/docs/assets/image-20250201122427341.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/docs/assets/image-20250201122427341.png
--------------------------------------------------------------------------------
/docs/network/Reverse Proxy Setup.md:
--------------------------------------------------------------------------------
1 | # Reverse Proxy Setup
2 |
3 | This document will explain how to use the chat software and setup a reverse proxy. This will result in the url being https://your-domain.com/app instead of https://your-domain.com:2086/ [^portnote] .
4 |
5 | ------
6 |
7 | ## nginx Setup
8 |
9 | The following configuration is a example on how you can use the chat app using the reverse proxy. It will change the address from https://you-domain.com:2086 to https://your-domain.com/app
10 |
11 | ```nginx
12 | location /app/ {
13 | proxy_pass http://127.0.0.1:2086/;
14 | proxy_set_header Host $host;
15 | }
16 |
17 | location /socket.io/ {
18 | proxy_pass http://127.0.0.1:2086/socket.io/;
19 | proxy_set_header Host $host;
20 | }
21 | ```
22 |
23 | ------
24 |
25 | ## apache Setup
26 |
27 | You can also use apache instead of nginx. You will likely need to enable specific modules.
28 |
29 | ```bash
30 | sudo a2enmod proxy proxy_http proxy_wstunnel
31 | sudo systemctl restart apache2
32 | ```
33 |
34 | This is a untested apache configuration and a example on how to setup the reverse proxy:
35 |
36 | ```xml
37 |
38 | ServerName dcts.chat
39 | DocumentRoot /var/www/html
40 |
41 | # Proxy for /app/
42 | ProxyPreserveHost On
43 | ProxyPass /app/ http://127.0.0.1:2086/
44 | ProxyPassReverse /app/ http://127.0.0.1:2086/
45 |
46 | # Proxy for /socket.io/
47 | ProxyPass /socket.io/ http://127.0.0.1:2086/socket.io/
48 | ProxyPassReverse /socket.io/ http://127.0.0.1:2086/socket.io/
49 |
50 | # Handle WebSocket Upgrade
51 |
52 | ProxyPreserveHost On
53 | ProxyPass ws://127.0.0.1:2086/socket.io/
54 | ProxyPassReverse ws://127.0.0.1:2086/socket.io/
55 |
56 |
57 | ErrorLog ${APACHE_LOG_DIR}/error.log
58 | CustomLog ${APACHE_LOG_DIR}/access.log combined
59 |
60 | ```
61 |
62 | > [!NOTE]
63 | >
64 | > The apache setup was not tested yet and is only a rough example on how it could work.
65 |
66 | > [!IMPORTANT]
67 | >
68 | > Its important to change the socket.io path as well because otherwise the client will run into 404 errors trying to find the socket.io endpoint. Both for nginx and apache!
69 |
70 | > [!CAUTION]
71 | >
72 | > Currently there is issue where the nginx proxy would work but its unable to properly serve images. Until a fix is found its not recommended to use this. If you know what you're doing and find a fix yourself feel free to share it [on the subreddit](https://www.reddit.com/r/dcts/) or [create a issue on github](https://github.com/hackthedev/dcts-shipping/).
73 |
74 | [^portnote]: The port configured inside of your config.json file
75 |
76 |
--------------------------------------------------------------------------------
/docs/sql/errors/SQL Tables and Columns not setting up automatically.md:
--------------------------------------------------------------------------------
1 | # SQL Tables and Columns not setting up automatically
2 |
3 | This document explains common errors when the application tries to automatically setup SQL tables and columns.
4 |
5 | ------
6 |
7 | ## Error: Table 'dcts.messages' doesn't exist in engine
8 |
9 | This error can occur when you launch the application and it tries to access the tables without them existing. Its possible that it creates a log in mysql, making the statement below return 1 despite the tables not existing.
10 |
11 | To fix this issue make sure the database exists and restart the mysql service. This will get rid of the log entry, making the statement below work and properly generate the tables and columns.
12 |
13 | ```sql
14 | SELECT COUNT(*)
15 | FROM information_schema.tables
16 | WHERE table_schema = "dcts"
17 | AND table_name = "messages"
18 | ```
19 |
20 |
--------------------------------------------------------------------------------
/example-plugin/Checkout docs folder:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/example-plugin/Checkout docs folder
--------------------------------------------------------------------------------
/example-plugin/functions/info.mjs:
--------------------------------------------------------------------------------
1 | export let pluginInfo = {
2 | author: "HackTheDev",
3 | version: "1.0",
4 | license: "none"
5 | }
--------------------------------------------------------------------------------
/example-plugin/functions/plugin_onLoad.mjs:
--------------------------------------------------------------------------------
1 | // Example Imports
2 | import Logger from "../../../modules/functions/logger.mjs";
3 | import { pluginInfo } from "./info.mjs" // your custom file
4 |
5 | // Example Code
6 | Logger.info("Content")
7 | Logger.success("Content");
8 | Logger.error("Content")
9 |
10 | export function exampleAdd(a, b){
11 | return a + b;
12 | }
13 |
--------------------------------------------------------------------------------
/example-plugin/sockets/test.mjs:
--------------------------------------------------------------------------------
1 | import { validateMemberId } from "../../../modules/functions/main.mjs";
2 | import { serverconfig } from "../../../index.mjs";
3 |
4 | export default (socket) => {
5 |
6 | socket.on('test', (member, response) => {
7 | if (
8 | validateMemberId(member.id, socket) === true &&
9 | serverconfig.servermembers[member.id].token === member.token
10 | ) {
11 | response({ type: 'success', message: "Worked!" });
12 |
13 | } else {
14 | response({ type: 'error', message: 'Invalid member or token' });
15 | }
16 | });
17 |
18 | };
--------------------------------------------------------------------------------
/example-plugin/web/main.js:
--------------------------------------------------------------------------------
1 | // Example Code
2 | // The main.js file is your entry point (client-side). and will run automatically
3 |
4 | let channels = document.querySelectorAll("#channeltree a");
5 |
6 | channels.forEach(channel => {
7 | console.log(channel)
8 | channel.style.color = "red";
9 | });
10 |
--------------------------------------------------------------------------------
/modules/functions/chat/template.mjs:
--------------------------------------------------------------------------------
1 | /*
2 | Just a copy/paste file template.
3 | */
4 | import {serverconfig, fetch} from "../../index.mjs"
5 |
--------------------------------------------------------------------------------
/modules/functions/http.mjs:
--------------------------------------------------------------------------------
1 | import {server, serverconfig, http, https, app, setServer, fs} from "../../index.mjs";
2 | import Logger from "./logger.mjs";
3 |
4 | var serverconfigEditable = serverconfig;
5 |
6 | export function checkSSL(){
7 | if(serverconfig.serverinfo.ssl.enabled == 1){
8 |
9 | setServer(https.createServer({
10 | key: fs.readFileSync(serverconfig.serverinfo.ssl.key),
11 | cert: fs.readFileSync(serverconfig.serverinfo.ssl.cert),
12 | ca: fs.readFileSync(serverconfig.serverinfo.ssl.chain),
13 |
14 | requestCert: false,
15 | rejectUnauthorized: false },app));
16 |
17 | Logger.success("Running Server in public (production) mode with SSL.");
18 | }
19 | else{
20 | Logger.warn("Running Server in localhost (testing) mode.");
21 | Logger.warn("If accessed via the internet, SSL wont work and will cause problems");
22 |
23 | setServer(http.createServer(app))
24 | }
25 | }
--------------------------------------------------------------------------------
/modules/functions/logger.mjs:
--------------------------------------------------------------------------------
1 | class Logger {
2 | static colors = {
3 | reset: "\x1b[0m",
4 | bright: "\x1b[1m",
5 | dim: "\x1b[2m",
6 | underscore: "\x1b[4m",
7 | blink: "\x1b[5m",
8 | reverse: "\x1b[7m",
9 | hidden: "\x1b[8m",
10 |
11 | fgBlack: "\x1b[30m",
12 | fgRed: "\x1b[31m",
13 | fgGreen: "\x1b[32m",
14 | fgYellow: "\x1b[33m",
15 | fgBlue: "\x1b[34m",
16 | fgMagenta: "\x1b[35m",
17 | fgCyan: "\x1b[36m",
18 | fgWhite: "\x1b[37m",
19 | fgGray: "\x1b[90m",
20 |
21 | bgBlack: "\x1b[40m",
22 | bgRed: "\x1b[41m",
23 | bgGreen: "\x1b[42m",
24 | bgYellow: "\x1b[43m",
25 | bgBlue: "\x1b[44m",
26 | bgMagenta: "\x1b[45m",
27 | bgCyan: "\x1b[46m",
28 | bgWhite: "\x1b[47m"
29 | };
30 |
31 | static log(level, message, color) {
32 | if (message instanceof Error) {
33 | console.log(`${color}${Logger.displayDate()}[${level}] ${message.message}\n${message.stack}${Logger.colors.reset}`);
34 | } else if (typeof message === 'object') {
35 | console.log(`${color}${Logger.displayDate()}[${level}] ${JSON.stringify(message, null, 2)}${Logger.colors.reset}`);
36 | } else {
37 | console.log(`${color}${Logger.displayDate()}[${level}] ${message}${Logger.colors.reset}`);
38 | }
39 | }
40 |
41 | static info(message, color = "") {
42 | Logger.log("INFO", message, color ? color + Logger.colors.fgCyan : Logger.colors.fgCyan);
43 | }
44 |
45 | static success(message, color = "") {
46 | Logger.log("SUCCESS", message, color ? color + Logger.colors.fgGreen : Logger.colors.fgGreen);
47 | }
48 |
49 | static warn(message, color = "") {
50 | Logger.log("WARN", message, color ? color + Logger.colors.fgYellow : Logger.colors.fgYellow);
51 | }
52 |
53 | static error(message, color = "") {
54 | Logger.log("ERROR", message, color ? color + Logger.colors.fgRed : Logger.colors.fgRed);
55 | }
56 |
57 | static debug(message, color = "") {
58 | Logger.log("DEBUG", message, color ? color + Logger.colors.bright + Logger.colors.fgBlack : Logger.colors.bright + Logger.colors.fgBlack);
59 | }
60 |
61 | static displayDate() {
62 | const today = new Date();
63 | const date = today.getFullYear() + '-' + (today.getMonth() + 1).toString().padStart(2, '0') + '-' + today.getDate().toString().padStart(2, '0');
64 | const time = today.getHours().toString().padStart(2, '0') + ":" + today.getMinutes().toString().padStart(2, '0') + ":" + today.getSeconds().toString().padStart(2, '0');
65 | return `[${date} ${time}] `;
66 | }
67 | }
68 |
69 | export default Logger;
70 |
--------------------------------------------------------------------------------
/modules/sockets/1. template.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | }
9 |
--------------------------------------------------------------------------------
/modules/sockets/account/setPFP.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig } from "../../../index.mjs";
2 | import { validateMemberId } from "../../functions/main.mjs";
3 |
4 | export default (socket) => {
5 | // socket.on code here
6 | socket.on('setPFP', function (member) {
7 | if (validateMemberId(member.id, socket) == true
8 | && serverconfig.servermembers[member.id].token == member.token) {
9 |
10 | serverconfig.servermembers[member.id].icon = member.icon;
11 | saveConfig(serverconfig);
12 |
13 | io.emit("updateMemberList",);
14 | }
15 | });
16 | }
17 |
--------------------------------------------------------------------------------
/modules/sockets/account/setStatus.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../../index.mjs";
2 | import { hasPermission } from "../../functions/chat/main.mjs";
3 | import Logger from "../../functions/logger.mjs";
4 | import { copyObject, escapeHtml, limitString, sendMessageToUser, validateMemberId } from "../../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('setStatus', function (member) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token) {
11 |
12 | serverconfig.servermembers[member.id].status = escapeHtml(limitString(member.status, 100));
13 | saveConfig(serverconfig);
14 |
15 | io.emit("updateMemberList");
16 | }
17 | });
18 | }
19 |
--------------------------------------------------------------------------------
/modules/sockets/account/setUsername.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../../index.mjs";
2 | import { copyObject, escapeHtml, limitString, sendMessageToUser, validateMemberId } from "../../functions/main.mjs";
3 |
4 | export default (socket) => {
5 | // socket.on code here
6 | socket.on('setUsername', function (member) {
7 | if (validateMemberId(member.id, socket) == true
8 | && serverconfig.servermembers[member.id].token == member.token) {
9 |
10 | serverconfig.servermembers[member.id].name = escapeHtml(limitString(member.username, 30));
11 | saveConfig(serverconfig);
12 | io.emit("updateMemberList");
13 | }
14 | });
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/modules/sockets/addRoleToChannel.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission, resolveCategoryByChannelId, resolveGroupByChannelId } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('addRoleToChannel', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | if (hasPermission(member.id, "manageChannels")) {
14 | try {
15 |
16 | var memberChannel = member.channel.replace("channel-", "");
17 |
18 | var group = resolveGroupByChannelId(memberChannel);
19 | var category = resolveCategoryByChannelId(memberChannel);
20 |
21 | serverconfig.groups[group].channels.categories[category].channel[memberChannel].permissions[member.role] = JSON.parse
22 | (
23 | `
24 | {
25 | "readMessages": 1,
26 | "sendMessages": 1
27 | }
28 | `
29 | );
30 | saveConfig(serverconfig);
31 |
32 | response({ type: "success", msg: "Role was successfully removed from the channel" });
33 | }
34 | catch (e) {
35 | Logger.error("Unable to add role to channel");
36 | Logger.error(e);
37 | }
38 | }
39 | else {
40 | response({ type: "error", msg: "denied" });
41 | }
42 | }
43 | });
44 | }
45 |
--------------------------------------------------------------------------------
/modules/sockets/addRoleToGroup.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('addRoleToGroup', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | if (hasPermission(member.id, "manageGroups")) {
14 | try {
15 | serverconfig.groups[member.group].permissions[member.role] = JSON.parse(
16 | `
17 | {
18 | "viewGroup": 1
19 | }
20 | `
21 | )
22 | saveConfig(serverconfig);
23 | response({ type: "success", msg: "Role was successfully added to the group" });
24 | }
25 | catch (e) {
26 | Logger.error("Unable to add role to group");
27 | Logger.error(e);
28 | }
29 | }
30 | else {
31 | response({ type: "error", msg: "denied" });
32 | }
33 | }
34 | });
35 | }
36 |
--------------------------------------------------------------------------------
/modules/sockets/checkChannelPermission.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, getCastingMemberObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('checkChannelPermission', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true) {
10 |
11 | member.id = xssFilters.inHTMLData(member.id);
12 | member.token = xssFilters.inHTMLData(member.token);
13 | member.permission = xssFilters.inHTMLData(member.permission);
14 | member.channel = xssFilters.inHTMLData(member.channel);
15 |
16 | var userObj = getCastingMemberObject(serverconfig.servermembers[member.id]);
17 |
18 | if (Array.isArray(member.permission)) {
19 |
20 | for (var i = 0; i < member.permission.length; i++) {
21 | if (hasPermission(member.id, member.permission[i], member.channel)) {
22 | response({ type: "success", permission: "granted", user: userObj });
23 | return;
24 | }
25 | }
26 |
27 | response({ type: "success", permission: "denied", user: userObj });
28 | }
29 | else { // Single permission check
30 |
31 | if (hasPermission(member.id, member.permission, member.channel)) {
32 | response({ type: "success", permission: "granted", user: userObj });
33 | } else {
34 | response({ type: "success", permission: "denied", user: userObj });
35 | }
36 | }
37 | }
38 | });
39 | }
40 |
--------------------------------------------------------------------------------
/modules/sockets/checkPermission.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, getCastingMemberObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('checkPermission', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true) {
10 |
11 | var userObj = getCastingMemberObject(serverconfig.servermembers[member.id]);
12 |
13 | if (Array.isArray(member.permission)) {
14 |
15 | for (var i = 0; i < member.permission.length; i++) {
16 |
17 | if (hasPermission(member.id, member.permission[i])) {
18 | response({ permission: "granted", user: userObj });
19 | return;
20 | }
21 | }
22 |
23 | response({ permission: "denied", user: userObj });
24 | }
25 | else { // Single permission check
26 |
27 | if (hasPermission(member.id, member.permission)) {
28 | response({ permission: "granted", user: userObj });
29 | } else {
30 | response({ permission: "denied", user: userObj });
31 | }
32 | }
33 | }
34 | });
35 | }
36 |
--------------------------------------------------------------------------------
/modules/sockets/createCategory.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { getChannelTree, hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, escapeHtml, generateId, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 |
9 | socket.on('createCategory', function (member, response) {
10 | if (validateMemberId(member.id, socket) == true &&
11 | serverconfig.servermembers[member.id].token == member.token
12 | ) {
13 |
14 | member.id = xssFilters.inHTMLData(member.id)
15 | member.token = xssFilters.inHTMLData(member.token)
16 | member.group = xssFilters.inHTMLData(member.group)
17 | member.value = xssFilters.inHTMLData(member.value)
18 |
19 | if (!hasPermission(member.id, "manageChannels")) {
20 | response({ error: "Missing permissions: manageChannels", msg: "Cant create category because you dont have the permissions to manage channels", type: "error" })
21 | return;
22 | }
23 |
24 | if (!member.group) {
25 | response({ error: "Missing parameter: group", msg: "No group specified", type: "error" })
26 | }
27 |
28 | try {
29 | var catId = generateId(4);
30 | serverconfig.groups[member.group].channels.categories[catId] = JSON.parse(
31 | `{
32 | "info": {
33 | "id": ${catId},
34 | "name": "${escapeHtml(member.value)}",
35 | "sortId": 0
36 | },
37 | "channel": {
38 | }
39 | }
40 | `);
41 | saveConfig(serverconfig);
42 | response({ error: null, msg: "Category created!", type: "success" })
43 |
44 | io.emit("receiveChannelTree", getChannelTree(member));
45 | }
46 | catch (e) {
47 | Logger.error("Couldnt create category");
48 | Logger.error(e);
49 | }
50 |
51 | }
52 | else {
53 | Logger.debug("Invalid token?")
54 | }
55 | });
56 | }
57 |
--------------------------------------------------------------------------------
/modules/sockets/createChannel.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { getChannelTree, hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, escapeHtml, generateId, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('createChannel', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | if (!hasPermission(member.id, "manageChannels")) {
14 | response({ msg: "You are not allowed to create a channel", type: "error", error: "Missing permissions to create channel" })
15 | return;
16 | }
17 |
18 | try {
19 | var channelId = generateId(4);
20 | serverconfig.groups[member.group].channels.categories[member.category].channel[channelId] = JSON.parse(
21 | `{
22 | "id": ${channelId},
23 | "name": "${xssFilters.inHTMLData(escapeHtml(member.value))}",
24 | "type": "${member.type}",
25 | "description": "Default Channel Description",
26 | "sortId": 0,
27 | "permissions": {
28 | "0": {
29 | "viewChannelHistory": 1,
30 | "readMessages": 1,
31 | "sendMessages": 1,
32 | "viewChannel": 0
33 | }
34 | }
35 | }
36 | `);
37 |
38 | saveConfig(serverconfig);
39 | io.emit("receiveChannelTree", getChannelTree(member));
40 | response({ msg: "Channel created successfully", type: "success" })
41 | }
42 | catch (e) {
43 | Logger.error("Couldnt create channel");
44 | Logger.error(e);
45 | }
46 | }
47 | });
48 | }
49 |
--------------------------------------------------------------------------------
/modules/sockets/createRole.mjs:
--------------------------------------------------------------------------------
1 | import { saveConfig, serverconfig } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { generateId, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('createRole', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | if (hasPermission(member.id, "manageRoles")) {
14 | try {
15 | var roleid = generateId(4);
16 |
17 | serverconfig.serverroles[roleid] = JSON.parse(
18 | `{
19 | "info": {
20 | "id": ${roleid},
21 | "name": "New Role",
22 | "icon": null,
23 | "color": "#FFFFFF",
24 | "deletable": 1,
25 | "sortId": ${generateId(4)},
26 | "displaySeperate": 0
27 | },
28 | "permissions": {
29 | "readMessages": 1,
30 | "sendMessages": 1,
31 | "uploadFiles": 1
32 | },
33 | "members": [
34 | ],
35 | "token": []
36 | }`
37 | );
38 |
39 | saveConfig(serverconfig);
40 | response({ type: "success", msg: "The role has been successfully created" });
41 | }
42 | catch (e) {
43 | Logger.error("Unable to create role");
44 | Logger.error(e);
45 | }
46 | }
47 | else {
48 | response({ type: "error", permission: "denied" });
49 | }
50 | }
51 | else {
52 | Logger.error("Token or ID incorrect");
53 | }
54 | });
55 | }
56 |
--------------------------------------------------------------------------------
/modules/sockets/deleteCategory.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { getChannelTree, hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('deleteCategory', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | if (!hasPermission(member.id, "manageChannels")) {
14 | response({ msg: "You arent allowed to delete categories", type: "error", error: "Cant delete category, missing permission manageChannels" })
15 | return;
16 | }
17 |
18 | try {
19 | delete serverconfig.groups[member.group].channels.categories[member.category.replace("category-", "")];
20 | saveConfig(serverconfig);
21 |
22 | response({ msg: "Category deleted", type: "success", error: null })
23 | io.emit("receiveChannelTree", getChannelTree(member));
24 | }
25 | catch (e) {
26 | Logger.error("Couldnt delete category");
27 | Logger.error(e);
28 | }
29 | }
30 | });
31 | }
32 |
--------------------------------------------------------------------------------
/modules/sockets/deleteChannel.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { getChannelTree, hasPermission, resolveCategoryByChannelId, resolveGroupByChannelId } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('deleteChannel', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | if (!hasPermission(member.id, "manageChannels")) {
14 | response({ msg: "You arent allowed to deleteChannels", type: "error", error: "Missing Permissions: manageChannels" })
15 | return;
16 | }
17 |
18 | try {
19 | var channelId = member.channelId.replace("channel-", "");
20 | var group = resolveGroupByChannelId(channelId);
21 | var category = resolveCategoryByChannelId(channelId);
22 |
23 | if (channelId == serverconfig.serverinfo.defaultChannel) {
24 | response({ msg: "You cant delete the default channel", type: "error", error: "Cant delete default channel" })
25 | return;
26 | }
27 |
28 | delete serverconfig.groups[group].channels.categories[category].channel[channelId];
29 | saveConfig(serverconfig);
30 |
31 | response({ msg: "Channel deleted", type: "success", error: null })
32 | io.emit("receiveChannelTree", getChannelTree(member));
33 | }
34 | catch (e) {
35 | Logger.error("Couldnt delete channel");
36 | Logger.error(e);
37 | }
38 | }
39 | });
40 | }
41 |
--------------------------------------------------------------------------------
/modules/sockets/deleteEmoji.mjs:
--------------------------------------------------------------------------------
1 | import { fs, io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { checkRateLimit, copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('deleteEmoji', function (member, response) {
9 | checkRateLimit(socket);
10 |
11 | member.id = xssFilters.inHTMLData(member.id)
12 | member.token = xssFilters.inHTMLData(member.token)
13 | member.emoji = xssFilters.inHTMLData(member.emoji)
14 | if (member.emoji.includes("..")) return;
15 |
16 | if (validateMemberId(member.id, socket) == true
17 | ) {
18 |
19 | if (hasPermission(member.id, "manageEmojis")) {
20 | try {
21 |
22 | try {
23 | if (member.emoji.includes("..")) return
24 |
25 | fs.unlinkSync(`./public/emojis/${member.emoji}`);
26 | response({ type: "success", msg: "Emoji deleted successfully" });
27 |
28 | } catch (error) {
29 | Logger.error("Coudlnt delete emoji")
30 | Logger.error(error)
31 |
32 | response({ type: "error", msg: "Cant Delete Emoji", error: error });
33 | }
34 | }
35 | catch (e) {
36 | Logger.error("Unable to resolve member");
37 | Logger.error(e);
38 | }
39 | }
40 | else {
41 | response({ type: "error", msg: "You dont have permissions to manage emojis" });
42 | }
43 | }
44 | });
45 | }
46 |
--------------------------------------------------------------------------------
/modules/sockets/deleteGroup.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('deleteGroup', function (member) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 | if (serverconfig.groups[member.group].info.isDeletable == 0) {
13 | sendMessageToUser(socket.id, JSON.parse(
14 | `{
15 | "title": "Error!",
16 | "message": "This group cant be deleted.",
17 | "buttons": {
18 | "0": {
19 | "text": "Ok",
20 | "events": ""
21 | }
22 | },
23 | "type": "error",
24 | "popup_type": "confirm"
25 | }`));
26 | return;
27 | }
28 |
29 | if (!hasPermission(member.id, "manageGroups")) {
30 | sendMessageToUser(socket.id, JSON.parse(
31 | `{
32 | "title": "Missing permissions!",
33 | "message": "You arent allowed to delete groups",
34 | "buttons": {
35 | "0": {
36 | "text": "Ok",
37 | "events": ""
38 | }
39 | },
40 | "type": "error",
41 | "popup_type": "confirm"
42 | }`));
43 | return;
44 | }
45 |
46 |
47 | try {
48 | delete serverconfig.groups[member.group];
49 | saveConfig(serverconfig);
50 |
51 | io.emit("updateGroupList");
52 | }
53 | catch (e) {
54 | Logger.error("Couldnt delete group");
55 | Logger.error(e);
56 | }
57 | }
58 | });
59 | }
60 |
--------------------------------------------------------------------------------
/modules/sockets/deleteRole.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('deleteRole', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 | if (hasPermission(member.id, "manageRoles")) {
13 | try {
14 |
15 | if (serverconfig.serverroles[member.roleId].info.deletable == 1) {
16 | delete serverconfig.serverroles[member.roleId];
17 | saveConfig(serverconfig);
18 |
19 | response({ type: "success", msg: "The role has been successfully deleted" });
20 | }
21 | else {
22 | response({ type: "error", msg: "This role cant be deleted" });
23 | }
24 | }
25 | catch (e) {
26 | Logger.error("Unable to delete role");
27 | Logger.error(e);
28 | }
29 | }
30 | else {
31 | response({ type: "error", msg: "denied" });
32 | }
33 | }
34 | else {
35 | Logger.error("Token or ID incorrect");
36 | }
37 | });
38 | }
39 |
--------------------------------------------------------------------------------
/modules/sockets/getAllRoles.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { getMemberHighestRole } from "../functions/chat/helper.mjs";
3 | import { hasPermission } from "../functions/chat/main.mjs";
4 | import Logger from "../functions/logger.mjs";
5 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
6 |
7 | export default (socket) => {
8 | // socket.on code here
9 | socket.on('getAllRoles', function (member, response) {
10 | if (validateMemberId(member.id, socket) == true
11 | ) {
12 | if (!hasPermission(member.id, "manageRoles", member.group)) {
13 | return;
14 | }
15 |
16 | var highestRole = getMemberHighestRole(member.id);
17 |
18 | var roles = serverconfig.serverroles;
19 | var sortIndex = 0;
20 | var returnRole = [];
21 |
22 | let sortedRoles = Object.keys(roles).sort((a, b) => {
23 | return roles[b].info.sortId - roles[a].info.sortId
24 | });
25 |
26 | sortedRoles = sortedRoles.reverse().map((key) => roles[key]);
27 |
28 |
29 |
30 | // Only returns roles that are can be assigned
31 | Object.keys(sortedRoles).reverse().forEach(function (role) {
32 | //console.log(roles[role].info.name)
33 |
34 | if (sortedRoles[role].info.sortId < highestRole.info.sortId || hasPermission(member.id, "administrator", member.group)) {
35 | sortIndex = sortedRoles[role].info.sortId;
36 |
37 | if (sortedRoles[role].members.includes(member.targetUser)) {
38 | sortedRoles[role].info.hasRole = 1;
39 | }
40 | else {
41 | sortedRoles[role].info.hasRole = 0;
42 | }
43 |
44 | // Get Highest role of user doing it
45 | var executer = getMemberHighestRole(member.id);
46 |
47 | // Only let people show roles they can actually assign
48 | if (sortedRoles[role].info.sortId < executer.info.sortId && role != 0 && role != 1) {
49 | returnRole.push(sortedRoles[role]);
50 | }
51 | }
52 | });
53 |
54 |
55 |
56 | io.emit("updateMemberList");
57 | response({ type: "success", data: returnRole });
58 | }
59 | });
60 | }
61 |
--------------------------------------------------------------------------------
/modules/sockets/getBans.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, getCastingMemberObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('getBans', async function (member, response) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | try {
14 | if (!hasPermission(member.id, "manageBans")) {
15 | sendMessageToUser(socket.id, JSON.parse(
16 | `{
17 | "title": "Missing permissions!",
18 | "message": "You arent allowed to manage Bans",
19 | "buttons": {
20 | "0": {
21 | "text": "Ok",
22 | "events": ""
23 | }
24 | },
25 | "type": "error",
26 | "popup_type": "confirm"
27 | }`));
28 |
29 | response({ type: "error", msg: "You dont have permissions to manage Bans" });
30 | return;
31 | }
32 |
33 | let banDataObj = copyObject(serverconfig.banlist);
34 |
35 | Object.entries(banDataObj).forEach(([bannedUserId, banData]) => {
36 | banData.bannedModObj = getCastingMemberObject(serverconfig.servermembers[banData.bannedBy]) || null;
37 | banData.bannedUserObj = getCastingMemberObject(serverconfig.servermembers[bannedUserId]) || null;
38 | });
39 |
40 |
41 | response({ type: "success", data: banDataObj, msg: "Successfully received banlist" })
42 | }
43 | catch (e) {
44 | Logger.error("Couldnt get emojis");
45 | Logger.error(e)
46 | }
47 | }
48 | });
49 | }
50 |
--------------------------------------------------------------------------------
/modules/sockets/getChannelInfo.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission, resolveChannelById } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on("getChannelInfo", function (member, response) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 | if (hasPermission(member.id, "manageChannels")) {
13 | var channelObj = resolveChannelById(member.channel.replace("channel-", ""));
14 | response({ type: "success", msg: "Successfully resolved channel", data: channelObj });
15 | }
16 | else {
17 | response({ type: "error", msg: "You dont have the permissions to manage channels" })
18 | }
19 | }
20 | else {
21 | Logger.warn("ID or Token was invalid while requesting server information");
22 | Logger.warn(`ID: ${member.id}`);
23 | Logger.warn(`Token: ${member.token}`);
24 | }
25 | });
26 | }
27 |
--------------------------------------------------------------------------------
/modules/sockets/getChannelTree.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { getChannelTree, hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('getChannelTree', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | ) {
11 |
12 | member.id = xssFilters.inHTMLData(member.id)
13 | member.token = xssFilters.inHTMLData(member.token)
14 | member.group = xssFilters.inHTMLData(member.group)
15 |
16 | if (!hasPermission(member.id, "viewGroup", member.group)) {
17 | return;
18 | }
19 |
20 | response({ type: "success", data: getChannelTree(member) });
21 | //io.to(usersocket[member.id]).emit("receiveChannelTree", getChannelTree(member));
22 | }
23 | });
24 | }
25 |
--------------------------------------------------------------------------------
/modules/sockets/getChatlog.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, usersocket, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import { getSavedChatMessage } from "../functions/io.mjs";
4 | import Logger from "../functions/logger.mjs";
5 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
6 |
7 | export default (socket) => {
8 | // socket.on code here
9 |
10 | socket.on('getChatlog', async function (member) {
11 | if (validateMemberId(member.id, socket) == true
12 | && serverconfig.servermembers[member.id].token == member.token) {
13 |
14 | if (hasPermission(member.id, ["viewChannel", "viewChannelHistory"], member.channelId)) {
15 | io.to(usersocket[member.id]).emit("receiveChatlog", await getSavedChatMessage(member.groupId, member.categoryId, member.channelId, member.index));
16 | }
17 | }
18 | });
19 | }
20 |
--------------------------------------------------------------------------------
/modules/sockets/getCurrentChannel.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, usersocket, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('getCurrentChannel', function (member) {
9 | if (validateMemberId(member.id, socket) == true) {
10 |
11 | try {
12 | if (hasPermission(member.id, "viewChannel", member.channel) == true) {
13 | io.to(usersocket[member.id]).emit("receiveCurrentChannel", serverconfig.groups[member.group].channels.categories[member.category].channel[member.channel]);
14 | }
15 | }
16 | catch {
17 | io.to(usersocket[member.id]).emit("receiveCurrentChannel", serverconfig.groups[member.group]);
18 | }
19 | }
20 | });
21 | }
22 |
--------------------------------------------------------------------------------
/modules/sockets/getEmojis.mjs:
--------------------------------------------------------------------------------
1 | import { fs, io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('getEmojis', async function (member, response) {
9 |
10 | if (validateMemberId(member.id, socket) == true &&
11 | serverconfig.servermembers[member.id].token == member.token
12 | ) {
13 |
14 | try {
15 |
16 | /*
17 | Maybe use this with a permission like "useEmojis" until it becomes a problem
18 | if(!hasPermission(member.id, "manageEmojis")){
19 | sendMessageToUser(socket.id, JSON.parse(
20 | `{
21 | "title": "Missing permissions!",
22 | "message": "You arent allowed to manage Emojis",
23 | "buttons": {
24 | "0": {
25 | "text": "Ok",
26 | "events": "onclick='closeModal()'"
27 | }
28 | },
29 | "type": "error"
30 | }`));
31 |
32 | response({type: "error", msg: "You dont have permissions to manage Emojis"});
33 | return;
34 | }
35 | */
36 |
37 | // Emoji List array
38 | var emojiList = [];
39 |
40 | // Get all local emojis sorted by creation date
41 | fs.readdirSync("./public/emojis").sort((a, b) => {
42 | let aStat = fs.statSync(`./public/emojis/${a}`),
43 | bStat = fs.statSync(`./public/emojis/${b}`);
44 |
45 | return new Date(bStat.birthtime).getTime() - new Date(aStat.birthtime).getTime();
46 | }).forEach(file => {
47 | emojiList.push(file);
48 | });
49 |
50 | if (emojiList.length > 0) {
51 | response({ type: "success", data: emojiList, msg: "Successfully received emojis" })
52 | }
53 | else {
54 | response({ type: "error", data: null, msg: "No Emojis found" })
55 | }
56 | }
57 | catch (e) {
58 | Logger.error("Couldnt get emojis");
59 | Logger.error(e);
60 | }
61 | }
62 | });
63 | }
64 |
--------------------------------------------------------------------------------
/modules/sockets/getGroupBanner.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, usersocket, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('getGroupBanner', function (member) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token) {
11 |
12 | if (!hasPermission(member.id, "viewGroup", member.group)) {
13 | return;
14 | }
15 |
16 | io.to(usersocket[member.id]).emit("receiveGroupBanner", serverconfig.groups[member.group].info.banner);
17 | }
18 | });
19 | }
20 |
--------------------------------------------------------------------------------
/modules/sockets/getGroupChannels.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on("getGroupChannels", function (member, response) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 | if (hasPermission(member.id, "manageChannels") ||
13 | hasPermission(member.id, "manageGroup") ||
14 | hasPermission(member.id, "manageGroups")) {
15 |
16 | response(serverconfig.groups);
17 | }
18 | else {
19 | response({ type: "error", msg: "You dont have the permissions to manage group channels" })
20 | }
21 | }
22 | else {
23 | Logger.warn("ID or Token was invalid while requesting server information");
24 | Logger.warn(`ID: ${member.id}`);
25 | Logger.warn(`Token: ${member.token}`);
26 | }
27 | });
28 | }
29 |
--------------------------------------------------------------------------------
/modules/sockets/getGroupInfo.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on("getGroupInfo", function (member, response) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 | if (hasPermission(member.id, "manageGroups")) {
13 |
14 | var groupObj = serverconfig.groups[member.group];
15 | response({ type: "success", msg: "Successfully resolved group", data: groupObj });
16 | }
17 | else {
18 | response({ type: "error", msg: "You dont have the permissions to manage groups" })
19 | }
20 | }
21 | else {
22 | Logger.warn("ID or Token was invalid while requesting server information");
23 | Logger.warn(`ID: ${member.id}`);
24 | Logger.warn(`Token: ${member.token}`);
25 | }
26 | });
27 | }
28 |
--------------------------------------------------------------------------------
/modules/sockets/getGroupList.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, usersocket, xssFilters } from "../../index.mjs";
2 | import { getGroupList, hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('getGroupList', function (member) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token) {
11 | io.to(usersocket[member.id]).emit("receiveGroupList", getGroupList(member));
12 | }
13 | });
14 | }
15 |
--------------------------------------------------------------------------------
/modules/sockets/getMemberList.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { getMemberList, hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('getMemberList', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token) {
11 |
12 | if (!hasPermission(member.id, "viewGroup", member.group)) {
13 | response({ error: true, msg: "You arent allowed to view this group", type: "error" })
14 | return;
15 | }
16 |
17 | response({ data: getMemberList(member, member.channel) })
18 | }
19 | });
20 | }
21 |
--------------------------------------------------------------------------------
/modules/sockets/getMemberProfile.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, usersocket, xssFilters } from "../../index.mjs";
2 | import { getMemberProfile, hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { checkRateLimit, copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('getMemberProfile', async function (member) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | try {
14 | // bug: being online on two devices with the same account
15 | // will show the profile on both devices in the same position
16 | io.to(usersocket[xssFilters.inHTMLData(member.id)]).emit("receiveMemberProfile",
17 | {
18 | "code": await getMemberProfile(
19 | xssFilters.inHTMLData(member.target)),
20 | "top": xssFilters.inHTMLData(member.posY),
21 | "left": xssFilters.inHTMLData(member.posX)
22 | }
23 | );
24 | }
25 | catch (e) {
26 | Logger.error("Couldnt get member profile");
27 | Logger.error(e);
28 | }
29 | }
30 | });
31 | }
32 |
--------------------------------------------------------------------------------
/modules/sockets/getPluginList.mjs:
--------------------------------------------------------------------------------
1 | import { validateMemberId, copyObject } from "../functions/main.mjs";
2 | import { serverconfig } from "../../index.mjs";
3 | import { scanDirectory } from "../functions/io.mjs";
4 |
5 | export default (socket) => {
6 | socket.on('getPluginList', (member, response) => {
7 | let plugins = scanDirectory("./public/plugins", { includeFiles: false, recursive: false });
8 | let pluginObj = {};
9 |
10 | // foreach plugin
11 | for (let i = 0; i < plugins.length; i++) {
12 | let pluginName = copyObject(plugins[i]).split("\\").pop();
13 |
14 | pluginObj[pluginName] = {};
15 | pluginObj[pluginName].filePaths = [];
16 |
17 | // check root of plugin
18 | let pluginRoot = scanDirectory(plugins[i], { includeFiles: true, recursive: false });
19 |
20 | // check for entry script
21 | if (pluginRoot.includes(`${plugins[i]}\\main.js`)) {
22 | pluginObj[pluginName].filePaths.push(`${plugins[i]}\\main.js`);
23 | pluginObj[pluginName].filePaths = pluginObj[pluginName].filePaths.map(plugin => plugin.replace("public\\", ""));
24 | }
25 | }
26 |
27 | response({ type: 'success', plugins: pluginObj });
28 | });
29 | };
30 |
--------------------------------------------------------------------------------
/modules/sockets/getServerInfo.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on("getServerInfo", function (member, response) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 | var serverInfoObj = {
13 | name: serverconfig.serverinfo.name,
14 | description: serverconfig.serverinfo.description,
15 | defaultChannel: serverconfig.serverinfo.defaultChannel,
16 | uploadFileTypes: serverconfig.serverinfo.uploadFileTypes,
17 | messageLoadLimit: serverconfig.serverinfo.messageLoadLimit,
18 | tenorEnabled: serverconfig.serverinfo.tenor.enabled,
19 | sqlEnabled: serverconfig.serverinfo.sql.enabled,
20 | registrationEnabled: serverconfig.serverinfo.registration.enabled
21 |
22 | };
23 |
24 | if (hasPermission(member.id, "manageServer")) {
25 | // add more objects here
26 | serverInfoObj.useCloudflareImageCDN = serverconfig.serverinfo.useCloudflareImageCDN,
27 | serverInfoObj.cfAccountId = serverconfig.serverinfo.cfAccountId,
28 | serverInfoObj.cfAccountToken = serverconfig.serverinfo.cfAccountToken,
29 | serverInfoObj.cfHash = serverconfig.serverinfo.cfHash,
30 | serverInfoObj.maxUploadStorage = serverconfig.serverinfo.maxUploadStorage,
31 | serverInfoObj.rateLimit = serverconfig.serverinfo.rateLimit,
32 | serverInfoObj.dropInterval = serverconfig.serverinfo.dropInterval,
33 | serverInfoObj.messageLoadLimit = serverconfig.serverinfo.messageLoadLimit,
34 |
35 | serverInfoObj.moderation = serverconfig.serverinfo.moderation,
36 | serverInfoObj.registration = serverconfig.serverinfo.registration,
37 | serverInfoObj.login = serverconfig.serverinfo.login
38 | }
39 |
40 | response(serverInfoObj);
41 | }
42 | else {
43 | Logger.warn("ID or Token was invalid while requesting server information");
44 | Logger.warn(`ID: ${member.id}`);
45 | Logger.warn(`Token: ${member.token}`);
46 | }
47 | });
48 | }
49 |
--------------------------------------------------------------------------------
/modules/sockets/getServerRoles.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on("getServerRoles", function (member, response) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 | if (hasPermission(member.id, "manageRoles")) {
13 | response(serverconfig.serverroles);
14 | }
15 | else {
16 | response({ type: "error", msg: "You dont have the permissions to manage server roles" })
17 | }
18 | }
19 | else {
20 | Logger.warn("ID or Token was invalid while requesting server information");
21 | Logger.warn(`ID: ${member.id}`);
22 | Logger.warn(`Token: ${member.token}`);
23 | }
24 | });
25 | }
26 |
--------------------------------------------------------------------------------
/modules/sockets/getUserFromId.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, getCastingMemberObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('getUserFromId', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | ) {
11 | response({ type: "success", user: getCastingMemberObject(serverconfig.servermembers[member.target]) });
12 | }
13 | });
14 | }
15 |
--------------------------------------------------------------------------------
/modules/sockets/isTyping.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, typingMembers, typingMembersTimeout, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, escapeHtml, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('isTyping', function (member) {
9 | // todo : check for perms to view channel
10 | if (validateMemberId(member.id, socket, true) == true
11 | && serverconfig.servermembers[member.id].token == member.token) {
12 |
13 | //consolas("Typing room: " + member.room);
14 | //consolas("Typing member id: " + member.id);
15 |
16 | // if user is muted dont do anything
17 | if (serverconfig.mutelist.hasOwnProperty(member.id)) {
18 | return;
19 | }
20 |
21 | var username = serverconfig.servermembers[member.id].name;
22 | if (typingMembers.includes(username) == false) {
23 | typingMembers.push(escapeHtml(username));
24 | }
25 |
26 | clearTimeout(typingMembersTimeout[username]);
27 | typingMembersTimeout[username] = setTimeout(() => {
28 |
29 | if (typingMembers.includes(username) == true) {
30 | const index = typingMembers.indexOf(escapeHtml(username));
31 | if (index !== -1) {
32 | typingMembers.splice(index, 1); // Remove the element at the found index
33 | }
34 |
35 | }
36 |
37 | io.in(member.room).emit("memberTyping", typingMembers);
38 |
39 | }, 4 * 1000);
40 |
41 | //console.log(typingMembersTimeout[username]);
42 |
43 | io.in(member.room).emit("memberTyping", typingMembers);
44 | }
45 | });
46 | }
47 |
--------------------------------------------------------------------------------
/modules/sockets/pow.mjs:
--------------------------------------------------------------------------------
1 | import { powVerifiedUsers, serverconfig, xssFilters } from "../../index.mjs";
2 | import { copyObject, validateMemberId } from "../functions/main.mjs";
3 |
4 | export default (socket) => {
5 | // socket.on code here
6 | // Send a PoW challenge to the client
7 | socket.on('requestPow', () => {
8 | const challenge = crypto.randomBytes(16).toString('hex');
9 | socket.emit('powChallenge', { challenge, difficulty: powDifficulty });
10 | });
11 |
12 | // Verify the PoW solution
13 | socket.on('verifyPow', ({ challenge, solution }) => {
14 | if (isValidProof(challenge, solution)) {
15 |
16 | if (!powVerifiedUsers.includes(socket.id)) {
17 | powVerifiedUsers.push(socket.id);
18 | }
19 |
20 | console.log('Client authenticated');
21 | socket.emit('authSuccess', { message: 'Authenticated' });
22 | } else {
23 | console.log('Client failed to authenticate');
24 | socket.emit('authFailure', { message: 'Failed to authenticate' });
25 | }
26 | });
27 |
28 | function isValidProof(challenge, solution) {
29 | const hash = crypto.createHash('sha256').update(challenge + solution).digest('hex');
30 | return hash.substring(0, powDifficulty) === Array(powDifficulty + 1).join('0');
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/modules/sockets/removeRoleFromChannel.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission, resolveCategoryByChannelId, resolveGroupByChannelId } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('removeRoleFromChannel', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | if (hasPermission(member.id, "manageChannels")) {
14 | try {
15 |
16 | var memberChannel = member.channel.replace("channel-", "");
17 |
18 | var group = resolveGroupByChannelId(memberChannel);
19 | var category = resolveCategoryByChannelId(memberChannel);
20 |
21 | delete serverconfig.groups[group].channels.categories[category].channel[memberChannel].permissions[member.role];
22 | saveConfig(serverconfig);
23 |
24 | response({ type: "success", msg: "Role was successfully removed from the channel" });
25 | }
26 | catch (e) {
27 | Logger.error("Unable to remove role from channel");
28 | Logger.error(e);
29 | }
30 | }
31 | else {
32 | response({ type: "error", msg: "denied" });
33 | }
34 | }
35 | });
36 | }
37 |
--------------------------------------------------------------------------------
/modules/sockets/removeRoleFromGroup.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('removeRoleFromGroup', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | if (hasPermission(member.id, "manageGroups")) {
14 | try {
15 | delete serverconfig.groups[member.group].permissions[member.role];
16 | saveConfig(serverconfig);
17 |
18 | response({ type: "success", msg: "Role was successfully removed from the group" });
19 | }
20 | catch (e) {
21 | Logger.error("Unable to remove role to group");
22 | Logger.error(e);
23 | }
24 | }
25 | else {
26 | response({ type: "error", msg: "denied" });
27 | }
28 | }
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/modules/sockets/removeUserFromRole.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, usersocket, xssFilters } from "../../index.mjs";
2 | import { getMemberHighestRole } from "../functions/chat/helper.mjs";
3 | import { hasPermission } from "../functions/chat/main.mjs";
4 | import Logger from "../functions/logger.mjs";
5 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
6 |
7 | export default (socket) => {
8 | // socket.on code here
9 | socket.on('removeUserFromRole', function (member, response) {
10 | if (validateMemberId(member.id, socket) == true
11 | && serverconfig.servermembers[member.id].token == member.token
12 | ) {
13 |
14 | Logger.debug(`trying to remove role`)
15 | member.id = xssFilters.inHTMLData(member.id)
16 | member.token = xssFilters.inHTMLData(member.token)
17 | member.target = xssFilters.inHTMLData(member.target)
18 |
19 | try {
20 | var executer = getMemberHighestRole(member.id);
21 | var target = getMemberHighestRole(member.target);
22 | let hasPerms = hasPermission(member.id, "manageMembers")
23 |
24 |
25 | // If user is not a admin they cant assign roles that are higher
26 | if ((executer.info.sortId >= target.info.sortId)) {
27 | if (!hasPerms) {
28 | response({ type: "error", msg: "You cant remove roles that are higher or equal then yours" });
29 | return;
30 | }
31 | }
32 | // Default Roles
33 | if (serverconfig.serverroles[member.role].info.id == 0 || serverconfig.serverroles[member.role] == 1) {
34 | return;
35 | }
36 |
37 | // return only filtered
38 | serverconfig.serverroles[member.role].members = serverconfig.serverroles[member.role].members.filter(id => id !== member.target);
39 |
40 | saveConfig(serverconfig);
41 |
42 |
43 | io.emit("updateMemberList");
44 | io.to(usersocket[member.target]).emit("updateMemberList");
45 | response({ type: "success", msg: "Role removed" });
46 | }
47 | catch (e) {
48 | Logger.error("Unable to remove member from group");
49 | Logger.error(e);
50 | }
51 | }
52 | });
53 | }
54 |
--------------------------------------------------------------------------------
/modules/sockets/reports/deleteMessageInReport.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, usersocket, xssFilters } from "../../../index.mjs";
2 | import { hasPermission, resolveChannelById } from "../../functions/chat/main.mjs";
3 | import { getSavedChatMessage } from "../../functions/io.mjs";
4 | import Logger from "../../functions/logger.mjs";
5 | import { validateMemberId } from "../../functions/main.mjs";
6 | import { deleteChatMessagesFromDb, getChatMessagesFromDb, getReports, saveReport } from "../../functions/mysql/helper.mjs";
7 |
8 | export default (socket) => {
9 |
10 | // socket.on code here
11 | socket.on('deleteMessageInReport', async function (member, response) {
12 | if (validateMemberId(member.id, socket) == true
13 | && serverconfig.servermembers[member.id].token == member.token
14 | ) {
15 |
16 | if (hasPermission(member.id, "manageMessages")) {
17 | try {
18 | let deleteResult = await deleteChatMessagesFromDb(member.messageId);
19 |
20 | if(deleteResult.affectedRows >= 1){
21 | io.emit("receiveDeleteMessage", member.messageId);
22 | response({ type: "success", msg: "Message was deleted"});
23 | }
24 | else{
25 | Logger.debug(deleteResult)
26 | response({ type: "error", msg: "Message cant be deleted"});
27 | }
28 |
29 | }
30 | catch (e) {
31 | Logger.error("Unable to get reports");
32 | Logger.error(e);
33 | }
34 | }
35 | else {
36 | response({ type: "error", msg: "You're not allowed to manage messages" });
37 | }
38 | }
39 | });
40 | }
41 |
--------------------------------------------------------------------------------
/modules/sockets/reports/deleteReport.mjs:
--------------------------------------------------------------------------------
1 | import { serverconfig, usersocket, xssFilters } from "../../../index.mjs";
2 | import { hasPermission, resolveChannelById } from "../../functions/chat/main.mjs";
3 | import { getSavedChatMessage } from "../../functions/io.mjs";
4 | import Logger from "../../functions/logger.mjs";
5 | import { validateMemberId } from "../../functions/main.mjs";
6 | import { deleteReport, getChatMessagesFromDb, getReports, saveReport } from "../../functions/mysql/helper.mjs";
7 |
8 | export default (socket) => {
9 |
10 | // socket.on code here
11 | socket.on('deleteReport', async function (member, response) {
12 | if (validateMemberId(member.id, socket) == true
13 | && serverconfig.servermembers[member.id].token == member.token
14 | ) {
15 |
16 | if (hasPermission(member.id, "manageReports")) {
17 | try {
18 | let reports = await deleteReport(xssFilters.inHTMLData(member.reportId));
19 |
20 | if(reports.affectedRows >= 1)
21 | response({ type: "success", msg: "Report deleted", reports: reports});
22 | else
23 | response({ type: "error", msg: "Cant delete Report", reports: reports});
24 | }
25 | catch (e) {
26 | Logger.error("Unable to get reports");
27 | Logger.error(e);
28 | }
29 | }
30 | else {
31 | response({ type: "error", msg: "You're not allowed to manage reports" });
32 | }
33 | }
34 | });
35 | }
36 |
--------------------------------------------------------------------------------
/modules/sockets/reports/fetchReports.mjs:
--------------------------------------------------------------------------------
1 | import { serverconfig, usersocket, xssFilters } from "../../../index.mjs";
2 | import { hasPermission, resolveChannelById } from "../../functions/chat/main.mjs";
3 | import { getSavedChatMessage } from "../../functions/io.mjs";
4 | import Logger from "../../functions/logger.mjs";
5 | import { validateMemberId } from "../../functions/main.mjs";
6 | import { getChatMessagesFromDb, getReports, saveReport } from "../../functions/mysql/helper.mjs";
7 |
8 | export default (socket) => {
9 |
10 | // socket.on code here
11 | socket.on('fetchReports', async function (member, response) {
12 | if (validateMemberId(member.id, socket) == true
13 | && serverconfig.servermembers[member.id].token == member.token
14 | ) {
15 |
16 | if (hasPermission(member.id, "manageReports")) {
17 | try {
18 | let reports = await getReports();
19 | Object.keys(reports).forEach(function (report) {
20 | reports[report].reportCreator = JSON.parse(reports[report].reportCreator)
21 | reports[report].reportedUser = JSON.parse(reports[report].reportedUser)
22 | });
23 |
24 | response({ type: "success", msg: "Reports fetched", reports: reports});
25 | }
26 | catch (e) {
27 | Logger.error("Unable to get reports");
28 | Logger.error(e);
29 | }
30 | }
31 | else {
32 | response({ type: "error", msg: "You're not allowed to manage reports" });
33 | }
34 | }
35 | });
36 | }
37 |
--------------------------------------------------------------------------------
/modules/sockets/resolveMember.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, getCastingMemberObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('resolveMember', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | member.id = xssFilters.inHTMLData(member.id)
14 | member.token = xssFilters.inHTMLData(member.token)
15 |
16 | if (hasPermission(member.id, "resolveMembers")) {
17 | try {
18 | var resolved = copyObject(serverconfig.servermembers[member.target]);
19 |
20 | response({ type: "success", msg: "User Data was resolved", data: getCastingMemberObject(resolved) });
21 | }
22 | catch (e) {
23 | Logger.error("Unable to resolve member");
24 | console.log(e);
25 | }
26 | }
27 | else {
28 | response({ type: "error", msg: "denied" });
29 | }
30 | }
31 | });
32 | }
33 |
--------------------------------------------------------------------------------
/modules/sockets/saveChannelPermissions.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission, resolveCategoryByChannelId, resolveGroupByChannelId } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('saveChannelPermissions', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | member.id = xssFilters.inHTMLData(member.id)
14 | member.token = xssFilters.inHTMLData(member.token)
15 |
16 | if (hasPermission(member.id, "manageChannels")) {
17 | try {
18 | //console.log(member.role);
19 |
20 | var memberChannel = member.channel.replace("channel-", "");
21 | var group = resolveGroupByChannelId(memberChannel);
22 | var category = resolveCategoryByChannelId(memberChannel);
23 |
24 | serverconfig.groups[group].channels.categories[category].channel[memberChannel].permissions[member.role] = member.permission;
25 | saveConfig(serverconfig);
26 |
27 | io.emit("receiveChannelTree");
28 | response({ type: "success", msg: "Channel permissions have been updated" });
29 | }
30 | catch (e) {
31 | Logger.error("Unable to update channel permissions from role");
32 | Logger.error(e);
33 | }
34 | }
35 | else {
36 | response({ type: "error", msg: "denied" });
37 | }
38 | }
39 | });
40 | }
41 |
--------------------------------------------------------------------------------
/modules/sockets/saveMediaSettings.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on("saveMediaSettings", function (member, response) {
9 |
10 | if (validateMemberId(member.id, socket) == true &&
11 | serverconfig.servermembers[member.id].token == member.token
12 | ) {
13 | if (hasPermission(member.id, "manageUploads")) {
14 | try {
15 | serverconfig.serverinfo.maxUploadStorage = member.maxLocalUpload;
16 | serverconfig.serverinfo.useCloudflareImageCDN = member.useCloudflare;
17 | serverconfig.serverinfo.cfAccountId = member.cloudflareAccountId;
18 | serverconfig.serverinfo.cfAccountToken = member.cloudflareAccountToken;
19 | serverconfig.serverinfo.cfHash = member.cloudflareHash;
20 | saveConfig(serverconfig);
21 |
22 | response({ type: "success", msg: "Settings saved successfully, please try to upload a profile picture to see if it works." })
23 | }
24 | catch (error) {
25 | response({ type: "error", msg: "Server couldnt save settings: " + error })
26 | }
27 | }
28 | else {
29 | response({ type: "error", msg: "You dont have the permissions to manage the upload settings" })
30 | }
31 | }
32 | });
33 | }
34 |
--------------------------------------------------------------------------------
/modules/sockets/saveRateSettings.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on("saveRateSettings", function (member, response) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 | if (hasPermission(member.id, "manageRateSettings")) {
13 | try {
14 | serverconfig.serverinfo.rateLimit = member.newRateLimit;
15 | serverconfig.serverinfo.dropInterval = member.newDropInterval;
16 | saveConfig(serverconfig);
17 |
18 | response({ type: "success", msg: "Settings saved successfully." })
19 | }
20 | catch (error) {
21 | response({ type: "error", msg: "Server couldnt save rate settings: " + error })
22 | }
23 | }
24 | else {
25 | response({ type: "error", msg: "You dont have the permissions to manage the rate settings" })
26 | }
27 | }
28 | });
29 | }
30 |
--------------------------------------------------------------------------------
/modules/sockets/saveRolePermissions.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('saveRolePermissions', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | member.id = xssFilters.inHTMLData(member.id)
14 | member.token = xssFilters.inHTMLData(member.token)
15 | member.permissions = JSON.parse(xssFilters.inHTMLData(JSON.stringify(member.permissions)))
16 |
17 | if (hasPermission(member.id, "manageRoles")) {
18 | try {
19 | serverconfig.serverroles[member.role].permissions = member.permissions;
20 | saveConfig(serverconfig);
21 |
22 | io.emit("updateMemberList");
23 | response({ type: "success", msg: "Role permissions have been updated" });
24 | }
25 | catch (e) {
26 | Logger.error("Unable to update permissions from role");
27 | Logger.error(e);
28 | }
29 | }
30 | else {
31 | response({ type: "error", msg: "denied" });
32 | }
33 | }
34 | });
35 | }
36 |
--------------------------------------------------------------------------------
/modules/sockets/searchTenorGif.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, searchTenor, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('searchTenorGif', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | ) {
11 | member.id = xssFilters.inHTMLData(member.id)
12 | member.token = xssFilters.inHTMLData(member.token)
13 | member.search = xssFilters.inHTMLData(member.search)
14 |
15 | if (serverconfig.serverinfo.tenor.enabled != 1) {
16 | response({ type: "error", msg: "GIFs are disabled on this server" });
17 | }
18 | else {
19 | response({ type: "success", msg: "Trying to search GIF" });
20 | }
21 |
22 | searchTenor(member.search, member.id);
23 | Logger.debug("Searching GIF for " + member.search)
24 | }
25 | });
26 | }
27 |
--------------------------------------------------------------------------------
/modules/sockets/setDefaultChannel.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission, resolveChannelById } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, escapeHtml, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('setDefaultChannel', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token) {
11 |
12 | if (hasPermission(member.id, "manageServer")) {
13 |
14 | // Try to resolve channel first to see if it even exists
15 | let channel = resolveChannelById(member.value);
16 |
17 | // Couldnt find channel
18 | if (channel == null) {
19 | Logger.error(colors.red(`Channel with ID '${member.value}' wasnt found`))
20 | response({ type: "error", msg: `Channel with ID '${member.value}' wasnt found` });
21 | return;
22 | }
23 |
24 | serverconfig.serverinfo.defaultChannel = escapeHtml(member.value);
25 | saveConfig(serverconfig);
26 |
27 | response({ type: "success", msg: "Default Channel was successfully set" });
28 | }
29 | else {
30 | response({ type: "error", msg: "You cant change the server name: Missing permissions" });
31 | }
32 | }
33 | });
34 | }
35 |
--------------------------------------------------------------------------------
/modules/sockets/stoppedTyping.mjs:
--------------------------------------------------------------------------------
1 | import { io, serverconfig, typingMembers, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, escapeHtml, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 |
9 | socket.on('stoppedTyping', function (member) {
10 | if (validateMemberId(member.id, socket) == true
11 | && serverconfig.servermembers[member.id].token == member.token) {
12 |
13 | var username = serverconfig.servermembers[member.id].name;
14 |
15 | if (typingMembers.includes(username) == true) {
16 | const index = typingMembers.indexOf(escapeHtml(username));
17 | if (index !== -1) {
18 | typingMembers.splice(index, 1); // Remove the element at the found index
19 | }
20 |
21 | }
22 |
23 | io.in(member.room).emit("memberTyping", typingMembers);
24 | }
25 | });
26 | }
27 |
--------------------------------------------------------------------------------
/modules/sockets/unbanUser.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('unbanUser', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | member.id = xssFilters.inHTMLData(member.id)
14 | member.token = xssFilters.inHTMLData(member.token)
15 | member.duration = xssFilters.inHTMLData(member.duration)
16 |
17 | if (hasPermission(member.id, "manageBans")) {
18 | try {
19 | serverconfig.servermembers[member.target].isBanned = 0;
20 | delete serverconfig.banlist[member.target];
21 | saveConfig(serverconfig);
22 |
23 | response({ type: "success", msg: `The user ${serverconfig.servermembers[member.target].name} has been unbanned` });
24 | }
25 | catch (e) {
26 | response({ type: "error", msg: `User couldnt be unbanned` });
27 | consolas("Unable to resolve member".red);
28 | console.log(e);
29 | }
30 | }
31 | else {
32 | response({ type: "error", msg: "You arent allowed to unban members" });
33 | }
34 | }
35 | });
36 | }
37 |
--------------------------------------------------------------------------------
/modules/sockets/unmuteUser.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('unmuteUser', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | member.id = xssFilters.inHTMLData(member.id)
14 | member.token = xssFilters.inHTMLData(member.token)
15 |
16 | if (hasPermission(member.id, "muteUsers")) {
17 |
18 | if (serverconfig.mutelist.hasOwnProperty(member.target)) {
19 | delete serverconfig.mutelist[member.target];
20 | response({type: "success", msg: `The user ${serverconfig.servermembers[member.target].name} has been unmuted` });
21 | }
22 | else {
23 | response({type: "error", msg: `The user ${serverconfig.servermembers[member.target].name} isnt muted` });
24 | }
25 |
26 |
27 | serverconfig.servermembers[member.target].isMuted = 0;
28 | saveConfig(serverconfig);
29 |
30 | io.emit("updateMemberList");
31 | }
32 | else {
33 | //response({type: "error", msg: "denied"});
34 | }
35 | }
36 | });
37 | }
38 |
--------------------------------------------------------------------------------
/modules/sockets/updateChannelHierarchy.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, usersocket, xssFilters } from "../../index.mjs";
2 | import { getChannelTree, hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('updateChannelHierarchy', function (member, response) {
9 | checkRateLimit(socket);
10 |
11 | if (validateMemberId(member.id, socket) == true
12 | && serverconfig.servermembers[member.id].token == member.token
13 | ) {
14 |
15 | if (hasPermission(member.id, "manageChannels") ||
16 | hasPermission(member.id, "manageGroup") ||
17 | hasPermission(member.id, "manageGroups")) {
18 | try {
19 | serverconfig.groups = member.sorted;
20 |
21 | saveConfig(serverconfig);
22 |
23 | response({ type: "success", msg: "Changes were successfully applied" });
24 |
25 | // Update Channel Hierarchy for everyone
26 | io.to(usersocket[member.id]).emit("receiveChannelTree", getChannelTree(member));
27 | io.emit("receiveChannelTree", getChannelTree(member));
28 |
29 | // Update Group Hierarchy for everyone
30 | io.emit("updateGroupList");
31 | }
32 | catch (e) {
33 | Logger.error("Unable to sort roles");
34 | Logger.error(e)
35 | }
36 | }
37 | else {
38 | response({ type: "error", msg: "denied" });
39 | }
40 | }
41 | });
42 | }
43 |
--------------------------------------------------------------------------------
/modules/sockets/updateChannelName.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission, resolveCategoryByChannelId, resolveGroupByChannelId } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on("updateChannelName", function (member, response) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 | if (hasPermission(member.id, "manageChannels")) {
13 | var group = resolveGroupByChannelId(member.channel);
14 | var category = resolveCategoryByChannelId(member.channel);
15 |
16 | serverconfig.groups[group].channels.categories[category].channel[member.channel].name = member.name;
17 | saveConfig(serverconfig);
18 |
19 | response({ type: "success", msg: "Successfully updated channel name" });
20 |
21 | // Let everyone know about the update
22 | io.emit("receiveChannelTree", getChannelTree(member));
23 | }
24 | else {
25 | response({ type: "error", msg: "You dont have the permissions to manage channels" })
26 | }
27 | }
28 | else {
29 | Logger.warn("ID or Token was invalid while requesting server information");
30 | Logger.warn(`ID: ${member.id}`);
31 | Logger.warn(`Token: ${member.token}`);
32 | }
33 | });
34 | }
35 |
--------------------------------------------------------------------------------
/modules/sockets/updateEmoji.mjs:
--------------------------------------------------------------------------------
1 | import { fs, io, serverconfig, xssFilters } from "../../index.mjs";
2 | import { findEmojiByID } from "../functions/chat/helper.mjs";
3 | import { hasPermission } from "../functions/chat/main.mjs";
4 | import Logger from "../functions/logger.mjs";
5 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
6 |
7 | export default (socket) => {
8 | // socket.on code here
9 | socket.on('updateEmoji', async function (member, response) {
10 | checkRateLimit(socket);
11 |
12 | if (validateMemberId(member.id, socket) == true &&
13 | serverconfig.servermembers[member.id].token == member.token
14 | ) {
15 |
16 | try {
17 | if (!hasPermission(member.id, "manageEmojis")) {
18 | sendMessageToUser(socket.id, JSON.parse(
19 | `{
20 | "title": "Missing permissions!",
21 | "message": "You arent allowed to manage Emojis",
22 | "buttons": {
23 | "0": {
24 | "text": "Ok",
25 | "events": ""
26 | }
27 | },
28 | "type": "error",
29 | "popup_type": "confirm"
30 | }`));
31 |
32 | response({ type: "error", msg: "You dont have permissions to manage Emojis" });
33 | return;
34 | }
35 |
36 | var oldEmoji = findEmojiByID(member.emojiId);
37 | var newEmoji = `emoji_${member.emojiId}_${member.emojiName}.${oldEmoji.split(".").pop()}`;
38 |
39 | fs.rename('./public/emojis/' + oldEmoji, `./public/emojis/` + newEmoji, function (err) {
40 | if (err) {
41 | response({ type: "error", error: err, msg: "Couldnt update emoji" })
42 | }
43 | else {
44 | response({ type: "success", msg: "Emoji successfully updated" })
45 | }
46 | });
47 | }
48 | catch (e) {
49 | Logger.error("Couldnt get emojis");
50 | Logger.error(e);
51 | }
52 | }
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/modules/sockets/updateGroupBanner.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, escapeHtml, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('updateGroupBanner', function (member) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | if (!hasPermission(member.id, "manageGroups")) {
14 | sendMessageToUser(socket.id, JSON.parse(
15 | `{
16 | "title": "Missing permissions!",
17 | "message": "You arent allowed to change the group banner",
18 | "buttons": {
19 | "0": {
20 | "text": "Ok",
21 | "events": ""
22 | }
23 | },
24 | "type": "error",
25 | "popup_type": "confirm"
26 | }`));
27 | return;
28 | }
29 |
30 | try {
31 | // Default Fallback Banner
32 | if (member.value == null || member.value.length <= 0) {
33 | member.value = "https://t4.ftcdn.net/jpg/04/46/93/93/360_F_446939375_83iP0UYTg5F9vHl6icZwgrEBHXeXMVaU.jpg";
34 | }
35 |
36 | member.value = escapeHtml(member.value);
37 | serverconfig.groups[member.group].info.banner = member.value;
38 | saveConfig(serverconfig);
39 |
40 | io.emit("updateGroupList");
41 | //io.emit("receiveGroupBanner", member.value); // bug
42 | }
43 | catch (e) {
44 | Logger.error("Couldnt update group banner");
45 | Logger.error(e);
46 | }
47 | }
48 | });
49 | }
50 |
--------------------------------------------------------------------------------
/modules/sockets/updateGroupIcon.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('updateGroupIcon', function (member) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | if (!hasPermission(member.id, "manageGroups")) {
14 | sendMessageToUser(socket.id, JSON.parse(
15 | `{
16 | "title": "Missing permissions!",
17 | "message": "You arent allowed to change the group icon",
18 | "buttons": {
19 | "0": {
20 | "text": "Ok",
21 | "events": ""
22 | }
23 | },
24 | "type": "error",
25 | "popup_type": "confirm"
26 | }`));
27 | return;
28 | }
29 |
30 | try {
31 | if (member.value == null || member.value.length <= 0) {
32 | member.value = "https://wallpapers-clan.com/wp-content/uploads/2022/05/cute-pfp-25.jpg";
33 | }
34 |
35 | member.value = xssFilters.inHTMLData(member.value);
36 | serverconfig.groups[member.group].info.icon = member.value;
37 | saveConfig(serverconfig);
38 |
39 | io.emit("updateGroupList");
40 | }
41 | catch (e) {
42 | Logger.error("Couldnt update group icon");
43 | Logger.error(e);
44 | }
45 | }
46 | });
47 | }
48 |
--------------------------------------------------------------------------------
/modules/sockets/updateGroupName.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, escapeHtml, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('updateGroupName', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true &&
10 | serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | if (!hasPermission(member.id, "manageGroups")) {
14 | sendMessageToUser(socket.id, JSON.parse(
15 | `{
16 | "title": "Missing permissions!",
17 | "message": "You arent allowed to change the group name",
18 | "buttons": {
19 | "0": {
20 | "text": "Ok",
21 | "events": ""
22 | }
23 | },
24 | "type": "error",
25 | "popup_type": "confirm"
26 | }`));
27 | return;
28 | }
29 |
30 | try {
31 | var groupName = xssFilters.inHTMLData(escapeHtml(member.groupName));
32 | var groupDescription = xssFilters.inHTMLData(escapeHtml(member.groupDescription));
33 | var groupId = xssFilters.inHTMLData(escapeHtml(member.groupId));
34 |
35 | if (!groupDescription) {
36 | groupDescription = null;
37 | }
38 |
39 | serverconfig.groups[groupId].info.name = groupName;
40 | serverconfig.groups[groupId].info.description = groupDescription;
41 | saveConfig(serverconfig);
42 |
43 | response({ type: "success", msg: "Group Name Updated" });
44 |
45 | io.emit("updateGroupList");
46 | }
47 | catch (e) {
48 | Logger.error("Couldnt update group name");
49 | Logger.error(e);
50 |
51 | response({ type: "error", msg: "Unable to update group name" });
52 | }
53 | }
54 | });
55 | }
56 |
--------------------------------------------------------------------------------
/modules/sockets/updateGroupPermissions.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import { saveChatMessage } from "../functions/io.mjs";
4 | import Logger from "../functions/logger.mjs";
5 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
6 |
7 | export default (socket) => {
8 | // socket.on code here
9 | socket.on('updateGroupPermissions', function (member, response) {
10 | if (validateMemberId(member.id, socket) == true &&
11 | serverconfig.servermembers[member.id].token == member.token
12 | ) {
13 |
14 | if (!hasPermission(member.id, "manageGroups")) {
15 | sendMessageToUser(socket.id, JSON.parse(
16 | `{
17 | "title": "Missing permissions!",
18 | "message": "You arent allowed to change the group permissions",
19 | "buttons": {
20 | "0": {
21 | "text": "Ok",
22 | "events": ""
23 | }
24 | },
25 | "type": "error",
26 | "popup_type": "confirm"
27 | }`));
28 | return;
29 | }
30 |
31 | try {
32 |
33 | var groupPerms = xssFilters.inHTMLData(member.perms);
34 | var groupId = xssFilters.inHTMLData(member.groupId);
35 | var role = xssFilters.inHTMLData(member.roleId);
36 |
37 | serverconfig.groups[groupId].permissions[role] = groupPerms;
38 | saveConfig(serverconfig);
39 |
40 | io.emit("updateGroupList");
41 | response({ type: "success", msg: "Group Permissions Updated" });
42 |
43 | }
44 | catch (e) {
45 | Logger.error("Couldnt update group permissions");
46 | Logger.error(e);
47 |
48 | response({ type: "error", msg: "Unable to update group permissions" });
49 | }
50 | }
51 | });
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/modules/sockets/updateRoleAppearance.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, usersocket, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('updateRoleAppearance', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | if (hasPermission(member.id, "manageRoles")) {
14 | try {
15 | serverconfig.serverroles[member.roleId].info.name = member.data.info.name;
16 | serverconfig.serverroles[member.roleId].info.color = member.data.info.color;
17 | serverconfig.serverroles[member.roleId].info.displaySeperate = member.data.info.displaySeperate;
18 |
19 | saveConfig(serverconfig);
20 | response({ type: "success", msg: "Role was updated successfully" });
21 |
22 | // Update to everyone and yourself
23 | io.emit("updateMemberList");
24 | io.to(usersocket[member.id]).emit("updateMemberList");
25 | }
26 | catch (e) {
27 | Logger.error("Unable to sort roles");
28 | Logger.error(e);
29 | }
30 | }
31 | else {
32 | response({ type: "error", msg: "denied" });
33 | }
34 | }
35 | });
36 | }
37 |
--------------------------------------------------------------------------------
/modules/sockets/updateRoleHierarchy.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('updateRoleHierarchy', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token
11 | ) {
12 |
13 | if (hasPermission(member.id, "manageRoles")) {
14 | try {
15 | var sortedRoles = member.sorted.reverse();
16 |
17 | for (let i = 0; i < sortedRoles.length; i++) {
18 | var roleId = sortedRoles[i];
19 | serverconfig.serverroles[roleId].info.sortId = i;
20 | }
21 |
22 | saveConfig(serverconfig);
23 | response({ type: "success", msg: "Role was updated successfully" });
24 | }
25 | catch (e) {
26 | Logger.error("Unable to sort roles");
27 | Logger.error(e);
28 | }
29 | }
30 | else {
31 | response({ type: "error", msg: "denied" });
32 | }
33 | }
34 | });
35 | }
36 |
--------------------------------------------------------------------------------
/modules/sockets/updateServerDesc.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, escapeHtml, limitString, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 |
9 | socket.on('updateServerDesc', function (member, response) {
10 | if (validateMemberId(member.id, socket) == true
11 | && serverconfig.servermembers[member.id].token == member.token) {
12 |
13 | if (hasPermission(member.id, "manageServerInfo")) {
14 | Logger.warn(`Changing server description from ${serverconfig.serverinfo.description} to ${escapeHtml(limitString(member.value, 500))}`, "Debug");
15 |
16 | serverconfig.serverinfo.description = escapeHtml(limitString(member.value, 500));
17 | saveConfig(serverconfig);
18 |
19 | response({ type: "success", msg: "Server description was successfully changed" });
20 | }
21 | else {
22 | response({ type: "error", msg: "You cant change the server description: Missing permissions" });
23 | }
24 | }
25 | });
26 | }
27 |
--------------------------------------------------------------------------------
/modules/sockets/updateServerName.mjs:
--------------------------------------------------------------------------------
1 | import { io, saveConfig, serverconfig, xssFilters } from "../../index.mjs";
2 | import { hasPermission } from "../functions/chat/main.mjs";
3 | import Logger from "../functions/logger.mjs";
4 | import { copyObject, escapeHtml, limitString, sendMessageToUser, validateMemberId } from "../functions/main.mjs";
5 |
6 | export default (socket) => {
7 | // socket.on code here
8 | socket.on('updateServerName', function (member, response) {
9 | if (validateMemberId(member.id, socket) == true
10 | && serverconfig.servermembers[member.id].token == member.token) {
11 |
12 | if (hasPermission(member.id, "manageServerInfo")) {
13 | Logger.warn(`Changing servername from ${serverconfig.serverinfo.name} to ${escapeHtml(limitString(member.value, 300))}`);
14 |
15 | serverconfig.serverinfo.name = escapeHtml(limitString(member.value, 200));
16 | saveConfig(serverconfig);
17 |
18 | response({ type: "success", msg: "Server was successfully renamed" });
19 | }
20 | else {
21 | response({ type: "error", msg: "You cant change the server name: Missing permissions" });
22 | }
23 | }
24 | });
25 | }
26 |
--------------------------------------------------------------------------------
/modules/sockets/userLogin.mjs:
--------------------------------------------------------------------------------
1 | import { loginAttempts, serverconfig, xssFilters } from "../../index.mjs";
2 | import { banIp, getNewDate, unbanIp } from "../functions/chat/main.mjs";
3 | import { copyObject, findAndVerifyUser, validateMemberId } from "../functions/main.mjs";
4 |
5 | export default (socket) => {
6 | // socket.on code here
7 | socket.on('userLogin', function (member, response) {
8 | member.id = xssFilters.inHTMLData(member.id)
9 | member.password = xssFilters.inHTMLData(member.password)
10 | member.name = xssFilters.inHTMLData(member.name)
11 | member.duration = 0.1;
12 |
13 | // Handling ip ban
14 | var ip = socket.handshake.address;
15 | if (serverconfig.ipblacklist.hasOwnProperty(ip)) {
16 |
17 | // if the ban has expired, unban them
18 | if (Date.now() > serverconfig.ipblacklist[ip]) {
19 | unbanIp(socket)
20 | }
21 | }
22 |
23 |
24 | // initiate login counter
25 | if (!loginAttempts.hasOwnProperty(ip)) {
26 | loginAttempts.push(ip);
27 | loginAttempts[ip] = 0;
28 | }
29 |
30 | // increase login counter
31 | loginAttempts[ip]++;
32 |
33 | // if count exceeded, temporarily ban ip and clean up
34 | if (loginAttempts[ip] > serverconfig.serverinfo.login.maxLoginAttempts) {
35 | banIp(socket, getNewDate(serverconfig.serverinfo.moderation.bans.ipBanDuration).getTime());
36 | delete loginAttempts[ip];
37 |
38 | response({ error: "You've been temporarily banned. Please try again later" })
39 | socket.disconnect();
40 | return;
41 | }
42 |
43 | let loginCheck = findAndVerifyUser(member.loginName, member.password);
44 |
45 | if (loginCheck.result == true) {
46 | response({ error: null, member: loginCheck.member })
47 |
48 | }
49 | else if (loginCheck.result == false) {
50 | response({ error: "Invalid login" })
51 | }
52 | else {
53 | response({ error: "Account not found" })
54 | }
55 | });
56 | }
57 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dcts",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.mjs",
6 | "type": "module",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "author": "",
11 | "license": "",
12 | "dependencies": {
13 | "bcrypt": "^5.1.1",
14 | "colors": "^1.4.0",
15 | "crypto": "^1.0.1",
16 | "express": "^4.18.2",
17 | "file-type": "^18.2.1",
18 | "form-data": "^4.0.0",
19 | "fs-extra": "^11.2.0",
20 | "get-folder-size": "^2.0.0",
21 | "install": "^0.13.0",
22 | "mysql2": "^3.10.2",
23 | "node": "^19.8.1",
24 | "node-fetch": "^2.6.9",
25 | "request": "^2.88.2",
26 | "sanitize-html": "^2.13.0",
27 | "socket.io": "^4.6.1",
28 | "sqlstring": "^2.3.3",
29 | "uuid": "^9.0.0",
30 | "xhr2": "^0.2.1",
31 | "xss-filters": "^1.2.7"
32 | },
33 | "devDependencies": {
34 | "typescript": "^5.5.2"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/public/.idea/.name:
--------------------------------------------------------------------------------
1 | index.html
--------------------------------------------------------------------------------
/public/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/public/.idea/public.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/public/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/public/audioplayer/audioplayer.css:
--------------------------------------------------------------------------------
1 | .audio-player {
2 | float: left;
3 | width: auto;
4 | margin: 20px auto;
5 | margin-top: 0;
6 | padding: 10px;
7 | border: 2px solid #333;
8 | border-radius: 10px;
9 | background-color: #202225;
10 | text-align: center;
11 | }
12 |
13 | .audio-info {
14 | margin-bottom: 16px;
15 | font-weight: bold;
16 | color: lightgray;
17 | text-align: left;
18 | }
19 |
20 | .controls {
21 | display: flex;
22 | align-items: center;
23 | justify-content: space-between;
24 | }
25 |
26 | button {
27 | padding: 5px 10px;
28 | margin: 0px 10px;
29 | border: none;
30 | border-radius: 5px;
31 | background-color: #333;
32 | color: #fff;
33 | cursor: pointer;
34 | }
35 |
36 | button:hover {
37 | background-color: #555;
38 | }
39 |
40 | input[type="range"] {
41 | margin: 0 10px;
42 | }
--------------------------------------------------------------------------------
/public/css/channeltree.css:
--------------------------------------------------------------------------------
1 | #serverbanner-container {
2 | height: calc(200px - 40px);
3 | width: calc(100%);
4 | background-color: transparent;
5 | margin: 0 0 20px 0;
6 |
7 | display: block;
8 | float: left;
9 |
10 |
11 | overflow: hidden;
12 | box-shadow: 0 8px 8px -2px black;
13 | }
14 |
15 | #serverbanner-image {
16 | height: calc(100%);
17 | width: calc(100%);
18 | -webkit-transition: transform .5s ease;
19 |
20 | background-repeat: no-repeat;
21 | background-attachment: fixed;
22 | background-size: 100% 100%;
23 |
24 | border-radius: 6px;
25 |
26 | }
27 |
28 | #serverbanner-image:hover {
29 | -webkit-transform: scale(1.1);
30 | -moz-transform: scale(1.1);
31 | -o-transform: scale(1.1);
32 | transform: scale(1.1);
33 |
34 |
35 | }
36 |
37 | #serverbanner-image:not(:hover) {
38 | -webkit-transform: scale(1);
39 | -moz-transform: scale(1);
40 | -o-transform: scale(1);
41 | transform: scale(1);
42 | }
43 |
44 | #channellist {
45 | height: calc(100% - 40px - 50px);
46 | width: calc(300px);
47 |
48 | background-color: #24292E;
49 | color: white;
50 |
51 | display: block;
52 | float: left;
53 | }
54 |
55 | #channeltree {
56 | display: block;
57 | float: left;
58 |
59 | height: calc(100% - 32px - 175px - 32px);
60 | width: calc(100% - 32px);
61 |
62 | padding: 16px;
63 | overflow-y: auto;
64 | }
65 |
66 | #channeltree details ul li {
67 | margin-left: 25px;
68 | /* list-style-image: url("img/hashtag.png"); */
69 | }
--------------------------------------------------------------------------------
/public/css/emoji-autocomplete.css:
--------------------------------------------------------------------------------
1 | #emoji-suggestions .emoji-suggestion-entry:hover {
2 | transition: all 150ms;
3 | background-color: #30363c;
4 | }
5 |
6 | #emoji-suggestions .emoji-suggestion-entry:not(:hover) {
7 | transition: all 150ms;
8 | background-color: #24292E;
9 | }
--------------------------------------------------------------------------------
/public/css/groups/groupHomeDisplay.css:
--------------------------------------------------------------------------------
1 | #homeScreenGroupContainer {
2 | float: left;
3 | width: calc(100% - 64px);
4 | overflow-y: auto;
5 | overflow-x: hidden;
6 | padding: 32px;
7 | }
8 |
9 | #homeGroupStatsMostActiveUserContainer {
10 | float: left;
11 | max-height: 320px;
12 | width: 100%;
13 | overflow-y: auto;
14 | overflow-x: hidden;
15 |
16 | display: flex; /* Use flexbox for better layout */
17 | flex-wrap: wrap; /* Allows items to wrap if not enough space */
18 | gap: 8px; /* Spacing between items */
19 | align-content: flex-start; /* Ensures proper alignment */
20 | }
21 |
22 | .activeUserEntry {
23 | background-color: #24292E;
24 | border-radius: 8px;
25 | cursor: pointer;
26 |
27 | float: none; /* Remove float to use flexbox properly */
28 | flex: 1 1 calc(33.33% - 16px); /* Allows 3 per row, wraps on smaller screens */
29 | min-width: 180px; /* Prevents shrinking too small */
30 | max-width: 250px; /* Prevents items from stretching too wide */
31 |
32 | margin: 8px;
33 | padding: 2px 16px;
34 | text-align: center;
35 | }
36 |
37 | #activeUserTableList {
38 | width: 100%;
39 | }
40 |
--------------------------------------------------------------------------------
/public/css/themes/default.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/css/themes/default.css
--------------------------------------------------------------------------------
/public/emojis/emoji_109468018712_confusedlol.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/emojis/emoji_109468018712_confusedlol.webp
--------------------------------------------------------------------------------
/public/emojis/emoji_123503693162_nice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/emojis/emoji_123503693162_nice.png
--------------------------------------------------------------------------------
/public/emojis/emoji_140051899224_chuchu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/emojis/emoji_140051899224_chuchu.jpg
--------------------------------------------------------------------------------
/public/emojis/emoji_152067959921_stare.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/emojis/emoji_152067959921_stare.jpg
--------------------------------------------------------------------------------
/public/emojis/emoji_171207581436_catto.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/emojis/emoji_171207581436_catto.gif
--------------------------------------------------------------------------------
/public/highlight.css:
--------------------------------------------------------------------------------
1 | /* Customize the highlight.js styles for a dark background */
2 | .hljs {
3 | display: block !important;
4 | overflow-x: auto !important;
5 | background: #2b2b2b !important; /* Dark background */
6 | color: #f8f8f2 !important; /* Light text color */
7 | padding: 10px !important;
8 | border-radius: 5px !important;
9 | }
10 | .hljs-comment,
11 | .hljs-quote {
12 | color: #3cc969 !important; /* Comment color */
13 | }
14 | .hljs-keyword,
15 | .hljs-selector-tag,
16 | .hljs-subst {
17 | color: #3cb2cf !important; /* Keyword color */
18 | }
19 | .hljs-literal,
20 | .hljs-number,
21 | .hljs-tag .hljs-attr {
22 | color: #ae81ff !important; /* Literal color */
23 | }
24 | .hljs-string,
25 | .hljs-doctag {
26 | color: #C39178 !important; /* String color */
27 | }
28 | .hljs-title,
29 | .hljs-section,
30 | .hljs-name {
31 | color: #D6DCAA !important; /* Title color */
32 | }
33 | .hljs-type,
34 | .hljs-class .hljs-title {
35 | color: #a6e22e !important; /* Type color */
36 | }
37 | .hljs-tag,
38 | .hljs-variable,
39 | .hljs-template-variable,
40 | .hljs-regexp,
41 | .hljs-link,
42 | .hljs-selector-id,
43 | .hljs-selector-class {
44 | color: #f8f8f2 !important; /* Other syntax elements color */
45 | }
46 | .hljs-built_in,
47 | .hljs-builtin-name {
48 | color: #66d9ef !important; /* Built-in color */
49 | }
50 | .hljs-meta {
51 | color: #f8f8f2 !important; /* Meta color */
52 | }
53 | .hljs-emphasis {
54 | font-style: italic !important; /* Emphasis style */
55 | }
56 | .hljs-strong {
57 | font-weight: bold !important; /* Strong style */
58 | }
59 |
60 | .ql-syntax {
61 | background-color: #1F1F1F !important; /* Match the dark background */
62 | color: #f8f8f2 !important; /* Match the light text color */
63 | padding: 10px !important;
64 | border-radius: 3px !important;
65 |
66 | font-size: 14px !important;
67 | display: block;
68 | float: left;
69 | width: calc(100%);
70 | overflow-x: auto;
71 |
72 | }
--------------------------------------------------------------------------------
/public/img/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/back.png
--------------------------------------------------------------------------------
/public/img/broken.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/broken.jpg
--------------------------------------------------------------------------------
/public/img/default_banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/default_banner.png
--------------------------------------------------------------------------------
/public/img/default_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/default_icon.png
--------------------------------------------------------------------------------
/public/img/default_pfp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/default_pfp.png
--------------------------------------------------------------------------------
/public/img/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/delete.png
--------------------------------------------------------------------------------
/public/img/down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/down.png
--------------------------------------------------------------------------------
/public/img/emoji.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/emoji.png
--------------------------------------------------------------------------------
/public/img/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/error.png
--------------------------------------------------------------------------------
/public/img/error_banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/error_banner.png
--------------------------------------------------------------------------------
/public/img/hashtag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/hashtag.png
--------------------------------------------------------------------------------
/public/img/info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/info.png
--------------------------------------------------------------------------------
/public/img/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/loading.gif
--------------------------------------------------------------------------------
/public/img/sandwich.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/sandwich.png
--------------------------------------------------------------------------------
/public/img/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/save.png
--------------------------------------------------------------------------------
/public/img/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/settings.png
--------------------------------------------------------------------------------
/public/img/success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/success.png
--------------------------------------------------------------------------------
/public/img/up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/img/up.png
--------------------------------------------------------------------------------
/public/js/core/ChatManager.js:
--------------------------------------------------------------------------------
1 | class ChatManager{
2 | static async checkConnection(delay) {
3 | if (initConnectionCheck == false) {
4 |
5 | if (socket.connected == true) {
6 | if (connectionAttempts > 3) {
7 | showSystemMessage({
8 | title: "Connected!",
9 | text: "",
10 | icon: "info",
11 | img: null,
12 | type: "success",
13 | duration: 4000,
14 | onClick: () => {
15 | showSystemMessage({
16 | title: "shydevil",
17 | text: "hey what ya think about this image as profile banner?",
18 | icon: "/uploads/upload_146216404639_bloody-makima-thumb.jpg",
19 | img: "https://i.pinimg.com/originals/88/20/ff/8820ff7553baaf595822b58c5590b604.jpg",
20 | type: "neutral",
21 | duration: 4000,
22 | });
23 | }
24 | });
25 | }
26 | initConnectionCheck = true;
27 | }
28 | else {
29 |
30 | if (connectionAttempts > 3) {
31 | showSystemMessage({
32 | title: "Connecting..",
33 | text: "",
34 | icon: "info",
35 | img: null,
36 | type: "neutral",
37 | duration: 1000
38 | });
39 | }
40 |
41 | connectionAttempts++;
42 | }
43 | }
44 | else {
45 | if (socket.connected == false && initConnectionCheck == true) {
46 | disconnected = true;
47 | showSystemMessage({
48 | title: "Connection Lost",
49 | text: "",
50 | icon: "error",
51 | img: null,
52 | type: "error",
53 | duration: 1000
54 | });
55 | }
56 | else if (socket.connected == true && initConnectionCheck == true && disconnected == true) {
57 | disconnected = false;
58 | showSystemMessage({
59 | title: "Successfully reconnected!",
60 | text: "Refreshing data...",
61 | icon: "info",
62 | img: null,
63 | type: "success",
64 | duration: 2000
65 | });
66 | setTimeout(() => window.location.reload(), 2000)
67 | }
68 | }
69 |
70 |
71 |
72 | setTimeout(() => ChatManager.checkConnection(delay), delay)
73 | }
74 | }
--------------------------------------------------------------------------------
/public/js/core/CookieManager.js:
--------------------------------------------------------------------------------
1 | /*
2 | Author: HackTheDev
3 | */
4 | class CookieManager {
5 | static setCookie(name, value, days = 365) {
6 | var expires = "";
7 | if (days) {
8 | var date = new Date();
9 | date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
10 | expires = "; expires=" + date.toUTCString();
11 | }
12 | document.cookie = name + "=" + (value || "") + expires + "; path=/";
13 | }
14 | static getCookie(name) {
15 | var nameEQ = name + "=";
16 | var ca = document.cookie.split(';');
17 | for (var i = 0; i < ca.length; i++) {
18 | var c = ca[i];
19 | while (c.charAt(0) == ' ') c = c.substring(1, c.length);
20 | if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
21 | }
22 | return null;
23 | }
24 | static eraseCookie(name) {
25 | document.cookie = name + '=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
26 | }
27 |
28 | static exportCookies() {
29 | var cookieData = document.cookie.split(';').map(function (c) {
30 | var i = c.indexOf('=');
31 | return [c.substring(0, i), c.substring(i + 1)];
32 | });
33 |
34 | copy(JSON.stringify(JSON.stringify(cookieData)));
35 | }
36 |
37 | static importCookies(data) {
38 | var cookieData = JSON.parse(data);
39 | cookieData.forEach(function (arr) {
40 | document.cookie = arr[0] + '=' + arr[1];
41 | });
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/public/js/core/UserReports.js:
--------------------------------------------------------------------------------
1 | class UserReports {
2 | static reportMessage(messageId) {
3 |
4 | messageId = messageId.replace("msg-", "");
5 | messageId = parseInt(messageId)
6 |
7 | if (typeof (messageId) !== "number") {
8 | console.log({ error: "Parameter messageId is not a number" })
9 | return;
10 | }
11 |
12 | customPrompts.showPrompt(
13 | "Report Message",
14 | `
15 |
16 | Report Description
17 |
18 |
19 | `,
20 | (values) => {
21 | socket.emit("createReport", {
22 | id: UserManager.getID(),
23 | token: UserManager.getToken(),
24 | targetId: messageId,
25 | type: "message",
26 | description: values.reportDescription
27 | }, function (response) {
28 |
29 | showSystemMessage({
30 | title: response.msg,
31 | text: "",
32 | icon: response.type,
33 | img: null,
34 | type: response.type,
35 | duration: 2000
36 | });
37 | });
38 | },
39 | ["Report", "error"],
40 | false,
41 | 250
42 | );
43 | }
44 |
45 | static getReports() {
46 | socket.emit("fetchReports", {
47 | id: UserManager.getID(),
48 | token: UserManager.getToken()
49 | }, function (response) {
50 |
51 | try {
52 | if (response.type == "success") {
53 | let reports = response.reports;
54 | ModView.showReports(reports)
55 | }
56 | }
57 | catch (error) {
58 | console.log(error)
59 | }
60 | });
61 | }
62 | }
--------------------------------------------------------------------------------
/public/js/core/template.js:
--------------------------------------------------------------------------------
1 | document.addEventListener("DOMContentLoaded", function () {
2 | (function () {
3 | // your code here
4 | })();
5 | })
--------------------------------------------------------------------------------
/public/js/tooltips/dialogs/banUser.js:
--------------------------------------------------------------------------------
1 | function banUserTooltip(){
2 | tooltipSystem.showTooltip(
3 | document.getElementById('tt_banUserDialog_banReason'), // The target element
4 | 'tt_banUserDialog_banReason', // Unique ID for this tooltip
5 | `[Optional Field]
6 | You can specify a ban reason and it will be displayed to the user. To not show anything, keep this field empty as its optional.`, // Tooltip message
7 | 'Next', // Button text (optional)
8 | () => {
9 | //What should happen after the button press?
10 | tooltipSystem.showTooltip(
11 | document.getElementById('tt_banUserDialog_banDurationNumber'),
12 | 'tt_banUserDialog_banDurationNumber',
13 | `Here you need to input a number. For example "4". In the next field you can select the duration type.`,
14 | 'Next',
15 | () => {
16 | tooltipSystem.showTooltip(
17 | document.getElementById('tt_banUserDialog_banDurationType'),
18 | 'tt_banUserDialog_banDurationType',
19 | 'Here you can select the duration of the ban, like minutes, weeks, months or permanent.',
20 | 'Got it!'
21 | );
22 | }
23 | );
24 | }
25 | );
26 | }
--------------------------------------------------------------------------------
/public/js/tooltips/dialogs/createChannel.js:
--------------------------------------------------------------------------------
1 | function createChannelTooltip(){
2 | tooltipSystem.showTooltip(
3 | document.getElementById('tt_channelCreateDialog_channelName'), // The target element
4 | 'tt_channelCreateDialog_channelName', // Unique ID for this tooltip
5 | 'Enter your channel name here.', // Tooltip message
6 | 'Next', // Button text (optional)
7 | () => {
8 | tooltipSystem.showTooltip(
9 | document.getElementById('tt_channelCreateDialog_channelType'),
10 | 'tt_channelCreateDialog_channelType',
11 | 'Select the type of channel you want to create',
12 | 'Next',
13 | () => {
14 | tooltipSystem.showTooltip(
15 | document.getElementById('promptsSubmitButton'),
16 | 'tt_channelCreateDialog_chanelSubmit',
17 | 'Click to create the channel!',
18 | 'Got it!'
19 | );
20 | }
21 | );
22 | } // Callback when button is clicked (optional)
23 | );
24 | }
--------------------------------------------------------------------------------
/public/js/tooltips/dialogs/muteUser.js:
--------------------------------------------------------------------------------
1 | function muteUserTooltip(){
2 | tooltipSystem.showTooltip(
3 | document.getElementById('tt_muteUserDialog_muteReason'), // The target element
4 | 'tt_muteUserDialog_muteReason', // Unique ID for this tooltip
5 | `[Optional Field]
6 | You can specify a mute reason and it will be displayed to the user. To not show anything, keep this field empty as its optional.`, // Tooltip message
7 | 'Next', // Button text (optional)
8 | () => {
9 | //What should happen after the button press?
10 | tooltipSystem.showTooltip(
11 | document.getElementById('tt_muteUserDialog_muteDurationNumber'),
12 | 'tt_muteUserDialog_muteDurationNumber',
13 | `Here you need to input a number. For example "10". In the next field you can select the duration type.`,
14 | 'Next',
15 | () => {
16 | tooltipSystem.showTooltip(
17 | document.getElementById('tt_muteUserDialog_muteDurationType'),
18 | 'tt_muteUserDialog_muteDurationType',
19 | 'Here you can select the duration of the mute, like minutes, weeks, months or permanent.',
20 | 'Got it!'
21 | );
22 | }
23 | );
24 | }
25 | );
26 | }
--------------------------------------------------------------------------------
/public/plugins/loader.js:
--------------------------------------------------------------------------------
1 | function loadPlugins(){
2 | socket.emit("getPluginList", {id: UserManager.getID(), token: UserManager.getToken()}, function (response) {
3 | Object.keys(response.plugins).forEach(function(plugin) {
4 | let pluginObj = response.plugins[plugin];
5 |
6 | for(let i = 0; i < pluginObj.filePaths.length; i++){
7 | let file = pluginObj.filePaths[i];
8 |
9 | if(file.includes(`${plugin}\\main.js`)){
10 | loadScript(file);
11 | }
12 | }
13 | });
14 | });
15 | }
16 |
17 | function loadScript(url, callback) {
18 | const script = document.createElement('script');
19 | script.type = 'text/javascript';
20 | script.src = url;
21 |
22 | script.onload = function() {
23 | console.log(`Plugin loaded: ${url}`);
24 | if (callback) callback();
25 | };
26 |
27 | script.onerror = function() {
28 | console.error(`Failed to load Plugin: ${url}`);
29 | };
30 |
31 | document.head.appendChild(script);
32 | }
--------------------------------------------------------------------------------
/public/settings/account/settings.js:
--------------------------------------------------------------------------------
1 | console.log("%c" + "WAIT!", "color: #FF0000; -webkit-text-stroke: 2px black; font-size: 72px; font-weight: bold;");
2 | console.log("%c" + "People can use the console to steal your account xo !", "color: #FF0000; -webkit-text-stroke: 0px black; font-size: 20px; font-weight: bold;");
3 |
4 | // IMPORTANT! By default, socket.io() connects to the host that
5 | // served the page, so we dont have to pass the server url
6 | var socket = io.connect();
7 |
8 | socket.emit("userConnected", {
9 | id: UserManager.getID(), name: UserManager.getUsername(), icon: UserManager.getPFP(), status: UserManager.getStatus(), token: UserManager.getToken(),
10 | aboutme: UserManager.getAboutme(), banner: UserManager.getBanner()
11 | }, function (response) {
12 |
13 | });
14 |
15 |
16 | var page = getUrlParams("page") || "profile";
17 | loadPageContent(page)
18 |
19 | async function loadPageContent(page) {
20 |
21 | if(!page){
22 | console.log("No page specified")
23 | return;
24 | }
25 |
26 | try {
27 | // Attach CSS
28 | const head = document.head;
29 | const link = document.createElement("link");
30 | link.rel = "stylesheet";
31 | link.href = `page/${page}/${page}.css`;
32 | head.appendChild(link);
33 |
34 | // Load HTML content
35 | const response = await fetch(`page/${page}/${page}.html`);
36 | if (!response.ok) throw new Error(`Failed to load HTML for ${page}`);
37 | const html = await response.text();
38 | document.getElementById("content").innerHTML = html;
39 |
40 | // Load JS after HTML is loaded
41 | const script = document.createElement("script");
42 | script.src = `page/${page}/${page}.js`;
43 | script.onload = () => console.log(`${page}.js loaded successfully`);
44 | script.onerror = () => console.error(`Failed to load ${page}.js`);
45 | document.body.appendChild(script);
46 | } catch (error) {
47 | console.error("Error loading page content:", error);
48 | document.getElementById("content").innerHTML = "Failed to load content.
";
49 | }
50 | }
51 |
52 | function setUrl(param){
53 | window.history.replaceState(null, null, param); // or pushState
54 | let page = param.replace("?page=", "");
55 | loadPageContent(page)
56 | }
57 |
58 | function getUrlParams(param){
59 | var url = window.location.search;
60 | var urlParams = new URLSearchParams(url);
61 | var urlChannel = urlParams.get(param);
62 |
63 | return urlChannel;
64 | }
65 |
--------------------------------------------------------------------------------
/public/settings/channel/page/channel-info/channel-info.html:
--------------------------------------------------------------------------------
1 | Channel Info
2 |
3 |
4 |
Settings
5 |
6 |
7 | Channel Name
8 |
9 |
10 |
11 |
Save
12 |
13 |
--------------------------------------------------------------------------------
/public/settings/channel/page/channel-info/channel-info.js:
--------------------------------------------------------------------------------
1 | var channelname = document.getElementById("channel_name");
2 | var saveButton = document.getElementById("settings_channel_save");
3 |
4 | var serverconfigName;
5 | var editChannel = {};
6 |
7 | socket.emit("userConnected", { id: getID(), name: getUsername(), icon: getPFP(), status: getStatus(), token: getToken(),
8 | aboutme: getAboutme(), banner: getBanner()});
9 |
10 |
11 | socket.emit("getChannelInfo", {id: getID(), token: getToken(), channel: getUrlParams("id").replace("channel-", "")}, function (response) {
12 | try{
13 |
14 | console.log(response)
15 | channelname = document.getElementById("channel_name");
16 | saveButton = document.getElementById("settings_channel_save");
17 |
18 | serverconfigName = response.data.name;
19 | channelname.value = serverconfigName;
20 | editChannel = response;
21 |
22 | console.log(response);
23 | }
24 | catch(err){
25 | console.log("Unable to get Channel Information");
26 | console.log(err);
27 |
28 | alert("Unable to get channel info. Please try to reload slowly until it works. Known bug!");
29 | }
30 |
31 | });
32 |
33 |
34 | function getToken(){
35 | var token = getCookie("token");
36 |
37 | if(token == null || token.length <= 0){
38 | return null;
39 | }
40 | else{
41 | return token;
42 | }
43 | }
44 |
45 | function getID(){
46 | var id = getCookie("id");
47 |
48 | if(id == null || id.length != 12){
49 | id = generateId(12);
50 | setCookie("id", id, 360);
51 | return id;
52 | }
53 | else{
54 | return id;
55 | }
56 | }
57 | function updatePreview(){
58 |
59 | try{
60 |
61 | // Username
62 | if(channel_name.value != serverconfigName
63 | ){
64 | console.log("NOt same");
65 | saveButton.style.display = "block";
66 | }
67 | else{
68 | console.log("same");
69 | saveButton.style.display = "none";
70 | }
71 | }
72 | catch(e){
73 | console.log(e);
74 | }
75 |
76 | }
77 |
78 |
79 | function saveSettings(){
80 | try{
81 | if(channelname.value != null && channelname.value.length > 0 && channelname.value != serverconfigName){
82 | socket.emit("updateChannelName", {id:getID(), token: getToken(), channel: getUrlParams("id").split("-")[1], name: channelname.value }, function (response) {
83 | console.log(response);
84 |
85 | alert(response.msg);
86 | });
87 | }
88 |
89 | saveButton.style.display = "none";
90 | }
91 | catch(error){
92 | alert("Error while trying to save settings: " + error);
93 | return;
94 | }
95 | }
--------------------------------------------------------------------------------
/public/settings/group/page/group-info/group-info.html:
--------------------------------------------------------------------------------
1 | Channel Info
2 |
3 |
4 |
Settings
5 |
6 |
7 | Channel Name
8 |
9 |
10 |
11 |
Save
12 |
13 |
--------------------------------------------------------------------------------
/public/settings/server/page/about/about.css:
--------------------------------------------------------------------------------
1 | .profile_headline{
2 | text-transform: uppercase;
3 | margin: 0 0 8px 0;
4 | font-size: 14px;
5 | font-weight: bold;
6 | }
7 |
8 | #profile_change_container a{
9 | color: #ABB8BB;
10 | }
11 |
12 | #settings_profile_save {
13 | margin: 20px 0 0 0;
14 | padding: 2px 4px 2px 4px;
15 |
16 | border: 1px solid transparent;
17 | border-radius: 6px;
18 |
19 | background-color: #ABB8BE;
20 | color: black;
21 | text-align: center;
22 | width: 20%;
23 | }
24 |
25 | input[type=cehckbox]{
26 | float: left;
27 | display: inline-block;
28 | }
29 |
30 | input[type=text], input[type=password], input[type=number] {
31 | color: #ABB8BE;
32 | background-color: #292B2F;
33 | outline: none;
34 | padding: 4px 8px 4px 8px;
35 |
36 | margin: 4px 0 0 0;
37 |
38 | border-radius: 6px;
39 | border: 1px solid transparent;
40 | resize: none;
41 | }
42 |
43 | .profile_input_container {
44 | margin: 32px 0 32px 0 !important;
45 | }
--------------------------------------------------------------------------------
/public/settings/server/page/about/about.html:
--------------------------------------------------------------------------------
1 | About
2 |
3 |
4 |
5 |
6 |
7 |
8 |
30 |
31 |
32 |
33 |
41 |
42 |
43 |
44 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/public/settings/server/page/about/about.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/settings/server/page/about/about.js
--------------------------------------------------------------------------------
/public/settings/server/page/banlist/banlist.html:
--------------------------------------------------------------------------------
1 | Banlist
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/public/settings/server/page/channeltree-sorting/channeltree-sorting.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Channel Sorting
6 | Groups
7 |
8 |
10 | Save updates
11 |
12 |
13 |
15 | Cancel updates
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
Group Info
25 |
26 |
27 | Group ID
28 |
29 |
30 |
31 |
32 | Role Name
33 |
34 |
35 |
36 |
37 |
38 |
39 |
41 | Save updates
42 |
43 |
44 |
46 | Cancel updates
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
56 | Save updates
57 |
58 |
59 |
61 | Cancel updates
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/public/settings/server/page/easter/easter.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/settings/server/page/easter/easter.css
--------------------------------------------------------------------------------
/public/settings/server/page/emojis/emojis.css:
--------------------------------------------------------------------------------
1 | #profile_container{
2 | padding: 4px;
3 |
4 | width: calc(300px - 8px);
5 | height: auto;
6 | border-radius: 8px;
7 |
8 | background-color: #202225;
9 | color: #ABB8BE;
10 | }
11 |
12 | .profile_headline{
13 | text-transform: uppercase;
14 | margin: 0 0 8px 0;
15 | font-size: 14px;
16 | font-weight: bold;
17 | }
18 |
19 |
20 | #profile_change_container {
21 | float: left;
22 | display: block;
23 |
24 | margin: 0 60px 0 0;
25 | }
26 |
27 |
28 | .profile_input_container {
29 | margin: 0 0 20px 0;
30 | }
31 |
32 |
33 | #settings_profile_save {
34 | margin: 20px 0 0 0;
35 | padding: 2px 4px 2px 4px;
36 |
37 | border: 1px solid transparent;
38 | border-radius: 6px;
39 |
40 | background-color: #ABB8BE;
41 | color: black;
42 | text-align: center;
43 | width: 100%;
44 | }
45 |
46 | .emoji-entry {
47 | float: left;
48 | display: block;
49 | margin: 24px 0 0 0;
50 | width: 100%;
51 | }
52 |
53 | .emoji-img {
54 | float: left;
55 | margin: 0px 4px 0px 0px;
56 | }
57 |
58 | .emoji-img img{
59 | width: 50px;
60 | height: 50px;
61 | }
62 |
63 | .emoji-actions {
64 | margin: 0 0 0 15px;
65 | float: left;
66 | display: inline;
67 | }
68 |
69 | .emoji-action-icon {
70 | margin: 8px 0 0 0 ;
71 | width: 35px;
72 | height: 35px;
73 | float: left;
74 | }
75 |
76 | .emoji-name input[type=text]{
77 | margin: 15px 0 0 20px;
78 |
79 | width: calc(20%);
80 |
81 | float: left;
82 | display: inline-block;
83 | vertical-align: center;
84 |
85 | background-color: #292B2F;
86 | color: #ABB8BE;
87 | outline: none;
88 |
89 | border: 1px solid #70787b;
90 | border-radius: 4px;
91 |
92 | padding: 4px 8px 4px 8px;
93 | }
94 |
95 | #emoji-container {
96 | margin-bottom: 64px !important;
97 | }
--------------------------------------------------------------------------------
/public/settings/server/page/emojis/emojis.html:
--------------------------------------------------------------------------------
1 | Emojis
2 |
3 |
4 |
5 |
6 |
7 |
8 |
Upload Emoji
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/public/settings/server/page/file-uploads/file-uploads.css:
--------------------------------------------------------------------------------
1 | .profile_headline{
2 | text-transform: uppercase;
3 | margin: 0 0 8px 0;
4 | font-size: 14px;
5 | font-weight: bold;
6 | }
7 |
8 |
9 | #settings_profile_save {
10 | margin: 20px 0 0 0;
11 | padding: 2px 4px 2px 4px;
12 |
13 | border: 1px solid transparent;
14 | border-radius: 6px;
15 |
16 | background-color: #ABB8BE;
17 | color: black;
18 | text-align: center;
19 | width: 100%;
20 | }
21 |
22 | input[type=cehckbox]{
23 | float: left;
24 | display: inline-block;
25 | }
26 |
27 | input[type=text], input[type=password], input[type=number] {
28 | color: #ABB8BE;
29 | background-color: #292B2F;
30 | outline: none;
31 | padding: 4px 8px 4px 8px;
32 |
33 | margin: 4px 0 0 0;
34 |
35 | border-radius: 6px;
36 | border: 1px solid transparent;
37 | resize: none;
38 | }
39 |
40 | .profile_input_container {
41 | margin: 32px 0 32px 0 !important;
42 | }
--------------------------------------------------------------------------------
/public/settings/server/page/file-uploads/file-uploads.html:
--------------------------------------------------------------------------------
1 | File Uploads
2 |
3 |
4 |
Local File Upload
5 |
6 |
7 |
14 |
15 |
16 |
Cloudflare Image CDN
17 |
18 |
45 |
46 |
47 |
48 |
49 |
Save
50 |
51 |
--------------------------------------------------------------------------------
/public/settings/server/page/planned-features/planned-features.css:
--------------------------------------------------------------------------------
1 | .profile_headline{
2 | text-transform: uppercase;
3 | margin: 0 0 8px 0;
4 | font-size: 14px;
5 | font-weight: bold;
6 | }
7 |
8 |
9 | #settings_profile_save {
10 | margin: 20px 0 0 0;
11 | padding: 2px 4px 2px 4px;
12 |
13 | border: 1px solid transparent;
14 | border-radius: 6px;
15 |
16 | background-color: #ABB8BE;
17 | color: black;
18 | text-align: center;
19 | width: 20%;
20 | }
21 |
22 | input[type=cehckbox]{
23 | float: left;
24 | display: inline-block;
25 | }
26 |
27 | input[type=text], input[type=password], input[type=number] {
28 | color: #ABB8BE;
29 | background-color: #292B2F;
30 | outline: none;
31 | padding: 4px 8px 4px 8px;
32 |
33 | margin: 4px 0 0 0;
34 |
35 | border-radius: 6px;
36 | border: 1px solid transparent;
37 | resize: none;
38 | }
39 |
40 | .profile_input_container {
41 | margin: 32px 0 32px 0 !important;
42 | }
--------------------------------------------------------------------------------
/public/settings/server/page/planned-features/planned-features.html:
--------------------------------------------------------------------------------
1 | Planned Features
2 |
3 |
11 |
12 |
13 |
14 |
15 |
16 |
35 |
36 |
37 |
38 |
39 |
Save
40 |
41 |
--------------------------------------------------------------------------------
/public/settings/server/page/planned-features/planned-features.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/settings/server/page/planned-features/planned-features.js
--------------------------------------------------------------------------------
/public/settings/server/page/rate-limit/rate-limit.css:
--------------------------------------------------------------------------------
1 | .profile_headline{
2 | text-transform: uppercase;
3 | margin: 0 0 8px 0;
4 | font-size: 14px;
5 | font-weight: bold;
6 | }
7 |
8 |
9 | #settings_profile_save {
10 | margin: 20px 0 0 0;
11 | padding: 2px 4px 2px 4px;
12 |
13 | border: 1px solid transparent;
14 | border-radius: 6px;
15 |
16 | background-color: #ABB8BE;
17 | color: black;
18 | text-align: center;
19 | width: 20%;
20 | }
21 |
22 | input[type=cehckbox]{
23 | float: left;
24 | display: inline-block;
25 | }
26 |
27 | input[type=text], input[type=password], input[type=number] {
28 | color: #ABB8BE;
29 | background-color: #292B2F;
30 | outline: none;
31 | padding: 4px 8px 4px 8px;
32 |
33 | margin: 4px 0 0 0;
34 |
35 | border-radius: 6px;
36 | border: 1px solid transparent;
37 | resize: none;
38 | }
39 |
40 | .profile_input_container {
41 | margin: 32px 0 32px 0 !important;
42 | }
--------------------------------------------------------------------------------
/public/settings/server/page/rate-limit/rate-limit.html:
--------------------------------------------------------------------------------
1 | Rate Limit
2 |
3 |
4 |
Local File Upload
5 |
6 |
7 | Server Rate Limit
8 |
9 |
10 |
11 |
12 |
13 | Rate Limit Drop Interval
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
Save
22 |
23 |
--------------------------------------------------------------------------------
/public/settings/server/page/rate-limit/rate-limit.js:
--------------------------------------------------------------------------------
1 | var setting_rateLimit = document.getElementById("rate-limit");
2 | var setting_dropInterval = document.getElementById("drop-interval");
3 | var saveButton = document.getElementById("settings_profile_save");
4 |
5 | var rateLimit;
6 | var dropInterval;
7 |
8 | var serverconfigName;
9 | var serverconfigDesc;
10 |
11 |
12 | socket.emit("checkPermission", {id: UserManager.getID(), token: UserManager.getToken(), permission: "manageRateLimit" }, function (response) {
13 |
14 | if(response.permission == "denied"){
15 | window.location.href = window.location.origin + "/settings/server";
16 | }
17 | else{
18 | document.getElementById("pagebody").style.display = "block";
19 | }
20 | });
21 |
22 |
23 | socket.emit("getServerInfo", {id: UserManager.getID(), token: UserManager.getToken() }, function (response) {
24 |
25 | console.log(response);
26 | setting_rateLimit = document.getElementById("rate-limit");
27 | setting_dropInterval = document.getElementById("drop-interval");
28 | saveButton = document.getElementById("settings_profile_save");
29 |
30 | rateLimit = response.rateLimit;
31 | dropInterval = response.dropInterval;
32 |
33 | setting_rateLimit.value = rateLimit;
34 | setting_dropInterval.value = dropInterval;
35 | });
36 |
37 | function isChecked(element){
38 | return element.checked ? 1 : 0;
39 | }
40 |
41 | function updatePreview(){
42 |
43 | try{
44 |
45 | // Username
46 | if(setting_rateLimit.value != rateLimit ||
47 | setting_dropInterval.value != dropInterval
48 |
49 | ){
50 | console.log("NOt same");
51 | saveButton.style.display = "block";
52 | }
53 | else{
54 | console.log("same");
55 | saveButton.style.display = "none";
56 | }
57 |
58 | }
59 | catch(e){
60 | console.log(e);
61 | }
62 |
63 | }
64 |
65 |
66 | function saveSettings(){
67 | try{
68 |
69 | socket.emit("saveRateSettings", { id: UserManager.getID(), token: UserManager.getToken(),
70 | newRateLimit: setting_rateLimit.value,
71 | newDropInterval: setting_dropInterval.value
72 | }, function (response) {
73 |
74 | alert(response.msg);
75 | console.log(response);
76 | });
77 | }
78 | catch(error){
79 | alert("Error while trying to save settings: " + error);
80 | return;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/public/settings/server/page/server-info/server-info.html:
--------------------------------------------------------------------------------
1 | Server Info
2 |
3 |
4 |
Settings
5 |
6 |
7 | Server Name
8 |
9 |
10 |
11 |
12 | Server Description
13 |
14 |
15 |
16 |
Save
17 |
18 |
--------------------------------------------------------------------------------
/public/settings/server/page/support/support.css:
--------------------------------------------------------------------------------
1 | .profile_headline{
2 | text-transform: uppercase;
3 | margin: 0 0 8px 0;
4 | font-size: 14px;
5 | font-weight: bold;
6 | }
7 |
8 | #profile_change_container a{
9 | color: #ABB8BB;
10 | }
11 |
12 | #settings_profile_save {
13 | margin: 20px 0 0 0;
14 | padding: 2px 4px 2px 4px;
15 |
16 | border: 1px solid transparent;
17 | border-radius: 6px;
18 |
19 | background-color: #ABB8BE;
20 | color: black;
21 | text-align: center;
22 | width: 20%;
23 | }
24 |
25 | input[type=cehckbox]{
26 | float: left;
27 | display: inline-block;
28 | }
29 |
30 | input[type=text], input[type=password], input[type=number] {
31 | color: #ABB8BE;
32 | background-color: #292B2F;
33 | outline: none;
34 | padding: 4px 8px 4px 8px;
35 |
36 | margin: 4px 0 0 0;
37 |
38 | border-radius: 6px;
39 | border: 1px solid transparent;
40 | resize: none;
41 | }
42 |
43 | .profile_input_container {
44 | margin: 32px 0 32px 0 !important;
45 | }
--------------------------------------------------------------------------------
/public/settings/server/page/support/support.html:
--------------------------------------------------------------------------------
1 | Support
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/public/settings/server/page/support/support.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/settings/server/page/support/support.js
--------------------------------------------------------------------------------
/public/settings/server/page/whats-new/whats-new.css:
--------------------------------------------------------------------------------
1 | .profile_headline{
2 | text-transform: uppercase;
3 | margin: 0 0 8px 0;
4 | font-size: 14px;
5 | font-weight: bold;
6 | }
7 |
8 | .date {
9 | text-decoration: underline;
10 | }
11 |
12 | .feature{
13 | font-weight: bold;
14 | text-decoration: none;
15 |
16 | margin-top: 24px;
17 | }
18 |
19 | .detail {
20 |
21 | }
22 |
23 | .desc {
24 | font-style: italic;
25 | }
26 |
27 | * {
28 | line-height: 150%;
29 | }
30 |
31 | a{
32 | color: #5d7fe3;
33 | }
34 |
35 | code {
36 | padding: 0px 4px 2px 4px;
37 | border: 1.5px solid #5d7fe3;
38 | color: #5d7fe3;
39 | border-radius: 4px;
40 |
41 | margin: -4px 4px 4px 4px !important;
42 | word-break: break-word;
43 | }
44 |
45 | .update{
46 | padding: 12px 32px 12px 12px;
47 | background-color: #333539;
48 |
49 | margin-bottom: 60px !important;
50 | border-radius: 6px;
51 | }
52 |
53 | .update h2 {
54 | margin: 0;
55 | float: left;
56 | }
57 |
58 | label.update {
59 | float: right;
60 | }
61 |
62 | .update .head {
63 | float: left;
64 | width: calc(100%);
65 |
66 | color: #5d7fe3;
67 | }
68 |
69 | .update .head label{
70 | background-color: #5d7fe3;
71 | padding: 6px 12px 6px 12px;
72 |
73 | border-radius: 6px;
74 | color: white;
75 |
76 | margin-bottom: 0px !important;
77 | }
78 |
79 | .update .content {
80 | }
81 |
82 | ul.content ul {
83 | margin-bottom: 32px;
84 | }
85 |
86 | ul.update.current {
87 | --angle: 0deg;
88 | border: 2px solid;
89 | border-image: conic-gradient(from var(--angle), red, yellow, lime, aqua, blue, magenta, red) 1;
90 | animation: 10s rotate linear infinite;
91 | }
--------------------------------------------------------------------------------
/public/settings/server/page/whats-new/whats-new.js:
--------------------------------------------------------------------------------
1 | setupNotify();
--------------------------------------------------------------------------------
/public/sounds/message.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/sounds/message.mp3
--------------------------------------------------------------------------------
/public/sounds/normal.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/public/sounds/normal.mp3
--------------------------------------------------------------------------------
/settings/account/page/profile/profile.html:
--------------------------------------------------------------------------------
1 | Your Profile
2 |
3 |
40 |
41 |
42 |
Preview
43 |
44 |
45 |
46 |
47 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
About Me
67 |
68 |
69 |
70 |
71 |
72 |
Roles
73 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/settings/channel/page/channel-info/channel-info.html:
--------------------------------------------------------------------------------
1 | Channel Info
2 |
3 |
4 |
Settings
5 |
6 |
7 | Channel Name
8 |
9 |
10 |
11 |
Save
12 |
13 |
--------------------------------------------------------------------------------
/settings/channel/page/channel-info/channel-info.js:
--------------------------------------------------------------------------------
1 | var channelname = document.getElementById("channel_name");
2 | var saveButton = document.getElementById("settings_channel_save");
3 |
4 | var serverconfigName;
5 | var editChannel = {};
6 |
7 | socket.emit("userConnected", { id: getID(), name: getUsername(), icon: getPFP(), status: getStatus(), token: getToken(),
8 | aboutme: getAboutme(), banner: getBanner()});
9 |
10 |
11 | socket.emit("getChannelInfo", {id: getID(), token: getToken(), channel: getUrlParams("id").replace("channel-", "")}, function (response) {
12 | try{
13 |
14 | console.log(response)
15 | channelname = document.getElementById("channel_name");
16 | saveButton = document.getElementById("settings_channel_save");
17 |
18 | serverconfigName = response.data.name;
19 | channelname.value = serverconfigName;
20 | editChannel = response;
21 |
22 | console.log(response);
23 | }
24 | catch(err){
25 | console.log("Unable to get Channel Information");
26 | console.log(err);
27 |
28 | alert("Unable to get channel info. Please try to reload slowly until it works. Known bug!");
29 | }
30 |
31 | });
32 |
33 |
34 | function getToken(){
35 | var token = getCookie("token");
36 |
37 | if(token == null || token.length <= 0){
38 | return null;
39 | }
40 | else{
41 | return token;
42 | }
43 | }
44 |
45 | function getID(){
46 | var id = getCookie("id");
47 |
48 | if(id == null || id.length != 12){
49 | id = generateId(12);
50 | setCookie("id", id, 360);
51 | return id;
52 | }
53 | else{
54 | return id;
55 | }
56 | }
57 | function updatePreview(){
58 |
59 | try{
60 |
61 | // Username
62 | if(channel_name.value != serverconfigName
63 | ){
64 | console.log("NOt same");
65 | saveButton.style.display = "block";
66 | }
67 | else{
68 | console.log("same");
69 | saveButton.style.display = "none";
70 | }
71 | }
72 | catch(e){
73 | console.log(e);
74 | }
75 |
76 | }
77 |
78 |
79 | function saveSettings(){
80 | try{
81 | if(channelname.value != null && channelname.value.length > 0 && channelname.value != serverconfigName){
82 | socket.emit("updateChannelName", {id:getID(), token: getToken(), channel: getUrlParams("id").split("-")[1], name: channelname.value }, function (response) {
83 | console.log(response);
84 |
85 | alert(response.msg);
86 | });
87 | }
88 |
89 | saveButton.style.display = "none";
90 | }
91 | catch(error){
92 | alert("Error while trying to save settings: " + error);
93 | return;
94 | }
95 | }
--------------------------------------------------------------------------------
/settings/group/page/group-info/group-info.html:
--------------------------------------------------------------------------------
1 | Channel Info
2 |
3 |
4 |
Settings
5 |
6 |
7 | Channel Name
8 |
9 |
10 |
11 |
Save
12 |
13 |
--------------------------------------------------------------------------------
/settings/server/page/about/about.css:
--------------------------------------------------------------------------------
1 | .profile_headline{
2 | text-transform: uppercase;
3 | margin: 0 0 8px 0;
4 | font-size: 14px;
5 | font-weight: bold;
6 | }
7 |
8 | #profile_change_container a{
9 | color: #ABB8BB;
10 | }
11 |
12 | #settings_profile_save {
13 | margin: 20px 0 0 0;
14 | padding: 2px 4px 2px 4px;
15 |
16 | border: 1px solid transparent;
17 | border-radius: 6px;
18 |
19 | background-color: #ABB8BE;
20 | color: black;
21 | text-align: center;
22 | width: 20%;
23 | }
24 |
25 | input[type=cehckbox]{
26 | float: left;
27 | display: inline-block;
28 | }
29 |
30 | input[type=text], input[type=password], input[type=number] {
31 | color: #ABB8BE;
32 | background-color: #292B2F;
33 | outline: none;
34 | padding: 4px 8px 4px 8px;
35 |
36 | margin: 4px 0 0 0;
37 |
38 | border-radius: 6px;
39 | border: 1px solid transparent;
40 | resize: none;
41 | }
42 |
43 | .profile_input_container {
44 | margin: 32px 0 32px 0 !important;
45 | }
--------------------------------------------------------------------------------
/settings/server/page/about/about.html:
--------------------------------------------------------------------------------
1 | About
2 |
3 |
4 |
5 |
6 |
7 |
8 |
30 |
31 |
32 |
33 |
41 |
42 |
43 |
44 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/settings/server/page/about/about.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/settings/server/page/about/about.js
--------------------------------------------------------------------------------
/settings/server/page/banlist/banlist.css:
--------------------------------------------------------------------------------
1 | #profile_container{
2 | padding: 4px;
3 |
4 | width: calc(300px - 8px);
5 | height: auto;
6 | border-radius: 8px;
7 |
8 | background-color: #202225;
9 | color: #ABB8BE;
10 | }
11 |
12 | .profile_headline{
13 | text-transform: uppercase;
14 | margin: 0 0 8px 0;
15 | font-size: 14px;
16 | font-weight: bold;
17 | }
18 |
19 |
20 | #profile_change_container {
21 | float: left;
22 | display: block;
23 |
24 | margin: 0 60px 0 0;
25 | }
26 |
27 |
28 | .profile_input_container {
29 | margin: 0 0 20px 0;
30 | }
31 |
32 |
33 | #settings_profile_save {
34 | margin: 20px 0 0 0;
35 | padding: 2px 4px 2px 4px;
36 |
37 | border: 1px solid transparent;
38 | border-radius: 6px;
39 |
40 | background-color: #ABB8BE;
41 | color: black;
42 | text-align: center;
43 | width: 100%;
44 | }
45 | .banned-entry-img-container{
46 | float: left;
47 | display: block;
48 | width: 100%
49 | }
50 |
51 | .banned-entry-icon {
52 | float: left;
53 | display: block;
54 |
55 | margin-top: -12%;
56 | margin-left: 6%;
57 |
58 | width: 20%;
59 | height: 20%;
60 |
61 | border-radius: 50%;
62 | border: 1px solid #292B2F;
63 |
64 | object-fit: cover;
65 | background-color: transparent;
66 | background-position: center center;
67 | }
68 |
69 | .banned-entry-banner-container{
70 | float: left;
71 | display: block;
72 | width: 100%;
73 | }
74 |
75 | h1 {
76 | margin-top: 0;
77 | }
78 |
79 | .banned-entry-img-containers {
80 | float: left;
81 | display: block;
82 |
83 | margin-right: 2%;
84 |
85 | width: 40%;
86 | }
87 |
88 | .banned-entry-banner {
89 |
90 | width: 100%;
91 | height: 150px;
92 |
93 | border-radius: 6px;
94 | border: 2px solid #292B2F;
95 |
96 | object-fit: cover;
97 | background-color: transparent;
98 | background-position: center center;
99 | }
100 |
101 | .banned-entry-info-container {
102 | float: left;
103 | display: block;
104 | }
105 |
106 | .banned-entry-container {
107 | float: left;
108 | margin-bottom: 5%;
109 | }
110 |
--------------------------------------------------------------------------------
/settings/server/page/banlist/banlist.html:
--------------------------------------------------------------------------------
1 | Banlist
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/settings/server/page/channeltree-sorting/channeltree-sorting.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Channel Sorting
6 | Groups
7 |
8 |
10 | Save updates
11 |
12 |
13 |
15 | Cancel updates
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
Group Info
25 |
26 |
27 | Group ID
28 |
29 |
30 |
31 |
32 | Role Name
33 |
34 |
35 |
36 |
37 |
38 |
39 |
41 | Save updates
42 |
43 |
44 |
46 | Cancel updates
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
56 | Save updates
57 |
58 |
59 |
61 | Cancel updates
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/settings/server/page/emojis/emojis.css:
--------------------------------------------------------------------------------
1 | #profile_container{
2 | padding: 4px;
3 |
4 | width: calc(300px - 8px);
5 | height: auto;
6 | border-radius: 8px;
7 |
8 | background-color: #202225;
9 | color: #ABB8BE;
10 | }
11 |
12 | .profile_headline{
13 | text-transform: uppercase;
14 | margin: 0 0 8px 0;
15 | font-size: 14px;
16 | font-weight: bold;
17 | }
18 |
19 |
20 | #profile_change_container {
21 | float: left;
22 | display: block;
23 |
24 | margin: 0 60px 0 0;
25 | }
26 |
27 |
28 | .profile_input_container {
29 | margin: 0 0 20px 0;
30 | }
31 |
32 |
33 | #settings_profile_save {
34 | margin: 20px 0 0 0;
35 | padding: 2px 4px 2px 4px;
36 |
37 | border: 1px solid transparent;
38 | border-radius: 6px;
39 |
40 | background-color: #ABB8BE;
41 | color: black;
42 | text-align: center;
43 | width: 100%;
44 | }
45 |
46 | .emoji-entry {
47 | float: left;
48 | display: block;
49 | margin: 24px 0 0 0;
50 | width: 100%;
51 | }
52 |
53 | .emoji-img {
54 | float: left;
55 | margin: 0px 4px 0px 0px;
56 | }
57 |
58 | .emoji-img img{
59 | width: 50px;
60 | height: 50px;
61 | }
62 |
63 | .emoji-actions {
64 | margin: 0 0 0 15px;
65 | float: left;
66 | display: inline;
67 | }
68 |
69 | .emoji-action-icon {
70 | margin: 8px 0 0 0 ;
71 | width: 35px;
72 | height: 35px;
73 | float: left;
74 | }
75 |
76 | .emoji-name input[type=text]{
77 | margin: 15px 0 0 20px;
78 |
79 | width: calc(20%);
80 |
81 | float: left;
82 | display: inline-block;
83 | vertical-align: center;
84 |
85 | background-color: #292B2F;
86 | color: #ABB8BE;
87 | outline: none;
88 |
89 | border: 1px solid #70787b;
90 | border-radius: 4px;
91 |
92 | padding: 4px 8px 4px 8px;
93 | }
94 |
95 | #emoji-container {
96 | margin-bottom: 64px !important;
97 | }
--------------------------------------------------------------------------------
/settings/server/page/emojis/emojis.html:
--------------------------------------------------------------------------------
1 | Emojis
2 |
3 |
4 |
5 |
6 |
7 |
8 |
Upload Emoji
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/settings/server/page/file-uploads/file-uploads.css:
--------------------------------------------------------------------------------
1 | .profile_headline{
2 | text-transform: uppercase;
3 | margin: 0 0 8px 0;
4 | font-size: 14px;
5 | font-weight: bold;
6 | }
7 |
8 |
9 | #settings_profile_save {
10 | margin: 20px 0 0 0;
11 | padding: 2px 4px 2px 4px;
12 |
13 | border: 1px solid transparent;
14 | border-radius: 6px;
15 |
16 | background-color: #ABB8BE;
17 | color: black;
18 | text-align: center;
19 | width: 100%;
20 | }
21 |
22 | input[type=cehckbox]{
23 | float: left;
24 | display: inline-block;
25 | }
26 |
27 | input[type=text], input[type=password], input[type=number] {
28 | color: #ABB8BE;
29 | background-color: #292B2F;
30 | outline: none;
31 | padding: 4px 8px 4px 8px;
32 |
33 | margin: 4px 0 0 0;
34 |
35 | border-radius: 6px;
36 | border: 1px solid transparent;
37 | resize: none;
38 | }
39 |
40 | .profile_input_container {
41 | margin: 32px 0 32px 0 !important;
42 | }
--------------------------------------------------------------------------------
/settings/server/page/file-uploads/file-uploads.html:
--------------------------------------------------------------------------------
1 | File Uploads
2 |
3 |
4 |
Local File Upload
5 |
6 |
7 |
14 |
15 |
16 |
Cloudflare Image CDN
17 |
18 |
45 |
46 |
47 |
48 |
49 |
Save
50 |
51 |
--------------------------------------------------------------------------------
/settings/server/page/planned-features/planned-features.css:
--------------------------------------------------------------------------------
1 | .profile_headline{
2 | text-transform: uppercase;
3 | margin: 0 0 8px 0;
4 | font-size: 14px;
5 | font-weight: bold;
6 | }
7 |
8 |
9 | #settings_profile_save {
10 | margin: 20px 0 0 0;
11 | padding: 2px 4px 2px 4px;
12 |
13 | border: 1px solid transparent;
14 | border-radius: 6px;
15 |
16 | background-color: #ABB8BE;
17 | color: black;
18 | text-align: center;
19 | width: 20%;
20 | }
21 |
22 | input[type=cehckbox]{
23 | float: left;
24 | display: inline-block;
25 | }
26 |
27 | input[type=text], input[type=password], input[type=number] {
28 | color: #ABB8BE;
29 | background-color: #292B2F;
30 | outline: none;
31 | padding: 4px 8px 4px 8px;
32 |
33 | margin: 4px 0 0 0;
34 |
35 | border-radius: 6px;
36 | border: 1px solid transparent;
37 | resize: none;
38 | }
39 |
40 | .profile_input_container {
41 | margin: 32px 0 32px 0 !important;
42 | }
--------------------------------------------------------------------------------
/settings/server/page/planned-features/planned-features.html:
--------------------------------------------------------------------------------
1 | Planned Features
2 |
3 |
11 |
12 |
13 |
14 |
15 |
16 |
35 |
36 |
37 |
38 |
39 |
Save
40 |
41 |
--------------------------------------------------------------------------------
/settings/server/page/planned-features/planned-features.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/settings/server/page/planned-features/planned-features.js
--------------------------------------------------------------------------------
/settings/server/page/rate-limit/rate-limit.css:
--------------------------------------------------------------------------------
1 | .profile_headline{
2 | text-transform: uppercase;
3 | margin: 0 0 8px 0;
4 | font-size: 14px;
5 | font-weight: bold;
6 | }
7 |
8 |
9 | #settings_profile_save {
10 | margin: 20px 0 0 0;
11 | padding: 2px 4px 2px 4px;
12 |
13 | border: 1px solid transparent;
14 | border-radius: 6px;
15 |
16 | background-color: #ABB8BE;
17 | color: black;
18 | text-align: center;
19 | width: 20%;
20 | }
21 |
22 | input[type=cehckbox]{
23 | float: left;
24 | display: inline-block;
25 | }
26 |
27 | input[type=text], input[type=password], input[type=number] {
28 | color: #ABB8BE;
29 | background-color: #292B2F;
30 | outline: none;
31 | padding: 4px 8px 4px 8px;
32 |
33 | margin: 4px 0 0 0;
34 |
35 | border-radius: 6px;
36 | border: 1px solid transparent;
37 | resize: none;
38 | }
39 |
40 | .profile_input_container {
41 | margin: 32px 0 32px 0 !important;
42 | }
--------------------------------------------------------------------------------
/settings/server/page/rate-limit/rate-limit.html:
--------------------------------------------------------------------------------
1 | Rate Limit
2 |
3 |
4 |
Local File Upload
5 |
6 |
7 | Server Rate Limit
8 |
9 |
10 |
11 |
12 |
13 | Rate Limit Drop Interval
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
Save
22 |
23 |
--------------------------------------------------------------------------------
/settings/server/page/rate-limit/rate-limit.js:
--------------------------------------------------------------------------------
1 | var setting_rateLimit = document.getElementById("rate-limit");
2 | var setting_dropInterval = document.getElementById("drop-interval");
3 | var saveButton = document.getElementById("settings_profile_save");
4 |
5 | var rateLimit;
6 | var dropInterval;
7 |
8 | var serverconfigName;
9 | var serverconfigDesc;
10 |
11 |
12 |
13 | socket.emit("userConnected", { id: getID(), name: getUsername(), icon: getPFP(), status: getStatus(), token: getToken(),
14 | aboutme: getAboutme(), banner: getBanner()});
15 |
16 | socket.emit("checkPermission", {id:getID(), token: getToken(), permission: "manageRateLimit" }, function (response) {
17 |
18 | if(response.permission == "denied"){
19 | window.location.href = window.location.origin + "/settings/server";
20 | }
21 | else{
22 | document.getElementById("pagebody").style.display = "block";
23 | }
24 | });
25 |
26 |
27 | socket.emit("getServerInfo", {id:getID(), token: getToken() }, function (response) {
28 |
29 | console.log(response);
30 | setting_rateLimit = document.getElementById("rate-limit");
31 | setting_dropInterval = document.getElementById("drop-interval");
32 | saveButton = document.getElementById("settings_profile_save");
33 |
34 | rateLimit = response.rateLimit;
35 | dropInterval = response.dropInterval;
36 |
37 | setting_rateLimit.value = rateLimit;
38 | setting_dropInterval.value = dropInterval;
39 | });
40 |
41 | function isChecked(element){
42 | return element.checked ? 1 : 0;
43 | }
44 |
45 | function updatePreview(){
46 |
47 | try{
48 |
49 | // Username
50 | if(setting_rateLimit.value != rateLimit ||
51 | setting_dropInterval.value != dropInterval
52 |
53 | ){
54 | console.log("NOt same");
55 | saveButton.style.display = "block";
56 | }
57 | else{
58 | console.log("same");
59 | saveButton.style.display = "none";
60 | }
61 |
62 | }
63 | catch(e){
64 | console.log(e);
65 | }
66 |
67 | }
68 |
69 |
70 | function saveSettings(){
71 | try{
72 |
73 | socket.emit("saveRateSettings", { id: getID(), token: getToken(),
74 | newRateLimit: setting_rateLimit.value,
75 | newDropInterval: setting_dropInterval.value
76 | }, function (response) {
77 |
78 | alert(response.msg);
79 | console.log(response);
80 | });
81 | }
82 | catch(error){
83 | alert("Error while trying to save settings: " + error);
84 | return;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/settings/server/page/server-info/server-info.html:
--------------------------------------------------------------------------------
1 | Server Info
2 |
3 |
4 |
Settings
5 |
6 |
7 | Server Name
8 |
9 |
10 |
11 |
12 | Server Description
13 |
14 |
15 |
16 |
Save
17 |
18 |
--------------------------------------------------------------------------------
/settings/server/page/support/support.css:
--------------------------------------------------------------------------------
1 | .profile_headline{
2 | text-transform: uppercase;
3 | margin: 0 0 8px 0;
4 | font-size: 14px;
5 | font-weight: bold;
6 | }
7 |
8 | #profile_change_container a{
9 | color: #ABB8BB;
10 | }
11 |
12 | #settings_profile_save {
13 | margin: 20px 0 0 0;
14 | padding: 2px 4px 2px 4px;
15 |
16 | border: 1px solid transparent;
17 | border-radius: 6px;
18 |
19 | background-color: #ABB8BE;
20 | color: black;
21 | text-align: center;
22 | width: 20%;
23 | }
24 |
25 | input[type=cehckbox]{
26 | float: left;
27 | display: inline-block;
28 | }
29 |
30 | input[type=text], input[type=password], input[type=number] {
31 | color: #ABB8BE;
32 | background-color: #292B2F;
33 | outline: none;
34 | padding: 4px 8px 4px 8px;
35 |
36 | margin: 4px 0 0 0;
37 |
38 | border-radius: 6px;
39 | border: 1px solid transparent;
40 | resize: none;
41 | }
42 |
43 | .profile_input_container {
44 | margin: 32px 0 32px 0 !important;
45 | }
--------------------------------------------------------------------------------
/settings/server/page/support/support.html:
--------------------------------------------------------------------------------
1 | Support
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/settings/server/page/support/support.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/settings/server/page/support/support.js
--------------------------------------------------------------------------------
/settings/server/page/whats-new/whats-new.css:
--------------------------------------------------------------------------------
1 | .profile_headline{
2 | text-transform: uppercase;
3 | margin: 0 0 8px 0;
4 | font-size: 14px;
5 | font-weight: bold;
6 | }
7 |
8 | .date {
9 | text-decoration: underline;
10 | }
11 |
12 | .feature{
13 | font-weight: bold;
14 | text-decoration: none;
15 |
16 | margin-top: 24px;
17 | }
18 |
19 | .detail {
20 |
21 | }
22 |
23 | .desc {
24 | font-style: italic;
25 | }
26 |
27 | * {
28 | line-height: 150%;
29 | }
30 |
31 | code {
32 | padding: 0px 4px 2px 4px;
33 | border: 1.5px solid #5d7fe3;
34 | color: #5d7fe3;
35 | border-radius: 4px;
36 |
37 | margin: -2px 4px 2px 4px;
38 | word-break: break-word;
39 | }
40 |
41 | .update{
42 | padding: 12px 32px 12px 12px;
43 | background-color: #333539;
44 |
45 | margin-bottom: 60px !important;
46 | border-radius: 6px;
47 | }
48 |
49 | .update h2 {
50 | margin: 0;
51 | float: left;
52 | }
53 |
54 | label.update {
55 | float: right;
56 | }
57 |
58 | .update .head {
59 | float: left;
60 | width: calc(100%);
61 |
62 | color: #5d7fe3;
63 | }
64 |
65 | .update .head label{
66 | background-color: #5d7fe3;
67 | padding: 6px 12px 6px 12px;
68 |
69 | border-radius: 6px;
70 | color: white;
71 |
72 | margin-bottom: 0px !important;
73 | }
74 |
75 | .update .content {
76 | }
77 |
78 | ul.content ul {
79 | margin-bottom: 32px;
80 | }
81 |
82 | ul.update.current {
83 | --angle: 0deg;
84 | border: 2px solid;
85 | border-image: conic-gradient(from var(--angle), red, yellow, lime, aqua, blue, magenta, red) 1;
86 | animation: 10s rotate linear infinite;
87 | }
--------------------------------------------------------------------------------
/settings/server/page/whats-new/whats-new.js:
--------------------------------------------------------------------------------
1 | setupNotify();
--------------------------------------------------------------------------------
/sounds/message.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/sounds/message.mp3
--------------------------------------------------------------------------------
/sounds/normal.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackthedev/dcts-shipping/bc012d0068c5180f94115c83e2fb83c400e856ad/sounds/normal.mp3
--------------------------------------------------------------------------------
/start.sh:
--------------------------------------------------------------------------------
1 | screen -dmSL dcts node /home/dcts
2 |
--------------------------------------------------------------------------------
/supervisor.conf.example:
--------------------------------------------------------------------------------
1 | [program:dcts]
2 | directory=/home/dcts
3 | command=sh check.sh
4 | autostart=true
5 | autorestart=true
6 | stderr_logfile=/home/dcts/err.log
7 | stdout_logfile=/home/dcts/out.log
8 | stopsignal=QUIT
--------------------------------------------------------------------------------
/update.sh:
--------------------------------------------------------------------------------
1 | git clone git@github.com:hackthedev/dcts-shipping.git
2 | cp -rf $PWD/dcts-shipping/* $PWD
3 | rm -rf $PWD/dcts-shipping
--------------------------------------------------------------------------------
/version:
--------------------------------------------------------------------------------
1 | 449
--------------------------------------------------------------------------------