Initial commit: JustAMessenger v0.1.0
Серверная часть (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 — спецификация протокола
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user