How to validate firebase MessagingPayload size - firebase-cloud-messaging

How can I validate title and message of MessaginPayload.
I have nodejs function to send notification message to my mobile app.
Sometime we got error, because message is exceed the limit.
Firebase mention that Notification messages can contain an optional data payload. Maximum payload for both message types is 4000 bytes, except when sending messages from the Firebase console, which enforces a 1024 character limit.
So how can I check the message payload in nodejs.
import * as firebaseAdmin from "firebase-admin";
import serviceAccount from "./service-account-file.json";
const admin = firebaseAdmin.initializeApp(
{
credential: firebaseAdmin.credential.cert(serviceAccount as
firebaseAdmin.ServiceAccount),
},
"server"
);
const fcm = admin.messaging();
const sendMessage = async (title: any, message: any) => {
var topic = "mydomain.org";
const payload: firebaseAdmin.messaging.MessagingPayload = {
notification: {
title: title,
body: message,
click_action: "FLUTTER_NOTIFICATION_CLICK", // required only for onResume or
onLaunch callbacks
},
};
return await fcm.sendToTopic(topic, payload);
};
export { sendMessage };

Related

FCM not working in Firebase Cloud Function because admin sdk authentication-error

I am currently trying to send FCM using Firebase Cloud Function in the Flutter WEB environment. But it doesn't work very well
My Problem
My index.js Code
/* eslint-disable max-len */
const admin = require("firebase-admin");
const {applicationDefault} = require("firebase-admin/app");
const functions = require("firebase-functions");
const cors = require("cors")({origin: true});
admin.initializeApp({credential: applicationDefault(), databaseURL: "https://<PROJECT-ID>.firebaseio.com"});
const messaging = admin.messaging();
exports.sendNoti = functions.runWith({
allowInvalidAppCheckToken: true}).https.onRequest(async (req, res) => {
cors(req, res, async () =>{
if (res.app == undefined) {
console.log("App Check failed-precondition / The function must be called from an App Check verified app.");
}
console.log(res.app);
try {
await messaging.sendToDevice(req.body.data.targetDevices, {
notification: {
title: req.body.data.messageTitle,
body: req.body.data.messageBody,
},
});
res.set("Access-Control-Allow-Origin", "*");
res.status(200).send({"status": "success", "data": "GOOD"});
return true;
} catch (ex) {
console.log(ex);
res.set("Access-Control-Allow-Origin", "*");
res.status(200).send({"status": "fail", "data": ex});
return ex;
}
});
});
Error Message
{errorInfo: {code: messaging/authentication-error, message: An error occurred when trying to authenticate to the FCM servers. Make sure the credential used to authenticate this SDK has the proper permissions. See https://firebase.google.com/docs/admin/setup for setup instructions. Raw server response: "HTML CODE
". Status code: 401.}, codePrefix: messaging}
My Try
credential: admin.credential.applicationDefault(),
credential: admin.credential.cert("service.json"),
Use OnCall function
Use AppCheck

Market data routing to frontend: Alpaca WebSocket -> Node.js WebSocket -> React Frontend

I'm trying to use the websocket example from:
https://github.com/alpacahq/alpaca-trade-api-js/blob/master/examples/websocket_example_datav2.js
In order to connect to the Alpaca V2 data stream. Currently, my stream is working but I'm trying to route my data to the client side using Server Sent Events. My data flow seems like it should be:
Alpaca Data Stream API -> My Node.js server -> React Frontend.
The issue I have is using the DataStream object in the example in order to route the data to the frontend. Since, with the object alone, I don't have any route to subscribe to via Server Sent Events, does this mean that I should also be using either express, socket.io, or ws? Since the all of the ".on_xyz" methods are defined within the DataStream object, I'm not sure how to set up the endpoint properly to allow my frontend to subscribe to it. If anyone knows how to route this datastream information forward it would be greatly appreciated- I'm particularly trying to work with the .onStockQuote method but any of them is fine! I'm simply trying to use Node as an inbetween router so that I don't have to subscribe directly from the frontend (and not use the sdk), because that limits scalability of the API's use.
"use strict";
/**
* This examples shows how to use tha alpaca data v2 websocket to subscribe to events.
* You should use the alpaca api's data_steam_v2, also add feed besides the other parameters.
* For subscribing (and unsubscribing) to trades, quotes and bars you should call
* a function for each like below.
*/
import express from 'express';
const app = express()
const Alpaca = require("#alpacahq/alpaca-trade-api");
const API_KEY = "XYZ_Key";
const API_SECRET = "XYZ_Secret";
const PORT = 3000;
// Add a new message and send it to all subscribed clients
const addMessage = (req, res) => {
const message = req.body;
// Return the message as a response for the "/message" call
res.json(message);
return ;
};
class DataStream {
constructor({ apiKey, secretKey, feed }) {
this.alpaca = new Alpaca({
keyId: apiKey,
secretKey,
feed,
});
const socket = this.alpaca.data_stream_v2;
socket.onConnect(function () {
console.log("Connected");
socket.subscribeForQuotes(["AAPL"]);
// socket.subscribeForTrades(["FB"]);
// socket.subscribeForBars(["SPY"]);
// socket.subscribeForStatuses(["*"]);
});
socket.onError((err) => {
console.log(err);
});
socket.onStockTrade((trade) => {
console.log(trade);
});
socket.onStockQuote((quote) => {
console.log(quote);
});
socket.onStockBar((bar) => {
console.log(bar);
});
socket.onStatuses((s) => {
console.log(s);
});
socket.onStateChange((state) => {
console.log(state);
});
socket.onDisconnect(() => {
console.log("Disconnected");
});
socket.connect();
// unsubscribe from FB after a second
// setTimeout(() => {
// socket.unsubscribeFromTrades(["FB"]);
// }, 1000);
}
}
app.post("/message", addMessage);
let stream = new DataStream({
apiKey: API_KEY,
secretKey: API_SECRET,
feed: "sip",
paper: false,
});
app.listen(PORT, () => {
console.log(`App listening on port ${PORT}`);
});

How to get telegram chat id

So i have this python code that figures out channel chat id to send message for multiple channels in a given list.
I only have the channel invite link
I still didn't figure out how can i get the channel id by the name only.
import os
import telebot
API_KEY = os.environ['API_KEY']
bot = telebot.TeleBot(API_KEY)
a=input("edit msg.txt to send the msg if done press enter")
message=open("message.txt","a+")
bot.send_message(chat_id,message)
If you prefer to use Telegram API together with javascript and axios library then you might consider the following:
const method = 'get'
const headers: any = {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
timestamp: +new Date(),
}
const options = { headers: { ...headers } }
const urlTelegramBase =
'https://api.telegram.org/bot123456:ABCDEF'
const urlGetUpdates = `${urlTelegramBase}/getUpdates`
const username = 'user_name'
const {
data: { result: messages },
} = await axios[method](urlGetUpdates, options)
const chat_id = messages.find(
messageBlock => messageBlock.message.chat.username === username
).message.chat.id
console.info('chat_id': chat_id)
You can use the getChat method to resolve a channel username to the chat id. You can also just send the message using the username - see the docs of sendMessage and e.g. this answer.

ValidationError: Subscription is unusable or cannot be found. License failed

I'm trying to create a service that will be a middle man between my frontend framework and shutterstock. I'm running into an issue when trying to license an image where it says my subscription is unusable or cannot be found. I have done exactly what the documentation said and I don't know what I am missing.
let sstk = require("shutterstock-api");
sstk.setSandbox(true);
sstk.setAccessToken(process.env.SHUTTERSTOCK_TOKEN);
// Instantiate the shutterstock images api
const imagesApi = new sstk.ImagesApi();
// Instantiate the shutterstock users api
const usersApi = new sstk.UsersApi();
// Creates the body to send to shutterstock
const body = {
images: imageIds.map((imageId) => {
return {
image_id: imageId,
price: 0,
metadata: {
customer_id: "0",
},
};
}),
};
// Get subscription so we can grab the subscription id
usersApi
.getUserSubsciptionList()
.then(({ data }) => {
const subscription_id = data[0].id;
const queryParams = {
format: "jpg",
size: "huge",
subscription_id,
};
// If we successfully get the subscription id then license the images
imagesApi
.licenseImages(body, queryParams)
.then(({ data }) => {
console.log("licensedImages", data);
// Check if there was an error on any of the images
let numOfErrors = 0;
data.forEach((image) => {
if (image.error) {
numOfErrors += 1;
}
});
// If some of the images were successful
if (numOfErrors > 0 && numOfErrors < data.length) {
return errorHandler
// If all the images failed
} else if (numOfErrors > 0) {
return errorHandler
}
// If there are no errors send back the data to the frontend to manipulate it how it needs
return res.status(200).send(data);
})
.catch((err) => {
// If license error wasn't handled by Shutterstock
console.error(err);
return errorHandler
});
})
.catch((error) => {
// If subscription error wasn't handled by Shutterstock
console.error(error);
return errorHandler
});
Logged Response with status code 200
licensedImages [ exports {
image_id: id,
error:
'ValidationError: Subscription is unusable or cannot be found. License failed' } ]
I'm not sure why its not working. I've logged my subscription id and image id and they are correct.
The format and size do match the formats available on the subscription.
The subscription is a Developer Platform license.
What am I missing?
This is on an expressjs api
It looks like your Shutterstock account has both a 'Developer Platform' subscription and standard user subscription, which causes issues in the api. Your code is correct - the problem is with the validation of your subscription within the licensing flow. We'll reach out to you via email once we correctly attribute your different subscriptions.

Axios interceptors don't send data to API in production Heroku app

This is part 2 of me debugging my application in production
In part 1, I managed to at least see what was causing my problem and managed to solve that.
When I send a request to my API which is hosted on Heroku using axios interceptor, every single request object looks like this in the API
{ 'object Object': '' }
Before sending out data to the API, I console.log() the transformRequest in axios and I can see that the data I am sending is actually there.
Note: I have tested this process simply using
axios.<HTTP_METHOD>('my/path', myData)
// ACTUAL EXAMPLE
await axios.post(
`${process.env.VUE_APP_BASE_URL}/auth/login`,
userToLogin
);
and everything works and I get data back from the server.
While that is great and all, I would like to abstract my request implementation into a separate class like I did below.
Does anyone know why the interceptor is causing this issue? Am I misusing it?
request.ts
import axios from "axios";
import { Message } from "element-ui";
import logger from "#/plugins/logger";
import { UsersModule } from "#/store/modules/users";
const DEBUG = process.env.NODE_ENV === "development";
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_URL,
timeout: 5000,
transformRequest: [function (data) {
console.log('data', data)
return data;
}],
});
service.interceptors.request.use(
config => {
if (DEBUG) {
logger.request({
method: config.method,
url: config.url
});
}
return config;
},
error => {
return Promise.reject(error);
}
);
service.interceptors.response.use(
response => {
console.log('axios interception response', response)
return response.data;
},
error => {
const { response } = error;
console.error('axios interception error', error)
if (DEBUG) {
logger.error(response.data.message, response);
}
Message({
message: `Error: ${response.data.message}`,
type: "error",
duration: 5 * 1000
});
return Promise.reject({ ...error });
}
);
export default service;
Login.vue
/**
* Sign user in
*/
async onClickLogin() {
const userToLogin = {
username: this.loginForm.username,
password: this.loginForm.password
};
try {
const res = await UsersModule.LOGIN_USER(userToLogin);
console.log("res", res);
this.onClickLoginSuccess();
} catch (error) {
throw new Error(error);
}
}
UsersModule (VUEX Store)
#Action({ rawError: true })
async [LOGIN_USER](params: UserSubmitLogin) {
const response: any = await login(params);
console.log('response in VUEX', response)
if (typeof response !== "undefined") {
const { accessToken, username, name, uid } = response;
setToken(accessToken);
this.SET_UID(uid);
this.SET_TOKEN(accessToken);
this.SET_USERNAME(username);
this.SET_NAME(name);
}
}
users api class
export const login = async (data: UserSubmitLogin) => {
return await request({
url: "/auth/login",
method: "post",
data
});
};
I'm not sure what you're trying to do with transformRequest but that probably isn't what you want.
A quote from the documentation, https://github.com/axios/axios#request-config:
The last function in the array must return a string or an instance of Buffer, ArrayBuffer, FormData or Stream
If you just return a normal JavaScript object instead it will be mangled in the way you've observed.
transformRequest is responsible for taking the data value and converting it into something that can actually be sent over the wire. The default implementation does quite a lot of work manipulating the data and setting relevant headers, in particular Content-Type. See:
https://github.com/axios/axios/blob/885ada6d9b87801a57fe1d19f57304c315703079/lib/defaults.js#L31
If you specify your own transformRequest then you are replacing that default, so none of that stuff will happen automatically.
Without knowing what you're trying to do it's difficult to advise further but you should probably use a request interceptor rather than transformRequest for whatever it is you're trying to do.