public static async Task Run(string[] paramStrings) { try { var splash = new FrmInternalSplash(); splash.Show(); System.Windows.Forms.Application.DoEvents(); Logger.Info("Starting up Discord Media Loader application..."); var useTrace = false; #if DEBUG //temporary add debug log level if debugging... Logger.GlobalLogLevel |= LogLevel.Debug; Logger.Debug("Running in debug configuartion. Added log level debug."); #endif Logger.Debug($"Parameters: {string.Join(", ", paramStrings)}"); if (paramStrings.Contains("--trace") || paramStrings.Contains("-t")) { useTrace = true; Logger.GlobalLogLevel |= LogLevel.Trace; Logger.Trace("Trace parameter found. Added log level trace."); } Logger.Debug($"Application data folder: {DataDirectory}"); Logger.Trace("Checking application data folder..."); if (!Directory.Exists(DataDirectory)) { Logger.Debug("Creating application data folder..."); Directory.CreateDirectory(DataDirectory); Logger.Trace("Creating application data folder."); } Logger.Trace("Initializing profile optimizations..."); ProfileOptimization.SetProfileRoot(System.Windows.Forms.Application.UserAppDataPath); ProfileOptimization.StartProfile("profile.opt"); Logger.Trace("Finished initializing profile optimizations."); Logger.Trace("Trying to identify log memory..."); var logMemory = Logger.DefaultLogMemory as ArchivableConsoleLogMemory; if (logMemory != null) { var logFolder = Path.Combine(DataDirectory, "logs"); if (!Directory.Exists(logFolder)) { Logger.Debug("Creating log folder..."); Directory.CreateDirectory(logFolder); Logger.Trace("Created log folder."); } var logFile = Path.Combine(logFolder, SweetUtils.LegalizeFilename($"{DateTime.Now.ToString(CultureInfo.CurrentCulture.DateTimeFormat.SortableDateTimePattern)}.log.zip")); Logger.Trace($"Setting log file: {logFile}"); logMemory.AutoArchiveOnDispose = true; logMemory.ArchiveFile = logFile; } Logger.Debug("Loading database..."); Database = new LiteDatabase(Path.Combine(DataDirectory, "config.db")); Database.Log.Logging += (message) => Logger.Trace($"LiteDB: {message}"); Logger.Debug("Loading settings collection out of database..."); var settingsDB = Database.GetCollection <Settings>("settings"); if (settingsDB.Count() > 1) { Logger.Warn("Found more than one setting. Loading first one..."); } Settings = settingsDB.FindAll().FirstOrDefault(); if (Settings == null) { Logger.Warn("Settings not found. Creating new one. This is normal on first start up..."); Settings = new Settings(); Settings.Store(); } if (Settings.ShowStartUpHints) { if (MessageBox.Show(splash, "This tool is considered as a selfbot which may violate the Discord TOS. By using this tool you take the risk to get your account banned. Although this never happened yet (as far as I know) you have to confirm to this.\n\r\n\rDo you wish to continue?", "HOLD UP!!", MessageBoxButtons.YesNo) != DialogResult.Yes) { splash.Close(); return; } Settings.ShowStartUpHints = false; Settings.Store(); } Logger.Debug("Loading jobs collection out of database..."); Scheduler.JobList = Job.RestoreJobs().ToList(); Logger.Info("Loaded settings."); Logger.Debug( $"Settings: Email: {Settings.Email}, password: {(string.IsNullOrEmpty(Settings.Password) ? "not set" : "is set")}, use username: {Settings.UseUserData}, loginToken: {Settings.LoginToken}"); Logger.Trace("Updating log level..."); Logger.GlobalLogLevel = Settings.ApplicactionLogLevel; #if DEBUG //temporary add debug log level if debugging... Logger.GlobalLogLevel |= LogLevel.Debug; Logger.Debug("Running in debug configuartion. Added log level debug."); #endif if (useTrace) { Logger.GlobalLogLevel |= LogLevel.Trace; Logger.Trace("Creating application data folder."); } Logger.Debug("Creating discord client..."); var config = new DiscordSocketConfig() { DefaultRetryMode = RetryMode.AlwaysRetry, }; //Client = new DiscordSocketClient(config); DMLClient.Client.Log += (arg) => { var logMessage = $"DiscordClient: {arg.Message}"; switch (arg.Severity) { case LogSeverity.Verbose: Logger.Trace(logMessage); break; case LogSeverity.Debug: Logger.Trace(logMessage); break; case LogSeverity.Info: Logger.Info(logMessage); break; case LogSeverity.Warning: Logger.Warn(logMessage); break; case LogSeverity.Error: Logger.Error(logMessage); break; } return(Task.CompletedTask); }; Logger.Info("Trying to log into discord..."); DMLClient.Client.Connected += Client_Connected; var loggedIn = false; while (!loggedIn) { try { if (!string.IsNullOrEmpty(Settings.LoginToken)) { Logger.Debug("Trying to login with last known token..."); loggedIn = await DMLClient.Login(Settings.LoginToken); } } catch (HttpException) { Logger.Warn("HTTPException occured during login. Probably from login token."); } if (!loggedIn) { Logger.Debug("Showing dialog for username and password..."); var loginDlg = new LoginDialog(); if (loginDlg.ShowDialog() != DialogResult.OK) { return; } } } Logger.Debug("Start checking for invalid jobs..."); //Client while (DMLClient.Client.Guilds.Count == 0) { // wait until guilds are loaded } for (var i = Scheduler.JobList.Count - 1; i >= 0; i--) { var job = Scheduler.JobList[i]; var isError = false; var guild = FindServerById(job.GuildId); if (guild == null) { isError = true; } else { var channel = FindChannelById(guild, job.ChannelId); if (channel == null) { isError = true; } } if (isError) { MessageBox.Show($"Invalid job for guild {job.GuildId}, channel {job.ChannelId} found. Guild or channel may not exist any more. This job will be deleted...", "Invalid job", MessageBoxButtons.OK, MessageBoxIcon.Warning); Scheduler.JobList.Remove(job); Scheduler.RunningJobs.Remove(job.Id); job.Stop(); job.Delete(); } } splash.Close(); Logger.Info("Starting scheduler..."); Scheduler.Start(); System.Windows.Forms.Application.Run(new MainForm()); Logger.Info("Stopping scheduler..."); Scheduler.Stop(); } catch (Exception ex) { Logger.Error($"{ex.Message} [{ex.GetType().Name}] occured at: {ex.StackTrace}"); if (MessageBox.Show($"An error occured while running Discord Media Loader:\n{ex.GetType().Name}: {ex.Message}\n\nDo you aggree to sending the error report to the creator of the tool?", "Discord Media Loader", MessageBoxButtons.YesNo) == DialogResult.Yes) { Raven.Capture(new SentryEvent(ex)); } } }
internal async Task <List <SocketMessage> > Scan() { Debug($"Starting scan of guild {GuildId} channel {ChannelId}..."); var result = new List <SocketMessage>(); var limit = 100; var lastId = ulong.MaxValue; var isFirst = true; var finished = false; var guild = FindServerById(GuildId); var channel = FindChannelById(guild, ChannelId); if (Math.Abs(StopTimestamp) < 0.4) { StopTimestamp = KnownTimestamp; } Trace("Initialized scanning parameters."); while (!finished) { Trace("Entering scanning loop..."); SocketMessage[] messages; Trace($"Downloading next {limit} messages..."); if (isFirst) { messages = await channel.GetMessagesAsync(limit).ToArray() as SocketMessage[]; } else { messages = await channel.GetMessagesAsync(lastId, Direction.Before, limit).ToArray() as SocketMessage[]; } Trace($"Downloaded {messages.Length} messages."); isFirst = false; foreach (var m in messages) { if (!IsValid) { return(null); } Debug($"Processing message {m.Id}"); if (m.Id < lastId) { Trace($"Updating lastId ({lastId}) to {m.Id}"); lastId = m.Id; } if (SweetUtils.DateTimeToUnixTimeStamp(m.CreatedAt.UtcDateTime) <= StopTimestamp) { Debug("Found a message with a known timestamp...Stopping scan."); finished = true; continue; } Trace($"Message {m.Id} has {m.Attachments.Count} attachments."); if (m.Attachments.Count > 0) { result.Add(m); DML.Core.Core.Scheduler.TotalAttachments++; Trace($"Added message {m.Id}"); } Debug($"Finished message {m.Id}"); DML.Core.Core.Scheduler.MessagesScanned++; } finished = finished || messages.Length < limit; } Trace($"Downloaded all messages for guild {GuildId} channel {ChannelId}."); Trace("Sorting messages..."); result.Sort((a, b) => DateTime.Compare(a.CreatedAt.UtcDateTime, b.CreatedAt.UtcDateTime)); if (result.Count > 0) { Trace("Updating StopTimestamp for next scan..."); StopTimestamp = SweetUtils.DateTimeToUnixTimeStamp(result[result.Count - 1].CreatedAt.UtcDateTime); } Debug($"Fisnished scan of guild {GuildId} channel {ChannelId}."); return(result); }
public static async Task Run(string[] paramStrings) { try { var splash = new FrmInternalSplash(); splash.Show(); System.Windows.Forms.Application.DoEvents(); Info("Starting up Discord Media Loader application..."); var useTrace = false; #if DEBUG //temporary add debug log level if debugging... GlobalLogLevel |= LogLevel.Debug; Debug("Running in debug configuartion. Added log level debug."); #endif Debug($"Parameters: {string.Join(", ", paramStrings)}"); if (paramStrings.Contains("--trace") || paramStrings.Contains("-t")) { useTrace = true; GlobalLogLevel |= LogLevel.Trace; Trace("Trace parameter found. Added log level trace."); } Debug($"Application data folder: {DataDirectory}"); Trace("Checking application data folder..."); if (!Directory.Exists(DataDirectory)) { Debug("Creating application data folder..."); Directory.CreateDirectory(DataDirectory); Trace("Creating application data folder."); } Trace("Initializing profile optimizations..."); ProfileOptimization.SetProfileRoot(System.Windows.Forms.Application.UserAppDataPath); ProfileOptimization.StartProfile("profile.opt"); Trace("Finished initializing profile optimizations."); Trace("Trying to identify log memory..."); var logMemory = DefaultLogMemory as ArchivableConsoleLogMemory; if (logMemory != null) { var logFolder = Path.Combine(DataDirectory, "logs"); if (!Directory.Exists(logFolder)) { Debug("Creating log folder..."); Directory.CreateDirectory(logFolder); Trace("Created log folder."); } var logFile = Path.Combine(logFolder, SweetUtils.LegalizeFilename($"{DateTime.Now.ToString(CultureInfo.CurrentCulture.DateTimeFormat.SortableDateTimePattern)}.log.zip")); Trace($"Setting log file: {logFile}"); logMemory.AutoArchiveOnDispose = true; logMemory.ArchiveFile = logFile; } Debug("Loading database..."); Database = new LiteDatabase(Path.Combine(DataDirectory, "config.db")); Database.Log.Logging += (message) => Trace($"LiteDB: {message}"); Debug("Loading settings collection out of database..."); var settingsDB = Database.GetCollection <Settings>("settings"); if (settingsDB.Count() > 1) { Warn("Found more than one setting. Loading first one..."); } Settings = settingsDB.FindAll().FirstOrDefault(); if (Settings == null) { Warn("Settings not found. Creating new one. This is normal on first start up..."); Settings = new Settings(); Settings.Store(); } Debug("Loading jobs collection out of database..."); Scheduler.JobList = Job.RestoreJobs().ToList(); Info("Loaded settings."); Debug( $"Settings: Email: {Settings.Email}, password: {(string.IsNullOrEmpty(Settings.Password) ? "not set" : "is set")}, use username: {Settings.UseUserData}, loginToken: {Settings.LoginToken}"); Trace("Updating log level..."); GlobalLogLevel = Settings.ApplicactionLogLevel; #if DEBUG //temporary add debug log level if debugging... GlobalLogLevel |= LogLevel.Debug; Debug("Running in debug configuartion. Added log level debug."); #endif if (useTrace) { GlobalLogLevel |= LogLevel.Trace; Trace("Creating application data folder."); } Debug("Creating discord client..."); Client = new DiscordSocketClient(); Client.Log += (arg) => { var logMessage = $"DiscordClient: {arg.Message}"; switch (arg.Severity) { case LogSeverity.Verbose: Trace(logMessage); break; case LogSeverity.Debug: Trace(logMessage); break; case LogSeverity.Info: Info(logMessage); break; case LogSeverity.Warning: Warn(logMessage); break; case LogSeverity.Error: Error(logMessage); break; } return(Task.CompletedTask); }; Info("Trying to log into discord..."); var abort = false; Client.Connected += Client_Connected; while (Client.LoginState != LoginState.LoggedIn && !abort) { Debug(Client.ConnectionState.ToString()); Debug(Client.LoginState.ToString()); Trace("Entering login loop."); try { if (Client.ConnectionState == ConnectionState.Connecting) { continue; } if (!string.IsNullOrEmpty(Settings.LoginToken)) { Debug("Trying to login with last known token..."); await Client.LoginAsync(TokenType.User, Settings.LoginToken); await Task.Delay(1000); } } catch (HttpException ex) { Warn($"Login seems to have failed or gone wrong: {ex.GetType().Name} - {ex.Message}"); } if (Client.LoginState == LoginState.LoggedOut) { Settings.Password = string.Empty; Debug("Showing dialog for username and password..."); var loginDlg = new LoginDialog(); loginDlg.ShowDialog(); Trace("Dialog closed."); } } Debug("Start checking for invalid jobs..."); //Client while (Client.Guilds.Count == 0) { // wait until guilds are loaded } for (var i = Scheduler.JobList.Count - 1; i >= 0; i--) { var job = Scheduler.JobList[i]; var isError = false; var guild = FindServerById(job.GuildId); if (guild == null) { isError = true; } else { var channel = FindChannelById(guild, job.ChannelId); if (channel == null) { isError = true; } } if (isError) { MessageBox.Show($"Invalid job for guild {job.GuildId}, channel {job.ChannelId} found. Guild or channel may not exist any more. This job will be deleted...", "Invalid job", MessageBoxButtons.OK, MessageBoxIcon.Warning); Scheduler.JobList.Remove(job); Scheduler.RunningJobs.Remove(job.Id); job.Stop(); job.Delete(); } } splash.Close(); Info("Starting scheduler..."); Scheduler.Start(); System.Windows.Forms.Application.Run(new MainForm()); Info("Stopping scheduler..."); Scheduler.Stop(); } catch (Exception ex) { Error($"{ex.Message} occured at: {ex.StackTrace}"); } }
private void WorkQueue(int jobId) { try { Debug("Beginning job download..."); Trace("Finding job..."); var job = (from j in JobList where j.Id == jobId select j).FirstOrDefault(); if (job == null) { Warn($"Associating job not found! JobId: {jobId}"); return; } Trace("Found job."); Queue <SocketMessage> queue; Trace("Locking scheduler..."); lock (this) { Trace("Finiding queue..."); if (!RunningJobs.TryGetValue(jobId, out queue)) { Warn($"Queue for job {jobId} not found!"); return; } Trace("Queue found."); } Trace("Unlocked scheduler."); Debug($"Messages to process for job {jobId}: {queue.Count}"); while (queue.Count > 0) { Trace("Locking scheduler..."); lock (this) { Trace("Checking if still a job..."); if (!RunningJobs.ContainsKey(jobId)) { Warn($"Queue for job {jobId} not found!"); return; } Trace("Continue working..."); } Trace("Unlocked scheduler."); Trace("Dequeueing message..."); var message = queue.Dequeue(); Debug($"Attachments for message {message.Id}: {message.Attachments.Count}"); foreach (var a in message.Attachments) { try { var fileName = Path.Combine(DML.Core.Core.Settings.OperatingFolder, DML.Core.Core.Settings.FileNameScheme); Trace("Replacing filename placeholders..."); var extensionRequired = !fileName.EndsWith("%name%"); var serverName = "unknown"; var socketTextChannel = message.Channel as SocketTextChannel; if (socketTextChannel != null) { serverName = socketTextChannel.Guild.Name.Replace(":", "").Replace("/", "") .Replace("\\", ""); } fileName = fileName.Replace("%guild%", serverName) .Replace("%channel%", message.Channel.Name) .Replace("%timestamp%", SweetUtils.DateTimeToUnixTimeStamp(message.CreatedAt.UtcDateTime).ToString()) .Replace("%name%", a.Filename) .Replace("%id%", a.Id.ToString()); if (extensionRequired) { fileName += Path.GetExtension(a.Filename); } Trace($"Detemined file name: {fileName}."); if (File.Exists(fileName) && new FileInfo(fileName).Length == a.Size) { Debug($"{fileName} already existing with its estimated size. Skipping..."); continue; } Trace("Determining directory..."); var fileDirectory = Path.GetDirectoryName(fileName); if (!Directory.Exists(fileDirectory)) { Info($"Directory {fileDirectory} does not exist. Creating directory..."); Directory.CreateDirectory(fileDirectory); Debug("Created directory."); } var wc = new WebClient(); Debug($"Starting downloading of attachment {a.Id}..."); wc.DownloadFile(new Uri(a.Url), fileName); Debug($"Downloaded attachment {a.Id}."); Trace("Updating known timestamp for job..."); job.KnownTimestamp = SweetUtils.DateTimeToUnixTimeStamp(message.CreatedAt.UtcDateTime); job.Store(); } finally { AttachmentsDownloaded++; } } } } finally { Trace("Locking scheduler..."); lock (this) { Trace($"Removing {jobId} from running jobs..."); RunningJobs.Remove(jobId); Trace("Decreasing thread count..."); RunningThreads--; } Trace("Unlocked scheduler."); } }