From c39036acb7ddd714f14cadf7579cf574724130df Mon Sep 17 00:00:00 2001 From: niczem Date: Thu, 6 Jun 2024 06:36:57 +0200 Subject: [PATCH] npm run lint:fix --- index.d.ts | 2 +- 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 ++++++++--------- 11 files changed, 381 insertions(+), 381 deletions(-) diff --git a/index.d.ts b/index.d.ts index c1b57a3..3de3ad6 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/src/classes/server.ts b/src/classes/server.ts index 897af22..dcc7e40 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 3f4ab4e..cb85948 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 73bf3db..e80e76c 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 02b39e5..fa660a1 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 f817d4f..e2b0ed8 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 48bff05..9ab7d84 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 2ce24ba..9539c30 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 249a1e5..d9d031d 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 ffbac78..2c6b6ee 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 9d313a2..f41a988 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 +}