2012年3月3日土曜日

[AppleScript] Evernoteのノートを作成日でまとめてマージする

いい加減に記事タイトルの[AppleScript]いらないんじゃね?説。
AppleScript系の記事しか書いてないのになんで入れてるんだろう・・・

今回は久しぶりにEvernoteネタ。
スクリプト内で指定したノートブックから、作成日でまとめてノートをマージします。
「上限の100000ノート間近だけど手作業で減らすとか無理!」とか「使ってるWebサービスが1ノートずつログ送ってくる・・・」ってときを想定してます。
100000ノートの上限とか最近流行りましたし、大流行なiftttも1ノートずつ派ですね。
(僕は一時期iftttに4000ノートも増やされました。実は今回はそれ対策だったり。)

はじめて使った時はノートブック内のノート全てを作成日ごとにマージするので、ノートの多いノートブックだと結構時間かかると思います。
しかも動作中はEvernoteがアクティブになったり新規ウィンドウ開いたり、すっごく忙しそうに動きます。他の作業とかまずできません。
ていうかそもそも高速化とか最適化とか一切考えてないんで、Mac触らないときに実行してください。

変わりと言ってはなんですが、cronを使えば「毎週金曜日の夜中に実行」とかできます。
一度設定してしまえば永遠に放置でいい(はず)です。

ひとつだけ欠陥を抱えていて、マージし終わったらEvernoteを再起動します。
というのが、スクリプトが動いたあとEvernoteが劇的に重くなるので。
新規ノートの作成すらままなりません。しかも放置してても治らないという・・・
原因もよくわかんないしとりあえず再起動しとくか、という感じ。
特に困るということは無いと思いますが「そういう動作をするよ」ってことだけ注意してください。

ではこちらがスクリプト。コードはいつもどおり一番下。

Evernoteのノートを作成日ごとにマージ

あとがき


今回のスクリプト、ほとんど@s_z_k_3さんとこのコピペです。
多謝多謝でございますm(_ _)m
スズキさんのブログにあるスクリプトはどれもアイデア掻き立てられて楽しいので、Evernoteユーザーはぜひ。
s_z_k_3's Scripts in Tumblr.com
勝手にAppleScript師匠の一人と思ってます

コード読むだけでもかなり勉強になります。(理解するの大変だけど)
EvernoteのCPU占用率とか考えたことなかった。

あと、もうスクリプト書くときは当たり前に開いてる僕の中では完璧過ぎるリファレンスAS Hole(AppleScriptの穴)さん。
誇張なしでここ読まないとスクリプト書けません、いつもお世話になってますm(_ _)m
ちなみにこちらにはコード読んでも理解できないやつがゴロゴロあります。
理解できないとコピペすらできないから辛いですね。

ではでは下が今回のコード。
--Evernoteのノートを作成日ごとにまとめてマージする

--マージ対象のノートブック
--書式は配列 例;{"notebook1","notebook2","notebook3"}
set marge_notebook to {""}

--EvernoteのCPU占有率、裏で動いてるか見ています(同期中、マージ中など)
--1~100の数値で小さいほどシビア、使ってるMacのスペックと相談してください
set threshold to "10"

----------------------------

repeat with Abook in marge_notebook

--日本の今日と明日を取得
set createTZ_1 to -9
set createTZ_2 to -33
set createDate_1 to do shell script "TZ=JST" & createTZ_1 & " date +'%Y%m%d'"
set createDate_2 to do shell script "TZ=JST" & createTZ_2 & " date +'%Y%m%d'"

--ノートブック内の最終作成日を取得
set createList to createDateList(Abook)
set lastDate to minNum(createList) as string

--日付の書式を修正
set oldDelim to AppleScript's text item delimiters
set AppleScript's text item delimiters to "年"
set queryLastDate to text item 1 of lastDate
set lastDate to text item 2 of lastDate
set AppleScript's text item delimiters to "月"
if length of text item 1 of lastDate = 1 then
set demo to "0" & text item 1 of lastDate
else
set demo to text item 1 of lastDate
end if
set queryLastDate to queryLastDate & demo
set lastDate to text item 2 of lastDate
set AppleScript's text item delimiters to "日"
if length of text item 1 of lastDate = 1 then
set demo to "0" & text item 1 of lastDate
else
set demo to text item 1 of lastDate
end if
set queryLastDate to queryLastDate & demo
set AppleScript's text item delimiters to oldDelim

--検索してマージ
repeat until createDate_2 = queryLastDate
my waitEvernoteActivity(10, threshold)
set query to "notebook:" & Abook & " created:" & createDate_1 & " -created:" & createDate_2
tell application "Evernote"
find notes query
open collection window 2 with query string query
activate window 2
tell application "System Events" to keystroke "a" using {command down} --全選択
set a to selection
set b to length of a
if b > 1 then
tell application "System Events" to keystroke "m" using {command down, shift down} --マージ
end if
set createDate_1 to my backDate(createTZ_1)
set createTZ_1 to createTZ_1 + 24
set createDate_2 to my backDate(createTZ_2)
set createTZ_2 to createTZ_2 + 24
close window 1
end tell
end repeat
end repeat

--再起動
kill_aProc("Evernote") of me
tell application "Evernote" to activate


--aListの最小値を返す(比較できる書式であること)
on minNum(aList)
set min to text item 1 of aList
repeat with i from 2 to length of aList
if min > text item i of aList then
set min to text item i of aList
end if
end repeat
return min
end minNum

--aNotebook内ノートの作成日をリスト化
on createDateList(aNotebook)
tell application "Evernote"
set createDate to {}
set query to "notebook:" & aNotebook
open collection window 2 with query string query
activate window 2
delay 0.5
tell application "System Events" to keystroke "a" using {command down} --全選択
set noteList to selection
repeat with aNote in noteList
tell application "Evernote"
set end of createDate to creation date of aNote
end tell
end repeat
close window 1
end tell
return createDate
end createDateList

--日付を一日ずつ戻す
on backDate(TZnum)
set TZnum to TZnum + 24
return do shell script "TZ=JST" & TZnum & " date +'%Y%m%d'"
end backDate

on waitEvernoteActivity(intervalTime, threshold)
delay 1
repeat while my isEvernoteBusy(threshold)
delay intervalTime
end repeat
end waitEvernoteActivity

on isEvernoteBusy(threshold)
--EvernoteのCPU占有率を計る
--thresholdは0から100の間で50を目安に
--thresholdの値が低いほど判定がシビアになり、値が高いほど判定が緩くなる
set CPU to (paragraph 1 of (do shell script "ps aux|grep '[E]vernote.app/Contents/MacOS'|awk '{print $3;}'")) as number
if CPU > threshold then
log "busy"
return true
else
--Evernote.logを調べる
set aFilePath to POSIX path of ((path to application support from user domain as text) & "Evernote:logs:Evernote.log")
set pattern to do shell script "date '+^%F %T'"
try
do shell script "grep -c " & quoted form of pattern & space & quoted form of aFilePath
log "busy"
return true
on error
log "not busy"
return false
end try
end if
end isEvernoteBusy

--指定名称のプログラムを強制終了させる
on kill_aProc(aProcName)
tell application "System Events"
set procList to every process whose name contains aProcName
if procList is not equal to {} then
set aProc to contents of first item of procList
tell aProc
set anID to unix id
end tell
do shell script "kill -9 " & (anID as string)
end if
end tell
end kill_aProc

0 件のコメント:

コメントを投稿