20022025b
This commit is contained in:
Executable
+40
@@ -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)
|
||||
@@ -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 <image path>
|
||||
upload_r2.py --images-path <image 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 <image path>
|
||||
```
|
||||
Executable
+124
@@ -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()
|
||||
@@ -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)}")
|
||||
|
||||
Reference in New Issue
Block a user