Whenever streamedItem.eventName === "INSERT" for my table, I would like to POST streamedItem.dynamodb.NewImage (I think) to Zapier, so I can automate social media posting.
Below is my current file, and I am getting the error on Cloudwatch of ERROR connect ECONNREFUSED 127.0.0.1:3000.
/* Amplify Params - DO NOT EDIT
ENV
REGION
ZAPIER_URL
Amplify Params - DO NOT EDIT */
/**
* #type {import('#types/aws-lambda').APIGatewayProxyHandler}
*/
const http = require("http"); // or https
const defaultOptions = {
host: "localhost",
port: 3000, // or 443 for https
headers: {
"Content-Type": "application/json",
},
};
const post = (path, payload) =>
new Promise((resolve, reject) => {
const options = { ...defaultOptions, path, method: "POST" };
console.log("OPTIONS", options);
const req = http.request(options, (res) => {
let buffer = "";
res.on("data", (chunk) => (buffer += chunk));
console.log("buffer", buffer);
res.on("end", () => resolve(JSON.parse(buffer)));
});
req.on("error", (e) => reject(e.message));
req.write(JSON.stringify(payload));
req.end();
});
const zapierURL = "https://hooks.zapier.com/hooks/catch/xxxxxx/bljks0k/";
exports.handler = async (event, context) => {
for (const streamedItem of event.Records) {
if (streamedItem.eventName === "INSERT") {
console.log(
"streamedItem.dynamodb.NewImage",
streamedItem.dynamodb.NewImage
);
try {
await post(zapierURL, streamedItem.dynamodb.NewImage);
} catch (err) {
console.log("ERROR", err);
}
}
}
};
I would like the environment variables setup in a way that I can use localhost, the development server, or the production website.
I am using AWS Amplify, Next.js, and Javascript.
Related
I'm trying to call Redis from a Twilio Function (serverless) and I don't see incoming connections in my Redis log.
Is this setup viable?
Sample code follows:
const Redis = require('ioredis');
const fs = require('fs');
exports.handler = function (context, event, callback) {
const config = Runtime.getAssets()['config.json'].open();
let redisClientConfig = JSON.parse(config).redisConfig;
let contactCacheTime = JSON.parse(config).contactCacheTime;
if (!redisClientConfig) {
throw new Error('Redis config not set.');
}
const redisClient = new Redis(redisClientConfig);
redisClient.on('error', (err) => {
console.error(`Cannot connect to redis, reason: ${(err.message || err)}`);
});
redisClient.getex('mhn-twilio-bot-contact:'.concat(event.contactKey), 'EX', contactCacheTime)
.then((res) => {
if (!res) {
redisClient.setex('mhn-twilio-bot-contact:'.concat(event.contactKey), contactCacheTime, '<CACHED-VALUE>');
}
callback(null, { cached: res ? true : false });
})
.catch((err) => {
callback(null, { cached: false });
});
};
Hello so am trying to use undici with a proxy but it doesn't work i tired this
const client = new Client({
url: 'www.google.com',
proxy: 'http://user:pass#host:port'
})
as well as this
const { HttpsProxyAgent } = require("https-proxy-agent");
const proxy = new HttpsProxyAgent("http://user:pass#host:port");
time = new Date()
client.request({
path: '/',
method: 'GET',
httpsAgent: proxy
},
but nothing seems to work
See this link here:
https://github.com/nodejs/undici/blob/01302e6d2b2629cca4ad9327abe0f7a317f8399f/docs/best-practices/proxy.md#connect-with-authentication
import { Client } from 'undici'
import { createServer } from 'http'
import proxy from 'proxy'
const server = await buildServer()
const proxy = await buildProxy()
const serverUrl = `http://localhost:${server.address().port}`
const proxyUrl = `http://localhost:${proxy.address().port}`
proxy.authenticate = function (req, fn) {
fn(null, req.headers['proxy-authorization'] === `Basic ${Buffer.from('user:pass').toString('base64')}`)
}
server.on('request', (req, res) => {
console.log(req.url) // '/hello?foo=bar'
res.setHeader('content-type', 'application/json')
res.end(JSON.stringify({ hello: 'world' }))
})
const client = new Client(proxyUrl)
const response = await client.request({
method: 'GET',
path: serverUrl + '/hello?foo=bar',
headers: {
'proxy-authorization': `Basic ${Buffer.from('user:pass').toString('base64')}`
}
})
response.body.setEncoding('utf8')
let data = ''
for await (const chunk of response.body) {
data += chunk
}
console.log(response.statusCode) // 200
console.log(JSON.parse(data)) // { hello: 'world' }
server.close()
proxy.close()
client.close()
function buildServer () {
return new Promise((resolve, reject) => {
const server = createServer()
server.listen(0, () => resolve(server))
})
}
function buildProxy () {
return new Promise((resolve, reject) => {
const server = proxy(createServer())
server.listen(0, () => resolve(server))
})
}
I'm trying to get my bot to "dynamically" get the name of a command.
title is defined in module.exports as the name of the command that will show up in the Embed; however in 1 specific command where I get a joke from an API, this.title returns as Undefined instead of the command's name.
It only happens in this command.
I've tried using just title however that just returns "node".
What did I do wrong?
Code:
const Discord = require("discord.js");
const { title } = require("process");
const config = require("../data.json");
module.exports = {
name: "dadjoke",
title: "Dad Joke",
description: "A (not so) very funny dadjoke.",
execute(client, message, args) {
const https = require('https');
const url = "icanhazdadjoke.com";
var options = {
host: url,
port: 443,
path: "/",
headers: {"Accept":"application/json", "User-Agent":"crazyBot (https://github.com/acrazytown/crazybot)"}
}
function getData(options) {
https.get(options, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
const embed = new Discord.MessageEmbed()
.setColor(config.crazyBot.settings.accent_color)
.setAuthor("crazyBot", config.crazyBot.settings.icon_url)
.setTitle(this.title)
.setDescription(JSON.parse(data).joke)
.setFooter(`Powered by ${url}`);
message.channel.send(embed);
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
}
getData(options)
}
}
Because the function getData() doesn't have an object reference, the value of this within the function is undefined whereas the value of this within execute() is defined as the object being exported. One simple solution to this is to use Function.bind() to set the this keyword of getData() to the object reference.
This is how that would look in your execute() function:
execute(client, message, args) {
const https = require('https');
const url = "icanhazdadjoke.com";
var options = {
host: url,
port: 443,
path: "/",
headers: {"Accept":"application/json", "User-Agent":"crazyBot (https://github.com/acrazytown/crazybot)"}
}
var getData = function(options) {
https.get(options, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
const embed = new Discord.MessageEmbed()
.setColor(config.crazyBot.settings.accent_color)
.setAuthor("crazyBot", config.crazyBot.settings.icon_url)
.setTitle(this.title)
.setDescription(JSON.parse(data).joke)
.setFooter(`Powered by ${url}`);
message.channel.send(embed);
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
}.bind(this);
getData(options)
}
Relevant resources:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
I am currently working with azure functions in javascript. In my function, I am first getting a specific element from my CosmoDB (this is the async/await part). I get a result and then I want to do an https POST request. However, my problem is, that it never finished the HTTPs request and I don't really know why. What am I doing wrong?
(As you can see I tried 2 different ways of doing the request, once with the standard https function and the commented out the part with npm request package. However, both ways won't work).
Here is my code:
const CosmosClient = require('#azure/cosmos').CosmosClient;
var https = require('https');
var http = require('http');
var request = require('request');
const endpoint = "someEndpoint";
const masterKey = "anymasterkey";
const database = {
"id": "Database"
};
const container = {
"id": "Container1"
};
const databaseId = database.id;
const containerId = container.id;
const client = new CosmosClient({
endpoint: endpoint,
auth: {
masterKey: masterKey
}
});
module.exports = function (context, req) {
const country = "de";
const bban = 12345678;
const querySpec = {
query: "SELECT * FROM Container1 f WHERE f.country = #country AND f.bban = #bban",
parameters: [{
name: "#country",
value: country
},
{
name: "#bban",
value: bban
}
]
};
getContainers(querySpec).then((results) => {
const result = results[0];
context.log('here before request');
var options = {
host: 'example.com',
port: '80',
path: '/test',
method: 'POST'
};
// Set up the request
var req = http.request(options, (res) => {
var body = "";
context.log('request');
res.on("data", (chunk) => {
body += chunk;
});
res.on("end", () => {
context.res = body;
context.done();
});
}).on("error", (error) => {
context.log('error');
context.res = {
status: 500,
body: error
};
context.done();
});
req.end();
// request({
// baseUrl: 'someURL',
// port: 443,
// uri: 'someuri',
// method: 'POST',
// headers: {
// 'Content-Type': 'text/xml;charset=UTF-8',
// 'SOAPAction': 'someaction'
// },
// function (error, response, body) {
// context.log('inside request')
// if (error) {
// context.log('error', error);
// } else {
// context.log('response');
// }
// }
// })
})
};
async function getContainers(querySpec) {
const {container, database} = await init();
return new Promise(async (resolve, reject) => {
const {
result: results
} = await container.items.query(querySpec).toArray();
resolve(results);
})
}
async function init() {
const {
database
} = await client.databases.createIfNotExists({
id: databaseId
});
const {
container
} = await database.containers.createIfNotExists({
id: containerId
});
return {
database,
container
};
}
The last thing that happens is the print of "here before request". After that the function just does nothing until it timesout. So what am I doing wrong? Can't I just this combination of await/async and requests?
As commented you are not sending any data to the POST call. You need to have a req.write before the req.end
req.write(data);
req.end();
That is why the POST call is failing for you. After this fix, it should work
I tried to save the audio file from client and sent it to dialogflow for detection. But I couldn't get any error message. SessionClient works fine if I move out of req.pipe(). The request is a wav file.
router.post('/upload', function (req, res, next) {
var timeCode = new Date();
const filename = 'public/voiceFiles/' + timeCode.getTime() + '.wav';
req.pipe(fs.createWriteStream(filename))
.on('error', (e) => res.status(500).end(e.message))
.on('close', () => {
const readFile = util.promisify(fs.readFile);
readFile(filename)
.then(inputAudio => {
// The audio query request
const request = {
session: sessionPath,
queryInput: {
audioConfig: {
audioEncoding: encoding,
sampleRateHertz: sampleRateHertz,
languageCode: languageCode,
},
},
inputAudio: inputAudio,
};
// Recognizes the speech in the audio and detects its intent.
return sessionClient.detectIntent(request);
})
.then(responses => {
console.log('Detected intent:');
res.end(JSON.stringify(responses));
})
.catch(err => {
console.error('ERROR:', err);
res.end(err)
});
// [END dialogflow_detect_intent_audio]
})
});