Open ScepticMatt opened 1 year 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()
@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")
...
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.
Hetzner has implemented a security check (wich simple forwarding) to try and prevent bot access: