How to publish sns to a specific endpoint? - node.js

I have a issue with publishing sns to a specific endpoint.
My code:
var AWS = require('aws-sdk');
AWS.config.loadFromPath('/web/config.json');
var sns = new AWS.SNS();
sns.publish({
// TopicArn:'arn:aws:sns:us-west-2:302467918846:MyTestTopik',
TargetArn: 'arn:aws:sns:us-west-2:302467918846:MyTestTopik:613ee49c-d4dc-4354-a7e6-c1d9d8277c56',
Message: "Success!!! ",
Subject: "TestSNS"
}, function(err, data) {
if (err) {
console.log("Error sending a message " + err);
} else {
console.log("Sent message: " + data.MessageId);
}
});
When I use TopicArn, everything is fine. But when I try to send notification to a specific endpoint I take error:
Error sending a message InvalidParameter: Invalid parameter: Topic Name
And I have no idea what kind of parameters it is and from where.

Something similar is working fine for me.
I'm able to publish to a specific endpoint using: Apple Push Notification Service Sandbox (APNS_SANDBOX)
You might also want to try and update the aws-sdk, current version is 1.9.0.
Here's my code, TargetArn was copied directly from the SNS console. I omitted some of the data, like &
var sns = new AWS.SNS();
var params = {
TargetArn:'arn:aws:sns:us-west-2:302467918846:endpoint/APNS_SANDBOX/<APP_NAME>/<USER_TOKEN>'
Message:'Success!!! ',
Subject: 'TestSNS'
};
sns.publish(params, function(err,data){
if (err) {
console.log('Error sending a message', err);
} else {
console.log('Sent message:', data.MessageId);
}
});

You might have an invalid Region. Check you Region for the Topic and set it accordingly. For example if you are us-west-2 you could do something like
var sns = new aws.SNS({region:'us-west-2'});

None of this will work if you don't massage the payload a bit.
var arn = 'ENDPOINT_ARN';
console.log("endpoint arn: " + arn);
var payload = {
default: message_object.message,
GCM: {
data: {
message: message_object.message
}
}
};
// The key to the whole thing is this
//
payload.GCM = JSON.stringify(payload.GCM);
payload = JSON.stringify(payload);
// Create the params structure
//
var params= {
TargetArn: arn,
Message: payload,
MessageStructure: 'json' // Super important too
};
sns.publish(params , function(error, data) {
if (error) {
console.log("ERROR: " + error.stack);
}
else {
console.log("data: " + JSON.stringify(data));
}
context.done(null, data);
});
So, it turns out that you have to specify the message structure (being json). I tried to publish to endpoint from the AWS console and it worked great as long as I selected JSON. Using RAW would do nothing.
In my script was doing was the previous posts were doing:
var params = {
TargetArn: arn,
Message:'Success!!! ',
Subject: 'TestSNS'
};
And even though CloudWatch was logging success, I never once got the message.
As soon as I added the MessageStructure data and that I properly formatted the payload, it worked like a charm.
The [default] parameter is not useful but I left it in there to show what the structure could look like.
If you don't stringify the payload.GCM part, SNS will barf and say that your message should include a "GCM" element.
The only thing that is annoying is that you are required to know what the endpoint is. I was hoping that you didn't have to format the message based on the endpoint, which really defeats the purpose of SNS in some ways.

Are you trying endpoints other that push notifications such as sms? Direct addressing is currently only available for push notifications endpoints. That is the error you will get when you try to publish to a specific endpoint that does not allow direct direct addressing!
http://aws.amazon.com/sns/faqs/#Does_SNS_support_direct_addressing_for_SMS_or_Email

I was having the exact same issue as you. The problem is the TargetArn that you're using, there's not clear documentation about it. Error happens if you try to put the Application ARN in the TargetArn.
That will produce the error: Invalid parameter: TargetArn Reason: >arn:aws:sns:us-west-2:561315416312351:app/APNS_SANDBOX/com.APP_NAME_HERE.app is >not a valid ARN to publish to.
All you need to do is to put the EndpointArn in the TargetArn.
If you need to see the EndpointArn, you can:
Call listPlatformApplications() to get all your applications ARN's.
Call listEndpointsByPlatformApplication() with the App ARN to get the EndpointArn's list.
Enjoy!

Related

How to get data from a different channel youtube api node.js

I started using YouTube's API today since I want to make a Discord bot that can display a YouTube channels data. So, I went to the guides on the YouTube API site, followed the node.js guide, but ran into a problem. I do not know how I can get the data from a different channel than Google Developers (which is the channel their pulling data from in the explanation).
function getChannel(auth) {
var service = google.youtube('v3');
service.channels.list({
auth: auth,
part: 'snippet,contentDetails,statistics',
forUsername: 'GoogleDevelopers'
}, function(err, response) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
var channels = response.data.items;
if (channels.length == 0) {
console.log('No channel found.');
} else {
console.log('This channel\'s ID is %s. Its title is \'%s\', and ' +
'it has %s views.',
channels[0].id,
channels[0].snippet.title,
channels[0].statistics.viewCount);
}
});
}
Above is the code they use. I expected I could change Google Developers to any other YouTube channel and it would return the data from that, but if I change it to, for example Fireship, I get the error below. I searched their API reference, but I don't really understand what I'm doing wrong.
if (channels.length == 0) {
^
TypeError: Cannot read properties of undefined (reading 'length')
What should I do to fix this issue?
Thanks in advance!
If you check the docs for Channel.list you will find that the The parameter forUsername
The forUsername parameter specifies a YouTube username, thereby requesting the channel associated with that username.
so if you want to find it for a different channel or a different user then just change
forUsername: 'GoogleDevelopers'

Posting message to slack get TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["User-Agent"]

I have a working slack app running as an Azure Function using NodeJS. It is posting payloads fine to my channel. I would also like the Function to post a message to the channel via client.chat.postMessage. As far as I can see I have set everything up correctly but whenever I attempt to post the message I get an error:
TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["User-Agent"]
The code to post the message is:
const { WebClient, LogLevel } = require("#slack/web-api");
const client = new WebClient(process.env['BOT_USER_OAUTH_TOKEN'], {
// LogLevel can be imported and used to make debugging simpler
logLevel: LogLevel.DEBUG
});
const channelId = "C0319MTLHB8";
try {
// Call the chat.postMessage method using the WebClient
const result = await client.chat.postMessage({
channel: channelId,
text: "Hello world"
});
console.log(result);
} catch (error) {
context.res = {
// status: 200, /* Defaults to 200 */
body: "error: " + error
};
}
and this piece of code sits within module.exports.
I guess something doesn't like the contents of BOT_USER_OAUTH_TOKEN but this is a direct copy of the xoxb bot user oauth token. And is of the form:
xoxb-999999999999999-9999999999999-aBunchOfUpperAndLowerCaseCharacters
Any suggestions as to what I am doing wrong?
Thank you I'm Joe Too for your valuable discussed resolution. Posting as an answer to help other community members:
You missed an open bracket in const result = await client.chat.postMessage(
Glad #JimBurke, that you have solved yourself by correcting the syntax/transcription.
Isn't it Node.js 16 LTS?
I had a similar problem, But I made Node.js 14 LTS and it worked

How to add header properties to messages using seneca-amqp-transport

I am working on a project that requires the usage of a few rabbitmq queues. One of the queues requires that the messages are delayed for processing at a time in the future. I noticed in the documentation for rabbmitmq there is a new plugin called RabbitMQ Delayed Message Plugin that seems to allow this functionality. In the past for rabbmitmq based projects, I used seneca-amqp-transport for message adding and processing. The issue is that I have not seen any documentation for seneca or been able to find any examples outlining how to add header properties.
It seems as if I need to initially make sure the queue is created with x-delayed-type. Additionally, as each message is added to the queue, I need to make sure the x-delay header parameter is added to the message before it is sent to rabbbitmq. Is there a way to pass this parameter, x-delay, with seneca-amqp-transport?
Here is my current code for adding a message to the queue:
return new Promise((resolve, reject) => {
const client = require('seneca')()
.use('seneca-amqp-transport')
.client({
type: 'amqp',
pin: 'action:perform_time_consuming_act',
url: process.env.AMQP_SEND_URL
}).ready(() => {
client.act('action:perform_time_consuming_act', {
message: {data: 'this is a test'}
}, (err, res) => {
if (err) {
reject(err);
}
resolve(true);
});
});
}
In the code above, where would header-related data go?
I just looked up the code of the library and under lib/client/publisher.js , this should do the trick
function publish(message, exchange, rk, options) {
const opts = Object.assign({}, options, {
replyTo: replyQueue,
contentType: JSON_CONTENT_TYPE,
x-delay: 5000,
correlationId: correlationId
});
return ch.publish(exchange, rk, Buffer.from(message), opts);
}
Give it a Try , should work. Here the delay value if set to 5000 milliseconds. You can also overload the publish method to take the value as a parameter.

Amazon SES verifyEmailIdentity is not sending email

I want to automate the process of authorize email addresses to send mails through the Amazon SES service in javascript/Node.JS.
We are already sending mails via Node and that is working fine, but I can't get this working.
What I so far:
function verifyEmail(email, callback){
var sesService = new AWS.SES({
accessKeyId: "mykey",
secretAccessKey: 'myaccesskey',
region: 'eu-west-1'
});
sesService.verifyEmailIdentity({EmailAddress: email}, function(err, data){
console.log("verifyEmailIdentity", err, data);
return callback(err, data);
})
}
In the log I get this:
verifyEmailIdentity null
Object {ResponseMetadata: Object}
The ResponseMetadata object contains RequestId: "some-string"
So, I didn't get back an error but I didn't also receive an e-mail to confirm this request.
The key have the AmazonSESFullAccess policy added, so there are sufficient permissions to complete this.
I guess I forgot something very simple, but bases on the docs from Amazon I can't find what. And there aren't many examples for javascript is this, so I can't compare my code with others.
Still no idea why this wasn't working but now it works.
We had already plans to create an custom verify template (https://docs.aws.amazon.com/ses/latest/DeveloperGuide/custom-verification-emails.html) and I created an template while waiting on an answer using the CLI.
For using this template we must use an the sendCustomVerificationEmail() function from AWS.
And guess what? With that function the mail is send, and I'm able to verify the requested email address!
The verifyMail function now looks like:
function verifyEmail(email, callback){
sesService.sendCustomVerificationEmail({
EmailAddress: email,
TemplateName: 'MyTemplateName'
},function(err, data){
console.log("verifyEmailIdentity", err, data);
return callback(err, data);
})
}

Azure Mobile Services An unhandled exception occurred. Error: One of your scripts caused the service to become unresponsive

Apologize for my English.
I have a node js script that has to send AMQP messages to device using IoT hub. I've took thiss script from github of azure iot. Here is this sample.
Here is this sample
Here is my script, based on this one:
console.log("creating the client");
var Client = require('azure-iothub').Client;
console.log("client has been created");
var Message = require('azure-iot-common').Message;
console.log("message has been created");
var connectionString = "HostName=id**.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=***;
console.log(connectionString);
var targetDevice = 'devicesergey';
var client = Client.fromConnectionString(connectionString);
client.open(function (err) {
if (err) {
console.error('Could not connect: ' + err.message);
}
else {
console.log('Client connected');
var data = JSON.stringify({ text : 'foo' });
var message = new Message(data);
console.log("json message is created")
console.log('Sending message: ' + message.getData());
client.send(targetDevice, message, printResultFor('send'));
console.log("message has been sent");
}
});
function printResultFor(op) {
return function printResult(err, res) {
if (err) {
console.log(op + ' error: ' + err.toString());
} else {
console.log(op + ' status: ' + res.constructor.name);
}
};
}
That works fine locally and I see messages on my device emulator. But when I try to put it to Azure Mobile Services API and try to run it, I see this message on logs:
An unhandled exception occurred. Error: One of your scripts caused the service to become unresponsive and the service was restarted. This is commonly caused by a script executing an infinite loop or a long, blocking operation. The service was restarted after the script continuously executed for longer than 5000 milliseconds. at process.Server._registerUncaughtExceptionListenerAndCreateHttpServer._onUncaughtException (D:\home\site\wwwroot\node_modules\azure-mobile-services\runtime\server.js:218:17) at process.EventEmitter.emit (events.js:126:20)
And sometimes I see this IIS error
I know exactly that this line occurs this function: client.open(function....
I've evem tried to leave only client.open() and send a messages out of this function. But in this case I see "client is not connected".
I asked about this stuff on github. They advised me to asked here. Maybe someone know how to solve this issue (with script or Azure). I would be very very greatfull!
Thank you!
The Mobile Service Custom API is a script that expose the functionality of the express.js library, please see the section Overview of custom APIs of the offical document "Work with a JavaScript backend mobile service"
I reproduced the issue successfully. I guess your script was not wrapped in the code below as the body block, and not sent the response to the client like browser.
exports.get = function(request, response) {
// The body block
....
response.send(200, "<response-body>");
}
For more details of Mobile Service Custom API, please see https://msdn.microsoft.com/library/azure/dn280974.aspx.
Update:
I changed your code as below.
And In order to facilitate the test, I changed the permission for the api as below, then I can access the api link https://<mobile-service-name>.azure-mobile.net/api/test with browser.
I've just tried to execute my script on new Azure MS and it was unsuccesfully.
I will write my step-by-step actions, maybe you can see anything wrong, because I'm not so good in NodeJS.
Add a new Azure MS with new SQL Database
Add a new API "dev". Access - everyone for all points. Here is source code:
exports.get = function(request, response) {
console.log("creating the client");
var Client = require('azure-iothub').Client;
console.log("client has been created");
var Message = require('azure-iot-common').Message;
console.log("message has been created");
var connectionString = "HostName=i***.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey***";
console.log(connectionString);
var targetDevice = 'devicesergey';
var client = Client.fromConnectionString(connectionString);
client.open(function (err) {
if (err) {
console.error('Could not connect: ' + err.message);
}
else {
console.log('Client connected');
var data = JSON.stringify({ text : 'foo' });
var message = new Message(data);
console.log("json message is created")
console.log('Sending message: ' + message.getData());
client.send(targetDevice, message, printResultFor('send'));
console.log("message has been sent"); }
});
response(200, "Hello, world!");
};
function printResultFor(op) {
return function printResult(err, res) {
if (err) {
console.log(op + ' error: ' + err.toString());
} else {
console.log(op + ' status: ' + res.constructor.name);
}
};
}
If I try to execute this stuff it occurs "no azure-iothub" and "no azure-iot-common", so I need to use git to add these npm.
I clone this repository to my local dir using git access to Azure MS https://id.scm.azure-mobile.net/id.git
Enter the "API" folder and add the NPMs:
Then I perfom "Rescan", "Save changes", "Commit", "Push" on
After these actions I execute my script by path "http://id**.mobile-services.net/api/dev" and don't see anything o see the error "500.1013" and these messages on logs (id depends):
An unhandled exception occurred. Error: One of your scripts caused the
service to become unresponsive and the service was restarted. This is
commonly caused by a script executing an infinite loop or a long,
blocking operation. The service was restarted after the script
continuously executed for longer than 5000 milliseconds. at
process.Server._registerUncaughtExceptionListenerAndCreateHttpServer._onUncaughtException
(D:\home\site\wwwroot\node_modules\azure-mobile-services\runtime\server.js:218:17)
at process.EventEmitter.emit (events.js:126:20)
I can't realize what I'm doing wrong
UPDATE:
I've tried to use Kudu console for installing the npms and it returns many errors. If i figured out correctly, I need to update my node js and npm. But I don't know how to do this and I didn't manage to find a solution.
Here are logs:
I have lack of reputation, so I am not allowed to past log scripts.
I've tried to do these actions, but it doesn't help:
at the root of the repo, you'll find a .deployment file that has:
command = ..\ZumoDeploy.cmd Change it to
command = deploy.cmd And create a deploy.cmd next to it containing:
set
NPM_JS_PATH=%ProgramFiles(x86)%\npm\1.4.9\node_modules\npm\bin\npm-cli.js ..\ZumoDeploy.cmd Commit both files and push.
I'm confused. How is it possible? Azure Mobile services don't permit to install azure-iot-hub npm). What can I do with this issue?
UPDATE2:
Peter Pan - MSFT, you advised me to use Kudu DebucConsole to install necessary npm. But when I try to do it - I see errors.
I've messaged about this issue to "npm" command on github, they say that the version of npm which Azure is used to - is completely unsupported.
htt ps://github.com/npm/npm/issues/12210#event-615573997
UPDATE3 (04/12/2016)
I've solved this issue by different way. Created my own node JS script that is listening a port, read GET params(deviceId and message) and send D2C messages.
Unfortunately, I still can't get trow the Azure issue.
UPDATE4
Peter Pan gave me an advise how to use another version of nodejs and npm. Now I've succesfully installed necessary NPM modules. But now Azure Mobile Script APIs don't work, it shows me {"code":404,"error":"Error: Not Found"} on any script that I try to get in my browser.
Maybe I've deleted something when I tried to do these stuffs.

Resources