# [メタ情報] # 識別子: 公開用スクリプトを生成する # システム名: <<公開用スクリプトを生成する>>再生URLの?v=を削除した。置き換え文字列にペア行を追加した。 # 技術種別: Misc # 機能名: pmedia/scripts_pubにあるtxtファイル、サブフォルダ、サブフォルダ内のtxtファイルのリスト表示 # 使用言語: AppleScript ShellScript # 状態: 実行用 # [/メタ情報] 要約:この workflow は、選択した *_exe.txt ファイルから公開用 *_pub.txt を生成する自動処理である。保存先は M1 側ボリュームに固定し、Dropbox へは直接書き込まない。メタ情報が無い場合は自動付与し、既存メタでは更新日時を除去、状態を「公開用」に変更する。本文から個人情報・キー・パス等を匿名化し、key_patterns.txt に基づく追加置換も行う。未置換の秘密候補を抽出して警告し、生成後は公開 URL とエンコード URL を表示・コピーする。付属のシェルスクリプトで生成物を Dropbox に rsync 同期する。 ★出力先は常に M1 側の共有ボリューム /aaaaa/xxxxxxxxm1/scripts_pub に固定 aaaaaはM2の場合はVolumes M1の場合はUsersと記述 公開用スクリプトを生成する.workflow on run {input, parameters} -- ===== 設定 ===== -- 公開用生成物の保存先(正):M1 側ボリュームに固定 -- ※ この workflow は Dropbox には書き込まない set FACTORY_SAVE_DIR to "/Volumes/xxxxxxxxm1/scripts_pub/" -- Xserver 側での公開パス: wp-content/pmedia/scripts_pub/ 以下に置く前提 set SITE_BASE to "https://xxxxxxxx.com/wp-content/pmedia/" -- ================ -- 保存先フォルダを必ず作成(ボリュームがマウントされていないとエラー) try do shell script "/bin/mkdir -p " & quoted form of FACTORY_SAVE_DIR on error errm display alert "保存先フォルダエラー" message ("保存先フォルダ " & FACTORY_SAVE_DIR & " を作成/利用できませんでした。" & return & return & "・M1 Mac 側のボリューム xxxxxxxxm1 がマウントされているか確認してください。" & return & return & "システムメッセージ: " & errm) return end try if input is {} then display alert "ファイル未選択" message "Finderで *_exe.txt を選んで実行してください。" return end if -- 保存先フォルダ(文字列パス)を設定 set outFolder to FACTORY_SAVE_DIR if outFolder does not end with "/" then set outFolder to outFolder & "/" set processed to 0 set urlBlocks to {} -- 完了時に表示・コピーする「直リンク+エンコードURL」「秘密候補」ブロック repeat with selAlias in input try set srcPath to POSIX path of selAlias set qsrc to quoted form of srcPath -- *_exe.txt(大小区別なし/末尾空白除去)で終わるか判定 set isExe to do shell script "/bin/echo " & qsrc & " | /usr/bin/tr -d '\\r' | /usr/bin/sed -E 's/[[:space:]]+$//' | /usr/bin/grep -Eiq '_exe\\.txt$' && echo YES || echo NO" if isExe is not "YES" then display notification "受け取った: " & srcPath with title "対象外(*_exe.txt 判定NG)" else -- 出力ファイル名:*_exe.txt → *_pub.txt(NFC 正規化) set baseName to do shell script "/usr/bin/basename " & qsrc set pubNameRaw to do shell script "/bin/echo " & quoted form of baseName & " | /usr/bin/sed -E 's/_exe\\.txt$/_pub\\.txt/I'" set pubName to do shell script "/usr/bin/python3 -c 'import sys,unicodedata;print(unicodedata.normalize(\"NFC\",sys.argv[1]))' " & quoted form of pubNameRaw set destPath to outFolder & pubName set qdst to quoted form of destPath -- 既存チェック → 上書き確認 set skipThisFile to false set fileExists to do shell script "[ -e " & qdst & " ] && echo YES || echo NO" if fileExists is "YES" then set msg to "公開先に同名のファイルが存在します:" & return & return & destPath & return & return & "上書き保存しますか?" set dlgRes to display dialog msg buttons {"キャンセル", "上書き保存"} default button 2 cancel button 1 with icon note if (button returned of dlgRes) is not "上書き保存" then set skipThisFile to true end if end if if skipThisFile then -- スキップ else -- 先頭が [メタ情報] かチェック set hasMeta to do shell script "head -1 " & qsrc & " | /usr/bin/grep -q '^# \\[メタ情報\\]' && echo YES || echo NO" if hasMeta is "NO" then -- 識別子 = ファイル名(.txt を除いたもの)/更新日時は書かない set ident to do shell script "/bin/echo " & quoted form of baseName & " | /usr/bin/sed -E 's/\\.txt$//I'" set metaHeader to "# [メタ情報]" & return & ¬ "# 識別子: " & ident & return & ¬ "# システム名: 未分類" & return & ¬ "# 技術種別: Misc" & return & ¬ "# 機能名: Misc" & return & ¬ "# 使用言語: []" & return & ¬ "# 状態: 実行用" & return & ¬ "# [/メタ情報]" & return & return set tmpMeta to do shell script "/usr/bin/mktemp -t metahead" do shell script "/usr/bin/printf %s " & quoted form of metaHeader & " > " & quoted form of tmpMeta -- 一時ファイルは /tmp に作成 set tmpWorkExe to do shell script "/usr/bin/mktemp -t exework" do shell script "/bin/cat " & quoted form of tmpMeta & " " & qsrc & " > " & quoted form of tmpWorkExe do shell script "/bin/mv " & quoted form of tmpWorkExe & " " & qsrc do shell script "/bin/rm -f " & quoted form of tmpMeta else -- 既存メタ内の「# 更新日時: …」行を削除 set tmpWorkExe2 to do shell script "/usr/bin/mktemp -t exework" do shell script "/usr/bin/awk 'BEGIN{inm=0} /^# \\[メタ情報\\]/{inm=1} inm && /^# *更新日時:/{next} {print} /^# \\[\\/メタ情報\\]/{inm=0}' " & qsrc & " > " & quoted form of tmpWorkExe2 do shell script "/bin/mv " & quoted form of tmpWorkExe2 & " " & qsrc end if -- 公開用メタ(状態=公開用 にし、更新日時は削除) set tmpMetaPub to do shell script "/usr/bin/mktemp -t metapub" do shell script "/usr/bin/awk 'BEGIN{inm=0} /^# \\[メタ情報\\]/{inm=1} inm{ if($0 ~ /^# 状態:/){print \"# 状態: 公開用\"} else if($0 ~ /^# *更新日時:/){next} else {print} } /^# \\[\\/メタ情報\\]/{print; exit}' " & qsrc & " > " & quoted form of tmpMetaPub -- 本文抽出(メタブロック以降) set tmpBody to do shell script "/usr/bin/mktemp -t bodyraw" do shell script "/usr/bin/sed '1,/^# \\[\\/メタ情報\\]$/d' " & qsrc & " > " & quoted form of tmpBody -- 本文サニタイズ(鍵・パス等の粗い匿名化) set tmpBodySan to do shell script "/usr/bin/mktemp -t bodysan" set sedRules to "/usr/bin/sed -E " & ¬ " -e 's#(https?://docs\\.google\\.com/(spreadsheets|document|presentation)/d/)[^/]+#\\1<あなたのGoogleID>#g' " & ¬ " -e 's#(https?://drive\\.google\\.com/file/d/)[^/]+#\\1<あなたのGoogleID>#g' " & ¬ " -e 's#([?&]rlkey=)[A-Za-z0-9_-]+#\\1<あなたのID>#g' " & ¬ " -e 's#(APP_KEY\\s*=\\s*[\"])[^\"]+([\"])#\\1<あなたのキー>\\2#g' " & ¬ " -e 's#(APP_SECRET\\s*=\\s*[\"])[^\"]+([\"])#\\1<あなたのキー>\\2#g' " & ¬ " -e 's#(REFRESH_TOKEN\\s*=\\s*[\"])[^\"]*([\"])#\\1<あなたのキー>\\2#g' " & ¬ " -e 's#\\b(API_KEY|TOKEN|XSERVER_EMBED_TOKEN)\\b\\s*=\\s*\\\"[^\\\"]*\\\"#\\1 = \"<あなたのキー>\"#g' " & ¬ " -e 's#(token=)[A-Za-z0-9]+#\\1<あなたのキー>#g' " & ¬ " -e 's#(/Users/)[^ \\t\\n\\r]+#<あなたのファイルパス>#g' " & ¬ " -e 's#(/Volumes/)[^ \\t\\n\\r]+#<あなたのファイルパス>#g' " & ¬ " -e 's#(/home/)[^ \\t\\n\\r]+#<あなたのファイルパス>#g' " & ¬ " -e 's#xxxxxxxx\\.com#xxxxxxxx.com#g' " & ¬ " -e 's#[iI][mM][aA][kK][aA][tT]#xxxxxxxx#g' " & ¬ " -e 's#([A-Za-z0-9_-]{20,})#<あなたのID>#g' " do shell script sedRules & quoted form of tmpBody & " > " & quoted form of tmpBodySan -- 公開用を書き出し(メタ + 本文) do shell script "/bin/cat " & quoted form of tmpMetaPub & " " & quoted form of tmpBodySan & " > " & qdst & " && /bin/rm -f " & quoted form of tmpMetaPub & " " & quoted form of tmpBody & " " & quoted form of tmpBodySan -- 最終スクラブ(全体もう一度) set tmpWorkPub1 to do shell script "/usr/bin/mktemp -t pubwork" do shell script "/usr/bin/sed -E 's#xxxxxxxx\\.com#xxxxxxxx.com#g; s#[iI][mM][aA][kK][aA][tT]#xxxxxxxx#g' " & qdst & " > " & quoted form of tmpWorkPub1 do shell script "/bin/mv " & quoted form of tmpWorkPub1 & " " & qdst -- ★★ key_patterns.txt に基づく秘密キー置換 set pubDir to do shell script "dirname " & qdst set keyFile to pubDir & "/key_patterns.txt" set keyFileExists to do shell script "[ -f " & quoted form of keyFile & " ] && echo YES || echo NO" if keyFileExists is "YES" then -- 1) キー名(= "..." / = '...' を に)※「,」を含む行は除外 set rawKeys to do shell script "/usr/bin/grep -a -E '^[[:space:]]*[^#[:space:]][^#]*$' " & quoted form of keyFile & " | /usr/bin/grep -a -v ',' | /usr/bin/sed -E 's/[[:space:]]+#.*$//; s/^[[:space:]]+//; s/[[:space:]]+$//'" if rawKeys is not "" then set keyList to paragraphs of rawKeys repeat with k in keyList set keyName to contents of k if keyName is not "" then set escName to do shell script "/usr/bin/python3 -c " & quoted form of "import sys,re;print(re.escape(sys.argv[1]))" & " " & quoted form of keyName set sedExpr to "s#[[:<:]]" & escName & "[[:>:]][[:space:]]*=[[:space:]]*[\\\"\\'][^\\\"\\']*[\\\"\\']#" & keyName & " = \\\"<" & keyName & ">\\\"#g" set tmpWorkPub2 to do shell script "/usr/bin/mktemp -t pubwork" do shell script "/usr/bin/sed -E -e " & quoted form of sedExpr & " " & qdst & " > " & quoted form of tmpWorkPub2 do shell script "/bin/mv " & quoted form of tmpWorkPub2 & " " & qdst end if end repeat end if -- 2) ペア行(元,置換後)での全体置換 set pairsTSV to do shell script "/usr/bin/awk 'BEGIN{FS=\",\"; OFS=\"\\t\"} /^[[:space:]]*($|#)/{next} {orig=$1; sub(/^[[:space:]]+/,\"\",orig); sub(/[[:space:]]+$/,\"\",orig); repl=$0; sub(/^[^,]*,/,\"\",repl); sub(/^[[:space:]]+/,\"\",repl); sub(/[[:space:]]+$/,\"\",repl); if(orig!=\"\" && repl!=\"\"){print orig, repl}}' " & quoted form of keyFile if pairsTSV is not "" then set pairLines to paragraphs of pairsTSV repeat with lineText in pairLines set t to contents of lineText set tidx to offset of tab in t if tidx > 0 then set origVal to text 1 thru (tidx - 1) of t set replVal to text (tidx + 1) thru -1 of t set tmpWorkPub3 to do shell script "/usr/bin/mktemp -t pubwork" do shell script "/usr/bin/perl -0777 -pe 'BEGIN{$o=shift;$r=shift;} s/\\Q$o\\E/$r/g' -- " & quoted form of origVal & " " & quoted form of replVal & " " & qdst & " > " & quoted form of tmpWorkPub3 do shell script "/bin/mv " & quoted form of tmpWorkPub3 & " " & qdst end if end repeat end if end if -- ★★ 追加ここまで ★★ -- ★★ 疑わしい秘密候補をピックアップ(キー名は除外) set excludeFilter to "" if keyFileExists is "YES" then set excludeFilter to " | /usr/bin/grep -a -v -F -f " & quoted form of keyFile end if set suspectCmd to "/bin/cat " & qdst & " | " & ¬ "/usr/bin/grep -a -E -o '([A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,})|([A-Fa-f0-9]{32,})|([A-Za-z0-9+/]{32,}={0,2})|([A-Za-z0-9_-]{24,})' | " & ¬ "/usr/bin/grep -a -v '<[^>]+>'" & excludeFilter & " | " & ¬ "/usr/bin/sed -E 's/^/・/;' | /usr/bin/sort -u | /usr/bin/head -n 50" set suspects to do shell script suspectCmd if suspects is not "" then set blockSus to "秘密候補(未置換の可能性がある文字列・最大50件):" & return & suspects & return & "※必要に応じて key_patterns.txt にキー名またはペア行を追加し、再出力してください。" copy blockSus to end of urlBlocks end if -- URL 用の相対パス(Xserver 側) set relPathNFC to "scripts_pub/" & pubName -- NFC 正規化した文字列をパス区切りごとに URL エンコード set pyEnc to "from urllib.parse import quote; import sys,unicodedata as u; p=sys.argv[1]; print('/'.join(quote(u.normalize(\"NFC\", s)) for s in p.split('/')))" set encRel to do shell script "/usr/bin/python3 -c " & quoted form of pyEnc & " " & quoted form of relPathNFC set urlPlain to SITE_BASE & relPathNFC set urlEncoded to SITE_BASE & encRel set blockText to "直リンク: " & urlPlain & return & "エンコードURL: " & urlEncoded copy blockText to end of urlBlocks set processed to processed + 1 end if end if on error errm display notification errm with title "公開用生成エラー" end try end repeat -- 完了メッセージ(URL+秘密候補を表示&クリップボードへ) if processed > 0 then if (count of urlBlocks) > 0 then set AppleScript's text item delimiters to return & return set urlText to urlBlocks as text set AppleScript's text item delimiters to "" set the clipboard to urlText display dialog ("完了:" & processed & " 件更新" & return & return & urlText) buttons {"OK"} default button "OK" with icon note else display dialog ("完了:" & processed & " 件更新") buttons {"OK"} default button "OK" with icon note end if else display alert "対象なし" message "選択の中に *_exe.txt が見つかりませんでした。" end if end run /Users/xxxxxxxxm1/scripts/sync_scripts_pub_to_dropbox.sh #!/bin/bash set -x export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" if [ -x /opt/homebrew/bin/rsync ]; then RSYNC="/opt/homebrew/bin/rsync" else RSYNC="/usr/bin/rsync" fi SRC="/Users/xxxxxxxxm1/scripts_pub" DST="/Volumes/NO3_SSD/Dropbox/dropbox_1/pmedia/scripts_pub" mkdir -p "$DST" sleep 8 "$RSYNC" -av --delete --iconv=utf-8,utf-8-mac "$SRC/" "$DST/" exit 0