-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.ts
176 lines (158 loc) · 7.26 KB
/
server.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import express, { Application } from 'express';
import * as fs from 'fs';
import * as React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router';
import * as AxiosHooks from "axios-hooks";
import * as path from "path";
// App imports
import App from "./src/App";
import https from "https"
import * as constants from "constants";
import {CURRENT_SEASON} from "./src/AppTheme";
import {getEventTypeFromKey} from "./src/views/events/EventsView";
import {
Event,
FGCProvider,
ICompleteTeamResponse,
Match,
MatchParticipant,
Ranking,
Team
} from "@the-orange-alliance/lib-ems";
// Redux imports
import {createStore} from "redux";
import {Provider} from "react-redux";
import {IApplicationState} from "./src/store/Models";
import appReducer, {initialState} from "./src/store/Reducer";
import * as http from "http";
const app: Application = express();
const apiIp = "live.firstalumnicollegiatecomp.org";
FGCProvider.initialize(apiIp, 8443, 'https');
// FGCProvider.initialize("127.0.0.1", 8088);
// app.use('/api/*', (req: any, res: any) => {
// req.pipe()
// });
// The client needs this first line to find the actual index.js file.
app.use('/build/client', express.static(path.resolve("build/client")));
app.use(express.static(path.resolve("build/client")));
app.use('/static', express.static(path.resolve("static")));
// Serve requests with our render function
app.get("/", render);
app.get("/teams", render);
app.get("/team/:teamKey", render);
app.get("/events", render);
app.get("/events/:seasonKey", render);
app.get("/match/:matchKey", render);
app.get("/rankings", render);
app.get("/streams", render);
async function render(req: any, res: any, next: any) {
// Create application store.
const initialState: IApplicationState = await loadPageData(req);
const store = createStore(appReducer, initialState);
const context: any = {};
const index = fs.readFileSync("index.html", 'utf8');
const cache = await (AxiosHooks as any).serializeCache();
const appElement = React.createElement(App, {store: store});
const routerElement = React.createElement(StaticRouter, {location: req.url, context: context}, appElement);
const appProvider = React.createElement(Provider, {store: store}, routerElement);
const html = renderToString(appProvider);
const state = store.getState();
if (context.url) {
res.writeHead(301, {
Location: context.url
});
res.end();
} else {
res.send(
index
.replace("href=\"static/css/flag-icon.min.css", `href="${req.protocol}://${req.headers.host}/static/css/flag-icon.min.css`)
.replace("href=\"static/css/index.css", `href="${req.protocol}://${req.headers.host}/static/css/index.css`)
.replace('{{{body}}}', html)
.replace('["__AXIOS__"]', JSON.stringify(cache).replace(/</g, '\\u003c'))
.replace('["__REDUX__"]', JSON.stringify(prepareState(state)).replace(/</g, '\\u003c'))
.replace("build/client/index.js", `${req.protocol}://${req.headers.host}/build/client/index.js`)
);
}
}
async function loadPageData(req: any, params?: any): Promise<IApplicationState> {
if(req.protocol === 'http') FGCProvider.initialize(apiIp, 8080);
switch (req.path) {
case "/":
const homeTeams: Team[] = await FGCProvider.getTeamsBySeason(CURRENT_SEASON);
const upcomingMatches: Match[] = await FGCProvider.getUpcomingMatches(CURRENT_SEASON, 10);
const highestScoringMatch: Match = await FGCProvider.getHighestScoringMatch(CURRENT_SEASON, "quals", false);
const matchSize: number = await FGCProvider.getPlayedMatchCount(CURRENT_SEASON);
return {...initialState, teams: homeTeams, matches: upcomingMatches, completeMatch: highestScoringMatch, matchSize: matchSize};
case "/teams":
const teams: Team[] = await FGCProvider.getTeamsBySeason(CURRENT_SEASON);
return {...initialState, teams: teams};
case "/events":
const event: Event = await FGCProvider.getEventBySeason(CURRENT_SEASON);
const eventMatches: Match[] = await FGCProvider.getAllEventMatches(event.eventKey);
const eventTeams: Team[] = await FGCProvider.getTeams(event.eventKey);
const eventRanks: Ranking[] = await FGCProvider.getRankingTeams(event.eventKey, getEventTypeFromKey(event.season.seasonKey.toString()));
return {...initialState, event: event, matches: eventMatches.filter((m: Match) => m.tournamentLevel > Match.PRACTICE_LEVEL), teams: eventTeams, rankings: eventRanks};
case `/team/${req.params.teamKey}`:
const completeTeam: ICompleteTeamResponse = await FGCProvider.getCompleteTeam(req.params.teamKey, CURRENT_SEASON);
return {...initialState, completeTeam: {
rankings: completeTeam.rankings,
matches: completeTeam.matches.filter((m: Match) => m.tournamentLevel > Match.PRACTICE_LEVEL),
team: completeTeam.team
}};
case `/match/${req.params.matchKey}`:
const completeMatch: Match = await FGCProvider.getCompleteMatch(req.params.matchKey);
return {...initialState, completeMatch: completeMatch};
case "/rankings":
const rankings: Ranking[] = await FGCProvider.getRankingTeams("20-FCC-FER", getEventTypeFromKey("20"));
return {...initialState, rankings: rankings};
default:
return initialState;
}
}
function prepareState(state: IApplicationState): any {
return {
completeMatch: prepareCompleteMatch(state.completeMatch),
completeTeam: prepareCompleteTeam(state.completeTeam),
seasons: [],
matchSize: state.matchSize,
event: state.event.toJSON(),
matches: state.matches.map((m: Match) => prepareCompleteMatch(m)),
rankings: state.rankings.map((r: Ranking) => r.toJSON()),
teams: state.teams.map((t: Team) => t.toJSON())
};
}
function prepareCompleteMatch(match: Match): any {
const matchJSON: any = match.toJSON();
matchJSON.participants = typeof match.participants !== "undefined" ? match.participants.map((p: MatchParticipant) => p.toJSON()) : [];
matchJSON.details = typeof match.matchDetails !== "undefined" ? match.matchDetails.toJSON() : undefined;
return matchJSON;
}
function prepareCompleteTeam(cTeam: ICompleteTeamResponse) {
let cTeamJSON: any = {};
cTeamJSON.team = cTeam.team.toJSON();
cTeamJSON.matches = cTeam.matches.map((m: Match) => {
const matchJSON: any = m.toJSON();
matchJSON.participants = m.participants.map((p: MatchParticipant) => p.toJSON());
return matchJSON;
});
cTeamJSON.rankings = cTeam.rankings.map((r: Ranking) => r.toJSON());
return cTeamJSON;
}
// Start HTTP server
http.createServer(app).listen({
port: 80,
host: '0.0.0.0'
}, () => console.log("HTTP server listening on port 80"));
// Check for a HTTPS Cert on User's computer. If it's there, we'll serve HTTPS.
if (fs.existsSync('/etc/letsencrypt/live/live.firstalumnicollegiatecomp.org/cert.pem')) {
// We see a cert, lets open https server
https.createServer({
cert: fs.readFileSync('/etc/letsencrypt/live/live.firstalumnicollegiatecomp.org/cert.pem', 'utf8'),
key: fs.readFileSync('/etc/letsencrypt/live/live.firstalumnicollegiatecomp.org/privkey.pem', 'utf8'),
ca: fs.readFileSync('/etc/letsencrypt/live/live.firstalumnicollegiatecomp.org/fullchain.pem', 'utf8'),
secureOptions: constants.SSL_OP_NO_TLSv1
}, app).listen(443, function () {
console.log('HTTPS server listening on port 443')
});
}