diff --git a/Program.cs b/Program.cs index afe5ab2..e48eca9 100644 --- a/Program.cs +++ b/Program.cs @@ -17,8 +17,6 @@ namespace DiscordBotExample { class Program { - private static List _imageUrls; - private static Random _random = new Random(); private static DiscordSocketClient _client; private static CommandService _commands; private static IServiceProvider _services; @@ -30,35 +28,30 @@ class Program static async Task Main(string[] args) { - // Read environment variables var token = Environment.GetEnvironmentVariable("DISCORD_BOT_TOKEN"); var channelIdStr = Environment.GetEnvironmentVariable("DISCORD_CHANNEL_ID"); _fileId = Environment.GetEnvironmentVariable("GOOGLE_DRIVE_FILE_ID"); _credentialsPath = Environment.GetEnvironmentVariable("GOOGLE_CREDENTIALS_PATH"); var postTimeStr = Environment.GetEnvironmentVariable("POST_TIME"); - // Check if token, channelId, fileId, credentialsPath, or postTime is null or empty if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(channelIdStr) || string.IsNullOrEmpty(_fileId) || string.IsNullOrEmpty(_credentialsPath) || string.IsNullOrEmpty(postTimeStr)) { Console.WriteLine("Environment variables are not set correctly."); return; } - // Parse channel ID if (!ulong.TryParse(channelIdStr, out _channelId)) { Console.WriteLine("Invalid DISCORD_CHANNEL_ID format."); return; } - // Parse post time if (!TimeSpan.TryParse(postTimeStr, out _postTimeSpain)) { Console.WriteLine("Invalid POST_TIME format. It must be in the format HH:mm:ss."); return; } - // Initialize the Discord client and command service _client = new DiscordSocketClient(); _commands = new CommandService(); _services = new ServiceCollection() @@ -70,11 +63,9 @@ static async Task Main(string[] args) _client.Ready += OnReady; _client.MessageReceived += HandleCommandAsync; - // Start the bot await _client.LoginAsync(TokenType.Bot, token); await _client.StartAsync(); - // Block the application until it is closed await Task.Delay(-1); } @@ -88,46 +79,18 @@ private static async Task OnReady() { Console.WriteLine("Bot is connected."); - // Initialize command handling - await _commands.AddModulesAsync(typeof(Program).Assembly, _services); - - // Download and process the CSV file from Google Drive - var csvData = await DownloadCsvFromGoogleDrive(); - - if (csvData != null) - { - using (var reader = new StringReader(csvData)) - using (var csv = new CsvReader(reader, new CsvHelper.Configuration.CsvConfiguration(CultureInfo.InvariantCulture))) - { - _imageUrls = csv.GetRecords() - .Where(record => !string.IsNullOrWhiteSpace(record.image_url) && record.has_spoilers != "yes") - .Select(record => record.image_url.Trim()) - .ToList(); - } - - Console.WriteLine("Filtered URLs read from CSV:"); - foreach (var url in _imageUrls) - { - Console.WriteLine(url); - } - } - else - { - Console.WriteLine("Failed to download or read the CSV file. Exiting..."); - return; - } - - // Check if imageUrls is empty - if (_imageUrls.Count == 0) - { - Console.WriteLine("No valid URLs available. Exiting..."); - return; - } + await RegisterCommandsAsync(); // Register command modules // Schedule the first post await ScheduleNextPost(); } + private static async Task RegisterCommandsAsync() + { + // Register commands from the assembly + await _commands.AddModulesAsync(typeof(Program).Assembly, _services); + } + private static async Task HandleCommandAsync(SocketMessage messageParam) { var message = messageParam as SocketUserMessage; @@ -153,29 +116,21 @@ private static async Task ScheduleNextPost() { var nowUtc = DateTime.UtcNow; var spainTime = TimeZoneInfo.ConvertTimeFromUtc(nowUtc, _spainTimeZone); - - // Specify that nextPostTimeSpain is unspecified in terms of kind because we will convert it to a specific time zone var nextPostTimeSpain = DateTime.SpecifyKind(DateTime.Today.Add(_postTimeSpain), DateTimeKind.Unspecified); if (nextPostTimeSpain <= spainTime) { - // If the time has already passed for today, schedule for tomorrow nextPostTimeSpain = nextPostTimeSpain.AddDays(1); } - // Convert the unspecified time to Spain time zone and then to UTC nextPostTimeSpain = TimeZoneInfo.ConvertTimeToUtc(nextPostTimeSpain, _spainTimeZone); - - // Calculate the delay var delay = nextPostTimeSpain - nowUtc; Console.WriteLine($"Scheduling next post in {delay.TotalMinutes} minutes."); - await Task.Delay(delay); await PostRandomImageUrl(); - // Schedule the next post await ScheduleNextPost(); } @@ -183,7 +138,6 @@ public static async Task DownloadCsvFromGoogleDrive() { try { - // Set up Google Drive API service var credential = GoogleCredential.FromFile(_credentialsPath) .CreateScoped(DriveService.Scope.DriveReadonly); @@ -193,9 +147,9 @@ public static async Task DownloadCsvFromGoogleDrive() ApplicationName = "DiscordBotExample", }); - // Download the file var request = service.Files.Get(_fileId); var stream = new MemoryStream(); + request.MediaDownloader.ProgressChanged += progress => { if (progress.Status == Google.Apis.Download.DownloadStatus.Completed) @@ -223,27 +177,46 @@ public static async Task PostRandomImageUrl() { var channel = _client.GetChannel(_channelId) as IMessageChannel; - if (channel != null && _imageUrls.Count > 0) - { - int index = _random.Next(_imageUrls.Count); - string randomUrl = _imageUrls[index]; - await channel.SendMessageAsync(randomUrl); - } - else + if (channel != null) { - Console.WriteLine("No URLs available."); + string csvData = await DownloadCsvFromGoogleDrive(); + + if (!string.IsNullOrEmpty(csvData)) + { + using (var reader = new StringReader(csvData)) + using (var csv = new CsvReader(reader, new CsvHelper.Configuration.CsvConfiguration(CultureInfo.InvariantCulture))) + { + var imageUrls = csv.GetRecords() + .Where(record => !string.IsNullOrWhiteSpace(record.image_url) && record.has_spoilers != "yes") + .Select(record => record.image_url.Trim()) + .ToArray(); + + if (imageUrls.Length > 0) + { + int index = new Random().Next(imageUrls.Length); + string randomUrl = imageUrls[index]; + await channel.SendMessageAsync(randomUrl); + } + else + { + Console.WriteLine("No valid URLs available."); + } + } + } + else + { + Console.WriteLine("Failed to download or read the CSV file."); + } } } } - // Define a class that matches the CSV structure public class YourRecordClass { public string image_url { get; set; } public string has_spoilers { get; set; } } - // Command Module for handling commands public class CommandModule : ModuleBase { [Command("send")]