I have problems with the connection of dialogflow cx and firestore database - google-cloud-firestore

can someone help me with dialogflow cx webhooks and add data to Firestore, this is my index.js code but it does not store in the database. Thanks
Hello, can someone help me with dialogflow cx webhooks and add data to Firestore, this is my index.js code but it does not store in the database. Thanks
const Firestore = require('#google-cloud/firestore');
const PROJECTID = 'ia-proyecto';
const firestore = new Firestore({
projectId: PROJECTID,
timestampsInSnapshots: true,
});
exports.db_datos_personales = (req, res) => {
function replaceAll(string, search, replace) {
return string.split(search).join(replace);
}
console.log('Dialogflow Request body: ' + JSON.stringify(req.body));
let tag = req.body.fulfillmentInfo.tag;
console.log('Tag: ' + tag);
console.log('Session Info Parameters: ' + JSON.stringify(req.body.sessionInfo.parameters));
//
if (tag === 'nombre') {
const COLLECTION_NAME = 'Datos_Personales';
let Nombre_Usuario = replaceAll(JSON.stringify(req.body.sessionInfo.parameters['nombre_usuario']), '"', '');
let Ciudad_Usuario = replaceAll(JSON.stringify(req.body.sessionInfo.parameters['ciudad_usuario']), '"', '');
console.log('Nombre usuario: ' + Nombre_Usuario);
console.log('Ciudad usuario: ' + Ciudad_Usuario);
const data = {
Nombre_Usuario: Nombre_Usuario,
Ciudad_Usuario: Ciudad_Usuario,
};
console.log(JSON.stringify(data));
var answer = 'Welcome to the Cloud Audio family, '+ Nombre_Usuario +'! Enjoy our services.';
return firestore.collection(COLLECTION_NAME)
.set(data)
.then(doc => {
return res.status(200).send({
fulfillmentResponse: {
messages: [{
text: {
text: [answer]
}
}]
}
});
}).catch(err => {
console.error(err);
return res.status(404).send({ error: 'unable to store', err });
});
//
} else if (tag === 'pregunta') {
const COLLECTION_NAME = 'Pregunta_Usuario';
let pregunta_usuario = replaceAll(JSON.stringify(req.body.sessionInfo.parameters['pregunta_usuario']), '"', '');
console.log('Pregunta Usuario: ' + pregunta_usuario);
const data = {
pregunta_usuario: pregunta_usuario
};
console.log(JSON.stringify(data));
var answer = 'Your plan has been changed to the '+ pregunta_usuario + ' service.';
return firestore.collection(COLLECTION_NAME)
.doc(phone_number)
.update(data)
.then(doc => {
return res.status(200).send({
fulfillmentResponse: {
messages: [{
text: {
text: [answer]
}
}]
}
});
}).catch(err => {
console.error(err);
return res.status(404).send({ error: 'unable to update field', err });
});
}
};
I hope to have a solution, since I was more than a week and I can't find anything.

Related

Swift 5/iOS 13+ – Google Cloud Functions won't let me add a value

I'm using Google Cloud Functions (GCF) to schedule posts on Instagram (an app similar to Hootsuite). I just integrated local notifications and I want to add the ID (generated automatically by my "notificationManager") to the post (data sent to Google Cloud).
Basically, the way that it works is the app sends the data to GCF and GCF is responsible for adding the elements to Firestore Database, but after many failed attempts, I cannot seem to figure out how to add an additional value. My goal is to add the element "notificationIdentifier", but for some reason, GCF won't register it (I can't even see it in the logs!).
Here's what's in GCF:
/* eslint-disable max-len */
/* eslint-disable */
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const express = require("express");
const bodyParser = require("body-parser");
const axios = require("axios");
const FACEBOOK_GRAPH_API_VERSION = "v11.0";
const FACEBOOK_APP_ID = Undisclosed APP_ID;
const FACEBOOK_APP_SECRET = Undisclosed APP_SECRET;
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
admin.initializeApp();
const app = express();
const main = express();
const db = admin.firestore();
/**
* publish Instagram Media Object.
* #param {string} container_id instagram media object creation id.
* #param {string} accessToken user access token.
* #return {Promise} Returns container status
*/
async function getContainerStatus(container_id, accessToken) {
let status = "IN PROGRESS";
let response;
try {
response = await axios.get(
`https://graph.facebook.com/${FACEBOOK_GRAPH_API_VERSION}/${container_id}`,
{
params: {
access_token: accessToken,
fields: "status_code",
},
}
);
} catch (error) {
console.log(error);
return "ERROR";
}
// console.log(response.data.status_code, "status");
status = response.data.status_code;
return status;
}
/**
* Get LongLive Token Expire in 60 days.
* #param {string} accessToken user access token.
* #return {Promise} Return Long Live token.
*/
function getLongLiveToken(accessToken) {
return new Promise((resolve, reject) => {
axios
.get(
`https://graph.facebook.com/${FACEBOOK_GRAPH_API_VERSION}/oauth/access_token`,
{
params: {
grant_type: "fb_exchange_token",
client_id: FACEBOOK_APP_ID,
client_secret: FACEBOOK_APP_SECRET,
fb_exchange_token: accessToken,
},
}
)
.then((response) => {
resolve(response.data.access_token);
})
.catch((error) => {
reject(error);
});
});
}
/**
* Get Facebook Pages.
* #param {string} accessToken user access token.
* #return {Promise} Returns the facebook pages result.
*/
function getFacebookPages(accessToken) {
return new Promise((resolve, reject) => {
axios
.get(
`https://graph.facebook.com/${FACEBOOK_GRAPH_API_VERSION}/me/accounts`,
{
params: {
access_token: accessToken,
},
}
)
.then((response) => {
const data = response.data.data;
resolve(data);
})
.catch((error) => {
reject(error);
});
});
}
/**
* Get Instagram Account From Facebook Pages.
* #param {string} accessToken user access token.
* #param {string} pageId Page ID.
* #return {Promise} Returns the Instagram Account Id.
*/
function getInstagramAccountId(accessToken, pageId) {
return new Promise((resolve, reject) => {
axios
.get(
`https://graph.facebook.com/${FACEBOOK_GRAPH_API_VERSION}/${pageId}`,
{
params: {
access_token: accessToken,
fields: "instagram_business_account",
},
}
)
.then((response) => {
if (response.data.instagram_business_account) {
resolve({
id: response.data.instagram_business_account.id,
});
} else {
resolve({ error: "No instagram Business Account" });
}
})
.catch((error) => {
reject(error);
});
});
}
/**
* Get Facebook Profile.
* #param {string} accessToken user access token.
* #return {Promise} Returns the Facebook Account Profile.
*/
function getFacebookProfile(accessToken) {
return new Promise((resolve, reject) => {
axios
.get(`https://graph.facebook.com/${FACEBOOK_GRAPH_API_VERSION}/me`, {
params: {
access_token: accessToken,
fields: "name,picture,email",
},
})
.then((response) => {
resolve({
picture: response.data.picture.data.url,
name: response.data.name,
email: response.data.email,
facebookUserId: response.data.id,
});
})
.catch((error) => {
reject(error);
});
});
}
/**
* Get Instagram Profile.
* #param {string} accessToken user access token.
* #param {string} instagramAccountId Instagram Account ID.
* #return {Promise} Returns the Instagram Account Profile.
*/
function getInstagramProfile(accessToken, instagramAccountId) {
return new Promise((resolve, reject) => {
axios
.get(
`https://graph.facebook.com/${FACEBOOK_GRAPH_API_VERSION}/${instagramAccountId}`,
{
params: {
access_token: accessToken,
fields: "name,username,profile_picture_url",
},
}
)
.then((response) => {
resolve(response.data);
})
.catch((error) => {
reject(error);
});
});
}
/**
* Create Instagram Media Object.
* #param {string} accessToken user access token.
* #param {string} instagramAccountId Instagram Account ID.
* #param {string} caption caption.
* #param {string} mediaType Instagram Account ID.
* #param {string} mediaUrl media url
* #return {Promise} Returns created Instagram Media ID.
*/
function createInstagramMedia(
accessToken,
instagramAccountId,
caption,
mediaType,
mediaUrl,
tags,
) {
return new Promise((resolve, reject) => {
const params = {
access_token: accessToken,
caption: caption,
};
let user_tags = [];
if(tags != null) {
for (let i = 0; i < tags.length; i++) {
const user_tag = {
"username": tags[i],
"x": Math.random(),
"y": Math.random()
}
user_tags.push(user_tag);
}
}
if (mediaType == "PICTURE") {
params["image_url"] = mediaUrl;
if(tags != null) {
params["user_tags"] = user_tags;
}
} else if (mediaType == "VIDEO") {
params["video_url"] = mediaUrl;
params["media_type"] = "VIDEO";
} else {
reject({ message: "Unknow media!" });
return;
}
axios
.post(
`https://graph.facebook.com/${FACEBOOK_GRAPH_API_VERSION}/${instagramAccountId}/media`,
params
)
.then(async (response) => {
const container_id = response.data.id;
let container_status = "IN_PROGRESS";
while (container_status == "IN_PROGRESS") {
container_status = await getContainerStatus(
container_id,
accessToken
);
console.log(container_status, "Container status");
}
// resolve(response.data);
if (container_status == "ERROR") {
reject({ error: "Container error!" });
} else {
resolve(response.data);
}
})
.catch((error) => {
console.log(error);
reject(error);
});
});
}
/**
* publish Instagram Media Object.
* #param {string} accessToken user access token.
* #param {string} instagramAcctId instagram media object creation id.
* #param {string} mediaObjectId instagram media object creation id.
* #return {Promise} Returns the Instagram Account Profile.
*/
function publishMedia(accessToken, instagramAcctId, mediaObjectId) {
console.log(accessToken, " --> ", instagramAcctId, " --> ", mediaObjectId);
return new Promise((resolve, reject) => {
axios
.post(
`https://graph.facebook.com/${FACEBOOK_GRAPH_API_VERSION}/${instagramAcctId}/media_publish`,
{
access_token: accessToken,
creation_id: mediaObjectId,
}
)
.then((response) => {
resolve(response.data);
})
.catch((error) => {
console.log(error);
reject(error);
});
});
}
/**
* Facebook Login with uuid
* body params {uuid, accessToken}
*/
app.post("/register", async (req, res) => {
const uuid = req.body.uuid;
const accessToken = req.body.accessToken;
const instagramAccts = [];
let longLiveToken, userData, pages;
try {
longLiveToken = await getLongLiveToken(accessToken);
} catch (error) {
console.log(error);
return res.status(400).json({
error: "Failed to create LongLive Token",
});
}
try {
userData = await getFacebookProfile(accessToken);
} catch (error) {
console.log(error);
return res.status(400).json({
error: "Failed to get Facebook profile",
});
}
try {
pages = await getFacebookPages(accessToken);
} catch (error) {
console.log(error);
return res.status(400).json({
error: "Failed to get Facebook pages",
});
}
if (pages.length > 0) {
for (let i = 0; i < pages.length; i++) {
try {
const data = await getInstagramAccountId(accessToken, pages[i].id);
if (!data.error) {
const igProfile = await getInstagramProfile(accessToken, data.id);
// const tags = await db
// .collection("tags")
// .where("tag", igProfile["username"])
// .get();
// if (tags.docs.length < 1) {
// await db.collection("tags").add({
// tag: igProfile["username"],
// });
// }
igProfile["isActive"] = true;
if (i == 0) {
igProfile["isPrimary"] = true;
} else {
igProfile["isPrimary"] = false;
}
instagramAccts.push(igProfile);
}
} catch (error) {
console.log(error);
return res.status(400).json({
error: "Failed to get Instagram accounts",
});
}
}
}
try {
await db.collection("users").doc(uuid).set({
longLiveToken: longLiveToken,
picture: userData.picture,
name: userData.name,
email: userData.email,
facebookUserId: userData.facebookUserId,
accessToken: accessToken,
uuid: uuid,
instagramAccts: instagramAccts,
});
} catch (error) {
console.log(error);
return res.status(400).json({
error: "Failed to save user info to firestore",
});
}
return res.status(200).json({
message: "Success",
instagramAccts: instagramAccts,
});
});
app.post("/getInstagramAccounts", async (req, res) => {
const uuid = req.body.uuid;
const user = await db.collection("users").doc(uuid).get();
const userData = user.data();
const accessToken = userData.longLiveToken;
const instagramAccts = [];
let pages;
try {
pages = await getFacebookPages(accessToken);
} catch (error) {
console.log(error);
return res.status(400).json({
error: "Failed to get Facebook pages",
});
}
if (pages.length > 0) {
for (let i = 0; i < pages.length; i++) {
try {
const data = await getInstagramAccountId(accessToken, pages[i].id);
if (!data.error) {
const igProfile = await getInstagramProfile(accessToken, data.id);
if (i == 0) {
igProfile["isActive"] = true;
} else {
igProfile["isActive"] = false;
}
instagramAccts.push(igProfile);
}
} catch (error) {
console.log(error);
return res.status(400).json({
error: "Failed to get Instagram accounts",
});
}
}
}
try {
await db
.collection("users")
.doc(uuid)
.update({ instagramAccts: instagramAccts });
} catch (error) {
console.log(error);
return res.status(500).json({
error: "Failed to update instagram accounts",
});
}
return res.status(200).json({ instagramAccts: instagramAccts });
});
/**
* Schedule Instagram Media Object to publish.
* body params {time, mediaType, uuid, media, instagramAcctId}
*/
app.post("/schedule", async (req, res) => {
const uuid = req.body.uuid;
const time = req.body.time;
const mediaType = req.body.mediaType;
const media = req.body.media; // url string array
const tags = req.body.tags; // array of strings
const longitude = req.body.longitude;
const latitude = req.body.latitude;
const instagramAcctId = req.body.instagramAcctId;
const caption = req.body.caption;
const thumbnail = req.body.thumbnail;
const timeStamp = req.body.timeStamp;
const notificationIdentifier = req.notificationIdentifier;
try {
const postData = await db.collection("posts").add({
uuid: uuid,
time: time,
mediaType: mediaType,
media: media,
instagramAcctId: instagramAcctId,
published: false,
caption: caption,
tags: tags ? tags : null,
thumbnail: thumbnail ? thumbnail : null,
longitude: longitude,
latitude: latitude,
timeStamp: timeStamp,
notificationIdentifier: notificationIdentifier ? notificationIdentifier : null,
});
const ref = await postData.get();
await db.collection("posts").doc(ref.id).update({ id: ref.id });
res.status(200).json({
message: "Success!",
});
} catch (error) {
console.log(error);
res.status(500).json(error.message);
}
});
app.post("/update-schedule", async (req, res) => {
const id = req.body.id;
const time = req.body.time;
const tags = req.body.tags; // array of strings
const longitude = req.body.longitude;
const latitude = req.body.latitude;
const instagramAcctId = req.body.instagramAcctId;
const caption = req.body.caption;
const timeStamp = req.body.timeStamp;
const notificationIdentifier = req.body.notificationIdentifier;
const updateData = {};
if (time) {
updateData["time"] = time;
}
if (tags) {
updateData["tags"] = tags;
}
if (longitude) {
updateData["longitude"] = longitude;
}
if (latitude) {
updateData["latitude"] = latitude;
}
if (instagramAcctId) {
updateData["instagramAcctId"] = instagramAcctId;
}
if (caption) {
updateData["caption"] = caption;
}
if (timeStamp) {
updateData["timeStamp"] = timeStamp;
}
if (notificationID) {
updateData["notificationIdentifier"] = notificationIdentifier;
}
try {
await db.collection("posts").doc(id).update(updateData);
res.status(200).json({
message: "Update success!",
});
} catch (error) {
console.log(error);
res.status(500).json(error.message);
}
});
app.post("/remove-schedule", async (req, res) => {
const id = req.body.id;
try {
const postData = await db.collection("posts").doc(id).get();
if (postData.exists) {
await db.collection("posts").doc(id).delete();
res.status(200).json({
message: "Remove success!",
});
} else {
res.status(400).json({
message: "There is no such post!",
});
}
} catch (error) {
console.log(error);
res.status(500).json(error.message);
}
});
app.post("/get-posts-by-date", async (req, res) => {
const uuid = req.body.uuid;
let posts_by_date = [];
try {
const posts = await db
.collection("posts")
.where("published", "==", false)
.where("uuid", "==", uuid)
.orderBy("time")
.get();
for (let i = 0; i < posts.docs.length; i++) {
const postData = posts.docs[i].data();
console.log(new Date(postData["time"]).toLocaleDateString());
const localDate = new Date(postData["time"]).toLocaleDateString();
if (posts_by_date[localDate]) {
posts_by_date[localDate].push(postData);
} else {
posts_by_date[localDate] = [];
posts_by_date[localDate].push(postData);
}
}
console.log(posts_by_date, "posts by date");
return res.status(200).json({
posts: posts_by_date,
});
} catch (error) {
console.log(error);
return res.status(500).json(error.message);
}
});
exports.scheduledFunction = functions.pubsub
.schedule("* * * * *")
.onRun((context) => {
console.log("This will be run every 1 minute!");
db.collection("posts")
.where("published", "==", false)
.get()
.then((querySnapshot) => {
querySnapshot.forEach(async (doc) => {
console.log(doc.id, " => ", doc.data());
const post = doc.data();
const now = new Date();
const publishDate = new Date(post.time);
if (publishDate <= now) {
//publish media object.
const uuid = post.uuid;
const userRef = await db.collection("users").doc(uuid).get();
const user = userRef.data();
const longLiveToken = user.longLiveToken;
const instagramAcctId = post.instagramAcctId;
const medias = post.media;
//const notificationIdentifier = post.notificationIdentifier;
for (let i = 0; i < medias.length; i++) {
try {
const mediaObjects = await createInstagramMedia(
longLiveToken,
instagramAcctId,
post.caption,
post.mediaType,
medias[i],
post.tags,
// notificationIdentifier
);
const mediaObjectId = mediaObjects.id;
await publishMedia(
longLiveToken,
instagramAcctId,
mediaObjectId
);
} catch (error) {
console.log(error);
return;
}
}
await db
.collection("posts")
.doc(doc.id)
.update({ published: true });
}
});
})
.catch((error) => {
console.log("Error getting documents: ", error);
});
return null;
});
main.use("/v1", app);
main.use(bodyParser.json());
main.use(bodyParser.urlencoded({ extended: true }));
exports.api = functions.https.onRequest(main);
and this is how the data is sent:
private func schedulePost(uuid: String, time: Date, mediaType: String, media: [String], caption: String, tags:[String], location: CLLocation?, thumbImageUrl: String) {
var newCap: [String] = []
newCap.append(caption)
newCap.insert(contentsOf: tags, at: newCap.endIndex)
let newCaption = newCap.joined(separator: " ")
print (newCaption)
AuthManager.shared.loadUser()
guard let instagramAccountId = AuthManager.shared.currentUser?.id else {return}
let timeStamp = NSDate().timeIntervalSince1970
if !self.TrueStory {
StoryManager().addNewTask("POST", "Post", time, self.ImageURL)
print("Scheduled Post" + self.ImageURL)
// let notificationID = notificationIdentifier
//tags.insert(caption, at: tags.firstIndex)
let param = ["uuid": uuid, "time": time, "mediaType": mediaType, "media": media, "instagramAcctId": instagramAccountId, "caption": newCaption, "tags": "", "latitude": location?.coordinate.latitude ?? "", "longitude":location?.coordinate.longitude ?? "", "thumbnail":thumbImageUrl, "timeStamp":timeStamp, "notificationIdentifier":notificationIdentifier] as [String : Any]
print ("The PARAMS are: ")
print (param)
ServerApi.shared.scheduleIGPosts(param: param, success: {response in
print(response)
ProgressHUD.dismiss()
AppManager.shared.isPostScheduled = true
AppManager.shared.showNext()
// NotificationCenter.default.post(name: .PostWasSuccessfullyScheduled, object: nil, userInfo: ["posted": true])
}, failure: {(error) in
print(error)
self.showAlert(error.description)
ProgressHUD.dismiss()
})
} else if self.TrueStory {
StoryManager().addNewTask("STORY", "Story", time, self.ImageURL)
print("Scheduled Story" + self.ImageURL)
// let notificationID = notificationIdentifier
let param = ["uuid": uuid, "time": time, "mediaType": mediaType, "media": media, "instagramAcctId": instagramAccountId, "caption": caption, "tags": "", "latitude": location?.coordinate.latitude ?? "", "longitude":location?.coordinate.longitude ?? "", "thumbnail":thumbImageUrl, "timeStamp":timeStamp, "notificationIdentifier":notificationIdentifier] as [String : Any]
// "notificationID":notificationIdentifier
ServerApi.shared.scheduleIGPosts(param: param, success: {response in
print(response)
ProgressHUD.dismiss()
AppManager.shared.isPostScheduled = true
AppManager.shared.showNext()
// NotificationCenter.default.post(name: .PostWasSuccessfullyScheduled, object: nil, userInfo: ["posted": true])
}, failure: {(error) in
print(error)
self.showAlert(error.description)
ProgressHUD.dismiss()
})
}
}
And the "ScheduleIGPost" function for your entertainment:
import Foundation
import SwiftyJSON
import Alamofire
struct AppUrls {
static let baseUrl = URL that I wont disclose
static let registerIGAccounts = baseUrl + "register"
static let scheduleIGPosts = baseUrl + "schedule"
static let updateIGPosts = baseUrl + "update-schedule"
static let removeIGPosts = baseUrl + "remove-schedule"
}
class ServerApi {
static let shared = ServerApi()
func scheduleIGPosts(param: [String: Any], success: #escaping(JSON) -> Void, failure: #escaping(JSON) -> Void) {
ApiWrapper.requestPOSTURLWithoutToken(AppUrls.scheduleIGPosts, params: param, success: {(response) in
print(JSON(response))
success(JSON(response))
}, failure: { (error) in
let err = JSON(error)
print(err)
failure(err)
})
}
I did check and see if "param" included "notificationIdentifier" when sending to GCF and it does, but if I check the logs in GCF, I can see everything that's supposed to be except for "notificationIdentifier". And when I replace, for example, "tags" with the "notificationIdentifier", then it works.
I'm unsure if Firestore/Firebase has a limit of elements or not and why this behaviour is happening. To be honest, I couldn't find much information online.
Feel free to ask any questions if I was unclear, as I tend to be!
This was solved quite simply, the app is using a Cloud Function called "API" which is used before accessing the "Schedule" function. So changed the values (or rather added the values) and everything is working fine now.

This.localStream is null

I'm trying to develop and application that allow to a medic and a patient be able to communicate using an Api called connectycube, the chat and video call work, the problem is with to mute sound and video. I have implemented the buttons to mute sound and video, all this using jQuery dialogs, the first time I mute audio or video works, but when I close the dialog finishing the session and then I open the dialog with a new session, to mute audio and video do not work anymore and the message in the console is This.localStream is null
My Source Code:
const CREDENTIALS = {
appId: 'xxxxx',
authKey: 'xxxxx',
authSecret: 'xxxxx'
};
ConnectyCube.init(CREDENTIALS);
//This is a button in a main jquery dialog, this is the beginning of all
{
text: 'VideoCall',
click: function () {
$('#dv_progess').html('<div class="dv_progress">Connecting</div>').dialog('open');
ConnectyCube.createSession().then((session) => {
$('#dv_progess').dialog('close');
signup_user();
$('#dv_videocall').dialog('option', 'position', {my: 'right top', at: 'right top', of: window}).dialog('open');
}).catch((error) => {
console.log('Error=>' + JSON.stringify(error));
$('#dv_progess').dialog('close');
$('#dv_message').html('Error=>' + JSON.stringify(error)).dialog('open');
});
}
},
function signup_user() {
var login = 'P' + $('#hd_idusr').val();
/*Buscar si existe usuario registrado en la API*/
$('#dv_progress').html('<div class="dv_progress">Connecting</div>').dialog('open');
ConnectyCube.users.get({login: login}).then((result) => {
console.log('User Exists:' + result.user.id);
$('#dv_progress').dialog('close');
chat();
}).catch((error) => {
$('#dv_progress').dialog('close');
console.log('User not exists [' + error.info.message + ']');
var password = $('#txt_birthdate').val().replace(/-/g, '') + '*';
var email = $('#hd_email').val();
email = email ? email : login + '#email.com';
const userProfile = {
login: login,
password: password,
full_name: $('#txt_names').val(),
email: email
};
$('#dv_progress').html('<div class="dv_progress">Connecting</div>').dialog('open');
ConnectyCube.users.signup(userProfile).then((data) => {
console.log('ok=>' + data.user.id);
$('#dv_progress').dialog('close');
chat();
}).catch((error) => {
console.log('Error=>' + JSON.stringify(error));
$('#dv_progress').dialog('close');
$('#dv_messages').html('Error=>' + JSON.stringify(error)).dialog('open');
});
});
}
function chat() {
$('#dv_progress').html('<div class="dv_progress">Connecting</div>').dialog('open');
var login_patient = 'P' + $('#hd_idusr').val();
ConnectyCube.users.get({login: login_patient}).then((result) => {
$('#dv_progress').dialog('close');
var id_patient = result.user.id;
$('#hd_idpatient').val(id_patient);
const userCredentials = {
login: 'S' + $('#txt_medic').attr('data-id-user'),
password: $('#txt_medic').attr('data-psw')
};
$('#dv_progress').html('<div class="dv_progress">Connecting</div>').dialog('open');
ConnectyCube.createSession(userCredentials).then((session) => {
$('#dv_progress').dialog('close');
console.log(JSON.stringify(session));
console.log('Medic Created session');
$('#dv_progress').html('<div class="dv_progress">Connecting</div>').dialog('open');
ConnectyCube.login(userCredentials).then((user) => {
var id_professional = user.id;
console.log('Medic login succesful=>' + id_professional);
$('#hd_idprofessional').val(id_professional);
const chatCredentials = {
userId: id_professional,
password: $('#txt_medic').attr('data-psw')
};
$('#dv_progress').html('<div class="dv_progress">Connecting</div>').dialog('open');
ConnectyCube.chat.connect(chatCredentials).then(() => {
$('#dv_progress').dialog('close');
console.log('Medic Connected to chat');
console.log('Id Paciente:' + id_patient);
const dialogParams = {
type: 3,
occupants_ids: [id_patient]
};
$('#dv_progress').html('<div class="dv_progress">Connecting</div>').dialog('open');
ConnectyCube.chat.dialog.create(dialogParams).then(dialog => {
$('#dv_progress').dialog('close');
console.log(JSON.stringify(dialog));
console.log('Dialog Created:' + dialog._id);
$('#hd_iddialog').val(dialog._id);
$('#dv_messagearea').prop('contenteditable', true);
$('#btn_sendmsg,#btn_startvideocall,#btn_finishvideocall').prop('disabled', false);
}).catch(error => {
console.log('Error=>' + JSON.stringify(error));
$('#dv_progress').dialog('close');
$('#dv_messages').html('Error=>' + JSON.stringify(error)).dialog('open');
});
}).catch((error) => {
console.log('Error:' + JSON.stringify(error));
$('#dv_progress').dialog('close');
$('#dv_messages').html('Error:' + JSON.stringify(error)).dialog('open');
});
}).catch((error) => {
console.log('Error:' + JSON.stringify(error));
$('#dv_progress').dialog('close');
$('#dv_messages').html('Error:' + JSON.stringify(error)).dialog('open');
});
}).catch((error) => {
console.log('Error=>' + JSON.stringify(error));
$('#dv_progress').dialog('close');
$('#dv_messages').html('Error=>' + JSON.stringify(error)).dialog('open');
});
/*Fin Login Medico*/
}).catch((error) => {
console.log('Error=>' + JSON.stringify(error));
$('#dv_progress').dialog('close');
$('#dv_messages').html('Error=>' + JSON.stringify(error)).dialog('open');
});
}
function onMessage(userId, message) {
console.log('[ConnectyCube.chat.onMessageListener] callback:', userId, message);
var dv_message = $('#dv_messageschat');
dv_message.append('<div><b>Patient:</b>' + message.body + '</div>');
dv_message.scrollTop(dv_message[0].scrollHeight);
}
function isTyPing(isTyping, userId, dialogId) {
console.log("[ConnectyCube.chat.onMessageTypingListener] callback:", isTyping, userId, dialogId);
}
function sendMessage() {
ConnectyCube.chat.sendIsStopTypingStatus($('#hd_idpatient').val());
var mensaje = $('#dv_messagearea').text();
const message = {
type: 'chat',
body: mensaje,
extension: {
save_to_history: 1,
dialog_id: $('#hd_iddialog').val()
},
markable: 1
};
message.id = ConnectyCube.chat.send($('#hd_idpatient').val(), message);
var dv_message = $('#dv_messageschat');
dv_message.append('<div><b>Yo:</b>' + mensaje + '</div>');
dv_message.scrollTop(dv_message[0].scrollHeight);
$('#dv_messagearea').html('');
}
$('#dv_messagearea').keypress(function (e) {
ConnectyCube.chat.sendIsTypingStatus($('#hd_idpatient').val());
setTimeout(function () {
ConnectyCube.chat.sendIsStopTypingStatus($('#hd_idpatient').val());
}, 1000);
if (e.keyCode == 13) {
sendMessage();
return false;
}
});
function startVideo() {
const calleesIds = [$('#hd_idprofessional').val(), $('#hd_idpatient').val()]; /*User's ids*/
const sessionType = ConnectyCube.videochat.CallType.VIDEO;
const additionalOptions = {};
const session = ConnectyCube.videochat.createNewSession(calleesIds, sessionType, additionalOptions);
const mediaParams = {
audio: true,
video: true,
options: {
muted: true,
mirror: true
}
};
session.getUserMedia(mediaParams).then((localStream) => {
console.log(JSON.stringify(localStream));
session.attachMediaStream('vd_video1', localStream);
/*Iniciar la llamada*/
const extension = {};
session.call(extension, (error) => {
console.log(JSON.stringify(error));
});
$('#btn_finishvideocall').on('click', {x: session}, finishCall);
}).catch((error) => {
console.log(JSON.stringify(error));
});
}
function finishCall(e) {
const extension = {};
e.data.x.stop(extension);
/*Clean local stream*/
var videoElem1 = document.getElementById('vd_video1'),
stream1 = videoElem1.srcObject;
if (stream1 != null) {
var tracks = stream1.getTracks();
tracks.forEach(function (track) {
track.stop();
});
videoElem1.srcObject = null;
}
/*Clean remote stream*/
var videoElem2 = document.getElementById('vd_video2'),
stream2 = videoElem2.srcObject;
if (stream2 != null) {
var tracks = stream2.getTracks();
tracks.forEach(function (track) {
track.stop();
});
videoElem2.srcObject = null;
}
}
$('#dv_controllsvideocall').find('button').prop('disabled', true);
$('#btn_mutesound,#btn_mutevideo').hide();
function setSound(e) {
const session = e.data.x;
if (e.data.y == 'mute') {
$('#btn_mutesound').show();
$('#btn_unmutesound').hide();
session.mute('audio');
console.log('muted audio');
} else {
$('#btn_mutesound').hide();
$('#btn_unmutesound').show();
session.unmute('audio');
console.log('unmuted audio');
}
}
function setVideo(e) {
const session = e.data.x;
if (e.data.y == 'mute') {
$('#btn_mutevideo').show();
$('#btn_unmutevideo').hide();
session.mute('video');
console.log('muted video');
} else {
$('#btn_mutevideo').hide();
$('#btn_unmutevideo').show();
session.unmute('video');
console.log('unmuted video');
}
}
function acceptedCall(session, userId, extension) {
console.log('Accepted call');
$('#dv_controllsvideocall').find('button').prop('disabled', false);
}
function setStream(session, userID, remoteStream) {
console.log('stream assigned');
session.attachMediaStream('vd_video2', remoteStream);
$('#btn_mutesound').on('click', {x: session, y: 'unmute'}, setSound);
$('#btn_unmutesound').on('click', {x: session, y: 'mute'}, setSound);
$('#btn_mutevideo').on('click', {x: session, y: 'unmute'}, setVideo);
$('#btn_unmutevideo').on('click', {x: session, y: 'mute'}, setVideo);
}
function onStopCall(session, userId, extension) {
console.log('Finished Call');
}
ConnectyCube.chat.onMessageListener = onMessage;
ConnectyCube.chat.onMessageTypingListener = isTyPing;
ConnectyCube.videochat.onAcceptCallListener = acceptedCall;
ConnectyCube.videochat.onRemoteStreamListener = setStream;
ConnectyCube.videochat.onStopCallListener = onStopCall;
$('#btn_sendmsg').click(function () {
sendMessage();
});
$('#btn_startvideocall').click(function () {
startVideo();
});
$('#btn_exitvideocall').click(function () {
$('#dv_videocall').dialog('close');
});
/*Dialog for video call*/
$('#dv_videocall').dialog({
autoOpen: false,
resizable: false,
height: 600,
width: 220,
modal: false,
close: function () {
$(this).find('input').val('');
$('#dv_messagearea').prop('contenteditable', false).html('');
$('#dv_messageschat').html('');
$('#btn_sendmsg,#btn_startvideocall,#btn_finishvideocall').prop('disabled', true);
$('#dv_controllsvideocall').find('button').prop('disabled', true);
if (ConnectyCube.chat.isConnected) {
$('#btn_finishvideocall').trigger('click');
ConnectyCube.chat.disconnect();
ConnectyCube.logout().catch((error) => {
console.log('logout=>' + JSON.stringify(error));
});
ConnectyCube.destroySession().catch((error) => {
console.log('destroySession=>' + JSON.stringify(error));
});
}
}
});
$(window).bind('beforeunload', function () {
if (ConnectyCube.chat.isConnected) {
$('#btn_finishvideocall').trigger('click');
ConnectyCube.chat.disconnect();
ConnectyCube.logout().catch((error) => {
console.log('logout=>' + JSON.stringify(error));
});
ConnectyCube.destroySession().catch((error) => {
console.log('destroySession=>' + JSON.stringify(error));
});
}
});
I think the problem is in the function finishCall() when I clean the video tag and I don't know if that is the right way to free the resources. Despite this the chat and video call still work.
If someone has experience please help me, becasue I didn't found any solution, thanks in advance.

How to fix "_filePath.includes is not a function. ( In '_filePath.includes('&'), '_filePath.includes' is undefined)" in React Native?

I am trying to upload an image to Firebase Storage, however, ref.putfile() leads to the error in the tittle
I didn't find any appropriate resource related to this error
This is where I get image from user:
openPicker = () => {
// More info on all the options is below in the API Reference... just some common use cases shown here
const options = {
title: 'Fotoğraf Seç',
storageOptions: {
skipBackup: true,
path: 'images',
},
};
ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
}
else if (response.error) {
console.log('ImagePicker Error: ', response.error);
}
else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
}
else {
const source = { uri: response.uri}
this.setState({
imageMessageSrc: source
});
this.uploadImage();
}
});
}
Then I try to uploadImage to firebase
uploadImage = () => {
console.log("Here");
const filename = this.randIDGenerator// Generate unique name
firebase
.storage()
.ref(`${firebase.auth().currentUser.uid}/sentPictures/${filename}`)
.putFile(this.state.imageMessageSrc)
.then(() => {
console.log("Here1");
})
.catch((error) => {
console.log(error);
})
When I delete putFile, error is gone, but obviously nothing happens to database.
Problem is related to the difference between filePath and fileUri. So, the solution is as below:
openPicker = () => {
const options = {
title: 'Fotoğraf Seç',
storageOptions: {
skipBackup: true,
path: 'images',
allowsEditing: true,
},
};
ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
}
else if (response.error) {
console.log('ImagePicker Error: ', response.error);
}
else if (response.customButton) {
console.log('User tapped custom button: ',response.customButton);
}
else {
var path = '';
if (Platform.OS == 'ios')
path = response.uri.toString();
else {
path = response.path.toString();
}
const image= {
image: response.uri.toString(),
path: path
};
this.uploadImage(image);
}
});
}
uploadImage = (image) => {
firebase.storage().ref(uploadUrl).putFile(image.path);
}
I realized that Firebase Storage putFile function doesn't work with image uri, instead it should be supplied with filePath. I used uri of this image to directly show image on the screen even before upload.

Loopback remoteMethod with onesignal push notification

i still learn, and trying to be learn. im looking for trying hard remote method on loopback 3 for push notification to specific user with onesignal.
any wrong in my code ?
because always :
Error: [ 'All included players are not subscribed' ]
My Case :
im using ionic 3 framework
loopback 3 (or latest)
2 User, (Customer & Seller)
Customer buying product from thread's seller.
If success to order, the seller will receive the notification.
and This is My code :
Ajiorder.observe('after save', function (ctx, next) {
console.log('Order', ctx.instance);
let postingModel = app.models.AjiPosting;
let userAuth = app.models.AjiUserAuth;
postingModel.find({
where:
{ id: ctx.instance.id }
}, function (err, success) {
console.log(success, 'SUKSES');
if (ctx.instance) {
let dataFilter = [];
dataFilter.push({
'field': 'tag',
'key': 'id',
'relation': '=',
'value': success[0].id
});
console.log(success[0].idSeller, 'ID TOT')
console.log(dataFilter, 'dataFilter');
let data = {
idSeller: ctx.instance.idSeller
}
console.log(data, 'Data');
userAuth.find({
where:
{ id: ctx.instance.idCustomer }
}, function (err, result) {
console.log(result, 'Data Personal');
let content = result[0].namaLengkap + ' ' + 'Order your product';
console.log(content, 'Nama Order');
console.log(ctx.instance.idSeller, 'My Dream', success[0].id);
if (ctx.instance.id != success[0].id) {
console.log('Spirit');
sendMessage(dataFilter, content, data);
}
})
}
next();
});
});
var sendMessage = function (device, message, data) {
var restKey = 'XXXXXXXXXXXXXXXXXX';
var appID = 'XXXXXXXXXXXXXXXXX';
request(
{
method: 'POST',
uri: 'https://onesignal.com/api/v1/notifications',
headers: {
'authorization': 'Basic ' + restKey,
'content-type': 'application/json'
},
json: true,
body: {
'app_id': appID,
'filters': device,
'data': data,
'contents': { en: message }
}
},
function (error, response, body) {
try {
if (!body.errors) {
console.log(body);
} else {
console.error('Error:', body.errors);
}
} catch (err) {
console.log(err);
}
}
)
}
};
and i got this error :
Error: [ 'All included players are not subscribed' ]
Picture : Picture of Console Log Here
any one can help me ?
sorry for my english too bad.
Greetings
Solved !
I'm Forget to add some code from onesignal. thanks

How to test node.js-mongodb app using Mocha, Chai and Sinon? I am having difficulty with Sinon part

I am new to testing and having difficulty with Sinon stubs and mocks.
How can I write test for 'quote.list_quote' for following senario.
Here is the routes file : quotes.js
const express = require('express');
const request = require('request');
const async = require('async');
const validator = require('validator');
const quote_router = express.Router();
const confg = require("../../confg/confg");
const quote = require("../models/mquotes");
const quotes_model = quote.quotes;
// host name - needs to be set up using the environment variable
const hostname = confg.hostname;
// route for "quotes/"
quote_router.route("/")
// get route : display the random quote
.get((req, res) => {
// display random quote
async.waterfall([
(callback) => {callback(null, {res});},
quote.count_quotes
], check_quote_exist
);
})
// post route : create a new quote
.post((req, res) => {
const doc_json = {author : validator.escape(req.body.quote_author), quote_text : validator.escape(req.body.quote_text)};
const params = {res, doc_json, quote_action : quote.create_quote};
add_edit_quote(params);
})
// put route : edit the quote
.put((req, res) => {
const doc_json = {author : validator.escape(req.body.quote_author), quote_text : validator.escape(req.body.quote_text)};
const params = {res, doc_json, quote_action : quote.update_quote, qid : req.body.quote_id};
add_edit_quote(params);
})
// delete quote : delete the quote
.delete((req, res) => {
const qid = req.body.qid;
const condition = {_id : qid};
async.waterfall([
(callback) => {callback(null, {res, condition});},
quote.delete_quote
], request_quote_list
);
});
// route for "quotes/list" : display quotes list
quote_router.get("/list/", (req, res) => {
// mention the main operation
let operation;
if(req.body.operation != 'undefined') {
operation = req.body.operation;
} else {
operation = "list_quotes";
}
async.waterfall([
(callback) => {callback(null, {res, operation});},
quote.list_quote
], display_quotes_list
);
});
// display the quotes list
const display_quotes_list = (err, params, quotes_list) => {
if (err) {return console.log(err);}
const res = params.res;
const operation = params.operation;
const header_msg = "List of all the quotes";
let alert_msg;
if(operation == "list_quotes") {
alert_msg = null;
} else if(operation == "delete_quote") {
alert_msg = "Quote has been deleted";
}
const params_out = {
page: "quote_list",
title: 'Quotes Manager',
host: hostname,
header_msg,
alert_msg,
quotes_list
};
res.render('index', params_out);
};
// send http request for quote list page
const request_quote_list = (err, params) => {
if (err) {return console.log(err);}
const res = params.res;
const operation = "delete_quote";
request.get('http://' + hostname + '/quotes/list/', {json:{operation}},
(error, response, body) => {
if (!error && response.statusCode == 200) {
res.send(body);
}
});
};
module.exports = quote_router;
This is not complete file. I have included only a portion of it.
And her is the model file : mquotes.js
const mongoose = require('mongoose');
// Define quote schema
const quoteSchema = new mongoose.Schema({
author: String,
quote_text: {type: String, required: true}
},
{timestamps: true}
);
const quote = {};
// Define quotes model
quote.quotes = mongoose.model('quotes', quoteSchema);
// error handler
error_handler = (callback, err, params, return_value) => {
if(err) { return callback(err);}
else {callback(null, params, return_value);}
};
// add quote - create
quote.create_quote = (params, callback) => {
const res = params.res;
const doc_json = params.doc_json;
quote.quotes.create(doc_json, (err, quotes_detail) => {
error_handler(callback, err, {res, operation : 'create_quote'}, quotes_detail);
});
};
// count the number of quotes
quote.count_quotes = (params, callback) => {
quote.quotes.count({}, (err, quotes_count) => {
error_handler(callback, err, params, quotes_count);
});
};
// delete quote - delete - id
quote.delete_quote = (params, callback) => {
quote.quotes.remove(params.condition, (err, query) => {
error_handler(callback, err, params);
});
};
// list quote - find
quote.list_quote = (params, callback) => {
quote.quotes.find({}, (err, quotes_list) => {
error_handler(callback, err, params, quotes_list);
});
};
// find quote by id
quote.quote_by_id = (params, callback) => {
quote.quotes.findById(params.qid, (err, quotes_detail) => {
error_handler(callback, err, params, quotes_detail);
});
};
// returns the detail of random quote
quote.random_qoute = (params, callback) => {
const random_number = params.random_number;
// select one quote after skipping random_number of times
quote.quotes.findOne({}, (err, quotes_detail) => {
error_handler(callback, err, params, quotes_detail);
}).skip(random_number);
};
// update quote - update - id
quote.update_quote = (params, callback) => {
const options = {new: true};
const qid = params.qid;
const update_json = params.doc_json;
quote.quotes.findByIdAndUpdate(qid, {$set: update_json}, options, (err, quotes_detail) => {
params.operation = 'update_quote';
error_handler(callback, err, params, quotes_detail);
});
};
module.exports = quote;
I have installed mocha globally. Now, I want to test the model. Lets take the quote.list_quote function for example.
const mongoose = require('mongoose');
const chai = require('chai');
const sinon = require('sinon');
const expect = chai.expect; // use the "expect" style of Chai
const mquotes = require('./../../app/models/mquotes');
describe('Tests for quote models', () => {
describe("List quote", () => {
it('list_quote() should return list of quotes', () => {
});
});
});
Can anyone tell me about my coding practice too. I mean the way I use functions and modules.
First of all, you should try to use statics methods. And after that, you should use sinon-mongoose and sinon-as-promised if you want to use Promise in mongoose.
And this is my sample code and test with mocha, chai, and sinon. Hope useful for you.
model.js
var Schema = new mongoose.Schema({
name: String,
created_at: {
type: Date,
default: Date.now
},
updated_at: {
type: Date,
default: Date.now
}
});
Schema.statics.findByName = function(name, cb) {
this.findOne({
name: name
})
.exec()
.then(function getTemplate(template) {
if (!template) {
var error = new Error('Not found template by name: "' + name + '"');
error.status = 404;
return cb(error);
}
return cb(null, template);
})
.catch(function catchErrorWhenFindByTemplateName(error) {
error.status = 500;
return cb(error);
});
}
module.exports = mongoose.model('model', Schema);
test.js
var expect = require('chai').expect,
sinon = require('sinon'),
mongoose = require('mongoose');
require('sinon-as-promised');
require('sinon-mongoose');
var Model = require('../../app/models/model');
describe('Model', function () {
describe('static methods', function () {
describe('#findByName', function () {
var ModelMock;
beforeEach(function () {
ModelMock = sinon.mock(Model);
});
afterEach(function () {
ModelMock.restore();
});
it('should get error status 404 if not found template', function (done) {
var name = 'temp';
ModelMock
.expects('findOne').withArgs({name: name})
.chain('exec')
.resolves(null);
Model.findByName(name, function (error) {
expect(error.status).to.eql(404);
ModelMock.verify();
done();
});
});
it('should get message not found template if name is not existed', function (done) {
var name = 'temp';
ModelMock
.expects('findOne').withArgs({name: name})
.chain('exec')
.resolves(null);
Model.findByName(name, function (error) {
expect(error.message).to.match(/Not found template by name/gi);
ModelMock.verify();
done();
});
});
it('should get template when name is existed', function (done) {
var name = 'temp';
ModelMock
.expects('findOne').withArgs({name: name})
.chain('exec')
.resolves('SUCCESS');
Model.findByName(name, function (error) {
expect(error).to.be.null;
ModelMock.verify();
done();
});
});
it('should get error status 500 when model crashed', function (done) {
var name = 'temp';
ModelMock
.expects('findOne').withArgs({name: name})
.chain('exec')
.rejects(new Error('Oops! Crashed'));
Model.findByName(name, function (error) {
expect(error.status).to.eql(500);
ModelMock.verify();
done();
});
});
});
});
});