# [メタ情報] # 識別子: マイライブラリ_dropboxAPI_Mac_GASデータ交換_exe # システム名: マイライブラリ_dropboxAPI_Mac_GASデータ交換 # 技術種別: Misc # 機能名: Misc # 使用言語: Python # 状態: 公開用 # [/メタ情報] # [/メタ情報] 要約:DropboxのOAuth認証設定、リンク自動取得、GASとの通信を行う3本のPythonスクリプト群。 ①dropbox_auth_setup.pyはローカルHTTPサーバで認証コードを受け取り、Dropboxのアクセストークンとリフレッシュトークンを取得する。 ②get_dropbox_link.pyはリフレッシュトークンを用いてDropbox APIに接続し、指定ローカルファイルの共有リンクを取得または生成し、dl=0をraw=1に変換して出力する。 ③send_request.pyはAppleScriptから受け取ったDropboxリンクやファイル情報をGASのエンドポイントへJSON形式で送信し、更新処理を実行する。 M2Mac ▫️DropboxのAPIからトークン取得 Python <任意のフォルダパス>/dropbox_auth_setup.py dropbox_auth_setup.py ``` import os import webbrowser import http.server import socketserver import urllib.parse import requests from dotenv import load_dotenv # .envファイルのロード env_path = "<任意のフォルダパス>" load_dotenv(env_path) APP_KEY = os.environ.get("APP_KEY") APP_SECRET = os.environ.get("APP_SECRET") REDIRECT_URI = "http://localhost:8080" AUTH_URL = "https://www.dropbox.com/oauth2/authorize" TOKEN_URL = "https://api.dropboxapi.com/oauth2/token" # 📡 Step 1: 認証コードを取得する params = { "response_type": "code", "client_id": APP_KEY, "redirect_uri": REDIRECT_URI, "token_access_type": "offline" } url = f"{AUTH_URL}?{urllib.parse.urlencode(params)}" print("🌐 ブラウザで認証を開始します...") webbrowser.open(url) # 🔁 Step 2: ローカルでcodeを受け取る class OAuthHandler(http.server.SimpleHTTPRequestHandler): def do_GET(self): query = urllib.parse.urlparse(self.path).query code = urllib.parse.parse_qs(query).get("code", [None])[0] self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write("

認証完了。ターミナルに戻ってください。

".encode("utf-8")) self.server.auth_code = code with socketserver.TCPServer(("localhost", 8080), OAuthHandler) as httpd: httpd.handle_request() code = httpd.auth_code # 🎫 Step 3: アクセストークン+リフレッシュトークン取得 print("🔐 トークンを取得しています...") res = requests.post(TOKEN_URL, data={ "code": code, "grant_type": "authorization_code", "client_id": APP_KEY, "client_secret": APP_SECRET, "redirect_uri": REDIRECT_URI }) if res.status_code != 200: print("❌ 認証に失敗しました:", res.text) exit(1) tokens = res.json() print("✅ ACCESS_TOKEN:", tokens["access_token"]) print("🔄 REFRESH_TOKEN:", tokens["refresh_token"]) ``` get_dropbox_link.py <任意のフォルダパス>/get_dropbox_link.py <任意のフォルダパス>/get_dropbox_link.py ◆M2 Mac M1 Mac共用 ``` # get_dropbox_link.py — リフレッシュトークン対応版 import sys import os import json import re import dropbox from dotenv import load_dotenv # .envファイルのロード env_path = "<任意のフォルダパス>" load_dotenv(env_path) # ✅ あなたのDropboxアプリ情報をここに記入 APP_KEY = os.environ.get("APP_KEY") APP_SECRET = os.environ.get("APP_SECRET") REFRESH_TOKEN = os.environ.get("REFRESH_TOKEN") # 🔁 Dropboxオブジェクトを取得(リフレッシュ対応) def get_dbx(): return dropbox.Dropbox( oauth2_refresh_token=<個別のトークン文字列>, app_key=APP_KEY, app_secret=APP_SECRET ) # 🔧 Dropbox内の相対パスを取得 def get_dropbox_path(local_path): possible_roots = [ "<任意のフォルダパス>", "/Volumes/NO3_SSD/Dropbox/dropbox_1" ] for root in possible_roots: if local_path.startswith(root): relative_path = local_path[len(root):] return "/dropbox_1" + relative_path print(f"ERROR: ファイルがDropboxフォルダ内にありません\nlocal_path: {local_path}", file=sys.stderr) sys.exit(1) # 🔗 共有リンクを取得または作成 def get_shared_link(dbx, dbx_path): try: links = dbx.sharing_list_shared_links(path=dbx_path, direct_only=True).links if links: return convert_to_raw_url(links[0].url) except Exception: pass # なければ新規作成 try: link = dbx.sharing_create_shared_link_with_settings(dbx_path) return convert_to_raw_url(link.url) except Exception as e: print("❌ Dropbox APIで共有リンクを作成できませんでした:", file=sys.stderr) print(e, file=sys.stderr) sys.exit(1) # 🔄 dl=0 → raw=1 変換 def convert_to_raw_url(url): return re.sub(r'dl=0', 'raw=1', url) # 🏁 実行エントリポイント if __name__ == "__main__": if len(sys.argv) < 2: print("Usage: get_dropbox_link.py ", file=sys.stderr) sys.exit(1) local_path = sys.argv[1] dbx_path = get_dropbox_path(local_path) print(f"📂 Dropbox API 送信パス = {dbx_path}", file=sys.stderr) dbx = get_dbx() link = get_shared_link(dbx, dbx_path) print(link) ``` ▫️macとspreadsheetのデータ交換 Python send_request.py <任意のフォルダパス>/send_request.py <任意のフォルダパス>/send_request.py ◆M1 Mac、M2 Mac共通 ``` import sys import os import json import requests from dotenv import load_dotenv # .envファイルのロード env_path = "<任意のフォルダパス>" load_dotenv(env_path) # Google Apps Script API エンドポイント GAS_URL = os.environ.get("GAS_URL") # 🔍 受け取った引数を確認 print("📥 受信引数:", sys.argv) # コマンドライン引数を取得 if len(sys.argv) < 5: print("❌ 引数が不足しています") sys.exit(1) dropbox_link, file_path, file_name, extn = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4] # 🔍 受け取ったデータをログに記録 print("📥 受信データ from AppleScript:") print(f" dropboxLink: {dropbox_link}") print(f" filePath: {file_path}") print(f" fileName: {file_name}") print(f" extn: {extn}") # 送信データ data = { "dropboxLink": dropbox_link, "filePath": file_path, "fileName": file_name, "updateFlag": "ADD" } # 🔍 送信データを確認 print("📤 送信データ:", json.dumps(data, indent=2, ensure_ascii=False)) # GAS にデータを送信 try: response = requests.post(GAS_URL, json=data) response.raise_for_status() gas_response = response.json() print("📥 GAS レスポンス:", json.dumps(gas_response, indent=2, ensure_ascii=False)) if gas_response.get("status") == "success": print("✅ GAS にデータが正常に送信されました!") print("success") else: print(f"❌ GAS でエラー発生: {gas_response.get('message')}") print("error") except requests.exceptions.RequestException as e: print(f"❌ GAS 送信エラー: {e}") print("error") ```