Skip to content

Commit f9ad218

Browse files
committed
Initial Commit
0 parents  commit f9ad218

18 files changed

Lines changed: 2003 additions & 0 deletions

.env.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
DOPPLER_TOKEN=
2+
POSTGRES_PASSWORD=
3+
POSTGRES_USER=
4+
TUNNEL_TOKEN=
5+
MINIO_ROOT_USER=
6+
MINIO_ROOT_PASSWORD=

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.idea
2+
.env
3+
node_modules
4+
*.iml

Dockerfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM node:18-alpine3.18
2+
3+
RUN wget -q -t3 'https://packages.doppler.com/public/cli/rsa.8004D9FF50437357.key' -O /etc/apk/keys/cli@doppler-8004D9FF50437357.rsa.pub && \
4+
echo 'https://packages.doppler.com/public/cli/alpine/any-version/main' | tee -a /etc/apk/repositories && \
5+
apk add doppler
6+
7+
WORKDIR /apiserver
8+
COPY .. .
9+
RUN yarn
10+
RUN yarn build
11+
12+
EXPOSE 8787
13+
CMD ["doppler", "run", "--", "yarn", "runserver"]

docker-compose.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
services:
2+
tunnel:
3+
image: cloudflare/cloudflared:latest
4+
restart: unless-stopped
5+
command: "tunnel run"
6+
volumes:
7+
- ./data/cloudflared:/etc/cloudflared
8+
env_file:
9+
- .env
10+
networks:
11+
- webnet
12+
13+
rpcavatar:
14+
build: .
15+
container_name: "rpcavatar"
16+
restart: unless-stopped
17+
env_file:
18+
- .env
19+
ports:
20+
- 8787:8787
21+
networks:
22+
- webnet
23+
24+
db:
25+
image: postgres:alpine
26+
restart: unless-stopped
27+
env_file:
28+
- .env
29+
ports:
30+
- 5432:5432
31+
volumes:
32+
- ./data/postgres_data:/var/lib/postgresql/data
33+
networks:
34+
- webnet
35+
36+
adminer:
37+
image: adminer
38+
restart: always
39+
ports:
40+
- 8087:8080
41+
networks:
42+
- webnet
43+
44+
minio:
45+
image: minio/minio:latest
46+
container_name: minio
47+
environment:
48+
- MINIO_ROOT_USER=minioadmin
49+
- MINIO_ROOT_PASSWORD=minioadmin
50+
ports:
51+
- "9001:9001"
52+
volumes:
53+
- ./data/minio:/data
54+
command: server /data --console-address ":9001"
55+
networks:
56+
- webnet
57+
58+
networks:
59+
webnet:

license.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 HypherionSA
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

package.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "rpc-image-server",
3+
"version": "1.0.0",
4+
"description": "A relay server to allow local files to be used as icons in Discord RPCs",
5+
"author": "HypherionSA",
6+
"license": "MIT",
7+
"private": true,
8+
"scripts": {
9+
"lint": "eslint .",
10+
"lint:fix": "eslint --fix .",
11+
"format": "prettier --write 'src/**/*.ts'",
12+
"devserver": "ts-node -r dotenv/config ./src/index.ts",
13+
"build": "tsc",
14+
"runserver": "node -r dotenv/config dist/index.js"
15+
},
16+
"dependencies": {
17+
"@hono/node-server": "^1.14.0",
18+
"@mikro-orm/core": "^6.4.12",
19+
"@mikro-orm/postgresql": "^6.4.12",
20+
"aws-sdk": "^2.1692.0",
21+
"dotenv": "^16.4.7",
22+
"file-type": "^20.4.1",
23+
"hono": "^4.7.6",
24+
"minio": "^8.0.5",
25+
"sharp": "^0.34.1",
26+
"ts-node": "^10.9.2"
27+
},
28+
"devDependencies": {
29+
"@types/minio": "^7.1.1",
30+
"@types/node": "^22.14.0",
31+
"typescript": "^5.8.3"
32+
},
33+
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
34+
}

readme.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
### RPCRelay Server
2+
3+
An experimental project to allow discord RPC mods like Simple RPC use local images, as RPC icons.
4+
5+
***
6+
7+
### TODO: Fill this out with self-hosting information

src/cleanup.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import Database from './const/database';
2+
import { EntityManager } from '@mikro-orm/core';
3+
import { FileHashes } from './database/filehashes';
4+
import { S3Storage } from './storage';
5+
6+
const storage = new S3Storage();
7+
8+
/**
9+
* Cleanup logic, to remove images after 7 days. This is just to save on storage
10+
*/
11+
export class Cleanup {
12+
13+
/**
14+
* Register Cleanup Job, that runs once every 24 hours
15+
*/
16+
public startCleanupJob() {
17+
const DAY_IN_MS = 1000 * 60 * 60 * 24;
18+
setInterval(async () => {
19+
try {
20+
await this.deleteOldImages();
21+
} catch (e) {}
22+
}, DAY_IN_MS)
23+
}
24+
25+
/**
26+
* Clean up the images from both MINIO (or S3 in the future), and the database
27+
* @private
28+
*/
29+
private async deleteOldImages() {
30+
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
31+
32+
const db = await Database.getInstance()
33+
const em: EntityManager = db.em
34+
const hashes = await em.findAll(FileHashes)
35+
36+
if (hashes.length > 0) {
37+
for (let i = 0; i < hashes.length; i++) {
38+
const hash = hashes[i];
39+
40+
if (hash.uploadedAt < sevenDaysAgo) {
41+
em.remove(hash);
42+
await storage.deleteFile(hash.cdnUrl);
43+
}
44+
}
45+
}
46+
47+
await em.flush()
48+
}
49+
50+
}

src/const/database.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { MikroORM } from '@mikro-orm/core';
2+
import config from '../mikro-orm.config';
3+
4+
/**
5+
* Database Client Initialization
6+
*/
7+
class Database {
8+
private static instance: MikroORM;
9+
10+
public static async getInstance(): Promise<MikroORM> {
11+
if (!Database.instance || !await Database.instance.isConnected()) {
12+
Database.instance = await MikroORM.init(config);
13+
}
14+
15+
return Database.instance;
16+
}
17+
}
18+
19+
export default Database;

src/const/environment.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Environment Variables
3+
*/
4+
export default {
5+
postgresql: {
6+
host: process.env.DATABASE_HOST || '127.0.0.1',
7+
database: process.env.DATABASE_NAME || 'rpc',
8+
username: process.env.DATABASE_USER || 'rpc',
9+
password: process.env.DATABASE_PASSWORD || 'rpc',
10+
port: process.env.DATABASE_PORT || 5432,
11+
},
12+
bucket: {
13+
url: process.env.S3_HOST || '127.0.0.1',
14+
accessKey: process.env.S3_ACCESSKEY || 'minioadmin',
15+
secret: process.env.S3_SECRET || 'minioadmin',
16+
bucketName: process.env.S3_BUCKET || 'rpc2',
17+
},
18+
running_env: process.env.ENV || 'dev',
19+
};

0 commit comments

Comments
 (0)