fix v15
This commit is contained in:
+66
-12
@@ -55,6 +55,7 @@ var Unrestrict = &cli.Command{
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "email", Usage: "Email of the user"},
|
||||
&cli.StringFlag{Name: "domain", Usage: "Custom domain of the user"},
|
||||
&cli.BoolFlag{Name: "no-notify", Usage: "Do not email the lift notice to the user"},
|
||||
},
|
||||
Action: runUnrestrict,
|
||||
}
|
||||
@@ -247,23 +248,65 @@ func notifyRestrictionOwner(user *db.User, level string, expires time.Time) {
|
||||
RulesURL: strings.TrimRight(conf.App.ExternalURL, "/") + "/rules",
|
||||
Appeal: i18n.T(lang, "mail.restriction.appeal"),
|
||||
}
|
||||
// 加超时:SMTP 不可达时 gomail 的裸 Dial 会一直等到系统 TCP 超时(可达两分钟),
|
||||
// 运营者站在终端前会以为命令卡死。超时只影响通知,不影响已写入的处置。
|
||||
reportNoticeResult(user, sendNotice(notice), "处置已生效")
|
||||
}
|
||||
|
||||
// notifyRestrictionLifted 告知箱主「限制已解除」。
|
||||
//
|
||||
// 与处置通知同等重要:只通知「你被罚了」而不通知「已经解除」,用户会一直以为还在限制里,
|
||||
// 既不敢发内容,也可能反复来问。这封信也顺带说明「私密内容不会自动恢复」——
|
||||
// 否则他会以为解禁后一切照旧。
|
||||
func notifyRestrictionLifted(user *db.User, level string) {
|
||||
if user.Email == "" {
|
||||
fmt.Println("(该账号没有邮箱,跳过解除通知)")
|
||||
return
|
||||
}
|
||||
|
||||
lang := user.Language
|
||||
if lang == "" {
|
||||
lang = conf.App.DefaultLang
|
||||
}
|
||||
levelDesc := i18n.T(lang, "restriction.level."+level)
|
||||
notice := mail.RestrictionNotice{
|
||||
To: user.Email,
|
||||
Heading: i18n.T(lang, "mail.unrestrict.heading"),
|
||||
Greeting: i18n.T(lang, "mail.restriction.greeting", user.Name),
|
||||
Body: i18n.T(lang, "mail.unrestrict.body", user.Domain, levelDesc),
|
||||
Note: i18n.T(lang, "mail.unrestrict.note"),
|
||||
RulesText: i18n.T(lang, "mail.restriction.rules"),
|
||||
RulesURL: strings.TrimRight(conf.App.ExternalURL, "/") + "/rules",
|
||||
// 解除通知不需要申诉入口(Appeal 留空,模板会整段省略)。
|
||||
}
|
||||
reportNoticeResult(user, sendNotice(notice), "解除已生效")
|
||||
}
|
||||
|
||||
// sendNotice 发送一封通知邮件,带 20 秒超时。
|
||||
//
|
||||
// 为什么要超时:gomail 这版没有 Timeout 字段,裸 Dial 会一直等到系统 TCP 超时(可达两分钟),
|
||||
// 运营者站在终端前会以为命令卡死。通知失败不影响已经写入的处置结果。
|
||||
func sendNotice(notice mail.RestrictionNotice) error {
|
||||
done := make(chan error, 1)
|
||||
go func() { done <- mail.SendRestrictionNoticeMail(notice) }()
|
||||
select {
|
||||
case err := <-done:
|
||||
if err != nil {
|
||||
logrus.WithError(err).WithField("user_id", user.ID).Warn("处置通知邮件发送失败(处置已生效)")
|
||||
fmt.Println("⚠️ 通知邮件发送失败(处置已生效)。请检查 [mail] 配置,或用 --no-notify 跳过通知。")
|
||||
return
|
||||
}
|
||||
return err
|
||||
case <-time.After(20 * time.Second):
|
||||
logrus.WithField("user_id", user.ID).Warn("处置通知邮件发送超时(处置已生效)")
|
||||
fmt.Println("⚠️ 通知邮件发送超时(处置已生效)。请检查 SMTP 配置。")
|
||||
return errors.New("发送通知邮件超时")
|
||||
}
|
||||
}
|
||||
|
||||
// reportNoticeResult 统一输出通知结果(成功/失败都不影响已生效的处置)。
|
||||
func reportNoticeResult(user *db.User, err error, action string) {
|
||||
if err != nil {
|
||||
logrus.WithError(err).WithField("user_id", user.ID).Warn("通知邮件发送失败(" + action + ")")
|
||||
fmt.Printf("⚠️ 通知邮件发送失败(%s)。请检查 [mail] 配置,或用 --no-notify 跳过通知。\n", action)
|
||||
return
|
||||
}
|
||||
fmt.Printf("已发送处置通知邮件至 %s(语言 %s)\n", user.Email, i18n.Resolve(lang))
|
||||
lang := user.Language
|
||||
if lang == "" {
|
||||
lang = conf.App.DefaultLang
|
||||
}
|
||||
fmt.Printf("已发送通知邮件至 %s(语言 %s)\n", user.Email, i18n.Resolve(lang))
|
||||
}
|
||||
|
||||
func runUnrestrict(ctx *cli.Context) error {
|
||||
@@ -277,7 +320,14 @@ func runUnrestrict(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
affected, err := db.NewRestrictionsStore(database).RevokeActive(ctx.Context, user.ID)
|
||||
store := db.NewRestrictionsStore(database)
|
||||
// 先取级别:撤销之后就读不到了,而通知邮件需要写明解除的是哪一级。
|
||||
level, _, err := store.ActiveLevel(ctx.Context, user.ID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "query active restriction")
|
||||
}
|
||||
|
||||
affected, err := store.RevokeActive(ctx.Context, user.ID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "revoke restrictions")
|
||||
}
|
||||
@@ -287,8 +337,12 @@ func runUnrestrict(ctx *cli.Context) error {
|
||||
fmt.Println("没有生效中的处置,无需操作")
|
||||
return nil
|
||||
}
|
||||
logrus.WithFields(logrus.Fields{"user_id": user.ID, "count": affected}).Info("已撤销处置")
|
||||
logrus.WithFields(logrus.Fields{"user_id": user.ID, "count": affected, "level": level}).Info("已撤销处置")
|
||||
fmt.Printf("已撤销 %d 条生效中的处置\n", affected)
|
||||
|
||||
if !ctx.Bool("no-notify") && level != "" {
|
||||
notifyRestrictionLifted(user, string(level))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -440,6 +440,11 @@ var enDict = map[string]string{
|
||||
"mail.restriction.rules": "Read the community rules and enforcement policy",
|
||||
"mail.restriction.appeal": "If you believe this is a mistake, contact the site operator through the footer link and we will review it.",
|
||||
|
||||
// 解除处置通知(同一封模板,文案不同)
|
||||
"mail.unrestrict.heading": "Your question box restriction has been lifted",
|
||||
"mail.unrestrict.body": "The restriction on your question box @%s (%s) has been lifted and the related features are available again.",
|
||||
"mail.unrestrict.note": "The enforcement record is kept for audit. Content that was set private is not restored automatically; set it back to public item by item from your dashboard.",
|
||||
|
||||
// 处置级别名称(邮件与文案共用)
|
||||
"restriction.level.L1": "Stop distribution",
|
||||
"restriction.level.L2": "Narrow publishing",
|
||||
|
||||
@@ -440,6 +440,11 @@ var jaDict = map[string]string{
|
||||
"mail.restriction.rules": "コミュニティルールと対応方針を見る",
|
||||
"mail.restriction.appeal": "誤りだと思われる場合は、フッターの「管理人に連絡」からご連絡ください。確認のうえ対応します。",
|
||||
|
||||
// 解除处置通知(同一封模板,文案不同)
|
||||
"mail.unrestrict.heading": "質問箱の制限が解除されました",
|
||||
"mail.unrestrict.body": "あなたの質問箱 @%s の制限(%s)が解除され、関連する機能が利用可能になりました。",
|
||||
"mail.unrestrict.note": "対応の記録は監査用に保持されます。非公開にされた内容は自動では戻りません。管理画面から個別に公開へ戻してください。",
|
||||
|
||||
// 处置级别名称(邮件与文案共用)
|
||||
"restriction.level.L1": "配信停止",
|
||||
"restriction.level.L2": "公開の縮小",
|
||||
|
||||
@@ -440,6 +440,11 @@ var zhCNDict = map[string]string{
|
||||
"mail.restriction.rules": "查看社区规则与处置说明",
|
||||
"mail.restriction.appeal": "如果你认为处置有误,请通过站点页脚的「找站长」联系我们,我们会复核。",
|
||||
|
||||
// 解除处置通知(同一封模板,文案不同)
|
||||
"mail.unrestrict.heading": "你的提问箱限制已解除",
|
||||
"mail.unrestrict.body": "你的提问箱 @%s 的限制(%s)已解除,相关功能已恢复。",
|
||||
"mail.unrestrict.note": "处置记录会保留用于审计;此前被转为私密的内容不会自动恢复,需要你在后台逐条重新设为公开。",
|
||||
|
||||
// 处置级别名称(邮件与文案共用)
|
||||
"restriction.level.L1": "停止分发",
|
||||
"restriction.level.L2": "收窄公开",
|
||||
|
||||
@@ -440,6 +440,11 @@ var zhTWDict = map[string]string{
|
||||
"mail.restriction.rules": "檢視社群規則與處置說明",
|
||||
"mail.restriction.appeal": "如果你認為處置有誤,請透過頁尾的「找站長」聯絡我們,我們會複核。",
|
||||
|
||||
// 解除处置通知(同一封模板,文案不同)
|
||||
"mail.unrestrict.heading": "你的提問箱限制已解除",
|
||||
"mail.unrestrict.body": "你的提問箱 @%s 的限制(%s)已解除,相關功能已恢復。",
|
||||
"mail.unrestrict.note": "處置紀錄會保留用於稽核;先前被轉為私密的內容不會自動恢復,需要你在後台逐條重新設為公開。",
|
||||
|
||||
// 处置级别名称(邮件与文案共用)
|
||||
"restriction.level.L1": "停止分發",
|
||||
"restriction.level.L2": "收窄公開",
|
||||
|
||||
Reference in New Issue
Block a user