269 lines
11 KiB
C#
269 lines
11 KiB
C#
using System.Text;
|
|
|
|
#pragma warning disable IDE0130 // Namespace does not match folder structure
|
|
namespace FireflyClient
|
|
#pragma warning restore IDE0130 // Namespace does not match folder structure
|
|
{
|
|
/// <summary>
|
|
/// Command-line interface for Firefly
|
|
/// </summary>
|
|
public class Program
|
|
{
|
|
static async Task Main(string[] args)
|
|
{
|
|
Console.WriteLine("Firefly Client");
|
|
Console.WriteLine("Enter commands (type EXIT to quit)");
|
|
Console.WriteLine("Use double quotes for values with spaces: HSET email:1 subject \"Hello World\"");
|
|
Console.WriteLine("Type HELP for basic commands or HELP EMAIL for email examples");
|
|
|
|
// Parse command line arguments
|
|
string host = "127.0.0.1";
|
|
int port = 6379;
|
|
string password = string.Empty;
|
|
|
|
for (int i = 0; i < args.Length; i++)
|
|
{
|
|
if ((args[i] == "--host" || args[i] == "-h") && i + 1 < args.Length)
|
|
{
|
|
host = args[++i];
|
|
}
|
|
else if ((args[i] == "--port" || args[i] == "-p") && i + 1 < args.Length && int.TryParse(args[i + 1], out int parsedPort))
|
|
{
|
|
port = parsedPort;
|
|
i++;
|
|
}
|
|
else if ((args[i] == "--password" || args[i] == "--pass") && i + 1 < args.Length)
|
|
{
|
|
password = args[++i];
|
|
}
|
|
else if (args[i] == "--help" || args[i] == "-?")
|
|
{
|
|
PrintClientHelp();
|
|
return;
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
await RunInteractiveClientAsync(host, port, password);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Error: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
static void PrintClientHelp()
|
|
{
|
|
Console.WriteLine("\nFirefly Client Usage:");
|
|
Console.WriteLine(" --host, -h <hostname> Server hostname or IP (default: 127.0.0.1)");
|
|
Console.WriteLine(" --port, -p <port> Server port (default: 6379)");
|
|
Console.WriteLine(" --password, --pass <pwd> Server password");
|
|
Console.WriteLine(" --help, -? Show this help message\n");
|
|
Console.WriteLine("Example: FireflyClient --host localhost --port 6380 --password secret123\n");
|
|
}
|
|
|
|
static Task RunInteractiveClientAsync(string host, int port, string password)
|
|
{
|
|
using var client = new FireflyClient(host, port);
|
|
Console.WriteLine($"Connecting to server at {host}:{port}...");
|
|
Console.WriteLine("Connected to server!");
|
|
|
|
// If password wasn't provided as a command line argument, prompt for it
|
|
if (string.IsNullOrEmpty(password))
|
|
{
|
|
Console.Write("Enter password (leave empty if no password required): ");
|
|
password = Console.ReadLine() ?? string.Empty;
|
|
}
|
|
|
|
// Authenticate if password was provided
|
|
if (!string.IsNullOrEmpty(password))
|
|
{
|
|
bool success = client.Authenticate(password);
|
|
|
|
// Check if authentication failed
|
|
if (!success)
|
|
{
|
|
Console.WriteLine("Authentication failed. Disconnecting.");
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|
|
|
|
while (true)
|
|
{
|
|
// Get command from user
|
|
Console.Write("> ");
|
|
string input = Console.ReadLine() ?? string.Empty;
|
|
|
|
if (string.IsNullOrEmpty(input) || input.Equals("EXIT", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
// Send QUIT command before exiting
|
|
try
|
|
{
|
|
string response = client.ExecuteCommand("QUIT");
|
|
Console.WriteLine($"Server: {response.TrimEnd('\r', '\n')}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Error while quitting: {ex.Message}");
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Check for help commands
|
|
if (input.Equals("HELP", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
PrintBasicCommands();
|
|
continue;
|
|
}
|
|
// Handle clear screen command
|
|
else if (input.Equals("CLS", StringComparison.OrdinalIgnoreCase) ||
|
|
input.Equals("CLEAR", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
Console.Clear();
|
|
continue;
|
|
}
|
|
|
|
try
|
|
{
|
|
// Parse the command
|
|
string[] parts = SplitCommandLine(input);
|
|
if (parts.Length == 0) continue;
|
|
|
|
string command = parts[0];
|
|
string[] args = [.. parts.Skip(1)];
|
|
|
|
// Execute the command
|
|
string response = client.ExecuteCommand(command, args);
|
|
FormatAndPrintResponse(response);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Error: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
Console.WriteLine("Disconnected from server.");
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
// Helper method to split command line respecting quotes
|
|
static string[] SplitCommandLine(string commandLine)
|
|
{
|
|
var result = new List<string>();
|
|
bool inQuotes = false;
|
|
StringBuilder currentArg = new();
|
|
|
|
for (int i = 0; i < commandLine.Length; i++)
|
|
{
|
|
char c = commandLine[i];
|
|
|
|
if (c == '"')
|
|
{
|
|
inQuotes = !inQuotes;
|
|
// Don't include the quote character
|
|
}
|
|
else if (c == ' ' && !inQuotes)
|
|
{
|
|
// End of argument
|
|
if (currentArg.Length > 0)
|
|
{
|
|
result.Add(currentArg.ToString());
|
|
currentArg.Clear();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
currentArg.Append(c);
|
|
}
|
|
}
|
|
|
|
// Add the last argument if any
|
|
if (currentArg.Length > 0)
|
|
{
|
|
result.Add(currentArg.ToString());
|
|
}
|
|
|
|
return [.. result];
|
|
}
|
|
|
|
static void FormatAndPrintResponse(string response)
|
|
{
|
|
// Remove trailing whitespace
|
|
response = response.TrimEnd();
|
|
|
|
if (response.StartsWith('*') && response.Contains("\r\n"))
|
|
{
|
|
// Format array responses for better readability
|
|
string[] parts = response.Split("\r\n");
|
|
if (parts.Length > 1)
|
|
{
|
|
Console.WriteLine("Server: Array response:");
|
|
for (int i = 1; i < parts.Length; i++)
|
|
{
|
|
if (!string.IsNullOrEmpty(parts[i]))
|
|
{
|
|
// For simple string and bulk string responses in an array
|
|
if (parts[i].StartsWith('+') || parts[i].StartsWith('$'))
|
|
{
|
|
Console.WriteLine($"{i}) {parts[i][1..]}");
|
|
}
|
|
else if (!parts[i].StartsWith('*')) // Skip the array count line
|
|
{
|
|
Console.WriteLine($"{i}) {parts[i]}");
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Default formatting
|
|
Console.WriteLine($"Server: {response}");
|
|
}
|
|
|
|
// Helper method: Print basic commands
|
|
static void PrintBasicCommands()
|
|
{
|
|
Console.WriteLine("\n==== Basic Firefly Commands ====");
|
|
|
|
Console.WriteLine("\n## String Operations ##");
|
|
Console.WriteLine("SET key value # Set a string value");
|
|
Console.WriteLine("GET key # Get a string value");
|
|
Console.WriteLine("DEL key # Delete a key");
|
|
Console.WriteLine("SEXISTS key # Check if string key exists");
|
|
|
|
Console.WriteLine("\n## List Operations ##");
|
|
Console.WriteLine("LPUSH key value # Add value to the beginning of a list");
|
|
Console.WriteLine("RPUSH key value # Add value to the end of a list");
|
|
Console.WriteLine("LPOP key # Remove and return the first element");
|
|
Console.WriteLine("RPOP key # Remove and return the last element");
|
|
Console.WriteLine("LRANGE key start end # Get a range of elements (0 -1 for all)");
|
|
Console.WriteLine("LINDEX key index # Get element at specific position");
|
|
Console.WriteLine("LGET key [index] # Get entire list or element at index");
|
|
Console.WriteLine("LEXISTS key # Check if list key exists");
|
|
|
|
Console.WriteLine("\n## Hash Operations ##");
|
|
Console.WriteLine("HSET key field value # Set a field in a hash");
|
|
Console.WriteLine("HGET key field # Get a field from a hash");
|
|
Console.WriteLine("HDEL key field # Delete a field from a hash");
|
|
Console.WriteLine("HEXISTS key field # Check if field exists in hash");
|
|
Console.WriteLine("HGETALL key # Get all fields and values in a hash");
|
|
Console.WriteLine("HMSET key field1 val1... # Set multiple fields at once");
|
|
Console.WriteLine("HASKEY key # Check if hash key exists");
|
|
|
|
Console.WriteLine("\n## Server Operations ##");
|
|
Console.WriteLine("PING # Test connection");
|
|
Console.WriteLine("ECHO message # Echo a message");
|
|
Console.WriteLine("SAVE # Save database to disk");
|
|
Console.WriteLine("BGSAVE # Save database in background");
|
|
Console.WriteLine("QUIT # Gracefully disconnect from server");
|
|
|
|
Console.WriteLine("\n## Help Commands ##");
|
|
Console.WriteLine("HELP # Show this help message");
|
|
Console.WriteLine("HELP EMAIL # Show email storage examples");
|
|
Console.WriteLine("CLS, CLEAR # Clear the console screen");
|
|
Console.WriteLine("EXIT # Exit the client");
|
|
}
|
|
}
|
|
} |