How to send image using Discord.MessageAttachment - javascript

I'm retrieving image data from the google maps API and trying to send it as an image through 'Discord.MessageAttachment', however it is throwing the error:
TypeError: Discord.MessageAttachment is not a constructor
at C:\Users\dario\OneDrive\dev\JavaScript\DscBot\src\index.js:35:30
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
Here is the releveant code
const latitude = Math.random() * 180 - 90;
const longitude = Math.random() * 360 - 180;
const apiUrl = `https://maps.googleapis.com/maps/api/streetview?size=400x400&location=${latitude},${longitude}&key=*MyAPIKey`;
axios
.get(apiUrl, { responseType: 'arraybuffer' })
.then(response => {
const attachment = new Discord.MessageAttachment(response.data, 'image.jpg');
message.channel.send(attachment);
})
.catch(error => {
console.error(error);
message.channel.send('Failed to get a street view image.');
});
Note that I am on the latest version of Discord.js, and this 'Discord is imported (I think) correctly:
const Discord = require('discord.js');
I expected an image to be sent to the server which I am testing it on, however 'Failed to get a street view image.' was returned alongside a terminal error.

In the newest version of Discord.js "MessageAttachment" was renamed to "AttachmentBuilder". (More Info in the documentation)
So your code would have to look like this:
const latitude = Math.random() * 180 - 90;
const longitude = Math.random() * 360 - 180;
const apiUrl = `https://maps.googleapis.com/maps/api/streetview?size=400x400&location=${latitude},${longitude}&key=*MyAPIKey`;
axios
.get(apiUrl, { responseType: 'arraybuffer' })
.then(response => {
const attachment = new Discord.AttachmentBuilder(response.data, { name: 'image.jpg' });
message.channel.send(attachment);
})
.catch(error => {
console.error(error);
message.channel.send('Failed to get a street view image.');
});

Related

react firebase image post 400 error on uploading

I am trying to upload an image to a cloud storage and received an post 400 error
The file is in initialize in another component.
Thanks for help
const projectStorage = getStorage();
useEffect(() => {
const storageRef = ref(projectStorage, file.name);
uploadBytes(storageRef, file).then((snap) => {
let percentage = (snap.bytesTransferred / snap.totalBytes) * 100;
setProgress(percentage);
console.log('File Uploaded');
}, (err) => {
setError(err);
}, async () => {
//this url doesnt change the setstate url becuase it is in seperate score
const url = await storageRef.getDownloadURL();
setUrl(url);
})
}, [file]);
I created a new project on firebase and then change the permissions on the storage rules and its works.

Cannot get Mt.Everest RGB Tile Data from Mapbox (Not Found)

I have been looking to get back working on a JS Everest Flight Sim. Originally I had tried to create my own elevation mesh and tiles using DEM elevation data and mapping it to vertices Z axis.
I decided using Mapbox RGB tiles for elevation data would be a better approach. Unfortunately I can't seem to get it to work. The Omaha Nebraska doc example works but now the Mt. Everest tile.
I've brought the issue up here as well: https://github.com/mapbox/sphericalmercator/issues/43
Perhaps someone from Mapbox can offer me some insights :)
import fs from "fs";
import dotenv from "dotenv";
import fetch from "node-fetch";
import SphericalMercator from "#mapbox/sphericalmercator";
dotenv.config();
const queryMapbox = async () => {
const merc = new SphericalMercator({
size: 256,
});
const xyFromLatLong = (lat, long, merc) => {
return merc.forward([long, lat]);
};
const zoom = 14;
const long = 86.922623;
const lat = 27.986065;
const xyPos = xyFromLatLong(lat, long, merc);
console.log({ xyPos });
try {
// Example from Docs - Omaha, Nebraska
// const response = await fetch(
// `https://api.mapbox.com/v4/mapbox.terrain-rgb/14/12558/6127.pngraw?access_token=${process.env.ACCESS_TOKEN}`
// );
// const filename = "omaha-rgb.png"
const response = await fetch(
`https://api.mapbox.com/v4/mapbox.terrain-rgb/${zoom}/${xyPos[0].toFixed(0)}/${xyPos[1].toFixed(0)}.pngraw?access_token=${process.env.ACCESS_TOKEN}`
);
const filename = "everest-rgb.png"
await new Promise((resolve, reject) => {
const fileStream = fs.createWriteStream(`./data/${filename}`);
response.body.pipe(fileStream);
response.body.on("error", (err) => {
reject(err);
});
fileStream.on("finish", function () {
resolve();
});
});
console.log({ response });
// console.log({ res });
} catch (err) {
console.error(err);
}
};
queryMapbox(); // Test
I think you are using the wrong library to convert lon, lat to tile x, y. The documentation mentions some libraries, including this one:
tilebelt: a set of JavaScript utilities for requesting and working with tiles.
Example:
const tilebelt = require("#mapbox/tilebelt");
console.log(tilebelt.pointToTile(86.922623, 27.986065, 14));
// Output:
// [ 12147, 6864, 14 ]
With those x and y the URL will be something like this:
https://api.mapbox.com/v4/mapbox.terrain-rgb/14/12147/6864.pngraw?access_token=YOUR_MAPBOX_ACCESS_TOKEN

Telegram bot with telegraf.js : can't send random photo to chat using flickr api

I am a newbie in telegram bots creation and want to make a simple bot which allows a user to choose between a singer or actor photo in the commands and then using the flickr API send it to the chat:
const Telegraf = require('telegraf')
const { Router, Markup } = Telegraf
const axios = require('axios')
const api_key = '123'
const telegram = new Telegraf('123')
const inlineMessageRatingKeyboard = Markup.inlineKeyboard([
Markup.callbackButton('Singer', 'singer'),
Markup.callbackButton('Actor', 'actor')
]).extra()
const getSingerPhoto = () => {
axios.get(`https://www.flickr.com/services/rest/?method=flickr.photos.search&api_key=${api_key}&tags=gerard+way&format=json&nojsoncallback=1`)
.then(photosInfo => {
const photosArray = (photosInfo.data && photosInfo.data.photos && photosInfo.data.photos.photo) || null;
const photoObject = (photosArray && photosArray[photosArray.length * Math.random() | 0]) || null;
let { server, id, secret } = photoObject;
telegram.action('singer', (ctx) => {
ctx.replyWithPhoto({
url: `https://live.staticflickr.com/${server}/${id}_${secret}_q.jpg`
})
})
})
.catch(error => console.log(error));
}
telegram.on('message', (ctx) => ctx.telegram.sendMessage(
ctx.from.id,
'What kind of photo do you want?',
inlineMessageRatingKeyboard
)
)
telegram.command('singer', getSingerPhoto());
telegram.action('actor', (ctx) => {
ctx.replyWithPhoto({
source: './way.png'
})
})
telegram.startPolling()
Flickr API is okay - I get the photo array (photosArray) and then take a random photo object (photoObject) from it, then I put it to the necessary photo URL (https://live.staticflickr.com/${server}/${id}_${secret}_q.jpg) and it generates okay too.
The problem is that it's always exactly the same photo, I have to always restart the bot to generate a new photo URL. What am I doing wrong, how to avoid it and send a random photo every time a user calls the command singer? Any help will be appreciated.
As i see in your code you executing getSingerPhoto only once
telegram.command('singer', getSingerPhoto());
just change it to
telegram.command('singer', getSingerPhoto);
edit:
i'm not familiar with telegraf api, but i also see that you registering action inside a response of axios, so that's why photo being cached
telegram.action('singer', (ctx) => {
ctx.replyWithPhoto({
url: `https://live.staticflickr.com/${server}/${id}_${secret}_q.jpg`
})
})
so, instead add ctx param in getSingerPhoto(ctx) that you will get from command/action, just call it inside and remove another action that you have inside
edit2:
completed code:
const getSingerPhoto = (ctx) => {
axios.get(`https://www.flickr.com/services/rest/?method=flickr.photos.search&api_key=${api_key}&tags=gerard+way&format=json&nojsoncallback=1`)
.then(photosInfo => {
const photosArray = (photosInfo.data && photosInfo.data.photos && photosInfo.data.photos.photo) || null;
const photoObject = (photosArray && photosArray[photosArray.length * Math.random() | 0]) || null;
let { server, id, secret } = photoObject;
ctx.replyWithPhoto({
url: `https://live.staticflickr.com/${server}/${id}_${secret}_q.jpg`
})
})
.catch(error => console.log(error));
}
telegram.action('singer', getSingerPhoto);

My Discord bot sends messages in a weird way

I'm currently working on a Discord bot that tracks Steam prices and sends them to chat. I made this code for it:
setInterval(() => {
const currentDate = new Date();
var yourchannel = client.channels.cache.get('[CHANNEL ID]');
fetch('https://steamcommunity.com/market/priceoverview/?appid=730&market_hash_name=Operation%20Breakout%20Weapon%20Case&currency=6', )
.then(res => res.text())
.then(text => yourchannel.send(`Breakout case price on ${currentDate.toLocaleDateString(`pl-PL`)} is ${text}`))
}, 1000 * 60 * 60 * 24);
});
I want my bot to send message "Breakout case price on [date] is [price]." For example "Breakout case price on 10.02.2021 is 5.94zł", but instead it sends this:
Breakout case price on 10.02.2021 is {"success":true,"lowest_price":"5,92zł","volume":"13,807","median_price":"6,01zł"}
It's because you send the whole object returned from fetch. You only need to send a property of that object (like json.lowest_price). You'll also need to make sure that you parse the body text as JSON. You'll need to use res.json() instead of res.text().
if (message.content === 'lowest_price') {
fetch(
'https://steamcommunity.com/market/priceoverview/?appid=730&market_hash_name=Operation%20Breakout%20Weapon%20Case&currency=6',
)
.then((res) => res.json())
.then((json) =>
message.channel.send(
`Breakout case price on ${new Date().toLocaleDateString('pl-PL')} is ${
json.lowest_price
}`,
),
)
.catch((error) => {
console.log(error);
message.channel.send('Oops, there was an error fetching the price');
});
}
Check out the basics of objects on MDN.

Receiving 2 responses from Mapbox API using express GET request

I have a very basic app that takes a UK Postcode as a URL parameter and returns the longitude and latitude via the Mapbox API.
It seems I am receiving 2 responses: The first response is returned successfully and displayed on screen, then the second response is caught by my catch block with the following error Error: TypeError: Cannot read property 'geometry' of undefined I understand the error but don't understand that why the app executes successfully (returns lng and lat to user) then shows an error?
./server.js
require('dotenv').config()
const express = require('express');
const server = express();
const MapApi = require('./datasources/map')
const Map = new MapApi;
server.get('/:postcode', async (req,res) => {
const { postcode } = req.params
const [lng, lat] = await Map.getLngLat( postcode )
res.send(`Longitude: ${lng}, Latitude: ${lat}`)
})
const { PORT_NUMBER } = process.env
server.listen(PORT_NUMBER, () => console.log('Listening on port ', PORT_NUMBER))
./datasources/map.js
require('dotenv').config()
const axios = require('axios');
class MapApi {
constructor(){
this.baseURL = (search_term) => {
return `https://api.mapbox.com/geocoding/v5/mapbox.places/${search_term}.json?access_token=${process.env.MAPBOX_ACCESS_TOKEN}`
}
}
// Get Lng, Lat from Postocde
async getLngLat (search_term) {
return axios.get( this.baseURL(search_term) )
.then(response => {
return typeof response.data === "object"
? response.data.features[0].geometry.coordinates
: [0,0]
})
.catch(err => {
console.error('Error: ', err)
})
}
}
module.exports = MapApi
If i include the following line console.log(`Time ${Date.now()} - Type ${typeof response}`) in the then block of the axios request
I get the following console output >
Time 1575388974209 - Type object
Time 1575388975073 - Type object
Error: TypeError: Cannot read property 'geometry' of undefined

Categories

Resources