using CommandLine;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using RedisManager.Utils;
using RedisManager.Commands;
namespace RedisManager.Commands
{
///
/// Command line options for the GET command.
/// Used to retrieve the value of a Redis key.
///
[Verb("get", HelpText = "Get value of a key.")]
public class GetOptions : InstanceOptions
{
///
/// Gets or sets the key name to retrieve the value for.
///
[Value(0, MetaName = "key", Required = true, HelpText = "Key name.")]
public string Key { get; set; }
///
/// Gets or sets whether to output the result in table format.
///
[Option("table", Required = false, HelpText = "Output as table.")]
public bool Table { get; set; }
}
///
/// Command line options for the SET command.
/// Used to set the value of a Redis key with optional TTL.
///
[Verb("set", HelpText = "Set value of a key.")]
public class SetOptions : InstanceOptions
{
///
/// Gets or sets the key name to set the value for.
///
[Value(0, MetaName = "key", Required = true, HelpText = "Key name.")]
public string Key { get; set; }
///
/// Gets or sets the value to store in the key.
///
[Value(1, MetaName = "value", Required = true, HelpText = "Value.")]
public string Value { get; set; }
///
/// Gets or sets the time to live in seconds for the key.
///
[Option("ttl", Required = false, HelpText = "Time to live in seconds.")]
public int? TTL { get; set; }
}
///
/// Command line options for the DEL command.
/// Used to delete one or more Redis keys with optional confirmation.
///
[Verb("del", HelpText = "Delete one or more keys.")]
public class DelOptions : InstanceOptions
{
///
/// Gets or sets whether to skip the confirmation prompt.
///
[Option("yes", Required = false, HelpText = "Skip confirmation.")]
public bool Yes { get; set; }
///
/// Gets or sets the collection of keys to delete.
///
[Value(0, MetaName = "keys", Min = 1, Required = true, HelpText = "Key(s) to delete.")]
public IEnumerable Keys { get; set; }
///
/// Gets or sets whether to output the result in table format.
///
[Option("table", Required = false, HelpText = "Output as table.")]
public bool Table { get; set; }
}
///
/// Static class containing implementations for basic Redis string operations.
/// Provides functionality for GET, SET, and DEL commands with various output formats.
///
public static class StringCommands
{
///
/// Executes the GET command to retrieve a value from Redis.
/// Supports table output format and JSON pretty-printing.
///
/// The GET command options
/// The RedisManager configuration
/// Exit code (0 for success, non-zero for failure)
public static int RunGet(GetOptions opts, Config config)
{
var instance = RedisUtils.GetInstance(config, opts.Instance);
using var redis = RedisUtils.ConnectRedis(instance);
var db = redis.GetDatabase();
var value = db.StringGet(opts.Key);
if (opts.Table)
{
RedisUtils.PrintTable(new[] { "Key", "Value" }, new List { new[] { opts.Key, value.IsNull ? "[null]" : value.ToString() } });
}
else if (value.IsNull)
Console.WriteLine(Output.Yellow($"[null]"));
else
{
// Try pretty-print JSON
string str = value.ToString();
if (IsJson(str))
{
try
{
var doc = JsonDocument.Parse(str);
var pretty = JsonSerializer.Serialize(doc, new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine(Output.Green(pretty));
}
catch { Console.WriteLine(Output.Green(str)); }
}
else
{
Console.WriteLine(Output.Green(str));
}
}
return 0;
}
///
/// Executes the SET command to store a value in Redis.
/// Supports optional TTL (time to live) for the key.
///
/// The SET command options
/// The RedisManager configuration
/// Exit code (0 for success, non-zero for failure)
public static int RunSet(SetOptions opts, Config config)
{
var instance = RedisUtils.GetInstance(config, opts.Instance);
using var redis = RedisUtils.ConnectRedis(instance);
var db = redis.GetDatabase();
bool ok;
if (opts.TTL.HasValue)
ok = db.StringSet(opts.Key, opts.Value, TimeSpan.FromSeconds(opts.TTL.Value));
else
ok = db.StringSet(opts.Key, opts.Value);
if (ok)
Console.WriteLine(Output.Green("OK"));
else
Console.WriteLine(Output.Red("Failed to set key."));
return 0;
}
///
/// Executes the DEL command to delete one or more keys from Redis.
/// Supports confirmation prompts and table output format.
///
/// The DEL command options
/// The RedisManager configuration
/// Exit code (0 for success, non-zero for failure)
public static int RunDel(DelOptions opts, Config config)
{
var instance = RedisUtils.GetInstance(config, opts.Instance);
using var redis = RedisUtils.ConnectRedis(instance);
var db = redis.GetDatabase();
var keys = opts.Keys.Select(k => (RedisKey)k).ToArray();
if (!opts.Yes)
{
Console.WriteLine(Output.Yellow($"Are you sure you want to delete {keys.Length} key(s)? (y/N)"));
var response = Console.ReadLine()?.ToLower();
if (response != "y" && response != "yes")
{
Console.WriteLine(Output.Red("Operation cancelled."));
return 1;
}
}
var count = db.KeyDelete(keys);
if (opts.Table)
RedisUtils.PrintTable(new[] { "Keys", "Deleted" }, new List { new[] { string.Join(", ", opts.Keys), count.ToString() } });
else
Console.WriteLine(Output.Green($"Deleted {count} key(s)"));
return 0;
}
///
/// Determines if a string appears to be JSON formatted.
/// Checks if the string starts and ends with curly braces or square brackets.
///
/// The string to check for JSON formatting
/// True if the string appears to be JSON, false otherwise
private static bool IsJson(string str)
{
str = str.Trim();
return (str.StartsWith("{") && str.EndsWith("}")) || (str.StartsWith("[") && str.EndsWith("]"));
}
}
}