fix(guilds): фон комнаты в READY и без дублей категорий в шаблонах
- ReadyChannel отдаёт background_file_id: после перезагрузки фон комнаты больше не теряется до REST-запроса (AGENT.md 7.5) - шаблон больше не создаёт категории дважды: они перечислены в шаблоне и раньше создавались ещё и по ссылке из комнаты - тест: структура «Сообщества» ровно 7 комнат без повторов
This commit is contained in:
@@ -132,6 +132,9 @@ type ReadyChannel struct {
|
||||
Slowmode int `json:"slowmode_seconds,omitempty"`
|
||||
CanSend bool `json:"can_send"`
|
||||
CanConnect bool `json:"can_connect"`
|
||||
// BackgroundFileID — фон комнаты: приходит и в READY, и в CHANNEL_UPDATE
|
||||
// (AGENT.md 7.5), иначе после перезагрузки фон терялся бы до REST-запроса.
|
||||
BackgroundFileID string `json:"background_file_id,omitempty"`
|
||||
// Поля личных бесед (type = dm): собеседник и последнее сообщение.
|
||||
RecipientID string `json:"recipient_id,omitempty"`
|
||||
IconFileID string `json:"icon_file_id,omitempty"`
|
||||
|
||||
@@ -271,6 +271,9 @@ func channelPayload(channel store.Channel, canSend, canConnect bool) ReadyChanne
|
||||
if channel.GuildID != nil {
|
||||
payload.GuildID = formatID(*channel.GuildID)
|
||||
}
|
||||
if channel.BackgroundFileID != nil {
|
||||
payload.BackgroundFileID = formatID(*channel.BackgroundFileID)
|
||||
}
|
||||
if channel.ParentID != nil {
|
||||
payload.ParentID = formatID(*channel.ParentID)
|
||||
}
|
||||
|
||||
@@ -150,26 +150,31 @@ func (s *Server) applyGuildTemplate(ctx context.Context, guild *store.Guild, tem
|
||||
}
|
||||
}
|
||||
|
||||
// Категории создаются до комнат: комнаты ссылаются на них через parent_id.
|
||||
// Категории создаём первыми: комнаты ссылаются на них через parent_id.
|
||||
// В шаблоне категория перечислена отдельной записью, поэтому повторно её
|
||||
// не создаём — только запоминаем идентификатор.
|
||||
categories := map[string]uint64{}
|
||||
position := 0
|
||||
for _, channel := range template.Channels {
|
||||
parentID := uint64(0)
|
||||
if channel.Category != "" {
|
||||
id, ok := categories[channel.Category]
|
||||
if !ok {
|
||||
if channel.Type != store.ChannelCategory {
|
||||
continue
|
||||
}
|
||||
if _, exists := categories[channel.Name]; exists {
|
||||
continue
|
||||
}
|
||||
created, err := s.store.CreateChannel(ctx, store.CreateChannelParams{
|
||||
GuildID: &guild.ID, Type: store.ChannelCategory,
|
||||
Name: channel.Category, Position: position,
|
||||
Name: channel.Name, Position: position,
|
||||
})
|
||||
if err != nil {
|
||||
return humaError(err)
|
||||
}
|
||||
categories[channel.Category] = created.ID
|
||||
categories[channel.Name] = created.ID
|
||||
position++
|
||||
id = created.ID
|
||||
}
|
||||
parentID = id
|
||||
for _, channel := range template.Channels {
|
||||
if channel.Type == store.ChannelCategory {
|
||||
continue
|
||||
}
|
||||
params := store.CreateChannelParams{
|
||||
GuildID: &guild.ID,
|
||||
@@ -177,7 +182,7 @@ func (s *Server) applyGuildTemplate(ctx context.Context, guild *store.Guild, tem
|
||||
Name: channel.Name,
|
||||
Position: position,
|
||||
}
|
||||
if parentID != 0 && channel.Type != store.ChannelCategory {
|
||||
if parentID, ok := categories[channel.Category]; ok {
|
||||
params.ParentID = &parentID
|
||||
}
|
||||
if _, err := s.store.CreateChannel(ctx, params); err != nil {
|
||||
|
||||
@@ -157,3 +157,36 @@ func contains(list []string, value string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestGuildFromTemplateCreatesNoDuplicates(t *testing.T) {
|
||||
srv, _ := newTestServer(t)
|
||||
owner := registerAndLogin(t, srv, "tpl_dup", "tpl-dup@example.com")
|
||||
created := doJSON(t, srv, http.MethodPost, "/api/v1/guilds",
|
||||
`{"name":"Дубли","template_id":"community"}`, owner)
|
||||
guildID := decodeResponse[struct {
|
||||
Guild struct {
|
||||
ID string `json:"id"`
|
||||
} `json:"guild"`
|
||||
}](t, created).Guild.ID
|
||||
|
||||
channels := doJSON(t, srv, http.MethodGet, "/api/v1/guilds/"+guildID+"/channels", "", owner)
|
||||
list := decodeResponse[struct {
|
||||
Channels []struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
} `json:"channels"`
|
||||
}](t, channels)
|
||||
seen := map[string]int{}
|
||||
for _, channel := range list.Channels {
|
||||
seen[channel.Type+":"+channel.Name]++
|
||||
}
|
||||
for key, count := range seen {
|
||||
if count > 1 {
|
||||
t.Fatalf("комната %s создана %d раза", key, count)
|
||||
}
|
||||
}
|
||||
// «Сообщество»: 2 категории, 4 текстовые и 1 голосовая.
|
||||
if len(list.Channels) != 7 {
|
||||
t.Fatalf("комнат %d, ожидалось 7", len(list.Channels))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user