mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
Root cause: server's db.Role and db.VoiceState structs had no JSON tags, causing Go to serialize field names as PascalCase while the C# client expected snake_case. Every role deserialized with Id=0, crashing ToDictionary with "duplicate key: 0". - Add json tags to Role and VoiceState in Server/db/models.go - Change Disconnected event to carry reason string for diagnostics - Wire ErrorReceived in MainViewModel to show server-side WS errors - Fix MainWindow to surface WebSocket errors on MainPage (not ConnectPage) - Use _reconnectCts.Token for receive loop instead of caller's token - Make ToDictionary calls safe with TryAdd to prevent future crashes
152 lines
3.8 KiB
Go
152 lines
3.8 KiB
Go
package db
|
|
|
|
import "time"
|
|
|
|
// User represents a row in the users table.
|
|
type User struct {
|
|
ID int64
|
|
Username string
|
|
PasswordHash string
|
|
Avatar *string
|
|
RoleID int64
|
|
TOTPSecret *string
|
|
Status string
|
|
CreatedAt string
|
|
LastSeen *string
|
|
Banned bool
|
|
BanReason *string
|
|
BanExpires *string
|
|
}
|
|
|
|
// Session represents a row in the sessions table.
|
|
type Session struct {
|
|
ID int64
|
|
UserID int64
|
|
TokenHash string
|
|
Device string
|
|
IP string
|
|
CreatedAt string
|
|
LastUsed string
|
|
ExpiresAt string
|
|
}
|
|
|
|
// Invite represents a row in the invites table.
|
|
type Invite struct {
|
|
ID int64
|
|
Code string
|
|
CreatedBy int64
|
|
Uses int
|
|
MaxUses *int
|
|
ExpiresAt *string
|
|
Revoked bool
|
|
CreatedAt string
|
|
}
|
|
|
|
// Role represents a row in the roles table.
|
|
type Role struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
Color *string `json:"color"`
|
|
Permissions int64 `json:"permissions"`
|
|
Position int `json:"position"`
|
|
IsDefault bool `json:"is_default"`
|
|
}
|
|
|
|
// Channel represents a row in the channels table.
|
|
type Channel struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
Category string `json:"category"`
|
|
Topic string `json:"topic"`
|
|
Position int `json:"position"`
|
|
SlowMode int `json:"slow_mode"`
|
|
Archived bool `json:"archived"`
|
|
CreatedAt string `json:"created_at"`
|
|
VoiceMaxUsers int `json:"voice_max_users"`
|
|
VoiceQuality *string `json:"voice_quality,omitempty"`
|
|
MixingThreshold *int `json:"mixing_threshold,omitempty"`
|
|
VoiceMaxVideo int `json:"voice_max_video"`
|
|
}
|
|
|
|
// Message represents a row in the messages table.
|
|
type Message struct {
|
|
ID int64
|
|
ChannelID int64
|
|
UserID int64
|
|
Content string
|
|
ReplyTo *int64
|
|
EditedAt *string
|
|
Deleted bool
|
|
Pinned bool
|
|
Timestamp string
|
|
}
|
|
|
|
// MessageWithUser joins a Message with the author's public fields.
|
|
type MessageWithUser struct {
|
|
Message
|
|
Username string
|
|
Avatar *string
|
|
}
|
|
|
|
// ReactionCount is an aggregated reaction count for a single emoji.
|
|
type ReactionCount struct {
|
|
Emoji string
|
|
Count int
|
|
MeReacted bool
|
|
}
|
|
|
|
// MessageSearchResult is a row returned by the FTS5 message search.
|
|
type MessageSearchResult struct {
|
|
MessageID int64
|
|
ChannelID int64
|
|
ChannelName string
|
|
Username string
|
|
Content string
|
|
Timestamp string
|
|
}
|
|
|
|
// VoiceState represents a row in the voice_states table.
|
|
// It tracks which voice channel a user is in and their current audio state.
|
|
type VoiceState struct {
|
|
UserID int64 `json:"user_id"`
|
|
ChannelID int64 `json:"channel_id"`
|
|
Username string `json:"username"`
|
|
Muted bool `json:"muted"`
|
|
Deafened bool `json:"deafened"`
|
|
Speaking bool `json:"speaking"`
|
|
Camera bool `json:"camera"`
|
|
Screenshare bool `json:"screenshare"`
|
|
}
|
|
|
|
// ServerStats contains aggregate counts for the admin dashboard.
|
|
type ServerStats struct {
|
|
UserCount int64 `json:"user_count"`
|
|
MessageCount int64 `json:"message_count"`
|
|
ChannelCount int64 `json:"channel_count"`
|
|
InviteCount int64 `json:"invite_count"`
|
|
DBSizeBytes int64 `json:"db_size_bytes"`
|
|
}
|
|
|
|
// UserWithRole extends User with the name of the user's role.
|
|
type UserWithRole struct {
|
|
User
|
|
RoleName string `json:"role_name"`
|
|
}
|
|
|
|
// AuditEntry represents a single row from the audit_log table joined with the
|
|
// actor's username.
|
|
type AuditEntry struct {
|
|
ID int64 `json:"id"`
|
|
ActorID int64 `json:"actor_id"`
|
|
ActorName string `json:"actor_name"`
|
|
Action string `json:"action"`
|
|
TargetType string `json:"target_type"`
|
|
TargetID int64 `json:"target_id"`
|
|
Detail string `json:"detail"`
|
|
CreatedAt string `json:"created_at"`
|
|
}
|
|
|
|
// sessionTTL is the duration a session remains valid after creation.
|
|
const sessionTTL = 30 * 24 * time.Hour
|