feat(guilds): оформление сервера — иконка, баннер, splash и акцентный цвет
Фаза 4 (AGENT.md 7.4): сервер можно оформить, поля в схеме были с Фазы 1, но
ручек и отдачи в API не было.
- `POST/DELETE /guilds/{id}/appearance/{icon|banner|splash}` (multipart,
MANAGE_GUILD, только изображения до 8 МБ): файл сохраняется назначением
`guild_icon|guild_banner|guild_splash`, предыдущий удаляется, пишется аудит
и уходит `GUILD_UPDATE`; ответ — обновлённый сервер;
- `PATCH /guilds/{id}` принимает `accent_color` (0 — цвет темы);
- оформление отдаётся в READY, в списке серверов, в детальной карточке и в
предпросмотре приглашения — клиенту не нужен отдельный запрос;
- анимированные GIF/APNG/WebP сохраняются как есть: изображения не
перекодируются, поэтому анимация не теряется;
- тесты: загрузка и очистка всех трёх видов, замена файла, запрет без
MANAGE_GUILD и без сессии, отказ для не-изображения, акцентный цвет.
This commit is contained in:
+15
-10
@@ -67,16 +67,21 @@ type ReadyUser struct {
|
||||
}
|
||||
|
||||
type ReadyGuild struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
OwnerID string `json:"owner_id"`
|
||||
IsMain bool `json:"is_main"`
|
||||
Channels []ReadyChannel `json:"channels"`
|
||||
Roles []ReadyRole `json:"roles"`
|
||||
MemberIDs []string `json:"member_ids"`
|
||||
MyRoles []string `json:"my_role_ids"`
|
||||
MyNickname string `json:"my_nickname,omitempty"`
|
||||
MyPerms []string `json:"my_permissions"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
OwnerID string `json:"owner_id"`
|
||||
IsMain bool `json:"is_main"`
|
||||
// Оформление сервера (AGENT.md 7.4): иконка, баннер, splash и акцент.
|
||||
IconFileID string `json:"icon_file_id,omitempty"`
|
||||
BannerFileID string `json:"banner_file_id,omitempty"`
|
||||
SplashFileID string `json:"splash_file_id,omitempty"`
|
||||
AccentColor int64 `json:"accent_color,omitempty"`
|
||||
Channels []ReadyChannel `json:"channels"`
|
||||
Roles []ReadyRole `json:"roles"`
|
||||
MemberIDs []string `json:"member_ids"`
|
||||
MyRoles []string `json:"my_role_ids"`
|
||||
MyNickname string `json:"my_nickname,omitempty"`
|
||||
MyPerms []string `json:"my_permissions"`
|
||||
// Emojis — кастомные эмодзи сервера (AGENT.md 7.12).
|
||||
Emojis []ReadyEmoji `json:"emojis"`
|
||||
// VoiceStates — кто находится в голосовых комнатах (AGENT.md 7.14).
|
||||
|
||||
+24
-12
@@ -128,18 +128,22 @@ func (s *Snapshot) Build(ctx context.Context, user *store.User) (*Ready, error)
|
||||
|
||||
func (s *Snapshot) buildGuild(ctx context.Context, guild store.Guild, user *store.User, resolved permissions.Resolved) (ReadyGuild, error) {
|
||||
readyGuild := ReadyGuild{
|
||||
ID: formatID(guild.ID),
|
||||
Name: guild.Name,
|
||||
OwnerID: formatID(guild.OwnerID),
|
||||
IsMain: guild.IsMain,
|
||||
Channels: []ReadyChannel{},
|
||||
Roles: []ReadyRole{},
|
||||
MemberIDs: []string{},
|
||||
MyRoles: []string{},
|
||||
MyPerms: []string{},
|
||||
Emojis: []ReadyEmoji{},
|
||||
VoiceStates: []ReadyVoiceState{},
|
||||
Sounds: []ReadySound{},
|
||||
ID: formatID(guild.ID),
|
||||
Name: guild.Name,
|
||||
OwnerID: formatID(guild.OwnerID),
|
||||
IsMain: guild.IsMain,
|
||||
AccentColor: guild.AccentColor,
|
||||
IconFileID: optionalFormatID(guild.IconFileID),
|
||||
BannerFileID: optionalFormatID(guild.BannerFileID),
|
||||
SplashFileID: optionalFormatID(guild.SplashFileID),
|
||||
Channels: []ReadyChannel{},
|
||||
Roles: []ReadyRole{},
|
||||
MemberIDs: []string{},
|
||||
MyRoles: []string{},
|
||||
MyPerms: []string{},
|
||||
Emojis: []ReadyEmoji{},
|
||||
VoiceStates: []ReadyVoiceState{},
|
||||
Sounds: []ReadySound{},
|
||||
}
|
||||
|
||||
// Кастомные эмодзи сервера: клиент показывает их в пикере и в тексте.
|
||||
@@ -362,6 +366,14 @@ func visibleStatus(status string, lastSeen *time.Time) string {
|
||||
return status
|
||||
}
|
||||
|
||||
// optionalFormatID отдаёт идентификатор файла или пустую строку.
|
||||
func optionalFormatID(id *uint64) string {
|
||||
if id == nil || *id == 0 {
|
||||
return ""
|
||||
}
|
||||
return formatID(*id)
|
||||
}
|
||||
|
||||
func formatID(id uint64) string {
|
||||
if id == 0 {
|
||||
return ""
|
||||
|
||||
Reference in New Issue
Block a user