feat(notify): 新增站级 Webhook 与用户级 Telegram 通知通道
在现有邮件通知之外补两条广播/点对点通道: - 站级 Webhook([notify] webhook_url):新提问 / 新回答 / 新追问 / 新私聊 / 新投票回复统一 POST JSON 到通用 Webhook(Discord / Slack / 企业微信机器人等)。 消息体同时带 content(Discord 直接可用)与结构化 event/title/body/link 字段。 - 用户级 Telegram([notify] telegram_bot_token + users.telegram_chat_id):箱主 自填 Chat ID,新提问 / 新投票回复点对点推送。 设计约束:通知是「尽力而为」旁路 —— 任一通道发送失败只记日志、不向上抛错, 绝不影响提问/回答的主流程;通道未配置时静默跳过。发送放在 shared.SafeGo 异步 执行,与现有邮件通知同一条路径。 6 处业务触发点接入 notify;私聊消息保留仅邮件(已有 5 分钟节流,避免广播刷屏)。 profile 页新增 Telegram Chat ID 输入框 + 四语言字典。app.sample.ini 加 [notify] 段。 测试覆盖 webhook 的 JSON 结构与未配置时的静默跳过。
This commit is contained in:
+57
-54
@@ -200,34 +200,37 @@ var jaDict = map[string]string{
|
||||
"admin.export": "データをエクスポート",
|
||||
|
||||
// 管理画面設定(追加)
|
||||
"admin.oldPasswordHint": "パスワード変更時のみ使用。空欄のままなら変更されません",
|
||||
"admin.newPasswordHint": "6〜64文字。空欄のままなら変更されません",
|
||||
"admin.notifyEmail": "メール",
|
||||
"admin.useCustomFg": "カスタム前景色を使用(それ以外は自動マッチ)",
|
||||
"admin.customFgHint": "有効時のみ適用されます。それ以外は自動生成されます",
|
||||
"admin.avatarPlaceholder": "アバターをアップロード(1:1 以外は縦横比が崩れます)",
|
||||
"admin.backgroundPlaceholder": "質問箱の背景をアップロード",
|
||||
"admin.qrBackgroundPlaceholder": "QRコードの背景画像をアップロード(暗すぎる背景はQRコードが読み取れなくなることがあります)",
|
||||
"admin.qrPreviewHint": "画像を選択するとプレビューが即時更新されます",
|
||||
"admin.preview": "ライブプレビュー",
|
||||
"admin.themePreset": "プリセットテーマ",
|
||||
"admin.themeDefault": "デフォルト",
|
||||
"admin.themeDark": "ダーク",
|
||||
"admin.themeOcean": "オーシャン",
|
||||
"admin.themeSunset": "サンセット",
|
||||
"admin.resetDefaults": "🔄 デフォルトに戻す",
|
||||
"admin.previewHint": "調整はプレビューのみです。「変更を保存」をクリックすると反映されます",
|
||||
"admin.socialHint": "チェックを入れてプロフィールURLを入力してください(https:// は不要)。チェックのない項目は表示されません。",
|
||||
"admin.enableAcfun": "AcFun を有効にする",
|
||||
"admin.enableBili": "Bilibili を有効にする",
|
||||
"admin.enableWeibo": "Weibo を有効にする",
|
||||
"admin.enableXiaohongshu": "小紅書 を有効にする",
|
||||
"admin.enableBlog": "個人ブログを有効にする",
|
||||
"admin.registerOnly": "登録ユーザーのみ質問を許可",
|
||||
"admin.updateHarassment": "迷惑行為対策を更新",
|
||||
"admin.globalBlockWords": "共通ブロックワード",
|
||||
"admin.globalBlockWordsHint": "ブロックワードは質問・チャット(相手からあなたへのメッセージ)・投票の投稿内容に適用されます。この設定は質問/チャット/投票の3つのタブで共有され、どこで変更してもすぐに反映されます。",
|
||||
"admin.updateBlockWords": "ブロックワードを保存",
|
||||
"admin.oldPasswordHint": "パスワード変更時のみ使用。空欄のままなら変更されません",
|
||||
"admin.newPasswordHint": "6〜64文字。空欄のままなら変更されません",
|
||||
"admin.notifyEmail": "メール",
|
||||
"admin.notifyTelegram": "Telegram 通知",
|
||||
"admin.notifyTelegramPlaceholder": "Telegram Chat ID(空欄なら送信しない)",
|
||||
"admin.notifyTelegramHint": "@userinfobot に何か送ると Chat ID を取得できます。サイト側で Telegram Bot の設定が必要です。",
|
||||
"admin.useCustomFg": "カスタム前景色を使用(それ以外は自動マッチ)",
|
||||
"admin.customFgHint": "有効時のみ適用されます。それ以外は自動生成されます",
|
||||
"admin.avatarPlaceholder": "アバターをアップロード(1:1 以外は縦横比が崩れます)",
|
||||
"admin.backgroundPlaceholder": "質問箱の背景をアップロード",
|
||||
"admin.qrBackgroundPlaceholder": "QRコードの背景画像をアップロード(暗すぎる背景はQRコードが読み取れなくなることがあります)",
|
||||
"admin.qrPreviewHint": "画像を選択するとプレビューが即時更新されます",
|
||||
"admin.preview": "ライブプレビュー",
|
||||
"admin.themePreset": "プリセットテーマ",
|
||||
"admin.themeDefault": "デフォルト",
|
||||
"admin.themeDark": "ダーク",
|
||||
"admin.themeOcean": "オーシャン",
|
||||
"admin.themeSunset": "サンセット",
|
||||
"admin.resetDefaults": "🔄 デフォルトに戻す",
|
||||
"admin.previewHint": "調整はプレビューのみです。「変更を保存」をクリックすると反映されます",
|
||||
"admin.socialHint": "チェックを入れてプロフィールURLを入力してください(https:// は不要)。チェックのない項目は表示されません。",
|
||||
"admin.enableAcfun": "AcFun を有効にする",
|
||||
"admin.enableBili": "Bilibili を有効にする",
|
||||
"admin.enableWeibo": "Weibo を有効にする",
|
||||
"admin.enableXiaohongshu": "小紅書 を有効にする",
|
||||
"admin.enableBlog": "個人ブログを有効にする",
|
||||
"admin.registerOnly": "登録ユーザーのみ質問を許可",
|
||||
"admin.updateHarassment": "迷惑行為対策を更新",
|
||||
"admin.globalBlockWords": "共通ブロックワード",
|
||||
"admin.globalBlockWordsHint": "ブロックワードは質問・チャット(相手からあなたへのメッセージ)・投票の投稿内容に適用されます。この設定は質問/チャット/投票の3つのタブで共有され、どこで変更してもすぐに反映されます。",
|
||||
"admin.updateBlockWords": "ブロックワードを保存",
|
||||
|
||||
// 審核の厳格度:質問 / 投票 / チャットで共通。判定規則は internal/security/censor/policy.go。
|
||||
"admin.moderationStrictness": "審核の厳格度",
|
||||
@@ -1054,36 +1057,36 @@ var jaDict = map[string]string{
|
||||
"stats.weekday.7": "日曜日",
|
||||
|
||||
// 質問箱オーナーのインサイト(/user/insights)
|
||||
"insights.title": "インサイト",
|
||||
"insights.heading": "あなたのインサイト",
|
||||
"insights.lead": "この数字はあなただけのものです。何人が質問箱を開いたか、いくつ質問が届いたか、まだ手つかずの質問がいくつあるか。すべて集計値で、訪問者や質問者の身元は一切含みません。",
|
||||
"insights.back": "設定に戻る",
|
||||
"insights.entryTitle": "インサイト",
|
||||
"insights.entryDesc": "質問箱に何人来たか、質問の対応状況を見る",
|
||||
"insights.summary": "ひと目で",
|
||||
"insights.noViews": "まだ訪問の記録がありません。誰かが質問箱を開くと数字が出はじめます。",
|
||||
"insights.today": "今日",
|
||||
"insights.week": "過去 7 日間",
|
||||
"insights.month": "過去 30 日間",
|
||||
"insights.newQuestions": "新着の質問",
|
||||
"insights.pv": "回表示",
|
||||
"insights.uv": "人",
|
||||
"insights.trendTitle": "過去 30 日間の閲覧推移",
|
||||
"insights.trendNote": "1 本が 1 日分。淡い部分が閲覧数、濃い部分がその日の重複を除いた訪問者数です。棒にカーソルを合わせると当日の閲覧/訪問者/質問数が出ます。",
|
||||
"insights.legendPV": "閲覧数(PV)",
|
||||
"insights.legendUV": "ユニーク訪問者(日ごとに重複排除)",
|
||||
"insights.legendHover": "カーソルで当日の内訳",
|
||||
"insights.hourTitle": "いつ来ているか",
|
||||
"insights.hourNote": "過去 30 日に届いた質問の時間帯分布。最も明るい棒が一番忙しい時間帯です。",
|
||||
"insights.funnelTitle": "質問の対応状況",
|
||||
"insights.funnelNote": "すべての質問を「回答済み/既読・未回答/未読」に分けたものです。",
|
||||
"insights.title": "インサイト",
|
||||
"insights.heading": "あなたのインサイト",
|
||||
"insights.lead": "この数字はあなただけのものです。何人が質問箱を開いたか、いくつ質問が届いたか、まだ手つかずの質問がいくつあるか。すべて集計値で、訪問者や質問者の身元は一切含みません。",
|
||||
"insights.back": "設定に戻る",
|
||||
"insights.entryTitle": "インサイト",
|
||||
"insights.entryDesc": "質問箱に何人来たか、質問の対応状況を見る",
|
||||
"insights.summary": "ひと目で",
|
||||
"insights.noViews": "まだ訪問の記録がありません。誰かが質問箱を開くと数字が出はじめます。",
|
||||
"insights.today": "今日",
|
||||
"insights.week": "過去 7 日間",
|
||||
"insights.month": "過去 30 日間",
|
||||
"insights.newQuestions": "新着の質問",
|
||||
"insights.pv": "回表示",
|
||||
"insights.uv": "人",
|
||||
"insights.trendTitle": "過去 30 日間の閲覧推移",
|
||||
"insights.trendNote": "1 本が 1 日分。淡い部分が閲覧数、濃い部分がその日の重複を除いた訪問者数です。棒にカーソルを合わせると当日の閲覧/訪問者/質問数が出ます。",
|
||||
"insights.legendPV": "閲覧数(PV)",
|
||||
"insights.legendUV": "ユニーク訪問者(日ごとに重複排除)",
|
||||
"insights.legendHover": "カーソルで当日の内訳",
|
||||
"insights.hourTitle": "いつ来ているか",
|
||||
"insights.hourNote": "過去 30 日に届いた質問の時間帯分布。最も明るい棒が一番忙しい時間帯です。",
|
||||
"insights.funnelTitle": "質問の対応状況",
|
||||
"insights.funnelNote": "すべての質問を「回答済み/既読・未回答/未読」に分けたものです。",
|
||||
"insights.funnelTotal": "すべての質問",
|
||||
"insights.funnelAnswered": "回答済み",
|
||||
"insights.funnelReadOnly": "既読・未回答",
|
||||
"insights.funnelUnread": "未読",
|
||||
"insights.answerRate": "回答率:回答済み ÷ 全質問",
|
||||
"insights.privacyTitle": "この数字について",
|
||||
"insights.privacyNote": "訪問統計は「ある日に何回来たか」だけを記録します。訪問者の識別子は日ごとに塩を変えた IP ハッシュで、IP・UA・閲覧ページは保存しません。そのため日をまたいで同一人物を紐付けることはできず、7 日/30 日の訪問者数は各日の重複排除後の合計です(同じ人が数日来るとその人数分カウントされます)。質問箱の持ち主自身のアクセスは含みません。",
|
||||
"insights.answerRate": "回答率:回答済み ÷ 全質問",
|
||||
"insights.privacyTitle": "この数字について",
|
||||
"insights.privacyNote": "訪問統計は「ある日に何回来たか」だけを記録します。訪問者の識別子は日ごとに塩を変えた IP ハッシュで、IP・UA・閲覧ページは保存しません。そのため日をまたいで同一人物を紐付けることはできず、7 日/30 日の訪問者数は各日の重複排除後の合計です(同じ人が数日来るとその人数分カウントされます)。質問箱の持ち主自身のアクセスは含みません。",
|
||||
|
||||
"insights.insight.empty": "まだデータがありません。最初の質問が届くか、誰かが質問箱を開くと表示されはじめます。",
|
||||
"insights.insight.weekViews": "過去 7 日間に %s 回の閲覧、%s 人の訪問者。",
|
||||
|
||||
Reference in New Issue
Block a user