forked from simrail/simrail.pro
Merge pull request 'v1.1.0' (#10) from dev into main
Reviewed-on: alekswilc/simrail-logs#10 Reviewed-by: Aleksander Wilczyński <aleks@alekswilc.dev>
This commit is contained in:
commit
0f46e29f0e
BIN
.gitea/assets/image-2.png
Normal file
BIN
.gitea/assets/image-2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
13
package.json
13
package.json
@ -1,16 +1,13 @@
|
||||
{
|
||||
"name": "play-history",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"name": "simrail-logs",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"postbuild": "copyfiles --error --up 1 src/http/views/*.* dist",
|
||||
"postbuild": "copyfiles --error --up 1 src/http/views/**/* dist",
|
||||
"dev": "npm run build && doppler run node dist"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"author": "Aleksander <alekswilc> Wilczyński",
|
||||
"license": "AGPL-3.0-only",
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/node": "^22.0.0",
|
||||
|
19
readme.md
19
readme.md
@ -3,26 +3,17 @@ Prosty projekt, logujący wyjścia z posterunków.
|
||||
|
||||
### Hej! Podoba Ci się projekt? Polajkuj post na [forum](https://forum.simrail.eu/topic/9142-logowanie-wyj%C5%9B%C4%87-z-posterunk%C3%B3w/), a będzie mi miło! Dla Ciebie to jedno kliknięcie, a dla mnie motywacja do rozwijania projektu
|
||||
|
||||
## Aplikacja
|
||||
https://simrail.alekswilc.dev/
|
||||
|
||||
## Cele
|
||||
- Ułatwienie zgłaszania graczy, którzy robią "Hit and Run" (psuje i wychodze z posterunku)
|
||||
- Statystyki
|
||||
|
||||
## Dalszy rozwój
|
||||
- Obsługa pociagów, a nie tylko posterunków
|
||||
|
||||
# Jak korzystać?
|
||||
|
||||
- Otwórz https://simrail.alekswilc.dev/
|
||||
- Znajdź interesujący Cie rekord.
|
||||
- Naciśnij przycisk więcej
|
||||
- Naciśnij na okienko z angielskim zapisem informacji (lub przycisk kopiuj link)
|
||||
- Wklej na kanał #multiplayer-help-request z opisem sytuacji.
|
||||
- Gotowe, kolejny troll jest zgłoszony.
|
||||
|
||||

|
||||
- Obsługa pociagów, a nie tylko posterunków (#8)
|
||||
|
||||
# Zgłaszanie błedów
|
||||
Aplikacja jest w wersji testowej, i obsługuje tylko serwer PL2
|
||||
|
||||
Jak zgłosić błąd?
|
||||
- Otwórz https://git.alekswilc.dev/alekswilc/simrail-logs/issues
|
||||
- Załóż konto (to tylko kilka kliknięć, a twoje zgłoszenie bardzo mi pomoże)
|
||||
|
103
src/http/api.ts
103
src/http/api.ts
@ -1,103 +0,0 @@
|
||||
import express from 'express';
|
||||
import { MLog } from '../mongo/logs.js';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import path from 'node:path';
|
||||
import dayjs from 'dayjs';
|
||||
import { PlayerUtil } from '../util/PlayerUtil.js';
|
||||
import { msToTime } from '../util/time.js';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
|
||||
export class ApiModule {
|
||||
public static load() {
|
||||
const app = express();
|
||||
|
||||
app.set('view engine', 'ejs');
|
||||
app.set('views', __dirname + '/views')
|
||||
|
||||
app.get('/', async (req, res) => {
|
||||
const records = await MLog.find()
|
||||
.sort({ leftDate: -1 })
|
||||
.limit(30)
|
||||
res.render('index.ejs', {
|
||||
records,
|
||||
dayjs,
|
||||
msToTime
|
||||
});
|
||||
})
|
||||
|
||||
const generateSearch = (regex: RegExp) => [
|
||||
{
|
||||
stationName: { $regex: regex },
|
||||
},
|
||||
{
|
||||
userUsername: { $regex: regex },
|
||||
},
|
||||
{
|
||||
stationShort: { $regex: regex },
|
||||
},
|
||||
{
|
||||
userSteamId: { $regex: regex },
|
||||
},
|
||||
{
|
||||
server: { $regex: regex },
|
||||
}
|
||||
]
|
||||
|
||||
app.get('/search', async (req, res) => {
|
||||
if (!req.query.q) return res.redirect('/');
|
||||
const s = req.query.q.toString().split(',').map(x => new RegExp(x, "i"));
|
||||
|
||||
const records = await MLog.aggregate([
|
||||
{
|
||||
$match: {
|
||||
$and: [
|
||||
...s.map(x => ({ $or: generateSearch(x) }))
|
||||
]
|
||||
}
|
||||
}
|
||||
])
|
||||
.sort({ leftDate: -1 })
|
||||
.limit(30)
|
||||
res.render('search.ejs', {
|
||||
records,
|
||||
dayjs,
|
||||
q: req.query.q,
|
||||
msToTime
|
||||
});
|
||||
})
|
||||
|
||||
app.get('/details/:id', async (req, res) => {
|
||||
if (!req.params.id) return res.redirect('/');
|
||||
const record = await MLog.findOne({ id: req.params.id });
|
||||
const player = await PlayerUtil.getPlayer(record?.userSteamId!);
|
||||
|
||||
res.render('details.ejs', {
|
||||
record,
|
||||
dayjs,
|
||||
player,
|
||||
msToTime
|
||||
});
|
||||
})
|
||||
|
||||
app.get('/api/last', async (req, res) => {
|
||||
const records = await MLog.find()
|
||||
.sort({ leftDate: -1 })
|
||||
.limit(30)
|
||||
res.json({ code: 200, records });
|
||||
})
|
||||
|
||||
app.get('/api/search', async (req, res) => {
|
||||
if (!req.query.q) return res.send('invalid');
|
||||
const records = await MLog.find({ $text: { $search: req.query.q as string } })
|
||||
.sort({ leftDate: -1 })
|
||||
.limit(30)
|
||||
|
||||
res.json({ code: 200, records });
|
||||
})
|
||||
|
||||
app.listen(2005);
|
||||
}
|
||||
}
|
129
src/http/routes/stations.ts
Normal file
129
src/http/routes/stations.ts
Normal file
@ -0,0 +1,129 @@
|
||||
import { Router } from 'express';
|
||||
import { MLog, raw_schema } from '../../mongo/logs.js';
|
||||
import dayjs from 'dayjs';
|
||||
import { PlayerUtil } from '../../util/PlayerUtil.js';
|
||||
import { msToTime } from '../../util/time.js';
|
||||
import { PipelineStage } from 'mongoose';
|
||||
|
||||
const generateSearch = (regex: RegExp) => [
|
||||
{
|
||||
stationName: { $regex: regex },
|
||||
},
|
||||
{
|
||||
userUsername: { $regex: regex },
|
||||
},
|
||||
{
|
||||
stationShort: { $regex: regex },
|
||||
},
|
||||
{
|
||||
userSteamId: { $regex: regex },
|
||||
},
|
||||
{
|
||||
server: { $regex: regex },
|
||||
}
|
||||
]
|
||||
|
||||
export class StationsRoute {
|
||||
static load() {
|
||||
const app = Router();
|
||||
|
||||
app.get('/', async (req, res) => {
|
||||
const s = req.query.q?.toString().split(',').map(x => new RegExp(x, "i"));
|
||||
|
||||
const filter: PipelineStage[] = [];
|
||||
|
||||
|
||||
s && filter.push({
|
||||
$match: {
|
||||
$and: [
|
||||
...s.map(x => ({ $or: generateSearch(x) }))
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const records = await MLog.aggregate(filter)
|
||||
.sort({ leftDate: -1 })
|
||||
.limit(30)
|
||||
res.render('stations/index.ejs', {
|
||||
records,
|
||||
dayjs,
|
||||
q: req.query.q,
|
||||
msToTime
|
||||
});
|
||||
})
|
||||
|
||||
app.get('/details/:id', async (req, res) => {
|
||||
if (!req.params.id) return res.redirect('/stations/');
|
||||
const record = await MLog.findOne({ id: req.params.id });
|
||||
const player = await PlayerUtil.getPlayer(record?.userSteamId!);
|
||||
|
||||
res.render('stations/details.ejs', {
|
||||
record,
|
||||
dayjs,
|
||||
player,
|
||||
msToTime
|
||||
});
|
||||
})
|
||||
|
||||
app.get('/leaderboard/', async (req, res) => {
|
||||
const s = req.query.q?.toString().split(',').map(x => new RegExp(x, "i"));
|
||||
|
||||
const data = Object.keys(raw_schema)
|
||||
.reduce((o, key) => ({ ...o, [key]: `$${key}` }), {});
|
||||
|
||||
const filter: PipelineStage[] = [
|
||||
{
|
||||
$project: {
|
||||
// record.leftDate - record.joinedDate
|
||||
result: { $subtract: ['$leftDate', '$joinedDate'] },
|
||||
...data
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
s && filter.unshift(
|
||||
{
|
||||
$match: {
|
||||
$and: [
|
||||
...s.map(x => ({ $or: generateSearch(x) }))
|
||||
]
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
const records = await MLog.aggregate(filter)
|
||||
.sort({ result: -1 })
|
||||
.limit(30)
|
||||
res.render('stations/leaderboard.ejs', {
|
||||
records,
|
||||
dayjs,
|
||||
q: req.query.q,
|
||||
msToTime
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
// API ENDPOINTS
|
||||
// CREATE AN ISSUE IF YOU NEED API ACCESS: https://git.alekswilc.dev/alekswilc/simrail-logs/issues
|
||||
/*
|
||||
app.get('/api/last', async (req, res) => {
|
||||
const records = await MLog.find()
|
||||
.sort({ leftDate: -1 })
|
||||
.limit(30)
|
||||
res.json({ code: 200, records });
|
||||
})
|
||||
|
||||
app.get('/api/search', async (req, res) => {
|
||||
if (!req.query.q) return res.send('invalid');
|
||||
const records = await MLog.find({ $text: { $search: req.query.q as string } })
|
||||
.sort({ leftDate: -1 })
|
||||
.limit(30)
|
||||
|
||||
res.json({ code: 200, records });
|
||||
})*/
|
||||
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
26
src/http/server.ts
Normal file
26
src/http/server.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import express from 'express';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import path from 'node:path';
|
||||
import { StationsRoute } from './routes/stations.js';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
|
||||
export class ApiModule {
|
||||
public static load() {
|
||||
const app = express();
|
||||
|
||||
app.set('view engine', 'ejs');
|
||||
app.set('views', __dirname + '/views')
|
||||
|
||||
app.get('/', (_, res) => res.render('home'));
|
||||
|
||||
// backward compatible
|
||||
app.get('/details/:id', (req, res) => res.redirect('/stations/details/'+req.params.id));
|
||||
|
||||
app.use('/stations/', StationsRoute.load());
|
||||
|
||||
app.listen(2005);
|
||||
}
|
||||
}
|
7
src/http/views/_modules/footer.ejs
Normal file
7
src/http/views/_modules/footer.ejs
Normal file
@ -0,0 +1,7 @@
|
||||
<div style="font-size: 13.5px;">
|
||||
<p>Made with <span style="color: red;">❤️</span> by <a href="https://www.alekswilc.dev/">alekswilc</a> for SimRail Community</p>
|
||||
<p><a href="https://git.alekswilc.dev/alekswilc/">Open Source</a></p>
|
||||
<% if (thanks) { %>
|
||||
<p>Podziękowania dla <a href="https://discord.com/users/1079005960653254656">AQUALYTH</a>, osób lajkujących <a href="https://forum.simrail.eu/topic/9142-logowanie-wyj%C5%9B%C4%87-z-posterunk%C3%B3w/">posta</a>, osób użytkujących strone i całego community Simrail <span style="color: red;">❤️</span></p>
|
||||
<% } %>
|
||||
</div>
|
21
src/http/views/_modules/header.ejs
Normal file
21
src/http/views/_modules/header.ejs
Normal file
@ -0,0 +1,21 @@
|
||||
<header>
|
||||
<h1><a style="color: white; text-decoration: none;" href="/">SimRail Logs</a></h1>
|
||||
|
||||
<% if (section==='stations' ) { %>
|
||||
<nav style="margin-bottom: 0;">
|
||||
<a href="/">Strona Główna</a> /
|
||||
<a href="https://git.alekswilc.dev/alekswilc/simrail-logs/issues/8">Logi pociągów</a>
|
||||
</nav>
|
||||
<nav>
|
||||
<a href="/stations/">Logi posterunków</a> /
|
||||
<a href="/stations/leaderboard">Tablica godzin</a>
|
||||
</nav>
|
||||
<% } else {%>
|
||||
<a href="/stations/">Logi posterunków</a> /
|
||||
<a href="https://git.alekswilc.dev/alekswilc/simrail-logs/issues/8">Logi pociągów</a>
|
||||
<% } %>
|
||||
<br />
|
||||
<p style="color: darkorange; font-size: 14px;">Hej! Podoba Ci się projekt? Polajkuj post na <a
|
||||
href="https://forum.simrail.eu/topic/9142-logowanie-wyj%C5%9B%C4%87-z-posterunk%C3%B3w/">forum</a>, a będzie
|
||||
mi miło! Dla Ciebie to jedno kliknięcie, a dla mnie motywacja do rozwijania projektu.</p>
|
||||
</header>
|
113
src/http/views/home.ejs
Normal file
113
src/http/views/home.ejs
Normal file
@ -0,0 +1,113 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>simrail.alekswilc.dev</title>
|
||||
<meta name="description" content="Simrail Utils">
|
||||
<meta property="og:title" content="simrail.alekswilc.dev">
|
||||
<meta property="og:url" content="https://simrail.alekswilc.dev">
|
||||
<meta property="og:description" content="Simrail Utils">
|
||||
<meta property="og:type" content="website">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/open-fonts@1.1.1/fonts/inter.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@exampledev/new.css@1.1.2/new.min.css">
|
||||
|
||||
<style>
|
||||
p {
|
||||
margin: 1%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<%- include('_modules/header.ejs', { section:'home' }) %>
|
||||
|
||||
<p>Prosty projekt, logujący wyjścia z posterunków.</p>
|
||||
<h3>Cele projektu</h3>
|
||||
<p>Główne założenia</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Ułatwienie zgłaszania graczy, którzy robią "Hit and Run" (psuje i wychodze z posterunku)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Statystyki</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Rozwój aplikacji</h3>
|
||||
<p>Planowane funkcjonalności</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Obsługa pociągów (<a href="https://git.alekswilc.dev/alekswilc/simrail-logs/issues/8">#8</a>)</p>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Informacje dodatkowe</h3>
|
||||
<details>
|
||||
<summary>
|
||||
Zgłaszanie błędów i propozycji
|
||||
</summary>
|
||||
|
||||
<h6>Zgłaszanie błedów</h6>
|
||||
<ul>
|
||||
<li>Otwórz <a
|
||||
href="https://git.alekswilc.dev/alekswilc/simrail-logs/issues">https://git.alekswilc.dev/alekswilc/simrail-logs/issues</a>
|
||||
</li>
|
||||
<li>Zaloguj się (np poprzez Discorda)</li>
|
||||
<li>Naciśnij przycisk "New issue" ("Nowe zgłoszenie")</li>
|
||||
<li>W tytule napisz krótki opis (np. Problem z wyświetleniem strony)</li>
|
||||
<li>Opisz problem (kiedy występuje, podaj linki, postaraj sie napisać jak moge odtworzyć ten błąd, jak
|
||||
powinna zachowywać sie aplikacja bez tego błędu)</li>
|
||||
<li>Poczekaj na informacje z mojej strony</li>
|
||||
<li>Dziekuje :)</li>
|
||||
</ul>
|
||||
|
||||
<img src="https://git.alekswilc.dev/alekswilc/simrail-logs/raw/branch/main/.gitea/assets/image-1.png">
|
||||
|
||||
|
||||
<h6>Zgłaszanie propozycji</h6>
|
||||
<ul>
|
||||
<li>Otwórz <a
|
||||
href="https://git.alekswilc.dev/alekswilc/simrail-logs/issues">https://git.alekswilc.dev/alekswilc/simrail-logs/issues</a>
|
||||
</li>
|
||||
<li>Zaloguj się (np poprzez Discorda)</li>
|
||||
<li>Naciśnij przycisk "New issue" ("Nowe zgłoszenie")</li>
|
||||
<li>W tytule napisz krótki opis (np. Logi wejścia i wyjścia z pociągów)</li>
|
||||
<li>Opisz propozycje (dokładnie co z dyżurkami ale dla pociągów)</li>
|
||||
<li>Poczekaj na informacje z mojej strony</li>
|
||||
<li>Dziekuje :)</li>
|
||||
</ul>
|
||||
|
||||
<img src="https://git.alekswilc.dev/alekswilc/simrail-logs/raw/branch/main/.gitea/assets/image-2.png">
|
||||
</details>
|
||||
|
||||
|
||||
|
||||
<h2>Licencja</h2>
|
||||
<details>
|
||||
<summary>
|
||||
Copyright (C) 2024 Aleksander <alekswilc> Wilczyński
|
||||
</summary>
|
||||
|
||||
|
||||
<code style="white-space: pre-line">This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see https://www.gnu.org/licenses/.</code>
|
||||
</details>
|
||||
|
||||
<hr>
|
||||
<%- include('_modules/footer.ejs', { thanks: true }) %>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,89 +1,86 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>simrail.alekswilc.dev</title>
|
||||
<meta name="description"
|
||||
content="<%= record.stationName %> | <%= record.userUsername %> | <%= dayjs(record.leftDate).format('hh:mm DD/MM/YYYY') %>">
|
||||
<meta property="og:title" content="Simrail Log">
|
||||
<meta property="og:url" content="https://simrail.alekswilc.dev/details/<%= record.id %>/">
|
||||
<meta property="og:description"
|
||||
content="<%= record.stationName %> | <%= record.userUsername %> | <%= dayjs(record.leftDate).format('hh:mm DD/MM/YYYY') %>"">
|
||||
<meta property=" og:type" content="website">
|
||||
<meta property="og:image" content="<%= record.userAvatar %>" />
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/open-fonts@1.1.1/fonts/inter.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@exampledev/new.css@1.1.2/new.min.css">
|
||||
|
||||
<style>
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
function copydata() {
|
||||
navigator.clipboard.writeText(document.getElementById('data').textContent.replace(/ /g, '').split('\n').filter(x => x).join(''))
|
||||
|
||||
}
|
||||
|
||||
function copylink() {
|
||||
navigator.clipboard.writeText("https://simrail.alekswilc.dev/details/<%= record.id %>/")
|
||||
}
|
||||
</script>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<h1><a style="color: white; text-decoration: none;" href="/">SimRail Logs</a></h1>
|
||||
<p><a href="https://git.alekswilc.dev/alekswilc/simrail-logs">Dokumentacja</a></p>
|
||||
<br />
|
||||
<p style="color: darkorange;">Hej! Podoba Ci się projekt? Polajkuj post na <a href="https://forum.simrail.eu/topic/9142-logowanie-wyj%C5%9B%C4%87-z-posterunk%C3%B3w/">forum</a>, a będzie mi miło! Dla Ciebie to jedno kliknięcie, a dla mnie motywacja do rozwijania projektu</p>
|
||||
</header>
|
||||
|
||||
<div class="details">
|
||||
|
||||
<p>Użytkownik: <a href="<%= player.profileurl %>">
|
||||
<%= record.userUsername %>
|
||||
</a></p>
|
||||
<p>Stacja: <%= record.stationName %>
|
||||
</p>
|
||||
<p>Serwer: <%= record.server.toUpperCase() %>
|
||||
</p>
|
||||
<p>Data wejścia: <%= record.joinedDate ? dayjs(record.joinedDate).format('HH:mm DD/MM/YYYY') : '--:-- --/--/--'
|
||||
%> (<%= record.joinedDate ? dayjs(record.joinedDate).fromNow() : '--' %>)</p>
|
||||
<p>Data wyjścia: <%= dayjs(record.leftDate).format('HH:mm DD/MM/YYYY') %> (<%= dayjs(record.leftDate).fromNow()
|
||||
%>)</p>
|
||||
<p>Spędzony czas: <%= record.joinedDate ? msToTime(record.leftDate - record.joinedDate) : '--' %>
|
||||
</p>
|
||||
|
||||
<br />
|
||||
<code class="clickable" style="white-space: pre-line" onclick="copydata()" id="data">;station: <%= record.stationName %>
|
||||
;steam: <%= record.userSteamId %>
|
||||
;server: <%= record.server %>
|
||||
;name: <%= record.userUsername %>
|
||||
;joined: <%=record.joinedDate ? dayjs(record.joinedDate).format() : 'no-data'%>
|
||||
;left: <%=dayjs(record.leftDate).format()%>
|
||||
;url: https://simrail.alekswilc.dev/details/<%= record.id %>/
|
||||
</code>
|
||||
<br />
|
||||
<p><button onclick="copylink()">Kopiuj link</button></p>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>simrail.alekswilc.dev</title>
|
||||
<meta name="description"
|
||||
content="<%= record.stationName %> | <%= record.userUsername %> | <%= dayjs(record.leftDate).format('hh:mm DD/MM/YYYY') %>">
|
||||
<meta property="og:title" content="Simrail Log">
|
||||
<meta property="og:url" content="https://simrail.alekswilc.dev/details/<%= record.id %>/">
|
||||
<meta property="og:description"
|
||||
content="<%= record.stationName %> | <%= record.userUsername %> | <%= dayjs(record.leftDate).format('hh:mm DD/MM/YYYY') %>"">
|
||||
<meta property=" og:type" content="website">
|
||||
<meta property="og:image" content="<%= record.userAvatar %>" />
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/open-fonts@1.1.1/fonts/inter.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@exampledev/new.css@1.1.2/new.min.css">
|
||||
|
||||
<style>
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
function copydata() {
|
||||
navigator.clipboard.writeText(document.getElementById('data').textContent.replace(/ /g, '').split('\n').filter(x => x).join(''))
|
||||
|
||||
}
|
||||
|
||||
function copylink() {
|
||||
navigator.clipboard.writeText("https://simrail.alekswilc.dev/details/<%= record.id %>/")
|
||||
}
|
||||
</script>
|
||||
|
||||
<body>
|
||||
<%- include('../_modules/header.ejs', { section: 'stations' }) %>
|
||||
|
||||
<div class="details">
|
||||
|
||||
<p>Użytkownik: <a href="<%= player.profileurl %>">
|
||||
<%= record.userUsername %>
|
||||
</a></p>
|
||||
<p>Stacja: <%= record.stationName %>
|
||||
</p>
|
||||
<p>Serwer: <%= record.server.toUpperCase() %>
|
||||
</p>
|
||||
<p>Data wejścia: <%= record.joinedDate ? dayjs(record.joinedDate).format('HH:mm DD/MM/YYYY') : '--:-- --/--/--'
|
||||
%> (<%= record.joinedDate ? dayjs(record.joinedDate).fromNow() : '--' %>)</p>
|
||||
<p>Data wyjścia: <%= dayjs(record.leftDate).format('HH:mm DD/MM/YYYY') %> (<%= dayjs(record.leftDate).fromNow()
|
||||
%>)</p>
|
||||
<p>Spędzony czas: <%= record.joinedDate ? msToTime(record.leftDate - record.joinedDate) : '--' %>
|
||||
</p>
|
||||
|
||||
<br />
|
||||
<code class="clickable" style="white-space: pre-line" onclick="copydata()" id="data">;station: <%= record.stationName %>
|
||||
;steam: <%= record.userSteamId %>
|
||||
;server: <%= record.server %>
|
||||
;name: <%= record.userUsername %>
|
||||
;joined: <%=record.joinedDate ? dayjs(record.joinedDate).format() : 'no-data'%>
|
||||
;left: <%=dayjs(record.leftDate).format()%>
|
||||
;url: https://simrail.alekswilc.dev/details/<%= record.id %>/
|
||||
</code>
|
||||
<br />
|
||||
<p><button onclick="copylink()">Kopiuj link</button></p>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
<%- include('../_modules/footer.ejs', { thanks: false }) %>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,85 +1,91 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>simrail.alekswilc.dev</title>
|
||||
<meta name="description" content="Simrail Utils">
|
||||
<meta property="og:title" content="simrail.alekswilc.dev">
|
||||
<meta property="og:url" content="https://simrail.alekswilc.dev">
|
||||
<meta property="og:description" content="Simrail Utils">
|
||||
<meta property="og:type" content="website">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/open-fonts@1.1.1/fonts/inter.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@exampledev/new.css@1.1.2/new.min.css">
|
||||
|
||||
<style>
|
||||
p {
|
||||
margin: 1%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<h1><a style="color: white; text-decoration: none;" href="/">SimRail Logs</a></h1>
|
||||
<p><a href="https://git.alekswilc.dev/alekswilc/simrail-logs">Dokumentacja</a></p>
|
||||
<br />
|
||||
<p style="color: darkorange;">Hej! Podoba Ci się projekt? Polajkuj post na <a href="https://forum.simrail.eu/topic/9142-logowanie-wyj%C5%9B%C4%87-z-posterunk%C3%B3w/">forum</a>, a będzie mi miło! Dla Ciebie to jedno kliknięcie, a dla mnie motywacja do rozwijania projektu</p>
|
||||
</header>
|
||||
|
||||
<h2>Wyszukaj posterunek, osobe lub serwer</h2>
|
||||
|
||||
<div class="container">
|
||||
<input type="text" id="search">
|
||||
<button onclick="search()">Szukaj</button>
|
||||
<p>Użyj przecinka, aby wyszukać wiele wartości: pl2,Łazy</p>
|
||||
</div>
|
||||
|
||||
<h2>Ostatnie opuszczenia posterunków</h2>
|
||||
|
||||
<ul>
|
||||
<% records.forEach(record=> { %>
|
||||
<li>
|
||||
<details>
|
||||
<summary>[<span style="color:lightskyblue">
|
||||
<%= record.server.toUpperCase() %>
|
||||
</span>] <span style="color: lightskyblue">
|
||||
<%= record.stationName %>
|
||||
</span> - <span style="color:hotpink">
|
||||
<%= record.userUsername %>
|
||||
</span>
|
||||
<p style="margin-bottom: 0; opacity: 0.5;">
|
||||
<%= dayjs(record.leftDate).format('HH:mm DD/MM/YYYY') %>
|
||||
</p>
|
||||
</summary>
|
||||
<p>Data dołączenia: <%= record.joinedDate ? dayjs(record.joinedDate).format('HH:mm DD/MM/YYYY')
|
||||
: '--:-- --/--/--' %> (<%= record.joinedDate ? dayjs(record.joinedDate).fromNow() : '--' %>)
|
||||
</p>
|
||||
<p>Data wyjścia: <%= dayjs(record.leftDate).format('HH:mm DD/MM/YYYY') %> (<%=
|
||||
dayjs(record.leftDate).fromNow() %>)</p>
|
||||
<p>Spędzony czas: <%= record.joinedDate ? msToTime(record.leftDate - record.joinedDate) : '--' %>
|
||||
</p>
|
||||
|
||||
<a href="/details/<%= record.id %>">
|
||||
<button>Więcej</button>
|
||||
</a>
|
||||
</details>
|
||||
</li>
|
||||
<% }) %>
|
||||
</ul>
|
||||
|
||||
<script>
|
||||
function search() {
|
||||
location.href = '/search?q=' + document.getElementById('search').value
|
||||
}
|
||||
document.getElementById('search').addEventListener("keyup", (event) => {
|
||||
if (event.key === "Enter")
|
||||
search();
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>simrail.alekswilc.dev</title>
|
||||
<meta name="description" content="Simrail Utils">
|
||||
<meta property="og:title" content="simrail.alekswilc.dev">
|
||||
<meta property="og:url" content="https://simrail.alekswilc.dev">
|
||||
<meta property="og:description" content="Simrail Utils">
|
||||
<meta property="og:type" content="website">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/open-fonts@1.1.1/fonts/inter.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@exampledev/new.css@1.1.2/new.min.css">
|
||||
|
||||
<style>
|
||||
p {
|
||||
margin: 1%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<%- include('../_modules/header.ejs', { section: 'stations' }) %>
|
||||
|
||||
<h2>Wyszukaj posterunek, osobe lub serwer</h2>
|
||||
|
||||
<div class="container">
|
||||
<input type="text" id="search" value="<%=q%>">
|
||||
<button onclick="search()">Szukaj</button>
|
||||
<button onclick="clearSearch()">Wyczyść</button>
|
||||
|
||||
<p>Użyj przecinka, aby wyszukać wiele wartości: pl2,Łazy</p>
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
<% records.forEach(record=> { %>
|
||||
<li>
|
||||
<details>
|
||||
<summary>[<span style="color:lightskyblue">
|
||||
<%= record.server.toUpperCase() %>
|
||||
</span>] <span style="color: lightskyblue">
|
||||
<%= record.stationName %>
|
||||
</span> - <span style="color:hotpink">
|
||||
<%= record.userUsername %>
|
||||
</span>
|
||||
<p style="margin-bottom: 0; opacity: 0.5;">
|
||||
<%= dayjs(record.leftDate).format('HH:mm DD/MM/YYYY') %>
|
||||
</p>
|
||||
</summary>
|
||||
<p>Data dołączenia: <%= record.joinedDate ? dayjs(record.joinedDate).format('HH:mm DD/MM/YYYY')
|
||||
: '--:-- --/--/--' %> (<%= record.joinedDate ? dayjs(record.joinedDate).fromNow() : '--' %>)
|
||||
</p>
|
||||
<p>Data wyjścia: <%= dayjs(record.leftDate).format('HH:mm DD/MM/YYYY') %> (<%=
|
||||
dayjs(record.leftDate).fromNow() %>)</p>
|
||||
<p>Spędzony czas: <%= record.joinedDate ? msToTime(record.leftDate - record.joinedDate) : '--' %>
|
||||
</p>
|
||||
|
||||
<a href="/details/<%= record.id %>">
|
||||
<button>Więcej</button>
|
||||
</a>
|
||||
</details>
|
||||
</li>
|
||||
<% }) %>
|
||||
</ul>
|
||||
|
||||
<% if (!records.length) { %>
|
||||
<h4>Nie znaleziono wyników dla twojego zapytania.</h4>
|
||||
<% } %>
|
||||
|
||||
<hr>
|
||||
<%- include('../_modules/footer.ejs', { thanks: false }) %>
|
||||
|
||||
<script>
|
||||
function search() {
|
||||
location.href = '/stations/?q=' + document.getElementById('search').value
|
||||
}
|
||||
function clearSearch() {
|
||||
console.log('test')
|
||||
location.href = '/stations/';
|
||||
}
|
||||
document.getElementById('search').addEventListener("keyup", (event) => {
|
||||
if (event.key === "Enter")
|
||||
search();
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,87 +1,92 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>simrail.alekswilc.dev</title>
|
||||
<meta name="description" content="Simrail Utils">
|
||||
<meta property="og:title" content="simrail.alekswilc.dev">
|
||||
<meta property="og:url" content="https://simrail.alekswilc.dev/search?q=<%=q%>">
|
||||
<meta property="og:description" content="Simrail Utils">
|
||||
<meta property="og:type" content="website">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/open-fonts@1.1.1/fonts/inter.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@exampledev/new.css@1.1.2/new.min.css">
|
||||
|
||||
<style>
|
||||
p {
|
||||
margin: 1%;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<h1><a style="color: white; text-decoration: none;" href="/">SimRail Logs</a></h1>
|
||||
<p><a href="https://git.alekswilc.dev/alekswilc/simrail-logs">Dokumentacja</a></p>
|
||||
<br />
|
||||
<p style="color: darkorange;">Hej! Podoba Ci się projekt? Polajkuj post na <a href="https://forum.simrail.eu/topic/9142-logowanie-wyj%C5%9B%C4%87-z-posterunk%C3%B3w/">forum</a>, a będzie mi miło! Dla Ciebie to jedno kliknięcie, a dla mnie motywacja do rozwijania projektu</p>
|
||||
</header>
|
||||
|
||||
<h2>Wyszukaj posterunek, osobe lub serwer</h2>
|
||||
|
||||
|
||||
<div class="container">
|
||||
<input type="text" id="search" value="<%=q%>">
|
||||
<button onclick="search()">Szukaj</button>
|
||||
<p>Użyj przecinka, aby wyszukać wiele wartości: pl2,Łazy</p>
|
||||
</div>
|
||||
|
||||
<h2>Wyniki wyszukiwania</h2>
|
||||
|
||||
<ul>
|
||||
<% records.forEach(record=> { %>
|
||||
<li>
|
||||
<details>
|
||||
<summary>[<span style="color:lightskyblue">
|
||||
<%= record.server.toUpperCase() %>
|
||||
</span>] <span style="color: lightskyblue">
|
||||
<%= record.stationName %>
|
||||
</span> - <span style="color:hotpink">
|
||||
<%= record.userUsername %>
|
||||
</span>
|
||||
<p style="margin-bottom: 0; opacity: 0.5;">
|
||||
<%= dayjs(record.leftDate).format('HH:mm DD/MM/YYYY') %>
|
||||
</p>
|
||||
</summary>
|
||||
<p>Data dołączenia: <%= record.joinedDate ? dayjs(record.joinedDate).format('HH:mm DD/MM/YYYY')
|
||||
: '--:-- --/--/--' %> (<%= record.joinedDate ? dayjs(record.joinedDate).fromNow() : '--' %>)
|
||||
</p>
|
||||
<p>Data wyjścia: <%= dayjs(record.leftDate).format('HH:mm DD/MM/YYYY') %> (<%=
|
||||
dayjs(record.leftDate).fromNow() %>)</p>
|
||||
<p>Spędzony czas: <%= record.joinedDate ? msToTime(record.leftDate - record.joinedDate) : '--' %>
|
||||
</p>
|
||||
|
||||
<a href="/details/<%= record.id %>">
|
||||
<button>Więcej</button>
|
||||
</a>
|
||||
</details>
|
||||
</li>
|
||||
<% }) %>
|
||||
</ul>
|
||||
|
||||
<script>
|
||||
function search() {
|
||||
location.href = '/search?q=' + document.getElementById('search').value
|
||||
}
|
||||
document.getElementById('search').addEventListener("keyup", (event) => {
|
||||
if (event.key === "Enter")
|
||||
search();
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>simrail.alekswilc.dev</title>
|
||||
<meta name="description" content="Simrail Utils">
|
||||
<meta property="og:title" content="simrail.alekswilc.dev">
|
||||
<meta property="og:url" content="https://simrail.alekswilc.dev/search?q=<%=q%>">
|
||||
<meta property="og:description" content="Simrail Utils">
|
||||
<meta property="og:type" content="website">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/open-fonts@1.1.1/fonts/inter.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@exampledev/new.css@1.1.2/new.min.css">
|
||||
|
||||
<style>
|
||||
p {
|
||||
margin: 1%;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<%- include('../_modules/header.ejs', { section: 'stations' }) %>
|
||||
|
||||
<h2>Tablica godzin</h2>
|
||||
<div class="container">
|
||||
<input type="text" id="search" value="<%=q%>">
|
||||
<button onclick="search()">Filtruj</button>
|
||||
<button onclick="clearSearch()">Wyczyść</button>
|
||||
|
||||
<p>Użyj przecinka, aby wyszukać wiele wartości: pl2,Łazy</p>
|
||||
</div>
|
||||
<ul>
|
||||
<% records.forEach(record=> { %>
|
||||
<li>
|
||||
<details>
|
||||
<summary>[<span style="color:lightskyblue">
|
||||
<%= record.server.toUpperCase() %>
|
||||
</span>] <span style="color: lightskyblue">
|
||||
<%= record.stationName %>
|
||||
</span> - <span style="color:hotpink">
|
||||
<%= record.userUsername %>
|
||||
</span>- <span style="color:lightseagreen">
|
||||
<%= record.joinedDate ? msToTime(record.leftDate - record.joinedDate) : '--' %>
|
||||
</span>
|
||||
<p style="margin-bottom: 0; opacity: 0.5;">
|
||||
<%= dayjs(record.leftDate).format('HH:mm DD/MM/YYYY') %>
|
||||
</p>
|
||||
</summary>
|
||||
<p>Data dołączenia: <%= record.joinedDate ? dayjs(record.joinedDate).format('HH:mm DD/MM/YYYY')
|
||||
: '--:-- --/--/--' %> (<%= record.joinedDate ? dayjs(record.joinedDate).fromNow() : '--' %>)
|
||||
</p>
|
||||
<p>Data wyjścia: <%= dayjs(record.leftDate).format('HH:mm DD/MM/YYYY') %> (<%=
|
||||
dayjs(record.leftDate).fromNow() %>)</p>
|
||||
<p>Spędzony czas: <%= record.joinedDate ? msToTime(record.leftDate - record.joinedDate) : '--' %>
|
||||
</p>
|
||||
|
||||
<a href="/details/<%= record.id %>">
|
||||
<button>Więcej</button>
|
||||
</a>
|
||||
</details>
|
||||
</li>
|
||||
<% }) %>
|
||||
</ul>
|
||||
|
||||
<% if (!records.length) { %>
|
||||
<h4>Nie znaleziono wyników dla twojego zapytania.</h4>
|
||||
<% } %>
|
||||
|
||||
|
||||
<script>
|
||||
function search() {
|
||||
location.href = '/stations/leaderboard?q=' + document.getElementById('search').value
|
||||
}
|
||||
|
||||
function clearSearch() {
|
||||
location.href = '/stations/leaderboard'
|
||||
}
|
||||
|
||||
document.getElementById('search').addEventListener("keyup", (event) => {
|
||||
if (event.key === "Enter")
|
||||
search();
|
||||
|
||||
});
|
||||
</script>
|
||||
<hr>
|
||||
<%- include('../_modules/footer.ejs', { thanks: false }) %>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -3,7 +3,7 @@ import './util/time.js';
|
||||
import { SimrailClient, SimrailClientEvents } from './util/SimrailClient.js';
|
||||
import dayjs from 'dayjs';
|
||||
import { StationsModule } from './modules/stations.js';
|
||||
import { ApiModule } from './http/api.js';
|
||||
import { ApiModule } from './http/server.js';
|
||||
import mongoose from 'mongoose';
|
||||
import { IPlayer } from './types/player.js';
|
||||
import { Station, Server } from '@simrail/types';
|
||||
|
@ -1,47 +1,47 @@
|
||||
import { Model, model, Schema } from 'mongoose';
|
||||
|
||||
|
||||
const schema = new Schema<ILog>(
|
||||
{
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
userSteamId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
userUsername: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
userAvatar: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
joinedDate: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: undefined
|
||||
},
|
||||
leftDate: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
stationName: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
stationShort: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
server: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
}
|
||||
);
|
||||
export const raw_schema = {
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
userSteamId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
userUsername: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
userAvatar: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
joinedDate: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: undefined
|
||||
},
|
||||
leftDate: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
stationName: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
stationShort: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
server: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
}
|
||||
|
||||
const schema = new Schema<ILog>(raw_schema);
|
||||
schema.index({ stationName: 'text', userUsername: 'text', stationShort: 'text', userSteamId: 'text', server: 'text' })
|
||||
|
||||
export type TMLog = Model<ILog>
|
||||
|
@ -10,5 +10,9 @@ export const msToTime = (duration: number) => {
|
||||
const minutes = Math.floor((duration / (1000 * 60)) % 60);
|
||||
const hours = Math.floor((duration / (1000 * 60 * 60)) % 24);
|
||||
|
||||
if (minutes === 0 && hours === 0 && duration > 0)
|
||||
return "1m";
|
||||
|
||||
|
||||
return `${hours ? `${hours}h ` : ''}${minutes ? `${minutes}m` : ''}`;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user