diff --git a/get_refresh_token.py b/get_refresh_token.py new file mode 100755 index 0000000..02bbf4f --- /dev/null +++ b/get_refresh_token.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +#https://note.com/surugawannoebi/n/n6ae44d916fd4 + +import requests +from requests.auth import HTTPBasicAuth + +def get_dropbox_refresh_token(app_key, app_secret, auth_code): + url = "https://api.dropbox.com/oauth2/token" + headers = { + "Content-Type": "application/x-www-form-urlencoded" + } + data = { + "code": auth_code, + "grant_type": "authorization_code", + } + auth = HTTPBasicAuth(app_key, app_secret) + + response = requests.post(url, headers=headers, data=data, auth=auth) + + if response.status_code == 200: + tokens = response.json() + print("リフレッシュトークン:", tokens.get("refresh_token")) + return tokens.get("refresh_token") + else: + print("エラーが発生しました:", response.json()) + return None + +# App Key, App Secret, 認証コード(アクセスコード)を設定 +# APP_KEY = "YOUR_APP_KEY" +# APP_SECRET = "YOUR_APP_SECRET" +# AUTH_CODE = "YOUR_AUTH_CODE" +# https://www.dropbox.com/oauth2/authorize?client_id=np81qqat6atveal&token_access_type=offline&response_type=code + +APP_KEY = os.getenv('DROPBOX_APP_KEY') +APP_SECRET = os.getenv('DROPBOX_APP_SECRET') +AUTH_CODE = os.getenv('DROPBOX_AUTH_CODE') + +refresh_token = get_dropbox_refresh_token(APP_KEY, APP_SECRET, AUTH_CODE) \ No newline at end of file diff --git a/readme.md b/readme.md index 96d88ef..e48649c 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,13 @@ -# typora-img-uploader-r2 +# typora-img-uploader + +## Upload to R2 Upload images to R2 using Typora. +```bash +pip install python-dotenv boto3 +``` + ``` bash:.env .env @@ -12,7 +18,32 @@ R2_SECRET_ACCESS_KEY = 'securet access key' R2_CUSTOM_URL = 'https://custom.domain/' ``` -## Usage +### Usage ```python -upload.py --image-path +upload_r2.py --images-path +``` + +## Upload to DropBox +Upload images to Dropbox. + +``` bash +pip install dropbox python-dotenv +``` + +``` bash:.env +.env + +DROPBOX_APP_KEY=your_app_key +DROPBOX_APP_SECRET=your_app_secret +DROPBOX_REFRESH_TOKEN=your_refresh_token +``` + +Required permissions: +- files.content.write +- files.content.read +- sharing.write + +### Usage +```python +upload_dropbox.py --images-path ``` \ No newline at end of file diff --git a/upload_dropbox.py b/upload_dropbox.py new file mode 100755 index 0000000..95333ce --- /dev/null +++ b/upload_dropbox.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import os +import sys # sysモジュールを追加 +import argparse +from pathlib import Path +from typing import List +import mimetypes +from dotenv import load_dotenv +import dropbox +from dropbox.files import FileMetadata +from dropbox.exceptions import ApiError, AuthError +import uuid # 追加 + +def get_content_type(file_path: str) -> str: + """ファイルのContent-Typeを取得""" + content_type, _ = mimetypes.guess_type(file_path) + return content_type or 'application/octet-stream' + +def upload_to_dropbox(dbx: dropbox.Dropbox, file_path: str) -> str: + """ファイルをDropboxにアップロードし、共有リンクを返す""" + try: + # ファイル存在チェックを追加 + if not os.path.isfile(file_path): + print(f"Error: File not found - {file_path}") + return "" + + # オリジナルのファイル名から拡張子を取得 + original_name = os.path.basename(file_path) + _, ext = os.path.splitext(original_name) + + # UUID4を使用してランダムなファイル名を生成 + random_filename = f"{uuid.uuid4()}{ext.lower()}" # 拡張子を小文字に統一 + dropbox_path = f"/typora_img/{random_filename}" + + # ファイルをアップロード + try: + with open(file_path, 'rb') as f: + file_metadata: FileMetadata = dbx.files_upload( + f.read(), + dropbox_path, + mute=True # content_type引数を削除 + ) + except IOError as e: + print(f"Error reading file {file_path}: {str(e)}") + return "" + + # 共有リンクを作成 + try: + shared_link = dbx.sharing_create_shared_link_with_settings(dropbox_path) + return shared_link.url.replace('dl=0', 'raw=1') + except dropbox.exceptions.ApiError as e: + if e.error.is_shared_link_already_exists(): + # リンクが既に存在する場合は既存のリンクを取得 + shared_link = dbx.sharing_get_shared_links(dropbox_path) + return shared_link.links[0].url.replace('dl=0', 'raw=1') + raise + + except Exception as e: + print(f"Unexpected error uploading {file_path}: {str(e)}") + return "" + +def main(): + try: + # 環境変数の読み込み + load_dotenv() + + # Dropbox認証情報の取得と検証 + app_key = os.getenv('DROPBOX_APP_KEY') + app_secret = os.getenv('DROPBOX_APP_SECRET') + refresh_token = os.getenv('DROPBOX_REFRESH_TOKEN') + + # 認証情報の存在チェック + missing_vars = [] + if not app_key: + missing_vars.append('DROPBOX_APP_KEY') + if not app_secret: + missing_vars.append('DROPBOX_APP_SECRET') + if not refresh_token: + missing_vars.append('DROPBOX_REFRESH_TOKEN') + + if missing_vars: + raise ValueError(f"以下の環境変数が設定されていません: {', '.join(missing_vars)}") + + # Dropboxクライアントの初期化とリフレッシュトークンの検証 + try: + dbx = dropbox.Dropbox( + oauth2_refresh_token=refresh_token, + app_key=app_key, + app_secret=app_secret + ) + # 接続テスト + try: + dbx.users_get_current_account() + except AuthError: + raise ValueError("リフレッシュトークンが無効です。新しいトークンを取得してください。") + except Exception as e: + raise ValueError(f"Dropbox APIの呼び出しに失敗しました: {str(e)}") + + except Exception as e: + raise ValueError(f"Dropboxクライアントの初期化に失敗しました: {str(e)}") + + # コマンドライン引数の設定 + parser = argparse.ArgumentParser(description='Upload images to Dropbox') + parser.add_argument('--images-path', nargs='+', required=True, + help='Path to image files to upload') + args = parser.parse_args() + + # 各ファイルをアップロード + for image_path in args.images_path: + if os.path.exists(image_path): + shared_link = upload_to_dropbox(dbx, image_path) + if shared_link: + print(shared_link) + else: + print(f"File not found: {image_path}") + + except Exception as e: + print(f"Error: {str(e)}", file=sys.stderr) + sys.exit(1) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/upload.py b/upload_r2.py similarity index 97% rename from upload.py rename to upload_r2.py index 544dccc..233c371 100755 --- a/upload.py +++ b/upload_r2.py @@ -24,7 +24,7 @@ def validate_environment(): 'R2_CUSTOM_URL' ] - missing_vars = [var for var in required_vars if not os.getenv(var)] + missing_vars = [var for var in required_vars if not os.getqenv(var)] if missing_vars: raise ValueError(f"Missing required environment variables: {', '.join(missing_vars)}")