首页龙虾技能列表 › libby-book-monitor — 技能工具

📚 libby-book-monitor — 技能工具

v1.0.0

[自动翻译] Track book availability on Libby/OverDrive libraries. Search library catalogues, manage a watchlist, and get notified when books are added. Use for "l...

0· 457·0 当前·0 累计
by @alexpolonsky·MIT-0
下载技能包
License
MIT-0
最后更新
2026/2/26
安全扫描
VirusTotal
无害
查看报告
OpenClaw
安全
high confidence
The skill's code, instructions, and resource requests are consistent with a simple Libby/OverDrive catalog watcher: it only needs python3, talks to the OverDrive Thunder API, and stores data under the user's home directory.
评估建议
This skill appears coherent and implements exactly what it claims: a local CLI that queries the OverDrive Thunder API and stores watchlists under ~/.libby-book-monitor. Before installing, review the config and data directory (it will create ~/.libby-book-monitor/config.json on first run). Remember this is unofficial tooling — the Thunder API search results may not reflect real-time borrowability and the tool does not perform any borrowing or hold actions. If you plan to run it regularly (cron/au...
详细分析 ▾
用途与能力
Name/description match the included code and instructions. The script implements searching, a watchlist, and periodic checks against the OverDrive Thunder API. Required binaries (python3) and config paths (~/.libby-book-monitor) are proportionate to the stated purpose.
指令范围
SKILL.md instructs running the included Python CLI with arguments, storing data under the user's data dir, and optionally using an env var (LIBBY_BOOK_MONITOR_DATA) to override the path. The runtime instructions do not ask the agent to read unrelated files, harvest credentials, or contact unexpected endpoints; network calls are limited to the documented thunder.api.overdrive.com API.
安装机制
No install spec is provided (instruction-only skill). The package includes a single Python script that uses only the stdlib. No downloads from arbitrary URLs or package installs occur during install.
凭证需求
No required environment variables or credentials are declared. The script optionally respects LIBBY_BOOK_MONITOR_DATA to change the data directory; no secrets or unrelated credentials are requested or accessed.
持久化与权限
Skill is not always-enabled and does not request system-wide changes. It stores its own per-user configuration and watchlist under ~/.libby-book-monitor (or an overridden path), which is expected for this CLI utility. It does not modify other skills or agent-wide settings.
安全有层次,运行前请审查代码。

License

MIT-0

可自由使用、修改和再分发,无需署名。

运行时依赖

🖥️ OSmacOS · Linux

版本

latestv1.0.02026/2/21

Initial ClawHub release

● 无害

安装命令 点击复制

官方npx clawhub@latest install libby-book-monitor
镜像加速npx clawhub@latest install libby-book-monitor --registry https://cn.clawhub-mirror.com

技能文档

Track book availability on Libby/OverDrive libraries. Search catalogues, manage a watchlist, and get notified when books are added to your library's collection.

Disclaimer: This is an unofficial tool, not affiliated with or endorsed by OverDrive/Libby. Catalogue data queries APIs that power the website and may not reflect actual availability. This tool does NOT borrow books or place holds. Provided "as is" without warranty of any kind.

Quick Start

# Search a library catalogue
python3 {baseDir}/scripts/libby-book-monitor.py search telaviv "Project Hail Mary"

# Add a book to your watchlist python3 {baseDir}/scripts/libby-book-monitor.py watch "Kafka on the Shore" --author "Haruki Murakami"

# Check your watchlist against the API python3 {baseDir}/scripts/libby-book-monitor.py check

# Show your watchlist python3 {baseDir}/scripts/libby-book-monitor.py list

Commands

CommandDescription
search Search a library catalogue by title/author
watch </code></td><td>Add a book to the watchlist</td></tr><tr><td><code>unwatch <title></code></td><td>Remove a book from the watchlist</td></tr><tr><td><code>list</code></td><td>Show the watchlist with status</td></tr><tr><td><code>check</code></td><td>Check all watchlist books against the API</td></tr></tbody></table> <h2>Options</h2><table><thead><tr><th>Option</th><th>Commands</th><th>Description</th></tr></thead><tbody><tr><td><code>--profile <name></code></td><td>all</td><td>Separate watchlist per user</td></tr><tr><td><code>--author <name></code></td><td>watch</td><td>Specify book author</td></tr><tr><td><code>--library <code></code></td><td>watch</td><td>Library code (default: from config)</td></tr><tr><td><code>--notify</code></td><td>check</td><td>Only print newly found books (for cron)</td></tr><tr><td><code>--data-dir <path></code></td><td>all</td><td>Custom data directory</td></tr></tbody></table> <h2>Profiles</h2><p>Use <code>--profile</code> to maintain separate watchlists for different people:</p><pre><code>python3 {baseDir}/scripts/libby-book-monitor.py --profile jane watch "Dune" python3 {baseDir}/scripts/libby-book-monitor.py --profile bob check --notify </code></pre><h2>Configuration</h2><p>Default library is <code>telaviv</code> Israel Digital. Edit <code>~/.libby-book-monitor/config.json</code> to change:</p><pre><code>{ "default_library": "nypl", "libraries": { "nypl": "New York Public Library" } } </code></pre><p>The library code is the subdomain from your library's OverDrive site (e.g., <code>nypl.overdrive.com</code> -> <code>nypl</code>).</p><h2>Cron Integration</h2><p>Run a daily check that only outputs when books are newly found:</p><pre><code>python3 {baseDir}/scripts/libby-book-monitor.py --profile jane check --notify </code></pre><p>If any new books are found, send the results to the user.</p><h2>Notes</h2><ul><li>Works with non-Latin scripts (Hebrew, Arabic, CJK, etc.)</li> <li>Books are considered "found" when <code>isOwned: true</code> in the API response</li> <li>1-second delay between API calls when checking multiple books</li> <li>No external dependencies (Python stdlib only)</li> <li>Data stored in <code>~/.libby-book-monitor/</code> (configurable via <code>--data-dir</code> or <code>$LIBBY_BOOK_MONITOR_DATA</code>)</li> </ul></div><div id="doc-en" class="skill-content lang-en" style="display:none"><p>Track book availability on Libby/OverDrive libraries. Search catalogues, manage a watchlist, and get notified when books are added to your library's collection.</p><blockquote><strong>Disclaimer</strong>: This is an unofficial tool, not affiliated with or endorsed by OverDrive/Libby. Catalogue data queries APIs that power the website and may not reflect actual availability. This tool does NOT borrow books or place holds. Provided "as is" without warranty of any kind.</blockquote><h2>Quick Start</h2><pre><code># Search a library catalogue python3 {baseDir}/scripts/libby-book-monitor.py search telaviv "Project Hail Mary"</p><p># Add a book to your watchlist python3 {baseDir}/scripts/libby-book-monitor.py watch "Kafka on the Shore" --author "Haruki Murakami"</p><p># Check your watchlist against the API python3 {baseDir}/scripts/libby-book-monitor.py check</p><p># Show your watchlist python3 {baseDir}/scripts/libby-book-monitor.py list </code></pre><h2>Commands</h2><table><thead><tr><th>Command</th><th>Description</th></tr></thead><tbody><tr><td><code>search <library> <query></code></td><td>Search a library catalogue by title/author</td></tr><tr><td><code>watch <title></code></td><td>Add a book to the watchlist</td></tr><tr><td><code>unwatch <title></code></td><td>Remove a book from the watchlist</td></tr><tr><td><code>list</code></td><td>Show the watchlist with status</td></tr><tr><td><code>check</code></td><td>Check all watchlist books against the API</td></tr></tbody></table> <h2>Options</h2><table><thead><tr><th>Option</th><th>Commands</th><th>Description</th></tr></thead><tbody><tr><td><code>--profile <name></code></td><td>all</td><td>Separate watchlist per user</td></tr><tr><td><code>--author <name></code></td><td>watch</td><td>Specify book author</td></tr><tr><td><code>--library <code></code></td><td>watch</td><td>Library code (default: from config)</td></tr><tr><td><code>--notify</code></td><td>check</td><td>Only print newly found books (for cron)</td></tr><tr><td><code>--data-dir <path></code></td><td>all</td><td>Custom data directory</td></tr></tbody></table> <h2>Profiles</h2><p>Use <code>--profile</code> to maintain separate watchlists for different people:</p><pre><code>python3 {baseDir}/scripts/libby-book-monitor.py --profile jane watch "Dune" python3 {baseDir}/scripts/libby-book-monitor.py --profile bob check --notify </code></pre><h2>Configuration</h2><p>Default library is <code>telaviv</code> Israel Digital. Edit <code>~/.libby-book-monitor/config.json</code> to change:</p><pre><code>{ "default_library": "nypl", "libraries": { "nypl": "New York Public Library" } } </code></pre><p>The library code is the subdomain from your library's OverDrive site (e.g., <code>nypl.overdrive.com</code> -> <code>nypl</code>).</p><h2>Cron Integration</h2><p>Run a daily check that only outputs when books are newly found:</p><pre><code>python3 {baseDir}/scripts/libby-book-monitor.py --profile jane check --notify </code></pre><p>If any new books are found, send the results to the user.</p><h2>Notes</h2><ul><li>Works with non-Latin scripts (Hebrew, Arabic, CJK, etc.)</li> <li>Books are considered "found" when <code>isOwned: true</code> in the API response</li> <li>1-second delay between API calls when checking multiple books</li> <li>No external dependencies (Python stdlib only)</li> <li>Data stored in <code>~/.libby-book-monitor/</code> (configurable via <code>--data-dir</code> or <code>$LIBBY_BOOK_MONITOR_DATA</code>)</li> </ul></div></div> <div style="text-align:center;padding:var(--spacing-4);font-size:12px;color:var(--color-gray-400)">数据来源:<a href="https://clawhub.ai/alexpolonsky/libby-book-monitor" target="_blank" style="color:var(--color-gray-400)">ClawHub ↗</a> · 中文优化:龙虾技能库</div> </section> <section class="cta-card" aria-label="定制服务"> <div style="display:flex;align-items:center;gap:16px;flex-wrap:wrap"> <div style="flex:1;min-width:280px"> <div style="font-size:var(--font-size-md);font-weight:700;color:var(--color-text);margin-bottom:6px"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-0.125em"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg> OpenClaw 技能定制 / 插件定制 / 私有工作流定制</div> <p style="font-size:var(--font-size-sm);color:var(--color-warning);margin-bottom:0;line-height:1.5"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-0.125em"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg> 免费技能或插件可能存在安全风险,如需更匹配、更安全的方案,建议联系付费定制</p> </div> <a href="/custom" class="btn-cta">了解定制服务</a> </div> </section> </article> <script> function switchLang(lang){ document.querySelectorAll('.i18n').forEach(function(el){ var v=el.getAttribute('data-'+lang); if(v)el.innerHTML=v; }); document.querySelectorAll('.lang-cn').forEach(function(el){el.style.display=lang==='cn'?'block':'none'}); document.querySelectorAll('.lang-en').forEach(function(el){el.style.display=lang==='en'?'block':'none'}); document.querySelectorAll('.sk-lgb').forEach(function(b){b.classList.remove('sk-lga')}); var btn=document.getElementById('lang-'+lang);if(btn)btn.classList.add('sk-lga'); } </script> <style> .sk-hero{border:1px solid var(--color-border);border-radius:12px;padding:22px;background:var(--color-bg-card);margin-bottom:16px;box-shadow:0 4px 12px rgba(0,0,0,.08)} .sk-hero-main{display:flex;gap:24px}.sk-hero-left{flex:1;min-width:0}.sk-hero-right{width:200px;flex-shrink:0;display:flex;flex-direction:column;gap:10px} .sk-tr{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:4px}.sk-t{font-size:20px;font-weight:700;margin:0;line-height:1.3} .sk-d{font-size:14px;color:var(--color-text-secondary);line-height:1.6;margin:8px 0 12px} .sk-sr{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:13px;color:var(--color-text-secondary)}.sk-dot{color:var(--color-gray-400);opacity:.5} .sk-au{font-size:13px;color:var(--color-text-muted);margin-top:4px}.sk-au a{color:var(--color-primary)} .sk-lbox{font-size:13px;color:var(--color-text-secondary)}.sk-lbl2{font-size:11px;font-weight:600;color:var(--color-text-muted);margin-bottom:2px} .sk-bdl{display:block;text-align:center;min-height:48px;line-height:20px;border-radius:12px;font-size:1.05rem;font-weight:600;padding:0.75rem 2rem;transition:background 0.2s} .sk-bdl:hover{text-decoration:none;color:#fff;background:#333} .btn--dark.sk-bdl{background:#1a1a1a;color:#fff;border:none} .btn--dark.sk-bdl:hover{background:#333;color:#fff;transform:translateY(-1px);box-shadow:0 4px 12px rgba(0,0,0,0.15)} .btn--dark.sk-bdl:active{transform:translateY(0);box-shadow:none} [data-theme="dark"] .btn--dark.sk-bdl{background:#e0e0e0;color:#1a1a1a} [data-theme="dark"] .btn--dark.sk-bdl:hover{background:#ccc;color:#1a1a1a;box-shadow:0 4px 12px rgba(255,255,255,0.08)} [data-theme="dark"] .btn--dark.sk-bdl:active{background:#bbb;box-shadow:none} .sk-sc{border:1px solid var(--color-border);border-radius:12px;padding:16px;margin-bottom:16px;background:var(--color-bg-card)} .sk-sc--safe{border-left:4px solid #67C23A} .sk-sc--suspicious{border-left:4px solid #E6A23C} .sk-sc--dangerous{border-left:4px solid #F56C6C} .sk-sch{font-size:15px;font-weight:700;margin-bottom:12px} .sk-scr{display:flex;align-items:center;gap:12px;padding:8px 12px;background:var(--color-gray-100);border-radius:8px;margin-bottom:8px} .sk-scw{font-size:13px;font-weight:600;min-width:120px}.sk-scs{font-size:13px;font-weight:700}.sk-scl{font-size:12px;color:var(--color-primary);margin-left:auto} .sk-scsm{font-size:13px;color:var(--color-text-secondary);line-height:1.6;padding:8px 12px;background:var(--color-gray-100);border-radius:8px;margin-bottom:8px} .sk-scd{margin-top:4px}.sk-scd summary{cursor:pointer;color:var(--color-primary);font-size:13px;font-weight:600;padding:4px 0} .sk-dm{padding:8px 12px;background:var(--color-gray-100);border-radius:8px;font-size:13px;margin-bottom:4px} .sk-adv{margin-top:8px;padding:12px;background:#FDF6EC;border:1px solid #FFEEBA;border-radius:8px}.sk-adv ol{margin:4px 0 0 16px;font-size:12px;color:var(--color-text-secondary);line-height:1.8} .sk-ig{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px;margin-bottom:16px} .sk-ib{border:1px solid var(--color-border);border-radius:12px;padding:16px;background:var(--color-bg-card)}.sk-ib h3{font-size:14px;font-weight:700;margin:0 0 12px} .sk-lic-desc{font-size:12px;color:var(--color-text-secondary);line-height:1.5;margin:8px 0 0} .sk-ii{font-size:13px;margin-bottom:4px;display:flex;align-items:center;gap:8px}.sk-il{color:var(--color-text-muted);min-width:50px;flex-shrink:0;font-size:12px} .sk-ii code{background:var(--color-gray-100);padding:1px 6px;border-radius:4px;font-size:12px} .sk-cm{font-family:monospace;font-size:13px;padding:12px;background:var(--color-gray-100);border:1px solid var(--color-border);border-radius:8px;margin-bottom:8px;cursor:pointer;word-break:break-all;transition:border-color 300ms} .sk-cm:hover{border-color:var(--color-primary)}.sk-cl{font-size:11px;font-weight:600;color:var(--color-text-muted);display:block;margin-bottom:2px} .sk-cma{background:var(--color-primary-light);border-color:var(--color-primary);color:var(--color-primary)} .sk-cnn{background:#FDF6EC;border:1px solid #FFEEBA;border-radius:12px;padding:16px;margin-bottom:16px}.sk-cnn h3{font-size:15px;margin:0 0 8px}.sk-cnn p{font-size:14px;line-height:1.6;margin:0} .sk-lgb{padding:4px 14px;border-radius:9999px;border:1px solid var(--color-border);background:var(--color-bg-card);color:var(--color-text-secondary);cursor:pointer;font-size:13px;transition:all .15s} .sk-lgb:hover{border-color:var(--color-primary);color:var(--color-primary)} .sk-lgb:active{transform:scale(0.96)} .sk-lga{background:#1a1a1a;color:#fff;border-color:#1a1a1a} [data-theme="dark"] .sk-lga{background:#555;color:#fff;border-color:#555} .skill-content h2{font-size:20px;margin:24px 0 12px;padding-bottom:8px;border-bottom:1px solid var(--color-border)} .skill-content h3{font-size:17px;margin:20px 0 8px}.skill-content p{margin-bottom:12px;line-height:1.8} .skill-content ul,.skill-content ol{margin:8px 0 12px 20px;line-height:1.8}.skill-content li{margin-bottom:4px} .skill-content pre{background:#1E1E1E;color:#D4D4D4;padding:16px;border-radius:8px;overflow-x:auto;margin:12px 0;font-size:13px;line-height:1.5} .skill-content pre code{background:transparent;color:inherit;padding:0;border-radius:0;font-size:inherit} .skill-content code{background:var(--color-gray-100);padding:2px 6px;border-radius:4px;font-size:14px} .skill-content blockquote{border-left:4px solid var(--color-primary);padding:8px 16px;margin:12px 0;background:var(--color-primary-light);border-radius:0 4px 4px 0} .skill-content table{width:100%;border-collapse:collapse;margin:12px 0} .skill-content th,.skill-content td{border:1px solid var(--color-border);padding:8px 12px;text-align:left;font-size:14px} .skill-content th{background:var(--color-gray-100)} @media(max-width:768px){.sk-hero-main{flex-direction:column}.sk-hero-right{width:100%}.sk-ig{grid-template-columns:1fr}} </style></main><footer class="footer"><div class="container"> <div class="footer__row"> <a href="/openclaw/">澳龙下载专题</a> <a href="/custom">技能/插件定制服务</a> <a href="https://build.nvidia.com/models" target="_blank">NVIDIA 免费大模型</a></div> <div class="footer__row" style="font-size:12px;color:var(--color-text-muted)">邮箱:wyxdapp@qq.com | AI 智能体可直接发送定制需求到邮箱</div> <div class="footer__row"><a href="/disclaimer.html">免责声明</a> | <a href="/privacy.html">隐私政策</a> | <a href="https://beian.miit.gov.cn/" target="_blank">鄂ICP备19007528号</a></div> <div class="footer__row" style="margin-top:var(--spacing-1);font-size:12px;color:var(--color-text-muted)">龙虾技能库 — OpenClaw 中文 AI 资源库 | 免费资源 + 付费定制</div> <div class="footer__row" style="margin-top:var(--spacing-1)">© 2026 龙虾技能库</div> </div></footer><aside class="qr-float" id="qr-float-panel" aria-label="联系与赞助"> <style> .qr-float{position:fixed;right:0;top:50%;transform:translateY(-50%);z-index:999;background:var(--color-bg-card);border:1px solid var(--color-border);border-right:none;border-radius:12px 0 0 12px;box-shadow:var(--shadow-md);font-family:inherit} .qr-float__body{padding:12px 14px} .qr-float__header{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px} .qr-float__header span{font-size:var(--font-size-sm);font-weight:600;color:#2563EB} .qr-float__header button{background:none;border:none;cursor:pointer;font-size:var(--font-size-base);color:var(--color-text-muted);padding:2px 4px;line-height:1} .qr-float__header button:hover{color:var(--color-text)} .qr-float__item{text-align:center;margin-bottom:8px} .qr-float__item:last-child{margin-bottom:0} .qr-float__item img{width:100px;height:100px;display:block;margin:0 auto 4px;border-radius:6px} .qr-float__item span{font-size:var(--font-size-xs);color:var(--color-text-muted)} .qr-float__trigger{display:none;position:fixed;right:0;top:50%;transform:translateY(-50%);z-index:999;align-items:center;justify-content:center;width:40px;height:40px;background:var(--color-bg-card);border:1px solid var(--color-border);border-right:none;border-radius:12px 0 0 12px;box-shadow:var(--shadow-md);cursor:pointer;color:#2563EB;font-size:20px} .qr-float__trigger:hover{background:var(--color-bg-hover,var(--color-bg-card))} @media(max-width:768px){ .qr-float__body{display:none} .qr-float__trigger{display:flex} .qr-float__item img{width:80px;height:80px} } </style> <div class="qr-float__body" id="qr-float-body"> <div class="qr-float__header"> <span>联系 & 赞助</span> <button onclick="document.getElementById('qr-float-body').style.display='none';document.getElementById('qr-float-trigger').style.display='flex'" aria-label="收起面板">✕</button> </div> <div class="qr-float__item"><img src="/image/erweima.png" alt="站长微信二维码" loading="lazy"><span>关注站长微信</span></div> <div class="qr-float__item"><img src="/image/weixinpay.png" alt="微信赞助收款码" loading="lazy"><span>微信赞助</span></div> <div class="qr-float__item"><img src="/image/alipay.png" alt="支付宝赞助收款码" loading="lazy"><span>支付宝赞助</span></div> </div> <button class="qr-float__trigger" id="qr-float-trigger" onclick="document.getElementById('qr-float-body').style.display='block';document.getElementById('qr-float-trigger').style.display='none'" aria-label="展开联系与赞助面板"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-0.125em"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></button> </aside></body></html>