diff --git a/MMM-idos.css b/MMM-idos.css new file mode 100644 index 0000000..4063252 --- /dev/null +++ b/MMM-idos.css @@ -0,0 +1,32 @@ +/* Magic Mirror + * Module: MMM-idos + * Description: Display estimations for public transport stops in Bratislava, Slovakia + * + * By Adrian Matejov https://github.com/Adman + * MIT Licensed. + */ + +.MMM-idos { + width : 300px; +} + +.MMM-idos tr { + padding-top: 5px; +} + +.blinking .blink { + animation: blink 1s ease-in-out infinite alternate; +} + +@-webkit-keyframes blink { + from { opacity: 0.2; } + to { opacity: 1; } +} + +.idos-padding-left { + padding-left: 5px; +} + +.MMM-idos table { + font-size: 1rem; +} \ No newline at end of file diff --git a/MMM-idos.js b/MMM-idos.js new file mode 100644 index 0000000..c8028c8 --- /dev/null +++ b/MMM-idos.js @@ -0,0 +1,198 @@ +/* Magic Mirror Module + * Module: MMM-idos + * Description: Display estimations for public transport stops in the Czech Republic + * + * By elrubio https://github.com/soyrubio + * MIT Licensed. + */ + +Module.register('MMM-idos', { + defaults: { + maximumEntries: 5, + refreshInterval: 60000, // in milliseconds + displaySymbol: true, + displayLineNumber: true, + displayDestination: true, + + fadePoint: 0.25, // Start on the 1/4th of the list + fade: true, + blink: true, + torPorts: ['9050', '9052', '9053', '9054'] + }, + + getStyles: function () { + return ['font-awesome.css', this.file('MMM-idos.css')]; + }, + + getTranslations: function () { + return { + en: "translations/en.json", + sk: "translations/sk.json", + cz: "translations/sk.json", + } + }, + + start: function () { + Log.log('Starting module: ' + this.name); + + this.livetable = {}; + + this.idos_loaded = false; + this.idos_fetch_error = false; + + this.scheduleUpdate(); + this.updateDom(); + }, + + getDom: function () { + var wrapper = document.createElement('div'); + + if (this.idos_fetch_error) { + wrapper.innerHTML = this.translate('IDOS_FETCH_ERROR'); + wrapper.className = 'dimmed light small'; + return wrapper; + } + + if (!(this.idos_loaded)) { + wrapper.innerHTML = this.translate('LOADING'); + wrapper.className = 'dimmed light small'; + return wrapper; + } + + /* process data */ + var all_lines = this.livetable; + all_lines = all_lines.slice(0, this.config.maximumEntries); + + if (this.config.fade && this.config.fadePoint < 1) { + if (this.config.fadePoint < 0) { + this.config.fadePoint = 0; + } + var start_fade = all_lines.length * this.config.fadePoint; + var fade_steps = all_lines.length - start_fade; + } + + var table = document.createElement('table'); + table.className = 'small'; + + if (all_lines.length > 0) { + for (var i = 0; i < all_lines.length; i++) { + var line = all_lines[i]; + + var row = document.createElement('tr'); + + /* row fading */ + if (i + 1 >= start_fade) { + var curr_fade_step = i - start_fade; + row.style.opacity = 1 - (1 / fade_steps * curr_fade_step); + } + + /* display symbol */ + if (this.config.displaySymbol) { + var w_symbol_td = document.createElement('td'); + var w_symbol = document.createElement('span'); + w_symbol.className = 'fa fa-fw fa-' + line.type; + w_symbol_td.appendChild(w_symbol); + row.appendChild(w_symbol_td); + } + + /* display line number */ + if (this.config.displayLineNumber) { + var w_line_num_td = document.createElement('td'); + w_line_num_td.className = 'idos-padding-left align-right'; + w_line_num_td.innerHTML = line.number; + row.appendChild(w_line_num_td); + } + + /* display destination */ + if (this.config.displayDestination) { + var w_dest_td = document.createElement('td'); + w_dest_td.className = 'idos-padding-left align-left idos-destination'; + w_dest_td.innerHTML = line.destination; + row.appendChild(w_dest_td); + } + + /* display time left */ + var w_time_td = document.createElement('td'); + w_time_td.className = 'align-right idos-departure'; + if (this.config.blink) { + w_time_td.className += 'blink'; + } + var departure_time = this.getDepartureTime(line); + w_time_td.innerHTML = departure_time; + row.appendChild(w_time_td); + + /* display delay dot */ + var dot_td = document.createElement('td'); + dot_td.className = 'idos-delay-dot' + if (this.config.blink) { + w_time_td.className += 'blink'; + } + if (line.delay !== "0") { + dot_td.innerHTML = "•"; + } + row.appendChild(dot_td); + + /* departuring now should blink */ + row.className = 'bright' + if (this.config.blink && departure_time === "<1 min") + row.className += ' blinking'; + + table.appendChild(row); + } + } else { + var row = document.createElement('tr'); + table.appendChild(row); + + var no_line_cell = document.createElement('td'); + no_line_cell.className = 'dimmed light small'; + no_line_cell.innerHTML = this.translate('IDOS_NO_LINES'); + row.appendChild(no_line_cell); + } + + wrapper.appendChild(table); + return wrapper; + }, + + socketNotificationReceived: function (notification, payload) { + if (payload.module_id == this.identifier) { + if (notification === 'IDOS_UPDATE') { + this.idos_loaded = true; + this.idos_fetch_error = false; + this.livetable = payload.result; + this.updateDom(); + } else if (notification === 'IDOS_FETCH_ERROR') { + this.idos_fetch_error = true; + this.updateDom(); + } + } + }, + + scheduleUpdate: function () { + this.sendSocketNotification('IDOS_STOP_INFO', { + module_id: this.identifier, + stop_id: this.config.stopId, + ports: this.config.torPorts + }); + + var self = this; + setTimeout(function () { + self.scheduleUpdate(); + }, this.config.refreshInterval); + }, + + getDepartureTime: function (line) { + var now = new Date(); + var time = line.departure.split(":"); + var departure = new Date(now.getFullYear(), now.getMonth(), now.getDate(), time[0], time[1], 0); + var diff = (departure - now) / 60000; + departure.setMinutes(departure.getMinutes() + parseInt(line.delay)); + diff = (departure - now) / 60000; + if (diff < 1) { + diff = "<1" + } else { + diff = Math.round(diff); + } + diff += " min" + return diff; + } +}); diff --git a/README.md b/README.md new file mode 100644 index 0000000..9978922 --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +# MMM-idos + +This is a Magic Mirror Module (https://github.com/MichMich/MagicMirror/), which displays +real time estimated departures for public transport in the Czech Republic. + + +![screenshoot](img/screenshoot.png) + +## Installation + +Clone this module into your Magic Mirror modules folder. +1. Go into Magic Mirror's `modules` folder +2. Execute `git clone https://github.com/soyrubio/MMM-idos.git`. + +## Using the module + +In order to use this module, add the following configuration into Magic Mirror's config file (located in 'config/config.js'): + +```js +var config = { + modules: [ + { + module: 'MMM-idos', + header: '
', // no header will be displayed if ommited + position: 'top_right', // position of the module + config: { + stopId: string, // "https://idos.idnes.cz/vlakyautobusymhdvse/odjezdy/vysledky/?f=the_stop + /* other configurations */ + } + } + ] +} +``` + +## Configuration options + +| Option | Description +|--------------------- |------------ +| `stopId` | *Required* Id of the stop (parameter "z" in stop's livetable url).

**Type:** `int`
**Default value:** `none` +| `maximumEntries` | *Optional* The maximum entries shown.

**Type:** `int`
**Default value:** `10` +| `refreshInterval` | *Optional* How often to check for the next lines.

**Type:** `int`
**Default value:** `30000` milliseconds (60 seconds) +| `fade` | *Optional* Fade the future lines to black. (Gradient)

**Type:** `boolean`
**Default value:** `true` +| `fadePoint` | *Optional* Where to start fade?

**Type:** `float`
**Default value:** `0.25` (start on the 1/4 th of the list) +| `blink` | *Optional* Whether departures should blink when departure time is <1 min. >

**Type:** `boolean`
**Default value:** `true` +| `displaySymbol` | *Optional* Whether to display bus/tram symbols.

**Type:** `boolean`
**Default value:** `true` +| `displayLineNumber` | *Optional* Whether to display line number.

**Type:** `boolean`
**Default value:** `true` +| `displayDestination` | *Optional* Whether to display destination stop.

**Type:** `boolean`
**Default value:** `true` + +## Credits +The module is based on the [MMM-imhdsk By Adman](https://github.com/Adman/MMM-imhdsk), his module is far better than my own would be so this is basically the MMM-imhdsk module remade to fetch departures data from the idos.cz website. Thanks Adman! + +*Beware that by using this you might be violating idos.cz ToS* diff --git a/img/screenshot.png b/img/screenshot.png new file mode 100644 index 0000000..8932c2e Binary files /dev/null and b/img/screenshot.png differ diff --git a/node-idos.js b/node-idos.js new file mode 100644 index 0000000..7271779 --- /dev/null +++ b/node-idos.js @@ -0,0 +1,123 @@ +/* Magic Mirror Module + * Module: MMM-idos + * Description: Display estimations for public transport stops in the Czech Republic + * + * By elrubio https://github.com/soyrubio + * MIT Licensed. + * + * This is a web scraper for the MMM-idos module + * The data is scraped from https://idos.idnes.cz/vlakyautobusymhdvse/odjezdy/ + */ + +const puppeteer = require('puppeteer'); +const cheerio = require('cheerio'); + +function parse_body(body) { + const $ = cheerio.load(body) + + var stops = [] + $(".dep-row-first").each(function () { + var stop = $(this).find("h3").map(function () { + return $(this).text().trim() + }).toArray(); + stops.push(stop); + }); + var vehicles = $(".departures-table__cell img").map(function () { + return $(this).attr("alt") + }); + var delays = $(".cell-delay").map(function () { + return $(this).find(".delay-bubble").text().replace(/[^0-9]/g, "").replace(/^$/, "0") + }); + + var output = []; + for (let i = 0; i < stops.length; i++) { + stop = stops[i]; + + output.push({ + "destination": stop[0], + "number": stop[1].replace("Bus", "").replace("Tram", "").trim(), + "departure": stop[2].replace(/\n.*/g, ""), + "delay": delays[i], + "departurewdelay": getDepartureWDelay(stop[2], delays[i]), + "type": vehicles[i].replace("tramvaj", "train").replace("autobus", "bus").replace("trolejbus", "bus") + }); + } + + output.sort(getSortOrder("departurewdelay")); + + return output; +} + +function getSortOrder(prop) { + return function (a, b) { + if (a[prop] > b[prop]) { + return 1; + } else if (a[prop] < b[prop]) { + return -1; + } + return 0; + } +} + +function getDepartureWDelay(dep, delay) { + var now = new Date(); + var time = dep.split(":"); + var departure = new Date(now.getFullYear(), now.getMonth(), now.getDate(), time[0], time[1], 0); + var diff = (departure - now) / 60000; + departure.setMinutes(departure.getMinutes() + parseInt(delay)); + diff = (departure - now) / 60000; + diff = Math.round(diff); + return diff; +} + +async function scrape(options, callback) { + try { + var port_arg; + if (options.ports.length > 0) { + const randomPort = options.ports[Math.floor(Math.random() * options.ports.length)]; + port_arg = '--proxy-server=socks5://127.0.0.1:' + randomPort; + } + const browser = await puppeteer.launch({ + args: [port_arg], + executablePath: '/usr/bin/chromium-browser' + }); + const page = await browser.newPage(); + + await page.setRequestInterception(true); + page.on('request', (request) => { + if (['image', 'stylesheet', 'font', 'script'].indexOf(request.resourceType()) !== -1) { + request.abort(); + } else { + request.continue(); + } + }); + + await page.goto(options.url); + const content = await page.content(); + setTimeout(() => { + browser.close(); + }, 3000); + callback(null, content); + } catch (err) { + callback(err, null); + } +} + +exports.get_livetable = function (stop, ports) { + var url = 'https://idos.idnes.cz/vlakyautobusymhdvse/odjezdy/vysledky/?f=' + stop; + + //var stops = scrape(url, props.ports); + return new Promise(function (resolve, reject) { + scrape({ + url: url, + ports: ports + }, function (err, body) { + if (err) + return reject(err); + else + return resolve(parse_body(body)); + }) + }); + + return stops; +} diff --git a/node_helper.js b/node_helper.js new file mode 100644 index 0000000..ac2deb2 --- /dev/null +++ b/node_helper.js @@ -0,0 +1,40 @@ +/* Magic Mirror Module + * Module: MMM-idos + * Description: Display estimations for public transport stops in the Czech Republic + * + * By elrubio https://github.com/soyrubio + * MIT Licensed. + */ + +const NodeHelper = require('node_helper'); +const idos = require('./node-idos.js'); + +module.exports = NodeHelper.create({ + start: function() { + console.log('Starting node helper for: ' + this.name); + }, + + socketNotificationReceived: function(notification, payload) { + if (notification === 'IDOS_STOP_INFO') { + this.getDataForStop(payload.module_id, + payload.stop_id, + payload.ports); + } + }, + + getDataForStop: function(module_id, stop_id, ports) { + + var self = this; + idos.get_livetable(stop_id, ports).then(function(res) { + self.sendSocketNotification('IDOS_UPDATE', { + module_id: module_id, + result: res + }); + }).catch(function(err) { + console.log("MMM-idos fetch error: " + err); + self.sendSocketNotification('IDOS_FETCH_ERROR', { + module_id: module_id + }); + }); + } +}); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..80952b9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,504 @@ +{ + "name": "MMM-idos", + "version": "0.0.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/node": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.4.tgz", + "integrity": "sha512-k3NqigXWRzQZVBDS5D1U70A5E8Qk4Kh+Ha/x4M8Bt9pF0X05eggfnC9+63Usc9Q928hRUIpIhTQaXsZwZBl4Ew==" + }, + "@types/yauzl": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz", + "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==", + "optional": true, + "requires": { + "@types/node": "*" + } + }, + "agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bl": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", + "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "cheerio": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.1", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash": "^4.15.0", + "parse5": "^3.0.1" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" + }, + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "devtools-protocol": { + "version": "0.0.799653", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.799653.tgz", + "integrity": "sha512-t1CcaZbvm8pOlikqrsIM9GOa7Ipp07+4h/q9u0JXBWjPCjHdBl9KkddX87Vv9vBHoBGtwV79sYQNGnQM6iS5gg==" + }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "requires": { + "@types/yauzl": "^2.9.1", + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "~1.2.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, + "https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "requires": { + "agent-base": "5", + "debug": "4" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "requires": { + "@types/node": "*" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "requires": { + "find-up": "^4.0.0" + } + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "puppeteer": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-5.3.1.tgz", + "integrity": "sha512-YTM1RaBeYrj6n7IlRXRYLqJHF+GM7tasbvrNFx6w1S16G76NrPq7oYFKLDO+BQsXNtS8kW2GxWCXjIMPvfDyaQ==", + "requires": { + "debug": "^4.1.0", + "devtools-protocol": "0.0.799653", + "extract-zip": "^2.0.0", + "https-proxy-agent": "^4.0.0", + "pkg-dir": "^4.2.0", + "progress": "^2.0.1", + "proxy-from-env": "^1.0.0", + "rimraf": "^3.0.2", + "tar-fs": "^2.0.0", + "unbzip2-stream": "^1.3.3", + "ws": "^7.2.3" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "tar-fs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz", + "integrity": "sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.0.0" + } + }, + "tar-stream": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz", + "integrity": "sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "tor": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tor/-/tor-0.0.1.tgz", + "integrity": "sha1-26Z5bX+JDZOZ4W3W5YfKTl9fvwE=" + }, + "unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", + "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==" + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..45ea985 --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "MMM-idos", + "version": "1.0.0", + "description": "Display estimations for public transport stops in the Czech republic.", + "repository": { + "type": "git", + "url": "git+https://github.com/soyrubio/MMM-idos.git" + }, + "keywords": [ + "MagicMirror", + "bus stop", + "tram stop", + "czech republic", + "public transport" + ], + "author": "elrubio", + "license": "MIT", + "bugs": { + "url": "https://github.com/soyrubio/MMM-idos/issues" + }, + "homepage": "https://github.com/soyrubio/MMM-idos", + "dependencies": { + "cheerio": "^1.0.0-rc.3", + "puppeteer": "^5.3.1", + "tor": "0.0.1" + } +} diff --git a/translations/cz.json b/translations/cz.json new file mode 100644 index 0000000..db98426 --- /dev/null +++ b/translations/cz.json @@ -0,0 +1,4 @@ +{ + "IDOS_NO_LINES": "Žádné odchody", + "IDOS_FETCH_ERROR": "Nepodařilo se stáhnout data" +} diff --git a/translations/en.json b/translations/en.json new file mode 100644 index 0000000..42581de --- /dev/null +++ b/translations/en.json @@ -0,0 +1,4 @@ +{ + "IDOS_NO_LINES": "No lines at the moment", + "IDOS_FETCH_ERROR": "Failed to fetch data" +} diff --git a/translations/sk.json b/translations/sk.json new file mode 100644 index 0000000..4d22b8c --- /dev/null +++ b/translations/sk.json @@ -0,0 +1,4 @@ +{ + "IDOS_NO_LINES": "Aktuálne žiadne spoje", + "IDOS_FETCH_ERROR": "Nepodarilo sa stiahnuť dáta" +}