Ctrl K
ComunidadGuías…

internal/domain/moderation_warning.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package domain

// This file implements the server-side text form of SCAM/FAKE marks in the profile description (About):
// official clients render a localized badge based on tg.User.scam / tg.Channel.scam, but a bare badge
// is often ignored by the audience of a self-hosted deployment; so the About returned by getFullUser / channels.getFullChannel /
// invite previews injects a platform warning on the first line, followed by the peer's own description.
//
// The warning text comes from TELESRV_SCAM_WARNING / TELESRV_FAKE_WARNING (see internal/config,
// injected at startup by cmd/telesrv/main.go), and an empty value uses the built-in English default — consistent with
// the .env.example note «Empty keeps built-in English defaults».
//
// The stored description is never rewritten: the warning exists only on the read-path projection, and after the owner edits
// the description the warning still reappears on the first line (semantic guard in rpc/moderation_flags_projection_test.go).

import (
	"strings"
	"sync/atomic"
)

// The built-in default text is a full warning sentence (rather than the official client's SCAM/FAKE badge word): the official client only
// draws a two-letter badge next to the name, with no readable explanation in the description; here "why it was flagged" is written directly
// into the first line of the description, consistent with the operator-overridable semantics in .env (empty value → the text below).
// Both use official wording: fake is impersonating a real person/well-known organization, scam is fraud and demanding money.
const (
	defaultScamProfileWarning = "⚠️ Warning: This account has received numerous complaints " +
		"related to fraud or attempts to impersonate an official account. Be cautious, " +
		"especially if you are asked for money."
	defaultFakeProfileWarning = "⚠️ Warning: Many users have reported that this account is " +
		"impersonating a well-known person or organization."
)

// Held in an atomic.Value, the same pattern as startup-time configuration such as officialSystemUserDisplayName:
// the projection path is read-only, avoiding a data race if runtime refresh is added later.
var (
	scamProfileWarning atomic.Value // string
	fakeProfileWarning atomic.Value // string
)

// SetModerationProfileWarning records the operator-configured warning text; called once at startup.
// An empty value (or pure whitespace) means use the built-in English default.
func SetModerationProfileWarning(scam, fake string) {
	scamProfileWarning.Store(strings.TrimSpace(scam))
	fakeProfileWarning.Store(strings.TrimSpace(fake))
}

// moderationProfileWarning returns the currently effective warning text; an unflagged peer returns an empty string.
// admin rejects setting both flags at once (ErrPeerModerationFlagsInvalid), so scam taking priority is enough.
func moderationProfileWarning(scam, fake bool) string {
	if scam {
		if text, ok := scamProfileWarning.Load().(string); ok && text != "" {
			return text
		}
		return defaultScamProfileWarning
	}
	if fake {
		if text, ok := fakeProfileWarning.Load().(string); ok && text != "" {
			return text
		}
		return defaultFakeProfileWarning
	}
	return ""
}

// ModerationProfileWarning prepends the platform warning to the peer's own description:
// when unflagged it returns about verbatim (zero allocation); when flagged it returns "warning\ndescription",
// and when the description is empty it returns only the warning. The separator is a single newline — About renders line by line in the client.
func ModerationProfileWarning(scam, fake bool, about string) string {
	warning := moderationProfileWarning(scam, fake)
	if warning == "" {
		return about
	}
	if about == "" {
		return warning
	}
	return warning + "\n" + about
}