mirror of
https://github.com/orangecoding/fredy.git
synced 2026-06-16 12:31:07 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50b3fde075 | ||
|
|
1a3fc6f94d | ||
|
|
26ed42230a | ||
|
|
6f4defdc1b | ||
|
|
f798aed342 | ||
|
|
27e098c244 | ||
|
|
37948be0d3 | ||
|
|
cc7bbb77c4 | ||
|
|
96da0b7892 | ||
|
|
72993312c7 |
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v2.5.1
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: 18
|
||||
cache: 'yarn'
|
||||
- run: yarn install
|
||||
- run: yarn run test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:1.3
|
||||
FROM node:16-alpine AS builder
|
||||
FROM node:18-alpine AS builder
|
||||
COPY --chown=1000:1000 . /fredy
|
||||
WORKDIR /fredy
|
||||
USER 1000
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Christian Kellner
|
||||
Copyright (c) 2024 Christian Kellner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -17,7 +17,7 @@ _Fredy_ is supported by JetBrains under Open Source Support Program
|
||||
|
||||
## Usage
|
||||
|
||||
- Make sure to use Node.js 16 or above
|
||||
- Make sure to use Node.js 18 or above
|
||||
- Run the following commands:
|
||||
```ssh
|
||||
yarn (or npm install)
|
||||
@@ -33,9 +33,6 @@ _Fredy_ will start with the default port, set to `9998`. You can access _Fredy_
|
||||
|
||||
<img alt="Job Overview" width="30%" src="https://github.com/orangecoding/fredy/blob/master/doc/screenshot_3.png">
|
||||
</p>
|
||||
<p align="center">
|
||||
|
||||
</p>
|
||||
|
||||
## Understanding the fundamentals
|
||||
There are 3 important parts in Fredy, that you need to understand to leverage the full power of _Fredy_.
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import { markdown2Html } from '../../services/markdown.js';
|
||||
import Database from 'better-sqlite3';
|
||||
export const send = ({ serviceName, newListings, jobKey }) => {
|
||||
const db = new Database('db/listings.db');
|
||||
const fields = ['serviceName', 'jobKey', 'id', 'size', 'rooms', 'price', 'address', 'title', 'link', 'description'];
|
||||
db.prepare(`CREATE TABLE IF NOT EXISTS listing (${fields.join(' TEXT, ')} TEXT);`).run();
|
||||
const insert = db.prepare(`INSERT INTO listing (${fields.join(', ')}) VALUES (@${fields.join(', @')})`);
|
||||
newListings.map((listing) => {
|
||||
let insertListing = {};
|
||||
fields.map((field) => {
|
||||
insertListing[field] = listing[field];
|
||||
});
|
||||
insertListing.serviceName = serviceName;
|
||||
insertListing.jobKey = jobKey;
|
||||
insert.run(insertListing);
|
||||
});
|
||||
return Promise.resolve();
|
||||
};
|
||||
export const config = {
|
||||
id: 'sqlite',
|
||||
name: 'Sqlite',
|
||||
description: 'This adapter stores listings in a local sqlite3 database.',
|
||||
config: {},
|
||||
readme: markdown2Html('lib/notification/adapter/sqlite.md'),
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
### Sqlite Adapter
|
||||
|
||||
This adapter stores search results in an sqlite database in db/listings.db
|
||||
@@ -19,7 +19,7 @@ const config = {
|
||||
sortByDateParam: null,
|
||||
crawlFields: {
|
||||
id: '.aditem@data-adid | int',
|
||||
price: '.aditem-main--middle--price | removeNewline | trim',
|
||||
price: '.aditem-main--middle--price-shipping--price | removeNewline | trim',
|
||||
size: '.aditem-main .text-module-end span:nth-child(2) | removeNewline | trim',
|
||||
title: '.aditem-main .text-module-begin a | removeNewline | trim',
|
||||
link: '.aditem-main .text-module-begin a@href | removeNewline | trim',
|
||||
|
||||
38
package.json
38
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "fredy",
|
||||
"version": "7.4.0",
|
||||
"version": "8.0.0",
|
||||
"description": "[F]ind [R]eal [E]states [d]amn eas[y].",
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
@@ -55,54 +55,54 @@
|
||||
"Firefox ESR"
|
||||
],
|
||||
"dependencies": {
|
||||
"@douyinfe/semi-ui": "2.44.0",
|
||||
"@douyinfe/semi-ui": "2.49.2",
|
||||
"@rematch/core": "2.2.0",
|
||||
"@rematch/loading": "2.1.2",
|
||||
"@sendgrid/mail": "7.7.0",
|
||||
"@vitejs/plugin-react": "4.1.0",
|
||||
"@sendgrid/mail": "8.1.0",
|
||||
"@vitejs/plugin-react": "4.2.1",
|
||||
"better-sqlite3": "8.6.0",
|
||||
"body-parser": "1.20.2",
|
||||
"cookie-session": "2.0.0",
|
||||
"handlebars": "4.7.8",
|
||||
"highcharts": "11.1.0",
|
||||
"highcharts": "11.2.0",
|
||||
"highcharts-react-official": "3.2.1",
|
||||
"lodash": "4.17.21",
|
||||
"lowdb": "6.0.1",
|
||||
"markdown": "^0.5.0",
|
||||
"nanoid": "4.0.2",
|
||||
"nanoid": "5.0.4",
|
||||
"node-fetch": "3.3.2",
|
||||
"node-mailjet": "6.0.4",
|
||||
"node-mailjet": "6.0.5",
|
||||
"query-string": "8.1.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-redux": "8.1.2",
|
||||
"react-redux": "9.0.4",
|
||||
"react-router": "5.2.1",
|
||||
"react-router-dom": "5.3.0",
|
||||
"redux": "4.2.1",
|
||||
"redux-thunk": "2.4.2",
|
||||
"redux": "5.0.1",
|
||||
"redux-thunk": "3.1.0",
|
||||
"restana": "4.9.7",
|
||||
"serve-static": "1.15.0",
|
||||
"slack": "11.0.2",
|
||||
"string-similarity": "^4.0.4",
|
||||
"vite": "4.4.9",
|
||||
"vite": "5.0.10",
|
||||
"x-ray": "2.3.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.23.0",
|
||||
"@babel/eslint-parser": "7.22.15",
|
||||
"@babel/preset-env": "7.22.20",
|
||||
"@babel/preset-react": "7.22.15",
|
||||
"chai": "4.3.9",
|
||||
"eslint": "8.50.0",
|
||||
"@babel/core": "7.23.7",
|
||||
"@babel/eslint-parser": "7.23.3",
|
||||
"@babel/preset-env": "7.23.7",
|
||||
"@babel/preset-react": "7.23.3",
|
||||
"chai": "5.0.0",
|
||||
"eslint": "8.56.0",
|
||||
"eslint-config-prettier": "8.8.0",
|
||||
"eslint-plugin-react": "7.33.2",
|
||||
"esmock": "2.5.1",
|
||||
"esmock": "2.6.0",
|
||||
"history": "5.3.0",
|
||||
"husky": "4.3.8",
|
||||
"less": "4.2.0",
|
||||
"lint-staged": "13.2.2",
|
||||
"mocha": "10.2.0",
|
||||
"prettier": "3.0.3",
|
||||
"prettier": "3.1.1",
|
||||
"redux-logger": "3.0.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import * as similarityCache from '../../lib/services/similarity-check/similarityCache.js';
|
||||
import { get } from '../mocks/mockNotification.js';
|
||||
import { providerConfig, mockFredy } from '../utils.js';
|
||||
import chai from 'chai';
|
||||
import { expect } from 'chai';
|
||||
import * as provider from '../../lib/provider/einsAImmobilien.js';
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('#einsAImmobilien testsuite()', () => {
|
||||
after(() => {
|
||||
similarityCache.stopCacheCleanup();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as similarityCache from '../../lib/services/similarity-check/similarityCache.js';
|
||||
import { get } from '../mocks/mockNotification.js';
|
||||
import { providerConfig, mockFredy } from '../utils.js';
|
||||
import chai from 'chai';
|
||||
import { expect } from 'chai';
|
||||
import * as provider from '../../lib/provider/immobilienDe.js';
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('#immobilien.de testsuite()', () => {
|
||||
after(() => {
|
||||
similarityCache.stopCacheCleanup();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import * as similarityCache from '../../lib/services/similarity-check/similarityCache.js';
|
||||
import { get } from '../mocks/mockNotification.js';
|
||||
import { mockFredy, providerConfig } from '../utils.js';
|
||||
import chai from 'chai';
|
||||
import { expect } from 'chai';
|
||||
import * as provider from '../../lib/provider/immonet.js';
|
||||
import * as scrapingAnt from '../../lib/services/scrapingAnt.js';
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('#immonet testsuite()', () => {
|
||||
after(() => {
|
||||
similarityCache.stopCacheCleanup();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import * as similarityCache from '../../lib/services/similarity-check/similarityCache.js';
|
||||
import { get } from '../mocks/mockNotification.js';
|
||||
import { mockFredy, providerConfig } from '../utils.js';
|
||||
import chai from 'chai';
|
||||
import { expect } from 'chai';
|
||||
import * as provider from '../../lib/provider/immoscout.js';
|
||||
import * as scrapingAnt from '../../lib/services/scrapingAnt.js';
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('#immoscout testsuite()', () => {
|
||||
after(() => {
|
||||
similarityCache.stopCacheCleanup();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as similarityCache from '../../lib/services/similarity-check/similarityCache.js';
|
||||
import { get } from '../mocks/mockNotification.js';
|
||||
import { mockFredy, providerConfig } from '../utils.js';
|
||||
import chai from 'chai';
|
||||
import { expect } from 'chai';
|
||||
import * as provider from '../../lib/provider/immoswp.js';
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('#immoswp testsuite()', () => {
|
||||
after(() => {
|
||||
similarityCache.stopCacheCleanup();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as similarityCache from '../../lib/services/similarity-check/similarityCache.js';
|
||||
import { get } from '../mocks/mockNotification.js';
|
||||
import { mockFredy, providerConfig } from '../utils.js';
|
||||
import chai from 'chai';
|
||||
import { expect } from 'chai';
|
||||
import * as provider from '../../lib/provider/immowelt.js';
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('#immowelt testsuite()', () => {
|
||||
after(() => {
|
||||
similarityCache.stopCacheCleanup();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as similarityCache from '../../lib/services/similarity-check/similarityCache.js';
|
||||
import { get } from '../mocks/mockNotification.js';
|
||||
import { mockFredy, providerConfig } from '../utils.js';
|
||||
import chai from 'chai';
|
||||
import { expect } from 'chai';
|
||||
import * as provider from '../../lib/provider/kleinanzeigen.js';
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('#kleinanzeigen testsuite()', () => {
|
||||
after(() => {
|
||||
similarityCache.stopCacheCleanup();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as similarityCache from '../../lib/services/similarity-check/similarityCache.js';
|
||||
import { get } from '../mocks/mockNotification.js';
|
||||
import { mockFredy, providerConfig } from '../utils.js';
|
||||
import chai from 'chai';
|
||||
import { expect } from 'chai';
|
||||
import * as provider from '../../lib/provider/neubauKompass.js';
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('#neubauKompass testsuite()', () => {
|
||||
after(() => {
|
||||
similarityCache.stopCacheCleanup();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import utils from '../../lib/utils.js';
|
||||
import assert from 'assert';
|
||||
import chai from 'chai';
|
||||
const expect = chai.expect;
|
||||
import { expect } from 'chai';
|
||||
|
||||
const fakeWorkingHoursConfig = (from, to) => ({
|
||||
workingHours: {
|
||||
to,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as similarityCache from '../../lib/services/similarity-check/similarityCache.js';
|
||||
import { get } from '../mocks/mockNotification.js';
|
||||
import { mockFredy, providerConfig } from '../utils.js';
|
||||
import chai from 'chai';
|
||||
import { expect } from 'chai';
|
||||
import * as provider from '../../lib/provider/wgGesucht.js';
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('#wgGesucht testsuite()', () => {
|
||||
after(() => {
|
||||
similarityCache.stopCacheCleanup();
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import fs from 'fs';
|
||||
import chai from 'chai';
|
||||
import { expect } from 'chai';
|
||||
import { readFile } from 'fs/promises';
|
||||
import mutator from '../../lib/services/queryStringMutator.js';
|
||||
import queryString from 'query-string';
|
||||
const expect = chai.expect;
|
||||
|
||||
const data = await readFile(new URL('./testData.json', import.meta.url));
|
||||
|
||||
const testData = JSON.parse(data);
|
||||
|
||||
let _provider = await Promise.all(
|
||||
fs.readdirSync('./lib/provider/').map(async (integPath) => await import(`../../lib/provider/${integPath}`))
|
||||
fs.readdirSync('./lib/provider/').map(async (integPath) => await import(`../../lib/provider/${integPath}`)),
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import SimilarityCacheEntry from '../../lib/services/similarity-check/SimilarityCacheEntry.js';
|
||||
import chai from 'chai';
|
||||
const expect = chai.expect;
|
||||
import { expect } from 'chai';
|
||||
|
||||
describe('similarityCheck', () => {
|
||||
describe('#similarityCheck()', () => {
|
||||
it('should be false', () => {
|
||||
@@ -29,10 +29,10 @@ describe('similarityCheck', () => {
|
||||
it('should be false', () => {
|
||||
const check = new SimilarityCacheEntry(0);
|
||||
check.setCacheEntry(
|
||||
'The index is known by several other names, especially Sørensen–Dice index,[3] Sørensen index and Dice\'s coefficient. Other variations include the "similarity coefficient" or "index", such as Dice similarity coefficient (DSC). Common alternate spellings for Sørensen are Sorenson, Soerenson and Sörenson, and all three can also be seen with the –sen ending.'
|
||||
'The index is known by several other names, especially Sørensen–Dice index,[3] Sørensen index and Dice\'s coefficient. Other variations include the "similarity coefficient" or "index", such as Dice similarity coefficient (DSC). Common alternate spellings for Sørensen are Sorenson, Soerenson and Sörenson, and all three can also be seen with the –sen ending.',
|
||||
);
|
||||
check.setCacheEntry(
|
||||
'where |X| and |Y| are the cardinalities of the two sets (i.e. the number of elements in each set). The Sørensen index equals twice the number of elements common to both sets divided by the sum of the number of elements in each set.'
|
||||
'where |X| and |Y| are the cardinalities of the two sets (i.e. the number of elements in each set). The Sørensen index equals twice the number of elements common to both sets divided by the sum of the number of elements in each set.',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user