096c4d0a2d
Серверная часть (Go): - WebSocket сервер с бинарным протоколом - XChaCha20-Poly1305 шифрование - zstd сжатие с дедупликацией (64KB чанки) - SQLite хранилище (WAL режим) - Управление гильдиями, каналами, ролями - Федерация между серверами (ed25519) - REST API + WebSocket endpoints Клиентская часть (Flutter): - Material Design 3 тёмная тема (Discord-like) - WebSocket соединение с сервером - Экраны: сплэш, логин, домашний, гильдии, чат - Модели: пользователи, гильдии, каналы, сообщения, роли - Сервисы: соединение, API, криптография, тема - Виджеты: иконки гильдий, сообщения, ввод чата - Web сборка (PWA) Документация: - AGENTS.md — контекст для ИИ ассистентов - docs/protocol.md — спецификация протокола
136 lines
3.1 KiB
Go
136 lines
3.1 KiB
Go
package channel
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/justamessenger/server/internal/database"
|
|
"github.com/justamessenger/server/internal/models"
|
|
)
|
|
|
|
type Manager struct {
|
|
db *database.DB
|
|
}
|
|
|
|
func NewManager(db *database.DB) *Manager {
|
|
return &Manager{db: db}
|
|
}
|
|
|
|
func (m *Manager) Create(guildID, categoryID, name, channelType, topic string, position int) (*models.Channel, error) {
|
|
id := uuid.New().String()
|
|
_, err := m.db.Exec(
|
|
`INSERT INTO channels (id, guild_id, category_id, name, type, topic, position)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
id, guildID, categoryID, name, channelType, topic, position,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return m.Get(id)
|
|
}
|
|
|
|
func (m *Manager) Get(id string) (*models.Channel, error) {
|
|
row := m.db.QueryRow(
|
|
`SELECT id, guild_id, category_id, name, type, topic, position, created_at
|
|
FROM channels WHERE id = ?`, id,
|
|
)
|
|
c := &models.Channel{}
|
|
err := row.Scan(&c.ID, &c.GuildID, &c.Category, &c.Name, &c.Type, &c.Topic, &c.Position, &c.CreatedAt)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
func (m *Manager) ListByGuild(guildID string) ([]*models.Channel, error) {
|
|
rows, err := m.db.Query(
|
|
`SELECT id, guild_id, category_id, name, type, topic, position, created_at
|
|
FROM channels WHERE guild_id = ? ORDER BY position`, guildID,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var channels []*models.Channel
|
|
for rows.Next() {
|
|
c := &models.Channel{}
|
|
if err := rows.Scan(&c.ID, &c.GuildID, &c.Category, &c.Name, &c.Type, &c.Topic, &c.Position, &c.CreatedAt); err != nil {
|
|
return nil, err
|
|
}
|
|
channels = append(channels, c)
|
|
}
|
|
return channels, nil
|
|
}
|
|
|
|
func (m *Manager) Update(id, name, topic string, position int) error {
|
|
result, err := m.db.Exec(
|
|
`UPDATE channels SET name = ?, topic = ?, position = ? WHERE id = ?`,
|
|
name, topic, position, id,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
affected, _ := result.RowsAffected()
|
|
if affected == 0 {
|
|
return errors.New("channel not found")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *Manager) Delete(id string) error {
|
|
result, err := m.db.Exec(`DELETE FROM channels WHERE id = ?`, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
affected, _ := result.RowsAffected()
|
|
if affected == 0 {
|
|
return errors.New("channel not found")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *Manager) CreateCategory(guildID, name string, position int) (string, error) {
|
|
id := uuid.New().String()
|
|
_, err := m.db.Exec(
|
|
`INSERT INTO categories (id, guild_id, name, position) VALUES (?, ?, ?, ?)`,
|
|
id, guildID, name, position,
|
|
)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return id, nil
|
|
}
|
|
|
|
func (m *Manager) ListCategories(guildID string) ([]*struct {
|
|
ID string
|
|
Name string
|
|
Position int
|
|
}, error) {
|
|
rows, err := m.db.Query(
|
|
`SELECT id, name, position FROM categories WHERE guild_id = ? ORDER BY position`, guildID,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var cats []*struct {
|
|
ID string
|
|
Name string
|
|
Position int
|
|
}
|
|
for rows.Next() {
|
|
var c struct {
|
|
ID string
|
|
Name string
|
|
Position int
|
|
}
|
|
if err := rows.Scan(&c.ID, &c.Name, &c.Position); err != nil {
|
|
return nil, err
|
|
}
|
|
cats = append(cats, &c)
|
|
}
|
|
return cats, nil
|
|
}
|