From 8f67d387ccff1a8f084de7b6d0863a2f8af7ba1d Mon Sep 17 00:00:00 2001 From: markfodor Date: Sun, 26 Jan 2025 14:44:15 +0100 Subject: [PATCH 1/3] remove selenium and test with playwright, add runconfig --- .run/run InkCheck.run.xml | 25 +++++++++++++++++++ renderer/renderer.py | 49 ++++++++++++++------------------------ requirements.txt | Bin 2568 -> 2568 bytes 3 files changed, 43 insertions(+), 31 deletions(-) create mode 100644 .run/run InkCheck.run.xml diff --git a/.run/run InkCheck.run.xml b/.run/run InkCheck.run.xml new file mode 100644 index 0000000..eb1c57e --- /dev/null +++ b/.run/run InkCheck.run.xml @@ -0,0 +1,25 @@ + + + + + \ No newline at end of file diff --git a/renderer/renderer.py b/renderer/renderer.py index 3554064..6b8433f 100644 --- a/renderer/renderer.py +++ b/renderer/renderer.py @@ -3,15 +3,13 @@ instance, sized to the resolution of the eInk display and takes a screenshot. """ -from selenium import webdriver -from selenium.webdriver.chrome.options import Options -from time import sleep from jinja2 import Environment, FileSystemLoader from selenium.webdriver.common.by import By from logger.logger import logger import pathlib -import shutil import os +from playwright.sync_api import sync_playwright + class Renderer: @@ -23,7 +21,7 @@ def __init__(self, width, height): self.output_html = 'inkcheck.html' self.curr_path = str(pathlib.Path(__file__).parent.absolute()) self.project_path = os.path.abspath(os.curdir) - + self.absolute_input_html_template_path = os.path.join(self.curr_path, self.input_html_template) self.absolute_output_folder = os.path.join(self.project_path, self.output_folder) self.output_html_file_path = os.path.join(self.curr_path, self.output_html) @@ -37,7 +35,7 @@ def set_viewport_size(self, driver): current_window_size = driver.get_window_size() # Extract the client window size from the html tag - html = driver.find_element(By.TAG_NAME,'html') + html = driver.find_element(By.TAG_NAME, 'html') inner_width = int(html.get_attribute("clientWidth")) inner_height = int(html.get_attribute("clientHeight")) @@ -50,29 +48,23 @@ def set_viewport_size(self, driver): height=target_height ) - def take_screenshot(self): + def _take_screenshot(self): if not os.path.exists(self.output_html_file_path): - logger.error(f"HTML file does not exist: {self.output_html_file_path}. Probably not created properly from the template.") + logger.error( + f"HTML file does not exist: {self.output_html_file_path}. Probably not created properly from the template.") return - + if not os.path.exists(self.absolute_output_folder): os.mkdir(self.absolute_output_folder) - opts = Options() - opts.add_argument("--headless") - opts.add_argument("--hide-scrollbars") - opts.add_argument('--force-device-scale-factor=1') - driver = webdriver.Chrome(options=opts) - self.set_viewport_size(driver) - - driver.get('file://' + self.output_html_file_path) - sleep(1) - - success = driver.get_screenshot_as_file(self.output_image_path) - if success: - logger.info('Screenshot captured and saved to file.') - else: - logger.error('ERROR during the screen capture.') + with sync_playwright() as playwright: + webkit = playwright.webkit + browser = webkit.launch() + context = browser.new_context() + page = context.new_page() + page.goto(f"file://{self.output_html_file_path}") + page.screenshot(path=self.output_image_path) + browser.close() def render(self, timestamp, data_list, destination_folder): template_loader = FileSystemLoader(self.curr_path) @@ -86,11 +78,7 @@ def render(self, timestamp, data_list, destination_folder): file.write(rendered_template) logger.info(f"Template is rendered and saved to {self.output_html_file_path}") - self.take_screenshot() - self.copy_to_destination_folder(destination_folder) - - def copy_to_destination_folder(self, destination_folder): if not destination_folder or not os.path.isdir(destination_folder): logger.error('Destination folder is not configured properly.') return @@ -98,6 +86,5 @@ def copy_to_destination_folder(self, destination_folder): if not os.path.exists(destination_folder): os.makedirs(destination_folder) logger.info(f"Destination folder created: {destination_folder}") - - shutil.copy(self.output_image_path, destination_folder) - logger.info(f"Image copied to destination folder: {destination_folder}") + + self._take_screenshot() diff --git a/requirements.txt b/requirements.txt index 76054298845b9233a40bfdcb7a830f3069c2018f..cb70c80c95f5d60da6231ddf3681d2b11a551969 100644 GIT binary patch delta 49 zcmeAW=@8j)hJEt~b_phx0)`xhM21R+a)u&?OonuZ42BX0TOc%K&|@%RumqBZ3;<6V B3X}i< delta 42 ucmeAW=@8j)hFvz5A%`KAA&()Gp_Cz)!4?Qj81xtnfl!aZX!B8ac_skd-3bN& From 6b8c73333af7e9654aaff020599cdda0167f65ce Mon Sep 17 00:00:00 2001 From: markfodor Date: Sun, 26 Jan 2025 15:37:02 +0100 Subject: [PATCH 2/3] remove selenium leftover --- renderer/renderer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/renderer/renderer.py b/renderer/renderer.py index 6b8433f..f4debfd 100644 --- a/renderer/renderer.py +++ b/renderer/renderer.py @@ -4,13 +4,13 @@ """ from jinja2 import Environment, FileSystemLoader -from selenium.webdriver.common.by import By from logger.logger import logger import pathlib import os from playwright.sync_api import sync_playwright - +# if case of any issue installing playwright: +# https://github.com/microsoft/playwright-python/issues/1797 class Renderer: def __init__(self, width, height): From c45f99641c540fb0a712f12cce6b33e035703cdb Mon Sep 17 00:00:00 2001 From: markfodor Date: Mon, 14 Apr 2025 21:24:25 +0200 Subject: [PATCH 3/3] move to playwright, update dependencies, add run configs --- .run/get master-token.run.xml | 24 +++++++++++++++++++ .run/run docker image.run.xml | 19 +++++++++++++++ Dockerfile | 19 +++++++++++++++ README.md | 11 ++++----- collectors/googlekeep/README.md | 14 +++++------ collectors/googlekeep/exhange.py | 19 +++++++++++++++ collectors/googlekeep/googleKeepCollector.py | 6 +---- requirements.txt | Bin 2568 -> 2582 bytes 8 files changed, 93 insertions(+), 19 deletions(-) create mode 100644 .run/get master-token.run.xml create mode 100644 .run/run docker image.run.xml create mode 100644 Dockerfile create mode 100644 collectors/googlekeep/exhange.py diff --git a/.run/get master-token.run.xml b/.run/get master-token.run.xml new file mode 100644 index 0000000..a3c18d7 --- /dev/null +++ b/.run/get master-token.run.xml @@ -0,0 +1,24 @@ + + + + + \ No newline at end of file diff --git a/.run/run docker image.run.xml b/.run/run docker image.run.xml new file mode 100644 index 0000000..f018cab --- /dev/null +++ b/.run/run docker image.run.xml @@ -0,0 +1,19 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a2996a9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM mcr.microsoft.com/playwright/python:v1.51.0-noble + +# System dependencies +RUN apt-get update && apt-get install -y \ + gcc g++ python3-dev \ + && apt-get clean + +WORKDIR /inkcheck +COPY requirements.txt . + +# Install dependencies +RUN python3 -m pip install --upgrade pip \ + && pip3 install --no-cache-dir --upgrade -r requirements.txt + +RUN playwright install + +COPY . . +EXPOSE 8080 +ENTRYPOINT ["python3", "main.py"] diff --git a/README.md b/README.md index dd40b1f..00da42b 100644 --- a/README.md +++ b/README.md @@ -48,13 +48,8 @@ sudo raspi-config ```bash sudo apt update -sudo apt-get install python3-pip -sudo apt-get install chromium-chromedriver -sudo apt-get install libopenjp2-7-dev sudo apt install git -sudo apt-get install apache2 -y -sudo chown pi:www-data /var/www/html -sudo chmod 755 /var/www/html +sudo apt-get install python3-pip ``` 4. Make sure that the Apache server is running. If you are on the same local network with your server, just type the IP addess of your server in the browser and it should load the default index.html. @@ -63,7 +58,11 @@ sudo chmod 755 /var/www/html ```bash git clone https://github.com/markfodor/InkCheck cd InkCheck +python -m venv inkcheck +inkcheck/Scripts/activate pip install -r requirements.txt +playwright install +playwright install-deps ``` 6. Fill the variables in the global.json. Most of the variables are pre-filled, _destinationFolder_ should be the path where your Apache server is running. Sidenote: You can switch between portait and landscape mode by swtiching the _imageWidth_ and _imageHeight_ values. diff --git a/collectors/googlekeep/README.md b/collectors/googlekeep/README.md index 3275d98..87221eb 100644 --- a/collectors/googlekeep/README.md +++ b/collectors/googlekeep/README.md @@ -8,17 +8,15 @@ ## Setup To generate an app password: -1. Go to your [Google Account](https://myaccount.google.com/) -2. Select Security. -3. Under "Signing in to Google," select 2-Step Verification. -4. At the bottom of the page, select App passwords. -5. Enter a name that helps you remember where you’ll use the app password. -6. Select Generate. -7. Now you can copy the generated password to the config.json +TODO +1. Follow this [guide](https://github.com/rukins/gpsoauth-java/blob/b74ebca999d0f5bd38a2eafe3c0d50be552f6385/README.md#receiving-an-authentication-token) +2. When you have the oauth_token copy that to the exchange.py file in this folder +3. Follow comments and run the file +4. The printed value goes to the password field of config.json ``` { "username": "YOUR_MAIL_ADDRESS", - "password": "YOUR_PASSWORD", + "password": "YOUR_MASTER_TOKEN", "nodeName": "Daily schedule", "onlyUncheckedItems": true } diff --git a/collectors/googlekeep/exhange.py b/collectors/googlekeep/exhange.py new file mode 100644 index 0000000..d42e79d --- /dev/null +++ b/collectors/googlekeep/exhange.py @@ -0,0 +1,19 @@ +import gpsoauth + +# use the following guide to obtain token: +# https://github.com/rukins/gpsoauth-java/blob/b74ebca999d0f5bd38a2eafe3c0d50be552f6385/README.md#receiving-an-authentication-token +email = 'somebody@gmail.com' # use your own mail address +android_id = '0123456789abcdef' # just leave it as it is +token = '...' # insert the oauth_token here + +master_response = gpsoauth.exchange_token(email, token, android_id) +master_token = master_response['Token'] # if there's no token check the response for more details + +# use the printed value in the Google Keep config in the 'password' field +print(master_token) + +auth_response = gpsoauth.perform_oauth( + email, master_token, android_id, + service='sj', app='com.google.android.keep', + client_sig='...') +token = auth_response['Auth'] diff --git a/collectors/googlekeep/googleKeepCollector.py b/collectors/googlekeep/googleKeepCollector.py index 37ec3d0..e238ca8 100644 --- a/collectors/googlekeep/googleKeepCollector.py +++ b/collectors/googlekeep/googleKeepCollector.py @@ -23,11 +23,7 @@ def __init__(self): return self.client = gkeepapi.Keep() - successful_login = self.client.login(self.username, self.password) - if(successful_login): - logger.info('Google Keep login was succesful.') - else: - logger.error('Google Keep login failed.') + self.client.authenticate(self.username, self.password) def _get_items_on_node_by_node_id(self, node_id): node = self.client.get(node_id) diff --git a/requirements.txt b/requirements.txt index cb70c80c95f5d60da6231ddf3681d2b11a551969..d3d0af2e2808abfec764d2830bedb7b41cac5c79 100644 GIT binary patch delta 116 zcmeAWnID65rfHvO!kaslLMJ0H=kniVBBoN z62Zt0QEj|=BC9o%Vk$!kLn%W6kjw|d9EM^BTOc%Jumoxc8DY5jD7z>VP!CAJVDf!V FO#s~S7>)n{ delta 111 zcmbOx(jhWIg4KdSkHKW4Vm2eA>EvF<$E?OczVYNzCVN&BAj@d7KC|c~X12{&n4B18 z(-{gFiW%}55*bPvN*FR2Y=O`asLBAOayEF-HWkZHQPl+~JP^9^=BCNSS<@>@<# E0A5`e)&Kwi