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("]")); } } }