From 596d61ed2e56db69e6c0b6a4b1bd423ec98f0c44 Mon Sep 17 00:00:00 2001 From: niczem Date: Sun, 7 Jan 2024 11:21:09 +0000 Subject: [PATCH] Apply linting and formatting changes --- index.d.ts | 2 +- package-lock.json | 1 + src/classes/server.ts | 132 ++++++++++++++--------------- src/classes/sources/Position.d.ts | 20 ++--- src/classes/sources/Source.ts | 50 +++++------ src/classes/sources/adsb/adsbe.ts | 134 +++++++++++++++--------------- src/classes/sources/ais/mst.ts | 96 ++++++++++----------- src/classes/sources/ais/mt.ts | 50 +++++------ src/index.ts | 10 +-- src/legacy/api.ts | 122 +++++++++++++-------------- src/legacy/area.ts | 68 +++++++-------- src/legacy/lib/puppeteer.ts | 78 ++++++++--------- 12 files changed, 382 insertions(+), 381 deletions(-) diff --git a/index.d.ts b/index.d.ts index 3de3ad6..c1b57a3 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,3 +1,3 @@ -declare module 'position-api' { +declare module "position-api" { // Define the exported types and interfaces here } diff --git a/package-lock.json b/package-lock.json index 585754e..969fc34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "dependencies": { "@types/cors": "^2.8.17", "@types/express": "^4.17.17", + "@types/node": "^18.18.13", "brotli": "^1.3.3", "cheerio": "^1.0.0-rc.12", "cors": "^2.8.5", diff --git a/src/classes/server.ts b/src/classes/server.ts index dcc7e40..897af22 100644 --- a/src/classes/server.ts +++ b/src/classes/server.ts @@ -1,105 +1,105 @@ -import express from 'express' -import cors from 'cors' -import path from 'path' -import { api } from '../legacy/api' -import { areaApi } from '../legacy/area' -import ADSBexchange from './sources/adsb/adsbe' +import express from "express"; +import cors from "cors"; +import path from "path"; +import { api } from "../legacy/api"; +import { areaApi } from "../legacy/area"; +import ADSBexchange from "./sources/adsb/adsbe"; class Server { - app: any - constructor (port) { - this.init(port) + app: any; + constructor(port) { + this.init(port); } - init (port: number) { - this.app = express() - this.app.set('port', port) + init(port: number) { + this.app = express(); + this.app.set("port", port); this.app.use( cors({ - origin: '*' - }) - ) - this.app.get('/', (_request: any, response: any) => { - response.sendFile(path.join(__dirname, '/../static/index.html')) - }) - this.loadLegacyRoutes() - this.loadRoutes() - this.app.listen(this.app.get('port'), () => { - console.log('Node this.app is running on port', this.app.get('port')) - }) + origin: "*", + }), + ); + this.app.get("/", (_request: any, response: any) => { + response.sendFile(path.join(__dirname, "/../static/index.html")); + }); + this.loadLegacyRoutes(); + this.loadRoutes(); + this.app.listen(this.app.get("port"), () => { + console.log("Node this.app is running on port", this.app.get("port")); + }); } - loadRoutes () { + loadRoutes() { // /:sourcetype/:source/:vehicleidentifier/location/latest this.app.get( - '/adsb/adsbe/:icao/location/latest', + "/adsb/adsbe/:icao/location/latest", async (req: any, res: any) => { - console.log(req.params.icao) - const adsbe = new ADSBexchange() - const location = await adsbe.getLocation(req.params.icao) - console.log(location) + console.log(req.params.icao); + const adsbe = new ADSBexchange(); + const location = await adsbe.getLocation(req.params.icao); + console.log(location); res.send({ error: null, - data: location - }) - } - ) + data: location, + }); + }, + ); } - loadLegacyRoutes () { + loadLegacyRoutes() { // this route is wrongly named on purpose for legacy reasons. // AS VF is not as easy to reverse as the other ones, it is replaced by MST this.app.get( - '/legacy/getLastPositionFromVF/:mmsi', + "/legacy/getLastPositionFromVF/:mmsi", (req: any, res: any) => { api.getLocationFromMST(req.params.mmsi, (result) => { - res.send(result) - }) - } - ) + res.send(result); + }); + }, + ); this.app.get( - '/legacy/getLastPositionFromMT/:mmsi', + "/legacy/getLastPositionFromMT/:mmsi", (req: any, res: any) => { api.getLocationFromMT(req.params.mmsi, (result) => { - res.send(result) - }) - } - ) - this.app.get('/legacy/getLastPosition/:mmsi', (req: any, res: any) => { + res.send(result); + }); + }, + ); + this.app.get("/legacy/getLastPosition/:mmsi", (req: any, res: any) => { api.getLocation(req.params.mmsi, (result) => { - res.send(result) - }) - }) + res.send(result); + }); + }); // e.g. /getVesselsInArea/WMED,EMED this.app.get( - '/legacy/getVesselsInArea/:area', + "/legacy/getVesselsInArea/:area", async (req: any, res: any) => { await areaApi.fetchVesselsInArea( - req.params.area.split(','), + req.params.area.split(","), (result) => { - res.json(result) - } - ) - } - ) + res.json(result); + }, + ); + }, + ); this.app.get( - '/legacy/getVesselsNearMe/:lat/:lng/:distance', + "/legacy/getVesselsNearMe/:lat/:lng/:distance", async (req: any, res: any) => { await areaApi.fetchVesselsNearMe( req.params.lat, req.params.lng, req.params.distance, (result) => { - res.json(result) - } - ) - } - ) - this.app.get('/legacy/getVesselsInPort/:shipPort', (req: any, res: any) => { + res.json(result); + }, + ); + }, + ); + this.app.get("/legacy/getVesselsInPort/:shipPort", (req: any, res: any) => { api.getVesselsInPort(req.params.shipPort, (result) => { - res.send(result) - }) - }) + res.send(result); + }); + }); } } -export default Server +export default Server; diff --git a/src/classes/sources/Position.d.ts b/src/classes/sources/Position.d.ts index cb85948..3f4ab4e 100644 --- a/src/classes/sources/Position.d.ts +++ b/src/classes/sources/Position.d.ts @@ -1,13 +1,13 @@ -declare module 'PositionTypes' { +declare module "PositionTypes" { export interface Position { - timestamp: string - latitude: number - longitude: number - course: number - speed: number - source: string - source_type: string - altitude?: number - raw?: any + timestamp: string; + latitude: number; + longitude: number; + course: number; + speed: number; + source: string; + source_type: string; + altitude?: number; + raw?: any; } } diff --git a/src/classes/sources/Source.ts b/src/classes/sources/Source.ts index e80e76c..73bf3db 100644 --- a/src/classes/sources/Source.ts +++ b/src/classes/sources/Source.ts @@ -1,49 +1,49 @@ -import fetch from 'node-fetch' -import puppeteer from 'puppeteer' +import fetch from "node-fetch"; +import puppeteer from "puppeteer"; class Source { - browser: any - constructor () { - this.browser = false + browser: any; + constructor() { + this.browser = false; } getBrowser: any = async () => { if (this.browser) { - return this.browser + return this.browser; } this.browser = await puppeteer.launch({ headless: true, defaultViewport: { width: 1280, // Width of a MacBook screen - height: 1400 // Height of a MacBook screen + height: 1400, // Height of a MacBook screen }, // waitUntil: "domcontentloaded", args: [ - '--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36' - ] - }) - return this.browser - } + "--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36", + ], + }); + return this.browser; + }; - convertRawCoordinatesIntoDecimal (input): number { - const grade = parseInt(input.substring(0, input.indexOf('°'))) - const rest = input.substring(input.indexOf('°') + 1) - const minutes = parseInt(rest.substring(0, rest.indexOf("'"))) + convertRawCoordinatesIntoDecimal(input): number { + const grade = parseInt(input.substring(0, input.indexOf("°"))); + const rest = input.substring(input.indexOf("°") + 1); + const minutes = parseInt(rest.substring(0, rest.indexOf("'"))); const seconds = parseInt( - rest.substring(rest.indexOf("'") + 1).split('"')[0] - ) - return grade + (minutes + seconds / 60) / 60 + rest.substring(rest.indexOf("'") + 1).split('"')[0], + ); + return grade + (minutes + seconds / 60) / 60; } fetch = async function (url: string, headers: any, method: string) { const response = await fetch(url, { headers, body: undefined, - method - }) - const text = await response.text() - return text - } + method, + }); + const text = await response.text(); + return text; + }; } -export default Source +export default Source; diff --git a/src/classes/sources/adsb/adsbe.ts b/src/classes/sources/adsb/adsbe.ts index fa660a1..02b39e5 100644 --- a/src/classes/sources/adsb/adsbe.ts +++ b/src/classes/sources/adsb/adsbe.ts @@ -1,5 +1,5 @@ -import Source from '../Source' -import fetch from 'node-fetch' +import Source from "../Source"; +import fetch from "node-fetch"; class ADSBExchange extends Source { parseLocation = async function (result: any) { @@ -10,45 +10,45 @@ class ADSBExchange extends Source { course: result.course, speed: result.speed, raw: result.raw, - source: 'adsbExchange', - source_type: 'adsb' - } - return location - } + source: "adsbExchange", + source_type: "adsb", + }; + return location; + }; getLocation = async (icao: string) => { /// const response = await fetch( `https://globe.adsbexchange.com/data/traces/${icao.slice( - -2 + -2, )}/trace_recent_${icao}.json`, { headers: { - accept: 'application/json, text/javascript, */*; q=0.01', - 'accept-language': 'de-DE,de;q=0.9', - 'sec-ch-ua': + accept: "application/json, text/javascript, */*; q=0.01", + "accept-language": "de-DE,de;q=0.9", + "sec-ch-ua": '"Chromium";v="116", "Not)A;Brand";v="24", "Brave";v="116"', - 'sec-ch-ua-mobile': '?0', - 'sec-ch-ua-platform': '"macOS"', - 'sec-fetch-dest': 'empty', - 'sec-fetch-mode': 'cors', - 'sec-fetch-site': 'same-origin', - 'sec-gpc': '1', - 'x-requested-with': 'XMLHttpRequest', - Referer: 'https://globe.adsbexchange.com/?icao=39e68b', - 'Referrer-Policy': 'strict-origin-when-cross-origin' + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": '"macOS"', + "sec-fetch-dest": "empty", + "sec-fetch-mode": "cors", + "sec-fetch-site": "same-origin", + "sec-gpc": "1", + "x-requested-with": "XMLHttpRequest", + Referer: "https://globe.adsbexchange.com/?icao=39e68b", + "Referrer-Policy": "strict-origin-when-cross-origin", }, body: undefined, - method: 'GET' - } - ) - const bodyjson = await response.json() - const timestamp = bodyjson.timestamp - const trace = bodyjson.trace - const last_trace = trace[trace.length - 1] + method: "GET", + }, + ); + const bodyjson = await response.json(); + const timestamp = bodyjson.timestamp; + const trace = bodyjson.trace; + const last_trace = trace[trace.length - 1]; const [time_offset, lat, lon, alt_baro, ground_speed, ground_track] = - last_trace - const last_trace_timestamp = timestamp + time_offset + last_trace; + const last_trace_timestamp = timestamp + time_offset; const location = this.parseLocation({ timestamp: last_trace_timestamp, latitude: lat, @@ -56,43 +56,43 @@ class ADSBExchange extends Source { course: ground_track, speed: ground_speed, // knots altitude: alt_baro, - raw: bodyjson - }) - return await location - } + raw: bodyjson, + }); + return await location; + }; getLocationFull = async (icao: string) => { /// const response = await fetch( `https://globe.adsbexchange.com/data/traces/${icao.slice( - -2 + -2, )}/trace_full_${icao}.json`, { headers: { - accept: 'application/json, text/javascript, */*; q=0.01', - 'accept-language': 'de-DE,de;q=0.9', - 'sec-ch-ua': + accept: "application/json, text/javascript, */*; q=0.01", + "accept-language": "de-DE,de;q=0.9", + "sec-ch-ua": '"Chromium";v="116", "Not)A;Brand";v="24", "Brave";v="116"', - 'sec-ch-ua-mobile': '?0', - 'sec-ch-ua-platform': '"macOS"', - 'sec-fetch-dest': 'empty', - 'sec-fetch-mode': 'cors', - 'sec-fetch-site': 'same-origin', - 'sec-gpc': '1', - 'x-requested-with': 'XMLHttpRequest', - Referer: 'https://globe.adsbexchange.com/?icao=39e68b', - 'Referrer-Policy': 'strict-origin-when-cross-origin' + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": '"macOS"', + "sec-fetch-dest": "empty", + "sec-fetch-mode": "cors", + "sec-fetch-site": "same-origin", + "sec-gpc": "1", + "x-requested-with": "XMLHttpRequest", + Referer: "https://globe.adsbexchange.com/?icao=39e68b", + "Referrer-Policy": "strict-origin-when-cross-origin", }, body: undefined, - method: 'GET' - } - ) - const bodyjson = await response.json() - const timestamp = bodyjson.timestamp - const trace = bodyjson.trace + method: "GET", + }, + ); + const bodyjson = await response.json(); + const timestamp = bodyjson.timestamp; + const trace = bodyjson.trace; - console.log(trace) - const last_trace = trace[trace.length - 1] + console.log(trace); + const last_trace = trace[trace.length - 1]; const [ time_offset, lat, @@ -102,15 +102,15 @@ class ADSBExchange extends Source { unknown2, unknown3, unknown4, - unknown5 - ] = last_trace - console.log('check that lat and lon in correct order!!') - console.log('last trace') - console.log(last_trace) - console.log('=========') - const last_trace_timestamp = timestamp + time_offset - console.log(last_trace_timestamp) - console.log(new Date(last_trace_timestamp * 1000)) + unknown5, + ] = last_trace; + console.log("check that lat and lon in correct order!!"); + console.log("last trace"); + console.log(last_trace); + console.log("========="); + const last_trace_timestamp = timestamp + time_offset; + console.log(last_trace_timestamp); + console.log(new Date(last_trace_timestamp * 1000)); console.log( time_offset, lat, @@ -120,9 +120,9 @@ class ADSBExchange extends Source { unknown2, unknown3, unknown4, - unknown5 - ) - } + unknown5, + ); + }; } -export default ADSBExchange +export default ADSBExchange; diff --git a/src/classes/sources/ais/mst.ts b/src/classes/sources/ais/mst.ts index e2b0ed8..f817d4f 100644 --- a/src/classes/sources/ais/mst.ts +++ b/src/classes/sources/ais/mst.ts @@ -1,4 +1,4 @@ -import Source from '../Source' +import Source from "../Source"; class MyShipTracking extends Source { parseLocation = async function (result: any) { const location = { @@ -7,73 +7,73 @@ class MyShipTracking extends Source { longitude: result.longitude, course: result.course, speed: result.speed, - source: 'myshiptracking.com', - source_type: 'AIS' - } - return location - } + source: "myshiptracking.com", + source_type: "AIS", + }; + return location; + }; // the method in the sources class does not work if no seconds are in the string dmsToDecimalDegreesMST = function (dms) { - console.log(dms) - return parseFloat(dms) - } + console.log(dms); + return parseFloat(dms); + }; getLocation = async (mmsi: number) => { const result = await this.fetch( - 'https://www.myshiptracking.com/vessels/mmsi-' + mmsi, + "https://www.myshiptracking.com/vessels/mmsi-" + mmsi, { accept: - 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8', - 'accept-language': 'de-DE,de;q=0.6', - 'cache-control': 'max-age=0', - 'sec-ch-ua': + "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8", + "accept-language": "de-DE,de;q=0.6", + "cache-control": "max-age=0", + "sec-ch-ua": '"Chromium";v="116", "Not)A;Brand";v="24", "Brave";v="116"', - 'sec-ch-ua-mobile': '?0', - 'sec-ch-ua-platform': '"macOS"', - 'sec-fetch-dest': 'document', - 'sec-fetch-mode': 'navigate', - 'sec-fetch-site': 'none', - 'sec-fetch-user': '?1', - 'sec-gpc': '1', - 'upgrade-insecure-requests': '1', + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": '"macOS"', + "sec-fetch-dest": "document", + "sec-fetch-mode": "navigate", + "sec-fetch-site": "none", + "sec-fetch-user": "?1", + "sec-gpc": "1", + "upgrade-insecure-requests": "1", cookie: - 'usr_lang_exist=1; port_tz=LT; user_tz=MT; user_df=1; session_id_sp_trk=fd1i0pb2mt6i4nra9c1mejsmvk; offset=Europe%2FBerlin; usr_lang_exist=1; io=ilOBwd-Xh9Z1fGzpFaM0' + "usr_lang_exist=1; port_tz=LT; user_tz=MT; user_df=1; session_id_sp_trk=fd1i0pb2mt6i4nra9c1mejsmvk; offset=Europe%2FBerlin; usr_lang_exist=1; io=ilOBwd-Xh9Z1fGzpFaM0", }, - 'GET' - ) + "GET", + ); const pattern = - /(Longitude|Latitude|Course|Speed|Position Received)<\/th>\s*(.*?)<\/td>/g - const extractedData: any = {} - let match, parsedDate + /(Longitude|Latitude|Course|Speed|Position Received)<\/th>\s*(.*?)<\/td>/g; + const extractedData: any = {}; + let match, parsedDate; while ((match = pattern.exec(result)) !== null) { - const key = match[1] - const value = match[2] - extractedData[key] = value + const key = match[1]; + const value = match[2]; + extractedData[key] = value; } - console.log(extractedData['Position Received']) - console.log(123) + console.log(extractedData["Position Received"]); + console.log(123); // Extract the date and time string using regular expression - const regex = /title="([^"]+)"/ - const matchd = extractedData['Position Received'].match(regex) + const regex = /title="([^"]+)"/; + const matchd = extractedData["Position Received"].match(regex); if (matchd?.[1]) { - const dateTimeString = matchd[1] + const dateTimeString = matchd[1]; // Parse the extracted date and time string - const [datePart, timePart] = dateTimeString.split(' ') - const [year, month, day] = datePart.split('-') - const [hour, minute] = timePart.split(':') + const [datePart, timePart] = dateTimeString.split(" "); + const [year, month, day] = datePart.split("-"); + const [hour, minute] = timePart.split(":"); // JavaScript months are 0-based, so subtract 1 from the month - parsedDate = new Date(year, month - 1, day, hour, minute) + parsedDate = new Date(year, month - 1, day, hour, minute); - console.log(parsedDate) // This will log the parsed date object + console.log(parsedDate); // This will log the parsed date object } else { - console.log('Date not found in the input string.') + console.log("Date not found in the input string."); } const position = { @@ -81,11 +81,11 @@ class MyShipTracking extends Source { longitude: this.dmsToDecimalDegreesMST(extractedData.Longitude), course: 10, speed: parseFloat(extractedData.Speed), - timestamp: new Date(parsedDate).toISOString() - } - console.log(position) - return position - } + timestamp: new Date(parsedDate).toISOString(), + }; + console.log(position); + return position; + }; } -export default MyShipTracking +export default MyShipTracking; diff --git a/src/classes/sources/ais/mt.ts b/src/classes/sources/ais/mt.ts index 9ab7d84..48bff05 100644 --- a/src/classes/sources/ais/mt.ts +++ b/src/classes/sources/ais/mt.ts @@ -1,4 +1,4 @@ -import Source from '../Source' +import Source from "../Source"; class Marinetraffic extends Source { parseLocation = async function (result: any) { const location = { @@ -7,43 +7,43 @@ class Marinetraffic extends Source { longitude: result.longitude, course: result.course, speed: result.speed, - source: 'Marinetraffic', - source_type: 'AIS' - } - return location - } + source: "Marinetraffic", + source_type: "AIS", + }; + return location; + }; getLocation = async (mmsi: number) => { - const browser = await this.getBrowser() - const page = await browser.newPage() + const browser = await this.getBrowser(); + const page = await browser.newPage(); const url = - 'https://www.marinetraffic.com/en/ais/details/ships/mmsi:' + mmsi - await page.goto(url) + "https://www.marinetraffic.com/en/ais/details/ships/mmsi:" + mmsi; + await page.goto(url); // let parsedData = null; const waitForResponse = new Promise((resolve) => { - page.on('response', async (response) => { - const request = response.request() - if (request.url().includes('latestPosition')) { - const jsonresult = await response.text() - const parsedData = JSON.parse(jsonresult) - resolve(parsedData) + page.on("response", async (response) => { + const request = response.request(); + if (request.url().includes("latestPosition")) { + const jsonresult = await response.text(); + const parsedData = JSON.parse(jsonresult); + resolve(parsedData); } - }) - }) + }); + }); - const parsedData: any = await waitForResponse - browser.close() + const parsedData: any = await waitForResponse; + browser.close(); const result = { course: parseFloat(parsedData.course), speed: parseFloat(parsedData.speed), latitude: parseFloat(parsedData.lat), longitude: parseFloat(parsedData.lon), - timestamp: new Date(parsedData.lastPos * 1000).toISOString() // assuming lastPos is in seconds - } - return await this.parseLocation(result) - } + timestamp: new Date(parsedData.lastPos * 1000).toISOString(), // assuming lastPos is in seconds + }; + return await this.parseLocation(result); + }; } -export default Marinetraffic +export default Marinetraffic; diff --git a/src/index.ts b/src/index.ts index 9539c30..2ce24ba 100755 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,9 @@ #!/usr/bin/env ts-node -import dotenv from 'dotenv' -import Server from './classes/server' +import dotenv from "dotenv"; +import Server from "./classes/server"; -dotenv.config() +dotenv.config(); -const port = process.env.PORT ?? 5000 +const port = process.env.PORT ?? 5000; // eslint-disable-next-line no-new -new Server(port) +new Server(port); diff --git a/src/legacy/api.ts b/src/legacy/api.ts index d9d031d..249a1e5 100644 --- a/src/legacy/api.ts +++ b/src/legacy/api.ts @@ -1,101 +1,101 @@ -import Marinetraffic from '../classes/sources/ais/mt' -import MyShipTracking from '../classes/sources/ais/mst' +import Marinetraffic from "../classes/sources/ais/mt"; +import MyShipTracking from "../classes/sources/ais/mst"; -const moment = require('moment') -const request = require('request') +const moment = require("moment"); +const request = require("request"); const debug = (...args) => { if (true) { - console.log.apply(console, args) + console.log.apply(console, args); } -} +}; -async function getLocationFromVF (mmsi, cb) { - await getLocationFromMST(mmsi, cb) +async function getLocationFromVF(mmsi, cb) { + await getLocationFromMST(mmsi, cb); } -async function getLocationFromMST (mmsi, cb) { - const mst = new MyShipTracking() +async function getLocationFromMST(mmsi, cb) { + const mst = new MyShipTracking(); try { - const location = await mst.getLocation(mmsi) - console.log(location) + const location = await mst.getLocation(mmsi); + console.log(location); cb({ error: null, - data: location - }) + data: location, + }); } catch (e) { cb({ error: e, - data: null - }) + data: null, + }); } } -async function getLocationFromMT (mmsi, cb) { - const mt = new Marinetraffic() +async function getLocationFromMT(mmsi, cb) { + const mt = new Marinetraffic(); try { - const location = await mt.getLocation(mmsi) - console.log(location) + const location = await mt.getLocation(mmsi); + console.log(location); cb({ error: null, - data: location - }) + data: location, + }); } catch (e) { cb({ error: e, - data: null - }) + data: null, + }); } } -function getLocation (mmsi, cb) { - debug('getting location for vessel: ', mmsi) +function getLocation(mmsi, cb) { + debug("getting location for vessel: ", mmsi); getLocationFromVF(mmsi, function (VFResult) { - debug('got location from vf', VFResult) + debug("got location from vf", VFResult); getLocationFromMT(mmsi, function (MTResult) { if (MTResult.error) { - cb(VFResult) + cb(VFResult); } else { - debug('got location from mt', MTResult) + debug("got location from mt", MTResult); if (!VFResult.data) { - return cb(MTResult) + return cb(MTResult); } - const vfDate = moment(VFResult.data.timestamp) - const mtDate = moment(MTResult.data.timestamp) - const secondsDiff = mtDate.diff(vfDate, 'seconds') - debug('time diff in seconds: ', secondsDiff) + const vfDate = moment(VFResult.data.timestamp); + const mtDate = moment(MTResult.data.timestamp); + const secondsDiff = mtDate.diff(vfDate, "seconds"); + debug("time diff in seconds: ", secondsDiff); - cb(secondsDiff > 0 ? MTResult : VFResult) + cb(secondsDiff > 0 ? MTResult : VFResult); } - }) - }) + }); + }); } -function getVesselsInPort (shipPort, cb) { - const url = `https://www.marinetraffic.com/en/reports?asset_type=vessels&columns=flag,shipname,photo,recognized_next_port,reported_eta,reported_destination,current_port,imo,ship_type,show_on_live_map,time_of_latest_position,lat_of_latest_position,lon_of_latest_position,current_port_country,notes¤t_port_in_name=${shipPort}` - debug('getVesselsInPort', url) +function getVesselsInPort(shipPort, cb) { + const url = `https://www.marinetraffic.com/en/reports?asset_type=vessels&columns=flag,shipname,photo,recognized_next_port,reported_eta,reported_destination,current_port,imo,ship_type,show_on_live_map,time_of_latest_position,lat_of_latest_position,lon_of_latest_position,current_port_country,notes¤t_port_in_name=${shipPort}`; + debug("getVesselsInPort", url); const headers = { - accept: '*/*', - 'Accept-Language': 'en-US,en;q=0.5', - 'Accept-Encoding': 'gzip, deflate, brotli', - 'Vessel-Image': '0053e92efe9e7772299d24de2d0985adea14', - 'X-Requested-With': 'XMLHttpRequest' - } + accept: "*/*", + "Accept-Language": "en-US,en;q=0.5", + "Accept-Encoding": "gzip, deflate, brotli", + "Vessel-Image": "0053e92efe9e7772299d24de2d0985adea14", + "X-Requested-With": "XMLHttpRequest", + }; const options = { url, headers, json: true, gzip: true, deflate: true, - brotli: true - } + brotli: true, + }; request(options, function (error, response, html) { if ( (!error && response.statusCode === 200) || - (typeof response !== 'undefined' && response.statusCode === 403) + (typeof response !== "undefined" && response.statusCode === 403) ) { return cb( response.body.data.map((vessel) => ({ @@ -115,21 +115,21 @@ function getVesselsInPort (shipPort, cb) { port_current_id: vessel.PORT_ID, port_current: vessel.CURRENT_PORT, port_next_id: vessel.NEXT_PORT_ID, - port_next: vessel.NEXT_PORT_NAME - })) - ) + port_next: vessel.NEXT_PORT_NAME, + })), + ); } else { - debug('error in getVesselsInPort') - cb({ error: 'an unknown error occured' }) - return false + debug("error in getVesselsInPort"); + cb({ error: "an unknown error occured" }); + return false; } - }) + }); } export class api { - static getLocationFromVF = getLocationFromVF - static getLocationFromMT = getLocationFromMT - static getLocationFromMST = getLocationFromMST - static getLocation = getLocation - static getVesselsInPort = getVesselsInPort + static getLocationFromVF = getLocationFromVF; + static getLocationFromMT = getLocationFromMT; + static getLocationFromMST = getLocationFromMST; + static getLocation = getLocation; + static getVesselsInPort = getVesselsInPort; } diff --git a/src/legacy/area.ts b/src/legacy/area.ts index 2c6b6ee..ffbac78 100644 --- a/src/legacy/area.ts +++ b/src/legacy/area.ts @@ -1,19 +1,19 @@ -const scraper = require('./lib/puppeteer') +const scraper = require("./lib/puppeteer"); const fetchResultByArea = async (area, time, cb) => { await scraper.fetch( { url: `https://www.marinetraffic.com/en/reports?asset_type=vessels&columns=time_of_latest_position:desc,flag,shipname,photo,recognized_next_port,reported_eta,reported_destination,current_port,imo,ship_type,show_on_live_map,area,lat_of_latest_position,lon_of_latest_position&area_in=${area}&time_of_latest_position_between=${time}`, referer: - 'https://www.marinetraffic.com/en/data/?asset_type=vessels&columns=time_of_latest_position:desc,flag,shipname,photo,recognized_next_port,reported_eta,reported_destination,current_port,imo,ship_type,show_on_live_map,area,lat_of_latest_position,lon_of_latest_position&area_in|in|West%20Mediterranean,East%20Mediterranean|area_in=WMED,EMED&time_of_latest_position_between|gte|time_of_latest_position_between=60,525600', - responseSelector: '/en/reports?', + "https://www.marinetraffic.com/en/data/?asset_type=vessels&columns=time_of_latest_position:desc,flag,shipname,photo,recognized_next_port,reported_eta,reported_destination,current_port,imo,ship_type,show_on_live_map,area,lat_of_latest_position,lon_of_latest_position&area_in|in|West%20Mediterranean,East%20Mediterranean|area_in=WMED,EMED&time_of_latest_position_between|gte|time_of_latest_position_between=60,525600", + responseSelector: "/en/reports?", extraHeaders: { - 'vessel-image': '0053e92efe9e7772299d24de2d0985adea14' - } + "vessel-image": "0053e92efe9e7772299d24de2d0985adea14", + }, }, - cb - ) -} + cb, + ); +}; const mapResult = (result) => { return result.data.map((vessel) => ({ @@ -33,51 +33,51 @@ const mapResult = (result) => { port_current_id: vessel.PORT_ID, port_current: vessel.CURRENT_PORT, port_next_id: vessel.NEXT_PORT_ID, - port_next: vessel.NEXT_PORT_NAME - })) -} + port_next: vessel.NEXT_PORT_NAME, + })); +}; -const fetchVesselsInArea: Function = (regions = ['WMED', 'EMED'], cb) => { - const timeframe = [60, 525600] - fetchResultByArea(regions.join(','), timeframe.join(','), (result) => { +const fetchVesselsInArea: Function = (regions = ["WMED", "EMED"], cb) => { + const timeframe = [60, 525600]; + fetchResultByArea(regions.join(","), timeframe.join(","), (result) => { if (!result?.data.length) { - return cb(null) + return cb(null); } - return cb(mapResult(result)) - }) -} + return cb(mapResult(result)); + }); +}; const fetchResultNearMe = async (lat, lng, distance, time, cb) => { await scraper.fetch( { url: `https://www.marinetraffic.com/en/reports?asset_type=vessels&columns=time_of_latest_position:desc,flag,shipname,photo,recognized_next_port,reported_eta,reported_destination,current_port,imo,ship_type,show_on_live_map,area,lat_of_latest_position,lon_of_latest_position&time_of_latest_position_between=${time}&near_me=${lat},${lng},${distance}`, referer: - 'https://www.marinetraffic.com/en/data/?asset_type=vessels&columns=time_of_latest_position:desc,flag,shipname,photo,recognized_next_port,reported_eta,reported_destination,current_port,imo,ship_type,show_on_live_map,area,lat_of_latest_position,lon_of_latest_position&area_in|in|West%20Mediterranean,East%20Mediterranean|area_in=WMED,EMED&time_of_latest_position_between|gte|time_of_latest_position_between=60,525600', - responseSelector: '/en/reports?', + "https://www.marinetraffic.com/en/data/?asset_type=vessels&columns=time_of_latest_position:desc,flag,shipname,photo,recognized_next_port,reported_eta,reported_destination,current_port,imo,ship_type,show_on_live_map,area,lat_of_latest_position,lon_of_latest_position&area_in|in|West%20Mediterranean,East%20Mediterranean|area_in=WMED,EMED&time_of_latest_position_between|gte|time_of_latest_position_between=60,525600", + responseSelector: "/en/reports?", extraHeaders: { - 'vessel-image': '0053e92efe9e7772299d24de2d0985adea14' - } + "vessel-image": "0053e92efe9e7772299d24de2d0985adea14", + }, }, - cb - ) -} + cb, + ); +}; const fetchVesselsNearMe: Function = ( lat = 51.7419, lng = 3.89773, distance = 2, - cb + cb, ) => { - const timeframe = [60, 525600] - fetchResultNearMe(lat, lng, distance, timeframe.join(','), (result: any) => { + const timeframe = [60, 525600]; + fetchResultNearMe(lat, lng, distance, timeframe.join(","), (result: any) => { if (!result?.data.length) { - return cb(null) + return cb(null); } - return cb(mapResult(result)) - }) -} + return cb(mapResult(result)); + }); +}; export class areaApi { - static fetchVesselsInArea = fetchVesselsInArea - static fetchVesselsNearMe = fetchVesselsNearMe + static fetchVesselsInArea = fetchVesselsInArea; + static fetchVesselsNearMe = fetchVesselsNearMe; } diff --git a/src/legacy/lib/puppeteer.ts b/src/legacy/lib/puppeteer.ts index f41a988..9d313a2 100644 --- a/src/legacy/lib/puppeteer.ts +++ b/src/legacy/lib/puppeteer.ts @@ -1,61 +1,61 @@ -const puppeteer = require('puppeteer') +const puppeteer = require("puppeteer"); const scrapeJsonFromResponse = async (options, cb) => { const browser = await puppeteer.launch({ args: [ // Required for Docker version of Puppeteer - '--no-sandbox', - '--disable-setuid-sandbox', + "--no-sandbox", + "--disable-setuid-sandbox", // This will write shared memory files into /tmp instead of /dev/shm, // because Docker’s default for /dev/shm is 64MB - '--disable-dev-shm-usage' - ] - }) - const page = await browser.newPage() + "--disable-dev-shm-usage", + ], + }); + const page = await browser.newPage(); await page.setExtraHTTPHeaders({ - 'x-requested-with': 'XMLHttpRequest', + "x-requested-with": "XMLHttpRequest", referer: options.referer, - ...options.extraHeaders - }) - page.on('request', (interceptedRequest) => { - const reqUrl = interceptedRequest.url() - console.log('A request was started: ', reqUrl) - }) - page.on('requestfinished', async (request) => { - const resUrl = request.url() + ...options.extraHeaders, + }); + page.on("request", (interceptedRequest) => { + const reqUrl = interceptedRequest.url(); + console.log("A request was started: ", reqUrl); + }); + page.on("requestfinished", async (request) => { + const resUrl = request.url(); if (resUrl.indexOf(options.responseSelector) !== -1) { - const response = request.response() - const json = await response.json() - console.log('A response was received: ', await response.url()) - cb(json) + const response = request.response(); + const json = await response.json(); + console.log("A response was received: ", await response.url()); + cb(json); } - }) + }); // Mock real desktop chrome page.setViewport({ height: 1302, - width: 2458 - }) + width: 2458, + }); page.setUserAgent( - 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36' - ) + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36", + ); await page.evaluateOnNewDocument(() => { - Object.defineProperty(navigator, 'languages', { + Object.defineProperty(navigator, "languages", { get: function () { - return ['en-US', 'en', 'de-DE'] - } - }) - Object.defineProperty(navigator, 'plugins', { + return ["en-US", "en", "de-DE"]; + }, + }); + Object.defineProperty(navigator, "plugins", { get: function () { // this just needs to have `length > 0`, but we could mock the plugins too - return [1, 2, 3, 4, 5] - } - }) - }) + return [1, 2, 3, 4, 5]; + }, + }); + }); - await page.goto(options.url, { waitUntil: 'networkidle0' }) + await page.goto(options.url, { waitUntil: "networkidle0" }); - await browser.close() -} + await browser.close(); +}; module.exports = { - fetch: scrapeJsonFromResponse -} + fetch: scrapeJsonFromResponse, +};