feat(ads): server-driven ad-banner backend, wire & admin console (PR1)
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 49s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m12s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 49s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m12s
Turn the gated-off mock banner into a real advertising subsystem (backend + admin half; the UI rotation lands in PR2). - internal/ads: campaigns (percent weight + validity window; a perpetual, undeletable default that fills the remainder up to 100%), 1..N bilingual messages (en+ru), global display timings; ActiveSet computes the window-filtered, default-remainder, GCD-reduced, language-resolved rotation feed. Smooth-weighted-round-robin math is unit-tested. - migration 00006 (+ jetgen): ad_campaigns / ad_messages / ad_settings, seeded default campaign + house message + default timings. - eligibility = !paid_account && hint_balance==0 && !no_banner role (new role; guests qualify). The resolved feed rides the profile.get response (no new RPC, works for guests, nothing distinct to filter); language by service_language. - live update: a notify `banner` sub-kind (re-poll signal) published when an operator grants hints or grants/revokes no_banner, so the client shows/hides in place. - admin console /_gm/banners (+ /_gm/banner-settings): campaign + message CRUD with reorder, default protection, clamped timings. - wire: fbs BannerInfo/BannerCampaign on Profile; gateway transcode forwards it. - docs: ARCHITECTURE §10, FUNCTIONAL (+ _ru), backend README, PRERELEASE tracker (incl. the deferred app.load aggregator note).
This commit is contained in:
@@ -372,6 +372,58 @@ type MessageView struct {
|
||||
Back string
|
||||
}
|
||||
|
||||
// BannersView is the advertising-campaign list page.
|
||||
type BannersView struct {
|
||||
Items []BannerCampaignRow
|
||||
}
|
||||
|
||||
// BannerCampaignRow is one campaign in the list. Window is a human-readable
|
||||
// validity window ("perpetual" for the default); ActiveNow reports whether it
|
||||
// would rotate right now (enabled and within its window).
|
||||
type BannerCampaignRow struct {
|
||||
ID string
|
||||
Name string
|
||||
Weight int
|
||||
IsDefault bool
|
||||
Enabled bool
|
||||
Window string
|
||||
Messages int
|
||||
ActiveNow bool
|
||||
}
|
||||
|
||||
// BannerDetailView is the campaign detail/edit page. StartsAt/EndsAt are the
|
||||
// "YYYY-MM-DDTHH:MM" (UTC) values for the datetime-local inputs, empty when open.
|
||||
type BannerDetailView struct {
|
||||
ID string
|
||||
Name string
|
||||
Weight int
|
||||
IsDefault bool
|
||||
Enabled bool
|
||||
StartsAt string
|
||||
EndsAt string
|
||||
Messages []BannerMessageRow
|
||||
}
|
||||
|
||||
// BannerMessageRow is one bilingual message of a campaign. First/Last drive the
|
||||
// reorder buttons (disabled at the ends).
|
||||
type BannerMessageRow struct {
|
||||
ID string
|
||||
BodyEn string
|
||||
BodyRu string
|
||||
First bool
|
||||
Last bool
|
||||
}
|
||||
|
||||
// BannerSettingsView is the global display-timings form.
|
||||
type BannerSettingsView struct {
|
||||
HoldMs int
|
||||
EdgePauseMs int
|
||||
ScrollPxPerSec int
|
||||
FadeOutMs int
|
||||
GapMs int
|
||||
FadeInMs int
|
||||
}
|
||||
|
||||
// FeedbackView is the paginated user-feedback queue. Status is the active
|
||||
// unread/read/archived filter; NameMask/ExtMask are the sender glob filters;
|
||||
// UserID pins the list to one account (the per-user link from /users);
|
||||
|
||||
Reference in New Issue
Block a user