Compare commits

...

9 Commits
7.2.0 ... 7.4.0

Author SHA1 Message Date
weakmap@gmail.com
17b4bad2e4 fixing notification provider 2023-09-27 17:45:38 +02:00
weakmap@gmail.com
fbad4456d7 upgrading dependencies 2023-09-07 20:52:27 +02:00
weakmap@gmail.com
deec626feb Merge branch 'master' of https://github.com/orangecoding/fredy 2023-09-07 20:40:15 +02:00
weakmap@gmail.com
88c6641485 fixing wgGesucht test 2023-09-07 20:40:07 +02:00
Christian Kellner
f4eedda658 moving back to sqllite v8.2.0 2023-05-11 12:17:26 +02:00
Christian Kellner
d2b80561f8 moving back to sqllite v8.2.0 2023-05-11 12:16:28 +02:00
Christian Kellner
3bda88a075 upgrade dependencies 2023-05-11 11:51:23 +02:00
Christian Kellner
86465e0076 next release version 2023-05-08 09:33:20 +02:00
Christian Kellner
d947dad488 fixing ebay kleinanzeigen, now becoming kleinanzeigen 2023-05-08 09:32:07 +02:00
17 changed files with 1675 additions and 1395 deletions

View File

@@ -9,7 +9,7 @@ const template = fs.readFileSync(path.resolve(__dirname + '/notification/emailTe
const emailTemplate = Handlebars.compile(template); const emailTemplate = Handlebars.compile(template);
export const send = ({ serviceName, newListings, notificationConfig, jobKey }) => { export const send = ({ serviceName, newListings, notificationConfig, jobKey }) => {
const { apiPublicKey, apiPrivateKey, receiver, from } = notificationConfig.find( const { apiPublicKey, apiPrivateKey, receiver, from } = notificationConfig.find(
(adapter) => adapter.id === 'mailjet' (adapter) => adapter.id === config.id,
).fields; ).fields;
const to = receiver const to = receiver
.trim() .trim()

View File

@@ -2,13 +2,13 @@ import { markdown2Html } from '../../services/markdown.js';
import { getJob } from '../../services/storage/jobStorage.js'; import { getJob } from '../../services/storage/jobStorage.js';
import fetch from 'node-fetch'; import fetch from 'node-fetch';
export const send = ({ serviceName, newListings, notificationConfig, jobKey }) => { export const send = ({ serviceName, newListings, notificationConfig, jobKey }) => {
const { webhook, channel } = notificationConfig.find((adapter) => adapter.id === 'mattermost').fields; const { webhook, channel } = notificationConfig.find((adapter) => adapter.id === config.id).fields;
const job = getJob(jobKey); const job = getJob(jobKey);
const jobName = job == null ? jobKey : job.name; const jobName = job == null ? jobKey : job.name;
let message = `### *${jobName}* (${serviceName}) found **${newListings.length}** new listings:\n\n`; let message = `### *${jobName}* (${serviceName}) found **${newListings.length}** new listings:\n\n`;
message += `| Title | Address | Size | Price |\n|:----|:----|:----|:----|\n`; message += `| Title | Address | Size | Price |\n|:----|:----|:----|:----|\n`;
message += newListings.map( message += newListings.map(
(o) => `| [${o.title}](${o.link}) | ` + [o.address, o.size.replace(/2m/g, '$m^2$'), o.price].join(' | ') + ' |\n' (o) => `| [${o.title}](${o.link}) | ` + [o.address, o.size.replace(/2m/g, '$m^2$'), o.price].join(' | ') + ' |\n',
); );
return fetch(webhook, { return fetch(webhook, {
method: 'POST', method: 'POST',

View File

@@ -3,7 +3,7 @@ import { getJob } from '../../services/storage/jobStorage.js';
import fetch from 'node-fetch'; import fetch from 'node-fetch';
export const send = ({ serviceName, newListings, notificationConfig, jobKey }) => { export const send = ({ serviceName, newListings, notificationConfig, jobKey }) => {
const { priority, server, topic } = notificationConfig.find((adapter) => adapter.id === 'ntfy').fields; const { priority, server, topic } = notificationConfig.find((adapter) => adapter.id === config.id).fields;
const job = getJob(jobKey); const job = getJob(jobKey);
const jobName = job == null ? jobKey : job.name; const jobName = job == null ? jobKey : job.name;
const promises = newListings.map((newListing) => { const promises = newListings.map((newListing) => {

View File

@@ -1,7 +1,7 @@
import sgMail from '@sendgrid/mail'; import sgMail from '@sendgrid/mail';
import { markdown2Html } from '../../services/markdown.js'; import { markdown2Html } from '../../services/markdown.js';
export const send = ({ serviceName, newListings, notificationConfig, jobKey }) => { export const send = ({ serviceName, newListings, notificationConfig, jobKey }) => {
const { apiKey, receiver, from, templateId } = notificationConfig.find((adapter) => adapter.id === 'sendGrid').fields; const { apiKey, receiver, from, templateId } = notificationConfig.find((adapter) => adapter.id === config.id).fields;
sgMail.setApiKey(apiKey); sgMail.setApiKey(apiKey);
const msg = { const msg = {
templateId, templateId,

View File

@@ -2,7 +2,7 @@ import Slack from 'slack';
import { markdown2Html } from '../../services/markdown.js'; import { markdown2Html } from '../../services/markdown.js';
const msg = Slack.chat.postMessage; const msg = Slack.chat.postMessage;
export const send = ({ serviceName, newListings, notificationConfig, jobKey }) => { export const send = ({ serviceName, newListings, notificationConfig, jobKey }) => {
const { token, channel } = notificationConfig.find((adapter) => adapter.id === 'slack').fields; const { token, channel } = notificationConfig.find((adapter) => adapter.id === config.id).fields;
return newListings.map((payload) => return newListings.map((payload) =>
msg({ msg({
token, token,
@@ -35,7 +35,7 @@ export const send = ({ serviceName, newListings, notificationConfig, jobKey }) =
ts: new Date().getTime() / 1000, ts: new Date().getTime() / 1000,
}, },
], ],
}) }),
); );
}; };
export const config = { export const config = {

View File

@@ -19,7 +19,7 @@ function shorten(str, len = 30) {
return str.length > len ? str.substring(0, len) + '...' : str; return str.length > len ? str.substring(0, len) + '...' : str;
} }
export const send = ({ serviceName, newListings, notificationConfig, jobKey }) => { export const send = ({ serviceName, newListings, notificationConfig, jobKey }) => {
const { token, chatId } = notificationConfig.find((adapter) => adapter.id === 'telegram').fields; const { token, chatId } = notificationConfig.find((adapter) => adapter.id === config.id).fields;
const job = getJob(jobKey); const job = getJob(jobKey);
const jobName = job == null ? jobKey : job.name; const jobName = job == null ? jobKey : job.name;
//we have to split messages into chunk, because otherwise messages are going to become too big and will fail //we have to split messages into chunk, because otherwise messages are going to become too big and will fail
@@ -30,7 +30,7 @@ export const send = ({ serviceName, newListings, notificationConfig, jobKey }) =
(o) => (o) =>
`<a href='${o.link}'><b>${shorten(o.title.replace(/\*/g, ''), 45).trim()}</b></a>\n` + `<a href='${o.link}'><b>${shorten(o.title.replace(/\*/g, ''), 45).trim()}</b></a>\n` +
[o.address, o.price, o.size].join(' | ') + [o.address, o.price, o.size].join(' | ') +
'\n\n' '\n\n',
); );
/** /**
* This is to not break the rate limit. It is to only send 1 message per second * This is to not break the rate limit. It is to only send 1 message per second

View File

@@ -32,7 +32,7 @@ const config = {
}; };
export const metaInformation = { export const metaInformation = {
name: 'Ebay Kleinanzeigen', name: 'Ebay Kleinanzeigen',
baseUrl: 'https://www.ebay-kleinanzeigen.de/', baseUrl: 'https://www.kleinanzeigen.de/',
id: 'kleinanzeigen', id: 'kleinanzeigen',
}; };
export const init = (sourceConfig, blacklist, blacklistedDistricts) => { export const init = (sourceConfig, blacklist, blacklistedDistricts) => {

View File

@@ -2,7 +2,7 @@ import { metaInformation as immoScoutInfo } from '../provider/immoscout.js';
import { metaInformation as immoNetInfo } from '../provider/immonet.js'; import { metaInformation as immoNetInfo } from '../provider/immonet.js';
import { config } from '../utils.js'; import { config } from '../utils.js';
const additionalImmonetUrlParams = `&wait_for_selector=.content-wrapper-tiles&js_snippet=${new Buffer( const additionalImmonetUrlParams = `&wait_for_selector=.content-wrapper-tiles&js_snippet=${Buffer.from(
'window.scrollTo(0,document.body.scrollHeight);' 'window.scrollTo(0,document.body.scrollHeight);'
).toString('base64')}`; ).toString('base64')}`;

View File

@@ -1,8 +1,8 @@
import lodash from 'lodash'; import lodash from 'lodash';
import { LowSync } from 'lowdb'; import { LowSync } from 'lowdb';
export default class LowdashAdapter extends LowSync { export default class LowdashAdapter extends LowSync {
constructor(adapter) { constructor(adapter, defaultData = {}) {
super(adapter); super(adapter, defaultData);
this.chain = lodash.chain(this).get('data'); this.chain = lodash.chain(this).get('data');
} }
} }

View File

@@ -7,11 +7,10 @@ import LowdashAdapter from './LowDashAdapter.js';
const file = path.join(getDirName(), '../', 'db/jobs.json'); const file = path.join(getDirName(), '../', 'db/jobs.json');
const adapter = new JSONFileSync(file); const adapter = new JSONFileSync(file);
const db = new LowdashAdapter(adapter); const db = new LowdashAdapter(adapter, { jobs: [] });
db.read(); db.read();
db.data ||= { jobs: [] };
export const upsertJob = ({ jobId, name, blacklist = [], enabled = true, provider, notificationAdapter, userId }) => { export const upsertJob = ({ jobId, name, blacklist = [], enabled = true, provider, notificationAdapter, userId }) => {
const currentJob = const currentJob =

View File

@@ -5,12 +5,10 @@ import LowdashAdapter from './LowDashAdapter.js';
const file = path.join(getDirName(), '../', 'db/jobListingData.json'); const file = path.join(getDirName(), '../', 'db/jobListingData.json');
const adapter = new JSONFileSync(file); const adapter = new JSONFileSync(file);
const db = new LowdashAdapter(adapter); const db = new LowdashAdapter(adapter, {});
db.read(); db.read();
db.data ||= {};
const buildKey = (jobKey, providerId, endpoint) => { const buildKey = (jobKey, providerId, endpoint) => {
let key = `${jobKey}`; let key = `${jobKey}`;
if (jobKey == null && endpoint == null) { if (jobKey == null && endpoint == null) {

View File

@@ -6,24 +6,24 @@ import * as jobStorage from './jobStorage.js';
import path from 'path'; import path from 'path';
import LowdashAdapter from './LowDashAdapter.js'; import LowdashAdapter from './LowDashAdapter.js';
const defaultData = {
user: [
//you probably want to change the default password ;)
{
id: nanoid(),
lastLogin: Date.now(),
username: 'admin',
password: hasher.hash('admin'),
isAdmin: true,
},
],
};
const file = path.join(getDirName(), '../', 'db/users.json'); const file = path.join(getDirName(), '../', 'db/users.json');
const adapter = new JSONFileSync(file); const adapter = new JSONFileSync(file);
const db = new LowdashAdapter(adapter); const db = new LowdashAdapter(adapter, defaultData);
db.read(); db.read();
db.data ||= {
user: [
//you probably want to change the default password ;)
{
id: nanoid(),
lastLogin: Date.now(),
username: 'admin',
password: hasher.hash('admin'),
isAdmin: true,
isDemo: false,
},
],
};
export const getUsers = (withPassword) => { export const getUsers = (withPassword) => {
const jobs = jobStorage.getJobs(); const jobs = jobStorage.getJobs();

View File

@@ -1,6 +1,6 @@
{ {
"name": "fredy", "name": "fredy",
"version": "7.2.0", "version": "7.4.0",
"description": "[F]ind [R]eal [E]states [d]amn eas[y].", "description": "[F]ind [R]eal [E]states [d]amn eas[y].",
"scripts": { "scripts": {
"start": "node index.js", "start": "node index.js",
@@ -55,27 +55,27 @@
"Firefox ESR" "Firefox ESR"
], ],
"dependencies": { "dependencies": {
"@douyinfe/semi-ui": "2.31.0", "@douyinfe/semi-ui": "2.44.0",
"@rematch/core": "2.2.0", "@rematch/core": "2.2.0",
"@rematch/loading": "2.1.2", "@rematch/loading": "2.1.2",
"@sendgrid/mail": "7.7.0", "@sendgrid/mail": "7.7.0",
"@vitejs/plugin-react": "3.1.0", "@vitejs/plugin-react": "4.1.0",
"better-sqlite3": "8.2.0", "better-sqlite3": "8.6.0",
"body-parser": "1.20.2", "body-parser": "1.20.2",
"cookie-session": "2.0.0", "cookie-session": "2.0.0",
"handlebars": "4.7.7", "handlebars": "4.7.8",
"highcharts": "10.3.3", "highcharts": "11.1.0",
"highcharts-react-official": "3.2.0", "highcharts-react-official": "3.2.1",
"lodash": "4.17.21", "lodash": "4.17.21",
"lowdb": "5.1.0", "lowdb": "6.0.1",
"markdown": "^0.5.0", "markdown": "^0.5.0",
"nanoid": "4.0.1", "nanoid": "4.0.2",
"node-fetch": "3.3.1", "node-fetch": "3.3.2",
"node-mailjet": "6.0.2", "node-mailjet": "6.0.4",
"query-string": "8.1.0", "query-string": "8.1.0",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-redux": "8.0.5", "react-redux": "8.1.2",
"react-router": "5.2.1", "react-router": "5.2.1",
"react-router-dom": "5.3.0", "react-router-dom": "5.3.0",
"redux": "4.2.1", "redux": "4.2.1",
@@ -84,25 +84,25 @@
"serve-static": "1.15.0", "serve-static": "1.15.0",
"slack": "11.0.2", "slack": "11.0.2",
"string-similarity": "^4.0.4", "string-similarity": "^4.0.4",
"vite": "4.2.0", "vite": "4.4.9",
"x-ray": "2.3.4" "x-ray": "2.3.4"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.21.3", "@babel/core": "7.23.0",
"@babel/eslint-parser": "7.21.3", "@babel/eslint-parser": "7.22.15",
"@babel/preset-env": "7.20.2", "@babel/preset-env": "7.22.20",
"@babel/preset-react": "7.18.6", "@babel/preset-react": "7.22.15",
"chai": "4.3.7", "chai": "4.3.9",
"eslint": "8.36.0", "eslint": "8.50.0",
"eslint-config-prettier": "8.7.0", "eslint-config-prettier": "8.8.0",
"eslint-plugin-react": "7.32.2", "eslint-plugin-react": "7.33.2",
"esmock": "2.1.0", "esmock": "2.5.1",
"history": "5.3.0", "history": "5.3.0",
"husky": "4.3.8", "husky": "4.3.8",
"less": "4.1.3", "less": "4.2.0",
"lint-staged": "13.2.0", "lint-staged": "13.2.2",
"mocha": "10.2.0", "mocha": "10.2.0",
"prettier": "2.8.5", "prettier": "3.0.3",
"redux-logger": "3.0.6" "redux-logger": "3.0.6"
} }
} }

View File

@@ -26,7 +26,7 @@ describe('#kleinanzeigen testsuite()', () => {
expect(notify.address).to.be.a('string'); expect(notify.address).to.be.a('string');
/** check the values if possible **/ /** check the values if possible **/
expect(notify.title).to.be.not.empty; expect(notify.title).to.be.not.empty;
expect(notify.link).that.does.include('https://www.ebay-kleinanzeigen.de'); expect(notify.link).that.does.include('https://www.kleinanzeigen.de');
expect(notify.address).to.be.not.empty; expect(notify.address).to.be.not.empty;
}); });
resolve(); resolve();

View File

@@ -29,7 +29,7 @@
"enabled": true "enabled": true
}, },
"kleinanzeigen": { "kleinanzeigen": {
"url": "https://www.ebay-kleinanzeigen.de/s-immobilien/duesseldorf/anzeige:angebote/wohnung/k0c195l2068r5", "url": "https://www.kleinanzeigen.de/s-immobilien/duesseldorf/anzeige:angebote/wohnung/k0c195l2068r5",
"enabled": true "enabled": true
}, },
"neubauKompass": { "neubauKompass": {

View File

@@ -23,7 +23,6 @@ describe('#wgGesucht testsuite()', () => {
expect(notify.id).to.be.a('string'); expect(notify.id).to.be.a('string');
expect(notify.title).to.be.a('string'); expect(notify.title).to.be.a('string');
expect(notify.details).to.be.a('string'); expect(notify.details).to.be.a('string');
expect(notify.size).to.be.a('string');
expect(notify.price).to.be.a('string'); expect(notify.price).to.be.a('string');
expect(notify.link).to.be.a('string'); expect(notify.link).to.be.a('string');
}); });

2954
yarn.lock

File diff suppressed because it is too large Load Diff