feat: implement IRC numerics batch 2 — connection registration, channel ops, user queries
Add comprehensive IRC numeric reply support: Connection registration (001-005): - 002 RPL_YOURHOST, 003 RPL_CREATED, 004 RPL_MYINFO, 005 RPL_ISUPPORT - All sent automatically during session creation after RPL_WELCOME Server statistics (251-255): - RPL_LUSERCLIENT, RPL_LUSEROP, RPL_LUSERCHANNELS, RPL_LUSERME - Sent during connection registration and via LUSERS command Channel operations: - MODE command: query channel modes (324 RPL_CHANNELMODEIS, 329 RPL_CREATIONTIME) - MODE command: query user modes (221 RPL_UMODEIS) - NAMES command: query channel member list (353/366) - LIST command: list all channels (322 RPL_LIST, 323 end of list) User queries: - WHOIS command: 311/312/318/319 numerics - WHO command: 352 RPL_WHOREPLY, 315 RPL_ENDOFWHO Database additions: - GetChannelCount, ListAllChannelsWithCounts - GetChannelCreatedAt, GetSessionCreatedAt Also adds StartTime to Globals for RPL_CREATED and updates README with comprehensive documentation of all new commands and numerics. closes #52
This commit is contained in:
@@ -953,3 +953,125 @@ func (database *Database) GetSessionChannels(
|
||||
|
||||
return scanChannels(rows)
|
||||
}
|
||||
|
||||
// GetChannelCount returns the total number of channels.
|
||||
func (database *Database) GetChannelCount(
|
||||
ctx context.Context,
|
||||
) (int64, error) {
|
||||
var count int64
|
||||
|
||||
err := database.conn.QueryRowContext(
|
||||
ctx,
|
||||
"SELECT COUNT(*) FROM channels",
|
||||
).Scan(&count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf(
|
||||
"get channel count: %w", err,
|
||||
)
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// ChannelInfoFull contains extended channel information.
|
||||
type ChannelInfoFull struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Topic string `json:"topic"`
|
||||
MemberCount int64 `json:"memberCount"`
|
||||
}
|
||||
|
||||
// ListAllChannelsWithCounts returns every channel
|
||||
// with its member count.
|
||||
func (database *Database) ListAllChannelsWithCounts(
|
||||
ctx context.Context,
|
||||
) ([]ChannelInfoFull, error) {
|
||||
rows, err := database.conn.QueryContext(ctx,
|
||||
`SELECT c.id, c.name, c.topic,
|
||||
COUNT(cm.session_id) AS member_count
|
||||
FROM channels c
|
||||
LEFT JOIN channel_members cm
|
||||
ON cm.channel_id = c.id
|
||||
GROUP BY c.id
|
||||
ORDER BY c.name`)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"list channels with counts: %w", err,
|
||||
)
|
||||
}
|
||||
|
||||
defer func() { _ = rows.Close() }()
|
||||
|
||||
var out []ChannelInfoFull
|
||||
|
||||
for rows.Next() {
|
||||
var chanInfo ChannelInfoFull
|
||||
|
||||
err = rows.Scan(
|
||||
&chanInfo.ID, &chanInfo.Name,
|
||||
&chanInfo.Topic, &chanInfo.MemberCount,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"scan channel full: %w", err,
|
||||
)
|
||||
}
|
||||
|
||||
out = append(out, chanInfo)
|
||||
}
|
||||
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("rows error: %w", err)
|
||||
}
|
||||
|
||||
if out == nil {
|
||||
out = []ChannelInfoFull{}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetChannelCreatedAt returns the creation time of a
|
||||
// channel.
|
||||
func (database *Database) GetChannelCreatedAt(
|
||||
ctx context.Context,
|
||||
channelID int64,
|
||||
) (time.Time, error) {
|
||||
var createdAt time.Time
|
||||
|
||||
err := database.conn.QueryRowContext(
|
||||
ctx,
|
||||
"SELECT created_at FROM channels WHERE id = ?",
|
||||
channelID,
|
||||
).Scan(&createdAt)
|
||||
if err != nil {
|
||||
return time.Time{}, fmt.Errorf(
|
||||
"get channel created_at: %w", err,
|
||||
)
|
||||
}
|
||||
|
||||
return createdAt, nil
|
||||
}
|
||||
|
||||
// GetSessionCreatedAt returns the creation time of a
|
||||
// session.
|
||||
func (database *Database) GetSessionCreatedAt(
|
||||
ctx context.Context,
|
||||
sessionID int64,
|
||||
) (time.Time, error) {
|
||||
var createdAt time.Time
|
||||
|
||||
err := database.conn.QueryRowContext(
|
||||
ctx,
|
||||
"SELECT created_at FROM sessions WHERE id = ?",
|
||||
sessionID,
|
||||
).Scan(&createdAt)
|
||||
if err != nil {
|
||||
return time.Time{}, fmt.Errorf(
|
||||
"get session created_at: %w", err,
|
||||
)
|
||||
}
|
||||
|
||||
return createdAt, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user