serJD's picture
Update app.py
60577ef verified
#!pip install -q specklepy
# lone github repro & add to sys paths
import gradio as gr
import os
import sys
import time
import copy
import requests
from notion_client import Client
from huggingface_hub import webhook_endpoint, WebhookPayload
from fastapi import Request
import requests
import datetime
import json
def get_database_properties_overview(database_pages):
# Iterate through the results (each page corresponds to a row in the database)
for page in database_pages:
print(f"Page ID: {page['id']}")
# Print the name and type of each property in this page
for prop_name, prop_data in page['properties'].items():
prop_type = prop_data['type']
print(f"Property Name: {prop_name}, Property Type: {prop_type}")
break
# query full database
def fetch_all_database_pages(client, database_id):
"""
Fetches all pages from a specified Notion database.
:param client: Initialized Notion client.
:param database_id: The ID of the Notion database to query.
:return: A list containing all pages from the database.
"""
start_cursor = None
all_pages = []
while True:
response = client.databases.query(
**{
"database_id": database_id,
"start_cursor": start_cursor
}
)
all_pages.extend(response['results'])
# Check if there's more data to fetch
if response['has_more']:
start_cursor = response['next_cursor']
else:
break
return all_pages
def get_property_value(page, property_name):
"""
Extracts the value from a specific property in a Notion page based on its type.
:param page: The Notion page data as retrieved from the API.
:param property_name: The name of the property whose value is to be fetched.
:return: The value or values contained in the specified property, depending on type.
"""
# Check if the property exists in the page
if property_name not in page['properties']:
return None # or raise an error if you prefer
property_data = page['properties'][property_name]
prop_type = property_data['type']
# Handle 'title' and 'rich_text' types
if prop_type in ['title', 'rich_text']:
return ''.join(text_block['text']['content'] for text_block in property_data[prop_type])
# Handle 'number' type
elif prop_type == 'number':
return property_data[prop_type]
# Handle 'select' type
elif prop_type == 'select':
return property_data[prop_type]['name'] if property_data[prop_type] else None
# Handle 'multi_select' type
elif prop_type == 'multi_select':
return [option['name'] for option in property_data[prop_type]]
# Handle 'date' type
elif prop_type == 'date':
if property_data[prop_type]['end']:
return (property_data[prop_type]['start'], property_data[prop_type]['end'])
else:
return property_data[prop_type]['start']
# Handle 'relation' type
elif prop_type == 'relation':
return [relation['id'] for relation in property_data[prop_type]]
# Handle 'people' type
elif prop_type == 'people':
return [person['name'] for person in property_data[prop_type] if 'name' in person]
# Add more handlers as needed for other property types
else:
# Return None or raise an error for unsupported property types
return None
def replace_property_value(page, property_name, new_value):
"""
Replaces the value of a specified property in a Notion page object.
:param page: The Notion page object.
:param property_name: The name of the property to replace.
:param new_value: The new value to set for the property.
"""
if property_name not in page['properties']:
raise ValueError(f"Property '{property_name}' not found in the page.")
prop_type = page['properties'][property_name]['type']
# Handle 'rich_text' and 'title' types
if prop_type in ['rich_text', 'title']:
page['properties'][property_name][prop_type] = [{'text': {'content': new_value}}]
# Handle 'number' type
elif prop_type == 'number':
page['properties'][property_name][prop_type] = new_value
# Handle 'select' type
elif prop_type == 'select':
page['properties'][property_name][prop_type] = {'name': new_value}
# Handle 'multi_select' type (assuming new_value is a list of strings)
elif prop_type == 'multi_select':
page['properties'][property_name][prop_type] = [{'name': val} for val in new_value]
# Handle 'date' type
elif prop_type == 'date':
page['properties'][property_name][prop_type] = {'start': new_value} # Assuming new_value is a date string
# Handle 'checkbox' type
elif prop_type == 'checkbox':
page['properties'][property_name][prop_type] = new_value # Assuming new_value is a boolean
# Handle 'url' type
elif prop_type == 'url':
page['properties'][property_name][prop_type] = new_value # Assuming new_value is a valid URL string
# Handle 'email' type
elif prop_type == 'email':
page['properties'][property_name][prop_type] = new_value # Assuming new_value is a valid email string
# Add more handlers for other types as needed
else:
raise NotImplementedError(f"Property type '{prop_type}' is not supported in this function.")
def remove_property(page, property_name):
"""
Removes a specified property from a Notion page object.
:param page: The Notion page object.
:param property_name: The name of the property to remove.
:return: The updated Notion page object.
"""
if property_name in page['properties']:
del page['properties'][property_name]
else:
raise ValueError(f"Property '{property_name}' not found in the page.")
return page
def check_and_update_or_create_page(notion, page_data, target_database_id, title_property_name):
"""
Checks if a page with the given title exists in the target database.
If it does, updates the page; if not, creates a new page.
:param notion: Notion client instance.
:param page_data: Data for the page to create or update.
:param target_database_id: ID of the target database.
:param title_property_name: The name of the title property to check.
"""
# Query the target database for a page with the same >> title <<
query_filter = {
"property": title_property_name,
"title": {
"equals": page_data['properties'][title_property_name]['title'][0]['text']['content']
}
}
response = notion.databases.query(database_id=target_database_id, filter=query_filter)
existing_pages = response.get('results', [])
if existing_pages:
# Page already exists, update it
page_id = existing_pages[0]['id']
#print(page_data['properties'])
notion.pages.update(page_id=page_id, properties=page_data['properties'])
else:
# Page does not exist, create it
notion.pages.create(parent={"database_id": target_database_id}, properties=page_data['properties'])
def get_page_by_id(notion_db_pages, page_id):
for pg in notion_db_pages:
if pg["id"] == page_id:
return pg
def reset_database(notion, database_id):
"""
Resets a Notion database by archiving all its pages.
Parameters:
notion (Client): The Notion client instance.
database_id (str): The ID of the database to reset.
"""
def retrieve_all_pages():
has_more = True
start_cursor = None
pages = []
while has_more:
response = notion.databases.query(
**{"database_id": database_id, "start_cursor": start_cursor}
)
pages.extend(response["results"])
has_more = response["has_more"]
start_cursor = response.get("next_cursor")
return pages
def delete_page(page_id):
notion.pages.update(page_id, archived=True)
pages = retrieve_all_pages()
for page in pages:
delete_page(page["id"])
print(f"Reset of database {database_id} completed.")
guiding_db_an = "1dafd962f861406d928bbdf109b9bfe4"
land_use_abbr = "3b0e681e922a41409b6a13c11105c56a"
target_db = "ec2a636f079d4d7686f94901b6238242"
# Function to run on button click
@webhook_endpoint # Define a unique endpoint URL
async def update_table(request: Request):
# Read the request body as JSON
payload = await request.json()
print(str(payload))
continueFlag = True
# Accessing nested data in the 'event' object
if continueFlag:
tkn = os.environ.get("NOTION_TOKEN")
notion = Client(auth=tkn)
database_pages = fetch_all_database_pages(notion, guiding_db_an)
lu_name_db = notion.databases.query(database_id=land_use_abbr)
name_mapper = {}
name_mapperM = {}
for page in lu_name_db["results"]:
oriName = get_property_value(page, "name")
shortName = get_property_value(page, "nameShort")
medName = get_property_value(page, "nameMedium")
name_mapper[oriName] = shortName
name_mapperM[oriName] = medName
# Iterate through the results (each page corresponds to a row in the database)
for page in database_pages:
#check speckleAnalysisName
speckName = get_property_value(page, "speckleName")
shortName = get_property_value(page, "nameShort")
longName = get_property_value(page, "nameLong")
#print(shortName)
#print(longName)
subAttributes = get_property_value(page, "level_4")
subAttributeFlag = False
if len(subAttributes)>1:
if subAttributes[0] != 'NA':
subAttributeFlag = True
for subAttr in subAttributes:
# construct new page (speckleName, Name, longName, shortName, remove level_4)
new_page = copy.deepcopy(page)
speckName_full = speckName+subAttr
if "#+" in shortName:
shortestName = name_mapper.get(subAttr,subAttr)
mediumName = name_mapperM.get(subAttr,subAttr)
#print("shortestName", shortestName, subAttr)
shortName_full = shortName.replace("#+", shortestName)
shortName_full.replace("DRT", "ART")
#update short name
replace_property_value(new_page, "nameShort", shortName_full )
if "#+" in longName:
longName_full = longName.replace("#+", "::" +mediumName)
longName_full = longName_full.replace(" ::", "::")
longName_full = longName_full.replace(":: ", "::")
longName_full.replace("DRT", "ART")
#update long name
replace_property_value(new_page, "nameLong", longName_full )
#update speckle name (-> as title column)
replace_property_value(new_page, "name", speckName_full)
# remove level_4 and speckleAnalysisName
new_page = remove_property(new_page, "level_4")
new_page = remove_property(new_page, "speckleName")
new_page = remove_property(new_page, "Items")
# update target database in notion
check_and_update_or_create_page(notion, new_page, target_db, "name")
if subAttributeFlag == False:
# forward page
new_page = copy.deepcopy(page)
replace_property_value(new_page, "name", speckName)
new_page = remove_property(new_page, "level_4")
new_page = remove_property(new_page, "speckleName")
new_page = remove_property(new_page, "Items")
# update target database in notion
#print(get_property_value(new_page, "nameLong"))
check_and_update_or_create_page(notion, new_page, target_db, "name")
return "table updated successfully"