Skip to content

通知模板 ​

定位:NanShare 的三类通知模板(文件整理、订阅、Emby)统一使用 Gonja(Go 版 Jinja2)语法。文件整理与 Emby 是 title/text/image 结构化模板,订阅是纯文本模板;每类模板的可用变量都要落在对应字段目录内,保存时会被逐项校验。

运维通知模板Gonja 变量Telegram / Emby

前置条件 ​

  • 已配置 Telegram Bot。
  • Emby 通知模板需在 Emby 中把 Webhook 指向 NanShare。
  • 文件整理通知需先开启整理基础配置中的整理通知开关,触发时机跟整理/监控任务绑定,参考 监控配置。
  • 订阅通知由订阅策略触发,相关开关与策略在 订阅设置 中维护。

文件整理通知 ​

模板结构 ​

  • 结构键固定为 title、text、image、link,缺键按空串处理。
  • 出现其它键:报「通知模板存在未支持键:…」。
  • 完全没有结构键:报「整理通知模板需要使用 title/text/image/link 结构键」。

字段目录(29 项) ​

keylabelsnippet说明
title_year标题+年份如 年会不能停! (2023)
title标题媒体标题,不含年份
year年份媒体年份
season_episode季集如 S01 E03,电影为空
media_type媒体类型如 电影、电视剧
category分类整理后的二级分类
resource_quality质量如 WEB-DL DV HDR10 2160p DV P7
releaseGroup压制组/字幕组制作组/字幕组
release_group压制组/字幕组(别名)等同于 releaseGroup
resource_term资源规格资源类型 + 特效 + 分辨率 + 杜比视界类型
webSource流媒体平台如 HBO、Netflix
audioCodec音频编码如 DDP5.1、TrueHD
vote_average评分TMDB/豆瓣评分,0 表示暂无
overview简介媒体简介
time_usage用时从开始识别到完成移动/复制的耗时
total_size体积格式化后的大小
file_count文件数本次整理涉及的文件数
tmdbidTMDB IDTMDB ID(可能为空)
imdbidIMDB IDIMDB ID(可能为空)
tvdbidTVDB IDTVDB ID(剧集场景更常见,可能为空)
doubanid豆瓣 ID豆瓣 ID(可能为空)
meta_weight_score洗版源总分源文件加权总分,如 84.0
meta_weight_dest_score洗版目标总分被比较目标的加权总分,如 55.5
meta_weight_delta洗版分差源总分减目标总分
meta_weight_rule洗版规则本次使用的洗版规则名
meta_weight_version洗版版本源命中并入库的版本名
meta_weight_note洗版说明如 替换掉 1 个旧版(1080p WEB-DL)
meta_weight_deleted_count洗版删除数本次覆盖删除的目标文件数量
meta_weight_detail洗版评分明细逐组评分明细,供高级模板使用

TIP

洗版字段只在本次整理触发洗版判定(分数比较、覆盖删除)时才有值,模板里建议用 {% if meta_weight_score %} 包裹;release_group 与 releaseGroup 完全等价,写哪个都行。

默认模板片段 ​

text
{
    "title": "🎬 {{ title_year }} {{ season_episode if season_episode else '' }} 已入库\n\n",
    "text": (
        "✨ 质量:{{ resource_quality }}\n"
        "{% if meta_weight_score %}"
        "⚖️ 洗版:{{ meta_weight_score }} → {{ meta_weight_dest_score }}\n"
        "{% endif %}"
        "{% if meta_weight_note %}"
        "📝 说明:{{ meta_weight_note }}\n"
        "{% endif %}"
        "{% if meta_weight_deleted_count %}"
        "🗑 已删除其他版本:{{ meta_weight_deleted_count }} 个\n"
        "{% endif %}"
        "{% if vote_average %}"
        "🌟 评分:{{ vote_average }}/10\n"
        "{% endif %}"
        "{% if media_type or category %}"
        "🎞 类型:{{ media_type }} · 🏷 类别:{{ category }}\n"
        "{% endif %}"
        "📂 数量:{{ file_count }} 个 · 💾 大小:{{ total_size }}\n"
        "{% if release_group %}"
        "👥 小组:{{ release_group }}\n"
        "{% endif %}"
        "⚡ 用时:{{ time_usage if time_usage else '未知' }}\n\n"
        "🔗 :[TMDB](https://www.themoviedb.org/{% if '电视' in media_type %}tv{% else %}movie{% endif %}/{{ tmdbid }}) · [豆瓣](https://m.douban.com/search/?query={{ title }}) · [IMDB](https://www.imdb.com/title/{{ imdbid }}) · [TVDB](https://thetvdb.com/?id={{ tvdbid }}&tab=series)\n"
        "{% if overview %}\n"
        "📝 简介:\n{{ overview | truncate(50, True, '...') }}"
        "{% endif %}"
    )
}

渲染规则 ​

  • failed / exists 状态完全不渲染模板:走代码里的固定文案,标题为 🎬 … 整理失败,正文固定包含质量、评分、类型/类别、数量/大小、小组、用时、失败原因等行。
  • image 渲染为空时,自动回退 backdrop_path,再回退 poster_path。
  • link 非空时,会在消息末尾追加一行 [查看详情](link)。
  • 模板渲染失败时该条通知整体失败并记录日志;未知变量统一报「存在未支持字段:…」。

订阅通知 ​

变量 ​

变量说明
name订阅名称
year年份
season_ep季集范围,如 S02 E01-03
mode_text策略中文名:分享追更 / 订阅转存
version版本信息组合(分辨率 · 特效 · 资源类型 · 视频编码 · 音频编码 · 制作组)
ep_progress剧集进度文本
strm_resultSTRM 生成结果摘要
strm_files本次生成的 STRM 文件列表
share_link本次使用的分享链接
done_eps本次完成的集数列表(整数)
completed_episodes当前已完成集数列表
media_typemovie 或 tv
resolution分辨率
effect特效
resource_type资源类型
release_group制作组
video_codec视频编码
audio_codec音频编码
sub当前订阅对象完整数据
selected本次选中的资源项
all_items本次处理的所有资源项

默认模板 ​

text
🎬 订阅追更通知

📌 {{ name }}{% if year %} ({{ year }}){% endif %}
{% if season_ep %}📺 {{ season_ep }}
{% endif %}📋 {{ mode_text }}
{% if version %}🏷️ {{ version }}
{% endif %}{% if strm_result %}
📁 {{ strm_result }}
{% endif %}{% if ep_progress %}
📊 {{ ep_progress }}
{% endif %}

渲染与回退 ​

  • 模板留空时直接使用代码内置的固定文案(与默认模板同形的 📌 / 📺 / 📋 / 🏷️ / 📁 / 📊 几行)。
  • 自定义模板渲染失败时会记录「Jinja2 模板渲染失败,使用默认模板」并回退到同一份固定文案,不会中断订阅任务。
  • 前端提示原文:「支持 Jinja2 语法。转存和分享订阅共用这套模板,常用变量如下:」并列出 、 、 、(列表) (列表) (订阅对象)。
  • 输入框 hint 原文:「支持 Jinja2 语法;常用变量:name、year、season_ep、mode_text、version、ep_progress、strm_result。」,placeholder 为「留空使用默认模板」,右上角提供「恢复默认模板」。

Emby 通知 ​

事件映射 ​

Webhook 事件名大小写不敏感,_、- 会先规整为 . 再匹配。支持的动作与全部别名:

动作Webhook 事件别名
新入库library.new、item.added、ItemAdded
开始播放playback.start、media.play、PlaybackStart
暂停播放playback.pause、media.pause、PlaybackPause
恢复播放playback.unpause、media.resume、PlaybackUnpause、PlaybackResume
停止播放playback.stop、media.stop、PlaybackStop
登录成功user.authenticated、UserAuthenticated、UserLoggedIn
登录失败user.authenticationfailed、UserAuthenticationFailed、UserLoginFailed、UserLockedOut
标记了item.rate、ItemRated、item.markplayed、item.markunplayed、item.markfavorite、item.unmarkfavorite、ItemMarkedPlayed、ItemMarkedUnplayed、ItemMarkedFavorite、ItemUnmarkedFavorite

未识别的事件不会走模板,而是直接发送一条「Emby 原始通知」并附带原始字段;开启调试或「记录原始字段到 log.log」后,未识别事件只写日志、不再推送 TG。

字段目录(30 项) ​

消息字段(18):

keylabelsnippet说明
action动作映射后的中文动作,如 新入库、开始播放、暂停播放、恢复播放、停止播放、登录失败
mark_status标记状态标记事件的具体状态,如 已观看、未观看、已收藏
action_detail动作详情当前动作的补充说明,标记事件等同于标记状态
media_type媒体类型媒体类型,如 电影、剧集、有声书
item_name媒体名称电影名或剧集季集名称
title_year标题年份媒体标题和年份,如 低智商犯罪 (2026)
season_episode季集剧集季集,如 S01 E04-E05
user_name用户触发事件的 Emby 用户名
user_id用户 IDWebhook 中的 Emby 用户 ID
client客户端播放或登录客户端名称
device_name设备播放或登录设备名称
ip_address来源 IPWebhook 中携带的远端 IP
percentage播放进度播放百分比,优先读取 Emby 进度字段
vote_average评分媒体评分,通常来自 CommunityRating
overview简介媒体简介
tmdbidTMDB IDItem.ProviderIds.Tmdb
imdbidIMDb IDItem.ProviderIds.Imdb
now_time操作时间NanShare 收到 Webhook 的时间

扩展字段(12):

keylabelsnippet说明
event原始事件Webhook 中的事件类型原值
item_idItem IDEmby Item Id
series_id剧集 IDEpisode 所属 SeriesId
season_id季 IDSeasonId 或 ParentId
episode_id集 ID集项目 ID
begin_season起始季解析出的起始季号
begin_episode起始集解析出的起始集号
end_episode结束集解析出的结束集号,多集或非连续时存在
episode_list集数列表解析出的集号列表
server_name服务器名称Webhook 中的 Emby 服务器名称
image_url图片地址自动用 Emby 助手和秒传播放配置生成的背景图或封面图地址
raw_json原始 JSON解析后的 Webhook payload JSON 文本

保存校验白名单 = 以上 30 项 + cycler / dict / joiner / lipsum / namespace / range / true / false / none / None,并且 {% set %} / {% for %} 定义的自定义名会被跳过不报错(出厂默认模板就是这样写的)。结构键之外的键会报「通知模板存在未支持键:…」;无法按 title/text/image 解析时报「Emby 通知模板仅支持 JSON/YAML 对象格式,或兼容的 Python 字典字面量格式,并需使用 title/text/image 结构键(image 可留空)」。

默认模板 ​

title 片段(按动作分派 emoji,再拼用户与媒体名):

text
{% if action == '新入库' and media_type == '电影' %}🎬 {% elif action == '新入库' and media_type == '剧集' %}📺 {% elif action == '新入库' and media_type == '有声书' %}📚 {% elif action == '新入库' %}🆕 {% elif action == '开始播放' %}▶️ {% elif action == '暂停播放' %}⏸️ {% elif action == '恢复播放' %}🔁 {% elif action == '停止播放' %}⏹️ {% elif action == '登录成功' %}✅ {% elif action == '登录失败' %}❌ {% elif action == '标记了' %}🏷️ {% endif %}{% if user_name %}【{{ user_name }}】{% endif %}{{ action }}{% if media_type %} {{media_type}} {% endif %}{{ item_name }}{% if mark_status %} {{ mark_status }}{% endif %}
默认模板完整内容(含超长 text 片段,点开复制)
text
{
"title": "{% if action == '新入库' and media_type == '电影' %}🎬 {% elif action == '新入库' and media_type == '剧集' %}📺 {% elif action == '新入库' and media_type == '有声书' %}📚 {% elif action == '新入库' %}🆕 {% elif action == '开始播放' %}▶️ {% elif action == '暂停播放' %}⏸️ {% elif action == '恢复播放' %}🔁 {% elif action == '停止播放' %}⏹️ {% elif action == '登录成功' %}✅ {% elif action == '登录失败' %}❌ {% elif action == '标记了' %}🏷️ {% endif %}{% if user_name %}【{{ user_name }}】{% endif %}{{ action }}{% if media_type %} {{media_type}} {% endif %}{{ item_name }}{% if mark_status %} {{ mark_status }}{% endif %}",
"text":
"{% set va = vote_average|default(0)|float(0) %}"
"{% set mt_lower = media_type|default('', true)|lower %}"
"{% set action_lower = action|default('', true)|lower %}"
"{% set is_new_content = '新入库' in action %}"
"{% set is_playing = '开始播放' in action %}"
"{% set is_paused = '暂停播放' in action %}"
"{% set is_resumed = '恢复播放' in action %}"
"{% set is_stopped = '停止播放' in action %}"
"{% set is_login_success = '登录成功' in action %}"
"{% set is_login_failed = '登录失败' in action %}"
"{% set is_marked = '标记了' in action %}"
"{% set progress_num = percentage|default(0)|int(0) %}"
"{% set time_str = now_time|default('12:00:00') %}"
"{% if ' ' in time_str %}{% set time_part = time_str.split(' ')[1] %}{% else %}{% set time_part = time_str %}{% endif %}"
"{% set hour = time_part.split(':')[0]|int if ':' in time_part else 12 %}"
"{% set is_late_night = hour >= 23 or hour < 6 %}"
"{% set is_early_morning = hour >= 6 and hour < 9 %}"
"{% set is_morning = hour >= 9 and hour < 12 %}"
"{% set is_noon = hour >= 12 and hour < 14 %}"
"{% set is_afternoon = hour >= 14 and hour < 18 %}"
"{% set is_evening = hour >= 18 and hour < 23 %}"
"{% if vote_average %}⭐️ 评分:{{ vote_average }}/10\n{% endif %}"
"{% if media_type == '电影' %}🎦{% elif media_type == '剧集' %}📺{% elif media_type == '有声书' %}📚{% else %}📱{% endif %} 媒体类型:{{ media_type }}\n"
"{% if percentage %}🔄 播放进度:{{ percentage }}%\n{% endif %}"
"{% if ip_address %}🌐 来源IP:{{ ip_address }}\n{% endif %}"
"{% if device_name %}📱 播放设备:{{ client }} {{ device_name }}\n{% endif %}"
"{% if user_name and not is_new_content %}👤 用户:{{ user_name }}\n{% endif %}"
"{% if tmdbid %}🍿 TMDB ID:{{ tmdbid }}\n{% endif %}"
"{% if imdbid %}🌟 IMDB ID:{{ imdbid }}\n{% endif %}"
"🕒 操作时间:{{ now_time }}\n"
"{% if overview and is_new_content %}"
"\n📝 简介:{{ overview[:100] }}…\n"
"{% elif overview and not is_new_content %}\n📝 剧情:{{ overview }}{% endif %}"
"{% if tmdbid or imdbid or item_name %}"
"\n\n{% set has_links = false %}"
"{% if tmdbid %}🔗 [TMDB](https://www.themoviedb.org/{% if media_type == '电影' %}movie{% elif media_type == '剧集' %}tv{% else %}movie{% endif %}/{{ tmdbid }}){% set has_links = true %}{% endif %}"
"{% set douban_search_possible = imdbid or item_name %}"
"{% if has_links and douban_search_possible %} | {% endif %}"
"{% if douban_search_possible %}✳️ {% if imdbid %}[豆瓣](https://www.douban.com/search?cat=1002&q={{ imdbid }}){% else %}[豆瓣](https://www.douban.com/search?cat=1002&q={{ item_name | urlencode }}){% endif %}{% set has_links = true %}{% endif %}"
"{% if imdbid %}{% if has_links %} | {% endif %}🌟 [IMDb](https://www.imdb.com/title/{{ imdbid }}/){% set has_links = true %}{% endif %}"
"{% if has_links %}\n{% endif %}"
"{% endif %}"
"\n"
"{% if is_new_content %}"
"{% if va >= 9.8 %}👑🔥 这TM才是真·封神榜!跪着看就完事了,建议全体起立!"
"{% elif va >= 9.5 %}💥 卧槽这分是充了多少钱?但有一说一确实能打,建议申遗!"
"{% elif va >= 9.0 %}🤙 这波在大气层!年度装逼必备作品,不看不是社会人!"
"{% elif va >= 8.5 %}👍 这分对得起你熬的夜!建议搭配炸鸡啤酒食用更佳~"
"{% elif va >= 8.0 %}🍺 中规中矩电子榨菜,拉屎时看刚刚好!"
"{% elif va >= 7.5 %}🤏 也就图一乐,建议开2倍速别浪费生命!"
"{% elif va >= 7.0 %}🙄 这分是刷的吧?建议下载反诈APP!"
"{% elif va >= 6.0 %}😅 6分保底神作,建议配合弹幕护体食用!"
"{% elif va >= 5.0 %}💩 卧槽这答辩也敢入库?建议申报金扫帚奖!"
"{% elif va >= 4.0 %}🤮 导演是喝高了拍的?建议众筹给编剧寄刀片!"
"{% elif va > 0 %}👻 这分是来搞行为艺术的?建议配合降压药观看!"
"{% elif media_type == '电影' %}🎬 新片到货!是骡子是马拉出来溜溜~"
"{% elif media_type == '剧集' %}📺 新剧上架!建议备好瓜子板凳开喷!"
"{% else %}🆕 新货到仓!是惊喜还是惊吓你说了算!{% endif %}"
"{% elif is_playing %}"
"{% if va > 0 %}"
"{% if va >= 9.8 %}🤯 全体注意!前方高能!建议暂停呼吸!"
"{% elif va >= 9.5 %}🚨 这不是演习!请系好安全带准备起飞!"
"{% elif va >= 9.0 %}💥 前方名场面预警!建议录屏反复观看!"
"{% elif va >= 8.5 %}🎇 建议关闭手机!错过镜头血亏一个亿!"
"{% elif va >= 8.0 %}🍿 瓜子饮料准备好,这个能下三碗饭!"
"{% elif va >= 7.5 %}📱 建议开弹幕,没网友吐槽根本看不下去!"
"{% elif va >= 7.0 %}😑 就当听个响,建议边刷抖音边看!"
"{% elif va >= 6.0 %}🤏 建议2倍速观看,时间就是金钱!"
"{% elif va >= 5.0 %}💣 勇士拔剑吧!建议呼叫沙雕网友陪看!"
"{% elif va >= 4.0 %}⚠️ 非战斗人员请撤离!辣眼睛预警!"
"{% else %}☢️ 注意这不是演习!烂片核爆倒计时!"
"{% endif %}"
"{% else %}"
"{% if is_late_night %}"
"{% if progress_num <= 5 %}🌙 大半夜不睡觉是吧?年轻人就是肝!"
"{% elif progress_num <= 20 %}🌃 夜猫子认证!建议来包辣条提神!"
"{% elif progress_num <= 50 %}🌌 这是要决战到天亮?瑞思拜!"
"{% elif progress_num <= 80 %}🌅 看到这个点?明天上班等着摸鱼吧!"
"{% else %}😴 好家伙直接看到天亮?建议申遗!{% endif %}"
"{% else %}"
"{% if progress_num <= 5 %}🚀 刚开局就想跑?给导演个面子!"
"{% elif progress_num <= 20 %}👀 前戏还没完!精彩的在后面!"
"{% elif progress_num <= 50 %}🎢 过山车开到半山腰!坐稳了!"
"{% elif progress_num <= 80 %}🔥 高潮要来了!纸巾备好!"
"{% else %}🏁 最后冲刺!憋住别上厕所!{% endif %}"
"{% endif %}"
"{% endif %}"
"{% elif is_paused %}"
"{% if va > 0 %}"
"{% if va >= 9.8 %}⏸️ 暂停神片?建议立即续播否则浑身蚂蚁爬!"
"{% elif va >= 9.5 %}⏸️ 看到一半暂停?你是真能忍!"
"{% elif va >= 9.0 %}🚫 暂停装逼现场?建议立即恢复!"
"{% elif va >= 8.5 %}🛑 看到高潮刹车?兄弟你好狠!"
"{% elif va >= 8.0 %}⏸️ 暂停干饭?建议边吃边看!"
"{% elif va >= 7.5 %}⏹️ 暂时停一手也行,别回头忘了续上!"
"{% elif va >= 7.0 %}🛌 暂停得好!建议先换换脑子再回来!"
"{% elif va >= 6.0 %}⏸️ 明智选择!建议转战王者峡谷!"
"{% elif va >= 5.0 %}🗑️ 暂停得好!建议冷静三秒再决定!"
"{% elif va >= 4.0 %}💢 暂停看这玩意?建议立即洗眼睛!"
"{% else %}☠️ 暂停保命!建议领取抗烂片补助!"
"{% endif %}"
"{% else %}"
"{% if is_late_night %}"
"{% if progress_num >= 90 %}🌙 都快看完了还暂停?你是懂吊胃口的!"
"{% elif progress_num >= 70 %}😴 看到这程度先歇会儿也合理,梦里记得续上!"
"{% elif progress_num >= 30 %}🌃 暂停在这?你是懂吊胃口的!"
"{% else %}👋 才看这点就暂停?建议先别急着下结论!{% endif %}"
"{% else %}"
"{% if progress_num >= 90 %}🎉 都到最后了先歇口气,回来收尾刚刚好!"
"{% elif progress_num >= 70 %}🛋️ 看到这程度暂停,回头接着看也不亏!"
"{% elif progress_num >= 30 %}⏸️ 暂停在这?你是懂吊胃口的!"
"{% else %}👀 刚开场先暂停?后面说不定真有活!{% endif %}"
"{% endif %}"
"{% endif %}"
"{% elif is_resumed %}"
"{% if va > 0 %}"
"{% if va >= 9.8 %}🔁 神片续播成功!建议把其他事统统往后放!"
"{% elif va >= 9.5 %}🚀 高能继续!这会儿退出血亏!"
"{% elif va >= 9.0 %}💥 名场面重新开张,准备接招!"
"{% elif va >= 8.5 %}🎬 续上这个节奏,今天这波值回票价!"
"{% elif va >= 8.0 %}🍿 瓜子饮料重新就位,继续整!"
"{% elif va >= 7.5 %}📺 电子榨菜回锅加热,继续下饭!"
"{% elif va >= 7.0 %}😏 又点回来了?说明它多少还有点东西!"
"{% elif va >= 6.0 %}🔁 既然续播了,那就再给它一次机会!"
"{% elif va >= 5.0 %}🧯 勇士回归现场,继续顶着看吧!"
"{% elif va >= 4.0 %}⚠️ 这都能恢复播放?只能说你是真勇!"
"{% else %}☢️ 核爆现场重新启动,请系好安全带!"
"{% endif %}"
"{% else %}"
"{% if progress_num >= 80 %}🏁 续播冲线阶段,离收工就差最后一口气!"
"{% elif progress_num >= 40 %}🔁 接上进度继续看,故事这会儿才有味道!"
"{% elif progress_num >= 10 %}📼 断点续播成功,继续看看它能整出什么活!"
"{% else %}▶️ 刚暂停就恢复?这节奏主打一个无缝衔接!{% endif %}"
"{% endif %}"
"{% elif is_stopped %}"
"{% if progress_num >= 95 %}🏁 本次基本看完收工,起身活动两步刚刚好!"
"{% elif progress_num >= 70 %}📴 本次播放先结束,下次从这里接着看也不亏!"
"{% elif progress_num >= 30 %}🛑 今天先看到这,回头续上也还在节奏里!"
"{% else %}👋 刚开场就收工?下次再给它一次机会!{% endif %}"
"{% elif is_login_success %}"
"{% if is_late_night %}🌙 夜猫子登录!建议开启隐身模式!"
"{% elif is_early_morning %}🌅 早起的鸟儿被抓包!建议装睡!"
"{% else %}🎉 欢迎老铁!建议备好肥宅快乐水!{% endif %}"
"{% elif is_login_failed %}⚠️ 密码不对还想白嫖?建议充值智商!"
"{% elif is_marked %}🏷️ 标记成功!建议同步发朋友圈装逼!"
"{% else %}📱 系统诈尸!建议立即截图发贴吧!{% endif %}\n"
}

TIP

默认模板文案很长,随时可以在工具箱 → Emby 通知里点「恢复默认」;image 留空时会自动使用 image_url。

图片与推送规则 ​

  • image_type 默认 backdrop:优先背景图(ParentBackdropItemId → series_id → item_id),缺失时回退封面;改为 primary 则优先封面、再回退背景。登录事件会优先使用用户头像。
  • 图片下载失败且「下载失败使用内置 Emby 原图」开启时,改用内置图继续发送;再失败才退化为纯文本通知。
  • 同一「媒体 + 客户端 + 用户」的停止播放事件在 600 秒内只会推送一次;同一对象的开始播放会重置这条去重记录。
  • Webhook 地址:/api/emby_notify/webhook?token=nanshare,完整示例为 http://你的IP:8115/api/emby_notify/webhook?token=nanshare。

使用流程 ​

  1. 在「设置 → Telegram Bot」配置并启用 Bot,勾选需要的通知场景。
  2. 文件整理通知:到整理配置页的基础配置填写整理 Telegram 通知模板,并开启整理通知。
  3. 订阅通知:到 [订阅设置](/subscribe/overview) 填写订阅通知模板,留空即用默认模板。
  4. Emby 通知:到工具箱 → Emby 通知填写模板,并在 Emby 配置 Webhook 地址。
  5. 用测试按钮或触发一次真实事件验证渲染效果。

常见问题 ​

模板不渲染或报错 ​

TIP

先确认变量名与模板类型是否匹配:整理/Emby 模板是 title/text/image 结构,订阅模板是纯文本。变量不存在时会渲染为空,建议用 or 或 |default(...) 提供兜底。

保存时报「存在未支持字段」 ​

TIP

说明模板里用到了字段目录之外的变量。文件整理通知只认 29 个字段,且不支持 {% set %} 自定义变量(会被当作未支持字段),把计算内联写进 / {% if %} 即可;Emby 通知认 30 个字段,{% set %} / {% for %} 的自定义名不受影响。

整理失败时为什么没走我的模板 ​

DANGER

failed / exists 状态刻意不渲染模板,统一走固定文案,保证失败原因格式稳定;只有成功整理(moved / copied / unchanged)才会使用自定义模板。

Emby 通知收不到 ​

TIP

确认 Webhook 地址带 token 参数且与 Emby 通知配置一致、Emby 能访问 NanShare 的 8115 端口;未识别事件只会发「原始字段」通知,可在 Emby 通知页开启记录原始字段排查;同一媒体+客户端+用户的停止播放 600 秒内只发一次。

NanShare 文档站仅说明 NanShare 项目的部署、配置与使用。