nl2go / hetzner-invoice

Automatically download and transform Hetzner invoices.
MIT License
12 stars 1 forks source link

Hetzner security check #26

Open ScepticMatt opened 1 year ago

ScepticMatt commented 1 year ago

Hetzner has implemented a security check (wich simple forwarding) to try and prevent bot access:

image

smarakdas314 commented 10 months ago

you can use playwright to simulate web browser, very sad Hetzner doesn't give API, scripts means to download csv invoices here's my day of work you can use

pip install playwright playwright-stealth && playwright install chromium

Script downloads latest invoice to /tmp

from playwright.sync_api import sync_playwright
from playwright_stealth import stealth_sync
import time

USERNAME = "admin@foobar.com"
PASSWORD = "CHANGEME"

def main():
    with sync_playwright() as p:
        # Launch a browser
        browser = p.chromium.launch(headless=True)

        # Create a new context with a custom user agent
        context = browser.new_context(user_agent='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36')

        # Create a new page within the context
        page = context.new_page()
        stealth_sync(page)

        # Navigate to a website
        page.goto('https://accounts.hetzner.com/login')

        # Fill in the username and password fields
        page.type('input#_username', USERNAME) 
        page.type('input#_password', PASSWORD)

        # Click on the login button
        page.click('input#submit-login')

        page.wait_for_load_state('load')

        page.goto('https://accounts.hetzner.com/invoice')

        # Wait for the first CSV link to be present
        csv_selector = 'a.btn-download[href*="/invoice/"][href$="/csv"]'
        page.wait_for_selector(csv_selector)

        # Get the URL of the first CSV link
        csv_link_url = page.query_selector(csv_selector).get_attribute('href')
        print(f"CSV Link URL: {csv_link_url}")

        with page.expect_download() as download_info:
            # Click the first CSV link
            page.click(csv_selector)

        download = download_info.value

        download.save_as("/tmp/" + download.suggested_filename)
        print(f"Download finished: {download.url}")

        browser.close()

if __name__ == "__main__":
    main()
Jetman80 commented 1 month ago

@smarakdas314 thanks for this script, saved a lot of time for me. Here is a short snippet to add 2FA:

...
import pyotp
...
...
page.wait_for_load_state("load")

totp = pyotp.TOTP(TWOFA_SECRET)
otp = totp.now()
# Fill in the 2FA code
page.type("input#input-verify-code", otp)
# Click on the verify button
page.click("input#btn-submit")

page.wait_for_load_state("load")
...
smarakdas314 commented 1 month ago

Glad to hear it @Jetman80 I had other idea for 2FA to implement invoice forwarding via group email to separate email address and fetching csv invoice from mailbox via IMAP implementation.

cicadadevops commented 3 days ago

https://github.com/roysbike/hetzner-invoice-exporter/blob/main/get_hz_invoice_csv.py

new billing model

https://docs.hetzner.com/general/others/changes-to-billing-system-for-october-2024