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.
|
Upload images to R2 using Typora.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install python-dotenv boto3
|
||||||
|
```
|
||||||
|
|
||||||
``` bash:.env
|
``` bash:.env
|
||||||
.env
|
.env
|
||||||
|
|
||||||
@@ -12,7 +18,32 @@ R2_SECRET_ACCESS_KEY = 'securet access key'
|
|||||||
R2_CUSTOM_URL = 'https://custom.domain/'
|
R2_CUSTOM_URL = 'https://custom.domain/'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
### Usage
|
||||||
```python
|
```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'
|
'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:
|
if missing_vars:
|
||||||
raise ValueError(f"Missing required environment variables: {', '.join(missing_vars)}")
|
raise ValueError(f"Missing required environment variables: {', '.join(missing_vars)}")
|
||||||
|
|
||||||
Reference in New Issue
Block a user