Merge commit 'd49272e17e6b162b9bf4a6934d0f89de3285316e' into HEAD

This commit is contained in:
Scott Anderson
2025-05-13 03:40:58 -04:00
717 changed files with 14198 additions and 11204 deletions
@@ -0,0 +1,67 @@
---
name: "📝 API/DB Feature Request"
about: Suggest a new backend API or database feature
title: "[Feature] <short description here>"
labels: [feature, backend]
assignees: ""
---
## ✨ API/Database Feature Request
### Summary
Describe the feature being requested. What functionality does it add to the backend or database? What problem does it solve?
## 📘 Use Case
Explain the use case behind this feature. Who is it for, and why is it needed now?
## 📥 Example API Request
```
POST /api/example-endpoint
Content-Type: application/json
Authorization: Bearer <token>
{
"exampleField": "value",
"anotherField": 123
}
```
## 📤 Example API Response
```
// JSON response
{
"id": "abc123",
"status": "success",
"data": {
"result": true,
"timestamp": "2025-04-30T18:00:00Z"
}
}
```
## 📦 Database Considerations
- **New Tables**: Yes/No
If yes, describe the schema or include a rough layout.
- **Modified Tables**: Yes/No
Describe what changes are needed and why.
- **Migrations Required**: Yes/No
- **Indexes Required**: Yes/No
Include any thoughts on performance or query efficiency.
## 🔐 Security & Access Control
- Does the endpoint require authentication? Yes/No
- Should it be limited to specific roles (e.g. admin, worker, user)?
- Any sensitive data in the request or response?
## 📎 Additional Context
Add any screenshots, designs, relevant discussion links, or references to prior issues.
+111 -15
View File
@@ -1,38 +1,134 @@
name: Deploy to Remote
name: 🚀 Deploy
on:
# Allow contributors to schedule manual deployments.
# Permission to deploy can be restricted by requiring approval in environment configuration.
workflow_dispatch:
inputs:
target_environment:
description: "Deployment Environment"
target_domain:
description: "Deployment Domain"
required: true
default: "openfront.dev"
type: choice
options:
- openfront.io
- openfront.dev
target_host:
description: "Deployment Host"
required: true
default: "staging"
type: choice
options:
- production
- eu
- us
- staging
target_subdomain:
description: "Deployment Subdomain"
required: false
default: ""
type: string
# Automatic deployment on push
# See https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#onpushpull_requestpull_request_targetpathspaths-ignore
push:
branches:
- "*"
jobs:
deploy:
name: Deploy to ${{ inputs.target_environment }}
# Don't deploy on push if this is a fork
if: ${{ github.event_name == 'workflow_dispatch' || github.repository == 'openfrontio/OpenFrontIO' }}
# Use different logic based on event type
name: Deploy to ${{
github.event_name == 'push'
&& (github.ref_name == 'main' && 'openfront.dev'
|| format('{0}.openfront.dev', github.ref_name))
|| inputs.target_subdomain && format('{0}.{1}', inputs.target_subdomain, inputs.target_domain)
|| inputs.target_domain
|| 'openfront.dev'
}}
runs-on: ubuntu-latest
environment: ${{ inputs.target_environment }}
environment: ${{
github.event_name == 'push'
&& (github.ref_name == 'main' && 'openfront.dev'
|| format('{0}.openfront.dev', github.ref_name))
|| inputs.target_subdomain && format('{0}.{1}', inputs.target_subdomain, inputs.target_domain)
|| inputs.target_domain
|| 'openfront.dev'
}}
env:
DOMAIN: ${{ inputs.target_domain || 'openfront.dev' }}
SUBDOMAIN: ${{ github.event_name == 'push' && github.ref_name || inputs.target_subdomain || 'main' }}
steps:
- uses: actions/checkout@v4
- name: Update deployment status
env:
FQDN: ${{ env.SUBDOMAIN && format('{0}.{1}', env.SUBDOMAIN, env.DOMAIN) || env.DOMAIN || 'openfront.dev' }}
run: |
echo "FQDN=$FQDN" >> $GITHUB_ENV
cat <<EOF >> $GITHUB_STEP_SUMMARY
### In progress :ship:
Deploying from $GITHUB_REF to $FQDN
EOF
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- run: |
- name: Create SSH private key
env:
SERVER_HOST_EU: ${{ secrets.SERVER_HOST_EU }}
SERVER_HOST_STAGING: ${{ secrets.SERVER_HOST_STAGING }}
SERVER_HOST_US: ${{ secrets.SERVER_HOST_US }}
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
set -euxo pipefail
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa
test -n "$SERVER_HOST_STAGING" && ssh-keyscan -H "$SERVER_HOST_STAGING" >> ~/.ssh/known_hosts
test -n "$SERVER_HOST_US" && ssh-keyscan -H "$SERVER_HOST_US" >> ~/.ssh/known_hosts
test -n "$SERVER_HOST_EU" && ssh-keyscan -H "$SERVER_HOST_EU" >> ~/.ssh/known_hosts
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts
cat >.env <<EOF
SERVER_HOST_STAGING=${{ secrets.SERVER_USERNAME }}@${{ secrets.SERVER_HOST }}
DOCKER_REPO_STAGING=${{ vars.DOCKERHUB_REPO }}
DOCKER_USERNAME=${{ vars.DOCKERHUB_USERNAME }}
- name: Deploy
env:
ADMIN_TOKEN: ${{ secrets.ADMIN_TOKEN }}
CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
DOCKER_REPO: ${{ vars.DOCKERHUB_REPO }}
DOCKER_USERNAME: ${{ vars.DOCKERHUB_USERNAME }}
ENV: ${{ inputs.target_domain == 'openfront.io' && 'prod' || 'staging' }}
HOST: ${{ github.event_name == 'workflow_dispatch' && inputs.target_host || 'staging' }}
MON_PASSWORD: ${{ secrets.MON_PASSWORD }}
MON_USERNAME: ${{ secrets.MON_USERNAME }}
OTEL_ENDPOINT: ${{ secrets.OTEL_ENDPOINT }}
OTEL_PASSWORD: ${{ secrets.OTEL_PASSWORD }}
OTEL_USERNAME: ${{ secrets.OTEL_USERNAME }}
R2_ACCESS_KEY: ${{ secrets.R2_ACCESS_KEY }}
R2_BUCKET: ${{ secrets.R2_BUCKET }}
R2_SECRET_KEY: ${{ secrets.R2_SECRET_KEY }}
SERVER_HOST_EU: ${{ secrets.SERVER_HOST_EU }}
SERVER_HOST_STAGING: ${{ secrets.SERVER_HOST_STAGING }}
SERVER_HOST_US: ${{ secrets.SERVER_HOST_US }}
SSH_KEY: ~/.ssh/id_rsa
VERSION_TAG: latest
run: |
echo "::group::deploy.sh"
./deploy.sh "$ENV" "$HOST" "$SUBDOMAIN"
echo "::endgroup::"
- name: Update deployment status ✅
if: success()
run: |
cat <<EOF >> $GITHUB_STEP_SUMMARY
### Success! :rocket:
Deployed from $GITHUB_REF to $FQDN
EOF
- name: Update deployment status ❌
if: failure()
run: |
cat <<EOF >> $GITHUB_STEP_SUMMARY
### Failure! :fire:
Unable to deploy from $GITHUB_REF to $FQDN
EOF
./deploy.sh ${{ inputs.target_environment }}
+1 -1
View File
@@ -5,5 +5,5 @@ static/
TODO.txt
resources/images/.DS_Store
resources/.DS_Store
.env
.env*
.DS_Store
Regular → Executable
+8 -1
View File
@@ -1 +1,8 @@
npx lint-staged
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
# Add PATH setup to ensure npx is found
export PATH="/usr/local/bin:$HOME/.npm-global/bin:$HOME/.nvm/versions/node/$(node -v)/bin:$PATH"
# Then run lint-staged if tests pass
npx lint-staged
+19
View File
@@ -9,6 +9,25 @@
"runtimeArgs": ["run-script", "test"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
},
{
"type": "node",
"request": "launch",
"name": "Debug Server",
"runtimeExecutable": "node",
"runtimeArgs": [
"--loader",
"ts-node/esm",
"--experimental-specifier-resolution=node",
"${workspaceFolder}/src/server/Server.ts"
],
"env": {
"GAME_ENV": "dev"
},
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"sourceMaps": true,
"restart": true
}
]
}
+32 -9
View File
@@ -1,13 +1,31 @@
# Use an official Node runtime as the base image
FROM node:18
FROM node:18 AS base
# Create dependency layer
FROM base AS dependencies
RUN apt-get update && apt-get install -y \
nginx \
supervisor \
git \
curl \
jq \
wget \
apache2-utils \
&& rm -rf /var/lib/apt/lists/*
RUN curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb > cloudflared.deb \
&& dpkg -i cloudflared.deb \
&& rm cloudflared.deb
# Final image
FROM base
# Copy installed packages from dependencies stage
COPY --from=dependencies / /
ARG GIT_COMMIT=unknown
ENV GIT_COMMIT=$GIT_COMMIT
# Install Nginx, Supervisor and Git (for Husky)
RUN apt-get update && apt-get install -y nginx supervisor git && \
rm -rf /var/lib/apt/lists/*
# Set the working directory in the container
WORKDIR /usr/src/app
@@ -25,6 +43,10 @@ COPY . .
# Build the client-side application
RUN npm run build-prod
# So we can see which commit was used to build the container
# https://openfront.io/commit.txt
RUN echo $GIT_COMMIT > static/commit.txt
# Copy Nginx configuration and ensure it's used instead of the default
COPY nginx.conf /etc/nginx/conf.d/default.conf
RUN rm -f /etc/nginx/sites-enabled/default
@@ -33,8 +55,9 @@ RUN rm -f /etc/nginx/sites-enabled/default
RUN mkdir -p /var/log/supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Expose only the Nginx port
EXPOSE 80 443
# Copy and make executable the startup script
COPY startup.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/startup.sh
# Start Supervisor to manage both Node.js and Nginx
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
# Use the startup script as the entrypoint
ENTRYPOINT ["/usr/local/bin/startup.sh"]
+9 -7
View File
@@ -116,21 +116,23 @@ This project is licensed under the terms found in the [LICENSE](LICENSE) file.
Contributions are welcome! Please feel free to submit a Pull Request.
1. Request to join the development [Discord](https://discord.gg/K9zernJB5z).
1. Fork the repository
2. Create your feature branch (`git checkout -b amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin amazing-feature`)
5. Open a Pull Request
1. Create your feature branch (`git checkout -b amazing-feature`)
1. Commit your changes (`git commit -m 'Add some amazing feature'`)
1. Push to the branch (`git push origin amazing-feature`)
1. Open a Pull Request
## 🌐 Translation
Translators are welcome! Please feel free to help translate into your language.
How to help?
1. Request to join the translation [Discord](https://discord.gg/rUukAnz4Ww)
1. Go to the project's Crowdin translation page: [https://crowdin.com/project/openfront-mls](https://crowdin.com/project/openfront-mls)
2. Login if you already have an account/ Sign up if you don't have one
3. Select the language you want to translate in/ If your language isn't on the list, click the "Request New Language" button and enter the language you want added there.
4. Translate the strings
1. Login if you already have an account/ Sign up if you don't have one
1. Select the language you want to translate in/ If your language isn't on the list, click the "Request New Language" button and enter the language you want added there.
1. Translate the strings
### Project Governance
+124 -53
View File
@@ -7,6 +7,48 @@
set -e # Exit immediately if a command exits with a non-zero status
# Initialize variables
ENABLE_BASIC_AUTH=false
# Parse command line arguments
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
--enable_basic_auth)
ENABLE_BASIC_AUTH=true
shift
;;
*)
POSITIONAL_ARGS+=("$1")
shift
;;
esac
done
# Restore positional parameters
set -- "${POSITIONAL_ARGS[@]}"
# Check command line arguments
if [ $# -lt 2 ] || [ $# -gt 3 ]; then
echo "Error: Please specify environment and host, with optional subdomain"
echo "Usage: $0 [prod|staging] [eu|us|staging|masters] [subdomain] [--enable_basic_auth]"
exit 1
fi
# Validate first argument (environment)
if [ "$1" != "prod" ] && [ "$1" != "staging" ]; then
echo "Error: First argument must be either 'prod' or 'staging'"
echo "Usage: $0 [prod|staging] [eu|us|staging|masters] [subdomain] [--enable_basic_auth]"
exit 1
fi
# Validate second argument (host)
if [ "$2" != "eu" ] && [ "$2" != "us" ] && [ "$2" != "staging" ] && [ "$2" != "masters" ]; then
echo "Error: Second argument must be either 'eu', 'us', 'staging', or 'masters'"
echo "Usage: $0 [prod|staging] [eu|us|staging|masters] [subdomain] [--enable_basic_auth]"
exit 1
fi
# Function to print section headers
print_header() {
echo "======================================================"
@@ -14,53 +56,73 @@ print_header() {
echo "======================================================"
}
# Load environment variables
ENV=$1
HOST=$2
SUBDOMAIN=$3 # Optional third argument for custom subdomain
# Set subdomain - use the custom subdomain if provided, otherwise use REGION
if [ -n "$SUBDOMAIN" ]; then
echo "Using custom subdomain: $SUBDOMAIN"
else
SUBDOMAIN=$HOST
echo "Using host as subdomain: $SUBDOMAIN"
fi
# Load common environment variables first
if [ -f .env ]; then
echo "Loading configuration from .env file..."
echo "Loading common configuration from .env file..."
export $(grep -v '^#' .env | xargs)
fi
# Check command line argument
if [ $# -ne 1 ] || ([ "$1" != "staging" ] && [ "$1" != "eu" ] && [ "$1" != "us" ]); then
echo "Error: Please specify environment (staging, eu, or us)"
echo "Usage: $0 [staging|eu|us]"
exit 1
# Load environment-specific variables
if [ -f .env.$ENV ]; then
echo "Loading $ENV-specific configuration from .env.$ENV file..."
export $(grep -v '^#' .env.$ENV | xargs)
fi
REGION=$1
VERSION_TAG="latest"
DOCKER_REPO=""
ENV=""
# Set environment-specific variables
if [ "$REGION" == "staging" ]; then
print_header "DEPLOYING TO STAGING ENVIRONMENT"
if [ "$HOST" == "staging" ]; then
print_header "DEPLOYING TO STAGING HOST"
SERVER_HOST=$SERVER_HOST_STAGING
DOCKER_REPO=$DOCKER_REPO_STAGING
ENV="staging"
elif [ "$REGION" == "us" ]; then
print_header "DEPLOYING TO US ENVIRONMENT"
elif [ "$HOST" == "us" ]; then
print_header "DEPLOYING TO US HOST"
SERVER_HOST=$SERVER_HOST_US
DOCKER_REPO=$DOCKER_REPO_PROD # Uses prod Docker repo for alt environment
ENV="prod"
elif [ "$HOST" == "masters" ]; then
print_header "DEPLOYING TO MASTERS HOST"
SERVER_HOST=$SERVER_HOST_MASTERS
else
print_header "DEPLOYING TO EU ENVIRONMENT"
print_header "DEPLOYING TO EU HOST"
SERVER_HOST=$SERVER_HOST_EU
DOCKER_REPO=$DOCKER_REPO_PROD
ENV="prod"
fi
# Check required environment variables
if [ -z "$SERVER_HOST" ]; then
echo "Error: SERVER_HOST_${REGION^^} not defined in .env file or environment"
echo "Error: ${HOST} not defined in .env file or environment"
exit 1
fi
# Check if basic auth is enabled and credentials are available
if [ "$ENABLE_BASIC_AUTH" = true ]; then
print_header "BASIC AUTH ENABLED"
if [ -z "$BASIC_AUTH_USER" ] || [ -z "$BASIC_AUTH_PASS" ]; then
echo "Error: Basic Auth is enabled but BASIC_AUTH_USER or BASIC_AUTH_PASS not defined in .env file or environment"
exit 1
fi
echo "Basic Authentication will be enabled with user: $BASIC_AUTH_USER"
else
# If basic auth is not enabled, set the variables to empty to ensure they don't get used
BASIC_AUTH_USER=""
BASIC_AUTH_PASS=""
echo "Basic Authentication is disabled"
fi
# Configuration
SSH_KEY=${SSH_KEY:-"~/.ssh/id_rsa"} # Use default or override from .env
DOCKER_USERNAME=${DOCKER_USERNAME} # Docker Hub username
UPDATE_SCRIPT="./update.sh" # Path to your update script
REMOTE_UPDATE_SCRIPT="/root/update-openfront.sh" # Where to place the script on server
REMOTE_USER="openfront"
REMOTE_UPDATE_PATH="/home/$REMOTE_USER"
REMOTE_UPDATE_SCRIPT="$REMOTE_UPDATE_PATH/update-openfront.sh" # Where to place the script on server
VERSION_TAG=$(date +"%Y%m%d-%H%M%S")
DOCKER_IMAGE="${DOCKER_USERNAME}/${DOCKER_REPO}:${VERSION_TAG}"
# Check if update script exists
if [ ! -f "$UPDATE_SCRIPT" ]; then
@@ -70,7 +132,9 @@ fi
# Step 1: Build and upload Docker image to Docker Hub
print_header "STEP 1: Building and uploading Docker image to Docker Hub"
echo "Region: ${REGION}"
echo "Environment: ${ENV}"
echo "Host: ${HOST}"
echo "Subdomain: ${SUBDOMAIN}"
echo "Using version tag: $VERSION_TAG"
echo "Docker repository: $DOCKER_REPO"
@@ -81,7 +145,7 @@ echo "Git commit: $GIT_COMMIT"
docker buildx build \
--platform linux/amd64 \
--build-arg GIT_COMMIT=$GIT_COMMIT \
-t $DOCKER_USERNAME/$DOCKER_REPO:$VERSION_TAG \
-t $DOCKER_IMAGE \
--push \
.
@@ -90,42 +154,46 @@ if [ $? -ne 0 ]; then
exit 1
fi
if [ $? -ne 0 ]; then
echo "❌ Failed to push image to Docker Hub. Stopping deployment."
exit 1
fi
echo "✅ Docker image built and pushed successfully."
# Step 2: Copy update script to Hetzner server
print_header "STEP 2: Copying update script to server"
echo "Target: $SERVER_HOST"
echo "Target: $REMOTE_USER@$SERVER_HOST"
# Make sure the update script is executable
chmod +x $UPDATE_SCRIPT
# Copy the update script to the server
scp -i $SSH_KEY $UPDATE_SCRIPT $SERVER_HOST:$REMOTE_UPDATE_SCRIPT
# Copy environment variables if needed
if [ -f .env ]; then
scp -i $SSH_KEY .env $SERVER_HOST:/root/.env
# Secure the .env file
ssh -i $SSH_KEY $SERVER_HOST "chmod 600 /root/.env"
fi
scp -i $SSH_KEY $UPDATE_SCRIPT $REMOTE_USER@$SERVER_HOST:$REMOTE_UPDATE_SCRIPT
if [ $? -ne 0 ]; then
echo "❌ Failed to copy update script to server. Stopping deployment."
exit 1
fi
echo "✅ Update script successfully copied to server."
# Step 3: Execute the update script on the server
print_header "STEP 3: Executing update script on server"
# Make the script executable on the remote server and execute it with the environment parameter
ssh -i $SSH_KEY $SERVER_HOST "chmod +x $REMOTE_UPDATE_SCRIPT && $REMOTE_UPDATE_SCRIPT $REGION $DOCKER_USERNAME $DOCKER_REPO"
ssh -i $SSH_KEY $REMOTE_USER@$SERVER_HOST "chmod +x $REMOTE_UPDATE_SCRIPT && \
cat > $REMOTE_UPDATE_PATH/.env << 'EOL'
GAME_ENV=$ENV
ENV=$ENV
HOST=$HOST
DOCKER_IMAGE=$DOCKER_IMAGE
DOCKER_TOKEN=$DOCKER_TOKEN
ADMIN_TOKEN=$ADMIN_TOKEN
CF_ACCOUNT_ID=$CF_ACCOUNT_ID
R2_ACCESS_KEY=$R2_ACCESS_KEY
R2_SECRET_KEY=$R2_SECRET_KEY
R2_BUCKET=$R2_BUCKET
CF_API_TOKEN=$CF_API_TOKEN
DOMAIN=$DOMAIN
SUBDOMAIN=$SUBDOMAIN
OTEL_USERNAME=$OTEL_USERNAME
OTEL_PASSWORD=$OTEL_PASSWORD
OTEL_ENDPOINT=$OTEL_ENDPOINT
BASIC_AUTH_USER=$BASIC_AUTH_USER
BASIC_AUTH_PASS=$BASIC_AUTH_PASS
EOL
chmod 600 $REMOTE_UPDATE_PATH/.env && \
$REMOTE_UPDATE_SCRIPT"
if [ $? -ne 0 ]; then
echo "❌ Failed to execute update script on server."
@@ -133,6 +201,9 @@ if [ $? -ne 0 ]; then
fi
print_header "DEPLOYMENT COMPLETED SUCCESSFULLY"
echo "✅ New version deployed to ${REGION} environment!"
echo "🌐 Check your ${REGION} server to verify the deployment."
echo "✅ New version deployed to ${ENV} environment in ${HOST} with subdomain ${SUBDOMAIN}!"
if [ "$ENABLE_BASIC_AUTH" = true ]; then
echo "🔒 Basic authentication enabled with user: $BASIC_AUTH_USER"
fi
echo "🌐 Check your server to verify the deployment."
echo "======================================================="
+1
View File
@@ -13,6 +13,7 @@ const gitignorePath = path.resolve(__dirname, ".gitignore");
/** @type {import('eslint').Linter.Config[]} */
export default [
includeIgnoreFile(gitignorePath),
{ ignores: ["src/server/gatekeeper/**"] },
{ files: ["**/*.{js,mjs,cjs,ts}"] },
{ languageOptions: { globals: { ...globals.browser, ...globals.node } } },
pluginJs.configs.recommended,
+29 -11
View File
@@ -1,14 +1,32 @@
# AWS Configuration
AWS_REGION=region-name
AWS_ACCOUNT_ID=your-account-id
# SSH Configuration
SSH_KEY=~/.ssh/your-ssh-key
# ECR (Elastic Container Registry)
ECR_REPO_NAME=your-repo-name
# Docker Configuration
DOCKER_USERNAME=username
DOCKER_REPO=your-repo-name
DOCKER_TOKEN=your_docker_token_here
# EC2 Deployment Hosts
EC2_HOST_STAGING=ec2-user@your-staging-ip
EC2_HOST_PROD=ec2-user@your-production-ip
EC2_KEY=~/.ssh/your-key-file.pem
# Admin credentials
ADMIN_TOKEN=your_admin_token_here
# Application Secrets
ADMIN_TOKEN=your-admin-token
# Cloudflare Configuration
CF_ACCOUNT_ID=your_cloudflare_account_id
CF_API_TOKEN=your_cloudflare_api_token
DOMAIN=your-domain.com
# R2 Configuration
R2_ACCESS_KEY=your_r2_access_key
R2_SECRET_KEY=your_r2_secret_key
R2_BUCKET=your-bucket-name
# Server Hosts
SERVER_HOST_STAGING=123.456.78.90
SERVER_HOST_EU=123.456.78.91
SERVER_HOST_US=123.456.78.92
# Monitoring Credentials
MON_USERNAME=monitor_username
MON_PASSWORD=monitor_password
# Version
VERSION_TAG="latest"
+1580 -13
View File
File diff suppressed because it is too large Load Diff
+15 -1
View File
@@ -80,6 +80,18 @@
"@aws-sdk/client-s3": "^3.758.0",
"@datastructures-js/priority-queue": "^6.3.1",
"@google-cloud/secret-manager": "^5.6.0",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/api-logs": "^0.200.0",
"@opentelemetry/auto-instrumentations-node": "^0.58.0",
"@opentelemetry/exporter-metrics-otlp-http": "^0.200.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.200.0",
"@opentelemetry/host-metrics": "^0.36.0",
"@opentelemetry/resources": "^2.0.0",
"@opentelemetry/sdk-logs": "^0.200.0",
"@opentelemetry/sdk-metrics": "^2.0.0",
"@opentelemetry/sdk-node": "^0.200.0",
"@opentelemetry/semantic-conventions": "^1.32.0",
"@opentelemetry/winston-transport": "^0.11.0",
"@types/dompurify": "^3.0.5",
"@types/express": "^4.17.21",
"@types/google-protobuf": "^3.15.12",
@@ -95,7 +107,7 @@
"d3": "^7.9.0",
"discord.js": "^14.16.3",
"dompurify": "^3.1.7",
"dotenv": "^16.4.7",
"dotenv": "^16.5.0",
"express": "^4.21.1",
"express-rate-limit": "^7.5.0",
"google-auth-library": "^9.14.0",
@@ -104,6 +116,7 @@
"html-webpack-plugin": "^5.6.3",
"ip-anonymize": "^0.1.0",
"jimp": "^0.22.12",
"jose": "^6.0.10",
"lit": "^3.2.1",
"msgpack5": "^6.0.2",
"nanoid": "^3.3.6",
@@ -127,6 +140,7 @@
"webpack-dev-server": "^5.0.4",
"wheelnav": "^1.7.1",
"winston": "^3.17.0",
"winston-transport": "^4.9.0",
"ws": "^8.18.0",
"zod": "^3.23.8"
},
+999 -1
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 17 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 70 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 61 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 67 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 42 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 100 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 64 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 65 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 25 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 113 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 62 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 48 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 25 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 34 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 79 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 409 B

After

Width:  |  Height:  |  Size: 7.0 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 80 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 79 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 65 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 57 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 37 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 49 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 45 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 58 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 600 B

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 11 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="150" viewBox="0 0 150 150">
<image href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAADICAYAAACZBDirAAAAAXNSR0IArs4c6QAADSRJREFUeF7t3E+MXWUZx/Hv/TPTOy1tpdM2FIrSYlRMCcbEoCSEnYsSjDsJGHXhAnVjwoaFBsNGNiSuDFEXEkVwZSIpCzeGhUEWGDUY1ISKoWgtbYGWdqYz949950+saDmn5Tyd5/R+T9K06bz3uc/5PKe/vOee6XT4z9EDrgPuAu4BbgduBPoXrPGPCiigQJsEhsBrwAvAM8BzwFFgVE6is3YmJeT2n//CA2vhtxuYWwu/9TVtOml7VUABBYrABCghuAAcWwvBx4HD5e9LuJWd383AQ8DdwE6gq50CCihwlQmMgePAIeBR4JUSgDcADwL3A7su2BVeZefu6SiggAIrO8I3gCeBx0oA3nd+x/cIsM+dn5eHAgpMgUDZCZZb4IdLAD4FHAS2TcGJe4oKKKBAETgFPFsCsCThXmBGFwUUUGBKBJaBIyUAyx/KgxCf9k7J5D1NBRRY+SxwVEKv/MFDAQUUmDqBywrA8qJNnQ6b6TDb6TBDh577x6m7eDxhBTZKYDQpt64TliYTzjLh3GRyWTu5Sw7Acq883+1xW3+WT88M+FC3x55en62drt88uFFXg++rwBQJlEe4pydj/jka8vfxiN8uL/KH4RInxqPV/95xCUftAFzf9X2o2+fzgy0cnN3M7m6XWTr0O52VDxE9FFBAgSshUIJuOJmwxIRj4zGHls7yi8UzvDYeXtJusHYAllveT/Y38bW5rXyiP8sHuj13fFdi0r6HAgq8p0DZEb45HvHicIkfLpzmd8NzKyFY56gVgGXRrm6Pr85t5d7BNVzb6frIuI6uaxRQ4IoIlLgrIfj0uTP8aOE0b4xHtT4TrBWAg06HO2cGfGvLtezr9d35XZGR+iYKKHApAiv/vWO0zHfOvMXzy4u1doG1AnBHp8s3Nm/nvsGWlYcdHgoooEBGgVOTMT9bPMP3z77NyUmJxPc+agXgnm6P716zgztnB2zy5rfK1K8roMAGCSxOJvx6aYFvn3mTo+PqZ8K1AvCDvT4/2LqTj/dnvf3doMH6tgooUC1QIu+Py0t8/fTxlSfCVUetALyp1+cn23avfP7noYACCmQWODwa8qVTx3h11GAA/nTbbkoQeiiggAKZBUrwfdEAzDwie1NAgSgBAzBK1roKKJBewABMPyIbVECBKAEDMErWugookF7AAEw/IhtUQIEoAQMwSta6CiiQXsAATD8iG1RAgSgBAzBK1roKKJBewABMPyIbVECBKAEDMErWugookF7AAEw/IhtUQIEoAQMwSta6CiiQXsAATD8iG1RAgSgBAzBK1roKKJBewABMPyIbVECBKAEDMErWugookF7AAEw/IhtUQIEoAQMwSta6CiiQXsAATD8iG1RAgSgBAzBK1roKKJBewABMPyIbVECBKAEDMErWugookF7AAEw/IhtUQIEoAQMwSta6CiiQXsAATD8iG1RAgSgBAzBK1roKKJBewABMPyIbVECBKAEDMErWugookF7AAEw/IhtUQIEoAQMwSta6CiiQXsAATD8iG1RAgSgBAzBK1roKKJBewABMPyIbVECBKAEDMErWugookF7AAEw/IhtUQIEoAQMwSta6CiiQXsAATD8iG1RAgSgBAzBK1roKKJBewABMPyIbVECBKAEDMErWugookF7AAEw/IhtUQIEoAQMwSta6CiiQXsAATD8iG1RAgSgBAzBK1roKKJBewABMPyIbVECBKAEDMErWugookF7AAEw/IhtUQIEoAQMwSta6CiiQXsAATD8iG1RAgSiBxgNwb7fH97bOs7fbj+rZugoooEAjAkfGQ755+gRHxqPKeh1gUrVq0OnwkV6fAd2qpX5dAQUU2FCBRcb8dTRkcVIZbdQKwLKoRF/53UMBBRTILFBib1xnZ7eWadUxmfls7U0BBRS4TIFaO8DLrO3LFFBAgdQCBmDq8dicAgpEChiAkbrWVkCB1AIGYOrx2JwCCkQKGICRutZWQIHUAgZg6vHYnAIKRAoYgJG61lZAgdQCBmDq8dicAgpEChiAkbrWVkCB1AIGYOrx2JwCCkQKGICRutZWQIHUAgZg6vHYnAIKRAoYgJG61lZAgdQCBmDq8dicAgpEChiAkbrWVkCB1AIGYOrx2JwCCkQKGICRutZWQIHUAgZg6vHYnAIKRAoYgJG61lZAgdQCBmDq8dicAgpEChiAkbrWVkCB1AIGYOrx2JwCCkQKGICRutZWQIHUAgZg6vHYnAIKRAoYgJG61lZAgdQCBmDq8dicAgpEChiAkbrWVkCB1AIGYOrx2JwCCkQKGICRutZWQIHUAgZg6vHYnAIKRAoYgJG61lZAgdQCBmDq8dic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" x="7.500" y="32.813" width="135.000" height="84.375" />
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 38 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 58 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 41 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 52 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 52 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 99 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 44 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 432 KiB

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 33 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 34 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 67 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 87 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 156 KiB

After

Width:  |  Height:  |  Size: 94 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 48 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 230 KiB

After

Width:  |  Height:  |  Size: 78 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 43 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 37 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 64 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 83 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 54 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 441 KiB

After

Width:  |  Height:  |  Size: 50 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 21 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 22 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="150" viewBox="0 0 150 150">
<image href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAADICAYAAACZBDirAAAAAXNSR0IArs4c6QAAC3FJREFUeF7t3E+M3GUZB/Dv7M4WFgqtoS2QlkDZ3ohePGC84MVDISWe4YDeuGhMwISLIeIFEzhoPHAwEU2QeDNUwMSLXDR48KDhYNKlQNvwpyW2uLDt7uyOfdfdSDw4g3l3uy/v55c0v0139pnn/TxvvnlnZttB/nPNJrktyX1JTiS5N8kdSYafeowvCRAg0JLAKMmZJK8nOZnktSTvJVkrixhsrqSE3N1Xv/HoZvgdSjK/GX5bj2lp0XolQIBAERgnKSG4nOSDzRB8Lsmb5e9LuJWT30KSJ5I8kORAkhl2BAgQ+JwJrCe5kOTlJE8nWSwBeDjJY0keTnLwU6fCz9naLYcAAQIbJ8LzSV5I8mwJwIeunvieSnLUyc/2IECgA4FyEiwvgZ8sAfhikvuT3NzBwi2RAAECReCjJK+UACxJeCTJHBcCBAh0IrCa5GwJwPJF+SDEp72dTN4yCRDYeC9wrYRe+cJFgACB7gQEYHcjt2ACBLYEBKC9QIBAtwICsNvRWzgBAgLQHiBAoFsBAdjt6C2cAAEBaA8QINCtgADsdvQWToCAALQHCBDoVkAAdjt6CydAQADaAwQIdCsgALsdvYUTICAA7QECBLoVEIDdjt7CCRAQgPYAAQLdCgjAbkdv4QQICEB7gACBbgUEYLejt3ACBASgPUCAQLcCArDb0Vs4AQIC0B4gQKBbAQHY7egtnAABAWgPECDQrYAA7Hb0Fk6AgAC0BwgQ6FZAAHY7egsnQEAA2gMECHQrIAC7Hb2FEyAgAO0BAgS6FRCA3Y7ewgkQEID2AAEC3QoIwG5Hb+EECAhAe4AAgW4FBGC3o7dwAgQEoD1AgEC3AgKw29FbOAECAtAeIECgWwEB2O3oLZwAAQFoDxAg0K2AAOx29BZOgIAAtAcIEOhWQAB2O3oLJ0BAANoDBAh0KyAAux29hRMgIADtAQIEuhUQgN2O3sIJEBCA9gABAt0KCMBuR2/hBAgIQHuAAIFuBQRgt6O3cAIEBKA9QIBAtwICsNvRWzgBAgLQHiBAoFsBAdjt6C2cAAEBaA8QINCtgADsdvQWToCAALQHCBDoVkAAdjt6CydAQADaAwQIdCsgALsdvYUTIDBVAA4GgwyHw5S7iwABArtZYDweZzQapdwnXVMF4Pz8fO65556Uu4sAAQK7WWB5eTlvvPFGyn3SNVUAHj58OM8880zK3UWAAIHdLHDu3Lk8/vjjKfdJ11QBuLCwkJMnT6bcXQQIENjNAouLizlx4kTKfdI1VQAeO3Ysr776asrdRYAAgd0scOrUqRw/fjzlPukSgJOEfJ8AgaYEBGBT49IsAQI1BQRgTU21CBBoSkAANjUuzRIgUFNAANbUVIsAgaYEBGBT49IsAQI1BQRgTU21CBBoSkAANjUuzRIgUFNAANbUVIsAgaYEBGBT49IsAQI1BQRgTU21CBBoSkAANjUuzRIgUFNAANbUVIsAgaYEBGBT49IsAQI1BQRgTU21CBBoSkAANjUuzRIgUFNAANbUVIsAgaYEBGBT49IsAQI1BQRgTU21CBBoSkAANjUuzRIgUFNAANbUVIsAgaYEBGBT49IsAQI1BQRgTU21CBBoSkAANjUuzRIgUFNAANbUVIsAgaYEBGBT49IsAQI1BQRgTU21CBBoSkAANjUuzRIgUFNAANbUVIsAgaYEBGBT49IsAQI1BQRgTU21CBBoSkAANjUuzRIgUFNAANbUVIsAgaYEBGBT49IsAQI1BQRgTU21CBBoSkAANjUuzRIgUFNAANbUVIsAgaYEBGBT49IsAQI1BQRgTU21CBBoSkAANjUuzRIgUFNAANbUVIsAgaYEBGBT49IsAQI1BQRgTU21CBBoSkAANjUuzRIgUFNAANbUVIsAgaYEBGBT49IsAQI1BQRgTU21CBBoSkAANjUuzRIgUFNAANbUVIsAgaYEBGBT49IsAQI1BQRgTU21CBBoSkAANjUuzRIgUFNAANbUVIsAgaYEBGBT49IsAQI1BQRgTU21CBBoSqB+AC4s5JXfnsyxhWNNQWiWAIH+BE4tnsr9Jx5MCcJJ1yDJeNKDFu44kpd+8uOUu4sAAQK7WWDxzJk8+J3vZvHM2YltThWAR2/am1997as5unfvxIIeQIAAgWspcHppKQ/94Y85/c+liW1MFYB37ZnLL++8NeXuIkCAwG4WOL2ymkfefj9vraxObHO6AJwb5hdHDuSuueHEgh5AgACBaynw1uooj5y9kHKfdAnASUK+T4BAUwICsKlxaZYAgZoCArCmploECDQlIACbGpdmCRCoKSAAa2qqRYBAUwICsKlxaZYAgZoCArCmploECDQlIACbGpdmCRCoKSAAa2qqRYBAUwICsKlxaZYAgZoCArCmploECDQlIACbGpdmCRCoKSAAa2qqRYBAUwICsKlxaZYAgZoCArCmploECDQlIACbGpdmCRCoKSAAa2qqRYBAUwICsKlxaZYAgZoCArCmploECDQlIACbGpdmCRCoKSAAa2qqRYBAUwICsKlxaZYAgZoCArCmploECDQlIACbGpdmCRCoKSAAa2qqRYBAUwICsKlxaZYAgZoCArCmploECDQlIACbGpdmCRCoKSAAa2qqRYBAUwICsKlxaZYAgZoCArCmploECDQlIACbGpdmCRCoKSAAa2qqRYBAUwICsKlxaZYAgZoCArCmploECDQlIACbGpdmCRCoKSAAa2qqRYBAUwICsKlxaZYAgZoCArCmploECDQlIACbGpdmCRCoKSAAa2qqRYBAUwICsKlxaZYAgZoCArCmploECDQlIACbGpdmCRCoKSAAa2qqRYBAUwICsKlxaZYAgZoCArCmploECDQlIACbGpdmCRCoKVA9AO+cG+b5wwdy955hzT7VIkCAQHWBN1dG+ea5C3l7dTSx9iDJeNKjjszN5qe335IvXbcns+UnXAQIENiFAmvj5K9XVvLtdz/MmdW1iR1OFYC3Dmfz/YP78vUb53P9jAScqOoBBAhcE4HL6+P8/uPl/PD8pbw/qhSA+2dn8q39ezf+7JuduSYL86QECBD4XwLlpeyltfU8f3EpP7+4lItr6xPBpjoB7hkM8uX5PfnBof05NjfM7MApcKKsBxAgsKMCo/E4f18Z5akPLuYvl1eyMp747l6mCsDyoC/MzuThfTfmkf17c2A4u/GDLgIECOwGgRJ1F0Zr+dnFpfz60scbp7/J8ZfpArAscDZJ+TT4ewf35d7rr9sIRG8H7obR64FA3wLr4+Qfa+v58+Ur+dH5S3lndZTJ7/7922yqE+AW79xgkLvmhvnGzTfk+N75HBrOpLw8Hg4GGwHpIkCAwE4IlIArL3nLy9wPRuv53dJyfvPRJzm9OsrqFC99t3r8TAG4dRK8ZXY2X5yfy1fmr8+dc7O5fTibm2Zm4q3BnRi95yDQt0A58S2tr+fd0VreWV3Ln5Yv52/Lq/lwbW3qk9//HYBbx8brBoPcMDPYOAHODZKZDLwv2Pe+tHoCOyJQ3tsr7/CtjrNxAvxkfZwr4/FU7/n9d4Of+QS4Iyv0JAQIENgBgRKAq5ufcfhgdwfAPQUBArtCoBwk10rovZnkSJK5XdGWJggQILD9AuXgd7YE4ItJ7k9y8/Y/p2cgQIDArhD4KMkrJQAfSvJUkqNX7/6d266YjSYIENhGgfJv5Mor3ydLAB5O8liSh5Mc3PzdwG18bqUJECBwzQTKe3/nk7yQ5NkSgOV3mBeSPJHkgSQHnASv2XA8MQEC2ydQTn4Xkryc5Okki1uf/Jb/6fTuJI8mOZHkUJL5JOXvfTq8fQNRmQCB7RUoJ77yP6Mub578Xkry3OZL4NGnw62cBG9Lct9mCN6b5I7NENzeFlUnQIDA9giU8DuT5PUkJ5O8dvWg9175FZjydP8C0fiMTBSv05cAAAAASUVORK5CYII=" x="7.500" y="32.813" width="135.000" height="84.375" />
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 16 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="150" viewBox="0 0 150 150">
<image href="data:image/png;base64,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" x="7.500" y="32.813" width="135.000" height="84.375" />
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 52 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 56 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 507 KiB

After

Width:  |  Height:  |  Size: 43 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 208 KiB

After

Width:  |  Height:  |  Size: 51 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 262 KiB

After

Width:  |  Height:  |  Size: 34 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 241 KiB

After

Width:  |  Height:  |  Size: 37 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 38 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 62 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Some files were not shown because too many files have changed in this diff Show More