diff --git a/gatsby-node.js b/gatsby-node.js new file mode 100644 index 0000000..b1554ff --- /dev/null +++ b/gatsby-node.js @@ -0,0 +1,13 @@ +exports.onCreateWebpackConfig = ({ + stage, + rules, + loaders, + plugins, + actions, + }) => { + actions.setWebpackConfig({ + resolve: { + fallback: { "os": require.resolve("os-browserify/browser") } + } + }) + } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 08a0ea7..f26d056 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,10 @@ "name": "infoscreen_gatsby", "version": "1.0.0", "dependencies": { + "fast-xml-parser": "^4.0.0-beta.8", "gatsby": "^4.4.0", "gatsby-plugin-react-svg": "^3.1.0", + "os-browserify": "^0.3.0", "react": "^17.0.1", "react-dom": "^17.0.1" }, @@ -7451,6 +7453,21 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, + "node_modules/fast-xml-parser": { + "version": "4.0.0-beta.8", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.0-beta.8.tgz", + "integrity": "sha512-2QEZ/WRt6mfrguLsluhvpTWNxdKYgvdZx3dA+Tnx0pUmlEA4ZWt32qSmA1sR1jXscFozHIKqZrikUeiCYSe3ow==", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + }, "node_modules/fastest-levenshtein": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", @@ -11551,6 +11568,11 @@ "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.2.1.tgz", "integrity": "sha512-Zl2RCcj/wRCakW9/yI83gutgNf7JFOPEHrCK72z+boIrU+PWAnIt6HADd1w+3keDQ90GCKbp1BduKZgkeNbz7A==" }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -14826,6 +14848,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, "node_modules/strtok3": { "version": "6.2.4", "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.2.4.tgz", @@ -14995,6 +15022,26 @@ "node": ">=4.0.0" } }, + "node_modules/svg-react-loader/node_modules/xml2js": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz", + "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "^4.1.0" + } + }, + "node_modules/svg-react-loader/node_modules/xmlbuilder": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", + "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=", + "dependencies": { + "lodash": "^4.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/svgo": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", @@ -16382,26 +16429,6 @@ "node": ">=8" } }, - "node_modules/xml2js": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz", - "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "^4.1.0" - } - }, - "node_modules/xmlbuilder": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", - "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=", - "dependencies": { - "lodash": "^4.0.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/xmlhttprequest-ssl": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz", @@ -22145,6 +22172,14 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, + "fast-xml-parser": { + "version": "4.0.0-beta.8", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.0-beta.8.tgz", + "integrity": "sha512-2QEZ/WRt6mfrguLsluhvpTWNxdKYgvdZx3dA+Tnx0pUmlEA4ZWt32qSmA1sR1jXscFozHIKqZrikUeiCYSe3ow==", + "requires": { + "strnum": "^1.0.5" + } + }, "fastest-levenshtein": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", @@ -25213,6 +25248,11 @@ "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.2.1.tgz", "integrity": "sha512-Zl2RCcj/wRCakW9/yI83gutgNf7JFOPEHrCK72z+boIrU+PWAnIt6HADd1w+3keDQ90GCKbp1BduKZgkeNbz7A==" }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -27623,6 +27663,11 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, + "strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, "strtok3": { "version": "6.2.4", "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.2.4.tgz", @@ -27742,6 +27787,23 @@ "emojis-list": "^2.0.0", "json5": "^0.5.0" } + }, + "xml2js": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz", + "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "^4.1.0" + } + }, + "xmlbuilder": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", + "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=", + "requires": { + "lodash": "^4.0.0" + } } } }, @@ -28750,23 +28812,6 @@ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" }, - "xml2js": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz", - "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=", - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "^4.1.0" - } - }, - "xmlbuilder": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", - "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=", - "requires": { - "lodash": "^4.0.0" - } - }, "xmlhttprequest-ssl": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz", diff --git a/package.json b/package.json index 4e02f4c..879b26c 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,10 @@ "clean": "gatsby clean" }, "dependencies": { + "fast-xml-parser": "^4.0.0-beta.8", "gatsby": "^4.4.0", "gatsby-plugin-react-svg": "^3.1.0", + "os-browserify": "^0.3.0", "react": "^17.0.1", "react-dom": "^17.0.1" }, diff --git a/src/components/News.tsx b/src/components/News.tsx new file mode 100644 index 0000000..12e2858 --- /dev/null +++ b/src/components/News.tsx @@ -0,0 +1,76 @@ +import * as React from "react"; +import { XMLParser } from "fast-xml-parser"; +import * as styles from "../styles/containers/News.module.css" + +const NEWS_REFRESH_INTERVAL = 15 * 60 * 1000; + +const News = () => { + const [news, setNews] = React.useState([]) + + React.useEffect(() => { + pullNews() + const newsInterval = setInterval(pullNews, NEWS_REFRESH_INTERVAL); + + return () => clearInterval(newsInterval); + }, []) + + const processNews = (news: {title: string; updated: string;}[], postillon: {title: string; pubDate: string; categories: string[]}[]) => { + const newsTable = [] + + for (const n of news) { + if (!n.title || n.title === "") continue; + + const updated = new Date(n.updated); + newsTable.push( + + {n.title} + {updated.getHours()}:{updated.getMinutes().toString().padStart(2, "0")} + + ); + } + + const toUsePostillon = postillon.filter((news) => !news.categories.includes("Sonntagsfrage") && !news.categories.includes("Newsticker") && !news.categories.includes("Ratgeber") && !news.categories.includes("PamS") && !news.categories.includes("Leserbriefe") && !news.categories.includes("Podcast")); + toUsePostillon.forEach((n, index) => { + if (index > 2) return; + const randTablePos = Math.floor(Math.random() * newsTable.length); + const updated = new Date(n.pubDate); + newsTable.splice(randTablePos, 0, + + {n.title} + {updated.getHours()}:{updated.getMinutes().toString().padStart(2, "0")} + + ) + }) + + setNews(newsTable); + } + + const pullNews = async () => { + const xml = new XMLParser(); + const response = await fetch("https://www.tagesschau.de/xml/atom/"); + const feed: {title: string; updated: string;}[] = xml.parse(await response.text()).feed.entry; + + // Feedburner does not allow cors but at least we get JSON + const postResponse = await fetch("https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Ffeeds.feedburner.com%2Fblogspot%2FrkEL"); + const data = await postResponse.json() + + processNews(feed, data.items); + } + + return
+
+ + + {news} + +
+ + + {news} + +
+
+
+} + +export default News; \ No newline at end of file diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 8725937..62ce676 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,6 +1,7 @@ import * as React from "react" import secrets from "../../secrets.json" import Calendar from "../components/Calendar"; +import News from "../components/News"; import WeatherAndTimeContainer from "../components/WeatherAndTime" import WeatherRadar from "../components/WeatherRadar"; @@ -34,6 +35,7 @@ const IndexPage = () => { + ) } diff --git a/src/styles/containers/News.module.css b/src/styles/containers/News.module.css new file mode 100644 index 0000000..7fd0bef --- /dev/null +++ b/src/styles/containers/News.module.css @@ -0,0 +1,38 @@ +.container { + grid-area: news; +} + +.inner { + height:100%; + width: 100%; + overflow:hidden; + border-radius: 5px; +} + +.inner table { + animation: newsSlider 60s linear 0s infinite normal; + border-collapse: collapse; +} + +.inner tr { + background:rgba(0, 0, 0, .1); + border-bottom: 2px solid black; +} + +.inner td { + padding:5px; +} + +.inner td:last-child { + text-align: right; + font-size: smaller; +} + +.inner td:first-child { + font-size: 120%; +} + +@keyframes newsSlider { + from {transform: translateY(0);} + to {transform: translateY(-100%);} +} \ No newline at end of file