Open aivantg opened 3 years ago
Looking through your readme (amazing documentation btw 🙏 so many useful links for setting up the gmail API), I noticed this part:
I also noticed that the initialize function is called whenever getMessages()
is called.
Does this mean we should start watching and calling initialize on our own to start the process? I'm also curious whether your repo handles the scheduling aspect too. You mention node-scheduler but that's not a dependency so I wasn't sure how it worked. An example would be amazing!
amazing documentation btw 🙏 so many useful links for setting up the gmail API
Thank you. I put a good deal of efforts into writing this doc. By the way I think my choice of word initialize for _initialize()
is somewhat misleading. As you noticed it is called every time getMessages()
method is called, instead of being called once when Gmailpush is instantiated. But you don't have to call gmail.users.watch()
or gmailpush._initialize()
by yourself because Gmailpush deals with them on your behalf.
For Node Schedule it's not part of Gmailpush but you can add it to your code like example below, or do you think it should be included in Gmailpush?
const schedule = require('node-schedule');
const fs = require('fs').promises;
...
app.post(
'/pubsub-push-endpoint',
express.json(),
(req, res) => {
res.sendStatus(200);
const email = gmailpush.getEmailAddress(req.body);
const token = users.find((user) => user.email === email).token;
gmailpush
.getMessages({
notification: req.body,
token
})
.then((messages) => {
console.log(messages);
fs.readFile('./gmailpush_history.json')
.then((result) => {
const prevHistories = JSON.parse(result);
const prevHistory = prevHistories.find((prevHistory) => prevHistory.emailAddress === email);
schedule.scheduleJob(new Date(prevHistory.watchExpiration - 1000 * 60 * 30), async () => {
prevHistory.watchExpiration = await gmailpush._refreshWatch();
fs.writeFile('./gmailpush_history.json', JSON.stringify(prevHistories));
});
});
})
.catch((err) => {
console.log(err);
});
}
);
But you don't have to call
gmail.users.watch()
orgmailpush._initialize()
by yourself because Gmailpush deals with them on your behalf.
I'm a little confused about this. From what I understand of Google's PubSub API, it doesn't start sending notifications to the subscriptions until a server starts watching the topic. But the example code doesn't start watching until there is a call to getMessages()
, which can only happen when there is a notification. This means that gmailpush
needs
watch()
to kick it off. Without this, it will never start watching and thus never get a notification that triggers a call to getMessages()
. watch()
. Without this, getMessages()
will never be called and the gmail API will stop sending updates. I'm not sure of all the use-cases of a library like this, but in my opinion, there could be 2 convenient things the library could do to help with this:
_refreshWatch()
that does what you've done in your sample code there, effectively "refreshing the watch call". This could be used to trigger that initial watch()
call as well as schedule future ones without anyone using the library needing to understand the details of the underlying json file. watch()
call when Gmailpush
gets instantiated and then use node-schedule
to refresh it every day.What do you think? I might have some misconceptions about how this library works, so let me know if I'm overcomplicating this in my head! My use case is setting up a personal email watcher so that I can run scripts whenever I get an email in my personal inbox. That's why I want to start watching and never stop watching.
I might be able to help with a basic implementation of this! I'm sure I could dive into the library and understand the basics in an hour or two. But given the sample code you wrote, I'm sure the easier fix that I suggested above could hopefully be implemented pretty quickly. Just let me know!
For "1. An initial call to watch() to kick it off", I will provide refreshWatch()
method. Although Gmail API documentation says that calling watch()
first is necessary to be able to get notifications, in my experience it is not necessary to call watch()
: Gmail push notifications are sent without my having called watch()
. (There is another example of mismatch between documentation and actual workings which has not yet been solved.) And watch()
is an email address-specific method. So kicking off the initial watch()
call when Gmailpush gets instantiated would make initialization syntax backward incompatible.
For "2. An inbox update once every 7 days so that it knows to make another call to watch()", I will implement Node Schedule into Gmailpush to call watch()
before watchExpiration
.
Thank you for your offer! But I think this should be done without taking your time.
Makes sense! So I can just use _refreshWatch()
to call the initial and any recurring calls to watch()
(before node schedule is built in). From my understanding, there's no need to mess with the json file as long as the watch is refreshed regularly enough that no messages are ever missed.
Okay, I just looked through the code, and I think I understand what you are saying when you said that the watch()
function being email-specific. I think a workaround I could use for my single-email instance is saving the body of a notification to serve as a dummy notification that I can use to call _initialize()
. Then, I can easily call _refreshWatch()
as frequently as daily using something like node-schedule.
You don't have to call watch()
manually if you think your inbox receives at least one email (including spams) for seven-day-period. Every activity on Gmail would be notified to your PubSub subscription end point. And if you've put getMessages()
into your app.post()
route without any conditionals filtering out invocation of getMessages()
, because Gmailpush automatically calls watch()
for every getMessages()
method, watch expiration would extend for seven days whenever any activities occur on Gmail.
By the way, looking into my code I had written one year ago I realized that json file is not necessary and information contained in it could be attached to Gmailpush class. It could make this library more usable. So next version would be either 1.1.0 or 2.0.0.
I followed the example code provided line for line, but it didn't seem like the topic was ever getting watched (and no history file was created). I debugged a little bit, and I don't think
this._initialize()
is being called using the setup that was provided in the readme. I'm sure I'm missing something simple, but any help on this?From poking around the source code, I noticed that the initialize function takes in a notification, but I'm still not sure when it's meant to be called 🤔