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 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/.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/renderer/renderer.py b/renderer/renderer.py index 3554064..f4debfd 100644 --- a/renderer/renderer.py +++ b/renderer/renderer.py @@ -3,16 +3,14 @@ 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 +# if case of any issue installing playwright: +# https://github.com/microsoft/playwright-python/issues/1797 class Renderer: def __init__(self, width, height): @@ -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 7605429..d3d0af2 100644 Binary files a/requirements.txt and b/requirements.txt differ