173 lines
7.6 KiB
Nu
Executable File
173 lines
7.6 KiB
Nu
Executable File
#!/usr/bin/env nu
|
|
|
|
let DATABASE_URL = $env.DATABASE_URL
|
|
|
|
# Fetch all messages, optionally filtered by channel
|
|
def messages [channel_id?: int] {
|
|
let query = if ($channel_id | is-empty) {
|
|
"COPY (SELECT m.id, m.channel_id, m.user_id, u.username, m.content, m.created_at, m.updated_at, m.is_edited FROM messages m JOIN users u ON m.user_id = u.id ORDER BY m.created_at DESC) TO STDOUT CSV HEADER;"
|
|
} else {
|
|
$"COPY \(SELECT m.id, m.channel_id, m.user_id, u.username, m.content, m.created_at, m.updated_at, m.is_edited FROM messages m JOIN users u ON m.user_id = u.id WHERE m.channel_id = ($channel_id) ORDER BY m.created_at DESC\) TO STDOUT CSV HEADER;"
|
|
}
|
|
|
|
psql $DATABASE_URL -c $query | from csv
|
|
}
|
|
|
|
# Fetch all users
|
|
def users [] {
|
|
psql $DATABASE_URL -c "COPY (SELECT id, username, display_name, email, twofa_enabled, created_at, updated_at FROM users ORDER BY created_at DESC) TO STDOUT CSV HEADER;"
|
|
| from csv | print
|
|
}
|
|
|
|
# Fetch specific user by ID or username
|
|
def user [identifier: string] {
|
|
let query = if ($identifier | into int | is-not-empty) {
|
|
$"COPY \(SELECT id, username, display_name, email, twofa_enabled, created_at, updated_at FROM users WHERE id = ($identifier)\) TO STDOUT CSV HEADER;"
|
|
} else {
|
|
$"COPY \(SELECT id, username, display_name, email, twofa_enabled, created_at, updated_at FROM users WHERE username = '($identifier)'\) TO STDOUT CSV HEADER;"
|
|
}
|
|
|
|
psql $DATABASE_URL -c $query | from csv
|
|
}
|
|
|
|
# Fetch all channels
|
|
def channels [] {
|
|
psql $DATABASE_URL -c "COPY (SELECT c.id, c.name, c.created_at, c.updated_at, COUNT(m.id) as message_count FROM channels c LEFT JOIN messages m ON c.id = m.channel_id GROUP BY c.id ORDER BY c.created_at DESC) TO STDOUT CSV HEADER;"
|
|
| from csv | print
|
|
}
|
|
|
|
# Fetch specific channel by ID
|
|
def channel [channel_id: int] {
|
|
psql $DATABASE_URL -c $"COPY \(SELECT c.id, c.name, c.created_at, c.updated_at, COUNT\(m.id\) as message_count FROM channels c LEFT JOIN messages m ON c.id = m.channel_id WHERE c.id = ($channel_id) GROUP BY c.id\) TO STDOUT CSV HEADER;"
|
|
| from csv
|
|
}
|
|
|
|
# Fetch all sessions
|
|
def sessions [] {
|
|
psql $DATABASE_URL -c "COPY (SELECT s.id, s.user_id, u.username, s.token, s.created_at, s.expires_at FROM sessions s JOIN users u ON s.user_id = u.id ORDER BY s.created_at DESC) TO STDOUT CSV HEADER;"
|
|
| from csv | print
|
|
}
|
|
|
|
# Fetch active sessions only
|
|
def active-sessions [] {
|
|
psql $DATABASE_URL -c "COPY (SELECT s.id, s.user_id, u.username, s.token, s.created_at, s.expires_at FROM sessions s JOIN users u ON s.user_id = u.id WHERE s.expires_at > NOW() ORDER BY s.created_at DESC) TO STDOUT CSV HEADER;"
|
|
| from csv | print
|
|
}
|
|
|
|
# Fetch all access codes
|
|
def access-codes [] {
|
|
psql $DATABASE_URL -c "COPY (SELECT ac.id, ac.creator_id, u.username as creator, ac.code, ac.name, ac.uses, ac.max_uses, ac.created_at, ac.expires_at FROM access_codes ac JOIN users u ON ac.creator_id = u.id ORDER BY ac.created_at DESC) TO STDOUT CSV HEADER;"
|
|
| from csv | print
|
|
}
|
|
|
|
# Fetch valid (non-expired, not fully used) access codes
|
|
def valid-access-codes [] {
|
|
psql $DATABASE_URL -c "COPY (SELECT ac.id, ac.creator_id, u.username as creator, ac.code, ac.name, ac.uses, ac.max_uses, ac.created_at, ac.expires_at FROM access_codes ac JOIN users u ON ac.creator_id = u.id WHERE ac.expires_at > NOW() AND ac.uses < ac.max_uses ORDER BY ac.created_at DESC) TO STDOUT CSV HEADER;"
|
|
| from csv | print
|
|
}
|
|
|
|
# Fetch message attachments
|
|
def attachments [message_id?: int] {
|
|
let query = if ($message_id | is-empty) {
|
|
"COPY (SELECT a.id, a.message_id, a.path, m.content as message_content, u.username FROM attachments a JOIN messages m ON a.message_id = m.id JOIN users u ON m.user_id = u.id ORDER BY a.id DESC) TO STDOUT CSV HEADER;"
|
|
} else {
|
|
$"COPY \(SELECT a.id, a.message_id, a.path, m.content as message_content FROM attachments a JOIN messages m ON a.message_id = m.id WHERE a.message_id = ($message_id)\) TO STDOUT CSV HEADER;"
|
|
}
|
|
|
|
psql $DATABASE_URL -c $query | from csv
|
|
}
|
|
|
|
# Get database statistics
|
|
def stats [] {
|
|
let user_count = (psql $DATABASE_URL -t -c "SELECT COUNT(*) FROM users;" | str trim | into int)
|
|
let channel_count = (psql $DATABASE_URL -t -c "SELECT COUNT(*) FROM channels;" | str trim | into int)
|
|
let message_count = (psql $DATABASE_URL -t -c "SELECT COUNT(*) FROM messages;" | str trim | into int)
|
|
let session_count = (psql $DATABASE_URL -t -c "SELECT COUNT(*) FROM sessions WHERE expires_at > NOW();" | str trim | into int)
|
|
let access_code_count = (psql $DATABASE_URL -t -c "SELECT COUNT(*) FROM access_codes WHERE expires_at > NOW() AND uses < max_uses;" | str trim | into int)
|
|
|
|
{
|
|
users: $user_count,
|
|
channels: $channel_count,
|
|
messages: $message_count,
|
|
active_sessions: $session_count,
|
|
valid_access_codes: $access_code_count
|
|
} | print
|
|
}
|
|
|
|
# Display help menu
|
|
def help-menu [] {
|
|
print "Available commands:"
|
|
print " messages [channel_id] - Fetch all messages or messages from a specific channel"
|
|
print " users - Fetch all users"
|
|
print " user <id|username> - Fetch specific user by ID or username"
|
|
print " channels - Fetch all channels"
|
|
print " channel <id> - Fetch specific channel by ID"
|
|
print " sessions - Fetch all sessions"
|
|
print " active-sessions - Fetch only active (non-expired) sessions"
|
|
print " access-codes - Fetch all access codes"
|
|
print " valid-access-codes - Fetch valid (non-expired, available) access codes"
|
|
print " attachments [message_id] - Fetch all attachments or attachments for a message"
|
|
print " stats - Show database statistics"
|
|
print " help - Show this help menu"
|
|
print " exit - Exit the interface"
|
|
}
|
|
|
|
# Main interactive loop
|
|
def main [] {
|
|
print "\n=== Database Query Interface ==="
|
|
help-menu
|
|
|
|
loop {
|
|
print ""
|
|
let input = (input "Enter command > ")
|
|
let parts = ($input | split words)
|
|
let cmd = ($parts | first)
|
|
|
|
match $cmd {
|
|
"messages" => {
|
|
if ($parts | length) > 1 {
|
|
let channel_id = ($parts | get 1 | into int)
|
|
messages $channel_id | print
|
|
} else {
|
|
messages | print
|
|
}
|
|
},
|
|
"users" => users,
|
|
"user" => {
|
|
if ($parts | length) > 1 {
|
|
user ($parts | get 1) | print
|
|
} else {
|
|
print "Usage: user <id|username>"
|
|
}
|
|
},
|
|
"channels" => channels,
|
|
"channel" => {
|
|
if ($parts | length) > 1 {
|
|
let channel_id = ($parts | get 1 | into int)
|
|
channel $channel_id | print
|
|
} else {
|
|
print "Usage: channel <id>"
|
|
}
|
|
},
|
|
"sessions" => sessions,
|
|
"active-sessions" => active-sessions,
|
|
"access-codes" => access-codes,
|
|
"valid-access-codes" => valid-access-codes,
|
|
"attachments" => {
|
|
if ($parts | length) > 1 {
|
|
let message_id = ($parts | get 1 | into int)
|
|
attachments $message_id | print
|
|
} else {
|
|
attachments | print
|
|
}
|
|
},
|
|
"stats" => stats,
|
|
"help" => help-menu,
|
|
"exit" => break,
|
|
_ => $"Unknown command: \($cmd). Type 'help' for available commands."
|
|
}
|
|
}
|
|
|
|
print "\nGoodbye!"
|
|
}
|