AppleScript名:指定文字列ではじまる要素のみ抽出(大文字、小文字を問わず) |
— Created 2017-10-29 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set stringArray to current application’s NSArray’s arrayWithArray:{"adobe", "Apple", "microsoft", "google"} set thePred to current application’s NSPredicate’s predicateWithFormat:"self BEGINSWITH[cd] ’A’" set bList to (stringArray’s filteredArrayUsingPredicate:thePred) as list –> {"adobe", "Apple"} |
タグ: 10.13savvy
指定文字列ではじまる要素のみ抽出(ワイルドカード使用)
1Dリスト(1次元配列)に入っているデータを、Cocoaのオブジェクトに変換してワイルドカードで指定要素を抽出するAppleScriptです。
割と短く書けるので、幅広く使いたくなるところですが……処理速度がそれほど速くありません。これだと、AppleScriptのリスト(配列)型変数をループで条件判定して抽出したほうが速く処理できそうです。
データ件数が増えた場合にはAppleScriptネイティブの配列とCocoaの配列(NSArray)で速度比較して、Cocoaのオブジェクトを使って高速になる条件はどこかにあると思われますが、少なくとも要素数が5個ぐらいの「おかわいらしい」サイズの配列変数だとAppleScriptネイティブのオブジェクトを使って地道にループで判定したほうが高速です。
AppleScript名:指定文字列ではじまる要素のみ抽出(ワイルドカード使用) |
— Created 2017-10-29 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set stringArray to current application’s NSArray’s arrayWithArray:{"adobe", "Apple", "microsoft", "google"} set thePred to current application’s NSPredicate’s predicateWithFormat:"self LIKE ’Ap*’" set bList to (stringArray’s filteredArrayUsingPredicate:thePred) as list –> {"Apple"} |
AppleScript名:指定文字列ではじまる要素のみ抽出(ワイルドカード使用、レコード) |
— Created 2017-10-29 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aRecList to {{aName:"adobe", anID:1}, {aName:"Apple", anID:2}, {aName:"microsoft", anID:3}, {aName:"google", anID:4}} set stringArray to current application’s NSArray’s arrayWithArray:aRecList set thePred to current application’s NSPredicate’s predicateWithFormat:"aName LIKE ’Ap*’" set bList to (stringArray’s filteredArrayUsingPredicate:thePred) as list –> {{aName:"Apple", anID:2}} |
指定リストから、Regexpで要素を抽出
AppleScript名:指定リストから、Regexpで要素を抽出 |
— Created 2017-10-29 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set stringArray to current application’s NSArray’s arrayWithArray:{"adobe", "22", "microsoft", "99"} set thePred to current application’s NSPredicate’s predicateWithFormat:"self MATCHES ’\\\\d\\\\d’" set bList to (stringArray’s filteredArrayUsingPredicate:thePred) as list –> {"22", "99"} |
指定リストから、文字数で要素を抽出
AppleScript名:指定リストから、文字数で要素を抽出 |
— Created 2017-10-29 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set stringArray to current application’s NSArray’s arrayWithArray:{"adobe", "22", "microsoft", "99"} set thePred to current application’s NSPredicate’s predicateWithFormat:"self.length > 5" set bList to (stringArray’s filteredArrayUsingPredicate:thePred) as list –> {"microsoft"} |
配列を逆順に(OLD Style AS)
AppleScriptネイティブの配列変数であるlist型変数を逆順にするAppleScriptです。
配列(list)の要素数が5,000以下ぐらいだと普通に変数に保持して、このように逆順に変換して配列に代入するのが一番速いでしょう。
配列(list)の要素数が5,000以上ぐらいだとscriptオブジェクト内に格納したpropertyに保持して、このように逆順に変換してpropertyに代入するのが一番速いでしょう。
Cocoaの配列変数(NSArray、NSMutableArray)に格納して速度面での優位性が生まれてくるのは、要素数が1万とか数十万アイテムぐらいになった場合です。
Cocoa Scriptingで予想外にパフォーマンスが出ないケースというのは、たいてい配列処理で件数が少なすぎて逆効果だったという場合が多いので、ネイティブのAppleScriptのlist型変数の各種処理も重要です。
AppleScript名:配列を逆順に(OLD Style AS) |
— Created 2017-07-30 by Takaaki Naganoya — 2017 Piyomaru Software set aList to {1, 2, 3, 4, 5, 6} set revArray to reverse of aList –> {6, 5, 4, 3, 2, 1} |
複数キーによるソートテスト3.1(OLD Style AppleScript)
OLD Style AppleScriptによる2D Listの複数キーによるソートを行うAppleScriptです。
以前掲載したソートルーチンの速度比較で、2D ArrayのソートでOLD Style AppleScript版はSingle Keyのルーチンでしたが、本来であればこのMulti-Keyのルーチンで比較を行うべきでした。
ASOC版はMulti-Keyのソートルーチンなので、2.0 vs 0.3 secondsというところ。
AppleScript名:複数キーによるソートテスト3.1 |
–複数キーによるソートテスト3(複数キーを許容。キー数無制限) script orig property aList : {} end script –テストデータ作成 set aList of orig to {} repeat 10000 times –3次まですべてのキーを使ったソートが発生するよう、1次、2次キーは乱数範囲をわざと狭くしてある set the end of aList of orig to {"a", random number from 1 to 10, random number from 1 to 10, random number from 1 to 100} end repeat set sDat to current date –ソート時間計測(開始時刻) –item 2をPrimary key、item 3とitem 4をサブキーにして降順ソート set resList to multiKeySortDescending(aList of orig, {2, 3, 4}) of multiKeySort set eDat to current date –ソート時間計測(終了時刻) return (eDat – sDat) –複数キーによるソート script multiKeySort script spd property bList : {} –1次キーでソートした結果が入る property cList : {} –1次キーでソートした結果のうち、1次キーで同じ値が連続する範囲が入る {{1,3},{10,20}} property dList : {} –2次キーで再ソートする対象の一部のリストが入る(ワーク用) property eList : {} –2次キーで再ソートした結果のリストが入る(ワーク用) end script –複数キー(Primary, Secondary……)による降順ソート。キーは指定用のリストに入れる –falseが返ってきたらエラー on multiKeySortDescending(aList, keyList) –Initialize –set aList of spd to {} set bList of spd to {} –■■■■ ここからパラメータのチェック ■■■■ –型チェック set aLen to length of keyList if class of keyList is not equal to list then return false –キー値のリストがlistではなかった場合error end if –ソート対象の2D Listの要素数を取得 set tmpLen to length of first item of aList repeat with i in keyList if i > tmpLen then return false –キー値として指定した内容が、ソート対象のリストの要素数よりも大きかった場合error end if end repeat –キー指定内容で重複がないかチェック set dupList to detectDuplicates(keyList) of me if dupList is not equal to {} then return false –指定したキーで重複があったらerror end if –キー指定内容に0が入っていないかチェック if 0 is in keyList then return false –■■■■ パラメータのチェックここまで ■■■■ set firstKeyNo to first item of keyList –1次キーで2D Listをソート(降順) set bList of spd to shellSortListDescending(aList, firstKeyNo) of me –複数キーによるソート検証および実行ループ repeat with iii from 1 to aLen – 1 set cList of spd to {} set dList of spd to {} set eList of spd to {} –n次キーの値が連続する箇所を探す set curData to missing value set sucF to false –データ連続箇所検出中フラグ(false=非連続、true=連続中) set biginItem to 0 set endItem to 0 set itemC to 0 repeat with i in bList of spd set thisData to item (item iii of keyList) of i –n次キー –現在の値と前の値が等しい(連続箇所を検出した、あるいは連続箇所の中にいる) if curData = thisData then if sucF = false then set biginItem to itemC set sucF to true else if sucF = true then –連続箇所の検索継続中、何もしない end if else –現在の値と前の値が等しくない(連続していない、あるいは連続箇所の末尾を検出した) if sucF = true then set the end of cList of spd to {biginItem, itemC} set sucF to false end if set curData to thisData end if set itemC to itemC + 1 end repeat –n次キーの連続状態の検出中のままリスト末尾に来た場合には、最終データを出力する if sucF = true and curData = thisData then set the end of cList of spd to {biginItem, itemC} end if –n次キーによる重複箇所がない場合には、n次キーによるソート結果をそのまま返す if cList of spd = {} then return bList of spd end if –n+1次キーによる部分ソートし直し repeat with i in cList of spd set {tmpB, tmpE} to i copy items tmpB thru tmpE of (bList of spd) to (dList of spd) set (eList of spd) to shellSortListDescending((dList of spd), (item (iii + 1) of keyList)) of me set tmpCounter to 1 repeat with ii from tmpB to tmpE copy item tmpCounter of (eList of spd) to item ii of (bList of spd) set tmpCounter to tmpCounter + 1 end repeat end repeat end repeat return (bList of spd) end multiKeySortDescending –リスト中から重複項目をリストアップする on detectDuplicates(aList) set aCount to length of aList set duplicationList to {} repeat aCount times set anItem to contents of (first item of aList) set aList to rest of aList if anItem is in aList then set the end of duplicationList to anItem end if end repeat return duplicationList end detectDuplicates –シェルソートで入れ子のリストを降順ソート on shellSortListDescending(aSortList, aKeyItem) script oBj property list : aSortList end script set len to count oBj’s list’s items set gap to 1 repeat while (gap ≤ len) set gap to ((gap * 3) + 1) end repeat repeat while (gap > 0) set gap to (gap div 3) if (gap < len) then repeat with i from gap to (len – 1) set temp to oBj’s list’s item (i + 1) set j to i repeat while ((j ≥ gap) and (contents of item aKeyItem of (oBj’s list’s item (j – gap + 1)) < item aKeyItem of temp)) set oBj’s list’s item (j + 1) to oBj’s list’s item (j – gap + 1) set j to j – gap end repeat set oBj’s list’s item (j + 1) to temp end repeat end if end repeat return oBj’s list end shellSortListDescending end script |
NSPoint(座標)を作成する
AppleScript名:NSPoint(座標)を作成する |
— Created 2017-06-22 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aPoint to current application’s NSMakePoint(100, 100) –> {x:100.0, y:100.0} |
Crayon Pickerの色をKeynote上に赤、青、その他で判定して表にする
「クレヨンピッカー」の色を赤、青、その他で判定してKeynoteの表にプロットするAppleScriptです。
AppleScript名:Crayon Pickerの色をKeynote上に赤、青、その他で判定して表にする |
— Created 2018-02-27 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" property NSColor : a reference to current application’s NSColor –Crayon Picker Color Data set crayonPickerList to {{0, 0, 0}, {6425, 6425, 6425}, {13107, 13107, 13107}, {19532, 19532, 19532}, {26214, 26214, 26214}, {32639, 32639, 32639}, {32896, 32896, 32896}, {39321, 39321, 39321}, {46003, 46003, 46003}, {52428, 52428, 52428}, {59110, 59110, 59110}, {65535, 65535, 65535}, ¬ {32896, 0, 0}, {32896, 16448, 0}, {32896, 32896, 0}, {16448, 32896, 0}, {0, 32896, 0}, {0, 32896, 16448}, {0, 32896, 32896}, {0, 16448, 32896}, {0, 0, 32896}, {16448, 0, 32896}, {32896, 0, 32896}, {32896, 0, 16448}, ¬ {65535, 0, 0}, {65535, 32896, 0}, {65535, 65535, 0}, {32896, 65535, 0}, {0, 65535, 0}, {0, 65535, 32896}, {0, 65535, 65535}, {0, 32896, 65535}, {0, 0, 65535}, {32896, 0, 65535}, {65535, 0, 65535}, {65535, 0, 32896}, ¬ {65535, 26214, 26214}, {65535, 52428, 26214}, {65535, 65535, 26214}, {52428, 65535, 26214}, {26214, 65535, 26214}, {26214, 65535, 52428}, {26214, 65535, 65535}, {26214, 52428, 65535}, {26214, 26214, 65535}, {52428, 26214, 65535}, {65535, 26214, 65535}, {65535, 28527, 53199} ¬ } tell application "Keynote" activate set newDoc to make new document with properties {document theme:theme "ホワイト"} — theme name is *Localized*. This is "White" in Japanese tell window 1 –set {x1, y1, x2, y2} to bounds set bounds to {0, 0, 1500, 900} end tell tell newDoc set blankSlide to master slide "空白" –master slide name is *Localized*. This is "Blank" in Japanese tell slide 1 set base slide to blankSlide delete every table set tRes to make new table tell tRes set row count to 12 set column count to 8 set background color of every cell to {65535, 65535, 65535} set header column count to 0 set header row count to 0 set footer row count to 0 repeat with i from 0 to (length of crayonPickerList) – 1 set a1Num to (i mod 12) + 1 set b1Num to ((i div 12) + 1) * 2 – 1 set b2Num to b1Num + 1 set aCol to contents of item (i + 1) of crayonPickerList tell column b1Num tell cell a1Num ignoring application responses set background color to aCol end ignoring end tell end tell —————————————————————————————————– copy aCol to {rCol, gCol, bCol} set aColor to makeNSColorFromRGBAval(rCol, gCol, bCol, 65535, 65535) of me set cdnStr to retColorIsRedOrBlueFromNSColor(aColor) of me –red, blue, other —————————————————————————————————– if cdnStr = "red" then set textCol to {65535, 0, 0} else if cdnStr = "blue" then set textCol to {0, 0, 65535} else set textCol to {0, 0, 0} end if tell column b2Num tell cell a1Num ignoring application responses set value to cdnStr set text color to textCol end ignoring end tell end tell end repeat end tell end tell end tell end tell on retColorIsRedOrBlueFromNSColor(aColor) set aColDomain to retColorDomainNameFromNSColor(aColor) of me if aColDomain is in {"magenta", "purple", "orange", "red"} then return "red" else if aColDomain is in {"green", "cyan", "blue"} then return "blue" else return "other" end if end retColorIsRedOrBlueFromNSColor on retColorDomainNameFromNSColor(aCol) set hueVal to aCol’s hueComponent() set satVal to aCol’s saturationComponent() set brightVal to aCol’s brightnessComponent() if satVal ≤ 0.01 then set satVal to 0.0 set colName to "" if satVal = 0.0 then if brightVal ≤ 0.2 then set colName to "black" else if (brightVal > 0.95) then set colName to "white" else set colName to "gray" end if else if hueVal ≤ (15.0 / 360) or hueVal ≥ (330 / 360) then set colName to "red" else if hueVal ≤ (45.0 / 360) then set colName to "orange" else if hueVal < (70.0 / 360) then set colName to "yellow" else if hueVal < (150.0 / 360) then set colName to "green" else if hueVal < (190.0 / 360) then set colName to "cyan" else if (hueVal < 250.0 / 360.0) then set colName to "blue" else if (hueVal < 290.0 / 360.0) then set colName to "purple" else set colName to "magenta" end if end if return colName end retColorDomainNameFromNSColor on makeNSColorFromRGBAval(redValue as integer, greenValue as integer, blueValue as integer, alphaValue as integer, aMaxVal as integer) set aRedCocoa to (redValue / aMaxVal) as real set aGreenCocoa to (greenValue / aMaxVal) as real set aBlueCocoa to (blueValue / aMaxVal) as real set aAlphaCocoa to (alphaValue / aMaxVal) as real set aColor to NSColor’s colorWithCalibratedRed:aRedCocoa green:aGreenCocoa blue:aBlueCocoa alpha:aAlphaCocoa return aColor end makeNSColorFromRGBAval |
色が赤系統か青系統かを判定する
指定の色が赤系統か青系統かその他かを判定するAppleScriptです。
パラメータをRTFから取得するプログラムで、テキストを青、データベースから取得して差し込む値を赤、コメント類を黒などで記述するようにしてみたため、赤/青/その他を判定するプログラムを作成してみました。
AppleScript名:色が赤系統か青系統かを判定する |
— Created 2018-02-27 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" property NSColor : a reference to current application’s NSColor set {rCol, gCol, bCol} to choose color set aColor to makeNSColorFromRGBAval(rCol, gCol, bCol, 65535, 65535) of me –Detect the color is red or blue (or other) set cdnStr to retColorIsRedOrBlueFromNSColor(aColor) of me –> "red" / "blue" / "ohter" on retColorIsRedOrBlueFromNSColor(aColor) set aColDomain to retColorDomainNameFromNSColor(aColor) of me if aColDomain is in {"magenta", "purple", "orange", "red"} then return "red" else if aColDomain is in {"green", "cyan", "blue"} then return "blue" else return "other" end if end retColorIsRedOrBlueFromNSColor on retColorDomainNameFromNSColor(aCol) set hueVal to aCol’s hueComponent() set satVal to aCol’s saturationComponent() set brightVal to aCol’s brightnessComponent() if satVal ≤ 0.01 then set satVal to 0.0 set colName to "" if satVal = 0.0 then if brightVal ≤ 0.2 then set colName to "black" else if (brightVal > 0.95) then set colName to "white" else set colName to "gray" end if else if hueVal ≤ (15.0 / 360) or hueVal ≥ (330 / 360) then set colName to "red" else if hueVal ≤ (45.0 / 360) then set colName to "orange" else if hueVal < (70.0 / 360) then set colName to "yellow" else if hueVal < (150.0 / 360) then set colName to "green" else if hueVal < (190.0 / 360) then set colName to "cyan" else if (hueVal < 250.0 / 360.0) then set colName to "blue" else if (hueVal < 290.0 / 360.0) then set colName to "purple" else set colName to "magenta" end if end if return colName end retColorDomainNameFromNSColor on makeNSColorFromRGBAval(redValue as integer, greenValue as integer, blueValue as integer, alphaValue as integer, aMaxVal as integer) set aRedCocoa to (redValue / aMaxVal) as real set aGreenCocoa to (greenValue / aMaxVal) as real set aBlueCocoa to (blueValue / aMaxVal) as real set aAlphaCocoa to (alphaValue / aMaxVal) as real set aColor to NSColor’s colorWithCalibratedRed:aRedCocoa green:aGreenCocoa blue:aBlueCocoa alpha:aAlphaCocoa return aColor end makeNSColorFromRGBAval |
Terminalで指定コマンドのman pageを表示する
Terminal.appで指定コマンドのman pageを表示するAppleScriptです。
Terminal.appには
{appName:”Terminal”, appBundleID:”com.apple.Terminal”, urlScheme:{“telnet”, “ssh”, “x-man-page”}}
と、いろいろURL Schemeが定義されており、そのうちの1つ、x-man-pageのURL Shcemeを利用して表示させてみました。
AppleScript名:Terminalで指定コマンドのman pageを表示する |
set aCommandName to "ps" set aURL to "x-man-page://" & aCommandName open location aURL |
Finderの最前面のWindowで表示中のフォルダをTerminalでオープン
Finderの最前面のWindowで表示中のフォルダをTerminalでオープンするAppleScriptです。
AppleScript名:Finderの最前面のWindowで表示中のフォルダをTerminalでオープン |
tell application "Finder" set wCount to count every window if wCount = 0 then return tell front window set aTarg to target as alias end tell end tell set targPOSIX to quoted form of (POSIX path of aTarg) set aCom to "cd " & targPOSIX tell application "Terminal" set tCount to count (every window whose visible is true) if tCount = 0 then do script aCom else do script aCom in front window end if end tell |
ANSI Colorの色名称でTerminalの文字色を変更
ANSI Colorの名称一覧から名前をえらんで、Terminalの文字色を変更するAppleScriptです。
これにどの程度の意味があるのかさっぱり分からないのですが、ANSI Colorで文字色を指定する趣味の人もいるということで、世界の広さを感じます。
▲Select ANSI color name
▲Before
▲After
AppleScript名:ANSI Colorの色名称でTerminalの文字色を変更 |
— Created 2018-02-06 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" –Dark –set ansiColTable to {{colName:"Black", colVal:{0, 0, 0}}, {colName:"Red", colVal:{34166, 0, 712}}, {colName:"Green", colVal:{5182, 39392, 620}}, {colName:"Yellow", colVal:{34811, 35431, 1086}}, {colName:"Blue", colVal:{0, 0, 39429}}, {colName:"White", colVal:{49207, 49511, 49827}}, {colName:"Magenta", colVal:{41397, 0, 41833}}, {colName:"Cyan", colVal:{4997, 38685, 41818}}} –Light set ansiColTable to {{colName:"Black", colVal:{21352, 21356, 21351}}, {colName:"Red", colVal:{56616, 0, 1392}}, {colName:"Green", colVal:{7241, 55116, 1162}}, {colName:"Yellow", colVal:{57396, 58567, 2377}}, {colName:"Blue", colVal:{0, 0, 65416}}, {colName:"White", colVal:{49207, 49511, 49827}}, {colName:"Magenta", colVal:{56440, 0, 57441}}, {colName:"Cyan", colVal:{7416, 58001, 57206}}} set tmpColorList to filterAnAttribute(ansiColTable, "colName") of me set aTargColor to choose from list tmpColorList with prompt "choose ANSI color name" if aTargColor = {} or aTargColor = false then return set targColorName to contents of first item of aTargColor set aRes to filterListUsingPredicate(ansiColTable, "colName ==[c] %@", targColorName) if aRes = missing value then return set colList to colVal of aRes tell application "Terminal" set normal text color of window 1 to colList –set background color of window 1 to colList end tell on filterListUsingPredicate(aList as list, aPredicateStr as string, targStr as string) set setKey to current application’s NSMutableSet’s setWithArray:aList set aPredicate to current application’s NSPredicate’s predicateWithFormat_(aPredicateStr, targStr) set aRes to (setKey’s filteredSetUsingPredicate:aPredicate) return (aRes’s allObjects()) as list of string or string end filterListUsingPredicate on filterAnAttribute(aList as list, anAttr as string) set anArray to current application’s NSArray’s arrayWithArray:aList set valList to anArray’s valueForKeyPath:anAttr return valList as list of string or string –as anything end filterAnAttribute |
POST method REST API__Sendgrid_Send v1
メールの高速大量送信サービス「SendGrid」のREST API経由でメールの送信を行うAppleScriptです。
試用にあたっては、SendGridにサインアップして試用アカウントを取得してください。この試用アカウントで実運用を行わないことがアカウト取得の前提条件となっています(かなり念押しされました、、、)。
アクセストークンを取得したら、本リスト内のretAccessTokenハンドラ内にペーストしてください。本リストを掲載状態のままAccessTokenが伏字の状態で実行しても、メール送信は行えません。
気になるメールの転送速度ですが、本AppleScriptではだいたい1通あたり0.1秒程度です。Mail.app経由で一般的なプロバイダのメールサーバーを経由して送るよりは10倍程度高速ですが、APIの呼び方をチューニングすることで、さらにこの10倍ぐらいの高速送信は行えるようになります。
AppleScript名:POST method REST API__Sendgrid_Send v1 |
— Created 2017-05-23 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set a1Dat to current application’s NSDate’s timeIntervalSinceReferenceDate() repeat with i from 1 to 10 set aSubject to "ぴよまるさんからの新しいおしらせ" & i as string set aBody to "ぴよまるさんこんばんわ" & i as string set toAddress to "maro@piyocast.com" set fromAddress to "piyomarusoft@mac.com" set aRes to sendMailViaSendGrid(aSubject, aBody, toAddress, fromAddress) of me end repeat set b1Dat to current application’s NSDate’s timeIntervalSinceReferenceDate() set c1Dat to (b1Dat – a1Dat) as real return c1Dat on sendMailViaSendGrid(aSubject, aBody, toAddress, fromAddress) set accessToken to "Bearer " & retAccessToken() —Access Token set reqURLStr to "https://api.sendgrid.com/v3/mail/send" set aRec to {personalizations:{{|to|:{{email:toAddress}}, subject:aSubject}}, |from|:{email:fromAddress, |name|:"ぴよ まるお"}, content:{{type:"text/plain", value:aBody}}} set aRes to callRestPOSTAPIAndParseResults(reqURLStr, accessToken, aRec) of me set aRESTres to json of aRes set aRESCode to (responseCode of aRes) as integer return (aRESCode = 202) –リクエスト成立ならtrueが返る( ) end sendMailViaSendGrid –POST methodのREST APIを呼ぶ on callRestPOSTAPIAndParseResults(aURL, anAPIkey, aRec) set aRequest to current application’s NSMutableURLRequest’s requestWithURL:(current application’s |NSURL|’s URLWithString:aURL) aRequest’s setHTTPMethod:"POST" aRequest’s setCachePolicy:(current application’s NSURLRequestReloadIgnoringLocalCacheData) aRequest’s setHTTPShouldHandleCookies:false aRequest’s setTimeoutInterval:60 aRequest’s setValue:anAPIkey forHTTPHeaderField:"Authorization" aRequest’s setValue:"application/json" forHTTPHeaderField:"Content-Type" aRequest’s setValue:"gzip" forHTTPHeaderField:"Content-Encoding" set dataJson to current application’s NSJSONSerialization’s dataWithJSONObject:aRec options:0 |error|:(missing value) aRequest’s setHTTPBody:dataJson –CALL REST API set aRes to current application’s NSURLConnection’s sendSynchronousRequest:aRequest returningResponse:(reference) |error|:(missing value) –Parse Results set resList to aRes as list set bRes to contents of (first item of resList) set resStr to current application’s NSString’s alloc()’s initWithData:bRes encoding:(current application’s NSUTF8StringEncoding) set jsonString to current application’s NSString’s stringWithString:resStr set jsonData to jsonString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) set aJsonDict to current application’s NSJSONSerialization’s JSONObjectWithData:jsonData options:0 |error|:(missing value) –Get Response Code set dRes to contents of second item of resList set resCode to (dRes’s statusCode()) as integer –Get Response Header set resHeaders to (dRes’s allHeaderFields()) as record return {json:aJsonDict, responseCode:resCode, responseHeader:resHeaders} end callRestPOSTAPIAndParseResults on retAccessToken() return "XX.XxX_XXxxXXxxxxxxXxXXXx.xXXXxXXXxXXXxXXxXxxxXXXxXXxxxXXXXxxxXxXxXXx" end retAccessToken |
Mail.appで送信元を明示的に指定しつつメール送信
Mail.appで送信元の氏名および送信先の氏名を明示的に指定しつつメール送信を行うAppleScriptです。
Mail.appの操作Scriptはやればやるだけ課題が見えてくるので、ほどほどのところで止めています。メールアカウントについて、1つしかアカウントを登録していなければデフォルトのメールアカウントでを前提にメール送信すればいいはずですが、複数のアカウントを登録しているケースが多いので、アカウントを指定する処理を書いてみました。
メールの大量連続送信については、1990年代からずっとAppleScriptで行なっていますが、途中で知り合いが盛大にやらかした(短時間で大量のメール送信を行なってさまざまなプロバイダのメールサーバーをコケさせかけた)影響もあって、日本国内のネットワークでは単位時間内に所定の本数を超えるメール送信を行うと、プロバイダからすぐにメール送信のリレーを止められ、その後しばらくメール送信を行えなくなるのが「お約束」となっています。
# だいたい、1秒に1通以上(1分に60通以上)送信すると疑われます。
かくして、メールの大量一括送信をScriptで行う場合には、ある程度「待ち時間」を入れつつ送信するか、REST API経由でSendGridのサービスを呼び出してメーラー以外でメール送信を行うあたりが落とし所になっています。
AppleScript名:Mail.appで送信元を明示的に指定しつつメール送信 |
–本来、メールアカウントのnameがわかっていれば、わざわざリストから選択する必要はない tell application "Mail" set aList to name of every account set aaSel to choose from list aList if aaSel = {} or aaSel = false then return set aSel to first item of aaSel end tell log aSel set mRes to makeAMailWithSpecifiedAccount("メールのタイトルだよ100", "テストメールの本文だよ100", "送信者の名前だよ", "送付先氏名", "nobody@piyocast.com", aSel) of me on makeAMailWithSpecifiedAccount(theSubject, theBody, myName, yourName, yourAddress, myAccountName) tell application "Mail" –Account check set anAccount to account myAccountName set aProp to enabled of anAccount if aProp is not equal to true then return false –アカウントが有効でなかった場合はエラーに set eList to (email addresses of anAccount) if eList = {} then return false –アカウントにメールアドレスの登録がなかった場合はエラーに(ねんのため) set myEmail to first item of eList –Make Sender set theSender to myName & "<" & myEmail & ">" –Make Message & Send set newMessage to make new outgoing message with properties {sender:theSender, subject:theSubject, content:theBody & return & return, visible:false} tell newMessage set visible to false make new to recipient at end of to recipients with properties {name:yourName, address:yourAddress} –受取人の指定 send –メール送信 end tell end tell return true end makeAMailWithSpecifiedAccount |
選択中のメール本文のSHA3チェックサムを計算
Mail.appで選択中のメール本文のSHA3チェックサムを計算するAppleScriptです。
macOS VistaことmacOS 10.13。もう、10.13.xのバージョン中に状況が好転するような気配がまったくしないこのOS。2018年6月のWWDCで次の10.14を発表して「アップデート間隔を伸ばす」と言ったところで、同じCEO、同じスタッフ、同じ開発期間でまた2018年10月にリリースするとかいったら「同じことの繰り返し」になるのではないかと戦々恐々としています。
macOS 10.13のMail.appでメールの文字化けなどが報告されているため、実際に同じ文面のメールのチェックサムを10.12と10.13で比較するためにこのAppleScriptを書いてみました。
結果は、とくに文字化けもなく同じチェックサム値が得られたものの、OSごと勝手にクラッシュしてシャットダウンするとか、Mail.appのルールが着信したてのメールに効かない時があるとか、Finderが不安定だとか、日本語入力時に辞書の用例が表示されると選択した候補で変換候補を確定できないとか、日本語入力時に確定後も変換ウィンドウが消えないとか、いまだにけっこうムチャクチャなOSです。
AppleScript名:選択中のメール本文のSHA3チェックサムを計算 |
— Created 2017-02-25 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "SHA3Kit" –https://github.com/jaeggerr/NSString-SHA3 set aMailBody to getSelectedMailBody() of me if aMailBody = false then error "No Selection" set origData to (current application’s NSString’s stringWithString:aMailBody) set aHash1 to (origData’s sha3:256) as string –> "C69C8E08D1E6A8DA53C4E00D02D5DB5C2937722730CF63C1EC44E59B57A3B03F" on getSelectedMailBody() tell application "Mail" set aaSel to selection if aaSel = {} or aaSel = "" then return false set aSel to first item of aaSel set aCon to content of aSel return aCon end tell end getSelectedMailBody |
選択中のメール本文のHexダンプを取得
AppleScript名:選択中のメール本文のHexダンプを取得 |
— Created 2017-02-25 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aMailBody to getSelectedMailBody() of me if aMailBody = false then error "No Selection" set theNSString to current application’s NSString’s stringWithString:aMailBody set aList to hexDumpString(theNSString) of me return aList on getSelectedMailBody() tell application "Mail" set aaSel to selection if aaSel = {} or aaSel = "" then return false set aSel to first item of aaSel set aCon to content of aSel return aCon end tell end getSelectedMailBody on hexDumpString(theNSString) set theNSData to theNSString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) set theString to (theNSData’s |description|()’s uppercaseString()) –Remove "<" ">" characters in head and tail set tLength to (theString’s |length|()) – 2 set aRange to current application’s NSMakeRange(1, tLength) set theString2 to theString’s substringWithRange:aRange –Replace Space Characters set aString to current application’s NSString’s stringWithString:theString2 set bString to aString’s stringByReplacingOccurrencesOfString:" " withString:"" set aResList to splitString(bString, 2) –> {"E3", "81", "82", "E3", "81", "84", "E3", "81", "86", "E3", "81", "88", "E3", "81", "8A"} return aResList end hexDumpString –Split NSString in specified aNum characters on splitString(aText, aNum) set aStr to current application’s NSString’s stringWithString:aText if aStr’s |length|() ≤ aNum then return aText set anArray to current application’s NSMutableArray’s new() set mStr to current application’s NSMutableString’s stringWithString:aStr set aRange to current application’s NSMakeRange(0, aNum) repeat while (mStr’s |length|()) > 0 if (mStr’s |length|()) < aNum then anArray’s addObject:(current application’s NSString’s stringWithString:mStr) mStr’s deleteCharactersInRange:(current application’s NSMakeRange(0, mStr’s |length|())) else anArray’s addObject:(mStr’s substringWithRange:aRange) mStr’s deleteCharactersInRange:aRange end if end repeat return (current application’s NSArray’s arrayWithArray:anArray) as list end splitString |
SeleniumでWebサーバー接続のじっけん
AppleScript名:SeleniumでWebサーバー接続テストのじっけん |
— Created 2018-02-26 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "Selenium" –https://github.com/appium/selenium-objective-c set aCap to current application’s SECapabilities’s new() aCap’s setPlatform:"Mac" aCap’s setBrowserName:"Safari" aCap’s setVersion:"11.0.3" –set anIP to ((current application’s NSHost’s hostWithName:"www.apple.com")’s address()) as string set {errorF, aRes} to current application’s SERemoteWebDriver’s alloc()’s initWithServerAddress:"0.0.0.0" |port|:8080 desiredCapabilities:aCap requiredCapabilities:(missing value) |error|:(reference) if errorF = missing value then return aRes’s |description|() as list of string or string –> "Error Domain=NSURLErrorDomain Code=-1004 \"サーバに接続できませんでした。\" UserInfo={NSUnderlyingError=0x6000022459d0 {Error Domain=kCFErrorDomainCFNetwork Code=-1004 \"サーバに接続できませんでした。\" UserInfo={NSErrorFailingURLStringKey=http://0.0.0.0:8080/wd/hub/status, NSErrorFailingURLKey=http://0.0.0.0:8080/wd/hub/status, _kCFStreamErrorCodeKey=61, _kCFStreamErrorDomainKey=1, NSLocalizedDescription=サーバに接続できませんでした。}}, NSErrorFailingURLStringKey=http://0.0.0.0:8080/wd/hub/status, NSErrorFailingURLKey=http://0.0.0.0:8080/wd/hub/status, _kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=61, NSLocalizedDescription=サーバに接続できませんでした。}" end if |
Pages書類からPDF書き出し v2
AppleScript名:Pages書類からPDF書き出し v2 |
— Created 2017-03-28 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set tmpPath to (path to desktop) as string set aRes to exportPagesDocToPDF(tmpPath) –Pages書類からPDF書き出し on exportPagesDocToPDF(targFolderPath as string) tell application "Pages" set dCount to count every document if dCount = 0 then return false end if set aPath to file of document 1 end tell set curPath to (current application’s NSString’s stringWithString:(POSIX path of aPath))’s lastPathComponent()’s stringByDeletingPathExtension()’s stringByAppendingString:".pdf" set outPath to (targFolderPath & curPath) tell application "Pages" set anOpt to {class:export options, image quality:Best} export document 1 to file outPath as PDF with properties anOpt end tell end exportPagesDocToPDF |
Keynote書類からPDF書き出し v2
AppleScript名:Keynote書類からPDF書き出し v2 |
— Created 2017-01-21 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set tmpPath to (path to desktop) as string set aRes to exportKeynoteDocToPDF(tmpPath) –Keynote書類からPDF書き出し on exportKeynoteDocToPDF(targFolderPath as string) tell application "Keynote" set dCount to count every document if dCount = 0 then return false end if set aPath to file of document 1 end tell set curPath to (current application’s NSString’s stringWithString:(POSIX path of aPath))’s lastPathComponent()’s stringByDeletingPathExtension()’s stringByAppendingString:".pdf" set outPath to (targFolderPath & curPath) tell application "Keynote" set anOpt to {class:export options, export style:IndividualSlides, all stages:false, skipped slides:true, PDF image quality:Best} export document 1 to file outPath as PDF with properties anOpt end tell return (outPath as alias) end exportKeynoteDocToPDF |
Numbers書類からPDF書き出し v2
AppleScript名:Numbers書類からPDF書き出し v2 |
— Created 2017-03-28 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set tmpPath to (path to desktop) as string set aRes to exportNumbersDocToPDF(tmpPath) –Pages書類からPDF書き出し on exportNumbersDocToPDF(targFolderPath as string) tell application "Numbers" set dCount to count every document if dCount = 0 then return false end if set aPath to file of document 1 end tell set curPath to (current application’s NSString’s stringWithString:(POSIX path of aPath))’s lastPathComponent()’s stringByDeletingPathExtension()’s stringByAppendingString:".pdf" set outPath to (targFolderPath & curPath) tell application "Numbers" set anOpt to {class:export options, image quality:Best} export document 1 to file outPath as PDF with properties anOpt end tell end exportNumbersDocToPDF |