Slackbot (Node): icon_emoji feature not working - node.js

My req payload to the Slack API using the icon_emoji feature of this API is not correct. The expected behavior is to have an emoji being :smile: to be displayed as my Slackbot's icon image whenever the bot posts a message to the channel. The current behavior is a default Slack image instead of the :smile:. I don't presently see what I am doing wrong. This is my fourth attempt across months at correcting this possibly so I would appreciate any advice here.
Here is my code, "as_user" has to be set to true for this to work per the documentation for posting messages.
Here is my index.js file:
const fetch = require("node-fetch"),
config = require("../config.js"),
icon = ":smile:";
module.exports = {
postMessage: (message) => {
if(!config.SLACK_CONFIG.webhook_url) {
throw Error("Please set SLACK_MEETUP_WEBHOOK_URL");
}
return fetch(config.SLACK_CONFIG.webhook_url, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ text: message, "as-user": false, "icon-emoji": icon })
}).then(res => res.text()).then((text) => {
if(text !== "ok") {
throw Error("Failed to post message to slack");
}
});
}
};

I faced this problem, I needed to add write customize permissions to the slack app (doc)
To add it:
Go to slack apps page and select the app
Go to OAuth & Permissions (under Features section)
In Scope subsection add chat:write.customize permission

I used the slack-node NPM module, and my code looks like
slack = new Slack();
slack.setWebhook('https://hooks.slack.com/services/JUMBLE/JUMBLE/ALONGERJUMBLE');
slack.webhook({
channel: "#mychannel",
username: "nametopostunder",
text: content,
icon_emoji: ":ship:",
}
My ship emoji posts successfully. If you want to roll your own, you could probably go read the slack-node module's code at https://github.com/clonn/slack-node-sdk#readme and figure out what magic they're using.

I didn't check slack-node, this is just an alternative solution with plain nodejs.
I tried a lot of combinations using 'hooks' endpoint, unfortunately it didn't work.
Instead of 'hooks' I used https://slack.com/api/chat.postMessage with slack token.
const https = require('https');
const slackToken = 'xoxb-XXXXX-XXX'
const data = JSON.stringify({
username: 'someUsername',
icon_emoji: ':+1:',
channel: '#your_channel',
token: slackToken,
text: 'helloWorld'
});
const options = {
hostname: 'slack.com',
port: 443,
path: '/api/chat.postMessage',
method: 'POST',
headers: {
'Content-Type': 'application/json',
authorization: `Bearer ${slackToken}`,
},
};
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`);
res.on('data', d => {
process.stdout.write(d);
});
});
req.on('error', error => {
console.error(error);
});
req.write(data);
req.end();

Did you check your display settings in slack? I encountered the same issue and changed the setting in Preferences => Messages & Media => Theme from Compact to Clean and the icon is displayed as expected.

Sometimes the icon for a message won't change becuase of 2 reasons:
First, the chat:write.customize permission is not granted as defined in the documentation:
https://api.slack.com/methods/chat.postMessage#authorship
In that case you won't get warnings or errors - just nothing happens.
Second - the because the username for the bot remains the same, the icons and messages are collapsed. This is true for both the (android) mobile app and the desktop app. On the mobile app however, you can click a message, see the detailview of the message and see the image that belongs to that particular message.
As we can see in that image, the first round of messages get the :information_source: icon, the icon/usernames of the rest of the messages are collapsed, but with different usernames the icons are visible.

Related

Puppteer post request

I'm trying to use puppeteer in order to fill the cart in the online store.
(is that legal, right?)
Anyway, the action should post the payload to the store server and I'm doing so in this way.
This code run after login to the system as user.
await page.setRequestInterception(true);
page.on("request", async (request) => {
if (request.url() === "https://www.store.com/server/carts/?userID=xyz&appId=x&loyalty=z") {
const res = await request.continue({
method: "POST",
postData: JSON.stringify(cartContent), // cartcontent is arr of object
headers: { ...request.headers(), ...moreHeaders }, // see note bellow the code
});
console.log(request.headers());
} else {
request.abort();
}
});
await page.goto("https://www.store.com/server/carts/?userID=xyz&appId=x&loyalty=z");
await browser.close();
I don't know why, but nothing actually happened. I believe is up to the request headers.
so I added the request.headers(), but when I log those headers they missing some other headers and contnent not same. so I hard-coded them from the browser when I'm logged in as a user. but still i fill i have lake of knowlege that i will glad to learn.
Headers from puppter (request.headers())
upgrade-insecure-request,user-agent,sec-ch-ua,sec-ch-ua-mobile,sec-ch-ua-platform,accept,cookie
Headers from browswer contains :
:authority,:method,path,scheme,accept,accept-encoding,accept-language ,authorization, content-length,content-type,cookie,origin,referer,
sec-ch-ua,sec-ch-ua,sec-ch-ua-platform,sec-fetch-dest,sec-fetch-mode,
sec-fetch-site,sec-fetch-site,user-agent,x-http-method-override

register webhooks on nodejs when order created

I have a shopify store mystore and I have an nodejs app myapp. I need to do is when something happens on mystore a webhook will be created/registered in my nodejs app. I have tried https://www.npmjs.com/package/#shopify/koa-shopify-webhooks this package but it is not working for me and I don't think that it is the same thing that I want. I just want that when let suppose order is created in store a webhook is registered.
if you just have to register a webhook you can use this code.
You just have to change the webhook topic and the endpoint.
This is for orders/create webhook registration
add shopify-api-node and request-promise packages and require them
const ShopifyAPIClient = require("shopify-api-node");
const request = require("request-promise");
then
const createOrderWebhook = await registerWebhook(yourShopDomain, yourShopAccessToken, {
topic: "orders/create",
address: "Your node app end point" //www.example.com/webhooks/createOrder,
format: "json",
});
add your registerWebhook function
const registerWebhook = async function (shopDomain, accessToken, webhook) {
const shopify = new ShopifyAPIClient({
shopName: shopDomain,
accessToken: accessToken,
});
const isCreated = await checkWebhookStatus(shopDomain, accessToken, webhook);
if (!isCreated) {
shopify.webhook.create(webhook).then(
(response) => console.log(`webhook '${webhook.topic}' created`),
(err) =>
console.log(
`Error creating webhook '${webhook.topic}'. ${JSON.stringify(
err.response.body
)}`
)
);
}
};
for checking the webhook already not created at Shopify you can use following code
const checkWebhookStatus = async function (shopDomain, accessToken, webhook) {
try {
const shopifyWebhookUrl =
"https://" + shopDomain + "/admin/api/2020-07/webhooks.json";
const webhookListData = {
method: "GET",
url: shopifyWebhookUrl,
json: true,
headers: {
"X-Shopify-Access-Token": accessToken,
"content-type": "application/json",
},
};
let response = await request.get(webhookListData);
if (response) {
let webhookTopics = response.webhooks.map((webhook) => {
return webhook.topic;
});
return webhookTopics.includes(webhook.topic);
} else {
return false;
}
} catch (error) {
console.log("This is the error", error);
return false;
}
};
Happy coding :)
You can not create/register a new webhook when the order created.
Webhooks are a tool for retrieving and storing data from a certain event. They allow you to register an https:// URL where the event data can be stored in JSON or XML formats. Webhooks are commonly used for:
Placing an order
Changing a product's price
Notifying your IM client or your pager when you are offline
Collecting data for data-warehousing
Integrating your accounting software
Filtering the order items and informing various shippers about the order
Removing customer data from your database when they uninstall your app

How to send email verification when registering a new user in Firebase? [duplicate]

In the past, I have used firebase.auth in the web client and once a user creates another user, I link certain security logic:
Once the user has been created I send an email to verify your email
with the function user.sendEmailVerification ().
As the user was created by another user, I assign a default password
and use the sendPasswordResetEmail () function so that the user
registers his new password.
That has worked well for me so far, but now for many reasons I need to move that logic to my server, for that I'm developing a backend with cloud functions and I'm using the Node.js Firebase Admin SDK version 6.4.0, but I can not find a way to use the functions of user.sendEmailVerification() and sendPasswordResetEmail() to implement the same logic on the server, the closest thing I found was:
auth.generateEmailVerificationLink (email)
auth.generatePasswordResetLink (email)
But it only generates a link for each one, which by the way the only emailVerification() serves me, the one from generatePasswordReset always tells me:
Try resetting your password again
Your request to reset your password has expired or the link has
already been used.
Even though be a new link, and it has not been used.
My 3 questions would be:
How can I make the sendEmailVerification () and
sendPasswordResetEmail () functions work on the server?
How can I make the link generated with
auth.generatePasswordResetLink (email) work correctly on the server?
Is there any way to use templates and emails on the server that are
in firebase auth?
Thank you in advance for sharing your experience with me, with all the programmers' community of stack overflow.
Those functions are not available in firebase-admin, but you should be able to run the client-side SDK (firebase) on the server as well. Not exactly a best practice, but it will get the job done. There's a long standing open feature request to support this functionality in the Admin SDK. You will find some helpful tips and workarounds there.
Could be a bug. I would consider reporting it along with a complete and minimal repro. The Admin SDK does have an integration test case for this use case, but it works slightly differently.
Not at the moment. Hopefully, this will be covered when the above feature request is eventually fulfilled.
The is a workaround provided here
https://github.com/firebase/firebase-admin-node/issues/46
I found a work-around that works well enough for my use case, see below. I'm not sure if this is best practice, but I wanted to keep the emails exactly the same between the server and client requests. Would love to hear about any flaws with this implementation 💡
As suggested above, it uses a three step process to do this:
Acquire a custom token via the admin sdk's createCustomToken(uid)
It converts this custom token to an idToken via the API
It invokes the send email verification endpoint on the API
const functions = require('firebase-functions');
const fetch = require('node-fetch');
const admin = require('firebase-admin');
const apikey = functions.config().project.apikey;
const exchangeCustomTokenEndpoint = `https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key=${apikey}`;
const sendEmailVerificationEndpoint = `https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=${apikey}`;
module.exports = functions.auth.user().onCreate(async (user) => {
if (!user.emailVerified) {
try {
const customToken = await admin.auth().createCustomToken(user.uid);
const { idToken } = await fetch(exchangeCustomTokenEndpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token: customToken,
returnSecureToken: true,
}),
}).then((res) => res.json());
const response = await fetch(sendEmailVerificationEndpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
requestType: 'VERIFY_EMAIL',
idToken: idToken,
}),
}).then((res) => res.json());
// eslint-disable-next-line no-console
console.log(`Sent email verification to ${response.email}`);
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
}
});
I'm sure it doesn't matter anymore, but I had a headache doing this so I'd like to share even if it isn't the greatest answer.
await admin.auth().createUser(
{email, password, displayName, phoneNumber, photoURL}
).then(function(userRecord) {
admin.auth().createCustomToken(userRecord.uid).then(function(customToken){
createdToken=customToken;
firebase.auth().signInWithCustomToken(createdToken).catch(function(error){
return console.log(error)
})
firebase.auth().onAuthStateChanged(function(user) {
user.sendEmailVerification().then(function(){
return console.log('It worked')
},function(error) {
return console.log(error)
})
});
})
})

How to get `fcm_options.link` functioning in firebase web notifications

I'm trying to get my FCM web notifications to contain a clickable link to my site, using the firebase admin SDK (version 7.0.0) for node.js. As far as I can tell I'm following the documentation to a T, but I'm unable to get the link working. To clarify, my notifications are working fine otherwise, it's just the link that I haven't got to work.
The documentation states:
For notification messages sent from the app server, the FCM JavaScript API supports the fcm_options.link key. Typically this is set to a page in your web app
I've included webpush.fcm_options.link inside my notification message. I've made sure to include an explicit notification payload in my message, as the documentation states that data messages don't support fcm_options.link.
Here's the structure of my message currently:
{
notification: {
title: 'Title',
body: 'Body',
},
data: {
// my data here
},
webpush: {
notification: {
requireInteraction: true,
icon: '/icons/notification.png'
},
fcm_options: {
link: 'https://example.com/'
}
},
// android: {},
// apns: {},
topic: 'sometopic'
};
Here's the function I'm using to send the message:
const admin = require('firebase-admin')
const sendMessage = message => {
admin
.messaging()
.send(message)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
});
};
The link property should be working according to the documentation: my url includes https and my notification is being sent from the app server, and includes an explicit notification payload. At the moment, clicking on the notification just makes it disappear, with nothing else happening.
UPDATE: I worked out what the issue was - my service worker was using the importScripts function, but I was using an out-of-date version of the firebase script that didn't support fcm_options.link. I changed it to my current version of firebase (5.8.5) and it works. All sorted!
in notification try This
"notification":{
"title":"IssA",
"body":"Lafi",
"icon": "Icon URL",
"click_action": "Your URL here"
}
In the last version, using firebase admin in node js, this is the right configuration:
var message = {
notification: {
title: "",
body: ""
},
webpush: {
fcmOptions: {
link: "https://yourlink.web.app"
}
}
};

Rendering Current Page With PhantomJS

I am building an analytics dashboard using the MERN stack (Express, Node) are the Important things to highlight.
As part of a dash view, I was trying to find if it's possible to trigger a PhantomJS call to create a pdf report using a button on the page itself.
Given you need to be logged in to see your own analytics, I can not just run phantom from the command line and pass it in the URL of one of the dashboard pages since it requires a login and queries to be made.
Is it possible to do this with phantomJS?
If I correctly understood your question.
Example:
[main.js]
const dashboardToPdfCtrl = require("./controllers/phantom/pdf");
router.route("/api/dashboard/phantom").post(dashboardToPdfCtrl.createPdf);
router.route("/api/dashboard/phantom/html")
.post(dashboardToPdfCtrl.createDashboard);
When the user clicks on the "button" you can validate the USER according to the architecture of your application.
[pdf.js]
exports.createPdf= async (req, res) => {
if (!req.user || !req.user.sub) {
return res
.status(401)
.send({ message: 'No authorization token was found' });
}
const instance = await phantom.create();
const page = await instance.createPage();
const settings = {
operation: "POST",
encoding: "utf8",
headers: {
"Content-Type": "application/json"
},
data: JSON.stringify({
user: req.body.userId,
anyDataYouNeedToRender: req.body.anyDataYouNeedToRender
})
};
//POST request to /api/dashboard/phantom/html
await page.open(
`${process.env.HOST}:${
process.env.PORT
}/api/dashboard/phantom/html`,
settings
);
//Save the content of /public/dashboard/dashboard.html with received data to pdf
const pageSaved = await page.render(
path.resolve(`./public/dashboard/file.pdf`)
);
if (pageSaved) await instance.exit();
}
exports.createDashboard = (req, res) => {
res.render(
path.resolve("./public/dashboard/dashboard.html"),
{ user: req.body.user,
anyDataYouNeedToRender: req.body:anyDataYouNeedToRender
}
);
};
Is that what you were looking for? I want to help you, feel free to ask detalization.
P.S. As friends told before in comments, it will be great if you give us more information to understend you goal.

Resources