Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

lvb

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lvb - npm Package Compare versions

Comparing version 0.0.2 to 1.0.0

lib/index.js

109

lib/departures.js
'use strict'
const {fetch} = require('fetch-ponyfill')({Promise: require('pinkie-promise')})
const isString = require('lodash.isstring')
const isObject = require('lodash.isobject')
const toArray = require('lodash.toarray')
const merge = require('lodash.merge')
const { fetch } = require('fetch-ponyfill')()
const isString = require('lodash/isString')
const merge = require('lodash/merge')
const moment = require('moment-timezone')
const qs = require('querystring').stringify
const { stringify } = require('querystring')

@@ -14,65 +12,66 @@ const defaults = {}

const transformTime = (date, time) => {
date = moment.tz(date, 'Europe/Berlin').subtract(4, 'hours')
let depDate = moment.tz(date.format('DD.MM.YYYY')+ ' ' + time, 'DD.MM.YYYY HH:mm', 'Europe/Berlin')
// time before departure time?
if(+depDate < +date){
depDate = depDate.add(1, 'days')
}
return depDate.toDate()
date = moment.tz(date, 'Europe/Berlin').subtract(4, 'hours')
let depDate = moment.tz(date.format('DD.MM.YYYY') + ' ' + time, 'DD.MM.YYYY HH:mm', 'Europe/Berlin')
// time before departure time?
if (+depDate < +date) {
depDate = depDate.add(1, 'days')
}
return depDate.toDate()
}
const transformDeparture = (date) => (d) => ({
line: {
id: d.number,
name: d.name,
class: d.type,
operator: d.operator,
direction: d.direction
},
timetable: [
{
departure: transformTime(date, d.time),
departureDelay: ((+d.time_prognosis) || 0) * 60 * 1000
},
...(d.later_departures || []).map((ld) => ({
departure: transformTime(date, ld.time),
departureDelay: ((+ld.time_prognosis) || 0) * 60 * 1000
}))
]
line: {
id: d.number,
name: d.name,
class: d.type,
operator: d.operator,
direction: d.direction
},
timetable: [
{
departure: transformTime(date, d.time),
departureDelay: ((+d.time_prognosis) || 0) * 60 * 1000
},
...(d.later_departures || []).map((ld) => ({
departure: transformTime(date, ld.time),
departureDelay: ((+ld.time_prognosis) || 0) * 60 * 1000
}))
]
})
const departures = (station, date = Date.now(), opt = {}) => {
const options = merge(defaults, opt)
// eslint-disable-next-line no-unused-vars
const options = merge(defaults, opt)
if(isString(station)) station = {id: station, type: 'station'}
if (isString(station)) station = { id: station, type: 'station' }
if(!isString(station.id)) throw new Error('invalid or missing station id')
if(station.type !== 'station') throw new Error('invalid or missing station type')
if (!isString(station.id)) throw new Error('invalid or missing station id')
if (station.type !== 'station') throw new Error('invalid or missing station type')
station = station.id
station = station.id
const day = moment.tz(date, 'Europe/Berlin').format("DD.MM.YYYY")
const time = moment.tz(date, 'Europe/Berlin').format("HH:mm")
const day = moment.tz(date, 'Europe/Berlin').format('DD.MM.YYYY')
const time = moment.tz(date, 'Europe/Berlin').format('HH:mm')
const body = {
'results[5][2][function]': 'ws_info_stop',
'results[5][2][data]': JSON.stringify([
{"name": "results[5][2][stop]", "value": station},
{"name": "results[5][2][date]", "value": day},
{"name": "results[5][2][time]", "value": time},
{"name": "results[5][2][mode]", "value": "stop"}
])
}
const body = {
'results[5][2][function]': 'ws_info_stop',
'results[5][2][data]': JSON.stringify([
{ 'name': 'results[5][2][stop]', 'value': station },
{ 'name': 'results[5][2][date]', 'value': day },
{ 'name': 'results[5][2][time]', 'value': time },
{ 'name': 'results[5][2][mode]', 'value': 'stop' }
])
}
return fetch('https://www.l.de/verkehrsbetriebe/fahrplan/', {
method: 'post',
body: qs(body),
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
}
})
.then((res) => res.json())
.then((res) => res.connections.map(transformDeparture(date)))
return fetch('https://www.l.de/verkehrsbetriebe/fahrplan/', {
method: 'post',
body: stringify(body),
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
}
})
.then((res) => res.json())
.then((res) => res.connections.map(transformDeparture(date)))
}
module.exports = departures
'use strict'
const {fetch} = require('fetch-ponyfill')({Promise: require('pinkie-promise')})
const isString = require('lodash.isstring')
const isObject = require('lodash.isobject')
const toArray = require('lodash.toarray')
const merge = require('lodash.merge')
const { fetch } = require('fetch-ponyfill')()
const isString = require('lodash/isString')
const toArray = require('lodash/toArray')
const merge = require('lodash/merge')
const moment = require('moment-timezone')
const qs = require('querystring').stringify
const { stringify } = require('querystring')

@@ -14,136 +13,136 @@ // todo: modes of transport, delays

const defaults = {
via: null
via: null
}
const transformRouteStop = (s) => ({
type: 'station',
id: s.id + '',
name: s.name,
coordinates: {
longitude: s.lng,
latitude: s.lat
}
// todo: arrival, departure, delay
type: 'station',
id: s.id + '',
name: s.name,
coordinates: {
longitude: s.lng,
latitude: s.lat
}
// todo: arrival, departure, delay
})
const transformLeg = (l) => ({
origin: {
type: 'station',
name: l.from.station,
id: l.route[0].id + '',
coordinates: {
longitude: +l.route[0].lng,
latitude: +l.route[0].lat
}
},
destination: {
type: 'station',
name: l.to.station,
id: l.route[l.route.length-1].id + '',
coordinates: {
longitude: +l.route[l.route.length-1].lng,
latitude: +l.route[l.route.length-1].lat
}
},
line: {
id: l.line,
class: l.type,
direction: l.direction,
operator: l.operator,
color: l.color
},
route: l.route.map(transformRouteStop),
departure: moment.tz(l.from.datetime, 'YYYYMMDDHHmmss', 'Europe/Berlin').toDate(),
departureDelay: (+l.from.shifting || 0)*60*1000, // negative shifting?
arrival: moment.tz(l.to.datetime, 'YYYYMMDDHHmmss', 'Europe/Berlin').toDate(),
arrivalDelay: (+l.to.shifting || 0)*60*1000, // negative shifting?
departurePlatform: l.from.platform || null,
arrivalPlatform: l.to.platform || null
origin: {
type: 'station',
name: l.from.station,
id: l.route[0].id + '',
coordinates: {
longitude: +l.route[0].lng,
latitude: +l.route[0].lat
}
},
destination: {
type: 'station',
name: l.to.station,
id: l.route[l.route.length - 1].id + '',
coordinates: {
longitude: +l.route[l.route.length - 1].lng,
latitude: +l.route[l.route.length - 1].lat
}
},
line: {
id: l.line,
class: l.type,
direction: l.direction,
operator: l.operator,
color: l.color
},
route: l.route.map(transformRouteStop),
departure: moment.tz(l.from.datetime, 'YYYYMMDDHHmmss', 'Europe/Berlin').toDate(),
departureDelay: (+l.from.shifting || 0) * 60 * 1000, // negative shifting?
arrival: moment.tz(l.to.datetime, 'YYYYMMDDHHmmss', 'Europe/Berlin').toDate(),
arrivalDelay: (+l.to.shifting || 0) * 60 * 1000, // negative shifting?
departurePlatform: l.from.platform || null,
arrivalPlatform: l.to.platform || null
})
const hashLeg = (l) => l.from.station+'@'+l.from.datetime+'@'+l.to.station+'@'+l.to.datetime+'@'+l.line+'@'+l.type
const hashLeg = (l) => l.from.station + '@' + l.from.datetime + '@' + l.to.station + '@' + l.to.datetime + '@' + l.line + '@' + l.type
const hashJourney = (j) => j.sections.map(hashLeg).join('-')
const transformFare = (f) => ({
type: 'fare',
model: f.name,
amount: +(f.price)/100,
currency: 'EUR'
type: 'fare',
model: f.name,
amount: +(f.price) / 100,
currency: 'EUR'
})
const transformTariffs = (t) => ({
model: t.tickets['1t0'].name,
amount: +(t.tickets['1t0'].price)/100,
currency: 'EUR',
fares: toArray(t.tickets).map(transformFare)
model: t.tickets['1t0'].name,
amount: +(t.tickets['1t0'].price) / 100,
currency: 'EUR',
fares: toArray(t.tickets).map(transformFare)
})
const transformZones = (z) => ({
departure: z.zone_start,
arrival: z.zone_end,
list: z.zones // todo
departure: z.zone_start,
arrival: z.zone_end,
list: z.zones // todo
})
const transformJourney = (j) => ({
type: 'journey',
id: hashJourney(j),
legs: j.sections.map(transformLeg),
price: transformTariffs(j.tariffs),
zones: transformZones(j.tariffs)
type: 'journey',
id: hashJourney(j),
legs: j.sections.map(transformLeg),
price: transformTariffs(j.tariffs),
zones: transformZones(j.tariffs)
})
const journeys = (origin, destination, date = Date.now(), opt = {}) => {
const options = merge(defaults, opt)
const options = merge(defaults, opt)
if(isString(origin)) origin = {id: origin, type: 'station'}
if(isString(destination)) destination = {id: destination, type: 'station'}
if (isString(origin)) origin = { id: origin, type: 'station' }
if (isString(destination)) destination = { id: destination, type: 'station' }
if(!isString(origin.id)) throw new Error('invalid or missing origin id')
if(origin.type !== 'station') throw new Error('invalid or missing origin type')
if(!isString(destination.id)) throw new Error('invalid or missing destination id')
if(destination.type !== 'station') throw new Error('invalid or missing destination type')
if (!isString(origin.id)) throw new Error('invalid or missing origin id')
if (origin.type !== 'station') throw new Error('invalid or missing origin type')
if (!isString(destination.id)) throw new Error('invalid or missing destination id')
if (destination.type !== 'station') throw new Error('invalid or missing destination type')
origin = origin.id
destination = destination.id
origin = origin.id
destination = destination.id
if(options.via){
if(isString(options.via)) options.via = {id: options.via, type: 'station'}
if(!isString(options.via.id)) throw new Error('invalid or missing options.via id')
if(options.via.type !== 'station') throw new Error('invalid or missing options.via type')
options.via = options.via.id
}
if (options.via) {
if (isString(options.via)) options.via = { id: options.via, type: 'station' }
if (!isString(options.via.id)) throw new Error('invalid or missing options.via id')
if (options.via.type !== 'station') throw new Error('invalid or missing options.via type')
options.via = options.via.id
}
const day = moment.tz(date, 'Europe/Berlin').format("DD.MM.YYYY")
const time = moment.tz(date, 'Europe/Berlin').format("HH:mm")
const day = moment.tz(date, 'Europe/Berlin').format('DD.MM.YYYY')
const time = moment.tz(date, 'Europe/Berlin').format('HH:mm')
const body = {
'results[5][2][function]': 'ws_find_connections',
'results[5][2][data]': JSON.stringify([
{"name": "results[5][2][is_extended]", "value": "1"},
{"name": "results[5][2][from]", "value": origin},
{"name": "results[5][2][to]", "value": destination},
{"name": "results[5][2][via]", "value": options.via || ""},
{"name": "results[5][2][time_mode]", "value": "departure"},
{"name": "results[5][2][time]", "value": time},
{"name": "results[5][2][date]", "value": day},
{"name": "results[5][2][means_of_transport][]", "value": "STR"},
{"name": "results[5][2][means_of_transport][]", "value": "BUS"},
{"name": "results[5][2][means_of_transport][]", "value": "S/U"},
{"name": "results[5][2][means_of_transport][]", "value": "RB/RE"},
{"name": "results[5][2][mode]", "value": "connection"}
])
}
const body = {
'results[5][2][function]': 'ws_find_connections',
'results[5][2][data]': JSON.stringify([
{ 'name': 'results[5][2][is_extended]', 'value': '1' },
{ 'name': 'results[5][2][from]', 'value': origin },
{ 'name': 'results[5][2][to]', 'value': destination },
{ 'name': 'results[5][2][via]', 'value': options.via || '' },
{ 'name': 'results[5][2][time_mode]', 'value': 'departure' },
{ 'name': 'results[5][2][time]', 'value': time },
{ 'name': 'results[5][2][date]', 'value': day },
{ 'name': 'results[5][2][means_of_transport][]', 'value': 'STR' },
{ 'name': 'results[5][2][means_of_transport][]', 'value': 'BUS' },
{ 'name': 'results[5][2][means_of_transport][]', 'value': 'S/U' },
{ 'name': 'results[5][2][means_of_transport][]', 'value': 'RB/RE' },
{ 'name': 'results[5][2][mode]', 'value': 'connection' }
])
}
return fetch('https://www.l.de/verkehrsbetriebe/fahrplan/', {
method: 'post',
body: qs(body),
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
}
})
.then((res) => res.json())
.then((res) => toArray(res.connections))
.then((res) => res.map(transformJourney))
return fetch('https://www.l.de/verkehrsbetriebe/fahrplan/', {
method: 'post',
body: stringify(body),
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
}
})
.then((res) => res.json())
.then((res) => toArray(res.connections))
.then((res) => res.map(transformJourney))
}
module.exports = journeys
'use strict'
const {fetch} = require('fetch-ponyfill')({Promise: require('pinkie-promise')})
const isString = require('lodash.isstring')
const merge = require('lodash.merge')
const querystring = require('querystring')
const stringify = querystring.stringify
const escape = querystring.escape
const { fetch } = require('fetch-ponyfill')()
const isString = require('lodash/isString')
const merge = require('lodash/merge')
const { stringify, escape } = require('querystring')
const moment = require('moment-timezone')
const Queue = require('p-queue').default
// todo: POI
const defaults = {
limit: 5
limit: 5
}

@@ -20,57 +19,59 @@

const getStationID = (s) => {
const body = {
'results[5][2][function]': 'ws_info_stop',
'results[5][2][data]': JSON.stringify([
{"name": "results[5][2][stop]", "value": s},
{"name": "results[5][2][date]", "value": moment.tz('Europe/Berlin').add(1, "days").format('DD.MM.YYYY')},
{"name": "results[5][2][time]", "value": ""},
{"name": "results[5][2][mode]", "value": "stop"}
])
}
const body = {
'results[5][2][function]': 'ws_info_stop',
'results[5][2][data]': JSON.stringify([
{ 'name': 'results[5][2][stop]', 'value': s },
{ 'name': 'results[5][2][date]', 'value': moment.tz('Europe/Berlin').add(1, 'days').format('DD.MM.YYYY') },
{ 'name': 'results[5][2][time]', 'value': '' },
{ 'name': 'results[5][2][mode]', 'value': 'stop' }
])
}
return fetch('https://www.l.de/verkehrsbetriebe/fahrplan/', {
method: 'post',
body: stringify(body),
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
}
})
.then((res) => res.json())
.then((res) => {
if(res.station_info.name !== s){
throw new Error(`internal error: valid station ID! Expected "${s}", got "${res.station_info.name}"`)
}
return res.station_info.id
})
.catch((e) => null) // todo: not so stable :P
// todo: what about res.lines (empty at the moment) and res.epon_ids?
return fetch('https://www.l.de/verkehrsbetriebe/fahrplan/', {
method: 'post',
body: stringify(body),
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
}
})
.then((res) => res.json())
.then((res) => {
if (res.station_info.name !== s) {
throw new Error(`internal error: valid station ID! Expected "${s}", got "${res.station_info.name}"`)
}
return res.station_info.id
})
.catch((e) => null) // todo: not so stable :P
// todo: what about res.lines (empty at the moment) and res.epon_ids?
}
const addStationID = (s) =>
getStationID(s.name)
.then((id) => merge({id: id+''}, s))
getStationID(s.name)
.then((id) => merge({ id: id + '' }, s))
const transformStation = (s) => ({
type: 'station',
name: s.name,
coordinates: {
longitude: +s.lng,
latitude: +s.lat
}
type: 'station',
name: s.name,
coordinates: {
longitude: +s.lng,
latitude: +s.lat
}
})
const stations = (query, opt = {}) => {
if(!query || !isString(query)){
throw new Error('query must be a string != ""')
}
if (!query || !isString(query)) {
throw new Error('query must be a string != ""')
}
const options = merge(defaults, opt)
return fetch(`https://www.l.de/ajax_de?mode=autocomplete&q=${escape(query)}&poi=&limit=${options.limit}`)
.then((res) => res.json())
.then((res) => res.stations)
.then((res) => res.map(transformStation))
.then((res) => Promise.all(res.map(addStationID)))
.then((res) => res.filter((x) => !!x.id))
const q = new Queue({ concurrency: 4 })
const options = merge(defaults, opt)
return fetch(`https://www.l.de/ajax_de?mode=autocomplete&q=${escape(query)}&poi=&limit=${options.limit}`)
.then((res) => res.json())
.then((res) => res.stations)
.then((res) => res.map(transformStation))
.then((res) => q.addAll(res.map((s) => () => addStationID(s))))
.then((res) => res.filter((x) => !!x.id))
}
module.exports = stations
{
"name": "lvb",
"version": "1.0.0",
"description": "Inofficial LVB (Leipziger Verkehrsbetriebe) API client.",
"version": "0.0.2",
"keywords": [
"deutschland",
"germany",
"leipzig",
"lvb",
"leipzig",
"public",
"sachsen",
"saxony",
"germany",
"deutschland",
"öpnv",
"public",
"transport"
"transport",
"öpnv"
],
"author": "Julius Tens <mail@juliustens.de>",
"homepage": "https://github.com/juliuste/lvb",
"bugs": "https://github.com/juliuste/lvb/issues",
"repository": "juliuste/lvb",
"bugs": "https://github.com/juliuste/lvb/issues",
"main": "./index.js",
"license": "ISC",
"author": "Julius Tens <mail@juliustens.eu>",
"files": [
"index.js",
"lib/*"
],
"main": "lib/index.js",
"scripts": {
"check-deps": "depcheck",
"fix": "eslint --fix lib test.js",
"lint": "eslint lib test.js",
"prepublishOnly": "npm test",
"test": "npm run lint && npm run check-deps && node test"
},
"dependencies": {
"fetch-ponyfill": "^4.1.0",
"lodash.merge": "^4.6.0",
"lodash.toarray": "^4.4.0",
"moment-timezone": "^0.5.13",
"pinkie-promise": "^2.0.1",
"lodash.isstring": "^4.0.1"
"fetch-ponyfill": "^6.1.0",
"lodash": "^4.17.11",
"moment-timezone": "^0.5.25",
"p-queue": "^6.0.2"
},
"devDependencies": {
"lodash.isdate": "^4.0.1",
"lodash.isnumber": "^3.0.3",
"lodash.isobject": "^3.0.2",
"tape": "^4.8.0"
"depcheck": "^0.8.1",
"eslint": "^5.16.0",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.17.3",
"eslint-plugin-node": "^9.1.0",
"eslint-plugin-promise": "^4.1.1",
"eslint-plugin-standard": "^4.0.0",
"tape": "^4.10.2",
"tape-promise": "^4.0.0"
},
"scripts": {
"test": "node test.js",
"prepublish": "npm test"
},
"engines": {
"node": ">=6"
},
"license": "MIT"
"node": ">=8"
}
}
# lvb
Client for the [LVB](https://l.de/verkehrsbetriebe) (Leipziger Verkehrsbetriebe) API. Inofficial, please ask LVB for permission before using this module in production. **Actually, there should be no need for projects like this since municipal public transportation endpoints should be open to the public. It's 2017.**
Client for the [LVB](https://l.de/verkehrsbetriebe) (Leipziger Verkehrsbetriebe) API. Inofficial, please ask LVB for permission before using this module in production. **Actually, there should be no need for projects like this since municipal public transportation endpoints should be open to the public. It's 2018.**

@@ -8,4 +8,2 @@ [![npm version](https://img.shields.io/npm/v/lvb.svg)](https://www.npmjs.com/package/lvb)

[![Greenkeeper badge](https://badges.greenkeeper.io/juliuste/lvb.svg)](https://greenkeeper.io/)
[![dependency status](https://img.shields.io/david/juliuste/lvb.svg)](https://david-dm.org/juliuste/lvb)
[![dev dependency status](https://img.shields.io/david/dev/juliuste/lvb.svg)](https://david-dm.org/juliuste/lvb#info=devDependencies)
[![license](https://img.shields.io/github/license/juliuste/lvb.svg?style=flat)](LICENSE)

@@ -12,0 +10,0 @@ [![chat on gitter](https://badges.gitter.im/juliuste.svg)](https://gitter.im/juliuste)

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc