diff --git a/.gitignore b/.gitignore index c066242..31d2eef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .venv/* -tokens.yml +.env +config.yaml __pycache__/ \ No newline at end of file diff --git a/capture_bot_san/__init__.py b/capture_bot_san/__init__.py new file mode 100755 index 0000000..ab2fc5d --- /dev/null +++ b/capture_bot_san/__init__.py @@ -0,0 +1 @@ +# empty file \ No newline at end of file diff --git a/capture_bot_san/__main__.py b/capture_bot_san/__main__.py new file mode 100755 index 0000000..dfc0fdb --- /dev/null +++ b/capture_bot_san/__main__.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from . import token +from . import config + +def main(): + config.read_config() + token.read_tokens() + + +if __name__ == '__main__': + main() + + diff --git a/capture_bot_san/config.py b/capture_bot_san/config.py index 42274cd..0aab96d 100755 --- a/capture_bot_san/config.py +++ b/capture_bot_san/config.py @@ -1,83 +1,52 @@ import yaml -from dropbox import DropboxOAuth2FlowNoRedirect - - -CONFIG_VERSION = 1 -CONFIG_FILE = 'tokens.yml' -# read or create config file -# find the config file, if it doesn't exist, create it +from . import constants class Config: def __init__(self): - self.Comment = '# Capture Bot San Config File' - self.DISCORD_TOKEN = '' - self.DROPBOX_APP_KEY = '' - self.DROPBOX_APP_SECRET = '' - self.DROPBOX_REFRESH_TOKEN = '' - -def create_config(): + self.DROPBOX_TEXTFILE_FOLDER = '' + self.DROPBOX_MEDIA_FOLDER = '' + self.MARKDOWN_FILENAME = '' + +# read or create config file +# find the config file or create it otherwise +def create_config(): + print('Creating config...') try: - open(CONFIG_FILE, 'w') + open(constants.CONFIG_FILE, 'w') except OSError as e: print(f'Error: {e.strerror}') + exit(1) def read_config(): config = Config() + print('Reading config...') + write_back = False try: - with open(CONFIG_FILE, 'r') as f: - file_content = yaml.safe_load(f) - if file_content is None: - file_content = {} + with open(constants.CONFIG_FILE, 'r') as file: + parsed = yaml.safe_load(file) or {} + config.DROPBOX_TEXTFILE_FOLDER = parsed.get('DROPBOX_TEXTFILE_FOLDER') or '' + config.DROPBOX_MEDIA_FOLDER = parsed.get('DROPBOX_MEDIA_FOLDER') or '' + config.MARKDOWN_FILENAME = parsed.get('MARKDOWN_FILENAME') or '' - config.DISCORD_TOKEN = file_content.get('DISCORD_TOKEN') or '' - config.DROPBOX_APP_KEY = file_content.get('DROPBOX_APP_KEY') or '' - config.DROPBOX_APP_SECRET = file_content.get('DROPBOX_APP_SECRET') or '' - config.DROPBOX_REFRESH_TOKEN = file_content.get('DROPBOX_REFRESH_TOKEN') or '' - - write_back = False - - if config.DISCORD_TOKEN == '': + if config.DROPBOX_TEXTFILE_FOLDER == '': write_back = True - print('Discord token not set') - print('Go to https://discord.com/developers/applications/ and create it.') - print('New Application -> Bot -> Token -> Copy!') - config.DISCORD_TOKEN = input('Discord Token: ').strip() - if config.DROPBOX_APP_KEY == '' or config.DROPBOX_APP_SECRET == '': + print('Dropbox textfile folder not set') + config.DROPBOX_TEXTFILE_FOLDER = input('Dropbox textfile folder(e.g. /notes): ').strip() + if config.DROPBOX_MEDIA_FOLDER == '': write_back = True - print('Dropbox app key or secret not set') - print('Go to https://www.dropbox.com/developers/apps and create it.') - print('1. Scoped Access, 2. Full Dropbox, 3. [whatever]') - print('Dropbox App key and App secret will be displayed.') - config.DROPBOX_APP_KEY = input('App key: ').strip() - config.DROPBOX_APP_SECRET = input('App secret: ').strip() - if config.DROPBOX_REFRESH_TOKEN == '': + print('Dropbox media folder not set') + config.DROPBOX_MEDIA_FOLDER = input('Dropbox media folder(e.g. /notes/media): ').strip() + if config.MARKDOWN_FILENAME == '': write_back = True - print('Dropbox refresh token not set. Try to get it...') - if config.DROPBOX_APP_KEY == '' or config.DROPBOX_APP_SECRET == '': - print('Requries Dropbox app key and secret. Give up.') - exit(1) - - auth_flow = DropboxOAuth2FlowNoRedirect(config.DROPBOX_APP_KEY, consumer_secret=config.DROPBOX_APP_SECRET, use_pkce=False, token_access_type='offline') - authorize_url = auth_flow.start() - print('1. Go to:', authorize_url) - print('2. Click "Allow" (you might have to log in first)') - print('3. Copy the authorization code.') - auth_code = input('Enter the authorization code here: ').strip() - try: - oauth_result = auth_flow.finish(auth_code) - print("Refresh token:", oauth_result.refresh_token) - config.DROPBOX_REFRESH_TOKEN = oauth_result.refresh_token - except Exception as e: - print('Error:', e) - exit(1) - + print('Markdown filename not set') + config.MARKDOWN_FILENAME = input('Markdown filename(e.g. capture.md): ').strip() if write_back: - with open(CONFIG_FILE, 'w') as f: - yaml.dump(config.__dict__, f) - + print('Writing back to config...') + yaml.dump({'DROPBOX_TEXTFILE_FOLDER': config.DROPBOX_TEXTFILE_FOLDER, 'DROPBOX_MEDIA_FOLDER': config.DROPBOX_MEDIA_FOLDER, 'MARKDOWN_FILENAME': config.MARKDOWN_FILENAME}, open(constants.CONFIG_FILE, 'w')) except FileNotFoundError: - file_content = create_config() + print('Config file not found. Creating...') + create_config() read_config() - - return config - + + + diff --git a/capture_bot_san/constants.py b/capture_bot_san/constants.py new file mode 100755 index 0000000..3855019 --- /dev/null +++ b/capture_bot_san/constants.py @@ -0,0 +1,2 @@ +TOKEN_FILE = '.env' +CONFIG_FILE = 'config.yaml' \ No newline at end of file diff --git a/capture_bot_san/main.py b/capture_bot_san/main.py deleted file mode 100755 index 95fe175..0000000 --- a/capture_bot_san/main.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python3 - -import config - - - -config.read_config() - - - diff --git a/capture_bot_san/token.py b/capture_bot_san/token.py new file mode 100755 index 0000000..d5dcc40 --- /dev/null +++ b/capture_bot_san/token.py @@ -0,0 +1,72 @@ +import dotenv +dotenv.load_dotenv() +import os +from dropbox import DropboxOAuth2FlowNoRedirect +from . import constants + +class Token: + def __init__(self): + self.DISCORD_TOKEN = '' + self.DROPBOX_APP_KEY = '' + self.DROPBOX_APP_SECRET = '' + self.DROPBOX_REFRESH_TOKEN = '' + +# read or create token file +# find the +def read_tokens(): + print('Reading tokens...') + token = Token() + token.DISCORD_TOKEN = os.getenv('DISCORD_TOKEN') or '' + token.DROPBOX_APP_KEY = os.getenv('DROPBOX_APP_KEY') or '' + token.DROPBOX_APP_SECRET = os.getenv('DROPBOX_APP_SECRET') or '' + token.DROPBOX_REFRESH_TOKEN = os.getenv('DROPBOX_REFRESH_TOKEN') or '' + + write_back = False + + if token.DISCORD_TOKEN == '': + write_back = True + print('Discord token not set') + print('Go to https://discord.com/developers/applications/ and create it.') + print('New Application -> Bot -> Token -> Copy!') + token.DISCORD_TOKEN = input('Discord Token: ').strip() + if token.DROPBOX_APP_KEY == '' or token.DROPBOX_APP_SECRET == '': + write_back = True + print('Dropbox app key or secret not set') + print('Go to https://www.dropbox.com/developers/apps and create it.') + print('1. Scoped Access, 2. Full Dropbox, 3. [whatever]') + print('Dropbox App key and App secret will be displayed.') + token.DROPBOX_APP_KEY = input('App key: ').strip() + token.DROPBOX_APP_SECRET = input('App secret: ').strip() + if token.DROPBOX_REFRESH_TOKEN == '': + write_back = True + print('Dropbox refresh token not set. Try to get it...') + if token.DROPBOX_APP_KEY == '' or token.DROPBOX_APP_SECRET == '': + print('Requries Dropbox app key and secret. Give up.') + exit(1) + + auth_flow = DropboxOAuth2FlowNoRedirect(token.DROPBOX_APP_KEY, consumer_secret=token.DROPBOX_APP_SECRET, use_pkce=False, token_access_type='offline') + authorize_url = auth_flow.start() + print('1. Go to:', authorize_url) + print('2. Click "Allow" (you might have to log in first)') + print('3. Copy the authorization code.') + auth_code = input('Enter the authorization code here: ').strip() + try: + oauth_result = auth_flow.finish(auth_code) + print("Refresh token:", oauth_result.refresh_token) + token.DROPBOX_REFRESH_TOKEN = oauth_result.refresh_token + except Exception as e: + print('Error:', e) + exit(1) + + if write_back: + dotenv.set_key(constants.TOKEN_FILE, 'DISCORD_TOKEN', token.DISCORD_TOKEN) + dotenv.set_key(constants.TOKEN_FILE, 'DROPBOX_APP_KEY', token.DROPBOX_APP_KEY) + dotenv.set_key(constants.TOKEN_FILE, 'DROPBOX_APP_SECRET', token.DROPBOX_APP_SECRET) + dotenv.set_key(constants.TOKEN_FILE, 'DROPBOX_REFRESH_TOKEN', token.DROPBOX_REFRESH_TOKEN) + print('Tokens written to .env file.') + + return token + + + + \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 4066f9f..1a9bebc 100644 --- a/poetry.lock +++ b/poetry.lock @@ -496,6 +496,20 @@ files = [ {file = "ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3"}, ] +[[package]] +name = "python-dotenv" +version = "1.0.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + [[package]] name = "pytz" version = "2024.1" @@ -738,4 +752,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "0cec85b8dce92143d2f503fb44a9c8cafe4cabe88f1aa29472b2dfa8bb288793" +content-hash = "f94df9517f6942e31a03c96b92a1eb0851ea71c7a61e4443c4590c1a9cdf18a5" diff --git a/pyproject.toml b/pyproject.toml index ce0d99a..3a94605 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,13 +6,16 @@ authors = ["kaz Saita "] license = "MIT" readme = "README.md" package-mode = false - +packages = [ + { include = "capture_bot_san" } +] [tool.poetry.dependencies] python = "^3.11" discord = "^2.3.2" dropbox = "^11.36.2" pytz = "^2024.1" pyyaml = "^6.0.1" +python-dotenv = "^1.0.1" [build-system]