diff --git a/.env_sample b/.env_sample new file mode 100644 index 0000000..0f56130 --- /dev/null +++ b/.env_sample @@ -0,0 +1,7 @@ +EMAIL=test@gmail.com +CLIENT_ID=xxxxxxxxxxxxxx.apps.googleusercontent.com +CLIENT_SECRET=xxxxxxxxxxxxxx +TOPIC_URL=projects//topics/MyPush +SUBSCRIPTION_URL=projects//subscriptions/MyPush-sub +EMAIL_LABEL=UNREAD +WEBHOOK_URL=https://discord.com/api/webhooks/get/yours diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0810116 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +credentials.json +token.json +gmailpush_history.json +.env +*.sh +node_modules +logs +backup diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..bee75fa Binary files /dev/null and b/favicon.ico differ diff --git a/getNewToken.js b/getNewToken.js new file mode 100644 index 0000000..5dbd66d --- /dev/null +++ b/getNewToken.js @@ -0,0 +1,38 @@ +require('dotenv').config(); +const readline = require('readline'); +const {google} = require('googleapis'); + +function getToken() { + const auth = new google.auth.OAuth2( + process.env.CLIENT_ID, + process.env.CLIENT_SECRET, + 'urn:ietf:wg:oauth:2.0:oob' + ); + + const authUrl = auth.generateAuthUrl({ + access_type: 'offline', + scope: ['https://www.googleapis.com/auth/gmail.readonly'], + }); + + console.log('Authorize this app by visiting this url:'); + console.log(authUrl); + + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + rl.question('Enter the code from that page here: ', (authCode) => { + rl.close(); + auth.getToken(authCode, (err, token) => { + if (err) { + return console.log('Error retrieving access token', err); + } + + console.log('Token:'); + console.log(token); + }); + }); +} + +getToken(); diff --git a/index.js b/index.js new file mode 100644 index 0000000..2bf5bc8 --- /dev/null +++ b/index.js @@ -0,0 +1,67 @@ +require("dotenv").config(); +const jsonToken = require("./token.json"); +const Gmailpush = require("gmailpush"); +const express = require("express"); +const app = express(); +const { WebhookClient } = require("discord.js"); +const webhook = new WebhookClient({ url: process.env.WEBHOOK_URL }); + +// Initialize with OAuth2 config and Pub/Sub topic +const gmailpush = new Gmailpush({ + clientId: process.env.CLIENT_ID, + clientSecret: process.env.CLIENT_SECRET, + pubsubTopic: process.env.TOPIC_URL, +}); + +const users = [ + { + email: process.env.EMAIL, + token: { + access_token: jsonToken.access_token, + refresh_token: jsonToken.refresh_token, + scope: jsonToken.scope, + token_type: jsonToken.token_type, + expiry_date: jsonToken.expiry_date, + }, + }, +]; + +app.post( + // Use URL set as Pub/Sub Subscription endpoint + "/pubsub", + express.json(), + async (req, res) => { + res.sendStatus(200); + const email = gmailpush.getEmailAddress(req.body); + const token = users.find((user) => user.email === email).token; + + const { subject } = await gmailpush + .getNewMessage({ + notification: req.body, + token, + }) + .then((message) => { + if (message === null) { + return {}; + } + if (!message.labelIds.includes(process.env.EMAIL_LABEL)) { + return {}; + } + return message; + }); + if (subject) { + webhook + .send({ content: subject }) + .then((message) => console.log(`Sent message: ${message.content}`)) + .catch(console.error); + } else { + console.log( + "Not sending message: Email Subject does not match label ID." + ); + } + } +); + +app.listen(3002, () => { + console.log("Server listening on port 3002..."); +}); diff --git a/package.json b/package.json new file mode 100644 index 0000000..5d0b161 --- /dev/null +++ b/package.json @@ -0,0 +1,36 @@ +{ + "name": "gmail-push-to-discord", + "version": "1.0.0", + "description": "Get real-time Gmail push notifications to your Discord channel!", + "keywords": [ + "gmail", + "discord", + "bot", + "api", + "webhook" + ], + "homepage": "https://github.com/jzvi12/gmail-push-to-discord", + "repository": { + "type": "git", + "url": "https://github.com/jzvi12/gmail-push-to-discord.git" + }, + "main": "index.js", + "scripts": { + "start": "node ./index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "bugs": "https://github.com/jzvi12/gmail-push-to-discord/issues", + "author": "jzvi12", + "license": "MIT", + "dependencies": { + "@google-cloud/pubsub": "^3.2.1", + "discord.js": "^14.6.0", + "dotenv": "^16.0.3", + "express": "^4.18.2", + "gmailpush": "^1.0.5", + "googleapis": "^61.0.0" + }, + "engines": { + "node": ">=10" + } +} diff --git a/watch_request.js b/watch_request.js new file mode 100644 index 0000000..f0ff334 --- /dev/null +++ b/watch_request.js @@ -0,0 +1,29 @@ +require('dotenv').config(); +const jsonToken = require('./token.json'); +const {google} = require('googleapis'); + +const auth = new google.auth.OAuth2(process.env.CLIENT_ID, process.env.CLIENT_SECRET); + +auth.setCredentials({ + access_token: jsonToken.access_token, + refresh_token: jsonToken.refresh_token, + scope: jsonToken.scope, + token_type: jsonToken.token_type, + expiry_date: jsonToken.expiry_date +}); + +const gmail = google.gmail({ + version: 'v1', + auth, +}); + +gmail.users + .watch({ + userId: process.env.EMAIL, + requestBody: { + labelIds: [process.env.EMAIL_LABEL], + topicName: process.env.TOPIC_URL, + }, + }) + .then((result) => console.log(result)) + .catch((err) => console.log(err));