diff --git a/README.md b/README.md index 84b7cc7..7b6ba87 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,10 @@ MONGODB_URI //mongoodb uri for the access/refresh tokens. AEMET_API_KEY //aemet api key to get spanish weather (https://opendata.aemet.es/centrodedescargas/inicio) SQL_CONNECTION //sql connection string for the train information PORT //port of the running app +TELEGRAM_TOKEN //Telegram bot API token to send notifications +TELEGRAM_CHAT_ID //Telegram chat id to send the notifications +EXTERNAL_URL //external url of the running app to create the public image urls +BROWSERLESS_URL //browserless websocket url to take screenshots ``` ## Weather @@ -41,5 +45,15 @@ Find next departure time of the train from a given origin and destination. It us ```javascript !ave girona, sants -//result: +//result: Próximo tren AVE de Girona a Barcelona-Sants sale a las 16:30:00 +``` + +## Photo +Take a screenshot of the current stream and send it to the chat. + +### commands + +```javascript +!foto +//result: https://external.url/images/cclj35.png ``` diff --git a/app.js b/app.js index ebdbd68..7c10c56 100644 --- a/app.js +++ b/app.js @@ -17,7 +17,7 @@ mongoose.connect(config.database).then(() => { const listener = app.listen(process.env.PORT, ()=> { console.log('Listening on port ', + listener.address().port) - app.get('/', (req, res) => res.send('Hello World!')) + app.get('/', (req, res) => res.send('Live!')) }) }) }) diff --git a/handlers/stream.js b/handlers/stream.js index f98d035..fb771b6 100644 --- a/handlers/stream.js +++ b/handlers/stream.js @@ -8,7 +8,6 @@ require('mathjs') const twitchUrl = 'https://www.twitch.tv/' class Stream { - async refreshPage() { await BrowserService.refreshPage().catch(() => { console.error('refreshPage on refreshPage')}) } @@ -53,11 +52,7 @@ class Stream { message_id: result.messageId, parse_mode: 'Markdown' } - try { - await bot.editMessageText(this._getText(result), options) - } catch { - console.log('error') - } + await bot.editMessageText(this._getText(result), options).catch(() => {}) await TwitchService.saveTitle(result.title) await BrowserService.startAndWarmUpBrowserIfNeeded().catch(() => { console.error('startAndWarmUpBrowserIfNeeded on stillLive')}) } else if (result && result.type === 'notLive') { diff --git a/helpers/browserApi.js b/helpers/browserApi.js index f9fdbbc..0a42bd2 100644 --- a/helpers/browserApi.js +++ b/helpers/browserApi.js @@ -6,14 +6,6 @@ class PuppeteerApi { page = null svgImage = null - constructor() { - } - - getSvgImage() { - return this.svgImage - } - - async createNewBrowser() { this.browser = await puppeteer.connect({ browserWSEndpoint: config.browserlessUrl }) this.browser.on('disconnected', async () => { @@ -24,38 +16,11 @@ class PuppeteerApi { }) } - async getBrowser() { - if (!this.browser) { - await this.createNewBrowser() - } - return this.browser - } - async createNewPage() { - this.page = await this._newPage() + this.page = this.browser.newPage() await this.handleStart() } - async getPage() { - if (!this.page) { - await this.createNewPage() - } - return this.page - } - - async _newPage() { - const browser = await this.getBrowser() - return await browser.newPage() - } - - async handBack(page) { - // close the page or even reuse it?. - await page.close() - - // you could add logic for closing the whole browser instance depending what - // you want. - } - async handleStart() { await this.page.setViewport({ width: 1920, height: 1080 }) await this.page.goto("https://www.twitch.tv/" + config.twitch.channels, { waitUntil: ['networkidle0', 'domcontentloaded'] }) @@ -72,9 +37,19 @@ class PuppeteerApi { this.svgImage = await this.page.$('div.persistent-player') } + async refreshPage() { + await this.page.reload({ waitUntil: ["networkidle0", "domcontentloaded"] }) + await this.removeElementsAndGetDiv() + } - async closeBrowser() { - await this.browser.close() + async takeScreenshot(path) { + if (this.svgImage) { + return await this.svgImage.screenshot({ + path: path, + omitBackground: true + }) + } + return null } async checkIfBrowserIsOpen() { @@ -95,12 +70,9 @@ class PuppeteerApi { return !isClosed } - async resfreshPage() { - await this.page.reload({ waitUntil: ["networkidle0", "domcontentloaded"] }) - await this.removeElementsAndGetDiv() + async closeBrowser() { + await this.browser.close() } - - } const browserApi = new PuppeteerApi() diff --git a/lib/inputParser.js b/lib/inputParser.js index 1566a18..d6ff27d 100644 --- a/lib/inputParser.js +++ b/lib/inputParser.js @@ -24,7 +24,7 @@ class InputParser { } isAskingForF5 (text) { - return text.toLowerCase().startsWith('!restartfoto') + return text.toLowerCase().startsWith('!f5') } } diff --git a/lib/messenger.js b/lib/messenger.js index f26f6ff..8a5f179 100644 --- a/lib/messenger.js +++ b/lib/messenger.js @@ -80,7 +80,7 @@ class Messenger { if (textSplit.length > 0 && inputParser.isAskingForTakeScreenshot(textSplit[0])) return handlers.stream.captureScreenshot(target, this.bot, this.notifier.bot, context['display-name']) - if (textSplit.length > 0 && inputParser.isAskingForF5(textSplit[0])) + if (textSplit.length > 0 && inputParser.isAskingForF5(textSplit[0]) && (context['mod'] || context['vip'])) return handlers.stream.refreshPage(target, this.bot, this.notifier.bot) } diff --git a/services/browser.js b/services/browser.js index 5192221..2061ae7 100644 --- a/services/browser.js +++ b/services/browser.js @@ -11,10 +11,7 @@ async function getScreenshot() { } const name = Math.random().toString(36).substring(2,8) try { - bufferImage = await browserApi.getSvgImage().screenshot({ - path: `public/images/${name}.png`, - omitBackground: true - }) + bufferImage = await browserApi.takeScreenshot(`public/images/${name}.png`) } catch (error) { console.log(error) return null @@ -22,10 +19,6 @@ async function getScreenshot() { return {buffer: bufferImage, fileName: `${name}.png` } } -async function closeBrowser() { - return await browserApi.closeBrowser() -} - async function startAndWarmUpBrowserIfNeeded() { const browserIsOpen = await browserApi.checkIfBrowserIsOpen() @@ -44,10 +37,12 @@ async function startAndWarmUpBrowserIfNeeded() { } async function refreshPage() { - await browserApi.resfreshPage() + await browserApi.refreshPage() } - +async function closeBrowser() { + return await browserApi.closeBrowser() +} async function closeBrowserIfNeeded() { const isOpened = await browserApi.checkIfBrowserIsOpen() diff --git a/services/twitch.js b/services/twitch.js index b3bba3f..feadac1 100644 --- a/services/twitch.js +++ b/services/twitch.js @@ -5,6 +5,7 @@ const endpointPrefix = 'https://api.twitch.tv/helix/streams' async function getStream() { let result = { type: 'notLive'} + let liveData = null const token = await dbManager.getToken(parseInt(config.twitch.userId)).lean() const endpoint = endpointPrefix + '?user_login=' + config.twitch.channels @@ -14,9 +15,15 @@ async function getStream() { 'Authorization': 'Bearer ' + token.accessToken } } - const response = await fetch(endpoint, options) - const data = await response.json() - const liveData = data?.data?.[0] ?? null + + try { + const response = await fetch(endpoint, options) + const data = await response.json() + liveData = data?.data?.[0] ?? null + + } catch { + result = { type: 'error'} + } const channel = await dbManager.getChannel(config.twitch.channels).lean() if (liveData && !channel.live) {