Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.4.0 #75

Merged
merged 32 commits into from
Nov 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f0134d1
1.3.3
neopostmodern Feb 2, 2021
61387a2
Merge branch 'master' into dev
neopostmodern Feb 15, 2021
68bf647
ci: add p flag to tar for macOS repackaging
neopostmodern Feb 16, 2021
6efb4c2
1.3.4
neopostmodern Feb 16, 2021
0c312b8
fix: request announcements from wohnungsbot.de
neopostmodern Feb 23, 2021
cddd028
feat: sort by date listed (newest), closes #54
neopostmodern Feb 23, 2021
b66a47f
Merge branch 'master' into dev
neopostmodern Feb 23, 2021
2b0c8b6
-Added immobilienScout24 data types.
avaleriani Sep 9, 2021
0fe619f
-Login actions condensed under bot actions type.
avaleriani Sep 13, 2021
2d7e697
-Added logout functionality.
avaleriani Sep 13, 2021
a17702a
-Fixed error on login process.
avaleriani Sep 13, 2021
6e9032f
-Added missing prettier config to match current code style.
avaleriani Sep 13, 2021
fe3bbe2
style: linting
neopostmodern Nov 22, 2021
54c0914
fix: check whether node-integration is available in app.html before a…
neopostmodern Nov 22, 2021
414ac82
chore: update package-lock.json
neopostmodern Nov 22, 2021
1ecfd3e
fix: harden and improve account flows
neopostmodern Nov 22, 2021
b043b10
style: linting
neopostmodern Nov 22, 2021
0147082
fix: inject CSS to hide cookie banner before initial sleep
neopostmodern Nov 22, 2021
2c250ce
feat: update indicator in sidebar, closes #26
neopostmodern Nov 22, 2021
aa839f5
fix: update URL schema
neopostmodern Nov 24, 2021
d1857c7
fix: art consent box displays correct value
neopostmodern Nov 24, 2021
f818bb2
chore: update project URL everywhere
neopostmodern Nov 24, 2021
696bc02
fix: fill additional fields on same page (if present) when logged in
neopostmodern Nov 24, 2021
010286f
feat: save data to IS24 profile if action is offered
neopostmodern Nov 24, 2021
7f8a9e4
fix: add small delay before accessing current value of text
neopostmodern Nov 24, 2021
073335e
feat: don't show a speech bubble when there's nothing really to say
neopostmodern Nov 25, 2021
c2ef1e0
refactor: don't store electron objects (BrowserWindow, BrowserView) i…
neopostmodern Nov 25, 2021
b01ce1c
chore: update all dependencies
neopostmodern Nov 25, 2021
3cefa3a
style: prettier
neopostmodern Nov 25, 2021
d2c91be
ci: use node v16 explicitly
neopostmodern Nov 25, 2021
468349e
build: include preload.js in build package
neopostmodern Nov 25, 2021
f25b64f
1.4.0
neopostmodern Nov 27, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/build-electron-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install dependencies
run: npm ci
- name: Decrypt keys
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/build-electron-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install dependencies
run: npm ci
- name: Decrypt keys
Expand Down
4 changes: 3 additions & 1 deletion .prettierrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@
}
}
],
"singleQuote": true
"singleQuote": true,
"trailingComma": "none",
"printWidth": 80
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Der Wohnungsbot ist Teil der Ausstellung *Von einem der auszog eine Wohnung in Berlin zu finden. Ein Automatisierungsdrama in drei Akten — 2. Akt: Das Versprechen des Bots*

## Info
[Website](https://wohnung.neopostmodern.com/)
[Website](https://wohnungsbot.de/)
[Ausstellungsansichten (vorläufig)](https://bericht.neopostmodern.com/portfolio/von-einem-der-auszog-eine-wohnung-in-berlin-zu-finden-2-akt)
[Artikel bei *Tagesspiegel Leute*](https://leute.tagesspiegel.de/neukoelln/unter-nachbarn/2019/09/11/95231/)

Expand Down
16 changes: 8 additions & 8 deletions app/Routes.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Switch, Route } from 'react-router';
import { Routes, Route } from 'react-router-dom';
import routes from './constants/routes';
import App from './containers/App';
import ConfigurationPage from './containers/ConfigurationPage';
Expand All @@ -10,12 +10,12 @@ import PlaceholderPage from './containers/PlaceholderPage';

export default () => (
<App>
<Switch>
<Route path={routes.SIDEBAR} component={SidebarPage} />
<Route path={routes.BOT_OVERLAY} component={BotOverlayPage} />
<Route path={routes.CONFIGURATION} component={ConfigurationPage} />
<Route path={routes.DEV_MENU} component={DevMenuPage} />
<Route path={routes.PLACEHOLDER} component={PlaceholderPage} />
</Switch>
<Routes>
<Route path={routes.SIDEBAR} element={<SidebarPage />} />
<Route path={routes.BOT_OVERLAY} element={<BotOverlayPage />} />
<Route path={routes.CONFIGURATION} element={<ConfigurationPage />} />
<Route path={routes.DEV_MENU} element={<DevMenuPage />} />
<Route path={routes.PLACEHOLDER} element={<PlaceholderPage />} />
</Routes>
</App>
);
127 changes: 60 additions & 67 deletions app/actions/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { markCompleted } from './cache';
import { sleep, timeout } from '../utils/async';
import type { Configuration } from '../reducers/configuration';
import type { dataStateType, OverviewDataEntry } from '../reducers/data';
import type { electronStateType } from '../reducers/electron';
import { electronObjects } from '../store/electronObjects';
import ElectronUtilsRedux from '../utils/electronUtilsRedux';
import {
popFlatFromQueue,
Expand All @@ -25,62 +25,56 @@ import AbortionSystem, {
ABORTION_MANUAL
} from '../utils/abortionSystem';

export const generateApplicationTextAndSubmit = (flatId: string) => async (
dispatch: Dispatch,
getState: GetState
) => {
const {
configuration,
data,
electron
}: {
configuration: Configuration,
data: dataStateType,
electron: electronStateType,
cache: cacheStateType
} = getState();
export const generateApplicationTextAndSubmit =
(flatId: string) => async (dispatch: Dispatch, getState: GetState) => {
const {
configuration,
data
}: {
configuration: Configuration,
data: dataStateType
} = getState();

const { webContents } = electron.views.puppet.browserView;
const electronUtils = new ElectronUtilsRedux(webContents, dispatch);
const { webContents } = electronObjects.views.puppet;
const electronUtils = new ElectronUtilsRedux(webContents, dispatch);

const pdfPath = await dispatch(printToPDF('puppet', flatId));
const pdfPath = await dispatch(printToPDF('puppet', flatId));

const { abortableAction: abortablePerformApplication, abort } = abortable(
performApplication
);
AbortionSystem.registerAbort(abort);
let success;
let reason;
try {
await timeout(
abortablePerformApplication(
dispatch,
electronUtils,
configuration,
data.overview[flatId]
),
300000
);
success = true;
} catch (error) {
// eslint-disable-next-line no-console
console.error(`Error in application:
const { abortableAction: abortablePerformApplication, abort } =
abortable(performApplication);
AbortionSystem.registerAbort(abort);
let success;
let reason;
try {
await timeout(
abortablePerformApplication(
dispatch,
electronUtils,
configuration,
data.overview[flatId]
),
300000
);
success = true;
} catch (error) {
// eslint-disable-next-line no-console
console.error(`Error in application:
${error}`);
success = false;
AbortionSystem.abort(ABORTION_ERROR);
reason = error.message;
}
if (AbortionSystem.abortionReason !== ABORTION_MANUAL) {
await markApplicationCompleted(dispatch, {
flatId,
success,
addressDescription: data.overview[flatId].address.description,
reason,
pdfPath
});
}
await dispatch(endApplicationProcess());
};
success = false;
AbortionSystem.abort(ABORTION_ERROR);
reason = error.message;
}
if (AbortionSystem.abortionReason !== ABORTION_MANUAL) {
await markApplicationCompleted(dispatch, {
flatId,
success,
addressDescription: data.overview[flatId].address.description,
reason,
pdfPath
});
}
await dispatch(endApplicationProcess());
};

const markApplicationCompleted = async (
dispatch: Dispatch,
Expand Down Expand Up @@ -108,17 +102,16 @@ export const endApplicationProcess = () => async (dispatch: Dispatch) => {
dispatch(setShowOverlay(true));
};

export const discardApplicationProcess = (
flatOverview: OverviewDataEntry
) => async (dispatch: Dispatch) => {
dispatch(setBotMessage(`Wohnung ist leider unpassend :(`));
await sleep(5000);
dispatch(popFlatFromQueue(flatOverview.id));
await markApplicationCompleted(dispatch, {
flatId: flatOverview.id,
success: false,
addressDescription: flatOverview.address.description,
reason: 'UNSUITABLE' // this won't show up in the sidebar
});
await dispatch(endApplicationProcess());
};
export const discardApplicationProcess =
(flatOverview: OverviewDataEntry) => async (dispatch: Dispatch) => {
dispatch(setBotMessage(`Wohnung ist leider unpassend :(`));
await sleep(5000);
dispatch(popFlatFromQueue(flatOverview.id));
await markApplicationCompleted(dispatch, {
flatId: flatOverview.id,
success: false,
addressDescription: flatOverview.address.description,
reason: 'UNSUITABLE' // this won't show up in the sidebar
});
await dispatch(endApplicationProcess());
};
98 changes: 60 additions & 38 deletions app/actions/bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,21 @@ import {
TASK_FINISHED,
SCROLL_WHILE_IDLE,
STOP_SCROLLING_WHILE_IDLE,
RESET_BOT
RESET_BOT,
LOGIN,
LOGOUT
} from '../constants/actionTypes';
import { electronObjects } from '../store/electronObjects';
import { sleep } from '../utils/async';
import { clickAction, scrollIntoViewAction } from './botHelpers';
import { calculateOverviewBoundingBoxes } from './overlay';
import ElectronUtils from '../utils/electronUtils';
import AbortionSystem from '../utils/abortionSystem';
import { entrySelector, entryTitleSelector } from '../utils/selectors';
import { electronRouting, setBrowserViewReady } from './electron';
import type { LoginData } from '../reducers/configuration';
import { LOGINSTATUS } from '../reducers/configuration';
import { setConfiguration } from './configuration';

export function queueInvestigateFlat(flatId: string): Action {
return async (dispatch: Dispatch, getState: GetState) => {
Expand All @@ -43,45 +49,37 @@ export function popFlatFromQueue(flatId: string): Action {
};
}

export const clickLogin = () => async (dispatch: Dispatch) => {
await dispatch(clickAction('#link_loginAccountLink'));
await sleep(1000);
await dispatch(clickAction('#link_loginLinkInternal'));
};

export const navigateToFlatPage = (flatId: string) => async (
dispatch: Dispatch,
getState: GetState
) => {
await sleep(10000);
dispatch(setBotIsActing(true));
dispatch(setBotMessage(`Wohnung ${flatId} suchen...`));
dispatch(setShowOverlay(false));
await dispatch(scrollIntoViewAction('puppet', entrySelector(flatId)));
dispatch(calculateOverviewBoundingBoxes());
dispatch(setShowOverlay(true));
await sleep(5000);
dispatch(setShowOverlay(false));
dispatch(setBotMessage(`Wohnung ${flatId} genauer anschauen!`));

const puppetView = new ElectronUtils(
getState().electron.views.puppet.browserView.webContents
);

const flatTitleSelector = entryTitleSelector(flatId);

/* eslint-disable no-await-in-loop */
while (AbortionSystem.nestedFunctionsMayContinue) {
if (!(await puppetView.elementExists(flatTitleSelector))) {
return true;
}
await dispatch(clickAction(flatTitleSelector));
export const navigateToFlatPage =
(flatId: string) => async (dispatch: Dispatch) => {
await sleep(10000);
dispatch(setBotIsActing(true));
dispatch(setBotMessage(`Wohnung ${flatId} suchen...`));
dispatch(setShowOverlay(false));
await dispatch(scrollIntoViewAction('puppet', entrySelector(flatId)));
dispatch(calculateOverviewBoundingBoxes());
dispatch(setShowOverlay(true));
await sleep(5000);
}
/* eslint-enable no-await-in-loop */
dispatch(setShowOverlay(false));
dispatch(setBotMessage(`Wohnung ${flatId} genauer anschauen!`));

const puppetView = new ElectronUtils(
electronObjects.views.puppet.webContents
);

const flatTitleSelector = entryTitleSelector(flatId);

/* eslint-disable no-await-in-loop */
while (AbortionSystem.nestedFunctionsMayContinue) {
if (!(await puppetView.elementExists(flatTitleSelector))) {
return true;
}
await dispatch(clickAction(flatTitleSelector));
await sleep(5000);
}
/* eslint-enable no-await-in-loop */

return false;
};
return false;
};

export function setBotIsActing(isActing: boolean): Action {
return {
Expand Down Expand Up @@ -153,3 +151,27 @@ export function resetBot(): Action {
payload: null
};
}

export function login(immobilienScout24Data: LoginData): Action {
return {
type: LOGIN,
payload: {
immobilienScout24Data
}
};
}

export function logout(): Action {
return {
type: LOGOUT,
payload: null
};
}

export function setLoginStatus(loginStatus: LOGINSTATUS): Action {
return async (dispatch: Dispatch, getState: GetState) => {
const { configuration } = getState();
configuration.immobilienScout24.status = loginStatus;
dispatch(setConfiguration(configuration));
};
}
Loading