mirror of
https://ceregatti.org/git/daniel/dayzdockerserver.git
synced 2025-05-06 14:21:18 +00:00
Implement much missing stuff:
Login. Still WIP, but works. Install server files. Once logged in, this works. Add support for experimental in both web and scripts. WIP. Continuous streaming text web interface for long-running server processes. Large refactor of the config file. Use arrays instead of delimited strings. Large refactor of the express server to support the above. Add Steam API key to env for when we do mod searches. Customize the bash shell of the web container should we exec into it. Ignore the env file.
This commit is contained in:
parent
20700cdc26
commit
569e45c93c
13 changed files with 269 additions and 199 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,6 +1,7 @@
|
||||||
.idea
|
.idea
|
||||||
*.iml
|
*.iml
|
||||||
.env*
|
.env*
|
||||||
|
env.json
|
||||||
node_modules/
|
node_modules/
|
||||||
web/client/bin
|
web/client/bin
|
||||||
web/client/obj
|
web/client/obj
|
||||||
|
|
|
@ -12,6 +12,7 @@ volumes:
|
||||||
serverfiles_experimental:
|
serverfiles_experimental:
|
||||||
# Upstream mission files
|
# Upstream mission files
|
||||||
mpmissions:
|
mpmissions:
|
||||||
|
mpmissions_experimental:
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ services:
|
||||||
- serverfiles:/serverfiles
|
- serverfiles:/serverfiles
|
||||||
- serverfiles_experimental:/serverfiles_experimental
|
- serverfiles_experimental:/serverfiles_experimental
|
||||||
- mpmissions:/serverfiles/mpmissions
|
- mpmissions:/serverfiles/mpmissions
|
||||||
|
- mpmissions_experimental:/serverfiles_experimental/mpmissions
|
||||||
- mods:/serverfiles/steamapps/workshop/content
|
- mods:/serverfiles/steamapps/workshop/content
|
||||||
- mods:/mods
|
- mods:/mods
|
||||||
- ./files:/files
|
- ./files:/files
|
||||||
|
|
|
@ -29,14 +29,14 @@ export yellow="\e[93m"
|
||||||
export lightblue="\e[94m"
|
export lightblue="\e[94m"
|
||||||
export blue="\e[34m"
|
export blue="\e[34m"
|
||||||
export magenta="\e[35m"
|
export magenta="\e[35m"
|
||||||
export cyan="\e[36m"
|
export cyan="\e[36m"
|
||||||
|
|
||||||
# DayZ release server Steam app ID.
|
# DayZ release server Steam app ID.
|
||||||
# Now that the Linux server is released, the binaries will come from this ID.
|
# Now that the Linux server is released, the binaries will come from this ID.
|
||||||
export release_server_appid=223350
|
export release_server_appid=223350
|
||||||
|
|
||||||
# Leaving the experimental server appid here to allow for the use of the experimental server.
|
# Leaving the experimental server appid here to allow for the use of the experimental server.
|
||||||
#export release_server_appid=1042420
|
export experimental_server_appid=1042420
|
||||||
|
|
||||||
# DayZ release client SteamID. This is for mods, as only the release client has them.
|
# DayZ release client SteamID. This is for mods, as only the release client has them.
|
||||||
export release_client_appid=221100
|
export release_client_appid=221100
|
||||||
|
@ -47,6 +47,7 @@ export SERVER_PROFILE="/profiles"
|
||||||
# Common container base directories
|
# Common container base directories
|
||||||
export FILES="/files"
|
export FILES="/files"
|
||||||
export SERVER_FILES="/serverfiles"
|
export SERVER_FILES="/serverfiles"
|
||||||
|
export SERVER_FILES_EXPERIMENTAL="/serverfiles_experimental"
|
||||||
|
|
||||||
# Used to check if dayZ is installed
|
# Used to check if dayZ is installed
|
||||||
export SERVER_INSTALL_FILE="${SERVER_FILES}/DayZServer"
|
export SERVER_INSTALL_FILE="${SERVER_FILES}/DayZServer"
|
||||||
|
|
|
@ -131,8 +131,10 @@ ARG USER_ID
|
||||||
|
|
||||||
RUN groupadd -g ${USER_ID} user && \
|
RUN groupadd -g ${USER_ID} user && \
|
||||||
useradd -l -u ${USER_ID} -m -g user user && \
|
useradd -l -u ${USER_ID} -m -g user user && \
|
||||||
mkdir -p /home/user /serverfiles/mpmissions /serverfiles/steamapps/workshop/content /web && \
|
mkdir -p /home/user \
|
||||||
chown -R user:user /home/user /serverfiles /web
|
/serverfiles/mpmissions /serverfiles/steamapps/workshop/content \
|
||||||
|
/serverfiles_experimental/mpmissions /serverfiles_experimental/steamapps/workshop/content /web && \
|
||||||
|
chown -R user:user /home/user /serverfiles /serverfiles_experimental /web
|
||||||
|
|
||||||
# Use our non-privileged user
|
# Use our non-privileged user
|
||||||
USER user
|
USER user
|
||||||
|
|
18
web/bin/dz
18
web/bin/dz
|
@ -180,7 +180,8 @@ login(){
|
||||||
dologin(){
|
dologin(){
|
||||||
if [ -f "${STEAM_LOGIN}" ]
|
if [ -f "${STEAM_LOGIN}" ]
|
||||||
then
|
then
|
||||||
source "${STEAM_LOGIN}"
|
echo "Logging in to Steam"
|
||||||
|
steamlogin=$(cat ${STEAM_LOGIN})
|
||||||
else
|
else
|
||||||
echo "No cached Steam credentials. Please configure this now: "
|
echo "No cached Steam credentials. Please configure this now: "
|
||||||
login
|
login
|
||||||
|
@ -189,9 +190,16 @@ dologin(){
|
||||||
|
|
||||||
# Perform the installation of the server files.
|
# Perform the installation of the server files.
|
||||||
install(){
|
install(){
|
||||||
if [ ! -f "${SERVER_INSTALL_FILE}" ] || [[ ${1} = "force" ]]
|
WHICH=${1}
|
||||||
|
if [[ ${WHICH} = "experimental" ]]
|
||||||
then
|
then
|
||||||
printf "[ ${yellow}DayZ${default} ] Downloading DayZ Server-Files!\n"
|
SERVER_FILES=${SERVER_FILES_EXPERIMENTAL}
|
||||||
|
SERVER_INSTALL_FILE="${SERVER_FILES}/DayZServer"
|
||||||
|
release_server_appid=${experimental_server_appid}
|
||||||
|
fi
|
||||||
|
if [ ! -f "${SERVER_INSTALL_FILE}" ] || [[ ${2} = "force" ]]
|
||||||
|
then
|
||||||
|
printf "[ ${yellow}DayZ${default} ] Downloading ${WHICH} DayZ Server-Files!\n"
|
||||||
dologin
|
dologin
|
||||||
${STEAMCMD} +force_install_dir ${SERVER_FILES} +login "${steamlogin}" +app_update "${release_server_appid}" validate +quit
|
${STEAMCMD} +force_install_dir ${SERVER_FILES} +login "${steamlogin}" +app_update "${release_server_appid}" validate +quit
|
||||||
# This installs the mpmissions for charnarusplus and enoch (AKA Livonia) from github. The game once allowed the full server
|
# This installs the mpmissions for charnarusplus and enoch (AKA Livonia) from github. The game once allowed the full server
|
||||||
|
@ -199,7 +207,7 @@ install(){
|
||||||
echo "Installing mpmissions for ChernarusPlus and Livonia from github..."
|
echo "Installing mpmissions for ChernarusPlus and Livonia from github..."
|
||||||
map default
|
map default
|
||||||
else
|
else
|
||||||
printf "[ ${lightblue}DayZ${default} ] The server is already installed.\n"
|
printf "[ ${lightblue}DayZ${default} ] The ${WHICH} server is already installed.\n"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,8 +349,6 @@ xml(){
|
||||||
installxml ${1}
|
installxml ${1}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Capture the first argument and shift it off so we can pass $@ to every function
|
|
||||||
C=${1}
|
|
||||||
shift || {
|
shift || {
|
||||||
usage
|
usage
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,13 @@ trap '
|
||||||
' SIGINT SIGTERM
|
' SIGINT SIGTERM
|
||||||
|
|
||||||
# Set PS1 so we know we're in the container
|
# Set PS1 so we know we're in the container
|
||||||
if ! grep -q "dz-web" .bashrc
|
echo "Adding PS1 to .bashrc..."
|
||||||
then
|
cat > .bashrc <<EOF
|
||||||
echo "Adding PS1 to .bashrc..."
|
|
||||||
cat >> .bashrc <<EOF
|
|
||||||
alias ls='ls --color'
|
alias ls='ls --color'
|
||||||
export PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
|
export PS1='${debian_chroot:+($debian_chroot)}\[\033[01;35m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
|
||||||
unset DEVELOPMENT
|
unset DEVELOPMENT
|
||||||
export PATH=${PATH}:/usr/local/dotnet
|
export PATH=${PATH}:/usr/local/dotnet
|
||||||
EOF
|
EOF
|
||||||
fi
|
|
||||||
|
|
||||||
# Shut steamcmd up
|
# Shut steamcmd up
|
||||||
if ! [ -d ${HOME}/.steam ]
|
if ! [ -d ${HOME}/.steam ]
|
||||||
|
@ -25,6 +22,16 @@ then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd /web
|
cd /web
|
||||||
|
if [ -n "${STEAMAPIKEY}" ]
|
||||||
|
then
|
||||||
|
cat > env.json <<EOF
|
||||||
|
{
|
||||||
|
"STEAMAPIKEY": "${STEAMAPIKEY}"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
echo "{}" > env.json
|
||||||
|
fi
|
||||||
#export DEBUG=express:*
|
#export DEBUG=express:*
|
||||||
npm run dev &
|
npm run dev &
|
||||||
wait $!
|
wait $!
|
||||||
|
|
|
@ -5,23 +5,24 @@ const store = useAppStore()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<Dialog v-model:visible="store.stream" maximizable modal :style="{ width: '50rem' }">
|
<Dialog v-model:visible="store.stream" maximizable modal :style="{ width: '50rem' }">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div class="col align-content-center justify-content-center"><i class="pi pi-exclamation-circle" style="color: green;"></i></div>
|
<div class="col align-content-center justify-content-center" style="font-size: 1.5em;">
|
||||||
|
<i v-if="store.streamLoading" class="pi pi-spin pi-cog" style="color: orange;"></i>
|
||||||
|
<i v-else class="pi pi-exclamation-circle" style="color: green;"></i>
|
||||||
|
</div>
|
||||||
<div class="col align-content-center justify-content-center white-space-nowrap">{{ $t('Server Output') }}</div>
|
<div class="col align-content-center justify-content-center white-space-nowrap">{{ $t('Server Output') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #default>
|
<template #default>
|
||||||
<div class="steamcmd">
|
<div class="container">
|
||||||
<pre class="pre">{{ store.streamText }}</pre>
|
<div class="autoscroll">{{ store.streamText }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
|
||||||
<i v-if="store.streamLoading" class="pi pi-spin pi-cog" style="color: red;"></i>
|
|
||||||
<i v-else class="pi pi-check" style="color: green;"></i>
|
|
||||||
</template>
|
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
<Dialog v-model:visible="store.alert" modal :header="$t('Alert')" :style="{ width: '25rem' }">
|
<Dialog v-model:visible="store.alert" modal :header="$t('Alert')" :style="{ width: '25rem' }">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
|
@ -31,6 +32,7 @@ const store = useAppStore()
|
||||||
</template>
|
</template>
|
||||||
{{ store.alertText }}
|
{{ store.alertText }}
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
<Dialog v-model:visible="store.error" modal :header="$t('Error')" :style="{ width: '25rem' }">
|
<Dialog v-model:visible="store.error" modal :header="$t('Error')" :style="{ width: '25rem' }">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
|
@ -40,13 +42,21 @@ const store = useAppStore()
|
||||||
</template>
|
</template>
|
||||||
{{ store.errorText }}
|
{{ store.errorText }}
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.steamcmd {
|
.container {
|
||||||
|
height: 300px;
|
||||||
min-height: 300px;
|
min-height: 300px;
|
||||||
}
|
}
|
||||||
.pre {
|
.autoscroll {
|
||||||
|
overflow-y: scroll;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
max-height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column-reverse;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,34 +1,46 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import Button from 'primevue/button'
|
import Button from 'primevue/button'
|
||||||
import { useFetch } from '@vueuse/core'
|
|
||||||
import { useAppStore } from '@/store.js'
|
import { useAppStore } from '@/store.js'
|
||||||
const store = useAppStore()
|
const store = useAppStore()
|
||||||
import { useI18n } from 'vue-i18n'
|
async function install(which) {
|
||||||
const { t } = useI18n()
|
const url = '/install/server/' + which
|
||||||
async function base() {
|
store.setStreamLoading(true)
|
||||||
let which = '/installbase'
|
const response = await fetch(url)
|
||||||
if (store.steamStatus.stableInstalled) {
|
for await (const chunk of response.body) {
|
||||||
which = '/updatebase'
|
store.setStream(new TextDecoder().decode(chunk), true)
|
||||||
|
}
|
||||||
|
store.setStreamLoading(false)
|
||||||
|
const data = JSON.parse(store.streamText.match(/({.*})/)[1])
|
||||||
|
if (data.errorCode === 0) {
|
||||||
|
store.setAlert(t('Successfully installed server files'))
|
||||||
|
store.steamStatus.installed[which] = true
|
||||||
|
} else if (data.errorMessage) {
|
||||||
|
store.setError(t(data.errorMessage))
|
||||||
|
} else {
|
||||||
|
store.setError(t('Unknown error'))
|
||||||
}
|
}
|
||||||
const { data } = await useFetch(which).get().json()
|
|
||||||
store.setAlert(t(data.value.message))
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<div v-if="! store.steamStatus.loggedIn" class="grid">
|
||||||
|
<div class="col-6 col-offset-3">
|
||||||
|
{{ $t('Please log in to Steam to install server files') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div class="col-6 col-offset-3">
|
<div class="col-6 col-offset-3">
|
||||||
<div>
|
<div>
|
||||||
<Button @click="base('stable')" v-if="! store.steamStatus.stableInstalled">{{ store.steamStatus.stableInstalled ? $t('Update Stable Server Files') : $t('Install Stable Server Files') }}</Button>
|
<Button v-if="! store.steamStatus.installed['stable']" @click="install('stable')" :disabled="! store.steamStatus.loggedIn">{{ $t('Install Stable Server Files') }}</Button>
|
||||||
<span v-else>{{ $t('Stable Server files are installed') }}</span>
|
<Button v-else severity="warn" @click="install('stable')" :disabled="! store.steamStatus.loggedIn">{{ $t('Stable Server files are installed') + ' - ' + $t('Update Stable Server Files') }}</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div class="col-6 col-offset-3">
|
<div class="col-6 col-offset-3">
|
||||||
<div>
|
<div>
|
||||||
<Button @click="base('experimental')" v-if="! store.steamStatus.experimentalInstalled">{{ store.steamStatus.experimentalInstalled ? $t('Update Experimental Server Files') : $t('Install Experimental Server Files') }}</Button>
|
<Button v-if="! store.steamStatus.installed['experimental']" @click="install('experimental')" :disabled="! store.steamStatus.loggedIn">{{ store.steamStatus.installed_experimental ? $t('Update Experimental Server Files') : $t('Install Experimental Server Files') }}</Button>
|
||||||
<span v-else>{{ $t('Experimental Server files are installed') }}</span>
|
<Button v-else severity="warn" @click="install('experimental')" :disabled="! store.steamStatus.loggedIn">{{ $t('Experimental Server files are installed') + ' - ' + $t('Update Experimental Server Files') }}</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -23,11 +23,11 @@ const test = async (type) => {
|
||||||
const continuous = async () => {
|
const continuous = async () => {
|
||||||
const url = '/test?type=continuous'
|
const url = '/test?type=continuous'
|
||||||
const response = await fetch(url)
|
const response = await fetch(url)
|
||||||
store.setStream('')
|
store.setStreamLoading(true)
|
||||||
for await (const chunk of response.body) {
|
for await (const chunk of response.body) {
|
||||||
store.setStream(new TextDecoder().decode(chunk), true)
|
store.setStream(new TextDecoder().decode(chunk), true)
|
||||||
}
|
}
|
||||||
store.setSteamLoading(false)
|
store.setStreamLoading(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -46,7 +46,7 @@ const continuous = async () => {
|
||||||
<div class="col-6 col-offset-3">
|
<div class="col-6 col-offset-3">
|
||||||
<div>
|
<div>
|
||||||
{{ $t('Stable Server files installed') }}:
|
{{ $t('Stable Server files installed') }}:
|
||||||
<span v-if="store.steamStatus.stableInstalled" class="pi pi-check" style="color: green"></span>
|
<span v-if="store.steamStatus.installed['stable']" class="pi pi-check" style="color: green"></span>
|
||||||
<span v-else class="pi pi-times" style="color: red"></span>
|
<span v-else class="pi pi-times" style="color: red"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -55,15 +55,15 @@ const continuous = async () => {
|
||||||
<div class="col-6 col-offset-3">
|
<div class="col-6 col-offset-3">
|
||||||
<div>
|
<div>
|
||||||
{{ $t('Experimental Server files installed') }}:
|
{{ $t('Experimental Server files installed') }}:
|
||||||
<span v-if="store.steamStatus.experimentalInstalled" class="pi pi-check" style="color: green"></span>
|
<span v-if="store.steamStatus.installed['experimental']" class="pi pi-check" style="color: green"></span>
|
||||||
<span v-else class="pi pi-times" style="color: red"></span>
|
<span v-else class="pi pi-times" style="color: red"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div class="col-6 col-offset-3">
|
<div class="col-6 col-offset-3">
|
||||||
<div v-if="store.steamStatus.version">
|
<div v-if="store.steamStatus.version_stable">
|
||||||
{{ $t('Version') }}: <span style="color: green;">{{ store.steamStatus.version }}</span>
|
{{ $t('Version') }}: <span style="color: green;">{{ store.steamStatus.version_stable }}</span>
|
||||||
<span class="bold">({{ store.steamStatus.appid }})</span>
|
<span class="bold">({{ store.steamStatus.appid }})</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,24 +9,20 @@ import { useAppStore } from '@/store.js'
|
||||||
const store = useAppStore()
|
const store = useAppStore()
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
function steamStatus(data) {
|
|
||||||
console.log(data)
|
|
||||||
if (data.errorCode === 0) {
|
|
||||||
store.setAlert(t('Successfully logged in to Steam'))
|
|
||||||
store.steamStatus.loggedIn = true
|
|
||||||
} else {
|
|
||||||
store.setError(t(data.errorMessage))
|
|
||||||
store.steamStatus.loggedIn = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async function logOut() {
|
async function logOut() {
|
||||||
const { data } = await useFetch('/logout').get().json()
|
const { data } = await useFetch('/logout').get().json()
|
||||||
steamStatus(data)
|
if (data.value.errorCode === 0) {
|
||||||
|
store.setAlert(t('Successfully logged out of Steam'))
|
||||||
|
store.steamStatus.loggedIn = false
|
||||||
|
} else if (data.errorMessage) {
|
||||||
|
store.setError(t(data.errorMessage))
|
||||||
|
} else {
|
||||||
|
store.setError(t('Unknown error'))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
async function login(e) {
|
async function login() {
|
||||||
loading.value = true
|
const url = '/login'
|
||||||
e.preventDefault()
|
const response = await fetch(url, {
|
||||||
const { data } = await useFetch('/login', {
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
|
@ -36,12 +32,23 @@ async function login(e) {
|
||||||
password: password.value,
|
password: password.value,
|
||||||
remember: remember.value,
|
remember: remember.value,
|
||||||
steamGuardCode: steamGuardCode.value
|
steamGuardCode: steamGuardCode.value
|
||||||
}).post().json()
|
})
|
||||||
})
|
})
|
||||||
loading.value = false
|
store.setStreamLoading(true)
|
||||||
steamStatus(data)
|
for await (const chunk of response.body) {
|
||||||
|
store.setStream(new TextDecoder().decode(chunk), true)
|
||||||
|
}
|
||||||
|
store.setStreamLoading(false)
|
||||||
|
const data = JSON.parse(store.streamText.match(/({.*})/)[1])
|
||||||
|
if (data.errorCode === 0) {
|
||||||
|
store.setAlert(t('Successfully logged in to Steam'))
|
||||||
|
store.steamStatus.loggedIn = true
|
||||||
|
} else if (data.errorMessage) {
|
||||||
|
store.setError(t(data.errorMessage))
|
||||||
|
} else {
|
||||||
|
store.setError(t('Unknown error'))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let loading = ref(false)
|
|
||||||
let username = ref('')
|
let username = ref('')
|
||||||
let password = ref('')
|
let password = ref('')
|
||||||
let remember = ref(false)
|
let remember = ref(false)
|
||||||
|
@ -49,46 +56,42 @@ let steamGuardCode = ref('')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div v-if="store.steamStatus.loggedIn" class="grid">
|
||||||
<div v-if="store.steamStatus.loggedIn" class="grid">
|
<div class="col-4 col-offset-4 text-center">{{ $t('Already logged in to steam') }}</div>
|
||||||
<div class="col-12">{{ $t('Already logged in to steam') }}</div>
|
<div class="col-12">
|
||||||
<div class="col-12">
|
<Button @click="logOut" severity="danger">{{ $t('Log out') }}</Button>
|
||||||
<Button @click="logOut">{{ $t('Log out') }}</Button>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="grid">
|
||||||
|
<div class="col-4 col-offset-4 text-left">
|
||||||
|
{{ $t('There are no saved Steam credentials. To install the server files and mods, please login to Steam') }}
|
||||||
|
</div>
|
||||||
|
<div class="col-4 col-offset-4 text-right">
|
||||||
|
<div class="col-6 text-left p-0">
|
||||||
|
<label for="username">{{ $t('Username') }}</label>
|
||||||
|
<InputText id="username" v-model="username" autofocus />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="grid">
|
<div class="col-4 col-offset-4 text-right">
|
||||||
<div class="col-12">
|
<div class="col-6 text-left p-0">
|
||||||
<h2>{{ $t('There are no saved Steam credentials. To install the server files and mods, please login to Steam') }}</h2>
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
</div>
|
|
||||||
<div class="col-2 col-offset-4 text-right">
|
|
||||||
<label for="username">{{ $t('Username') }}</label>
|
|
||||||
</div>
|
|
||||||
<div class="col-2 text-left">
|
|
||||||
<InputText id="username" v-model="username" />
|
|
||||||
</div>
|
|
||||||
<div class="col-2 col-offset-4 text-right">
|
|
||||||
<label for="password">{{ $t('Password') }}</label>
|
<label for="password">{{ $t('Password') }}</label>
|
||||||
</div>
|
|
||||||
<div class="col-2 text-left">
|
|
||||||
<Password id="password" v-model="password" :feedback="false" toggleMask />
|
<Password id="password" v-model="password" :feedback="false" toggleMask />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-2 col-offset-4 text-right">
|
</div>
|
||||||
|
<div class="col-4 col-offset-4 text-right">
|
||||||
|
<div class="col-6 text-left p-0">
|
||||||
<label for="steamGuardCode">{{ $t('Steam Guard Code') }}</label>
|
<label for="steamGuardCode">{{ $t('Steam Guard Code') }}</label>
|
||||||
</div>
|
|
||||||
<div class="col-2 text-left">
|
|
||||||
<InputText id="steamGuardCode" v-model="steamGuardCode" />
|
<InputText id="steamGuardCode" v-model="steamGuardCode" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-2 col-offset-4 text-right">
|
</div>
|
||||||
|
<div class="col-4 col-offset-4 text-right">
|
||||||
|
<div class="col-6 text-left p-0">
|
||||||
<label for="remember">{{ $t('Remember Credentials') }}</label>
|
<label for="remember">{{ $t('Remember Credentials') }}</label>
|
||||||
|
<Checkbox inputId="remember" v-model="remember" binary />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-2 text-left">
|
</div>
|
||||||
<Checkbox id="remember" v-model="remember" binary />
|
<div class="col-4 col-offset-4 text-left">
|
||||||
</div>
|
<Button type="button" @click="login" :loading="store.streamLoading" icon="pi pi-user" :label="$t('Submit')"></Button>
|
||||||
<div class="col-12 text-center">
|
|
||||||
<Button @click="login" :icon="loading ? 'pi pi-spin pi-spinner' : ''">{{ $t('Submit') }}</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,36 +1,51 @@
|
||||||
/*
|
// The STEAMAPIKEY is added to this file from the value in the .env file.
|
||||||
* The stable DayZ server Steam app ID.
|
import env from '/web/env.json' assert { type: "json" }
|
||||||
*/
|
|
||||||
const stable_server_appid = 223350
|
|
||||||
|
|
||||||
/*
|
// The stable DayZ server Steam app ID.
|
||||||
* The experimental DayZ server Steam app ID.
|
const server_appid_stable = 223350
|
||||||
*/
|
|
||||||
const experimental_server_appid = 1042420
|
|
||||||
|
|
||||||
/*
|
// The experimental DayZ server Steam app ID.
|
||||||
* DayZ release client Steam app ID. This is for mods, as only the release client has them.
|
const server_appid_experimental = 1042420
|
||||||
*/
|
|
||||||
|
// DayZ release client Steam app ID. This is for mods, as only the release client has them.
|
||||||
const client_appid = 221100
|
const client_appid = 221100
|
||||||
|
|
||||||
const serverFiles = "/serverfiles"
|
const server_files_stable = "/serverfiles"
|
||||||
const homeDir = "/home/user"
|
const server_files_experimental = "/serverfiles_experimental"
|
||||||
|
const home_dir = "/home/user"
|
||||||
|
|
||||||
// const steamAPIKey = process?.env["STEAMAPIKEY"] || ""
|
const search_url = `https://api.steampowered.com/IPublishedFileService/QueryFiles/v1/?numperpage=1000&appid=221100&return_short_description=true&strip_description_bbcode=true&key=${env.STEAMAPIKEY}&search_text=`
|
||||||
//
|
|
||||||
// const searchUrl = "https://api.steampowered.com/IPublishedFileService/QueryFiles/v1/?numperpage=1000&appid=221100&return_short_description=true&strip_description_bbcode=true&key=" + steamAPIKey + "&search_text="
|
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
|
appid: {
|
||||||
|
client: client_appid,
|
||||||
|
experimental: server_appid_experimental,
|
||||||
|
stable: server_appid_stable,
|
||||||
|
},
|
||||||
client_appid: client_appid,
|
client_appid: client_appid,
|
||||||
experimental_server_appid: experimental_server_appid,
|
install_file: {
|
||||||
installFile: serverFiles + "/DayZServer",
|
experimental: server_files_experimental + "/DayZServer",
|
||||||
loginFile: homeDir + "/steamlogin",
|
stable: server_files_stable + "/DayZServer",
|
||||||
modDir: "/mods/" + client_appid,
|
},
|
||||||
|
login_file: home_dir + "/steamlogin",
|
||||||
|
mod_dir: "/mods/" + client_appid,
|
||||||
port: 8000,
|
port: 8000,
|
||||||
// searchUrl: searchUrl,
|
search_url: search_url,
|
||||||
serverFiles: serverFiles,
|
server_appid: {
|
||||||
stable_server_appid: stable_server_appid,
|
experimental: server_appid_experimental,
|
||||||
|
stable: server_appid_stable,
|
||||||
|
},
|
||||||
|
server_files: {
|
||||||
|
experimental: server_files_experimental,
|
||||||
|
stable: server_files_stable,
|
||||||
|
},
|
||||||
steamUrl: 'https://steamcommunity.com/sharedfiles/filedetails/?id=',
|
steamUrl: 'https://steamcommunity.com/sharedfiles/filedetails/?id=',
|
||||||
|
version: {
|
||||||
|
experimental: "1.26.56789",
|
||||||
|
stable: "1.26.123456",
|
||||||
|
},
|
||||||
|
version_experimental: "1.26.56789",
|
||||||
|
version_stable: "1.26.123456",
|
||||||
}
|
}
|
||||||
|
|
||||||
export { config }
|
export { config }
|
||||||
|
|
|
@ -9,14 +9,19 @@ export const useAppStore = defineStore('app', {
|
||||||
modId: 0,
|
modId: 0,
|
||||||
modFile: false,
|
modFile: false,
|
||||||
mods: [],
|
mods: [],
|
||||||
searchText: false,
|
search: false,
|
||||||
|
searchText: '',
|
||||||
servers: [],
|
servers: [],
|
||||||
steamStatus: {
|
steamStatus: {
|
||||||
appid: 0,
|
installed: {
|
||||||
experimentalInstalled: false,
|
experimental: false,
|
||||||
|
stable: false,
|
||||||
|
},
|
||||||
loggedIn: false,
|
loggedIn: false,
|
||||||
stableInstalled: false,
|
version: {
|
||||||
version: ''
|
stable: '',
|
||||||
|
experimental: '',
|
||||||
|
}
|
||||||
},
|
},
|
||||||
stream: false,
|
stream: false,
|
||||||
streamLoading: false,
|
streamLoading: false,
|
||||||
|
@ -28,15 +33,14 @@ export const useAppStore = defineStore('app', {
|
||||||
this.alert = true
|
this.alert = true
|
||||||
},
|
},
|
||||||
setStream(streamText) {
|
setStream(streamText) {
|
||||||
this.stream = true
|
this.streamText += streamText
|
||||||
if (streamText) {
|
|
||||||
this.streamText += streamText
|
|
||||||
} else {
|
|
||||||
this.streamText = ''
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
setStreamLoading(streamLoading) {
|
setStreamLoading(streamLoading) {
|
||||||
|
this.stream = true
|
||||||
this.streamLoading = streamLoading
|
this.streamLoading = streamLoading
|
||||||
|
if (streamLoading) {
|
||||||
|
this.streamText = ''
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setError(error) {
|
setError(error) {
|
||||||
this.errorText = error
|
this.errorText = error
|
||||||
|
|
151
web/index.js
151
web/index.js
|
@ -12,7 +12,7 @@ import path from 'path'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import https from 'https'
|
import https from 'https'
|
||||||
import { spawn } from 'child_process'
|
import { spawn } from 'child_process'
|
||||||
import { config } from "./docroot/src/config.js";
|
import { config } from './docroot/src/config.js'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
File path delimiter
|
File path delimiter
|
||||||
|
@ -94,9 +94,9 @@ const getDirSize = (dirPath) => {
|
||||||
|
|
||||||
const getCustomXML = (modId) => {
|
const getCustomXML = (modId) => {
|
||||||
const ret = []
|
const ret = []
|
||||||
if (! fs.existsSync(config.modDir)) return ret
|
if (! fs.existsSync(config.mod_dir)) return ret
|
||||||
for(const file of configFiles) {
|
for(const file of configFiles) {
|
||||||
if (fs.existsSync(config.modDir + d + modId + d + file)) {
|
if (fs.existsSync(config.mod_dir + d + modId + d + file)) {
|
||||||
ret.push({name:file})
|
ret.push({name:file})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ const getCustomXML = (modId) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const getModNameById = (id) => {
|
const getModNameById = (id) => {
|
||||||
const files = fs.readdirSync(config.serverFiles, {encoding: 'utf8', withFileTypes: true})
|
const files = fs.readdirSync(config.server_files, {encoding: 'utf8', withFileTypes: true})
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
if (file.isSymbolicLink()) {
|
if (file.isSymbolicLink()) {
|
||||||
const sym = fs.readlinkSync(serverFiles + d + file.name)
|
const sym = fs.readlinkSync(serverFiles + d + file.name)
|
||||||
|
@ -116,8 +116,8 @@ const getModNameById = (id) => {
|
||||||
|
|
||||||
const getMods = () => {
|
const getMods = () => {
|
||||||
const mods = []
|
const mods = []
|
||||||
if (! fs.existsSync(config.modDir)) return mods
|
if (! fs.existsSync(config.mod_dir)) return mods
|
||||||
fs.readdirSync(config.modDir).forEach(file => {
|
fs.readdirSync(config.mod_dir).forEach(file => {
|
||||||
const name = getModNameById(file)
|
const name = getModNameById(file)
|
||||||
mods.push({name:name,id:file})
|
mods.push({name:name,id:file})
|
||||||
})
|
})
|
||||||
|
@ -132,26 +132,27 @@ const sendAlert = (res, message) => {
|
||||||
res.send({"alert": message})
|
res.send({"alert": message})
|
||||||
}
|
}
|
||||||
|
|
||||||
const steamcmd = async (args, res) => {
|
const cmd = async (command, args, res) => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
let stdout = ''
|
let stdout = ''
|
||||||
let stderr = ''
|
let stderr = ''
|
||||||
const command = 'steamcmd +force_install_dir ' + config.serverFiles + ' ' + args + ' +quit'
|
const re = /(\u001b\[.*?m)/g
|
||||||
console.log(command)
|
console.log(command, args)
|
||||||
const proc = spawn(command, {shell: true})
|
const proc = spawn(command, args)
|
||||||
proc.stdout.on('data', (data) => {
|
proc.stdout.on('data', (data) => {
|
||||||
const out = "[OUT] " + data + "\n"
|
const out = "[OUT] " + data.toString().replace(re,'') + "\n"
|
||||||
console.log(out)
|
console.log(out)
|
||||||
res.write(out)
|
res.write(out)
|
||||||
stdout += out
|
stdout += out
|
||||||
})
|
})
|
||||||
proc.stderr.on('data', (data) => {
|
proc.stderr.on('data', (data) => {
|
||||||
const err = "[ERROR] " + data + "\n"
|
const err = "[ERROR] " + data.toString().replace(re,'') + "\n"
|
||||||
|
res.write(err)
|
||||||
console.log(err)
|
console.log(err)
|
||||||
stderr += err
|
stderr += err
|
||||||
})
|
})
|
||||||
proc.on('error', (data) => {
|
proc.on('error', (data) => {
|
||||||
const err = "[ERROR] " + data + "\n"
|
const err = "[ERROR] " + data.toString().replace(re,'') + "\n"
|
||||||
console.log(err)
|
console.log(err)
|
||||||
stderr += err
|
stderr += err
|
||||||
})
|
})
|
||||||
|
@ -162,6 +163,14 @@ const steamcmd = async (args, res) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const steamcmd = async (args, which, res) => {
|
||||||
|
return await cmd('steamcmd', [ '+force_install_dir', config.server_files[which] ].concat(args).concat("+quit"), res)
|
||||||
|
}
|
||||||
|
|
||||||
|
const dz = async (args, res) => {
|
||||||
|
return cmd('dz', args, res)
|
||||||
|
}
|
||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
|
|
||||||
app.use(express.json())
|
app.use(express.json())
|
||||||
|
@ -170,35 +179,29 @@ app.use(express.urlencoded({extended: true}))
|
||||||
app.disable('etag')
|
app.disable('etag')
|
||||||
|
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
res.append('Access-Control-Allow-Origin', ['*'])
|
res.append('Access-Control-Allow-Origin', '*')
|
||||||
res.append('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
|
res.append('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
|
||||||
res.append('Access-Control-Allow-Headers', 'Content-Type')
|
res.append('Access-Control-Allow-Headers', 'Content-Type')
|
||||||
next()
|
next()
|
||||||
})
|
})
|
||||||
|
|
||||||
// Install a mod
|
// Install a mod
|
||||||
app.get(('/install/:modId'), (req, res) => {
|
app.get(('/install/mod/:modId'), async (req, res) => {
|
||||||
const modId = req.params["modId"]
|
const modId = req.params["modId"]
|
||||||
// Shell out to steamcmd, monitor the process, and display the output as it runs
|
// Shell out to steamcmd, monitor the process, and display the output as it runs
|
||||||
res.send(modId + " was installed")
|
await dz('a', [ modId ], res)
|
||||||
|
res.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
// Install base files
|
// Install base files
|
||||||
app.get('/installbase', async (req, res) => {
|
app.get('/install/server/:which', async (req, res) => {
|
||||||
let which = req.query?.which
|
const which = req.params["which"]
|
||||||
const username = fs.readFileSync(config.loginFile, 'utf8')
|
const appid = config.appid[which]
|
||||||
if (which === "experimental") {
|
const username = fs.readFileSync(config.login_file, 'utf8')
|
||||||
which = config.experimental_server_appid
|
let args = ['+login', username, '+app_update', appid, 'validate']
|
||||||
} else if (which === "stable") {
|
const result = await steamcmd(args, which, res)
|
||||||
which = config.stable_server_appid
|
res.write(JSON.stringify(result))
|
||||||
} else {
|
res.end()
|
||||||
sendError(res, "Invalid base file type")
|
|
||||||
}
|
|
||||||
let args = `+login "${username}" +app_update "${which}" validate`
|
|
||||||
const result = await steamcmd(args, res)
|
|
||||||
if (result.errorCode === 0) {
|
|
||||||
}
|
|
||||||
res.send(result)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Login to Steam
|
// Login to Steam
|
||||||
|
@ -207,39 +210,40 @@ app.post(('/login'), async (req, res) => {
|
||||||
const password = req.body?.password;
|
const password = req.body?.password;
|
||||||
const steamGuardCode = req.body?.steamGuardCode;
|
const steamGuardCode = req.body?.steamGuardCode;
|
||||||
const remember = req.body?.remember;
|
const remember = req.body?.remember;
|
||||||
let args = `+login "${username}" "${password}"`
|
let args = ['+login', username, password ]
|
||||||
if (steamGuardCode) args += ` "${steamGuardCode}"`
|
if (steamGuardCode) args.push(steamGuardCode)
|
||||||
const result = await steamcmd(args)
|
const result = await steamcmd(args, 'stable', res)
|
||||||
if (result.errorCode === 0) {
|
if (result.errorCode === 0) {
|
||||||
if (remember) {
|
if (remember) {
|
||||||
console.log("Writing login file")
|
console.log("Writing login file")
|
||||||
fs.writeFileSync(config.loginFile, username)
|
fs.writeFileSync(config.login_file, username)
|
||||||
|
} else {
|
||||||
|
console.log("Not writing login file")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.append('Content-Type', 'application/json')
|
res.write(JSON.stringify(result))
|
||||||
res.send(result)
|
res.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
// Logout from Steam
|
// Logout from Steam
|
||||||
app.get(('/logout'), async (req, res) => {
|
app.get(('/logout'), async (req, res) => {
|
||||||
let result = {"status": 304}
|
let result = {"errorCode": 0}
|
||||||
if (fs.existsSync(config.loginFile)) {
|
if (fs.existsSync(config.login_file)) {
|
||||||
fs.unlinkSync(config.loginFile, (err) => {
|
fs.rmSync('/home/user/.local/share/Steam/userdata', { recursive: true, force: true })
|
||||||
|
fs.unlinkSync(config.login_file, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
result.status = 500
|
result.errorCoder = 1
|
||||||
result.error = err
|
result.error = err
|
||||||
}
|
}
|
||||||
result.status = 200
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
res.append('Content-Type', 'application/json')
|
|
||||||
res.send(result)
|
res.send(result)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Get mod metadata by ID
|
// Get mod metadata by ID
|
||||||
app.get('/mod/:modId', (req, res) => {
|
app.get('/mod/:modId', (req, res) => {
|
||||||
const modId = req.params["modId"]
|
const modId = req.params["modId"]
|
||||||
const modDir = config.modDir + d + modId
|
const modDir = config.mod_dir + d + modId
|
||||||
const customXML = getCustomXML(modId)
|
const customXML = getCustomXML(modId)
|
||||||
const ret = {
|
const ret = {
|
||||||
id: modId,
|
id: modId,
|
||||||
|
@ -254,8 +258,8 @@ app.get('/mod/:modId', (req, res) => {
|
||||||
app.get('/mod/:modId/:file', (req, res) => {
|
app.get('/mod/:modId/:file', (req, res) => {
|
||||||
const modId = req.params["modId"]
|
const modId = req.params["modId"]
|
||||||
const file = req.params["file"]
|
const file = req.params["file"]
|
||||||
if (fs.existsSync(config.modDir + d + modId + d + file)) {
|
if (fs.existsSync(config.mod_dir + d + modId + d + file)) {
|
||||||
const contents = fs.readFileSync(config.modDir + d + modId + d + file)
|
const contents = fs.readFileSync(config.mod_dir + d + modId + d + file)
|
||||||
res.set('Content-type', 'application/xml')
|
res.set('Content-type', 'application/xml')
|
||||||
res.send(contents)
|
res.send(contents)
|
||||||
}
|
}
|
||||||
|
@ -282,8 +286,7 @@ app.get(('/remove/:modId'), (req, res) => {
|
||||||
// Search for a mod
|
// Search for a mod
|
||||||
app.get(('/search/:searchString'), (req, res) => {
|
app.get(('/search/:searchString'), (req, res) => {
|
||||||
const searchString = req.params["searchString"]
|
const searchString = req.params["searchString"]
|
||||||
const url = config.searchUrl + searchString
|
const url = config.search_url + searchString
|
||||||
// const url = "https://api.steampowered.com/IPublishedFileService/QueryFiles/v1/?numperpage=1000&appid=221100&return_short_description=true&strip_description_bbcode=true&key=" + config.steamAPIKey + "&search_text=" + searchString
|
|
||||||
https.get(url, resp => {
|
https.get(url, resp => {
|
||||||
let data = '';
|
let data = '';
|
||||||
resp.on('data', chunk => {
|
resp.on('data', chunk => {
|
||||||
|
@ -302,15 +305,19 @@ app.get(('/search/:searchString'), (req, res) => {
|
||||||
If the base files are installed, the version of the server, the appid (If release or experimental)
|
If the base files are installed, the version of the server, the appid (If release or experimental)
|
||||||
*/
|
*/
|
||||||
app.get('/status', (_, res) => {
|
app.get('/status', (_, res) => {
|
||||||
const installed = fs.existsSync(config.installFile)
|
|
||||||
const loggedIn = fs.existsSync(config.loginFile)
|
|
||||||
const ret = {
|
const ret = {
|
||||||
"appid": config.appid_version,
|
"appid": config.version['stable'],
|
||||||
"installed": installed,
|
"installed": {
|
||||||
"loggedIn": loggedIn,
|
"experimental": fs.existsSync(config.install_file['experimental']),
|
||||||
|
"stable": fs.existsSync(config.install_file['stable']),
|
||||||
|
},
|
||||||
|
"loggedIn": fs.existsSync(config.login_file),
|
||||||
}
|
}
|
||||||
if (installed) {
|
if (ret.installed.stable) {
|
||||||
ret.version = getVersion()
|
ret.version = {
|
||||||
|
stable: getVersion('stable'),
|
||||||
|
experimental: getVersion('experimental')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res.send(ret)
|
res.send(ret)
|
||||||
})
|
})
|
||||||
|
@ -331,29 +338,29 @@ app.get('/test', async (req, res) => {
|
||||||
res.send(ret)
|
res.send(ret)
|
||||||
} else if (type === "continuous") {
|
} else if (type === "continuous") {
|
||||||
res.set('Content-Type', 'text/plain')
|
res.set('Content-Type', 'text/plain')
|
||||||
res.write("data: This is a test server continuous output 1\n")
|
res.write("This is a test server continuous output 1\n")
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||||
res.write("data: This is a test server continuous output 2\n")
|
res.write("This is a test server continuous output 2\n")
|
||||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||||
res.write("data: This is a test server continuous output 3 but it's a very long line intended to force wrapping of text because the length is so long and the girth is so gorth\n")
|
res.write("This is a test server continuous output 3 but it's a very long line intended to force wrapping of text because the length is so long and the girth is so gorth\n")
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||||
res.write("data: This is a test server continuous output 4\nDone!")
|
res.write("This is a test server continuous output 4\n")
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||||
|
res.write("This is a test server continuous output 5 with a whole SHIT TON of text! Lorem ipsum ain't got nothing on this! Hell yeah! Let's add a lot\nof\n\nnewlines and ellipses and other garbage...\nthis and that...and the other!\nLet's keep pushing this down...WAY DOWN...\nDOWN\nDOWN\nDOWN...\n\n...")
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||||
|
res.write("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean lacinia tristique porta. Integer luctus dui non augue egestas, vitae faucibus massa placerat. In ornare sodales risus quis faucibus. Cras viverra mauris vel neque sollicitudin pretium. Integer quis consectetur purus. Nulla sed accumsan tortor. Nulla felis eros, egestas quis eros ut, hendrerit aliquam ante. Nulla sagittis tortor nulla, eu consectetur tellus tempus eget. In hac habitasse platea dictumst. Mauris interdum cursus massa ac vestibulum. Morbi sodales justo sed feugiat consequat. Nunc purus nibh, faucibus id porttitor eget, dignissim eu purus. Duis efficitur varius libero vitae tristique. Mauris libero dolor, tempor at sagittis in, malesuada auctor sapien. Nulla eu accumsan odio. Phasellus dapibus dictum nulla ac feugiat.\n")
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 500))
|
||||||
|
res.write("Pellentesque at massa vel eros auctor fringilla. Vestibulum at molestie augue. Proin dictum, tortor quis efficitur finibus, tortor nisi viverra libero, eget placerat lectus dolor a felis. Pellentesque vitae felis vulputate enim feugiat rutrum. Pellentesque auctor tempor eros sed consectetur. Integer id pellentesque massa, quis suscipit nisi. Fusce tempor cursus nulla nec imperdiet. Phasellus sodales iaculis eros, sed auctor lacus elementum vitae. Sed efficitur condimentum risus. Cras varius risus at quam condimentum, vitae cursus leo facilisis. Suspendisse pellentesque erat leo, a cursus augue blandit sed. Aliquam quis nibh vel sapien pulvinar feugiat quis eu diam. Pellentesque ullamcorper vestibulum leo non imperdiet.\n")
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 500))
|
||||||
|
res.write("In et nulla risus. Fusce luctus ligula vitae velit lacinia egestas. Nullam semper, nisl vel ultrices semper, magna sem vestibulum ipsum, in pulvinar elit diam ac odio. Etiam id laoreet odio, a vehicula est. Sed luctus lobortis sollicitudin. Morbi hendrerit erat vel lacus pellentesque, eget pretium nisi faucibus. Nunc a orci sed mauris commodo cursus. Morbi at ipsum fermentum, placerat felis at, porta felis. Pellentesque sit amet sollicitudin est, aliquet consequat tortor. Cras efficitur egestas pulvinar. Morbi ultrices, ligula ac luctus ullamcorper, risus metus hendrerit eros, et ultricies diam justo eget lorem. Duis varius pulvinar nulla a luctus. Curabitur sed quam cursus risus pellentesque dignissim id vel arcu.\n")
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 500))
|
||||||
|
res.write("This is a test server continuous output 5 with a whole SHIT TON of text! Lorem ipsum ain't got nothing on this! Hell yeah! Let's add a lot\nof\n\nnewlines and ellipses and other garbage...\nthis and that...and the other!\nLet's keep pushing this down...WAY DOWN...\nDOWN\nDOWN\nDOWN...\n\n...\n\nDone!")
|
||||||
res.end()
|
res.end()
|
||||||
} else {
|
} else {
|
||||||
res.send("Unknown test type")
|
res.send("Unknown test type")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Update base files
|
|
||||||
app.get('/updatebase', (req, res) => {
|
|
||||||
res.send("Base files were updated")
|
|
||||||
})
|
|
||||||
|
|
||||||
// Update mods
|
|
||||||
app.get('/updatemods', (req, res) => {
|
|
||||||
res.send("Mod files were updated")
|
|
||||||
})
|
|
||||||
|
|
||||||
ViteExpress.listen(app, config.port, () =>
|
ViteExpress.listen(app, config.port, () =>
|
||||||
console.log(`Server is listening on port ${config.port}`)
|
console.log(`Server is listening on port ${config.port}`)
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue