From 9eda82cc8fdf68040386235a8b6b0a8fbfa40fd5 Mon Sep 17 00:00:00 2001 From: siddiquiaffan Date: Sat, 7 Oct 2023 22:22:54 +0530 Subject: [PATCH 1/8] Prettify --- bot.js | 115 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 40 deletions(-) diff --git a/bot.js b/bot.js index 99c1a0e..c2a35bb 100644 --- a/bot.js +++ b/bot.js @@ -23,27 +23,31 @@ const reply_markup = { const processUrl = async (msg, ctx) => { try { - const url = await unshort(msg); - const productUrl = "http" + url.split("http")[1].split(" ")[0].replace("dl.", "www.") - if (isUrl(productUrl)) { - const merchant = productUrl.replace("www.", "").split("//")[1].split(".")[0]; - if (merchant.match(/amazon|flipkart|snapdeal/gi)) { - const noOfProducts = ( await manageProducts({ userId: ctx.from.id }, "read") )?.result?.length; + const url = await unshort(msg); + const productUrl = "http" + url.split("http")[1].split(" ")[0].replace("dl.", "www.") + + if (isUrl(productUrl)) { + const merchant = productUrl.replace("www.", "").split("//")[1].split(".")[0]; + + if (merchant.match(/amazon|flipkart|snapdeal/gi)) { + const noOfProducts = (await manageProducts({ userId: ctx.from.id }, "read"))?.result?.length; + if (noOfProducts < LIMIT) { const sentMsg = await ctx.reply(`Tracking ${merchant} product...`, { reply_to_message_id: ctx.message.message_id }); const details = await getProductDetails(productUrl, merchant); - + if (details.ok) { try { const tracking_id = getRandomId(); await manageProducts( { tracking_id, userId: ctx.from.id, merchant, title: details.title, link: details.link, initPrice: details.price, price: details.price, }, "update" - ); - await ctx.api.editMessageText( - ctx.chat.id, sentMsg.message_id, - ` \nTracking ${details.title}\n\nCurrent Price: ${details.price}\nLink: ${merchant}\n\nTo stop tracking send /stop_${tracking_id}`, - { parse_mode: "HTML", reply_markup } + ); + + await ctx.api.editMessageText( + ctx.chat.id, sentMsg.message_id, + ` \nTracking ${details.title}\n\nCurrent Price: ${details.price}\nLink: ${merchant}\n\nTo stop tracking send /stop_${tracking_id}`, + { parse_mode: "HTML", reply_markup } ); } catch (e) { } } else { @@ -51,21 +55,23 @@ const processUrl = async (msg, ctx) => { ctx.chat.id, sentMsg.message_id, `Sorry, I couldn't track this product. Make sure you've sent correct product link.`, { parse_mode: "Markdown", reply_markup } - ).catch(e => {}); - } - } else { - ctx.reply( "I'm sorry, but you can't add more products as you've already reached the maximum limit.\n\nPlease delete atleast one product. And try again.\n\nTo get list send /list", - { reply_to_message_id: ctx.message.message_id } ).catch(e => {}); + ).catch(e => { }); } + } else { - ctx.reply( `Sorry, I can't track this product. Cuz the link you sent is not a amazon or flipkart product link.` ).catch(e => {}); + ctx.reply("I'm sorry, but you can't add more products as you've already reached the maximum limit.\n\nPlease delete atleast one product. And try again.\n\nTo get list send /list", + { reply_to_message_id: ctx.message.message_id }).catch(e => { }); } + } else { - ctx.reply( `Sorry ${ctx.message.chat.first_name}, I can't track this product. Make sure you've sent correct product link.` ).catch(e => {}); + ctx.reply(`Sorry, I can't track this product. Cuz the link you sent is not a amazon or flipkart product link.`).catch(e => { }); } - } catch(e){ - console.error(e) + } else { + ctx.reply(`Sorry ${ctx.message.chat.first_name}, I can't track this product. Make sure you've sent correct product link.`).catch(e => { }); } + } catch (e) { + console.error(e) + } } @@ -74,9 +80,13 @@ bot.command("start", (ctx) => { try { ctx.reply( `Hello ${ctx.message.chat.first_name}, I can track price for Amazon & Flipkart products (Soon more).\n\nCheck /help to get started.\n`, - { reply_to_message_id: ctx.message.message_id, reply_markup, } - ).catch(() => {}) - manageUsers( { id: ctx.message.from.id, name: ctx.message.from.first_name }, "update" ); + { + reply_to_message_id: ctx.message.message_id, + reply_markup, + } + ).catch(() => { }) + + manageUsers({ id: ctx.message.from.id, name: ctx.message.from.first_name }, "update"); } catch (e) { console.log("Error", e); } @@ -91,7 +101,7 @@ bot.command("help", (ctx) => { reply_to_message_id: ctx.message.message_id, reply_markup, } - ).catch(() => {}) + ).catch(() => { }) } catch (e) { } }); @@ -100,16 +110,18 @@ bot.command("track", async (ctx) => { const message = ctx.message.text.replace("/track ", ""); processUrl(message, ctx); }); - + bot.command("list", async (ctx) => { try { const products = await manageProducts({ 'users.userId': ctx.from.id }, "read"); + const list = products.result .map( (product) => `${product.title}\nLast Price: ${product.price}\nLink: ${product.merchant}\nTo stop send /stop_${product.users.filter(u => u.userId == ctx.from.id)[0].tracking_id}` ) .join("\n\n"); + ctx.reply(`Here is your tracking list:\n\n${list}`, { reply_to_message_id: ctx.message.message_id, parse_mode: "HTML", @@ -124,10 +136,12 @@ bot.command("list", async (ctx) => { bot.hears(/^\/stop_([a-z0-9])/, async (ctx) => { const tracking_id = ctx.message.text.replace("/stop_", ""); + const result = await manageProducts( { tracking_id, userId: ctx.from.id }, "delete" ); + ctx.reply( result.ok ? `Stopped tracking product with tracking id ${tracking_id}` @@ -139,7 +153,9 @@ bot.command("broadcast", async (ctx) => { if (ADMINS.includes(ctx.from.id)) { let msg = ctx.message.text.replace("/broadcast ", ""); const inline_keyboard = ctx.message.text.split("inline_keyboard:")[1]; + msg = msg.replace("inline_keyboard:", "").replace(inline_keyboard, ""); + const users = await manageUsers({}, "read"); await Promise.all( users.result.map(async (user) => { @@ -168,6 +184,7 @@ bot.command("broadcast", async (ctx) => { bot.command("users", async (ctx) => { if (ADMINS.includes(ctx.from.id)) { let users = await manageUsers({}, "read"); + users = "List Of Users: \n\n" + users.result @@ -176,27 +193,30 @@ bot.command("users", async (ctx) => { `${user.id} - ${user.name}` ) .join("\n"); + ctx.reply(users, { parse_mode: "HTML" }); } }); bot.command("stats", async (ctx) => { - try{ - const[users, products] = await Promise.all([manageUsers, manageProducts].map( + try { + const [users, products] = await Promise.all([manageUsers, manageProducts].map( async (func) => await func({}, "read") + )); let prodCount = 0; products.result.map(prod => prodCount += prod.users.length); + ctx.reply( `Total Users: ${users.result.length}\nTotal Products: ${prodCount}` ); - }catch(e){ + } catch (e) { console.log(e) } }); bot.on('::url', async ctx => { - if(ctx.chat.type === "private"){ + if (ctx.chat.type === "private") { const message = ctx.message.text; processUrl(message, ctx); } @@ -207,10 +227,12 @@ bot.callbackQuery("stopTracking", async (ctx) => { ctx.update?.callback_query?.message?.reply_markup?.inline_keyboard[1][0]?.text?.split( " - " )[1]; + const result = await manageProducts( { tracking_id, userId: ctx.from.id }, "delete" ); + ctx.api.editMessageText( ctx.update?.callback_query?.message?.chat?.id, ctx.update?.callback_query?.message?.message_id, @@ -224,16 +246,26 @@ const track = async () => { try { const products = await manageProducts({}, "read"); // Process 10 products at a time - for (let i = 0; i < products.result.length; i = i + 10 ) { - const temp = products.result.slice(i, i + 10) - + for (let i = 0; i < products.result.length; i = i + 10) { + const temp = products.result.slice(i, i + 10) + await Promise.all( temp.map(async (product) => { const details = await getProductDetails(product.link, product.merchant); if (details.ok && !isNaN(details.price) && details.price !== product.price) { try { - await manageProducts({ tracking_id: product.tracking_id, userId: product.userId, merchant: product.merchant, title: details.title, link: product.link, initPrice: product.price, price: details.price, users: product.users}, "update"); + await manageProducts({ + tracking_id: product.tracking_id, + userId: product.userId, + merchant: product.merchant, + title: details.title, + link: product.link, + initPrice: product.price, + price: details.price, + users: product.users + }, "update"); + await Promise.all(product.users.map(async user => { bot.api.sendMessage( user.userId, @@ -246,28 +278,28 @@ const track = async () => { parse_mode: "HTML", reply_markup: { inline_keyboard: details?.link ? [ - [{ text: "Buy Now", url: productCommonUrl(details.link, true) }], - [{ text: "Stop Tracking - " + user.tracking_id, callback_data: `stopTracking`, }]] - : [] + [{ text: "Buy Now", url: productCommonUrl(details.link, true) }], + [{ text: "Stop Tracking - " + user.tracking_id, callback_data: `stopTracking`, }]] + : [] } }).catch(e => console.log(`🚀 ~ file: bot.js:255 ~ temp.map ~ e:`, e)) })) // wait for 1 sec await new Promise(resolve => setTimeout(resolve, 1000)) - } catch (e) { + } catch (e) { console.log(`🚀 ~ file: bot.js:260 ~ temp.map ~ e:`, e) bot.start() // wait for 5 sec await new Promise(resolve => setTimeout(resolve, 5000)) - } + } } }) ); } } catch (e) { console.log(`🚀 ~ file: bot.js:270 ~ track ~ e:`, e) - } + } }; bot.command("update", async (ctx) => { @@ -279,10 +311,13 @@ bot.command("update", async (ctx) => { bot.catch((err) => { console.error("err"); + const ctx = err.ctx; console.error(`Error while handling update ${ctx.update.update_id}:`); + const e = err.error; console.error("Error: ", e.description); + bot.start(); }); From f4d2f995be547cd69390cdccc5a6f091eb914d7e Mon Sep 17 00:00:00 2001 From: siddiquiaffan Date: Sat, 7 Oct 2023 22:24:53 +0530 Subject: [PATCH 2/8] Add HTTPS Proxy URL --- config.js | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/config.js b/config.js index bead029..71503ef 100644 --- a/config.js +++ b/config.js @@ -11,11 +11,25 @@ if(!process.env.DB_URL) { process.exit(1); } -const ADMINS = process.env.ADMINS || '' -const BOT_TOKEN = process.env.BOT_TOKEN || '' -const DB_URL = process.env.DB_URL || '' -const WORKER_URL = process.env.WORKER_URL || '' -const API_KEY = process.env.API_KEY || '' // Generate any API Key and pass it when accessing the API. +/** List of amdins (tg IDs) separated by space */ +const ADMINS = process.env.ADMINS ?? '' + +/** Telegram bot token */ +const BOT_TOKEN = process.env.BOT_TOKEN ?? '' + +/** HTTPS Proxy URL */ +const HTTPS_PROXY = process.env.PROXY ?? '' + +/** MongoDB URL */ +const DB_URL = process.env.DB_URL ?? '' + +/** Cloudflare Worker URL */ +const WORKER_URL = process.env.WORKER_URL ?? '' + +/** API Key - A random secure key to access api */ +const API_KEY = process.env.API_KEY ?? '' // Generate any API Key and pass it when accessing the API. + +/** Maximum number of products can be added by a user at a time. */ const LIMIT = Number(process.env.LIMIT) // Maximum number of products can be added by a user at a time. - -export { ADMINS, BOT_TOKEN, DB_URL, WORKER_URL, API_KEY, LIMIT } \ No newline at end of file + +export { ADMINS, BOT_TOKEN, DB_URL, WORKER_URL, API_KEY, LIMIT, HTTPS_PROXY } \ No newline at end of file From e4af450c45502821f9cfb8d5cad30efcf06f0f70 Mon Sep 17 00:00:00 2001 From: siddiquiaffan Date: Sat, 7 Oct 2023 22:25:08 +0530 Subject: [PATCH 3/8] Install https-proxy-agent --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 2e3bdbc..4342899 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "dotenv": "^10.0.0", "express": "^4.17.1", "grammy": "^1.5.4", + "https-proxy-agent": "^7.0.2", "mongodb": "^4.9.0" } } From 9b9a282e3c9725371b0df44b17cc412def5b625b Mon Sep 17 00:00:00 2001 From: siddiquiaffan Date: Sat, 7 Oct 2023 22:25:50 +0530 Subject: [PATCH 4/8] Return URL as it is if it's already unshorted --- unshort.js | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/unshort.js b/unshort.js index ca65765..b6b163c 100644 --- a/unshort.js +++ b/unshort.js @@ -1,19 +1,48 @@ import axios from 'axios'; + +const merchants = [ + 'amazon', + 'flipkart', + 'snapdeal', + 'ajio', + 'myntra', + 'jabong', + 'bewakoof', + 'limeroad', + 'shein', +] + +/** + * Get the long url from a short url + * @param {string} url + * @returns + */ const unshort = async (url) => { const extractUrl = req => req?.request?.res?.responseUrl || req?.request?._redirectable?._currentUrl || req?.request?._currentUrl || req?.request?._options?.href || 'https://' + req?.request?.host + req?.request?.path; + + + const host = new URL(url).hostname.split("."); + const merchant = host[0] === 'www' ? host[1] : host[0]; + + if (merchants.includes(merchant)) + return url; + + let longUrl = url; + try { const req = await axios.get(url); const result = extractUrl(req); - var longUrl = result ? result : url; + longUrl = result ? result : url; } catch (err) { const result = extractUrl(err); - var longUrl = result ? result : url; + longUrl = result ? result : url; } return longUrl; } + export default unshort; \ No newline at end of file From 0542f40f302142273706b5a5401f802807d247e1 Mon Sep 17 00:00:00 2001 From: siddiquiaffan Date: Sat, 7 Oct 2023 22:26:15 +0530 Subject: [PATCH 5/8] Use proxy, update selectors --- utils.js | 139 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 98 insertions(+), 41 deletions(-) diff --git a/utils.js b/utils.js index ac3d53e..f377ebd 100644 --- a/utils.js +++ b/utils.js @@ -1,33 +1,51 @@ import * as cheerio from 'cheerio' import axios from 'axios' -import {WORKER_URL} from './config.js' +import { WORKER_URL, HTTPS_PROXY } from './config.js' +import { HttpsProxyAgent } from 'https-proxy-agent'; const urlRegex = /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:[/?#]\S*)?$/i; + +/** + * check if string is url or not + * @param {string} str + * @returns {boolean} + */ const isUrl = (str) => { // Return true if string is a valid URL - return urlRegex.test(str); + return urlRegex.test(str); }; -const getRandomId = () => [...Array(10)].map(i=>(~~(Math.random()*36)).toString(36)).join(''); // Return a random id +/** + * Generate random string id + * @returns {string} + */ +const getRandomId = () => [...Array(10)].map(i => (~~(Math.random() * 36)).toString(36)).join(''); + const selectors = { - amazon: { - title: '#productTitle', - price1: 'span.a-price.a-text-price.a-size-medium.apexPriceToPay > span:nth-child(2)', price2: 'span.a-price.aok-align-center.priceToPay > span.a-offscreen', - image1: '#landingImage' - }, - flipkart: { - title: '.B_NuCI', - price1: '._30jeq3._16Jk6d', - image1: '#container > div > div._2c7YLP.UtUXW0._6t1WkM._3HqJxg > div._1YokD2._2GoDe3 > div._1YokD2._3Mn1Gg.col-5-12._78xt5Y > div:nth-child(1) > div > div._3li7GG > div._1BweB8 > div._3kidJX > div.CXW8mj._3nMexc > img', - }, - snapdeal: { - title: '#productOverview > div.col-xs-14.right-card-zoom.reset-padding > div > div.pdp-fash-topcenter-inner.layout > div.row > div.col-xs-18 > h1', - price1: '#buyPriceBox > div.row.reset-margin > div.col-xs-14.reset-padding.padL8 > div.disp-table > div.pdp-e-i-PAY-r.disp-table-cell.lfloat > span.pdp-final-price > span', - image1: '#bx-slider-left-image-panel > li:nth-child(1) > img' - } + amazon: { + title: '#productTitle', + // price1: 'span.a-price.a-text-price.a-size-medium.apexPriceToPay > span:nth-child(2)', price2: 'span.a-price.aok-align-center.priceToPay > span.a-offscreen', + price1: '#tp_price_block_total_price_ww span', + image1: '#landingImage' + }, + flipkart: { + title: '.B_NuCI', + price1: '._30jeq3._16Jk6d', + image1: '#container > div > div._2c7YLP.UtUXW0._6t1WkM._3HqJxg > div._1YokD2._2GoDe3 > div._1YokD2._3Mn1Gg.col-5-12._78xt5Y > div:nth-child(1) > div > div._3li7GG > div._1BweB8 > div._3kidJX > div.CXW8mj._3nMexc > img', + }, + snapdeal: { + title: '#productOverview > div.col-xs-14.right-card-zoom.reset-padding > div > div.pdp-fash-topcenter-inner.layout > div.row > div.col-xs-18 > h1', + price1: '#buyPriceBox > div.row.reset-margin > div.col-xs-14.reset-padding.padL8 > div.disp-table > div.pdp-e-i-PAY-r.disp-table-cell.lfloat > span.pdp-final-price > span', + image1: '#bx-slider-left-image-panel > li:nth-child(1) > img' + } } +/** + * Get common url for the product + * @param {string} link + * @param {string} tag +*/ const productCommonUrl = (link, tag) => { const url = new URL(link?.replace("www.", "")); const merchant = url.hostname.split(".")[0]; @@ -41,7 +59,7 @@ const productCommonUrl = (link, tag) => { break; case "flipkart": id = url.searchParams.get("pid"); - commonUrl = id ? "https://www.flipkart.com/product/p/itme?pid=" + id : link.includes('/p/itm') ?link.split('?')[0] : link; + commonUrl = id ? "https://www.flipkart.com/product/p/itme?pid=" + id : link.includes('/p/itm') ? link.split('?')[0] : link; break; default: null; @@ -50,28 +68,67 @@ const productCommonUrl = (link, tag) => { return commonUrl; }; -const getProductDetails = async(url, merchant) => { - try{ - const commonUrl = productCommonUrl(url); - const res = await axios.get(`${WORKER_URL}/?url=${encodeURIComponent(commonUrl)}`, { - headers: { - "User-Agent": - "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36", - }, - }); - const $ = cheerio.load(res.data); - const selector = selectors[merchant]; - const price = parseFloat($(selector.price1).text().trim().replace(/^\D+|[^0-9.]/g, '')) || parseFloat($(selector.price2).text().trim().replace(/^\D+|[^0-9.]/g, '')); - const title = $(selector.title).text().trim(); - const image = $(selector.image1).attr('src'); - if(!title || !price) { - return {ok: false} - } - return {ok: true, title, price, image, link: commonUrl} - }catch(e){ - console.log(e); - return {ok: false} - } + +/** + * Make request to the url + * @param {string} url + * @param {object} options + */ +const makeRequest = async (url, { method = 'GET', useProxy }) => { + try { + + const options = { method, headers: { "User-Agent": "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" } }; + if (useProxy) options.httpsAgent = new HttpsProxyAgent(HTTPS_PROXY); + + if (HTTPS_PROXY && useProxy) + return await axios(url, options); + + // else if (WORKER_URL) { + // const url1 = new URL(WORKER_URL) + // url1.searchParams.set('url', url) + + // return await axios(url1.toString(), options); + // } + + else return await axios(url, options); + } catch (err) { + throw err; + } +} + +/** + * Get product details from the url + * @param {string} url + * @param {string} merchant + * @returns + */ +const getProductDetails = async (url, merchant) => { + try { + const commonUrl = productCommonUrl(url); + const res = await makeRequest(commonUrl, { useProxy: commonUrl.includes('amazon.') }); + + const $ = cheerio.load(res.data); + const selector = selectors[merchant]; + + const priceEl = $(selector.price1) || $(selector.price2); + if (!priceEl || !priceEl.text()?.trim()) + return { ok: false } + + const price = priceEl.text()?.split('.')[0]?.trim().replace(/^\D+|[^0-9.]/g, ''); + + // const price = parseFloat($(selector.price1).text().trim().replace(/^\D+|[^0-9.]/g, '')) || parseFloat($(selector.price2).text().trim().replace(/^\D+|[^0-9.]/g, '')); + + const title = $(selector.title).text().trim(); + const image = $(selector.image1).attr('src'); + + if (!title || !price) + return { ok: false } + + return { ok: true, title, price, image, link: commonUrl } + } catch (e) { + console.log(e); + return { ok: false } + } } export { isUrl, getRandomId, getProductDetails, productCommonUrl }; From 6049f09343a19128f9dee9bc4c0ea9adc81f8590 Mon Sep 17 00:00:00 2001 From: siddiquiaffan Date: Sat, 7 Oct 2023 23:06:39 +0530 Subject: [PATCH 6/8] Switch to webhook --- bot.js | 4 ++-- index.js | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/bot.js b/bot.js index c2a35bb..8ff7145 100644 --- a/bot.js +++ b/bot.js @@ -289,7 +289,7 @@ const track = async () => { await new Promise(resolve => setTimeout(resolve, 1000)) } catch (e) { console.log(`🚀 ~ file: bot.js:260 ~ temp.map ~ e:`, e) - bot.start() + // bot.start() // wait for 5 sec await new Promise(resolve => setTimeout(resolve, 5000)) } @@ -318,7 +318,7 @@ bot.catch((err) => { const e = err.error; console.error("Error: ", e.description); - bot.start(); + // bot.start(); }); setInterval(track, 3600000); //Track every hr. diff --git a/index.js b/index.js index 0c129dc..7490c34 100644 --- a/index.js +++ b/index.js @@ -3,6 +3,7 @@ import { manageProducts, manageUsers } from "./db.js" import {API_KEY} from './config.js' import express from 'express' import bot from './bot.js' +import { webhookCallback } from "grammy" //Globals const port = process.env.PORT || 3000; @@ -81,5 +82,21 @@ app.get('/info', async(req, res) => { res.send(JSON.stringify({error: 'Invalid API key'})) }) +// use bot webhook path +app.use('/bot', webhookCallback(bot, 'express')); + +// set bot webhook, use req.url as webhook path +app.get('/setup', async (req, res) => { + // get host name from req + try { + const host = req.hostname; + bot.api.setWebhook(`https://${host}/bot`); + res.send('ok'); + } catch (e) { + console.log(e); + res.send('error'); + }; +}) + app.listen(port, async () => console.log('listening to port ' + port)); -bot.start().then(() => console.log('Bot launched!')); \ No newline at end of file +// bot.start().then(() => console.log('Bot launched!')); \ No newline at end of file From 9abeeb319c2d14b108e09959532b56c14d014098 Mon Sep 17 00:00:00 2001 From: siddiquiaffan Date: Sat, 7 Oct 2023 23:14:26 +0530 Subject: [PATCH 7/8] Add setup docs --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index d6768c1..5383bc0 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ A Telegram bot that can track price of Amazon & flipkart products (more coming s ## Deploy +**NOTE** - We're now using https proxy for sending requests. So add your proxy url in env as `PROXY` + [![Deploy with Heroku](https://www.herokucdn.com/deploy/button.svg "Deploy with Heroku")](https://heroku.com/deploy?template=https://github.com/siddiquiaffan/price-tracker "Deploy with Heroku") [![Deploy on Railway](https://railway.app/button.svg "Deploy on Railway")](https://railway.app/new/template?template=https://github.com/siddiquiaffan/price-tracker&envs=ADMINS,BOT_TOKEN,DB_URL,WORKER_URL,API_KEY,LIMIT&ADMINSDesc=Telegarm+ids+of+admins+separated+by+space&BOT_TOKENDesc=Get+Your+Bot+Token+From+@BotFather.&DB_URLDesc=Create+A+Database+In+Mongodb+And+Get+URL.&WORKER_URLDesc=Paste+worker.js+code+in+Cloudfare+Worker+and+get+url.&API_KEYDesc=Any+secret+key+to+access+API&LIMITDesc=Limit+of+products+to+track+per+user. "Deploy on Railway") @@ -47,6 +49,14 @@ Deploy locally: --- +### POST-DEPLOYMENT +**Setup bot:** Get your deployment url and navigate to {YOUR_DEPLOYMENT_URL}/setup +``` +Example: https://price-tracker.herokuapp.com/setup +``` +=> Replace `https://price-tracker.herokuapp.com/` with your deployment url. + +--- ## Contributing - Fork this repo ![fork](https://img.shields.io/github/forks/siddiquiaffan/price-tracker?label=fork&logo=Github) From ae5939de447762885db018690fea3b3dfc1533aa Mon Sep 17 00:00:00 2001 From: siddiquiaffan Date: Sat, 7 Oct 2023 23:45:08 +0530 Subject: [PATCH 8/8] Use long polling in development mode --- index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 7490c34..a675612 100644 --- a/index.js +++ b/index.js @@ -99,4 +99,8 @@ app.get('/setup', async (req, res) => { }) app.listen(port, async () => console.log('listening to port ' + port)); -// bot.start().then(() => console.log('Bot launched!')); \ No newline at end of file + +// if NODE_ENV is development, start polling +if (process.env.NODE_ENV === 'development') { + bot.start(); +} \ No newline at end of file