Skip to content

Commit 5a05fac

Browse files
committed
Update
1 parent 96f8cf9 commit 5a05fac

19 files changed

Lines changed: 935 additions & 800 deletions

.github/workflows/pre-commit-workflow.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
- name: Setup Python - https://github.com/actions/setup-python
2929
uses: actions/setup-python@v6
3030
with:
31-
python-version: '3.x' # Latest stable major version of Python
31+
python-version: "3.x" # Latest stable major version of Python
3232

3333
- name: Install Python dependencies
3434
run: |

.pre-commit-config.yaml

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
## Pre-commit configuration
2-
# Last update: 2025-09-14
2+
# Last update: 2025-10-20
33

44
# Save this file to '/.pre-commit-config.yaml'
55

66
repos:
7+
- repo: local
8+
hooks:
9+
- id: prettier
10+
name: prettier
11+
entry: prettier --write --print-width 220 --ignore-unknown
12+
language: node
13+
types_or: [javascript, jsx, ts, tsx, json, css, scss, html, markdown, yaml]
14+
additional_dependencies:
15+
- prettier@latest
16+
717
- repo: https://github.com/pre-commit/pre-commit-hooks
818
rev: v6.0.0
919
hooks:
@@ -24,13 +34,12 @@ repos:
2434
- id: check-yaml
2535
- id: debug-statements
2636
- id: destroyed-symlinks
27-
# - id: detect-aws-credentials
2837
- id: detect-private-key
2938
- id: file-contents-sorter
3039
- id: fix-byte-order-marker
40+
- id: forbid-submodules
41+
args: ["--fix=lf"]
3142
- id: forbid-new-submodules
32-
# - id: forbid-submodules
33-
# args: ["--fix=lf"]
3443
- id: mixed-line-ending
3544
args: ["--fix=lf"]
3645
- id: pretty-format-json
@@ -44,36 +53,14 @@ repos:
4453
- id: taplo-format
4554
- id: taplo-lint
4655

47-
- repo: https://github.com/rtts/djhtml
48-
rev: 3.0.10 # Without leading 'v'
49-
hooks:
50-
# - id: djhtml
51-
- id: djcss
52-
- id: djjs
53-
54-
# - repo: https://github.com/igorshubovych/markdownlint-cli
55-
# rev: v0.44.0
56-
# hooks:
57-
# - id: markdownlint
58-
# language: system
59-
# types: [markdown]
60-
# args: ["--disable=MD013", "--disable=MD024", "--disable=MD033", "--disable=MD045"]
61-
6256
- repo: https://github.com/sqlfluff/sqlfluff
63-
rev: 3.4.2 # Without leading 'v'
57+
rev: 3.5.0
6458
hooks:
6559
- id: sqlfluff-fix
6660
args: ["--dialect=mysql", "--exclude-rules=ambiguous.column_count, layout.long_lines, references.keywords"]
6761

68-
# - repo: https://github.com/digitalpulp/pre-commit-php # Requires brew install php-cs-fixer
69-
# rev: 1.4.0 # Without leading 'v'
70-
# hooks:
71-
# - id: php-cs-fixer
72-
# files: \.(php)$
73-
# args: [--rules=@PSR12]
74-
7562
- repo: https://github.com/astral-sh/ruff-pre-commit
76-
rev: v0.14.0
63+
rev: v0.14.1
7764
hooks:
7865
- id: ruff
7966
args: ["--fix", "--exit-non-zero-on-fix", "--ignore=B007,B023,C408,D103,E203,E266,E402,E501,F821,S105,S110,S310,SIM105"] # ruff-pre-commit does not recognize these rule selectors: B902,CM001,S410,SCS109,W503,W504
@@ -84,7 +71,7 @@ repos:
8471
rev: v1.10.0
8572
hooks:
8673
- id: python-check-blanket-noqa
87-
# - id: python-check-blanket-type-ignore
74+
- id: python-check-blanket-type-ignore
8875
- id: python-check-mock-methods
8976
- id: python-no-eval
9077
- id: python-no-log-warn
@@ -98,13 +85,13 @@ repos:
9885
rev: v3.21.0
9986
hooks:
10087
- id: pyupgrade
101-
args: ["--py313-plus"]
88+
args: ["--py314-plus"]
10289

10390
- repo: https://github.com/codespell-project/codespell
10491
rev: v2.4.1
10592
hooks:
10693
- id: codespell
107-
exclude: '^data/'
94+
exclude: "^data/"
10895
args: ["--ignore-words-list=alle,als,bootup,datas,deine,dokument,doubleclick,fo,ges,ist,itens,nax,oder,produkt,referers,ressource,ser,sie,tage,termine"] # The --ignore-words-list argument has a bug where it needs to be lowercase, see: https://github.com/codespell-project/codespell/issues/1390
10996

11097
default_language_version:
Lines changed: 121 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,131 +1,137 @@
11
// DHL Geschäftskundenportal Invoices Download - Puppeteer script that logs in, filters invoices for the previous month, and extracts their details for download
22
// Last update: 2025-10-03
33

4-
54
const puppeteer = require("puppeteer");
65

76
// Settings
87
const username = $env.DHL_USERNAME;
98
const password = $env.DHL_PASSWORD;
109

11-
1210
// Define an async function to contain all your await calls
1311
async function dhlGeschaftskundenportalInvoicesDownload() {
14-
const browser = await puppeteer.launch({
15-
headless: false,
16-
args: ["--no-sandbox", "--disable-setuid-sandbox", "--start-fullscreen"],
17-
});
18-
19-
const page = await browser.newPage();
20-
21-
// Settings
22-
await page.setViewport({ width: 1920, height: 1080 });
23-
await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36");
24-
// page.on('console', msg => console.log('BROWSER CONSOLE:', msg.text()));
25-
26-
// Navigate to login page
27-
await page.goto("https://geschaeftskunden.dhl.de");
28-
29-
// Cookies
30-
await page.waitForSelector("#onetrust-reject-all-handler", { visible: true, timeout: 5000 }).catch((e) => {
31-
console.log("Cookie consent button not found or already gone.");
12+
const browser = await puppeteer.launch({
13+
headless: false,
14+
args: ["--no-sandbox", "--disable-setuid-sandbox", "--start-fullscreen"],
15+
});
16+
17+
const page = await browser.newPage();
18+
19+
// Settings
20+
await page.setViewport({ width: 1920, height: 1080 });
21+
await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36");
22+
// page.on('console', msg => console.log('BROWSER CONSOLE:', msg.text()));
23+
24+
// Navigate to login page
25+
await page.goto("https://geschaeftskunden.dhl.de");
26+
27+
// Cookies
28+
await page
29+
.waitForSelector("#onetrust-reject-all-handler", {
30+
visible: true,
31+
timeout: 5000,
32+
})
33+
.catch((e) => {
34+
console.log("Cookie consent button not found or already gone.");
3235
});
33-
if (await page.$("#onetrust-reject-all-handler")) {
34-
await page.click("#onetrust-reject-all-handler");
35-
await page.waitForNavigation();
36-
}
37-
38-
// "Anmelden"
39-
await page.waitForSelector("#button-noName", { visible: true });
40-
await page.click("#button-noName");
41-
42-
// Fill in credentials
43-
await page.waitForSelector("#username", { visible: true, timeout: 10000 });
44-
await page.type("#username", username);
45-
await page.type("#password", password);
46-
47-
// Login
48-
await page.click('button[type="submit"]');
36+
if (await page.$("#onetrust-reject-all-handler")) {
37+
await page.click("#onetrust-reject-all-handler");
4938
await page.waitForNavigation();
50-
51-
// Navigate to invoice section
52-
await page.goto("https://geschaeftskunden.dhl.de/billing/invoice/overview");
53-
54-
// Display "Last 3 months" invoices
55-
await page.waitForSelector('[data-testid="date-range-input-field-function-icon-billingView-filter-dateRange"]');
56-
await page.click('[data-testid="date-range-input-field-function-icon-billingView-filter-dateRange"]');
57-
const presetDropdownSelector = '[data-testid="billingView-filter-dateRange-footer-presetRangeSelector"]';
58-
await page.waitForSelector(presetDropdownSelector, { visible: true });
59-
await page.select(presetDropdownSelector, "1");
60-
const submitButtonSelector = '[data-testid="billingView-filter-dateRange-footer-submit"]';
61-
await page.waitForSelector(submitButtonSelector, { visible: true, timeout: 5000 });
62-
await page.click(submitButtonSelector);
63-
64-
// Define the month and year for the previous month
65-
const today = new Date();
66-
const targetDate = new Date(today.getFullYear(), today.getMonth() - 1, 1);
67-
const targetMonth = targetDate.getMonth();
68-
const targetYear = targetDate.getFullYear();
69-
70-
// Get invoices details
71-
await page.waitForSelector('table[data-testid="billingView"] tbody > tr.dhlTable-row-default', { visible: true, timeout: 10000 });
72-
73-
const invoices = await page.evaluate(
74-
(month, year) => {
75-
const table = document.querySelector('table[data-testid="billingView"]');
76-
const rows = Array.from(table.querySelectorAll("tbody > tr.dhlTable-row-default"));
77-
const data = [];
78-
79-
for (const row of rows) {
80-
const dateCell = row.querySelector(".dhlTablecell:nth-child(2)");
81-
const invoiceNumberCell = row.querySelector(".dhlTablecell:nth-child(3)");
82-
const descriptionCell = row.querySelector(".dhlTablecell:nth-child(4)");
83-
const amountCell = row.querySelector(".dhlTablecell:nth-child(5)");
84-
85-
if (dateCell && invoiceNumberCell && descriptionCell && amountCell) {
86-
const dateText = dateCell.textContent.trim();
87-
const parts = dateText.split(".");
88-
const invoiceMonth = parseInt(parts[1], 10) - 1;
89-
const invoiceYear = parseInt(parts[2], 10);
90-
91-
if (invoiceMonth === month && invoiceYear === year) {
92-
const invoiceNumber = invoiceNumberCell.textContent.trim();
93-
const invoiceDescription = descriptionCell.textContent.trim();
94-
const invoiceAmount = amountCell.textContent.trim();
95-
96-
const downloadButton = row.querySelector("td .svgIcon-pdf").closest("button");
97-
const buttonId = downloadButton ? downloadButton.id : null;
98-
99-
data.push({
100-
date: dateText,
101-
invoiceNumber: invoiceNumber,
102-
description: invoiceDescription,
103-
amount: invoiceAmount,
104-
buttonId: buttonId,
105-
});
106-
}
107-
}
108-
}
109-
return data;
110-
},
111-
targetMonth,
112-
targetYear
113-
);
114-
115-
console.log("Filtered Invoices for Last Month:", invoices);
116-
117-
// Close browser
118-
await browser.close();
119-
120-
return invoices.map((invoice) => ({
121-
json: {
122-
date: invoice.dateText,
123-
invoiceNumber: invoice.invoiceNumber,
124-
description: invoice.description,
125-
amount: invoice.amount,
126-
buttonId: invoice.buttonId,
127-
},
128-
}));
39+
}
40+
41+
// "Anmelden"
42+
await page.waitForSelector("#button-noName", { visible: true });
43+
await page.click("#button-noName");
44+
45+
// Fill in credentials
46+
await page.waitForSelector("#username", { visible: true, timeout: 10000 });
47+
await page.type("#username", username);
48+
await page.type("#password", password);
49+
50+
// Login
51+
await page.click('button[type="submit"]');
52+
await page.waitForNavigation();
53+
54+
// Navigate to invoice section
55+
await page.goto("https://geschaeftskunden.dhl.de/billing/invoice/overview");
56+
57+
// Display "Last 3 months" invoices
58+
await page.waitForSelector('[data-testid="date-range-input-field-function-icon-billingView-filter-dateRange"]');
59+
await page.click('[data-testid="date-range-input-field-function-icon-billingView-filter-dateRange"]');
60+
const presetDropdownSelector = '[data-testid="billingView-filter-dateRange-footer-presetRangeSelector"]';
61+
await page.waitForSelector(presetDropdownSelector, { visible: true });
62+
await page.select(presetDropdownSelector, "1");
63+
const submitButtonSelector = '[data-testid="billingView-filter-dateRange-footer-submit"]';
64+
await page.waitForSelector(submitButtonSelector, {
65+
visible: true,
66+
timeout: 5000,
67+
});
68+
await page.click(submitButtonSelector);
69+
70+
// Define the month and year for the previous month
71+
const today = new Date();
72+
const targetDate = new Date(today.getFullYear(), today.getMonth() - 1, 1);
73+
const targetMonth = targetDate.getMonth();
74+
const targetYear = targetDate.getFullYear();
75+
76+
// Get invoices details
77+
await page.waitForSelector('table[data-testid="billingView"] tbody > tr.dhlTable-row-default', { visible: true, timeout: 10000 });
78+
79+
const invoices = await page.evaluate(
80+
(month, year) => {
81+
const table = document.querySelector('table[data-testid="billingView"]');
82+
const rows = Array.from(table.querySelectorAll("tbody > tr.dhlTable-row-default"));
83+
const data = [];
84+
85+
for (const row of rows) {
86+
const dateCell = row.querySelector(".dhlTablecell:nth-child(2)");
87+
const invoiceNumberCell = row.querySelector(".dhlTablecell:nth-child(3)");
88+
const descriptionCell = row.querySelector(".dhlTablecell:nth-child(4)");
89+
const amountCell = row.querySelector(".dhlTablecell:nth-child(5)");
90+
91+
if (dateCell && invoiceNumberCell && descriptionCell && amountCell) {
92+
const dateText = dateCell.textContent.trim();
93+
const parts = dateText.split(".");
94+
const invoiceMonth = parseInt(parts[1], 10) - 1;
95+
const invoiceYear = parseInt(parts[2], 10);
96+
97+
if (invoiceMonth === month && invoiceYear === year) {
98+
const invoiceNumber = invoiceNumberCell.textContent.trim();
99+
const invoiceDescription = descriptionCell.textContent.trim();
100+
const invoiceAmount = amountCell.textContent.trim();
101+
102+
const downloadButton = row.querySelector("td .svgIcon-pdf").closest("button");
103+
const buttonId = downloadButton ? downloadButton.id : null;
104+
105+
data.push({
106+
date: dateText,
107+
invoiceNumber: invoiceNumber,
108+
description: invoiceDescription,
109+
amount: invoiceAmount,
110+
buttonId: buttonId,
111+
});
112+
}
113+
}
114+
}
115+
return data;
116+
},
117+
targetMonth,
118+
targetYear,
119+
);
120+
121+
console.log("Filtered Invoices for Last Month:", invoices);
122+
123+
// Close browser
124+
await browser.close();
125+
126+
return invoices.map((invoice) => ({
127+
json: {
128+
date: invoice.dateText,
129+
invoiceNumber: invoice.invoiceNumber,
130+
description: invoice.description,
131+
amount: invoice.amount,
132+
buttonId: invoice.buttonId,
133+
},
134+
}));
129135
}
130136

131137
dhlGeschaftskundenportalInvoicesDownload().catch(console.error);

0 commit comments

Comments
 (0)