Telegram Bot API - public download urls for files contain bot token - telegram-bot

I need to get public url for file with telegram bot API. The problem with getFile method that it returns url in following format: https://api.telegram.org/file/bot<token>/<file_path> meaning I can't really share it in public because it contains my bot token, sharing this url wouldn't be secure.
Is it possible to get public url for file id that does not have my bot token in it? What are the alternatives?

I have created the following solution as a Proof Of Concept. Please check:
https://gist.github.com/gilpanal/099ff5fc94366fbaabd5e2fbedc7c86f
The idea is that you access to the binary data of your file through an intermediate API where your token is safe.
/*** server.js ***/
/* TESTED WITH NODE VERSION 14+ */
const express = require('express')
const app = express()
const https = require('https')
const port = process.env.PORT || 3000
// Use an Environment Variable to Secure Token Value
const BOT_TOKEN = <BOT_SECRET_TOKEN>
// For better CORS: https://expressjs.com/en/resources/middleware/cors.html
app.use( (req, res, next) => {
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
next()
})
app.get('/', (req, res) => {
res.sendStatus(200)
})
// Inspired by: https://stackoverflow.com/a/21024737
app.get('/fileDownload', (req, res) => {
let uploadResponse = { ok: false, result: null, error: 404, description: 'Not Found' }
if (req._parsedUrl && req._parsedUrl.query) {
const tel_file_path = 'https://api.telegram.org/file/bot' + BOT_TOKEN + req._parsedUrl.query
https.get(tel_file_path, (response) => {
const data = []
response.on('data', (chunk) => {
data.push(chunk)
}).on('end', () => {
const buffer = Buffer.concat(data)
res.send(buffer)
})
})
} else {
res.sendStatus(uploadResponse)
}
})
app.listen(port)
/*** app.js ***/
const TEL_PATH = '/music/file_352.mp3'
const API_FILEDONWLOAD = 'http://localhost:3000/fileDownload?'
const load = () => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', API_FILEDONWLOAD + TEL_PATH, true)
xhr.responseType = 'arraybuffer'
xhr.send()
xhr.addEventListener('progress', (e) => {
console.log(`${e.type}: ${e.loaded} bytes transferred\n`)
})
xhr.addEventListener('load', (e) => {
const audioData = e.target.response || e.target.result
resolve(audioData)
})
xhr.addEventListener('error', () => {
reject(Error('Track ' + TEL_PATH + ' failed to load'))
})
})
}
load().then((audiData) => {
console.log(audiData)
}).catch((err) =>{
console.log(err)
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
BODY
<script src="app.js"></script>
</body>
</html>

Related

external api results not loading in node.js using https module

whats wrong with my code? its showing no results....although it kinda works when i use google.com as url but in other cases it shows no results*I haven't shared my api key here(appid=)
const express = require('express');
const app = express();
const http = require('http');
app.get("/", function(req, res) {
const url= 'https://api.openweathermap.org/data/2.5/weather?q=london&appid='
http.get(url, function(response){
console.log(response);
// response.on("data", function(data){
// const weatherData = JSON.parse(data);
// const temp = weatherData.main.temp;
// // const weatherDescription = weatherData.weather[0].description;
// res.send(temp)
// })
// res.send('server is sending');
})
})
app.listen(3000, function(req, res){
console.log('Server is alive')
})

Server-Side Deployment using Node.js not giving proper SVG

This is related to question I asked here. One of the solutions was to create a bitmap and I'm trying to do that by exposing a service which returns SVG string from nodejs. I followed doc given here. It's returning a response with SVG content but the svg content doesn't seem to be right.
NodeJS Code
const express = require('express');
const vega = require('vega');
const app = express();
app.get('/vega', (request, response) => {
const spec = JSON.parse(request.query.spec);
const view = new vega.View(vega.parse(spec), {
logLevel: vega.Warn,
renderer: 'none'
});
const svgResult = view.toSVG();
svgResult.then(function(res){
response
.set('Cache-Control', `public, max-age=${60 * 60}`)
.type('svg').send(res);
}).catch((err) => console.log("rejected:", err));
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Listening on ${PORT}`));
Sample call request
http://localhost:3000/vega?spec=%7B%0D%0A++%22description%22%3A+%22A+simple+bar+chart+with+embedded+data.%22%2C%0D%0A++%22data%22%3A+%7B%0D%0A++++%22values%22%3A+%5B%0D%0A++++++%7B%22a%22%3A+%22A%22%2C%22b%22%3A+28%7D%2C+%7B%22a%22%3A+%22B%22%2C%22b%22%3A+55%7D%2C+%7B%22a%22%3A+%22C%22%2C%22b%22%3A+43%7D%2C%0D%0A++++++%7B%22a%22%3A+%22D%22%2C%22b%22%3A+91%7D%2C+%7B%22a%22%3A+%22E%22%2C%22b%22%3A+81%7D%2C+%7B%22a%22%3A+%22F%22%2C%22b%22%3A+53%7D%2C%0D%0A++++++%7B%22a%22%3A+%22G%22%2C%22b%22%3A+19%7D%2C+%7B%22a%22%3A+%22H%22%2C%22b%22%3A+87%7D%2C+%7B%22a%22%3A+%22I%22%2C%22b%22%3A+52%7D%0D%0A++++%5D%0D%0A++%7D%2C%0D%0A++%22mark%22%3A+%22bar%22%2C%0D%0A++%22encoding%22%3A+%7B%0D%0A++++%22x%22%3A+%7B%22field%22%3A+%22a%22%2C+%22type%22%3A+%22ordinal%22%7D%2C%0D%0A++++%22y%22%3A+%7B%22field%22%3A+%22b%22%2C+%22type%22%3A+%22quantitative%22%7D%0D%0A++%7D%0D%0A%7D
Sample response
<svg class="marks" width="0" height="0" viewBox="0 0 0 0" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g transform="translate(0,0)"><g class="mark-group role-frame root"><g transform="translate(0,0)"><path class="background" d="M0,0h0v0h0Z" style="fill: none;"></path><g></g></g></g></g></svg>
Appreciate any help find what's going wrong here.
Got it working with a few fixes in the above code.
const express = require('express');
const vega = require('vega');
const app = express();
app.get('/vega', (request, response) => {
const spec = JSON.parse(request.query.spec);
getSVG(spec, response);
// let res = render(spec, response);
// console.log('response', res);
});
async function getSVG(spec, response) {
const view = new vega.View(vega.parse(spec), {
loader: vega.loader(),
logLevel: vega.Warn,
renderer: 'none'
})
.initialize()
.finalize();
return (view.toSVG(1))
.then(_ => {
//console.log(_);
console.log("Processed SVG request at -", Date.now());
response
.set('Cache-Control', `public, max-age=${60 * 60}`)
.type('svg').send(_);
});
}
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Listening on ${PORT}`));

Is it ok to add routes in an Express middleware?

I am building a small authentication middleware (because I want to!) but to work the way I wanted I found I was adding routes dynamically to the app, both for the POST back of the username/password as well as the GET for the authentication page script and styles.
Here it is:
function appAuth(auth, options) {
let oneHourMs = (60 * 60 * 1000);
let sessionStore = {};
let html = `<html>
<head>
<link rel="stylesheet" href="style.css" type="text/css">
<script src="index.js" type="module"></script>
</head>
<body>
</body>
</html>`;
return function (request, response, next) {
if (!request.app.authMiddlewarePOST_setup) {
request.app.post(request.path, upload.array(), async function (req, res) {
let data = req.body;
console.log("data", data);
let { username, password } = data;
if (auth(username, password)) {
let now = new Date();
let sessionId = await makeSessionId(now, getRemoteAddr(req));
sessionStore[sessionId] = {
lastTouch: now,
id: sessionId
};
res.cookie("sessionid", sessionId);
res.redirect(302, req,path);
}
else {
res.status(401).send(html);
}
});
request.app.authMiddlewarePOST_setup = true;
}
// Do authenticated session detection
let sessionId = request.cookies.sessionid;
if (sessionId === undefined) {
response.status(401).send(html);
return;
}
let sessionObject = sessionStore[sessionId];
if (sessionObject === undefined
|| isExpired(sessionObject.lastTouch, oneHourMs)) {
response.status(401).send(html);
return;
}
// Otherwise it's all ok.
next();
};
}
I was wondering:
is it ok to add routes like this?
is it better to add a route with an obfuscated path? for example:
app.post("/" + middlewareId + "/" + randomnumber, ...)
if I'm doing this I suppose I should dispose of the route as well?
what would be some alternatives to doing this?
The git repo is over here - I don't want to clutter up the post with even more superflous code.

Always send error page after next function

I'm in express 4.16.3.
At first, this code works fine:
const express = require('express')
const router = express.Router()
let app = express()
router.use((req, res, next) => {
console.log('hi, express')
next()
})
app.use(router)
app.all('*', (req, res) => {
res.send("hello, world")
})
app.listen(8075, function () {
console.log('listening localhost:8072')
})
But when I try to set a param in next():
const express = require('express')
const router = express.Router()
let app = express()
router.use((req, res, next) => {
next('hello, express') ----------------mark
})
app.use(router)
app.all('*', (msg, req, res) => {
console.log(msg)
res.send(msg)
})
app.listen(8075, function () {
console.log('listening localhost:8072')
})
the response is always an error page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>hello, express</pre>
</body>
</html>
I just add a param in next function, but it seems broken express router.
What is the right way to use next() with params?
Isn't it a better practice to attach your required data with req object before calling next() ?
router.use((req, res, next) => {
req.data = { title: 'your sample data' };
next();
});
app.all('*', (req, res) => {
console.log(req.data);
});
This will attach your required data with the request object and pass the control to the next processing pipeline(app.all() handler in your code).
Then you can use that object in all of the available routes.
I don't know where in the Express docs this is stated, but what you're calling when you invoke next isn't another middleware function directly, rather telling the Express framework to call the next middleware function. A middleware function has fixed arguments passed to it, so you will only have access to the request, the response, and a function that may call the next middleware function in the chain. The only parameters this function takes is optionally the string 'route'.
In order to pass data to the next middleware function down the line your best bet is to modify the request object or the response object.
See Using Express middleware on the Express website.

How can I use the API of BigQuery in javascript?

Is it possible in javascript to get or insert data of BigQuery by Using API?
It does not working. (refer to the site https://developers.google.com/api-client-library/javascript/samples/samples)
<html>
<head>
<script src="https://apis.google.com/js/api.js"></script>
<script>
function start() {
gapi.client.init({
'apiKey': 'mykey',
}).then(function() {
return gapi.client.request({
'path' : 'https://www.googleapis.com/bigquery/v2/projects/projectId/queries/jobId',
'method' : 'GET'
'params' : {'projectId':'myid', 'jobId':'myid'}
});
}).then(function(response) {
console.log(response.result);
}, function(reason) {
console.log('Error: ' + reason.result.error.message);
});
};
gapi.load('client', start);
</script>
</head>
<body>
<div id="results"></div>
</body>
</html>
// Import the Google Cloud client library
const {BigQuery} = require('#google-cloud/bigquery');
async function queryStackOverflow() {
// Queries a public Stack Overflow dataset.
// Create a client
const bigqueryClient = new BigQuery();
// The SQL query to run
const sqlQuery = `SELECT repo.name FROM githubarchive.year.2019
where repo.name LIKE '%googlemaps%'
or repo.name LIKE '%google-maps%'
or repo.name LIKE '%google-maps-api%'
or repo.name LIKE '%googlemapsapi%'
Group by
repo.name`;
const options = {
query: sqlQuery,
};
// Run the query
const [rows] = await bigqueryClient.query(options);
console.log(rows);
}
queryStackOverflow();