NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name bahn.de+ // @license MIT // @version 1.0.2 // @description Zeigt durchschnittliche Verspätung (by zugfinder.de) und den vorrausichtlich eingesetzten Zugtyp für durch die DB betriebene Fernverkehrszüge an. Macht zusätzlich das Bahn-Logo klickbar. // @author kingjan1999 // @match *://reiseauskunft.bahn.de/* // @grant GM_xmlhttpRequest // @grant GM_addStyle // @connect zugfinder.de // @connect grahnert.de // @require https://code.jquery.com/jquery-3.3.1.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.26.0/polyfill.min.js // ==/UserScript== (function () { /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { module.exports = __webpack_require__(1); /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var _Zugfinder = __webpack_require__(2); var _States = _interopRequireDefault(__webpack_require__(3)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } GM_addStyle(_States.default.toString()); $(function () { $("tr.details ").bind("DOMSubtreeModified", function () { $(this).find(".products").each(function () { var item = $(this); if (item.hasClass("erledigt")) { return; } item.addClass("erledigt"); var product = item.text().replace(/ +(?= )/g, ''); product = product.replace(/^\s+|\s+$/g, ''); if (product !== 'Produkte' && product.trim().length > 1) { // Hier haben wir die Zugnummer var fernverkehr_regex = /(IC|ICE|EC|EN|RJ)\s[0-9]+/g; if (product.match(fernverkehr_regex) !== null) { if (product.match(fernverkehr_regex).length > 1) { // mehrere Zugnummer (z.B. ICE 633 ICE 683) product = product.match(fernverkehr_regex)[0]; } var zugnummer = product.split(" ")[1]; (0, _Zugfinder.resolveZugTyp)(product).then(function (typ) { if (typ) { item.append("<br /> Zugtyp (vorraus.): " + typ); } }); (0, _Zugfinder.resolveDelay)(product).then(function (_ref) { var average = _ref.average, quote = _ref.quote; var quote_zahl = parseInt(quote); if (quote_zahl > 95) { item.addClass("immer_puenktlich"); } else if (quote_zahl >= 90) { item.addClass("fast_puenktlich"); } else if (quote_zahl >= 80) { item.addClass("puenktlich"); } else if (quote_zahl >= 70) { item.addClass("leicht_unpuenktlich"); } else if (quote_zahl < 70) { item.addClass("unpuenktlich"); } if (average.length > 0) { item.append("<br /> ∅ Verspätung: " + average); } if (quote.length > 0) { item.append("<br /> Quote: " + quote + "%"); } }); } } }); }); $("#logo").css("cursor", "pointer").click(function () { window.location = "https://www.bahn.de/"; }); }); /***/ }), /* 2 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.resolveDelay = exports.resolveZugTyp = void 0; function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _next(value) { step("next", value); } function _throw(err) { step("throw", err); } _next(); }); }; } var zugtyp = /*#__PURE__*/ function () { var _ref = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee(product) { var regex, zugnummer, year, pad, zugid, data; return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: regex = /^(ICE|IC)\s([0-9]+)$/g; if (!(product.match(regex) === null)) { _context.next = 3; break; } return _context.abrupt("return", null); case 3: zugnummer = regex.exec(product)[2]; year = new Date().getFullYear(); pad = '00000'; zugid = year + "01" + pad.substring(0, pad.length - zugnummer.length) + zugnummer; // 01 = erstes Ergebnis _context.next = 9; return makeGMRequest("http://grahnert.de/fernbahn/datenbank/suche/index.php?zug_id=".concat(zugid)); case 9: data = _context.sent; return _context.abrupt("return", jQuery(data).find("#stammdaten p strong:contains('IC/ICE-Typ')").next().text()); case 11: case "end": return _context.stop(); } } }, _callee, this); })); return function zugtyp(_x) { return _ref.apply(this, arguments); }; }(); exports.resolveZugTyp = zugtyp; var delay = /*#__PURE__*/ function () { var _ref2 = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee2(product) { var data, average, quote; return regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: _context2.next = 2; return makeGMRequest("https://www.zugfinder.de/zuginfo.php?zugnr=".concat(product)); case 2: data = _context2.sent; average = $(data).find('.uhrbig').first().text().trim(); quote = $(data).find('[itemprop="ratingValue"]').text().trim(); quote = quote.substring(0, quote.length - 1); // remove % sign return _context2.abrupt("return", { average: average, quote: quote }); case 7: case "end": return _context2.stop(); } } }, _callee2, this); })); return function delay(_x2) { return _ref2.apply(this, arguments); }; }(); exports.resolveDelay = delay; function makeGMRequest(url) { return new Promise(function (resolve, reject) { GM_xmlhttpRequest({ method: 'GET', url: url, onload: function onload(res) { return resolve(res.responseText); }, onerror: function onerror(res) { return reject(res); } }); }); } /***/ }), /* 3 */ /***/ (function(module, exports, __webpack_require__) { exports = module.exports = __webpack_require__(4)(false); // imports // module exports.push([module.i, "#content div.detailContainer table.result tr td.immer_puenktlich {\n background-color: #3b5323; }\n\n#content div.detailContainer table.result tr td.fast_puenktlich {\n background-color: #6e9b41; }\n\n#content div.detailContainer table.result tr td.puenktlich {\n background-color: #a1c77a; }\n\n#content div.detailContainer table.result tr td.leicht_unpuenktlich {\n background-color: #d04343; }\n\n#content div.detailContainer table.result tr td.unpuenktlich {\n background-color: #8b2323;\n color: white; }\n #content div.detailContainer table.result tr td.unpuenktlich a {\n color: white; }\n", ""]); // exports /***/ }), /* 4 */ /***/ (function(module, exports) { /* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ // css base code, injected by the css-loader module.exports = function(useSourceMap) { var list = []; // return the list of modules as css string list.toString = function toString() { return this.map(function (item) { var content = cssWithMappingToString(item, useSourceMap); if(item[2]) { return "@media " + item[2] + "{" + content + "}"; } else { return content; } }).join(""); }; // import a list of modules into the list list.i = function(modules, mediaQuery) { if(typeof modules === "string") modules = [[null, modules, ""]]; var alreadyImportedModules = {}; for(var i = 0; i < this.length; i++) { var id = this[i][0]; if(typeof id === "number") alreadyImportedModules[id] = true; } for(i = 0; i < modules.length; i++) { var item = modules[i]; // skip already imported module // this implementation is not 100% perfect for weird media query combinations // when a module is imported multiple times with different media queries. // I hope this will never occur (Hey this way we have smaller bundles) if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) { if(mediaQuery && !item[2]) { item[2] = mediaQuery; } else if(mediaQuery) { item[2] = "(" + item[2] + ") and (" + mediaQuery + ")"; } list.push(item); } } }; return list; }; function cssWithMappingToString(item, useSourceMap) { var content = item[1] || ''; var cssMapping = item[3]; if (!cssMapping) { return content; } if (useSourceMap && typeof btoa === 'function') { var sourceMapping = toComment(cssMapping); var sourceURLs = cssMapping.sources.map(function (source) { return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */' }); return [content].concat(sourceURLs).concat([sourceMapping]).join('\n'); } return [content].join('\n'); } // Adapted from convert-source-map (MIT) function toComment(sourceMap) { // eslint-disable-next-line no-undef var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))); var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64; return '/*# ' + data + ' */'; } /***/ }) /******/ ]); })();