-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
219 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
config.py | ||
__pycache__ | ||
.DS_store | ||
logs/bot.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
notion-client | ||
pyTelegramBotAPI |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |