Adding new Admin UI. Updating Fredy to V3.0.0 as it has been a large rewrite. Thanks for all contributions and help on the way!
This commit is contained in:
Christian Kellner
2021-01-21 16:09:23 +01:00
committed by GitHub
parent 8185bfe818
commit b2847f6834
124 changed files with 9768 additions and 1495 deletions

View File

@@ -1,16 +1,21 @@
const { markdown2Html } = require('../../services/markdown');
/**
* simply prints out the found data to the console
* @param serviceName e.g immoscout
* @param serviceName e.g immowelt
* @param newListings an array with newly found listings
* @param notificationConfig config of this notification adapter
* @param jobKey name of the current job that is being executed
*/
exports.send = (serviceName, newListings, notificationConfig, jobKey) => {
const { enabled } = notificationConfig.console;
if (!enabled) {
return [Promise.resolve()];
}
exports.send = ({ serviceName, newListings, jobKey }) => {
/* eslint-disable no-console */
return [Promise.resolve(console.info(`Found entry from service ${serviceName}, Job: ${jobKey}:`, newListings))];
/* eslint-enable no-console */
};
exports.config = {
id: __filename.slice(__dirname.length + 1, -3),
name: 'Console',
description: 'This adapter sends new listings to the console. It is mostly useful for debugging.',
config: {},
readme: markdown2Html('lib/notification/adapter/console.md'),
};

View File

@@ -0,0 +1,4 @@
### Console Adapter
The console adapter prints everything found by Fredy into the console (not sending any notifications to you). This can be useful when you want to check if your search
criteria meet the expectations.

View File

@@ -6,21 +6,20 @@ const template = fs.readFileSync(path.resolve(__dirname, '../', 'emailTemplate/t
const Handlebars = require('handlebars');
const emailTemplate = Handlebars.compile(template);
const { markdown2Html } = require('../../services/markdown');
/**
* sends a new listing using MailJet
* @param serviceName e.g immoscout
* @param serviceName e.g immowelt
* @param newListings an array with newly found listings
* @param notificationConfig config of this notification adapter
* * @param jobKey name of the current job that is being executed
* @returns {Promise<Chat.PostMessage.Response> | void}
*/
exports.send = (serviceName, newListings, notificationConfig, jobKey) => {
const { apiPublicKey, apiPrivateKey, enabled, receiver, from } = notificationConfig.mailJet;
if (!enabled) {
return [Promise.resolve()];
}
exports.send = ({ serviceName, newListings, notificationConfig, jobKey }) => {
const { apiPublicKey, apiPrivateKey, receiver, from } = notificationConfig.find(
(adapter) => adapter.id === 'mailJet'
).fields;
return mailjet
.connect(apiPublicKey, apiPrivateKey)
@@ -47,3 +46,33 @@ exports.send = (serviceName, newListings, notificationConfig, jobKey) => {
],
});
};
exports.config = {
id: __filename.slice(__dirname.length + 1, -3),
name: 'MailJet',
description: 'MailJet is being used to send new listings via mail.',
readme: markdown2Html('lib/notification/adapter/mailJet.md'),
fields: {
apiPublicKey: {
type: 'text',
label: 'Public Api Key',
description: 'The public api key needed to access this service.',
},
apiPrivateKey: {
type: 'text',
label: 'Private Api Key',
description: 'The private api key needed to access this service.',
},
receiver: {
type: 'email',
label: 'Receiver Email',
description: 'The email address (single one) which Fredy is using to send notifications to.',
},
from: {
type: 'email',
label: 'Sender email',
description:
'The email address from which Fredy send email. Beware, this email address needs to be verified by Sendgrid.',
},
},
};

View File

@@ -0,0 +1,9 @@
### MailJet Adapter
SendGrid is a free email service (free as in "you cannot send more than 100(Sendgrid) and 200(Mailjet) emails a day"), which is more than enough for Fredy.
To use [SendGrid](https://sendgrid.com/), you need to create an account. You'll need to decided from which email address you want Fredy to send from. E.g. if you use yourGmailAccount@gmail.com, you have to add this to sendgrid and verify it as well.
Lastly you have to create an api-key and feed it into Fredy's config, as well as creating a new template. For this new template, I recommend copying and pasting the one I have provided under `/lib/notification/emailTemplate/template.hbs`.

View File

@@ -1,18 +1,16 @@
const sgMail = require('@sendgrid/mail');
const { markdown2Html } = require('../../services/markdown');
/**
* sends a new listing using SendGrid
* @param serviceName e.g immoscout
* @param serviceName e.g immowelt
* @param newListings an array with newly found listings
* @param notificationConfig config of this notification adapter
* * @param jobKey name of the current job that is being executed
* @param jobKey name of the current job that is being executed
* @returns {Promise<Chat.PostMessage.Response> | void}
*/
exports.send = (serviceName, newListings, notificationConfig, jobKey) => {
const { apiKey, enabled, receiver, from, templateId } = notificationConfig.sendGrid;
if (!enabled) {
return [Promise.resolve()];
}
exports.send = ({ serviceName, newListings, notificationConfig, jobKey }) => {
const { apiKey, receiver, from, templateId } = notificationConfig.find((adapter) => adapter.id === 'sendGrid').fields;
sgMail.setApiKey(apiKey);
const msg = {
templateId,
@@ -27,3 +25,33 @@ exports.send = (serviceName, newListings, notificationConfig, jobKey) => {
};
return sgMail.send(msg);
};
exports.config = {
id: __filename.slice(__dirname.length + 1, -3),
name: 'SendGrid',
description: 'SendGrid is being used to send new listings via mail.',
readme: markdown2Html('lib/notification/adapter/sendGrid.md'),
fields: {
apiKey: {
type: 'text',
label: 'Api Key',
description: 'The api key needed to access this service.',
},
receiver: {
type: 'email',
label: 'Receiver Email',
description: 'The email address (single one) which Fredy is using to send notifications to.',
},
from: {
type: 'email',
label: 'Sender Email',
description:
'The email address from which Fredy send email. Beware, this email address needs to be verified by Sendgrid.',
},
templateId: {
type: 'text',
label: 'Template Id',
description: 'Sendgrid supports templates which Fredy is using to send out emails that looks awesome ;)',
},
},
};

View File

@@ -0,0 +1,7 @@
### SendGrid Adapter
To use [MailJet](https://mailjet.com), you need to create an account. You'll need to decided from which email address you want Fredy to send from.
E.g. if you use yourGmailAccount@gmail.com, you have to add this to MailJet and verify it as well.
The given public/private api keys are needed in order to use MailJet with Fredy. Fredy will use the same template, it is using for SendGrid.

View File

@@ -1,19 +1,17 @@
const Slack = require('slack');
const msg = Slack.chat.postMessage;
const { markdown2Html } = require('../../services/markdown');
/**
* sends a new listing to slack
* @param serviceName e.g immoscout
* @param serviceName e.g immowelt
* @param newListings an array with newly found listings
* @param notificationConfig config of this notification adapter
* * @param jobKey name of the current job that is being executed
* @returns {Promise<Chat.PostMessage.Response> | void}
*/
exports.send = (serviceName, newListings, notificationConfig, jobKey) => {
const { token, channel, enabled } = notificationConfig.slack;
if (!enabled) {
return [Promise.resolve()];
}
exports.send = ({ serviceName, newListings, notificationConfig, jobKey }) => {
const { token, channel } = notificationConfig.find((adapter) => adapter.id === 'slack').fields;
return newListings.map((payload) =>
msg({
token,
@@ -49,3 +47,22 @@ exports.send = (serviceName, newListings, notificationConfig, jobKey) => {
})
);
};
exports.config = {
id: __filename.slice(__dirname.length + 1, -3),
name: 'Slack',
readme: markdown2Html('lib/notification/adapter/slack.md'),
description: 'Fredy will send new listings to the slack channel of your choice..',
fields: {
token: {
type: 'text',
label: 'Token',
description: 'The token needed to send notifications to slack.',
},
channel: {
type: 'channel',
label: 'Channel',
description: 'The channel where fredy should send notifications to.',
},
},
};

View File

@@ -0,0 +1,6 @@
### Slack Adapter
In order to use [Slack](https://slack.com), you need to create an account. When done, you need to create a new App in your workspace. Give it the permission `chat:write:bot` and `chat:write:user`.
Now you need to create a user token and a channel. Make sure the bot is installed to this channel.

View File

@@ -1,20 +1,17 @@
const TelegramBot = require('tg-yarl');
const { markdown2Html } = require('../../services/markdown');
const opts = { parse_mode: 'Markdown' };
/**
* sends new listings to telegram
* @param serviceName e.g immoscout
* @param serviceName e.g immowelt
* @param newListings an array with newly found listings
* @param notificationConfig config of this notification adapter
* * @param jobKey name of the current job that is being executed
* @returns {Promise<Void> | void}
*/
exports.send = (serviceName, newListings, notificationConfig, jobKey) => {
const { enabled, token, chatId } = notificationConfig.telegram;
if (!enabled) {
return [Promise.resolve()];
}
exports.send = ({ serviceName, newListings, notificationConfig, jobKey }) => {
const { token, chatId } = notificationConfig.find((adapter) => adapter.id === 'telegram').fields;
const bot = new TelegramBot(token);
@@ -34,3 +31,27 @@ exports.send = (serviceName, newListings, notificationConfig, jobKey) => {
function shorten(str, len = 30) {
return str.length > len ? str.substring(0, len) + '...' : str;
}
/**
* exported config is being used in the frontend to generate the fields
* incoming values will be the keys (and values) of the fields
*
*/
exports.config = {
id: __filename.slice(__dirname.length + 1, -3),
name: 'Telegram',
readme: markdown2Html('lib/notification/adapter/telegram.md'),
description: 'Fredy will send new listings to your mobile, using Telegram.',
fields: {
token: {
type: 'text',
label: 'Token',
description: 'The token needed to access this service.',
},
chatId: {
type: 'chatId',
label: 'Chat Id',
description: 'The chat id to send messages to you.',
},
},
};

View File

@@ -0,0 +1,13 @@
### Telegram Adapter
For Telegram, you need to create a Bot. This is pretty easy. Open [this](https://telegram.me/BotFather) url on your smartphone and follow the instructions.
A telegram bot is not allowed to send messages directly to a user, you as a user need to first contact the bot to get a chatId.
After the user has send a message to your bot the first time, you can gather the chatId like this:
```
curl -X GET https://api.telegram.org/bot{YOUR_TELEGRAM_TOKEN}/getUpdates
```
A more detailed list of instructions can be found here [https://core.telegram.org/bots#botfather](https://core.telegram.org/bots#botfather)

View File

@@ -2,13 +2,20 @@ const fs = require('fs');
const path = './adapter';
/** Read every integration existing in ./adapter **/
const adapter = fs.readdirSync('./lib/notification/adapter').map((integPath) => require(`${path}/${integPath}`));
const adapter = fs
.readdirSync('./lib/notification/adapter')
.filter((file) => file.endsWith('.js'))
.map((integPath) => require(`${path}/${integPath}`));
if (adapter.length === 0) {
throw new Error('Please specify at least one notification provider');
}
exports.send = (serviceName, payload, notificationConfig, jobKey) => {
//this is not being used in tests, therefor adapter are always set
return adapter.map((a) => a.send(serviceName, payload, notificationConfig, jobKey));
exports.send = (serviceName, newListings, notificationConfig, jobKey) => {
//this is not being used in tests, therefore adapter are always set
return adapter
.filter((notificationAdapter) => {
return notificationConfig.find((config) => config.id === notificationAdapter.config.id);
})
.map((a) => a.send({ serviceName, newListings, notificationConfig, jobKey }));
};