-
Notifications
You must be signed in to change notification settings - Fork 1
/
mapserver.ts
201 lines (173 loc) · 8.44 KB
/
mapserver.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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
import { GET, HttpRequest, HttpResponse, Path, POST, ResponseCodeError } from 'express-hibernate-wrapper';
import { promises } from 'fs';
import { load, save } from 'hibernatets';
import { DataBaseBase } from 'hibernatets/mariadb-base';
import { join } from 'path';
import { GeoLocation } from './models/location';
import { Site } from './models/site';
import { Tile } from './models/tile';
import { AddressResolver } from './service/address-from-geo';
import { ImageResolver } from './service/image-resolver';
import { MapAttributes } from './service/map-attributes-holder';
import { MappingWorldMapResovler } from './service/mapping-world-map-resolver';
import { MinesweeperResolver } from './service/minesweeper';
import { SitesAdder } from './service/site-adder';
import { UserMapLoader } from './service/user-map-loader';
import { MapResolver } from './service/woirld-map-resolver';
import { User } from './user/user';
@Path('mapserver')
export class Mapserver {
private static addressResolver = new AddressResolver();
@POST({ path: 'register', attributes: { needsUser: false } })
async registerGitHub(req: HttpRequest, res: HttpResponse) {
/*if (!req.body.url.endsWith('.json')&&req.body.url) {
throw new ResponseCodeError(400, 'url needs to be a json');
}*/
if (isNaN(+req.body.lat) || isNaN(+req.body.lon)) {
throw new ResponseCodeError(400, 'positions need to be a number');
}
const latitude = +req.body.lat;
if (latitude > 85 || latitude < -85) {
throw new ResponseCodeError(400, 'latitudes greater than 85 or smaller than -85 are not within the map');
}
let siteUrl: URL;
try {
siteUrl = new URL(req.body.url);
} catch (e) {
throw new ResponseCodeError(400, 'url needs to be a valid url pointing to a map.json');
}
const site = new Site(siteUrl.href, new GeoLocation(+req.body.lat, +req.body.lon));
if (req.body.icon && typeof req.body.icon === 'number') {
site.iconIndex = req.body.icon;
}
//const location = site.getLocation();
// site.address = await Mapserver.addressResolver.getAddressFromGeo(location);
await save(site);
new DataBaseBase().sqlquery('DELETE FROM mapcache');
res.send('ok');
/*if (!countries[site.address.country_code]) {
const countryData = await Mapserver.addressResolver.getCountryData(location);
const imageTile = await ImageResolver.getTileForPos(location);
//https://c.tile.openstreetmap.de/{z}/{x}/{y}.png
countries[site.address.country_code] = {
boundingbox: countryData.boundingbox,
tile: imageTile
};
console.log('set country');
}*/
}
@GET({ path: '', attributes: { needsUser: false } })
async index(req, res: HttpResponse) {
res.redirect('../../../mapserver/register.html');
}
@GET({ path: 'mapscript.js', attributes: { needsUser: false } })
@GET({ path: '/world/mapscript.js', attributes: { needsUser: false } })
@GET({ path: ':_/lat/:_/lon/:_/mapscript.js', attributes: { needsUser: false } })
async getMapScript(req: HttpRequest<User>, res: HttpResponse) {
const resource = join(__dirname, '../../public/mapscript.js');
let buffer = await promises.readFile(resource, { encoding: 'utf8' });
res.set('Content-Type', 'application/javascript')
.send(buffer);
}
@GET({ path: 'image/:zoom/:x/:y.png', attributes: { needsUser: false } })
@GET({ path: '/world/image/:zoom/:x/:y.png', attributes: { needsUser: false } })
@GET({ path: ':_/lat/:_/lon/:_/image/:zoom/:x/:y.png', attributes: { needsUser: false } })
async countryimage(req: HttpRequest, res: HttpResponse) {
const tempTile = new Tile();
tempTile.x = req.params.y; //stored wrong :(
tempTile.y = req.params.x;
tempTile.zoom = req.params.zoom;
const tile = await ImageResolver.loadTileData(tempTile);
res.set('Content-Type', 'image/png')
.send(Buffer.from(await tile.data));
}
@GET({ path: 'usermap/assets/:image', attributes: { needsUser: false } })
@GET({ path: 'assets/:image', attributes: { needsUser: false } })
@GET({ path: '/world/assets/:image', attributes: { needsUser: false } })
@GET({ path: ':zoom/lat/:tileX/lon/:tileY/assets/:image', attributes: { needsUser: false } })
async assets(req, res) {
const path = req.params.image;
if (path.includes('..') || path.includes('/')) {
throw new ResponseCodeError(403, '');
}
const resource = join(__dirname, `../../public/`, path);
const buffer = await promises.readFile(resource);
res.set('Content-Type', 'image/png')
.send(buffer);
}
@GET({ path: 'site.json', attributes: { needsUser: false } })
@GET({ path: '/world/site.json', attributes: { needsUser: false } })
async getRenderedSite(req: HttpRequest, res) {
if (req.path.includes('/world/site.json')) {
const worldMapJsonString = await new MapResolver().getWorldMapJson();
res.set('Content-Type', 'application/json')
.send(worldMapJsonString);
return;
}
const sites = await load(Site, 'TRUE=TRUE', undefined, {
deep: true
});
const pixel = new SitesAdder(new MapResolver()).getFirstTilePixelWithMultipleSites(sites);
//console.log(`${pixel.zoom} - ${pixel.lon} - ${pixel.lat}`);
const topLevelJsonString = await new MapResolver(pixel.zoom, pixel.lon, pixel.lat).getWorldMapJson();
res.set('Content-Type', 'application/json')
.send(topLevelJsonString);
}
@GET({ path: 'replsite.json', attributes: { needsUser: false } })
@GET({ path: '/world/replsite.json', attributes: { needsUser: false } })
async getRenderedReplSite(req: HttpRequest, res) {
if (req.path.includes('/world/replsite.json')) {
const worldMapJsonString = await new MappingWorldMapResovler().getWorldMapJson();
res.set('Content-Type', 'application/json')
.send(worldMapJsonString);
return;
}
const sites = await load(Site, 'TRUE=TRUE', undefined, {
deep: true
});
const pixel = new SitesAdder(new MappingWorldMapResovler()).getFirstTilePixelWithMultipleSites(sites);
//console.log(`${pixel.zoom} - ${pixel.lon} - ${pixel.lat}`);
const topLevelJsonString = await new MappingWorldMapResovler(pixel.zoom, pixel.lon, pixel.lat).getWorldMapJson();
res.set('Content-Type', 'application/json')
.send(topLevelJsonString);
}
@GET({ path: ':zoom/lat/:tileX/lon/:tileY/replsite.json', attributes: { needsUser: false } })
@GET({ path: ':zoom/lat/:tileX/lon/:tileY/site.json', attributes: { needsUser: false } })
async getRenderedSiteForPosition(req: HttpRequest, res: HttpResponse) {
if (!req.params.zoom || isNaN(+req.params.zoom)) {
res.status(400)
.send();
return;
}
let zoom = +req.params.zoom;
if (zoom > SitesAdder.maxZoom) {
throw new ResponseCodeError(400, "zoom level too high");
}
let classRef = MapResolver;
if (req.path.includes("replsite.json")) {
classRef = MappingWorldMapResovler;
}
const mapReolver = new classRef(zoom, +req.params.tileX, +req.params.tileY, MapAttributes.layerSizePerMap);
const worldMapJsonString = await mapReolver.getWorldMapJson();
res.set('Content-Type', 'application/json')
.send(worldMapJsonString);
}
@GET({ path: 'usermap/:referenceUuid.json' })
async getUserMap(req: HttpRequest<User>, res: HttpResponse) {
console.log(req.params.referenceUuid);
const user = await load(User, u => u.referenceUuid = req.params.referenceUuid, undefined, {
first: true,
deep: {
attributes: 'TRUE=TRUE',
privateMapOverrides: 'TRUE=TRUE'
}
});
const mapJson = await new UserMapLoader().getMapJsonForUser(user);
res.set('Content-Type', 'application/json')
.send(mapJson);
}
@GET({ path: "minesweeper.json", attributes: { needsUser: false } })
async getPlainMinesweeperMap(req: HttpRequest<User>, res: HttpResponse) {
res.send(await new MinesweeperResolver(true).buildMap());
}
}