From 0d521e76dacf319bab69216b96a4a048caab9ba1 Mon Sep 17 00:00:00 2001 From: Floke Date: Thu, 8 Jan 2026 21:07:12 +0000 Subject: [PATCH] feat(notion): Finalize relational DB implementation and scripts - Implement relational data structure in Notion as per the plan. - Add scripts for initial data import (import_product.py) and distribution to related databases (distribute_product_data.py). - Create helper scripts for reading Notion content. - Update Notion_Dashboard.md and GEMINI.md with the latest implementation status, database IDs, and key lessons learned from the MVP phase, including API constraints and schema-first principles. --- GEMINI.md | 12 ++ Notion_Dashboard.md | 20 ++- create_feature_translator_db.py | 68 +++++++++ distribute_product_data.py | 254 ++++++++++++++++++++++++++++++++ import_product.py | 123 ++++++++++++++-- read_file_content.py | 19 +++ read_notion_dashboard.py | 41 ++++++ 7 files changed, 522 insertions(+), 15 deletions(-) create mode 100644 create_feature_translator_db.py create mode 100644 distribute_product_data.py create mode 100644 read_file_content.py create mode 100644 read_notion_dashboard.py diff --git a/GEMINI.md b/GEMINI.md index 410bfa14..67cedfc3 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -60,6 +60,18 @@ The system architecture has evolved from a CLI-based toolset to a modern web app * **Problem:** Users didn't see when a background job finished. * **Solution:** Implementing a polling mechanism (`setInterval`) tied to a `isProcessing` state is superior to static timeouts for long-running AI tasks. +6. **Notion API - Schema First:** + * **Problem:** Scripts failed when trying to write data to a Notion database property (column) that did not exist. + * **Solution:** ALWAYS ensure the database schema is correct *before* attempting to import or update data. Use the `databases.update` endpoint to add the required properties (e.g., "Key Features", "Constraints") programmatically as a preliminary step. The API will not create them on the fly. + +7. **Notion API - Character Limits:** + * **Problem:** API calls failed with a `400 Bad Request` error when a rich text field exceeded the maximum length. + * **Solution:** Be aware of the **2000-character limit** for rich text properties. Implement logic to truncate text content before sending the payload to the Notion API to prevent validation errors. + +8. **Notion API - Response Structures:** + * **Problem:** Parsing functions failed with `TypeError` or `AttributeError` because the JSON structure for a property differed depending on how it was requested. + * **Solution:** Write robust helper functions that can handle multiple possible JSON structures. A property object retrieved via a direct property endpoint (`/pages/{id}/properties/{prop_id}`) is structured differently from the same property when it's part of a full page object (`/pages/{id}`). The parsing logic must account for these variations. + ## Next Steps * **Quality Assurance:** Implement a dedicated "Review Mode" to validate high-potential leads. * **Export:** Generate Excel/CSV enriched reports. diff --git a/Notion_Dashboard.md b/Notion_Dashboard.md index 52b3a62b..fde20571 100644 --- a/Notion_Dashboard.md +++ b/Notion_Dashboard.md @@ -92,6 +92,7 @@ Um die relationale Integrität zu wahren, sind folgende Datenbanken in Notion zw * **Messaging Matrix** $\leftrightarrow$ **Sector Master** (Welcher Schmerz gehört zu welcher Branche?) * **The Brain** $\leftrightarrow$ **Product Master** (Welches Support-Wissen gehört zu welcher Hardware?) * **GTM Workspace** $\leftrightarrow$ **Product Master** (Welche Kampagne bewirbt welches Gerät?) +* **Feature-to-Value Translator** $\leftrightarrow$ **Product Master** (Welcher Nutzen gehört zu welchem Feature?) --- @@ -141,6 +142,7 @@ Die folgenden IDs wurden bei der initialen Erstellung der Datenbanken generiert * **Enrichment Factory & RevOps:** `2e288f42-8544-8172-a3a7-f5101b6ac0f0` * **The Brain:** `2e288f42-8544-810f-8e7d-e9a2a3100779` * **GTM Workspace:** `2e288f42-8544-81cc-b167-f9dffe9c7bde` +* **Feature-to-Value Translator:** `2e288f42-8544-8184-ba08-d6d736879f19` --- @@ -154,5 +156,19 @@ Die folgenden IDs wurden bei der initialen Erstellung der Datenbanken generiert **Status:** Blueprint Finalisiert. **Nächster Schritt:** Umsetzung der Datenbank-Properties und API-Endpunkte gemäß diesem Dokument. -### 8.8 Erfolgreicher Datenimport (08. Jan. 2026) -Der Produkt-Datensatz "Puma M20" wurde erfolgreich mithilfe des `import_product.py`-Skripts und der Quelldatei `Puma_m20_2026-01-08.md` in die Notion-Datenbanken "Product Master", "Sector & Persona Master" und "Messaging Matrix" importiert. \ No newline at end of file +### 8.8 Erfolgreicher Datenimport & -verteilung (08. Jan. 2026) +Der Produkt-Datensatz "Puma M20" wurde erfolgreich importiert. Die strategischen Daten (Zielgruppen, Pain Points, Messaging) wurden anschließend aus dem Produkteintrag extrahiert und in die relational verknüpften Datenbanken "Sector & Persona Master" und "Messaging Matrix" verteilt. Dies schafft eine "Single Source of Truth" und legt die Grundlage für automatisierte Marketing-Workflows. + +### 8.9 Neu gelernte Lektionen (Post-MVP) + +6. **Notion API - Schema First:** + * **Problem:** Skripte schlugen fehl beim Versuch, Daten in eine nicht existierende Datenbankeigenschaft (Spalte) zu schreiben. + * **Lösung:** IMMER sicherstellen, dass das Datenbankschema korrekt ist, *bevor* Daten importiert oder aktualisiert werden. Den `databases.update`-Endpunkt verwenden, um die erforderlichen Eigenschaften (z.B. "Key Features", "Constraints") programmatisch als vorbereitenden Schritt hinzuzufügen. Die API erstellt diese nicht spontan. + +7. **Notion API - Zeichenbeschränkungen:** + * **Problem:** API-Aufrufe schlugen mit einem `400 Bad Request`-Fehler fehl, wenn ein Rich-Text-Feld die maximale Länge überschritt. + * **Lösung:** Das **2000-Zeichen-Limit** für Rich-Text-Eigenschaften beachten. Eine Logik implementieren, um den Textinhalt vor dem Senden des Payloads an die Notion-API zu kürzen, um Validierungsfehler zu vermeiden. + +8. **Notion API - Antwortstrukturen:** + * **Problem:** Parsing-Funktionen schlugen mit `TypeError` oder `AttributeError` fehl, da die JSON-Struktur für eine Eigenschaft unterschiedlich war, je nachdem, wie sie angefordert wurde. + * **Lösung:** Robuste Hilfsfunktionen schreiben, die mehrere mögliche JSON-Strukturen verarbeiten können. Ein Eigenschaftsobjekt, das über einen direkten Eigenschafts-Endpunkt (`/pages/{id}/properties/{prop_id}`) abgerufen wird, ist anders strukturiert als dieselbe Eigenschaft, wenn sie Teil eines vollständigen Seitenobjekts (`/pages/{id}`) ist. Die Parsing-Logik muss diese Variationen berücksichtigen. \ No newline at end of file diff --git a/create_feature_translator_db.py b/create_feature_translator_db.py new file mode 100644 index 00000000..db77357f --- /dev/null +++ b/create_feature_translator_db.py @@ -0,0 +1,68 @@ +# create_feature_translator_db.py +import requests +import time +import json + +# --- Configuration --- +try: + with open("notion_token.txt", "r") as f: + NOTION_TOKEN = f.read().strip() +except FileNotFoundError: + print("Error: notion_token.txt not found.") + exit(1) + +PARENT_PAGE_ID = "2e088f42854480248289deb383da3818" +NOTION_VERSION = "2022-06-28" +NOTION_API_BASE_URL = "https://api.notion.com/v1" + +HEADERS = { + "Authorization": f"Bearer {NOTION_TOKEN}", + "Notion-Version": NOTION_VERSION, + "Content-Type": "application/json", +} + +# --- Database Schema --- +DB_NAME = "Feature-to-Value Translator" +DB_SCHEMA = { + "title": [{"type": "text", "text": {"content": DB_NAME}}], + "properties": { + "Feature": {"title": {}}, + "Story (Benefit)": {"rich_text": {}}, + "Headline": {"rich_text": {}}, + "Product Master": { + "relation": { + "database_id": "2e288f42-8544-81d8-96f5-c231f84f719a", # Product Master DB ID + "dual_property": {} + } + } + } +} + +# --- Main Logic --- +def main(): + print(f"Attempting to create database: {DB_NAME}") + create_url = f"{NOTION_API_BASE_URL}/databases" + payload = { + "parent": {"type": "page_id", "page_id": PARENT_PAGE_ID}, + "title": DB_SCHEMA["title"], + "properties": DB_SCHEMA["properties"], + } + try: + response = requests.post(create_url, headers=HEADERS, json=payload) + response.raise_for_status() + db_data = response.json() + db_id = db_data["id"] + print(f"Successfully created database '{DB_NAME}' with ID: {db_id}") + print("\n--- IMPORTANT ---") + print("Please update 'Notion_Dashboard.md' with this new ID.") + print(f"'Feature-to-Value Translator': '{db_id}'") + print("-------------------") + + except requests.exceptions.HTTPError as e: + print(f"HTTP Error creating database {DB_NAME}: {e}") + print(f"Response content: {response.text}") + except Exception as e: + print(f"An unexpected error occurred: {e}") + +if __name__ == "__main__": + main() diff --git a/distribute_product_data.py b/distribute_product_data.py new file mode 100644 index 00000000..3c4a1ca5 --- /dev/null +++ b/distribute_product_data.py @@ -0,0 +1,254 @@ +# distribute_product_data.py +import requests +import json +import re +import os +import time + +# --- Configuration --- +try: + with open("notion_token.txt", "r") as f: + NOTION_TOKEN = f.read().strip() +except FileNotFoundError: + print("Error: notion_token.txt not found.") + exit(1) + +NOTION_VERSION = "2022-06-28" +NOTION_API_BASE_URL = "https://api.notion.com/v1" + +HEADERS = { + "Authorization": f"Bearer {NOTION_TOKEN}", + "Notion-Version": NOTION_VERSION, + "Content-Type": "application/json", +} + +# --- Database IDs (from Notion_Dashboard.md) --- +DB_IDS = { + "Product Master": "2e288f42-8544-81d8-96f5-c231f84f719a", + "Sector & Persona Master": "2e288f42-8544-8113-b878-ec99c8a02a6b", + "Messaging Matrix": "2e288f42-8544-81b0-83d4-c16623cc32d1", + "Feature-to-Value Translator": "2e288f42-8544-8184-ba08-d6d736879f19", +} + +# --- Helper Functions --- + +def create_notion_page(database_id, properties): + """Creates a new page in a Notion database.""" + url = f"{NOTION_API_BASE_URL}/pages" + payload = {"parent": {"database_id": database_id}, "properties": properties} + try: + response = requests.post(url, headers=HEADERS, json=payload) + response.raise_for_status() + print(f"Successfully created page in DB {database_id}.") + return response.json() + except requests.exceptions.HTTPError as e: + print(f"HTTP Error creating page in DB {database_id}: {e}\nResponse: {response.text}") + return None + +def update_notion_page(page_id, properties): + """Updates an existing page in Notion.""" + url = f"{NOTION_API_BASE_URL}/pages/{page_id}" + payload = {"properties": properties} + try: + response = requests.patch(url, headers=HEADERS, json=payload) + response.raise_for_status() + print(f"Successfully updated page {page_id}.") + return response.json() + except requests.exceptions.HTTPError as e: + print(f"HTTP Error updating page {page_id}: {e}\nResponse: {response.text}") + return None + +def find_notion_page_by_title(database_id, title): + """Searches for a page in a Notion database by its title property.""" + url = f"{NOTION_API_BASE_URL}/databases/{database_id}/query" + filter_payload = {"filter": {"property": "Name", "title": {"equals": title}}} + try: + response = requests.post(url, headers=HEADERS, json=filter_payload) + response.raise_for_status() + results = response.json().get("results") + return results[0] if results else None + except requests.exceptions.HTTPError as e: + print(f"HTTP Error searching page in DB {database_id}: {e}\nResponse: {response.text}") + return None + +def get_page_property(page_id, property_id): + """Retrieves a specific property from a Notion page.""" + url = f"{NOTION_API_BASE_URL}/pages/{page_id}/properties/{property_id}" + try: + response = requests.get(url, headers=HEADERS) + response.raise_for_status() + return response.json() + except requests.exceptions.HTTPError as e: + print(f"HTTP Error retrieving property {property_id}: {e}\nResponse: {response.text}") + return None + +def get_rich_text_content(property_object): + """Extracts plain text from a Notion rich_text property object.""" + if not property_object: + return "" + try: + # The property endpoint returns a list in the 'results' key + if 'results' in property_object and property_object['results']: + # The actual content is in the 'rich_text' object within the first result + rich_text_items = property_object['results'][0].get('rich_text', {}) + # It can be a single dict or a list, we handle the main plain_text for simplicity here + if isinstance(rich_text_items, dict) and 'plain_text' in rich_text_items: + return rich_text_items.get('plain_text', '') + # If it is a list of rich text objects (less common for a single property) + elif isinstance(rich_text_items, list): + return "".join(item.get("plain_text", "") for item in rich_text_items if isinstance(item, dict)) + + except (KeyError, IndexError, TypeError) as e: + print(f"Error parsing rich text object: {e}") + return "" + return "" + +def format_rich_text(text): + """Formats a string into Notion's rich text structure.""" + if len(text) > 2000: + print(f"Warning: Truncating text from {len(text)} to 2000 characters.") + text = text[:2000] + return {"rich_text": [{"type": "text", "text": {"content": text}}]} + +def format_title(text): + """Formats a string into Notion's title structure.""" + return {"title": [{"type": "text", "text": {"content": text}}]} + +def format_relation(page_ids): + """Formats a list of page IDs into Notion's relation structure.""" + if not isinstance(page_ids, list): + page_ids = [page_ids] + return {"relation": [{"id": page_id} for page_id in page_ids]} + +def parse_markdown_table(markdown_text): + """Parses a generic markdown table into a list of dicts.""" + lines = markdown_text.strip().split('\n') + if len(lines) < 2: + return [] + + headers = [h.strip() for h in lines[0].split('|') if h.strip()] + + data_rows = [] + for line in lines[2:]: # Skip header and separator + values = [v.strip() for v in line.split('|') if v.strip()] + if len(values) == len(headers): + data_rows.append(dict(zip(headers, values))) + + return data_rows + +# --- Main Logic --- + +def main(): + PRODUCT_NAME = "Puma M20" + print(f"--- Starting data distribution for product: {PRODUCT_NAME} ---") + + # 1. Get the product page from Product Master + product_page = find_notion_page_by_title(DB_IDS["Product Master"], PRODUCT_NAME) + if not product_page: + print(f"Product '{PRODUCT_NAME}' not found. Aborting.") + return + product_page_id = product_page["id"] + print(f"Found Product Page ID: {product_page_id}") + + # 2. Distribute Strategy Matrix Data + strategy_matrix_prop_id = product_page["properties"]["Strategy Matrix"]["id"] + strategy_matrix_obj = get_page_property(product_page_id, strategy_matrix_prop_id) + strategy_matrix_text = get_rich_text_content(strategy_matrix_obj) + + if strategy_matrix_text: + parsed_matrix = parse_markdown_table(strategy_matrix_text) + if parsed_matrix: + print("\n--- Distributing Strategy Matrix Data ---") + sector_page_ids_for_product = [] + + for row in parsed_matrix: + segment_name = row.get("Segment") + pain_point = row.get("Pain Point") + angle = row.get("Angle") + differentiation = row.get("Differentiation") + + if not all([segment_name, pain_point, angle, differentiation]): + print(f"Skipping row due to missing data: {row}") + continue + + print(f"\nProcessing Segment: {segment_name}") + + # Find or Create Sector in Sector & Persona Master + sector_page = find_notion_page_by_title(DB_IDS["Sector & Persona Master"], segment_name) + if sector_page: + sector_page_id = sector_page["id"] + print(f"Found existing Sector page with ID: {sector_page_id}") + update_notion_page(sector_page_id, {"Pains": format_rich_text(pain_point)}) + else: + print(f"Creating new Sector page for '{segment_name}'...") + new_sector_page = create_notion_page(DB_IDS["Sector & Persona Master"], {"Name": format_title(segment_name), "Pains": format_rich_text(pain_point)}) + if not new_sector_page: + print(f"Failed to create sector page for '{segment_name}'. Skipping.") + continue + sector_page_id = new_sector_page["id"] + + sector_page_ids_for_product.append(sector_page_id) + + # Create entry in Messaging Matrix + print(f"Creating Messaging Matrix entry for '{segment_name}'...") + messaging_properties = { + "Name": format_title(f"{PRODUCT_NAME} - {segment_name}"), + "Satz 1": format_rich_text(angle), + "Satz 2": format_rich_text(differentiation), + "Product Master": format_relation(product_page_id), + "Sector Master": format_relation(sector_page_id) + } + create_notion_page(DB_IDS["Messaging Matrix"], messaging_properties) + + # Update Product Master with relations to all processed sectors + if sector_page_ids_for_product: + print(f"\nUpdating Product Master with relations to {len(sector_page_ids_for_product)} sectors...") + update_notion_page(product_page_id, {"Sector Master": format_relation(sector_page_ids_for_product)}) + + # Clean up redundant fields in Product Master + print("Cleaning up redundant Strategy Matrix field in Product Master...") + update_notion_page(product_page_id, {"Strategy Matrix": format_rich_text("")}) + else: + print("Strategy Matrix is empty. Skipping distribution.") + + # 3. Distribute Feature-to-Value Translator Data + feature_translator_prop_id = product_page["properties"]["Feature-to-Value Translator"]["id"] + feature_translator_obj = get_page_property(product_page_id, feature_translator_prop_id) + feature_translator_text = get_rich_text_content(feature_translator_obj) + + if feature_translator_text: + parsed_features = parse_markdown_table(feature_translator_text) + if parsed_features: + print("\n--- Distributing Feature-to-Value Translator Data ---") + for item in parsed_features: + feature = item.get("Feature") + story = item.get("The Story (Benefit)") + headline = item.get("Headline") + + if not all([feature, story, headline]): + print(f"Skipping feature item due to missing data: {item}") + continue + + print(f"Creating Feature-to-Value entry for: {feature}") + create_notion_page( + DB_IDS["Feature-to-Value Translator"], + { + "Feature": format_title(feature), + "Story (Benefit)": format_rich_text(story), + "Headline": format_rich_text(headline), + "Product Master": format_relation(product_page_id) + } + ) + + # Clean up the source field + print("Cleaning up redundant Feature-to-Value Translator field in Product Master...") + update_notion_page(product_page_id, {"Feature-to-Value Translator": format_rich_text("")}) + else: + print("Feature-to-Value Translator is empty. Skipping distribution.") + + + print("\n--- Data distribution process complete. ---") + + +if __name__ == "__main__": + main() diff --git a/import_product.py b/import_product.py index 138d1643..c922403d 100644 --- a/import_product.py +++ b/import_product.py @@ -1,10 +1,19 @@ -# import_product.py import requests import json import re +import os +import time # --- Configuration --- -NOTION_TOKEN = "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" # This will be replaced by the user's actual token. +# NOTION_TOKEN wird jetzt aus der Datei gelesen +try: + with open("notion_token.txt", "r") as f: + NOTION_TOKEN = f.read().strip() +except FileNotFoundError: + print("Error: notion_token.txt not found.") + print("Please create the notion_token.txt file with your Notion integration token.") + exit(1) + NOTION_VERSION = "2022-06-28" NOTION_API_BASE_URL = "https://api.notion.com/v1" @@ -23,6 +32,11 @@ DB_IDS = { # --- Helper Functions --- +def clean_json_response(text): + if text.startswith("```json") and text.endswith("```"): + return text[7:-3].strip() + return text + def create_notion_page(database_id, properties): """Creates a new page in a Notion database.""" url = f"{NOTION_API_BASE_URL}/pages" @@ -43,6 +57,64 @@ def create_notion_page(database_id, properties): print(f"An unexpected error occurred while creating a page: {e}") return None +def update_notion_page(page_id, properties): + """Updates an existing page in Notion.""" + url = f"{NOTION_API_BASE_URL}/pages/{page_id}" + payload = { + "properties": properties + } + try: + response = requests.patch(url, headers=HEADERS, json=payload) + response.raise_for_status() + print(f"Successfully updated page {page_id}.") + return response.json() + except requests.exceptions.HTTPError as e: + print(f"HTTP Error updating page {page_id}: {e}") + print(f"Response content: {response.text}") + return None + except Exception as e: + print(f"An unexpected error occurred while updating a page: {e}") + return None + +def find_notion_page_by_title(database_id, title): + """Searches for a page in a Notion database by its title property.""" + url = f"{NOTION_API_BASE_URL}/databases/{database_id}/query" + filter_payload = { + "filter": { + "property": "Name", + "title": {"equals": title} + } + } + try: + response = requests.post(url, headers=HEADERS, json=filter_payload) + response.raise_for_status() + results = response.json().get("results") + if results: + return results[0] # Return the first matching page + return None + except requests.exceptions.HTTPError as e: + print(f"HTTP Error searching page in DB {database_id}: {e}") + print(f"Response content: {response.text}") + return None + except Exception as e: + print(f"An unexpected error occurred while searching for a page: {e}") + return None + +def get_database_properties(database_id): + """Retrieves the properties (schema) of a Notion database.""" + url = f"{NOTION_API_BASE_URL}/databases/{database_id}" + try: + response = requests.get(url, headers=HEADERS) + response.raise_for_status() + return response.json().get("properties") + except requests.exceptions.HTTPError as e: + print(f"HTTP Error retrieving database properties for DB {database_id}: {e}") + print(f"Response content: {response.text}") + return None + except Exception as e: + print(f"An unexpected error occurred while retrieving database properties: {e}") + return None + def format_rich_text(text): """Formats a string into Notion's rich text structure.""" return {"rich_text": [{"type": "text", "text": {"content": text}}]} @@ -78,25 +150,50 @@ def main(): print("ERROR: 'Puma_m20_2026-01-08.md' not found. Please make sure the file is in the same directory.") return - # --- Phase 1: Create Product in Product Master --- - print("--- Phase 1: Creating Product ---") + # Define the product name + PRODUCT_NAME = "Puma M20" # This will be replaced by the user's actual product name. + + # --- Phase 1: Prepare Product Data --- + print(f"--- Phase 1: Preparing Product Data for {PRODUCT_NAME} ---") product_analysis = extract_section(md_content, "2. Product Analysis") key_features = re.search(r"\*\*Key Features:\*\*(.*?)\*\*Constraints:\*\*", product_analysis, re.S).group(1).strip() constraints = re.search(r"\*\*Constraints:\*\*(.*)", product_analysis, re.S).group(1).strip() - + target_audience = extract_section(md_content, "3. Target Audience") + strategy_matrix = extract_section(md_content, "5. Strategy Matrix") + if len(strategy_matrix) > 2000: + strategy_matrix = strategy_matrix[:2000] # Truncate to 2000 characters + print("Warning: 'Strategy Matrix' content truncated to 2000 characters due to Notion API limit.") + feature_translator = extract_section(md_content, "FEATURE-TO-VALUE TRANSLATOR (PHASE 9)") + product_properties = { - "Name": format_title("Puma M20"), + "Name": format_title(PRODUCT_NAME), "Beschreibung": format_rich_text("Ein geländegängiger, wetterfester Roboter, der für anspruchsvolle Umgebungen konzipiert wurde."), - "Spezifikationen": format_rich_text(f"Key Features:\n{key_features}\n\nConstraints:\n{constraints}"), + "Key Features": format_rich_text(key_features), + "Constraints": format_rich_text(constraints), + "Target Audience": format_rich_text(target_audience), + "Strategy Matrix": format_rich_text(strategy_matrix), + "Feature-to-Value Translator": format_rich_text(feature_translator), "Layer": {"multi_select": [{"name": "Security"}, {"name": "Service"}]} } - product_page = create_notion_page(DB_IDS["Product Master"], product_properties) - if not product_page: - print("Failed to create product page. Aborting.") - return - product_page_id = product_page["id"] - print(f"Created Product 'Puma M20' with ID: {product_page_id}") + # Check if product already exists + existing_product_page = find_notion_page_by_title(DB_IDS["Product Master"], PRODUCT_NAME) + product_page_id = None + if existing_product_page: + product_page_id = existing_product_page["id"] + print(f"Product '{PRODUCT_NAME}' already exists with ID: {product_page_id}. Updating...") + updated_page = update_notion_page(product_page_id, product_properties) + if not updated_page: + print("Failed to update product page. Aborting.") + return + else: + print(f"Product '{PRODUCT_NAME}' not found. Creating new page...") + new_product_page = create_notion_page(DB_IDS["Product Master"], product_properties) + if not new_product_page: + print("Failed to create product page. Aborting.") + return + product_page_id = new_product_page["id"] + print(f"Created Product '{PRODUCT_NAME}' with ID: {product_page_id}") # --- Phase 2: Create Sectors in Sector & Persona Master --- diff --git a/read_file_content.py b/read_file_content.py new file mode 100644 index 00000000..396a4e0d --- /dev/null +++ b/read_file_content.py @@ -0,0 +1,19 @@ + +import argparse + +def read_file_content(file_path): + """Reads and prints the content of a specified file.""" + try: + with open(file_path, 'r', encoding='utf-8') as f: + print(f.read()) + except FileNotFoundError: + print(f"Error: File not found at '{file_path}'") + except Exception as e: + print(f"An error occurred: {e}") + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Read and display the content of a file.") + parser.add_argument("file_path", help="The path to the file you want to read.") + args = parser.parse_args() + + read_file_content(args.file_path) diff --git a/read_notion_dashboard.py b/read_notion_dashboard.py new file mode 100644 index 00000000..a70a22ba --- /dev/null +++ b/read_notion_dashboard.py @@ -0,0 +1,41 @@ + +import os +import requests +import json + +# Get the Notion API key from the environment variable +api_key = os.environ.get("NOTION_API_KEY") + +# If the API key is not set, try to read it from the file +if not api_key: + try: + with open("notion_token.txt", "r") as f: + api_key = f.read().strip() + except FileNotFoundError: + print("Error: notion_token.txt not found.") + print("Please set the NOTION_API_KEY environment variable or create the notion_token.txt file.") + exit() + +# The ID of the page to retrieve +page_id = "2e288f42-8544-81d8-96f5-c231f84f719a" # Product Master + +# The Notion API endpoint for retrieving a page +url = f"https://api.notion.com/v1/pages/{page_id}" + +# The headers for the API request +headers = { + "Authorization": f"Bearer {api_key}", + "Content-Type": "application/json", + "Notion-Version": "2022-06-28", +} + +# Make the API request +response = requests.get(url, headers=headers) + +# Check the response status code +if response.status_code == 200: + # Print the response content + print(json.dumps(response.json(), indent=2)) +else: + print(f"Error: {response.status_code}") + print(response.text)