I am creating a project where I can read messages of gmail. I am having problem to display list of messages. I've just quickstart sample code of getting labels.
https://developers.google.com/gmail/api/quickstart/js#step_1_set_up_the_sample
<!DOCTYPE html>
<html>
<head>
<title>Gmail API Quickstart</title>
<meta charset="utf-8" />
</head>
<body>
<p>Gmail API Quickstart</p>
<button id="authorize_button" onclick="handleAuthClick()">Authorize</button>
<button id="signout_button" onclick="handleSignoutClick()">Sign Out</button>
<pre id="content" style="white-space: pre-wrap;"></pre>
<script type="text/javascript">
const CLIENT_ID = 'XXXXX-XXXXXXXXXXXXX.apps.googleusercontent.com';
const API_KEY = 'XXXXXXXXXXXXXXXX';
const DISCOVERY_DOC = 'https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest';
const SCOPES = 'https://www.googleapis.com/auth/gmail.readonly';
let tokenClient;
let gapiInited = false;
let gisInited = false;
document.getElementById('authorize_button').style.visibility = 'hidden';
document.getElementById('signout_button').style.visibility = 'hidden';
function gapiLoaded() {
gapi.load('client', intializeGapiClient);
}
async function intializeGapiClient() {
await gapi.client.init({
apiKey: API_KEY,
discoveryDocs: [DISCOVERY_DOC],
});
gapiInited = true;
maybeEnableButtons();
}
function gisLoaded() {
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: CLIENT_ID,
scope: SCOPES,
callback: '', // defined later
});
gisInited = true;
maybeEnableButtons();
}
function maybeEnableButtons() {
if (gapiInited && gisInited) {
document.getElementById('authorize_button').style.visibility = 'visible';
}
}
function handleAuthClick() {
tokenClient.callback = async (resp) => {
if (resp.error !== undefined) {
throw (resp);
}
document.getElementById('signout_button').style.visibility = 'visible';
document.getElementById('authorize_button').innerText = 'Refresh';
await listLabels();
};
if (gapi.client.getToken() === null) {
tokenClient.requestAccessToken({prompt: 'consent'});
} else {
tokenClient.requestAccessToken({prompt: ''});
}
}
function handleSignoutClick() {
const token = gapi.client.getToken();
if (token !== null) {
google.accounts.oauth2.revoke(token.access_token);
gapi.client.setToken('');
document.getElementById('content').innerText = '';
document.getElementById('authorize_button').innerText = 'Authorize';
document.getElementById('signout_button').style.visibility = 'hidden';
}
}
async function listLabels() {
let response;
try {
response = await gapi.client.gmail.users.labels.list({
'userId': 'me',
});
} catch (err) {
document.getElementById('content').innerText = err.message;
return;
}
const labels = response.result.labels;
if (!labels || labels.length == 0) {
document.getElementById('content').innerText = 'No labels found.';
return;
}
const output = labels.reduce(
(str, label) => `${str}${label.name}\n`,
'Labels:\n');
document.getElementById('content').innerText = output;
}
</script>
<script async defer src="https://apis.google.com/js/api.js" onload="gapiLoaded()"></script>
<script async defer src="https://accounts.google.com/gsi/client" onload="gisLoaded()"></script>
</body>
</html>
This code is working fine without any errors.
I want to modify this code and get list of messages. But I am just unable to find right method to get list of messages.
Can someone please help me?
This is the documentation for labels. Compare that with the sample code you have for labels.
Then try to follow the same principle for messages. This is the documentation for messages. Following bullet 1, the code to get the list of messages might be something like
gapi.client.gmail.users.messages.list({'userId': 'me'});
You can work out how to parse the response from the linked documentation
Update:
The documentation says
each message resource contains only an id and a threadId. Additional message details can be fetched using the messages.get method.
This means you have to do something like
gapi.client.gmail.users.messages.get({
'userId': 'me',
'id' : <message_id>
});
Related
I am trying to build a chat app. In the first step the user sends username and if the name is not already existing is logged in. Then can send a message to another user, here comes the error, after the first messages the server sends to the other clients (except the one the message came from) this message but it gets duplicated and the more messages I send the number of duplicates seems to multiply.
I tried so much changes, including sending back the message from server to all client including the one it originated from, but cannot find a solution for these duplicates --- please help me!
(built with bootstrap & jQuery)
Tried sending a message from user to server, UI shows the message to user and server sends message to all other connected users except the one it came from, all other users should see the message too then on their UI
Here is the HTML & CSS UI:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<link rel="stylesheet" href="styles.css">
<style>
.formular {
width: 90%;
position: fixed;
bottom: 0;
}
li {list-style: none;}
#header {position: fixed;
top: 0}
#msgDisplay {padding-top: 2em;}
</style>
<title>Document</title>
</head>
<body>
<div class="container" id="header">
WEBSOCKETS
</div>
<div class="container mt-3" id="msgDisplay">
<ul class="messages">
</ul>
<form action="?" class="formular">
<input type="text" class="input" id="input">
<button type="button" class="btn btn-primary" >Login</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.6.1.min.js"
integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script>
<script src="app.js">
</script>
</body>
</html>
Here is the user JavaScript:
let scrollBottom = () => {
window.scrollTo(0, 999999);
let heightForm = document.querySelector('.formular').offsetHeight;
document.querySelector('.messages').style.paddingBottom = heightForm + 'px';
};
let showMessage = (msg) => {
console.log('MSG DISPLAY: ', msg)
$('.messages').append($('<li>').html(msg))
scrollBottom()
}
let sendmessageF = () => {
ws.send($('#input').val());
$('.input').val(''); // Eingabe leeren
}
window.onresize = scrollBottom;
let username = '';
let ws;
let wsOK = false;
let submitF = (e) => {
e.preventDefault();
if (username == '') {
username = $('.input').val();
if (wsOK == false) {
// Create WebSocket connection.
ws = new WebSocket('ws://localhost:5041');
ws.binaryType = 'blob';
// Connection opened
ws.addEventListener('open', (e) => {
e.preventDefault()
console.log('NEW SOCKED OPENED', e)
console.log('NEW USER: ', username)
ws.send(JSON.stringify({ req: '/login', user: username }))
wsOK = true;
});
}
}
else if (username != ''){
ws.send(JSON.stringify({ req: '/message', message: $('.input').val() }))
showMessage($('.input').val())
}
// Listen for messages
ws.addEventListener('message', (event) => {
console.log('Message from server => ', event.data);
if (event.data instanceof Blob) {
let reader = new FileReader(); // UM BLOB AUSZULESEN
reader.readAsText(event.data)
reader.onload = () => {
console.log("Result BLOB: " + reader.result);
showMessage('BLOB: ', reader.result)
};
}
else if (JSON.parse(event.data) instanceof Object){
let msg = JSON.parse(event.data);
console.log('SERVER MSG: ', msg)
if(msg.itype == 'loginSuccess'){
showMessage(msg.res)
$('.btn').html('Senden')
username = msg.res.split(':')[1].trim()
console.log('USERNAME: ', username)
}
else if (msg.itype == 'loginFail'){
showMessage(msg.res)
username = '';
wsOK = false;
ws.destroy()
}
else if (msg.itype == 'valUserMsg'){
console.log('HIER ???')
showMessage(msg.res)
}
}
});
}
$('.btn').click(submitF)`
Here is the node.js Server:
const express = require('express'); // NPM INSTALLEREN
const app = express();
const PORT = process.env.PORT || 5041;
const server = require('http').createServer(app)
const fs = require('fs');
const bodyParser = require('body-parser'); // NPM INSTALLEREN
const WebSocket = require('ws') // NPM INSTALLEREN
const wss = new WebSocket.Server({ server: server })
// const Random = require('./modules/random.js');
server.listen(PORT, () => {
console.log('SERVER PORT: ', PORT)
})
app.use(express.static('www'));
app.use(bodyParser.text({ type: 'text/xml' }));
app.use(bodyParser.json({ type: '*/*' }));
let wsConns = [];
let allUser = [];
wss.on('connection', (wsConn) => { // wsConn ORIGIN
console.log('NEUER CLIENT CONNECTED')
let username = '';
wsConn.on('message', (message) => {
let msgReceived = JSON.parse(message)
console.log('MESSAGE RECEIVED: ', msgReceived)
if (msgReceived.req == '/login') {
username = msgReceived.user
if (allUser.indexOf(username) == -1) {
allUser.push(username)
wsConns.push(wsConn)
console.log('ALLUSER: ',allUser)
console.log('WSCONNS: ',wsConns.length)
wsConn.send(JSON.stringify({itype:'loginSuccess',res:`Username akzeptiert: ${username}`}))
}
else {
wsConn.send(JSON.stringify({itype:'loginFail',res:'Username schon vergeben!'}))
}
}
else if (msgReceived.req == '/message'){
console.log('HIER???')
wss.clients.forEach((client)=>{ // anstatt wss.clients würde auch wsConns gehen (Arr mit allen Conn)
if(client !== wsConn && client.readyState === WebSocket.OPEN){
client.send(JSON.stringify({itype:'valUserMsg',res: msgReceived.message }))
}
})
console.log('WSCONNS: ',wsConns.length)
}
})
})
use ws.onmessage = ()... instead of ws.addEventListener('message', ...
Javascript / Node.js importing html file
I'm making a node.js server which sends emails on demand. The variable "output" is what I want to send via email. When I use inline html it works fine, however I want to import a complete html file instead.
const { EmailClient } = require("#azure/communication-email");
const connectionString = "<ACS_CONNECTION_STRING>";
const sender = "<SENDER_EMAIL>";
const toRecipients = {
to: [
{ email: "<alice#contoso.com>", displayName: "Alice" },
],
};
const client = new EmailClient(connectionString);
const emailContent = {
subject: "Send email plain text - JS sample",
plainText: "",
// html: "<h3>Hi, this works</h3>", // WORKS
// html: "<object type="text/html" data="file.html"></object>", // // Doesn't work
html: "<link href="file.html" rel="import" />", // // Doesn't work
};
async function main() {
try {
const emailMessage = {
sender: sender,
content: emailContent,
importance: 'low',
recipients: toRecipients,
};
const sendResult = await client.send(emailMessage);
if (sendResult && sendResult.messageId) {
const messageId = sendResult.messageId;
if (messageId === null || messageId === undefined) {
console.log("Message Id not found.");
return;
}
console.log("Send email success, MessageId :", messageId);
let counter = 0;
const statusInterval = setInterval(async function () {
counter++;
try {
const sendStatusResult = await client.getSendStatus(messageId);
if (sendStatusResult) {
console.log(`Email status for {${messageId}} : [${sendStatusResult.status}]`);
if (sendStatusResult.status.toLowerCase() !== "queued" || counter > 12) {
clearInterval(statusInterval);
}
}
} catch (e) {
console.log("Error in checking send mail status: ",e);
}
}, 5000);
} else {
console.error("Something went wrong when trying to send this email: ", sendResult);
}
} catch (e) {
console.log("################### Exception occurred while sending email #####################", e);
}
}
main();
Help is much appreciated.
You can use fs.readFileSync to import your HTML file as a string.
const emailContent = {
...
html: fs.readFileSync('./file.html', 'utf8'),
...
}
I am trying to check if the oAuth token currently associated to the user's account is still valid before running a refresh of the oAuth to reduce the number of oAuth refresh calls sending into the system. The only issue is, with my current setup, the process isn't running before the code that follows it which requires a valid oAuth to properly execute causing uncaught errors. How can I in the Node.js server have it so this process must complete before the async function continues and have it properly check/refresh the token?
Tech used:
Google Firebase
Node.js
Express
app.post('[redacted]', async (req, res) => {
if (req.body.token != '[redacted]') {
res.status(500).end()
return
}
let globalConfig;
let oAuthToken;
const cityRef = db.collection('orgsAndConfigs').doc(`${req.body.orgId}`);
const doc = await cityRef.get();
if (!doc.exists) {
console.log('No such document!');
} else {
globalConfig = doc.data();
}
async function checkOAuthValid(){
try{
if(!globalConfig.oAuthToken || globalConfig.oAuthToken_expires.toDate() < Date() || !globalConfig.refresh_token){
return true
} else {
return false
}
} catch (e) {
return true
}
}
async function checkoAuth() {
const runoAuth = await checkOAuthValid()
if (runoAuth) {
try {
const params = new url.URLSearchParams({ client_id: '[redacted]', client_secret: '[redacted]', refresh_token: globalConfig.refresh_token, grant_type: 'refresh_token' });
axios.post('https://driftapi.com/oauth2/token', params.toString())
.then(async function (response) {
oAuthToken = response.data.access_token;
const orgDoc = db.collection('orgsAndConfigs').doc(`${req.body.orgId}`);
var oAuthExpires = new Date();
oAuthExpires.setSeconds(oAuthExpires.getSeconds() + 7200);
const resolution = await orgDoc.update({ refresh_token: response.data.refresh_token, oAuthToken: oAuthToken, oAuthToken_expires: Timestamp(oAuthExpires) });
})
} catch (e) {
const orgDoc = db.collection('orgsAndConfigs').doc(`${req.body.orgId}`);
const resolution = await orgDoc.update({ refresh_token: null });
}
} else {
oAuthToken = globalConfig.oAuthToken;
}
}
const tokenAquired = await checkoAuth();
[remainder of the code]
The account address is getting displayed on the console properly when initializing but showing undefined when calling console.log(account) from other functions. Here is my code.
var account;
window.addEventListener('load', async () => {
if (window.ethereum) {
window.web3 = new Web3(ethereum);
ethereum.autoRefreshOnNetworkChange = false;
const accounts = await ethereum.enable();
account = accounts[0];
console.log(account); //here the account working properly.
}
});
var contractaddress = '0x26708Df214A65Dda444E61266642e6650F4e8923';
function get_request_details() {
console.log(account); //here it is showing undefined
}
window.onload = get_request_details;
The problem was arising because the function was running before the initialization can be done and that is why I modified the code as follows.
var account;
window.addEventListener('load', async () => {
if (window.ethereum) {
window.web3 = new Web3(ethereum);
ethereum.autoRefreshOnNetworkChange = false;
const accounts = await ethereum.enable();
account = accounts[0];
console.log(account); //here the account working properly.
get_request_details();
}
});
var contractaddress = '0x26708Df214A65Dda444E61266642e6650F4e8923';
function get_request_details() {
console.log(account); //here it is also working
}
I called the function from the async event only so that when the initialization will be done after than only the function should run.
I don't see the contractaddress variable used anywhere. So here is my opinion.
const get_request_details = function(account) {
console.log(account);
}
const run_after_window_loaded = async function() {
if (!window.ethereum) {
return false;
}
window.web3 = new Web3(ethereum);
ethereum.autoRefreshOnNetworkChange = false;
const accounts = await ethereum.enable();
console.log(accounts);
if(accounts.length > 0){
get_request_details(accounts[0]);
}
}
window.addEventListener('DOMContentLoaded', async function(event) {
await run_after_window_loaded();
});
My program in a nutshell. If the trigger word is detected in the message, my application creates invoices.
The issue: Multiple calls to the trigger function. All of the requests to the API are simultaneous. This causes my data to have problems.
I have added the async and await to wait for the trigger function to complete. But it seems my calls are still being called all together.
// Links to a Facebook Live.
export const fblive = async (liveid) => {
if (liveid != null) {
try {
const reg = new RegExp("\\d{5,}");
const found = liveid.match(reg);
if (found > 0) {
console.log(found, " || ", found[0]);
let activate = false;
var userid = "";
//var accesstoken = ''
var accesstoken =''
var videoID = found;
var live_url =
"https://streaming-graph.facebook.com/" +
videoID +
"/live_comments?access_token=" +
accesstoken +
"&comment_rate=one_hundred_per_second&fields=from{name,id},message";
var source = new EventSource(live_url);
source.onmessage = function (event) {
var result = JSON.parse(event["data"]);
let trigger_word = result["message"].search("#");
// looking at comments
readcomment(result["message"]);
if (result["from"] != null) {
console.log("FROM ! !:", result["from"]);
}
};
} else {
console.log("ZERO FOUND");
}
} catch (error) {
console.log("FB LIVE COMMENT IS NOT RUNNING");
}
} else {
console.log("Live ID not valid");
}
};
// Looking at every comment in a facebook live
export const readcomment = async (the_comment) => {
try {
console.log(" CALLING LIVE READ COMMENT ", the_comment);
let re = await new Promise((resolve) =>
setTimeout(
setTimeout(async function () {
console.log(the_comment);
if (the_comment.includes("#")) {
populatelist();
console.log(the_comment);
let new_string = the_comment.trim().split(" ");
console.log(new_string, " STRING SPLIT");
let customer_found = await findcust(new_string);
let item_found = await finditem(new_string);
console.log(customer_found, item_found, "WE FOUND ");
if (customer_found != false && item_found != false) {
console.log("THERE'S A TRIGGER SALE HERE");
let remove = await find_remov(new_string);
console.log(remove, "WE ARE LOOKING AT RMOVE ");
await comment_trigger(customer_found,item_found,remove)
console.log(the_comment)
console.log("promise for " , the_comment, " has been fullfilled")
}
}
}, 2000)
)
);
} catch (error) {
console.log(error.response)
}
};
// This is when a comment was found to be the triggers words (customer id and a item name)
export const comment_trigger = async (customer, item, rmv) => {
// FIND THE ITEM IN INVOICE.
const client = find(customer, customer_list1);
const real_item = find(item, item_list1);
try {
console.log(client, real_item);
if (client != false && real_item != false) {
let inv = await invoicesbycustomer(client.id);
console.log(inv);
if (inv == undefined || inv.length ==0) {
console.log(customer, item);
console.log(real_item.id);
let new_Invoice = new Invoice("", client);
let new_item = new Product(real_item.id, real_item.name, 1);
await new_Invoice.addItem(new_item);
console.log(new_Invoice);
await createInvoice(new_Invoice);
console.log("NO INVOICE WAS FOUND FOR THIS CLIENT");
} else {
console.log(inv);
// making sure there's a real invoice.
console.log("DATA TYPE IS ", typeof inv);
if (typeof inv !== "undefined") {
console.log(inv, "THIS IS INVOICE WITH CLIENT");
console.log(inv[0].node.items.length);
let oldItems = inv[0].node.items;
let NewInvoice = new Invoice(
inv[0].node.id,
inv[0].node.customer.id
);
let Itemsize = oldItems.length;
let found = false;
if (Itemsize > 0) {
//IF ITEMS EXIST ADD QTY.
// ELSE ADD THIS NEW ITEM.
for (let x in oldItems) {
if (real_item.id == oldItems[x].product.id) {
found = true;
}
}
if (found && rmv == "removeqty") {
await removeqtyitem(customer, item);
} else if (found && rmv == "removeAll") {
await removeitem(customer, item);
} else if (found) {
let aqi = await addqtyitem(customer, item);
} else {
// add item
await additems(customer, item);
}
} else {
await additems(customer, item);
}
}
}
} else {
let errmssg = "";
if (!client) {
errmssg = errmssg.concat(" ", " Client is not valid ");
console.log("client not found", errmssg);
}
if (!real_item) {
errmssg = errmssg.concat("", " Item not found");
}
console.log(errmssg);
console.error(errmssg);
}
} catch (error) {
console.error(error.response.data)
}
};
Here's an example of the api being called. this is using graphql
//DELETING INVOICE API CALL
export const deleteInvoice = async(id) => {
const invoiceId = id;
console.log(invoiceId, "THIS I S INVOICE DELET EDELETE DELETE DELTE ")
try {
const token = "zCtQa00zlorbFFum6I7Rlzc0QwMDoS";
const shema = `
mutation ($input: InvoiceDeleteInput !) {
invoiceDelete(input: $input) {
didSucceed
inputErrors {
path
code
message
}
}
}`;
//About to submit my shema to waveapps
const API_URL="https://gql.waveapps.com/graphql/public"
const bussID = "QnVzaW5lc3M6ZTIyZmVhODEtNjg5OC00N2ZiLTgzOGItYWMyYzllNDZiM2Jk";
let watch = await axios(API_URL, {
method: "POST",
headers: {
Authorization: token ? `Bearer ${token}` : "",
"Content-Type": "application/json",
},
data:{
query: shema,
variables: {
input:{
invoiceId: invoiceId,
}
},
},
})
console.log(watch.data)
} catch (error) {
console.log(error.response)
}
//console.log("return delete invoice complete")
};
I have used async/await and promises.
When multiple calls are made. The await and promises are still being called at the same time. Not sure what else to look at? any suggestions please. I have spent a week on this.