Skip to content

Commit

Permalink
feat: first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
techmovie committed Mar 21, 2023
1 parent df5d550 commit e99db58
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
config.py
__pycache__
.DS_store
logs/bot.log
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Notion Telegram Bot

A simple Telegram Bot that updates a Notion database based on user input. This bot supports various property types and allows users to specify a custom database_id to update.

## Setup

1. Install the required Python packages:


```
pip install -r requirements.txt
```

2. Copy the `config_sample.py` file and rename it to `config.py`.

3. Set up your Notion API key and database ID in `config.py`:

```
NOTION_API_KEY = "your_notion_api_key"
NOTION_DATABASE_ID = "your_notion_database_id"
```

4. Set up your Telegram API key in `config.py`:

```
TELEGRAM_API_KEY = "your_telegram_api_key"
```

5. Run the bot:

```
python main.py
```

## Usage

1. Start a conversation with the bot in Telegram.
2. Use the `/start` or `/help` command to get instructions on how to format your message.
3. Send a message with the specified format to update the Notion database.
3 changes: 3 additions & 0 deletions config_sample.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
NOTION_API_KEY = "your_notion_api_key"
NOTION_DATABASE_ID = "your_notion_database_id"
TELEGRAM_API_KEY = "your_telegram_api_key"
19 changes: 19 additions & 0 deletions logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import logging
import os

def setup_logger():
log_file_path = os.path.join('logs', 'bot.log')

logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(log_file_path),
logging.StreamHandler()
]
)

logger = logging.getLogger(__name__)
return logger

logger = setup_logger()
5 changes: 5 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from telegram_bot import TelegramBot

if __name__ == '__main__':
bot = TelegramBot()
bot.start()
25 changes: 25 additions & 0 deletions message_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from notion_manager import NotionManager
from logger import logger

notion_manager = NotionManager()
def send_help():
help_message = (
"To update the Notion database, send a message starting with the /update command and the following format:\n\n"
"/update\n"
"database_id:your_custom_database_id (optional)\n"
"property_name1:value1\n"
"property_name2:value2\n"
"...\n\n"
"If you don't specify a database_id, the bot will use the default one from the configuration file.\n\n"
"Supported property types: title, rich_text, number, select, multi_select, "
"date, people, files, checkbox, url, email, phone_number"
)
return help_message

def process_message(message):
try:
# Add data to the Notion database
notion_manager.add_to_database(message)
return "Data added to Notion database"
except Exception as e:
raise e
91 changes: 91 additions & 0 deletions notion_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
from notion_client import Client
from config import NOTION_API_KEY, NOTION_DATABASE_ID
from logger import logger

class NotionManager:
def __init__(self):
self.notion = Client(auth=NOTION_API_KEY)
self.default_database_id = NOTION_DATABASE_ID

def get_database_properties(self,database_id = None):
if database_id is None:
database_id = self.default_database_id
database = self.notion.databases.retrieve(database_id)
return database["properties"]

def _get_database_id(self, message):
lines = message.split('\n')
for line in lines:
if line.startswith('database_id:'):
return line.split('database_id:')[1].strip()
return self.default_database_id

def get_database_properties(self, database_id):
database = self.notion.databases.retrieve(database_id)
return database["properties"]

def parse_message(self, message):
data = {}
lines = message.split('\n')
for line in lines:
if ':' in line:
prop_name, value = line.split(':', 1)
data[prop_name] = value
return data

def add_to_database(self, message):
try:
database_id = self._get_database_id(message)
properties = self.get_database_properties(database_id)
data = self.parse_message(message)
if not properties:
raise BaseException(f"The properties of database {database_id} is empty.Please check the database and try again.")
if not data:
raise ValueError("The parsed message is empty. Please check the message format.")

unrecognized_properties = []
new_page = {}
for key, value in data.items():
if key in properties:
new_page[key] = self.create_property_value(properties[key]['type'], value)
elif(key != "database_id"):
unrecognized_properties.append(key)
if unrecognized_properties:
raise ValueError(f"The following keys are not present in the database properties: {', '.join(unrecognized_properties)}. Please check the property names and try again.")
if not new_page:
raise ValueError("The provided property is empty. Please check the message format.")
self.notion.pages.create(parent={"database_id": database_id}, properties=new_page)
except ValueError as ve:
raise ve
except Exception as e:
raise e

def create_property_value(self, property_type, value):
if property_type == "title":
return {"title": [{"text": {"content": value}}]}
elif property_type == "rich_text":
return {"rich_text": [{"text": {"content": value}}]}
elif property_type == "number":
return {"number": float(value)}
elif property_type == "select":
return {"select": {"name": value}}
elif property_type == "multi_select":
return {"multi_select": [{"name": v.strip()} for v in value.split(',')]}
elif property_type == "date":
return {"date": {"start": value}}
elif property_type == "people":
# This example assumes that user input is a comma-separated list of user IDs.
return {"people": [{"id": user_id.strip()} for user_id in value.split(',')]}
elif property_type == "files":
# This example assumes that user input is a comma-separated list of file URLs.
return {"files": [{"external": {"url": file_url.strip()}} for file_url in value.split(',')]}
elif property_type == "checkbox":
return {"checkbox": value.lower() == 'true'}
elif property_type == "url":
return {"url": value}
elif property_type == "email":
return {"email": value}
elif property_type == "phone_number":
return {"phone_number": value}
else:
raise ValueError(f"Unsupported property type: {property_type}")
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
notion-client
pyTelegramBotAPI
31 changes: 31 additions & 0 deletions telegram_bot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import telebot
from config import TELEGRAM_API_KEY
from message_handler import process_message, send_help
from logger import logger

class TelegramBot:
def __init__(self):
self.bot = telebot.TeleBot(TELEGRAM_API_KEY)

def start(self):
@self.bot.message_handler(commands=['start', 'help'])
def handle_help(message):
response = send_help()
self.bot.reply_to(message, response)

@self.bot.message_handler(commands=['update'])
def handle_update(message):
message_text = message.text
message_text = message_text.replace('/update', '', 1).strip()

if not message_text:
self.bot.reply_to(message, "The message is empty. Please provide the required information.")

try:
process_message(message_text)
self.bot.reply_to(message, "The Notion database has been updated successfully.")
except Exception as e:
logger.exception(f"Failed to update the Notion database,{e}")
self.bot.reply_to(message, f"An error occurred while updating the Notion database: {e}")

self.bot.polling()

0 comments on commit e99db58

Please sign in to comment.