From 901f6387367027e0c656c52c1c0fa0c1a505369a Mon Sep 17 00:00:00 2001 From: Rattatwinko <89251490+ZockerKatze@users.noreply.github.com> Date: Tue, 15 Apr 2025 21:59:56 +0200 Subject: [PATCH] i like to suck on penis --- PfandApplication/__init__.py | 5 + PfandApplication/main.py | 59 ++++-- PfandApplication/tgtg_orderchecker/README.md | 7 + .../tgtg_orderchecker/__init__.py | 0 .../tgtg_orderchecker/getkey/getapi.py | 6 + .../tgtg_orderchecker/getkey/main.py | 27 +++ PfandApplication/tgtg_orderchecker/key.py | 14 ++ PfandApplication/tgtg_orderchecker/main.py | 183 ++++++++++++++++++ .../tgtg_orderchecker/setupkey.py | 96 +++++++++ README.md | 8 +- run.py | 6 +- 11 files changed, 394 insertions(+), 17 deletions(-) create mode 100644 PfandApplication/tgtg_orderchecker/README.md create mode 100644 PfandApplication/tgtg_orderchecker/__init__.py create mode 100644 PfandApplication/tgtg_orderchecker/getkey/getapi.py create mode 100644 PfandApplication/tgtg_orderchecker/getkey/main.py create mode 100644 PfandApplication/tgtg_orderchecker/key.py create mode 100644 PfandApplication/tgtg_orderchecker/main.py create mode 100644 PfandApplication/tgtg_orderchecker/setupkey.py diff --git a/PfandApplication/__init__.py b/PfandApplication/__init__.py index e69de29..54385e0 100644 --- a/PfandApplication/__init__.py +++ b/PfandApplication/__init__.py @@ -0,0 +1,5 @@ +""" + +Initializing of stuff is done in both of the classes in main.py! + +""" diff --git a/PfandApplication/main.py b/PfandApplication/main.py index 382dcb5..3f5b937 100644 --- a/PfandApplication/main.py +++ b/PfandApplication/main.py @@ -3,12 +3,6 @@ import tkinter import webbrowser from tkinter import ttk, messagebox, filedialog import json - - -from PfandApplication.wiki import main as WIKI -from PfandApplication.pfand_scanner import launch_pfand_scanner -from PfandApplication.updater import open_updater as open_updater, run_silent_update - from PIL import Image, ImageTk import os import subprocess @@ -22,6 +16,14 @@ import queue import numpy as np import shutil +# Local Dependencies +from PfandApplication.wiki import main as WIKI +from PfandApplication.pfand_scanner import launch_pfand_scanner +from PfandApplication.updater import open_updater as open_updater, run_silent_update +from PfandApplication.tgtg_orderchecker import main as tgtg +from PfandApplication.tgtg_orderchecker import setupkey as tgtg_kt + + class Achievement: def __init__(self, title, description, condition_type, condition_value): self.title = title @@ -349,12 +351,9 @@ class PfandCalculator: label = tk.Label(about_window, text=( - "PfandApp V.7.04.301 ; Könnte einige Versionen hinten sein!\n" + "PfandApp V.8.04.301-PKG1\n\n" "Erstellt mit TKinter, CV2, Numpy, PyZbar, TGTG-API, TKCalendar, Datetime\n" "Eigene Module: Updater, TGTG_OC, Wiki, BuildUtil\n" - "Großen Dank an SPAR, HOFER\n" - "Daten werden in RootFS gespeichert\n" - "Danke für die Idee --> Österreich" ), padx=10, pady=10, @@ -371,6 +370,34 @@ class PfandCalculator: # Close button close_button = tk.Button(about_window, text="Close", command=about_window.destroy) close_button.grid(row=1, column=1, padx=10, pady=10, sticky="ew") + # TGTG Credits + def TGTG_credits(self): + about_tgtg = tk.Toplevel(self.root) + about_tgtg.title("Über TGTG-OrderChecker") + about_tgtg.resizable(True, True) + about_tgtg.grid_columnconfigure(0, weight=1) + about_tgtg.grid_columnconfigure(1, weight=1) + about_tgtg.grid_rowconfigure(0, weight=1) + + label_TGTG = tk.Label( + about_tgtg, + text="TooGoodToGo OrderChecker\nOriginalerweiße: https://github.com/ZockerKatze/tgtg_orderchecker\nV1.102.202 (PfandVersion-PKG)", + padx=10, + pady=10, + justify="center", + anchor="center" + ) + label_TGTG.grid(row=0, column=0, columnspan=2, pady=10, sticky="nsew") + + url_TGTG = "https://github.com/ZockerKatze/tgtg_orderchecker" + + # Website button + website_button_TGTG = tk.Button(about_tgtg, text="View Repo In Browser", command=lambda: webbrowser.open(url_TGTG)) + website_button_TGTG.grid(row=1, column=0, padx=10, pady=10, sticky="ew") + + # Close button + close_button = tk.Button(about_tgtg, text="Close", command=about_tgtg.destroy) + close_button.grid(row=1, column=1, padx=10, pady=10, sticky="ew") def update_credits(self): # Credits for the Updater Application (not some update function for some credits) || Rewrote this in Version 7.04.101 => Inconsistency is key about_update = tk.Toplevel(self.root) @@ -478,6 +505,14 @@ class PfandCalculator: products_menu.add_command(label="Produkt hinzufügen", command=self.show_add_product_window, accelerator="Strg+P") products_menu.add_command(label="Produkte verwalten", command=self.show_manage_products_window, accelerator="Strg+Shift+P") + # TGTG Menu (used to not exist) + + tgtg_menu = tk.Menu(self.menubar, tearoff=0) + self.menubar.add_cascade(label="TGTG", menu=tgtg_menu) + tgtg_menu.add_command(label="Öffne TGTG-OC", command=tgtg.start_tgtg, accelerator="Strg+F12") + tgtg_menu.add_command(label="Öffne KeyTool", command=tgtg_kt.ask_for_tokens, accelerator="Strg+F11") + tgtg_menu.add_separator() + tgtg_menu.add_command(label="Über TGTG", command=self.TGTG_credits) # No keybind , why tf would you need one anyways update_menu = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Updater", menu=update_menu) @@ -499,8 +534,8 @@ class PfandCalculator: self.root.bind('', lambda e: self.handle_shift_f2(e)) self.root.bind('', lambda e: self.show_achievements()) self.root.bind('', lambda e: self.delete_achievements()) - self.root.bind('', lambda e: start_tgtg(self.root)) - self.root.bind('', lambda e: ask_for_tokens()) + self.root.bind('', lambda e: tgtg.start_tgtg(self.root)) + self.root.bind('', lambda e: tgtg_kt.ask_for_tokens()) self.root.bind('', lambda e: self.create_credits()) self.root.bind('', lambda e: self.export_barcodes_csv() if e.state & 0x1 else self.export_history_csv()) self.root.bind('', lambda e: self.show_add_product_window()) diff --git a/PfandApplication/tgtg_orderchecker/README.md b/PfandApplication/tgtg_orderchecker/README.md new file mode 100644 index 0000000..ce3adf8 --- /dev/null +++ b/PfandApplication/tgtg_orderchecker/README.md @@ -0,0 +1,7 @@ +This is a "better" Version of the TGTG App i made once +This is only experimental thats why its only in the credits! + +This sometimes gets bricked for no fucking reason, dont run it with a bad API key , it WILL say that you are a idiot and it will curse your whole familiy in arabic, +dont try pulling stupid shit on this fucking API it has no fucking mercy, AT ALL + +Version --> PKG1 diff --git a/PfandApplication/tgtg_orderchecker/__init__.py b/PfandApplication/tgtg_orderchecker/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/PfandApplication/tgtg_orderchecker/getkey/getapi.py b/PfandApplication/tgtg_orderchecker/getkey/getapi.py new file mode 100644 index 0000000..e98a296 --- /dev/null +++ b/PfandApplication/tgtg_orderchecker/getkey/getapi.py @@ -0,0 +1,6 @@ +from tgtg import TgtgClient + +client = TgtgClient(email="your email here") +creds = client.get_credentials() + +print(creds) diff --git a/PfandApplication/tgtg_orderchecker/getkey/main.py b/PfandApplication/tgtg_orderchecker/getkey/main.py new file mode 100644 index 0000000..936b07d --- /dev/null +++ b/PfandApplication/tgtg_orderchecker/getkey/main.py @@ -0,0 +1,27 @@ +import json + +from tgtg import TgtgClient + + +def get_tgtg_credentials(): + email = input("Enter your TGTG account email: ") + + try: + client = TgtgClient(email=email) + credentials = client.get_credentials() + + # Save credentials to a JSON file + with open("tgtg_credentials.json", "w") as json_file: + json.dump(credentials, json_file, indent=4) + + # Print credentials in a readable format + print("\nYour TGTG API Credentials:") + print(json.dumps(credentials, indent=4)) + + print("\nCredentials have been saved to 'tgtg_credentials.json'.") + except Exception as e: + print(f"An error occurred: {e}") + + +if __name__ == "__main__": + get_tgtg_credentials() diff --git a/PfandApplication/tgtg_orderchecker/key.py b/PfandApplication/tgtg_orderchecker/key.py new file mode 100644 index 0000000..46af093 --- /dev/null +++ b/PfandApplication/tgtg_orderchecker/key.py @@ -0,0 +1,14 @@ +######################################### +# # +# AUTOGENERATED BY SETUPKEYTOOL V1.0.03 # +# THIS IS SENSITIVE INFORMATION # +# @ZockerKatze/@rattatwinko # +# # +######################################### + +from tgtg import TgtgClient + +# Don't ever give this Info to someone you dont trust! +# This is the Private Key to your TGTG Account + +client = TgtgClient(access_token="adsf", refresh_token="asdf", cookie="asfd") diff --git a/PfandApplication/tgtg_orderchecker/main.py b/PfandApplication/tgtg_orderchecker/main.py new file mode 100644 index 0000000..f5e6877 --- /dev/null +++ b/PfandApplication/tgtg_orderchecker/main.py @@ -0,0 +1,183 @@ +import tkinter as tk +from io import BytesIO +from tkinter import messagebox, ttk, Menu +from datetime import datetime +import requests +from PIL import Image, ImageTk +from .key import * + +class TGTGOrdersApp: + def __init__(self, parent): + self.parent = parent + self.frame = tk.Frame(self.parent, bg="#ffffff") + self.frame.pack(fill="both", expand=True) + + self.notebook = ttk.Notebook(self.frame) + self.notebook.pack(fill="both", expand=True) + + self.orders_tab = tk.Frame(self.notebook, bg="#ffffff") + self.notebook.add(self.orders_tab, text="Orders") + + self.log_tab = tk.Frame(self.notebook, bg="#ffffff") + self.notebook.add(self.log_tab, text="Log") + + self.log_text = tk.Text(self.log_tab, wrap=tk.WORD, height=15, font=("Arial", 10), bg="#f0f0f0") + self.log_text.pack(fill="both", expand=True, padx=10, pady=10) + + self.order_frame = tk.Frame(self.orders_tab, bg="#ffffff") + self.order_frame.pack(fill="both", expand=True, padx=10, pady=10) + + self.menu = Menu(self.parent) + self.parent.config(menu=self.menu) + self.filemenu = Menu(self.menu) + self.menu.add_cascade(label="File", menu=self.filemenu) + self.filemenu.add_command(label="Exit", command=self.exit_applet) + self.filemenu.add_command(label="Refetch", command=self.display_orders) + self.filemenu.add_command(label="Save Log", command=self.save_log) + self.filemenu.add_separator() + self.filemenu.add_command(label="About", command=self.about) + + self.parent.after(1000, self.on_startup) + + def log_message(self, message): + timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + self.log_text.insert(tk.END, f"{timestamp} - {message}\n") + self.log_text.yview(tk.END) + + def format_time(self, iso_time): + try: + dt = datetime.fromisoformat(iso_time.replace("Z", "+00:00")) + local_time = dt.astimezone() + return local_time.strftime("%H:%M") + except ValueError: + return "Unknown Error!" + + def fetch_orders(self): + self.log_message("[ INFO ]: Fetching orders...") + try: + active_orders = client.get_active() + if not isinstance(active_orders, dict) or "orders" not in active_orders: + raise ValueError("Unexpected API response format.") + orders_list = active_orders.get("orders", []) + except Exception as e: + self.log_message(f"[ ERROR ]: Error fetching active orders: {e}") + messagebox.showerror("Error", f"Error fetching active orders: {e}") + return [] + + orders_data = [] + for order in orders_list: + try: + order_info = { + "name": order.get("item_name", "Unknown"), + "store_name": order.get("store_name", "Unknown"), + "address": order.get("pickup_location", {}).get("address", {}).get("address_line", "Unknown"), + "quantity": order.get("quantity", 1), + "price": order.get("total_price", {}).get("minor_units", 0) / (10 ** order.get("total_price", {}).get("decimals", 2)), + "currency": order.get("total_price", {}).get("code", "Unknown"), + "payment_method": order.get("payment_method_display_name", "Unknown"), + "pickup_window": { + "start": self.format_time(order.get("pickup_interval", {}).get("start", "Unknown")), + "end": self.format_time(order.get("pickup_interval", {}).get("end", "Unknown")) + }, + "image_url": order.get("item_cover_image", {}).get("current_url", "") + } + orders_data.append(order_info) + except Exception as e: + self.log_message(f"[ FATAL ERROR ]: Skipping an order due to an error: {e}") + return orders_data + + + def display_orders(self): + self.log_message("[ INFO ]: Displaying orders...") + orders = self.fetch_orders() + if not orders: + messagebox.showinfo("Info", "No active orders found.") + self.log_message("[ ERROR ]: No active orders found.") + return + + # Clear existing widgets + for widget in self.order_frame.winfo_children(): + widget.destroy() + + # Create a scrollable frame inside a Canvas + canvas = tk.Canvas(self.order_frame, bg="#ffffff") + scroll_frame = tk.Frame(canvas, bg="#ffffff") + scrollbar = tk.Scrollbar(self.order_frame, orient="vertical", command=canvas.yview) + + canvas.configure(yscrollcommand=scrollbar.set) + + scrollbar.pack(side="right", fill="y") + canvas.pack(side="left", fill="both", expand=True) + canvas.create_window((0, 0), window=scroll_frame, anchor="nw") + + # Store image references to prevent garbage collection + image_refs = [] + + for order in orders: + text = (f"{order['name']} - {order['store_name']}\n" + f"Address: {order['address']}\n" + f"Quantity: {order['quantity']}\n" + f"Price: {order['price']} {order['currency']}\n" + f"Payment: {order['payment_method']}\n" + f"Pickup: {order['pickup_window']['start']} to {order['pickup_window']['end']}\n") + + label = tk.Label(scroll_frame, text=text, justify="left", padx=10, pady=5, anchor="w", font=("Arial", 10), + bg="#f0f0f0", relief="ridge") + label.pack(fill="x", pady=5) + + if order["image_url"]: + try: + response = requests.get(order["image_url"]) + img_data = BytesIO(response.content) + img = Image.open(img_data) + img.thumbnail((150, 150), Image.Resampling.LANCZOS) + img_tk = ImageTk.PhotoImage(img) + + img_label = tk.Label(scroll_frame, image=img_tk) + img_label.image = img_tk # Store reference + image_refs.append(img_tk) # Prevent garbage collection + img_label.pack(pady=5) + except Exception as e: + self.log_message(f"[ ERROR ]: Failed to load image: {e}") + + # Update scroll region + scroll_frame.update_idletasks() + canvas.config(scrollregion=canvas.bbox("all")) + + # Enable scrolling with the mouse wheel + def on_mouse_wheel(event): + canvas.yview_scroll(-1 * (event.delta // 120), "units") + + canvas.bind_all("", on_mouse_wheel) # Windows & MacOS + canvas.bind_all("", lambda e: canvas.yview_scroll(-1, "units")) # Linux Scroll Up + canvas.bind_all("", lambda e: canvas.yview_scroll(1, "units")) # Linux Scroll Down + + def on_startup(self): + self.log_message("[ INFO ]: Application started.") + self.display_orders() + + def exit_applet(self): + self.log_message("[ INFO ]: Exiting Applet") + self.parent.quit() + + def about(self): + messagebox.showinfo("About", "PythonTGTG Script for fetching Orders on Desktop") + + def save_log(self): + try: + log_content = self.log_text.get("1.0", tk.END) + with open("log_file.log", "w") as log_file: + log_file.write(log_content) + self.log_message("[ INFO ]: Log file saved successfully.") + except Exception as e: + self.log_message(f"[ ERROR ]: Error saving log file: {e}") + messagebox.showerror("Error", f"Error saving log file: {e}") + +def start_tgtg(parent=None): + new_window = tk.Toplevel(parent) # Create a new window + new_window.title("TGTG Bestellungen") + new_window.geometry("500x600") + + # Start the TGTGOrdersApp inside this new window + app = TGTGOrdersApp(new_window) + diff --git a/PfandApplication/tgtg_orderchecker/setupkey.py b/PfandApplication/tgtg_orderchecker/setupkey.py new file mode 100644 index 0000000..1f2f08f --- /dev/null +++ b/PfandApplication/tgtg_orderchecker/setupkey.py @@ -0,0 +1,96 @@ + +import tkinter as tk +from tkinter import messagebox +import os + +# Get the current working directory +current_directory = os.getcwd() + +# Check if the current directory is already 'tgtg_orderchecker', if so adjust the path +if current_directory.endswith('tgtg_orderchecker'): + KEY_FILE_PATH = os.path.join(current_directory, 'key.py') +else: + KEY_FILE_PATH = os.path.join(current_directory, 'tgtg_orderchecker', 'key.py') + +# Function to modify the key.py file +def modify_key_file(access_token, refresh_token, cookie): + try: + # Check if the key.py file exists + if os.path.exists(KEY_FILE_PATH): + # Ask the user if they want to replace the existing file + result = messagebox.askyesno("File Exists", f"{KEY_FILE_PATH} already exists. Do you want to replace it?") + if not result: + return # If user chooses "No", do nothing and return + + # Open and modify the file with new values + with open(KEY_FILE_PATH, 'w') as file: + file.write(f'''######################################### +# # +# AUTOGENERATED BY SETUPKEYTOOL V1.0.03 # +# THIS IS SENSITIVE INFORMATION # +# @ZockerKatze/@rattatwinko # +# # +######################################### + +from tgtg import TgtgClient + +# Don't ever give this Info to someone you dont trust! +# This is the Private Key to your TGTG Account + +client = TgtgClient(access_token="{access_token}", refresh_token="{refresh_token}", cookie="{cookie}") +''') + + + messagebox.showinfo("Success", f"{KEY_FILE_PATH} has been updated successfully.") + except Exception as e: + messagebox.showerror("Error", f"Failed to modify {KEY_FILE_PATH}: {str(e)}") + +# Function to handle the Tkinter window for user input +def ask_for_tokens(): + def submit_tokens(): + access_token = access_token_entry.get() + refresh_token = refresh_token_entry.get() + cookie = cookie_entry.get() + + if not access_token or not refresh_token or not cookie: + messagebox.showerror("Error", "All fields are required!") + return + + # Modify the key file + modify_key_file(access_token, refresh_token, cookie) + + # Create Tkinter window + root = tk.Tk() + root.title("Enter API Credentials") + + + title_label = tk.Label(root, text="Enter your API Credentials", font=("Arial", 14, "bold")) + title_label.grid(row=0, columnspan=2, pady=10) + + # Add labels and entry fields for the tokens and cookie + tk.Label(root, text="Access Token:").grid(row=1, column=0) + access_token_entry = tk.Entry(root, width=40) + access_token_entry.grid(row=1, column=1) + + tk.Label(root, text="Refresh Token:").grid(row=2, column=0) + refresh_token_entry = tk.Entry(root, width=40) + refresh_token_entry.grid(row=2, column=1) + + tk.Label(root, text="Cookie:").grid(row=3, column=0) + cookie_entry = tk.Entry(root, width=40) + cookie_entry.grid(row=3, column=1) + + # Submit button to process the tokens + submit_button = tk.Button(root, text="Submit", command=submit_tokens) + submit_button.grid(row=4, columnspan=2) + + # Keep the window on top + root.attributes("-topmost", True) + + # Start Tkinter main loop + root.mainloop() + +# Run the application +if __name__ == "__main__": + ask_for_tokens() + diff --git a/README.md b/README.md index a62bfd8..1b4f566 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# ♻️ Pfandrechner Application Suite +# ♻️ Pfandrechner -**Version:** V.7.04.301 +**Version:** V.8.04.301-PKG1 **License:** [MIT](LICENSE) Welcome to the **Pfandrechner Application - Package** – a sleek and powerful tool for tracking and calculating container deposits ("Pfand") in Austria 🇦🇹. Whether you're returning a few bottles or managing full bags, this app has you covered! @@ -17,6 +17,8 @@ This is a copy of [Pfand](https://github.com/ZockerKatze/pfand), but this is in 📜 **History & Exports** – View your past returns and export the data for safekeeping or bragging rights. +📦 **TGTG Integration** – Check on your "Too Good To Go" orders directly within the app. ( You need to setup your API Key first! ) + ⚙️ **Smart Updater** – Keeps the app fresh with the latest features and fixes. --- @@ -26,7 +28,7 @@ This is a copy of [Pfand](https://github.com/ZockerKatze/pfand), but this is in ### 1. Clone the Repository ```bash -git clone https://github.com/ZockerKatze/pfand.git +git clone https://github.com/ZockerKatze/pfand_PKG.git cd pfand ``` diff --git a/run.py b/run.py index bbf0bab..421b8f7 100644 --- a/run.py +++ b/run.py @@ -3,11 +3,13 @@ from PfandApplication import main """ If the function launch gets called with -False -> No autoupdates will be run + +False -> No autoupdates will be run || Best for Debugging! + True -> Autoupdates will be run """ if __name__ == "__main__": - main.PfandCalculator.launch(True) # By default True + main.PfandCalculator.launch(False)