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"`
|
Slowmode int `json:"slowmode_seconds,omitempty"`
|
||||||
CanSend bool `json:"can_send"`
|
CanSend bool `json:"can_send"`
|
||||||
CanConnect bool `json:"can_connect"`
|
CanConnect bool `json:"can_connect"`
|
||||||
|
// BackgroundFileID — фон комнаты: приходит и в READY, и в CHANNEL_UPDATE
|
||||||
|
// (AGENT.md 7.5), иначе после перезагрузки фон терялся бы до REST-запроса.
|
||||||
|
BackgroundFileID string `json:"background_file_id,omitempty"`
|
||||||
// Поля личных бесед (type = dm): собеседник и последнее сообщение.
|
// Поля личных бесед (type = dm): собеседник и последнее сообщение.
|
||||||
RecipientID string `json:"recipient_id,omitempty"`
|
RecipientID string `json:"recipient_id,omitempty"`
|
||||||
IconFileID string `json:"icon_file_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 {
|
if channel.GuildID != nil {
|
||||||
payload.GuildID = formatID(*channel.GuildID)
|
payload.GuildID = formatID(*channel.GuildID)
|
||||||
}
|
}
|
||||||
|
if channel.BackgroundFileID != nil {
|
||||||
|
payload.BackgroundFileID = formatID(*channel.BackgroundFileID)
|
||||||
|
}
|
||||||
if channel.ParentID != nil {
|
if channel.ParentID != nil {
|
||||||
payload.ParentID = formatID(*channel.ParentID)
|
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{}
|
categories := map[string]uint64{}
|
||||||
position := 0
|
position := 0
|
||||||
for _, channel := range template.Channels {
|
for _, channel := range template.Channels {
|
||||||
parentID := uint64(0)
|
if channel.Type != store.ChannelCategory {
|
||||||
if channel.Category != "" {
|
continue
|
||||||
id, ok := categories[channel.Category]
|
}
|
||||||
if !ok {
|
if _, exists := categories[channel.Name]; exists {
|
||||||
|
continue
|
||||||
|
}
|
||||||
created, err := s.store.CreateChannel(ctx, store.CreateChannelParams{
|
created, err := s.store.CreateChannel(ctx, store.CreateChannelParams{
|
||||||
GuildID: &guild.ID, Type: store.ChannelCategory,
|
GuildID: &guild.ID, Type: store.ChannelCategory,
|
||||||
Name: channel.Category, Position: position,
|
Name: channel.Name, Position: position,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return humaError(err)
|
return humaError(err)
|
||||||
}
|
}
|
||||||
categories[channel.Category] = created.ID
|
categories[channel.Name] = created.ID
|
||||||
position++
|
position++
|
||||||
id = created.ID
|
|
||||||
}
|
}
|
||||||
parentID = id
|
for _, channel := range template.Channels {
|
||||||
|
if channel.Type == store.ChannelCategory {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
params := store.CreateChannelParams{
|
params := store.CreateChannelParams{
|
||||||
GuildID: &guild.ID,
|
GuildID: &guild.ID,
|
||||||
@@ -177,7 +182,7 @@ func (s *Server) applyGuildTemplate(ctx context.Context, guild *store.Guild, tem
|
|||||||
Name: channel.Name,
|
Name: channel.Name,
|
||||||
Position: position,
|
Position: position,
|
||||||
}
|
}
|
||||||
if parentID != 0 && channel.Type != store.ChannelCategory {
|
if parentID, ok := categories[channel.Category]; ok {
|
||||||
params.ParentID = &parentID
|
params.ParentID = &parentID
|
||||||
}
|
}
|
||||||
if _, err := s.store.CreateChannel(ctx, params); err != nil {
|
if _, err := s.store.CreateChannel(ctx, params); err != nil {
|
||||||
|
|||||||
@@ -157,3 +157,36 @@ func contains(list []string, value string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
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