├── .env.example ├── .gitignore ├── LICENSE ├── README.md ├── api_calls.py ├── main.py └── requirements.txt /.env.example: -------------------------------------------------------------------------------- 1 | OPENAI_API_KEY="your_api_key" 2 | NOTION_TOKEN="your_notion_token" 3 | NOTION_DATABASE_ID="your_database_id" 4 | 5 | ``` -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | build/ 11 | develop-eggs/ 12 | dist/ 13 | downloads/ 14 | eggs/ 15 | .eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | wheels/ 22 | share/python-wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .nox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *.cover 48 | *.py,cover 49 | .hypothesis/ 50 | .pytest_cache/ 51 | cover/ 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | local_settings.py 60 | db.sqlite3 61 | db.sqlite3-journal 62 | 63 | # Flask stuff: 64 | instance/ 65 | .webassets-cache 66 | 67 | # Scrapy stuff: 68 | .scrapy 69 | 70 | # Sphinx documentation 71 | docs/_build/ 72 | 73 | # PyBuilder 74 | .pybuilder/ 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | # For a library or package, you might want to ignore these files since the code is 86 | # intended to run in multiple environments; otherwise, check them in: 87 | # .python-version 88 | 89 | # pipenv 90 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 91 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 92 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 93 | # install all needed dependencies. 94 | #Pipfile.lock 95 | 96 | # poetry 97 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 98 | # This is especially recommended for binary packages to ensure reproducibility, and is more 99 | # commonly ignored for libraries. 100 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 101 | #poetry.lock 102 | 103 | # pdm 104 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 105 | #pdm.lock 106 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 107 | # in version control. 108 | # https://pdm.fming.dev/#use-with-ide 109 | .pdm.toml 110 | 111 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 112 | __pypackages__/ 113 | 114 | # Celery stuff 115 | celerybeat-schedule 116 | celerybeat.pid 117 | 118 | # SageMath parsed files 119 | *.sage.py 120 | 121 | # Environments 122 | .env 123 | .venv 124 | env/ 125 | venv/ 126 | ENV/ 127 | env.bak/ 128 | venv.bak/ 129 | 130 | # Spyder project settings 131 | .spyderproject 132 | .spyproject 133 | 134 | # Rope project settings 135 | .ropeproject 136 | 137 | # mkdocs documentation 138 | /site 139 | 140 | # mypy 141 | .mypy_cache/ 142 | .dmypy.json 143 | dmypy.json 144 | 145 | # Pyre type checker 146 | .pyre/ 147 | 148 | # pytype static type analyzer 149 | .pytype/ 150 | 151 | # Cython debug symbols 152 | cython_debug/ 153 | 154 | # PyCharm 155 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 156 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 157 | # and can be added to the global gitignore or merged into this file. For a more nuclear 158 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 159 | .idea/ 160 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NotionWizard 2 | 3 | This is a simple Notion Page Assistant that uses OpenAI's functions to create a Notion page. 4 | 5 | It provides a chat-based interface where you can interact with the assistant. Simply enter your message in the chat input and press Enter. The assistant will respond with appropriate actions. 6 | 7 | ## Prerequisites 8 | 9 | - You need to have Python installed on your machine. You can download it from [here](https://www.python.org/downloads/). 10 | - You also need to install the `openai` and `requests` Python libraries. You can install them using pip: 11 | 12 | ```bash 13 | pip install -r requirements.txt 14 | ``` 15 | 16 | - You need to have an OpenAI API key. You can get it from [here](https://beta.openai.com/signup/). 17 | - You also need a Notion API token and a Page ID. You can get them by following the instructions [here](https://developers.notion.com/docs). 18 | - Please also check [here](https://developers.notion.com/docs/create-a-notion-integration) for more information on how to create a Notion integration. 19 | - To get the page ID, click on Share at the top right of your Notion page and copy the link. The page ID is the last part of the link. For example, if the link is `https://www.notion.so/Getting-Started-c51d744605e94cf9b2a74a9692338072`, the page ID is `c51d744605e94cf9b2a74a9692338072`. 20 | 21 | 22 | ## Usage 23 | 24 | 1. Clone this repository: 25 | 26 | 2. Navigate to the project directory: 27 | 28 | ```bash 29 | cd openai-notion-page-creator 30 | ``` 31 | 32 | 4. Run the script: 33 | 34 | ```bash 35 | streamlit run main.py 36 | ``` 37 | Enter your OpenAI API key, Notion API token, and Page ID in the appropriate fields and click on the `Submit` button. 38 | 39 | ## Contributing 40 | 41 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 42 | 43 | ## License 44 | 45 | [MIT](https://choosealicense.com/licenses/mit/) 46 | 47 | -------------------------------------------------------------------------------- /api_calls.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | import requests 4 | import streamlit as st 5 | from dotenv import load_dotenv 6 | # Load environment variables from .env file 7 | load_dotenv() 8 | 9 | notion_token = os.getenv('NOTION_API_KEY') 10 | 11 | url = "https://api.notion.com/v1/pages" 12 | headers = { 13 | "Authorization": f"Bearer {notion_token}", 14 | "Content-Type": "application/json", 15 | "Notion-Version": "2022-06-28" 16 | } 17 | 18 | def create_notion_page_with_content(page_title, content, page_id): 19 | 20 | url = "https://api.notion.com/v1/pages/" 21 | 22 | payload = json.dumps({ 23 | "parent": { 24 | "page_id": page_id 25 | }, 26 | "properties": { 27 | "title": { 28 | "title": [{"type": "text", "text": {"content": page_title}}] 29 | } 30 | }, 31 | "children": [ 32 | { 33 | "object": "block", 34 | "type": "paragraph", 35 | "paragraph": { 36 | "rich_text": [{"type": "text", "text": { 37 | "content": content }}] 38 | } 39 | } 40 | ] 41 | 42 | }) 43 | response = requests.request("POST", url, headers=headers, data=payload) 44 | 45 | if response.status_code == 200: 46 | response = response.json() 47 | st.balloons() 48 | st.success("Page created successfully") 49 | page_title = response['properties']['title']['title'][0]['text']['content'] 50 | page_url = response['url'] 51 | st.session_state['page_title'] = page_title 52 | st.session_state['page_url'] = page_url 53 | 54 | return {'status': 'success', 'page_title': page_title, 'page_url': page_url} 55 | else: 56 | st.error(f"Failed to create page.{response.json()['message']}") 57 | return {'status': 'error', 'error': response} 58 | 59 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import json 2 | import time 3 | import openai 4 | import streamlit as st 5 | import api_calls 6 | import requests 7 | import os 8 | from dotenv import load_dotenv 9 | import requests 10 | 11 | # Load environment variables from .env file 12 | load_dotenv() 13 | 14 | openai_api_key = os.getenv('OPENAI_API_KEY') 15 | notion_api_key = os.getenv('NOTION_API_KEY') 16 | page_id = os.getenv('PAGE_ID') 17 | 18 | def setup_st_interface(): 19 | """Set up the Streamlit interface and handle API key form submission.""" 20 | st.title("Notion Page Assistant") 21 | # Initialize message history 22 | st.session_state.messages = st.session_state.get('messages', [{"role": "assistant", "content": "Welcome! How can I assist you today?"}]) 23 | 24 | # Display chat history 25 | for message in st.session_state.messages: 26 | with st.chat_message(message["role"]): 27 | st.markdown(message["content"]) 28 | 29 | 30 | def process_input(): 31 | """Process user input and display assistant response.""" 32 | if prompt := st.chat_input("What is up?"): 33 | st.session_state.messages.append({"role": "user", "content": prompt}) 34 | 35 | with st.chat_message("user"): 36 | st.markdown(prompt) 37 | 38 | assistant_response = get_assistant_response(prompt) 39 | 40 | with st.chat_message("assistant"): 41 | message_placeholder = st.empty() 42 | if assistant_response: 43 | response_chunk = "" 44 | for chunk in assistant_response.split(): 45 | response_chunk += chunk + " " 46 | time.sleep(0.05) 47 | message_placeholder.markdown(response_chunk + "▌") 48 | 49 | message_placeholder.markdown(assistant_response) 50 | 51 | st.session_state.messages.append({"role": "assistant", "content": assistant_response}) 52 | 53 | 54 | def get_assistant_response(input_text): 55 | functions = [ 56 | { 57 | "name": "get_response_for_chat", 58 | "description": "Gets a reply from the GPT-3 model to display in the chat", 59 | "parameters": { 60 | "type": "object", 61 | "properties": { 62 | "Reply": { 63 | "type": "string", 64 | "description": "The reply to display in the chat so as to make it look like a real conversation" 65 | } 66 | }, 67 | "required": ["Reply"] 68 | } 69 | }, 70 | { 71 | "name": "create_notion_page_with_content", 72 | "description": "Creates a new Notion page with the input text as the content.", 73 | "parameters": { 74 | "type": "object", 75 | "properties": { 76 | "Title": { 77 | "type": "string", 78 | "description": "The Title of the page" 79 | }, 80 | "Content": { 81 | "type": "string", 82 | "description": "The content of the page.You can generate this based on a user's input or take a user's input as content.Format this content accordingly" 83 | } 84 | }, 85 | "required": ["Title", "Content"] 86 | } 87 | }, 88 | ] 89 | model = "gpt-3.5-turbo-0613" 90 | messages = [{"role": "user", "content": input_text}] 91 | 92 | 93 | # Define the API endpoint 94 | api_endpoint = "https://api.openai.com/v1/chat/completions" 95 | 96 | # Set up the request payload 97 | payload = { 98 | "model": model, 99 | "messages": messages, 100 | "functions": functions 101 | } 102 | 103 | # Set up the request headers 104 | headers = { 105 | "Authorization": f"Bearer {openai_api_key}", 106 | "Content-Type": "application/json" 107 | } 108 | 109 | # Make the POST request 110 | response = requests.post(api_endpoint, json=payload, headers=headers) 111 | 112 | # Handle the response 113 | if response.status_code == 200: 114 | completion = response.json() 115 | else: 116 | # Handle error response 117 | return "Authentication Error, please check your APi keys and try again" 118 | 119 | try: 120 | function_arguments = json.loads(completion['choices'][0]['message']['function_call']['arguments']) 121 | print(function_arguments["Title"]) 122 | 123 | if 'Reply' in function_arguments: 124 | return function_arguments['Reply'] 125 | elif 'Content' in function_arguments: 126 | try: 127 | page_details = api_calls.create_notion_page_with_content( 128 | function_arguments['Title'], 129 | function_arguments['Content'], 130 | page_id 131 | ) 132 | except Exception as e: 133 | print(e) 134 | return "Error creating page. Please check your Notion integration/API keys and try again." 135 | return f"Page Title: {page_details['page_title']}\nURL: {page_details['page_url']}" 136 | except KeyError: 137 | return completion['choices'][0]['message']['content'] 138 | 139 | 140 | if __name__ == "__main__": 141 | setup_st_interface() 142 | process_input() 143 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peterw/NotionWizard/2f45f1114c4462690b90fe648adca235bbfc6123/requirements.txt --------------------------------------------------------------------------------