EnFinder FAQ と作者の愚痴

update 2024-11-16
Error RateLimitDuration とは何?
Evernote API 規制時のエラーメッセージです(単位時間あたりのリクエスト数っぽい)
このエラーに続く秒数の間 APIが制限されるとの事ですが、この値より早く解除されるなど基準(おそらく非公開)は不明です

通常はタスクバー左、認証時はダイアログで表示されます

ユーザー認証やユーザーの状態取得まで適用されるため、アプリ開発の大きな妨げになりました
開発者向けの Sandbox が存在した頃は、このような規制に遭うことがなかったため、最近厳しくなった可能性あり

サマリー表示で、サムネイルや本文テキストのプレビューを表示させている場合、規制により早く到達するため注意が必要です
(一度読み込んだらキャッシュは効きます)

※起動時に多くの情報を取得するため、起動終了を繰り返すのはオススメしません、タスクトレイに常駐させておくのが良いかと思われます

公式アプリのモッサリが、この規制に対応するためだったとしたら、スプーン曲げくらい凄い技術ですな 🥄
Evernote API の権限
APIの権限は認証画面の赤線の所

ver.0.1.4.3 で EnSetTime の機能(ノートの作成日時、更新日時 設定)を取り込みましたので、ノートの更新を利用するようになりました
その後追加された、ノートブックの移動やタグの変更なども同様
Evernote 無料プランでの利用
2024-08-06 から同期が1端末になった(それは同期というのか) 無料プラン

開発時に利用している無料アカウントは、今のところ Web と EnFinder で動作しています
端末数制限はサードパーティアプリに適用されないとどこかで見たよーな
(無料プランは、若干 API規制のしきい値が低いような気もしますが、気がする程度)

公式クライアントを利用しない(しなくなった)場合でもデータを端末に残しておくと、EnFinderはリソースファイルを流用できるはず
Shard, UserId, GUID は何ですか?
Shard(シャード): 元々はユーザーが収容されている物理サーバ(Google Cloud 移行前)、sで始まる
UserId: ユーザー番号(シャード毎ではなさそう)
GUID: ノートやノートブック等、あらゆるオブジェクトに付けられた一意の識別子

アプリ内で s00/xxxx みたいなのを見かけたら Shard/UserId の事です

コンテンツテーマ等を修正・追加した方は、アンインストール前にバックアップを取ってください 以前 A Digest of Evernote's Architecture | Evernote というブログ記事に詳細がありましたが、現在は無くなっています
1シャードに 100,000ユーザーくらい入れてるとか
検索/ノートブック からのノート表示件数について
ノートブック選択や検索した時のノート一覧取得順序は、トラフィックを抑えるため
最初に「リストの高さ分の個数」を取得します
次に「2回目以降リクエスト毎の検索ノート数」で設定された数を取得、これを「最大取得ノート数」を超えるまで繰り返します

したがって「最大取得ノート数」が 0 でも、リスト高さ分までは検索結果が表示されます(最もAPI消費の少ない検索)

ステータスバーに表示されるカウンタは、取得数/該当全数
ユーザーや被共有ノートをまたがった検索は、複数のリクエストが同時に発生します

※ver.0.1.4.3 から初回取得数を設定できるようになりました、初回取得数=0 の場合リスト高さ分 となります
検索結果(ノート一覧)のキャッシュ - 2024-11-16
検索結果のキャッシュは ver.0.1.4.7以降、ファイルに保存されるようになりました(それまではメモリ上に持っていたので、アプリ起動中のあいだ)

サーバ側のデータが更新基準は NoteStore.SyncState.updateCount(アカウントのノート等、変更ごとにインクリメントされる)で、 この値が更新されている場合、検索結果に変動が予想されるため、キャッシュは利用されず再取得します.
したがって Evernoteを定期的に更新している一般的なアカウントは、メモリ上のキャッシュと違いはほとんどありませんが、 Evernoteを更新しない書庫として利用しているアカウントにおいて、リクエスト数を減らせる可能性があります.

キャッシュは user-cache フォルダに作成され、古い updateCount の情報は定期的に削除、アプリ終了時にDBを最適化します
検索結果のコピー - 2024-11-16
[表示]-[検索結果のコピー] は、現在表示されている検索結果をクリップボードにコピーします ver.0.1.4.7以降

1行毎(CrLf)に Guid, 作成日, 更新日, タイトル, ノートブック, タグ の順にタブ区切り
表計算ソフトなどへ貼り付け可能です
検索結果の日時フォーマット - 2024-11-16
検索結果の日時フォーマットを言語ファイル(実行ファイルフォルダ)へ記載 ver.0.1.4.7以降

<DateTimeFormat> と <DateTimeSecFormat>(秒あり) セクション
システムやユーザーロケールの影響を受けるので、月の文字表記 mmm や mmmm は、言語設定に応じた月となるはずです(未確認)
和暦が使いたい方は、Gee や ggE 等も表示できるはず(未確認)

変更後、要アプリ再起動
ノート日時変更(ver.0.1.4.3以降)
ノート一覧等に反映するには「検索の更新」(F5)
被共有ノートブックは「キャッシュクリア + 検索の更新」(Ctrl + F5)

【注意】公式クライアントで開いたままのノートをEnFinderで日時変更した場合、公式クライアントが更新日時を上書きしてしまう場合があります
EnSetTime では被共有ノートブック内ノートの日時を変更できませんでしたが、EnFinderではできるようになってるハズ
タグに色は付けられますか?
表示-タグ色
アカウントごとにタグ色は変えられますか?
変えられません
タグ名に単純マッチです
プロファイルフォルダの tagcolor.json に保存されます
タグが階層化されません
ver.0.1.4.6で実装されました(忘れてました)
文字化けする pdf がある
フォント埋め込みが行われていない pdf ファイルで起こります
iframe でブラウザに pdf を表示させているため WebView2(Chromium) の影響を受けています
(何年も放置されている有名な症状)

pdf.js を使用すれば解決すると思いますが、ローカルではクロスオリジンの問題があるよーな

最近(2024-09-20頃)、Google Chrome で修正された様子
EnFinder が使用している webview2の元である、Microsoft Edge は解消されていないが Chromiumのアップデートで直るかも(他力本願)
ゴミ箱 が無い
ver.0.1.4.5 でゴミ箱が実装されました

ゴミ箱の並び替えは、新しく削除された順のみです.
また、ゴミ箱内の検索はできません(APIで検索文字を入れても弾かれてしまいました)
暗号化テキストの復号化
復号化には、チグサウェブ(千草)さんの javascript コードを利用(ほぼ丸写し)させて頂いております
https://chigusa-web.com/blog/evernote-decrypt/

暗号化テキストを含むノートは、javascript ライブラリをオンラインで取り込んでいます(base.js参照)
crypto-js と enfinder_decrypt.js
ポータブル版は?
当初ポータブルで作成しようとしましたが、Web認証→アプリへトークンを受け渡しにレジストリ登録(管理者権限)が必要な事や WebView2 キャッシュフォルダ等の残骸が残るため、インストーラでの提供となりました
そんな理由でポータブル提供は難しいかも
「検索の更新」と「キャッシュクリア+検索の更新」の違い
「検索の更新」は UpdateCount(Evernoteの更新カウンタ)が更新されているかをチェックして、更新されている場合は再取得、更新されていない場合はキャッシュ利用
「キャッシュクリア+検索の更新」は、キャッシュを削除して再取得

稀に違うノートブックのキャッシュが表示されるというバグが残っているような...
被共有ノートブックは、ノートブックの下にタグがあります
被共有ノートブックのノートは、持ち主のノートストアに存在していて、利用されているタグも持ち主のノートストアに存在します
そのため被共有ノートブックのタグはノートブック配下に存在するほうがデータ的に自然と思われるためです

自身のや他の被共有ノートブックに同名のタグが存在しても、タグ(のGUID)は別物になります
(公式では同じ名前のタグが複数並んでいた時期がありました)
検索履歴と検索ワード記録他
検索窓の ↑ ↓ キーで履歴・・・アプリ終了まで

Ctrl + 数字・・・shortcutWords.json に記録されます
・検索ワード登録: Ctrl + Shift + 数字(1~9 ※テンキー不可) ← 検索窓に文字を入力した状態で
・検索ワード呼出: Ctrl + 数字(1~9 ※テンキー不可)

検索窓のクリア(新規検索) Ctrl + Y
タブとウィンドウ表示
Ctrl + ノート選択 → 新規タブで開きます
ノート一覧のダブルクリック → ウィンドウ表示

一般的な
Ctrl + W で現在のタブを閉じる(最後の一つ以外)
Ctrl + Tab で次のタブ

タブ⇔ウィンドウ の切替は、タブ内のボタンからも
ショートカット(ツールバー) からノートを開く場合、基本的(既に開いていなければ)に新規タブとなります
同じノートを複数のタブやウィンドウでは、開けません(多分)
使用しているフォルダとレジストリ
フォルダ
%PROGRAMFILES%\EnFinder ←インストール先
%APPDATA%\Boltzsoft\EnFinder ←プロファイルとキャッシュ
%LOCALAPPDATA%\Boltzsoft\EnFinder ←WebView2生成物
※各フォルダへのアクセスは、メニューの ツール - フォルダ

レジストリ
HKEY_CLASSES_ROOT\boltzsoftenfinder ←Web認証後カスタムスキームで使用
ノートの構造
大まかに HTMLと似ていて
content(コンテンツ) という XMLで記述された本文と
0個以上の resource(リソース) という、画像などの添付で構成されていて、
それぞれに属性情報が付随します(タイトルやファイル名など)

content には resouce を呼び出す箇所に <en-media /> というタグが記述してあり、オプションの hash と type で resouce とひも付けを行っています
公式Evernoteクライアントアプリのリソースキャッシュ使用について
公式Evernoteクライアントのリソースキャッシュは、ノート毎のフォルダ
%APPDATA%\Evernote\resource-cache\User番号\ノートGUID\
にデータ本体のハッシュ(MD5)をファイル名として保存されています

EnFinderは、公式と似た構造の
%APPDATA%\Boltzsoft\EnFinder\content\resource-cache\User番号\ノートGUID\
へリソースキャッシュを保存します

EnFinderから、公式アプリのキャッシュファイルを利用する場合
公式キャッシュファイルのハードリンクを自身のキャッシュフォルダへ作成し、速度とストレージ消費を抑える仕組みを取っています
ハードリンクが利用できない場合(非NTFSや別ボリューム等)は、コピーを行います
キャッシュフォルダを変更したい
プロファイルフォルダにある EnFinder.ini へ下記の形式で記述(追記)すれば
次回起動時から切り替わるハズ(確認不足)

[System]
CacheDir=%APPDATA%\Boltzsoft\Enfinder\content

公式アプリのキャッシュフォルダと同一ボリュームのNTFSドライブを推奨(ハードリンクの関係で)
ノート表示の css/コンテンツテーマ を変更/作成したい
プロファイル - content 内の common.css を変更するか
※ common.css は全てのノート表示に影響します

プロファイル - theme 内に 好きな名前で css ファイルを作成して下さい
表示 - コンテンツテーマ から選択できます
アプリで選択されたコンテンツテーマ(index)とテーマ一覧は theme.js に保存され、各HTMLのjavascriptによって適用されます

common.css はアップデートインストール時に上書きされます
また、プロファイルフォルダはアンインストール時に削除されますので、いずれもバックアップを取っておいて下さい
プロファイル - content フォルダの中身
content-cacheコンテンツキャッシュ(dir)
resource-cacheリソースキャッシュ(dir)
user-cacheユーザー情報, 検索結果キャッシュ(dir)
themeコンテンツテーマ(dir)
common.css共通css
base.htmlコンテンツ表示 元ファイル
base.js↑ javascript
none.html無題(何も読み込んでないタブ)
none.js↑ javascript
tagcolor.jsタグ色の配列(今のところ未使用) ノート内にタグ色のバーを付けられたりする
theme.jsコンテンツテーマ一覧と選択Index
date.reg.txtノート日付設定時にOCR情報から取得する日付の正規表現
time.reg.txtノート時刻設定時にOCR情報から取得する時刻の正規表現
各 html から css や js を呼び出しているだけなので、決め打ちなのは html のファイル名のみです
tagcolor.js や theme.js はアプリ内の設定を javascriptから利用するためのものです
コンテンツキャッシュ(プロファイル - content - content-cache - User - Guid フォルダ)の中身
content.xmlコンテンツ表示 元ファイル
content.htmlコンテンツ表示HTML
note.jsノート情報
note.jsonノート情報(note.jsの元)
updateSequenceNum.txt更新番号
summary.txtサマリ キャッシュ
thumbnail75.bmpサムネイル キャッシュ
updateSequenceNum が更新されている. または base.html が content.html より新しい場合、content.html は再生成されます
後者の判定は ver.0.1.4.5 以降
テーマ(スタイル)について
「アプリテーマ」と「コンテンツテーマ」があり、前者はアプリ全体(作成不可)、後者はノート表示部のブラウザへ適用される css の事になります
ブラウザのダークモードを選択できるようにすべきですが部品の都合で、そちらは見送ってます

※テーマの動的切替とWebView2の相性が悪いらしく、テーマ切り替え後にノートが表示されなくなった場合は EnFinderを再起動してみてください
ノート表示とリソース(添付)
EnFinder はノート表示用の html 作成する際、Evernote の本文(<en-note>)をそのまま body へ投入します(元になるhtmlは、base.html)
同時に note.js というファイルを同じフォルダへ作成します
note.js にはリソース情報を含むノート情報(note.json)を配列へ展開したスクリプトが記述されていて、enfinder.js に記述されている javascript で 本文内の <en-media> の hash をキーに、htmlの各タグ(img等)へ変換しています

つまり、ノート表示部分は javascript により整形されているので、カスタマイズ可能という事です
今のところ、画像やpdf等しかインライン表示になっていません(秀作をお待ちしてます)
新規ノート追加とマークダウン
テキスト + 添付ファイル(ノート末尾に置かれます)
マークダウン + 添付ファイル(ノート末尾に置かれます)
での作成が行えます

マークダウンについて、詳しくないのでライブラリそのまま乗せてます
DaringFireballCommonMark の選択
マークダウンを使われるような方には不要かもしれませんが、プレビューを付けてます(自分の確認用?)

当初、ブラウザの contentitable を用いて本文作成を画策しましたが、添付の扱いや Evernote側で許可していないタグやオプションが多数あり、 あまりに面倒なので保留としてます
代わりにマークダウンを導入しましたが、残念ながら作者は詳しくない...
アンインストール時の注意
設定情報などを含む EnFinder のプロファイルフォルダ(%APPDATA%\Boltzsoft\EnFinder)が削除されるので
コンテンツテーマ等を修正・追加した方は、アンインストール前にバックアップを取ってください
タスクトレイからのアプリ終了文言が変
公式アプリのオマージュ
日本語以外の言語表記にしたい
実行ファイルの場所にある EnFinder.language (xml)を編集して下さい

ただし、日付が yyyy/mm/dd 形式なのは変わりません(要望があれば変更するかも)
※ ver.0.1.4.7 で日付形式を言語ファイルに出しました(<DateTimeFormat> と <DateTimeSecFormat>)
mmm や mmmm は、文字表記の月(ロケール設定による)になるハズ
高DPIでサムネイルが小さい
サムネイルサイズは 75px 固定です
150 や 75 等にしろとか https://dev.evernote.com/doc/articles/thumbnails.php
でも公式アプリ(ver.10)は 88px くらい
SVGイメージの表示
ver.0.1.4.0 でSVGイメージの表示できるようになりました
Chromium は、ローカルにある svgファイルの拡張子が .svg 以外だと type が無視されて表示されないらしい
(img, object, iframe, embed で type を指定しても表示されないのを確認)
APIの謎 - 幽霊リソース
コンテンツに <en-media として記載されているがリソースデータには存在しない、幽霊リソース
(Webクリップノートで散見され、元Webのイメージへ何らかの効果を使用している等で起きるっぽい)

これが存在すると、未取得のリソースとしてデータ本体を取得するも、結局ありませんでした~
という無駄が大量に発生してしまいます
ver.0.1.3.0 で幽霊数の比較を行い改善を試みていますが、完全には判断が付いていません
APIの謎 - resource-guid と hash の紐づけ
ノート取得APIは
・コンテンツのみ
・コンテンツ + リソース属性
・コンテンツ + リソース属性 + リソースデータ本体
・リソース属性 + リソースデータ本体
みたいな種類があるわけです

リソースデータ本体は、公式キャッシュに存在する可能性が高いため、
まずは軽量な「コンテンツ + リソース属性」を取得します

コンテンツのリソースタグは
<en-media hash="xxxxxx" type="image/png" /> みたいなの
ハッシュとタイプのみ ←Guidが無い

リソース属性は、
Guid, ファイル名, タイプ等 ←ハッシュが無い

つまり、コンテンツ内の <en-media> とリソース属性を一意につなぐキーが存在しません
(en-mediaタグの出現順序とリソース情報の順番は無関係なのを確認済み)

リソース本体の公式キャッシュが存在したとしても、同じタイプが複数存在する場合(webクリップには多数あったりする)
「リソース属性 + リソースデータ本体」を取得して、データ本体からハッシュを計算することで、やっと情報が繋がるワケです

「コンテンツの <en-media> に Guid を持たせる」or「リソース属性にハッシュを持たせる」のどちらかが必要かと...

ちなみにハッシュからリソース属性を一つづつ取得する API(getResourceByHash) が存在しますが、多数のリソースを含むWebクリップ等でこれを使うと、あっという間にリクエスト数制限にかかってしまいます
そのため、EnFinder では不明リソースが2を超える場合、不本意ながら「リソース属性 + リソースデータ本体」でリソース全てを取得しています

公式アプリキャッシュのリソース情報(hash.meta)の etag が updateSequenceNum と一致する事に気づき
ver.0.1.3.0 でリソース情報とデータの紐づけにより、リソースのリクエスト数を減らすことができました
APIの謎 - 同一ハッシュのリソース名消失
ひとつのノートに同じハッシュのデータを複数投入すると、ファイル名はそのうちの一つしか保存されない(重複排除の副作用)
ノートが違えば、データの違う同一ハッシュ(いわゆる衝突)をそれぞれ保存可能
作成動機
Evernote Legacy 終了と Evernote 10 への不満
行間広すぎ、ネイティブアプリのサクサク感が欲しい
配布や改変
配布など自由ですが、利用者が損害を被ったり利益を損なうような改変は禁止します
そのうえで、プロファイル内の html, js, css は自由に変更・配布して下さい
css, javascript に詳しい方、期待しております
EnFinder の今後について
EnSetTime 時代に作成していたクラスを流用する形で作成しましたが、作り込んでいくうちに根本的に変更したい箇所が多数あり
時間のなさと作者の疲弊で、Evernoteのサービス終了と新EnFinder完成のどちらが早いかわかりませんw
(相談役とかで雇って下さい)