diff --git a/DML.AppCore/DML.AppCore.csproj b/DML.AppCore/DML.AppCore.csproj
new file mode 100644
index 0000000..6d9fa23
--- /dev/null
+++ b/DML.AppCore/DML.AppCore.csproj
@@ -0,0 +1,17 @@
+
+
+
+ netstandard1.4
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DML.Client/DML.Client.csproj b/DML.Client/DML.Client.csproj
new file mode 100644
index 0000000..4b6dd43
--- /dev/null
+++ b/DML.Client/DML.Client.csproj
@@ -0,0 +1,15 @@
+
+
+
+ netstandard1.4
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DML.Client/DMLClient.cs b/DML.Client/DMLClient.cs
new file mode 100644
index 0000000..691f563
--- /dev/null
+++ b/DML.Client/DMLClient.cs
@@ -0,0 +1,25 @@
+using System.Threading.Tasks;
+using Discord;
+using Discord.WebSocket;
+
+namespace DML.Client
+{
+ public static class DMLClient
+ {
+ public static DiscordSocketClient Client { get; set; } = new DiscordSocketClient(new DiscordSocketConfig(){DefaultRetryMode = RetryMode.RetryRatelimit|RetryMode.RetryTimeouts});
+
+ public static async Task Login(string token)
+ {
+ await Client.LoginAsync(TokenType.User, token);
+ await Client.StartAsync();
+ await Task.Delay(1000);
+
+ while (Client.LoginState == LoginState.LoggingIn || Client.ConnectionState == ConnectionState.Connecting)
+ {
+ // wait
+ }
+
+ return Client.LoginState == LoginState.LoggedIn && Client.ConnectionState == ConnectionState.Connected;
+ }
+ }
+}
diff --git a/DML.Core/Classes/Job.cs b/DML.Core/Classes/Job.cs
new file mode 100644
index 0000000..2f283e2
--- /dev/null
+++ b/DML.Core/Classes/Job.cs
@@ -0,0 +1,158 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Discord;
+using Discord.WebSocket;
+
+namespace DML.Core.Classes
+{
+ public class Job
+ {
+ public int Id { get; set; }
+ public ulong GuildId { get; set; }
+ public ulong ChannelId { get; set; }
+ public double KnownTimestamp { get; set; } = 0;
+ private double StopTimestamp { get; set; } = 0;
+ private bool IsValid { get; set; } = true;
+
+ internal void Store()
+ {
+ Debug("Storing job to database...");
+ Trace("Getting jobs collection...");
+ var jobDb = DML.Core.Core.Database.GetCollection("jobs");
+
+ Trace("Adding new value...");
+
+ if (jobDb.Find(x => x.ChannelId == ChannelId && x.GuildId == GuildId).Any())
+ {
+ jobDb.Update(this);
+ }
+ else
+ {
+ jobDb.Insert(this);
+ }
+ }
+
+ internal void Delete()
+ {
+ Debug("Deleting job from database...");
+ Trace("Getting jobs collection...");
+ var jobDb = DML.Core.Core.Database.GetCollection("jobs");
+
+ Trace("Deleting value...");
+ jobDb.Delete(Id);
+ }
+
+ private SocketGuild FindServerById(ulong id)
+ {
+ Trace($"Trying to find server by Id: {id}");
+ return (from s in DML.Core.Core.Client.Guilds where s.Id == id select s).FirstOrDefault();
+ }
+
+ private SocketTextChannel FindChannelById(SocketGuild server, ulong id)
+ {
+ Trace($"Trying to find channel in {server} by id: {id}");
+ return (from c in server.TextChannels where c.Id == id select c).FirstOrDefault();
+ }
+
+ internal async Task> Scan()
+ {
+ Debug($"Starting scan of guild {GuildId} channel {ChannelId}...");
+ var result = new List();
+
+ 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;
+ }
+
+ internal void Stop()
+ {
+ IsValid = false;
+ }
+
+ internal static IEnumerable RestoreJobs()
+ {
+ Debug("Restoring jobs...");
+ Trace("Getting jobs collection...");
+ var jobDb = DML.Core.Core.Database.GetCollection("jobs");
+
+ Trace("Creating new empty job list");
+ return jobDb.FindAll();
+ }
+ }
+}
diff --git a/DML.Core/Classes/JobScheduler.cs b/DML.Core/Classes/JobScheduler.cs
new file mode 100644
index 0000000..21d3305
--- /dev/null
+++ b/DML.Core/Classes/JobScheduler.cs
@@ -0,0 +1,290 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Discord.WebSocket;
+
+namespace DML.Core.Classes
+{
+ internal class JobScheduler
+ {
+ private ulong messageScanned = 0;
+ private ulong totalAttachments = 0;
+ private ulong attachmentsDownloaded = 0;
+
+ private bool Run { get; set; } = false;
+ internal List JobList { get; set; } = new List();
+ internal Dictionary> RunningJobs = new Dictionary>();
+ internal int RunningThreads { get; set; } = 0;
+
+ internal ulong MessagesScanned
+ {
+ get
+ {
+ lock (this)
+ {
+ return messageScanned;
+ }
+ }
+ set
+ {
+ lock (this)
+ {
+ messageScanned = value;
+ }
+ }
+ }
+
+ internal ulong TotalAttachments
+ {
+ get
+ {
+ lock (this)
+ {
+ return totalAttachments;
+ }
+ }
+ set
+ {
+ lock (this)
+ {
+ totalAttachments = value;
+ }
+ }
+ }
+
+ internal ulong AttachmentsDownloaded
+ {
+ get
+ {
+ lock (this)
+ {
+ return attachmentsDownloaded;
+ }
+ }
+ set
+ {
+ lock (this)
+ {
+ attachmentsDownloaded = value;
+ }
+ }
+ }
+
+ internal ulong AttachmentsToDownload => TotalAttachments - AttachmentsDownloaded;
+
+ internal void Stop()
+ {
+ Run = false;
+ }
+
+ internal void Start()
+ {
+ Run = true;
+
+ Task.Run(async () =>
+ {
+ Info("Started JobScheduler...");
+ while (Run)
+ {
+ Debug("Entering job list handler loop...");
+ //foreach (var job in JobList)
+ for (var i = JobList.Count - 1; i >= 0; i--)
+ {
+ var job = JobList[i];
+ Debug($"Checking job {job}");
+ var hasJob = false;
+
+ Trace("Locking scheduler...");
+ lock (this)
+ {
+ Trace("Checking if job is already performed...");
+ hasJob = RunningJobs.ContainsKey(job.Id);
+ }
+ Trace("Unlocked scheduler.");
+
+ if (!hasJob)
+ {
+ Debug("Job is not performed yet...Performing job...");
+ var queue = new Queue();
+
+ Trace("Locking scheduler...");
+ lock (this)
+ {
+ Trace("Adding job to running jobs.");
+ RunningJobs.Add(job.Id, queue);
+ }
+ Trace("Unlocked scheduler.");
+
+ Trace("Issuing job message scan...");
+ var messages = await job.Scan();
+
+ if (messages == null)
+ continue;
+
+ Trace($"Adding {messages.Count} messages to queue...");
+ foreach (var msg in messages)
+ {
+ queue.Enqueue(msg);
+ }
+ Trace($"Added {queue.Count} messages to queue.");
+
+ if (messages.Count != queue.Count)
+ Warn("Not all messages have been added into the queue.");
+
+ var startedDownload = false;
+
+ while (!startedDownload)
+ {
+ Debug("Entering loop to check thread availability");
+ Trace("Locking scheduler...");
+ lock (this)
+ {
+ Trace($"Checking thread limit. Running: {RunningThreads}, Max: {DML.Core.Core.Settings.ThreadLimit}");
+ if (RunningThreads >= DML.Core.Core.Settings.ThreadLimit)
+ continue;
+
+ RunningThreads++;
+ startedDownload = true;
+ }
+ Trace("Unlocked scheduler.");
+ }
+
+ Trace("Start downloading job async.");
+ Task.Run(() => WorkQueue(job.Id)); // do not await to work parallel
+ }
+ }
+ }
+ });
+ }
+
+ 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 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.");
+ }
+ }
+ }
+}
diff --git a/DML.Core/Classes/Settings.cs b/DML.Core/Classes/Settings.cs
new file mode 100644
index 0000000..0466c97
--- /dev/null
+++ b/DML.Core/Classes/Settings.cs
@@ -0,0 +1,38 @@
+using System.Diagnostics;
+
+namespace DML.Core.Classes
+{
+ internal class Settings
+ {
+ public int Id { get; } = 1; // using always unique ID
+ public string Email { get; set; }
+ public string Password { get; set; }
+ public string LoginToken { get; set; }
+ public bool UseUserData { get; set; } = false;
+ public bool SavePassword { get; set; } = false;
+ public LogLevel ApplicactionLogLevel { get; set; } = LogLevel.Info | LogLevel.Warn | LogLevel.Error;
+ public string OperatingFolder { get; set; }
+ public string FileNameScheme { get; set; } = @"%guild%\%channel%\%id%";
+ public bool SkipExistingFiles { get; set; } = true;
+ public int ThreadLimit { get; set; } = 50;
+
+ internal void Store()
+ {
+ Trace("Getting settings collection...");
+ var settingsDB = DML.Core.Core.Database.GetCollection("settings");
+
+ Debug("Storing settings to database...");
+
+ if (settingsDB.Exists(_setting => _setting.Id == Id))
+ {
+ Trace("Updating existing value...");
+ settingsDB.Update(this);
+ }
+ else
+ {
+ Trace("Adding new value...");
+ settingsDB.Insert(this);
+ }
+ }
+ }
+}
diff --git a/DML.Core/Core.cs b/DML.Core/Core.cs
new file mode 100644
index 0000000..ffd7e14
--- /dev/null
+++ b/DML.Core/Core.cs
@@ -0,0 +1,260 @@
+using System;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Discord;
+using Discord.Net;
+using Discord.WebSocket;
+using DML.Core.Classes;
+
+namespace DML.Core
+{
+ public static class Core
+ {
+ internal static DiscordSocketClient Client { get; set; }
+ internal static LiteDatabase Database { get; set; }
+ internal static Settings Settings { get; set; }
+ internal static JobScheduler Scheduler { get; } = new JobScheduler();
+
+ internal static string DataDirectory
+ => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Serraniel\Discord Media Loader");
+
+ 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");
+ 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 static Task Client_Connected()
+ {
+ Debug("Connected");
+ return Task.CompletedTask;
+ }
+
+ //TODO: this is thrid time we implement this.....this has to be fixed!!!
+ private static SocketGuild FindServerById(ulong id)
+ {
+ Trace($"Trying to find server by Id: {id}");
+ return (from s in Core.Client.Guilds where s.Id == id select s).FirstOrDefault();
+ }
+
+ private static SocketTextChannel FindChannelById(SocketGuild server, ulong id)
+ {
+ Trace($"Trying to find channel in {server} by id: {id}");
+ return (from c in server.TextChannels where c.Id == id select c).FirstOrDefault();
+ }
+ }
+}
diff --git a/DML.Core/DML.Core.Old.csproj b/DML.Core/DML.Core.Old.csproj
new file mode 100644
index 0000000..438b9a8
--- /dev/null
+++ b/DML.Core/DML.Core.Old.csproj
@@ -0,0 +1,15 @@
+
+
+
+ netcoreapp1.1
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Discord Media Loader.Application/Classes/Core.cs b/Discord Media Loader.Application/Classes/Core.cs
new file mode 100644
index 0000000..c740049
--- /dev/null
+++ b/Discord Media Loader.Application/Classes/Core.cs
@@ -0,0 +1,297 @@
+using System;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Runtime;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using Discord;
+using Discord.WebSocket;
+using DML.AppCore.Classes;
+using DML.Application.Dialogs;
+using DML.Client;
+using LiteDB;
+using SharpRaven;
+using SharpRaven.Data;
+using SweetLib.Utils;
+using SweetLib.Utils.Logger;
+using SweetLib.Utils.Logger.Memory;
+using Logger = SweetLib.Utils.Logger.Logger;
+
+namespace DML.Application.Classes
+{
+ public static class Core
+ {
+ //internal static DiscordSocketClient Client { get; set; }
+ internal static LiteDatabase Database { get; set; }
+ internal static Settings Settings { get; set; }
+ internal static JobScheduler Scheduler { get; } = new JobScheduler();
+ internal static RavenClient Raven = new RavenClient("https://0de964231669473e9098b9f6cc1d6278:79d9f2eb24034de199b2a37cc058e0f2@sentry.io/257114");
+
+ internal static string DataDirectory
+ => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Serraniel\Discord Media Loader");
+
+ 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");
+ 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();
+ }
+
+ 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...");
+ var abort = false;
+
+ DMLClient.Client.Connected += Client_Connected;
+
+ var loggedIn = false;
+
+ while (!loggedIn)
+ {
+ if (!string.IsNullOrEmpty(Settings.LoginToken))
+ {
+ Logger.Debug("Trying to login with last known token...");
+ loggedIn= await DMLClient.Login(Settings.LoginToken);
+ }
+
+ if (!loggedIn)
+ {
+ Logger.Debug("Showing dialog for username and password...");
+ var loginDlg = new LoginDialog();
+ loginDlg.ShowDialog();
+ }
+ }
+
+ /*while ((Client.LoginState != LoginState.LoggedIn || Client.ConnectionState!=ConnectionState.Connected) && !abort)
+ {
+ Logger.Debug(Client.ConnectionState.ToString());
+ Logger.Debug(Client.LoginState.ToString());
+
+ Logger.Trace("Entering login loop.");
+
+ try
+ {
+ if (Client.ConnectionState == ConnectionState.Connecting)
+ continue;
+
+ if (!string.IsNullOrEmpty(Settings.LoginToken))
+ {
+ Logger.Debug("Trying to login with last known token...");
+ await Client.LoginAsync(TokenType.User, Settings.LoginToken);
+ await Client.StartAsync();
+ await Task.Delay(1000);
+ }
+
+ }
+ catch (HttpException ex)
+ {
+ Logger.Warn($"Login seems to have failed or gone wrong: {ex.GetType().Name} - {ex.Message}");
+ }
+
+ if (Client.LoginState == LoginState.LoggedOut)
+ {
+ Settings.Password = string.Empty;
+ Logger.Debug("Showing dialog for username and password...");
+ var loginDlg = new LoginDialog();
+ loginDlg.ShowDialog();
+ Logger.Trace("Dialog closed.");
+ }
+ }*/
+
+ 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} 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));
+ }
+ }
+
+ private static Task Client_Connected()
+ {
+ Logger.Debug("Connected");
+ return Task.CompletedTask;
+ }
+
+ //TODO: this is thrid time we implement this.....this has to be fixed!!!
+ private static SocketGuild FindServerById(ulong id)
+ {
+ Logger.Trace($"Trying to find server by Id: {id}");
+ return (from s in DMLClient.Client.Guilds where s.Id == id select s).FirstOrDefault();
+ }
+
+ private static SocketTextChannel FindChannelById(SocketGuild server, ulong id)
+ {
+ Logger.Trace($"Trying to find channel in {server} by id: {id}");
+ return (from c in server.TextChannels where c.Id == id select c).FirstOrDefault();
+ }
+ }
+}
diff --git a/Discord Media Loader.Application/Classes/Job.cs b/Discord Media Loader.Application/Classes/Job.cs
new file mode 100644
index 0000000..0a6d57c
--- /dev/null
+++ b/Discord Media Loader.Application/Classes/Job.cs
@@ -0,0 +1,188 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Discord;
+using Discord.WebSocket;
+using DML.Application.Classes;
+using DML.Client;
+using SweetLib.Utils;
+using static SweetLib.Utils.Logger.Logger;
+
+namespace DML.AppCore.Classes
+{
+ public class Job
+ {
+ public int Id { get; set; }
+ public ulong GuildId { get; set; }
+ public ulong ChannelId { get; set; }
+ public double KnownTimestamp { get; set; } = 0;
+ private double StopTimestamp { get; set; } = 0;
+ private bool IsValid { get; set; } = true;
+
+ internal void Store()
+ {
+ Debug("Storing job to database...");
+ Trace("Getting jobs collection...");
+ var jobDb = Core.Database.GetCollection("jobs");
+
+ Trace("Adding new value...");
+
+ if (jobDb.Find(x => x.ChannelId == ChannelId && x.GuildId == GuildId).Any())
+ {
+ jobDb.Update(this);
+ }
+ else
+ {
+ jobDb.Insert(this);
+ }
+ }
+
+ public void Delete()
+ {
+ Debug("Deleting job from database...");
+ Trace("Getting jobs collection...");
+ var jobDb = Core.Database.GetCollection("jobs");
+
+ Trace("Deleting value...");
+ jobDb.Delete(Id);
+ }
+
+ private SocketGuild FindServerById(ulong id)
+ {
+ Trace($"Trying to find server by Id: {id}");
+ return (from s in DMLClient.Client.Guilds where s.Id == id select s).FirstOrDefault();
+ }
+
+ private SocketTextChannel FindChannelById(SocketGuild server, ulong id)
+ {
+ Trace($"Trying to find channel in {server} by id: {id}");
+ return (from c in server.TextChannels where c.Id == id select c).FirstOrDefault();
+ }
+
+ internal async Task> Scan()
+ {
+ Debug($"Starting scan of guild {GuildId} channel {ChannelId}...");
+ var result = new List();
+
+ var limit = 100;
+ var lastId = ulong.MaxValue;
+ var isFirst = true;
+ var finished = false;
+
+ var guild = FindServerById(GuildId);
+ var channel = FindChannelById(guild, ChannelId);
+
+ Debug("Checking channel access");
+ if (!channel.Users.Contains(channel.Guild.CurrentUser))
+ {
+ Info("Skipping channel without access");
+ return result;
+ }
+
+ if (Math.Abs(StopTimestamp) < 0.4)
+ StopTimestamp = KnownTimestamp;
+ Trace("Initialized scanning parameters.");
+
+ while (!finished)
+ {
+ Trace("Entering scanning loop...");
+ var messages = new List();
+
+ Trace($"Downloading next {limit} messages...");
+ if (isFirst)
+ {
+ //messages = await channel.GetMessagesAsync(limit).ToArray() as SocketMessage[];
+ var realMessages = await channel.GetMessagesAsync(limit).ToArray();
+
+ foreach (var realMessageArray in realMessages)
+ {
+ foreach (var realMessage in realMessageArray)
+ {
+ messages.Add(realMessage);
+ }
+ }
+ }
+ else
+ {
+ var realMessages = await channel.GetMessagesAsync(lastId, Direction.Before, limit).ToArray();
+
+ foreach (var realMessageArray in realMessages)
+ {
+ foreach (var realMessage in realMessageArray)
+ {
+ messages.Add(realMessage);
+ }
+ }
+
+ //messages = await channel.GetMessagesAsync(lastId, Direction.Before, limit).ToArray() as SocketMessage[];
+ }
+ Trace($"Downloaded {messages.Count} 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);
+ Core.Scheduler.TotalAttachments += (ulong)m.Attachments.Count;
+ Trace($"Added message {m.Id}");
+ }
+ Debug($"Finished message {m.Id}");
+
+ Core.Scheduler.MessagesScanned++;
+ }
+
+ finished = finished || messages.Count < 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 void Stop()
+ {
+ IsValid = false;
+ }
+
+ public static IEnumerable RestoreJobs()
+ {
+ Debug("Restoring jobs...");
+ Trace("Getting jobs collection...");
+ var jobDb = Core.Database.GetCollection("jobs");
+
+ Trace("Creating new empty job list");
+ return jobDb.FindAll();
+ }
+ }
+}
diff --git a/Discord Media Loader.Application/Classes/JobScheduler.cs b/Discord Media Loader.Application/Classes/JobScheduler.cs
new file mode 100644
index 0000000..156a131
--- /dev/null
+++ b/Discord Media Loader.Application/Classes/JobScheduler.cs
@@ -0,0 +1,296 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
+using Discord;
+using Discord.WebSocket;
+using DML.Application.Classes;
+using SweetLib.Utils;
+using SweetLib.Utils.Logger;
+
+namespace DML.AppCore.Classes
+{
+ public class JobScheduler
+ {
+ private ulong messageScanned = 0;
+ private ulong totalAttachments = 0;
+ private ulong attachmentsDownloaded = 0;
+
+ private bool Run { get; set; } = false;
+ public List JobList { get; set; } = new List();
+ public Dictionary> RunningJobs = new Dictionary>();
+ internal int RunningThreads { get; set; } = 0;
+
+ internal ulong MessagesScanned
+ {
+ get
+ {
+ lock (this)
+ {
+ return messageScanned;
+ }
+ }
+ set
+ {
+ lock (this)
+ {
+ messageScanned = value;
+ }
+ }
+ }
+
+ internal ulong TotalAttachments
+ {
+ get
+ {
+ lock (this)
+ {
+ return totalAttachments;
+ }
+ }
+ set
+ {
+ lock (this)
+ {
+ totalAttachments = value;
+ }
+ }
+ }
+
+ internal ulong AttachmentsDownloaded
+ {
+ get
+ {
+ lock (this)
+ {
+ return attachmentsDownloaded;
+ }
+ }
+ set
+ {
+ lock (this)
+ {
+ attachmentsDownloaded = value;
+ }
+ }
+ }
+
+ public void Stop()
+ {
+ Run = false;
+ }
+
+ public void Start()
+ {
+ Run = true;
+
+ Task.Run(async () =>
+ {
+ Logger.Info("Started JobScheduler...");
+ while (Run)
+ {
+ Logger.Debug("Entering job list handler loop...");
+ //foreach (var job in JobList)
+ for (var i = JobList.Count - 1; i >= 0; i--)
+ {
+ var job = JobList[i];
+ Logger.Debug($"Checking job {job}");
+ var hasJob = false;
+
+ Logger.Trace("Locking scheduler...");
+ lock (this)
+ {
+ Logger.Trace("Checking if job is already performed...");
+ hasJob = RunningJobs.ContainsKey(job.Id);
+ }
+ Logger.Trace("Unlocked scheduler.");
+
+ if (!hasJob)
+ {
+ Logger.Debug("Job is not performed yet...Performing job...");
+ var queue = new Queue();
+
+ Logger.Trace("Locking scheduler...");
+ lock (this)
+ {
+ Logger.Trace("Adding job to running jobs.");
+ RunningJobs.Add(job.Id, queue);
+ }
+ Logger.Trace("Unlocked scheduler.");
+
+ Logger.Trace("Issuing job message scan...");
+ var messages = await job.Scan();
+
+ if (messages == null)
+ continue;
+
+ Logger.Trace($"Adding {messages.Count} messages to queue...");
+ foreach (var msg in messages)
+ {
+ queue.Enqueue(msg);
+ }
+ Logger.Trace($"Added {queue.Count} messages to queue.");
+
+ if (messages.Count != queue.Count)
+ Logger.Warn("Not all messages have been added into the queue.");
+
+ var startedDownload = false;
+
+ while (!startedDownload)
+ {
+ Logger.Debug("Entering loop to check thread availability");
+ Logger.Trace("Locking scheduler...");
+ lock (this)
+ {
+ Logger.Trace($"Checking thread limit. Running: {RunningThreads}, Max: {Core.Settings.ThreadLimit}");
+ if (RunningThreads >= Core.Settings.ThreadLimit)
+ continue;
+
+ RunningThreads++;
+ startedDownload = true;
+ }
+ Logger.Trace("Unlocked scheduler.");
+ }
+
+ Logger.Trace("Start downloading job async.");
+ Task.Run(() => WorkQueue(job.Id)); // do not await to work parallel
+ }
+ }
+ }
+ });
+ }
+
+ private void WorkQueue(int jobId)
+ {
+ try
+ {
+ Logger.Debug("Beginning job download...");
+ Logger.Trace("Finding job...");
+ var job = (from j in JobList where j.Id == jobId select j).FirstOrDefault();
+
+ if (job == null)
+ {
+ Logger.Warn($"Associating job not found! JobId: {jobId}");
+ return;
+ }
+ Logger.Trace("Found job.");
+
+ Queue queue;
+ Logger.Trace("Locking scheduler...");
+ lock (this)
+ {
+ Logger.Trace("Finiding queue...");
+ if (!RunningJobs.TryGetValue(jobId, out queue))
+ {
+ Logger.Warn($"Queue for job {jobId} not found!");
+ return;
+ }
+ Logger.Trace("Queue found.");
+ }
+ Logger.Trace("Unlocked scheduler.");
+
+ Logger.Debug($"Messages to process for job {jobId}: {queue.Count}");
+ while (queue.Count > 0)
+ {
+ Logger.Trace("Locking scheduler...");
+ lock (this)
+ {
+ Logger.Trace("Checking if still a job...");
+ if (!RunningJobs.ContainsKey(jobId))
+ {
+ Logger.Warn($"Queue for job {jobId} not found!");
+ return;
+ }
+ Logger.Trace("Continue working...");
+ }
+ Logger.Trace("Unlocked scheduler.");
+
+ Logger.Trace("Dequeueing message...");
+ var message = queue.Dequeue();
+
+ Logger.Debug($"Attachments for message {message.Id}: {message.Attachments.Count}");
+ foreach (var a in message.Attachments)
+ {
+ try
+ {
+ var fileName = Path.Combine(Core.Settings.OperatingFolder, Core.Settings.FileNameScheme);
+
+ Logger.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;
+ serverName = Path.GetInvalidFileNameChars().Aggregate(serverName, (current, c) => current.Replace(c, ' '));
+ }
+
+ var channelName = message.Channel.Name;
+ channelName = Path.GetInvalidFileNameChars().Aggregate(channelName, (current, c) => current.Replace(c, ' '));
+
+ fileName =
+ fileName.Replace("%guild%", serverName)
+ .Replace("%channel%", channelName)
+ .Replace("%timestamp%", SweetUtils.DateTimeToUnixTimeStamp(message.CreatedAt.UtcDateTime).ToString())
+ .Replace("%name%", a.Filename)
+ .Replace("%id%", a.Id.ToString());
+
+ if (extensionRequired)
+ fileName += Path.GetExtension(a.Filename);
+
+ Logger.Trace($"Detemined file name: {fileName}.");
+
+
+ if (File.Exists(fileName) && new FileInfo(fileName).Length == a.Size)
+ {
+ Logger.Debug($"{fileName} already existing with its estimated size. Skipping...");
+ continue;
+ }
+
+ Logger.Trace("Determining directory...");
+ var fileDirectory = Path.GetDirectoryName(fileName);
+
+ if (!Directory.Exists(fileDirectory))
+ {
+ Logger.Info($"Directory {fileDirectory} does not exist. Creating directory...");
+ Directory.CreateDirectory(fileDirectory);
+ Logger.Debug("Created directory.");
+ }
+
+ var wc = new WebClient();
+ Logger.Debug($"Starting downloading of attachment {a.Id}...");
+
+ wc.DownloadFile(new Uri(a.Url), fileName);
+ Logger.Debug($"Downloaded attachment {a.Id}.");
+
+ Logger.Trace("Updating known timestamp for job...");
+ job.KnownTimestamp = SweetUtils.DateTimeToUnixTimeStamp(message.CreatedAt.UtcDateTime);
+ job.Store();
+ }
+ finally
+ {
+ AttachmentsDownloaded++;
+ }
+ }
+ }
+ }
+ finally
+ {
+ Logger.Trace("Locking scheduler...");
+ lock (this)
+ {
+ Logger.Trace($"Removing {jobId} from running jobs...");
+ RunningJobs.Remove(jobId);
+ Logger.Trace("Decreasing thread count...");
+ RunningThreads--;
+ }
+ Logger.Trace("Unlocked scheduler.");
+ }
+ }
+ }
+}
diff --git a/Discord Media Loader.Application/Classes/Settings.cs b/Discord Media Loader.Application/Classes/Settings.cs
new file mode 100644
index 0000000..a9544ee
--- /dev/null
+++ b/Discord Media Loader.Application/Classes/Settings.cs
@@ -0,0 +1,38 @@
+using SweetLib.Utils.Logger;
+
+namespace DML.Application.Classes
+{
+ public class Settings
+ {
+ public int Id { get; } = 1; // using always unique ID
+ public string Email { get; set; }
+ public string Password { get; set; }
+ public string LoginToken { get; set; }
+ public bool UseUserData { get; set; } = false;
+ public bool SavePassword { get; set; } = false;
+ public LogLevel ApplicactionLogLevel { get; set; } = LogLevel.Info | LogLevel.Warn | LogLevel.Error;
+ public string OperatingFolder { get; set; }
+ public string FileNameScheme { get; set; } = @"%guild%\%channel%\%id%";
+ public bool SkipExistingFiles { get; set; } = true;
+ public int ThreadLimit { get; set; } = 50;
+
+ public void Store()
+ {
+ Logger.Trace("Getting settings collection...");
+ var settingsDB = Core.Database.GetCollection("settings");
+
+ Logger.Debug("Storing settings to database...");
+
+ if (settingsDB.Exists(_setting => _setting.Id == Id))
+ {
+ Logger.Trace("Updating existing value...");
+ settingsDB.Update(this);
+ }
+ else
+ {
+ Logger.Trace("Adding new value...");
+ settingsDB.Insert(this);
+ }
+ }
+ }
+}
diff --git a/Discord Media Loader.Application/DML.Application.csproj b/Discord Media Loader.Application/DML.Application.csproj
new file mode 100644
index 0000000..02bf1f5
--- /dev/null
+++ b/Discord Media Loader.Application/DML.Application.csproj
@@ -0,0 +1,230 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {C130DE6A-3237-42B5-BE9F-783D1CD104C6}
+ Library
+ Properties
+ DML.Application
+ Discord Media Loader.Application
+ v4.6.1
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Discord.Net.Commands.1.0.2\lib\netstandard1.1\Discord.Net.Commands.dll
+
+
+ ..\packages\Discord.Net.Core.1.0.2\lib\net45\Discord.Net.Core.dll
+
+
+ ..\packages\Discord.Net.Rest.1.0.2\lib\net45\Discord.Net.Rest.dll
+
+
+ ..\packages\Discord.Net.Rpc.1.0.2\lib\net45\Discord.Net.Rpc.dll
+
+
+ ..\packages\Discord.Net.Webhook.1.0.2\lib\netstandard1.1\Discord.Net.Webhook.dll
+
+
+ ..\packages\Discord.Net.WebSocket.1.0.2\lib\net45\Discord.Net.WebSocket.dll
+
+
+ ..\packages\LiteDB.3.1.0\lib\net35\LiteDB.dll
+ True
+
+
+ ..\packages\Microsoft.Extensions.DependencyInjection.1.1.1\lib\netstandard1.1\Microsoft.Extensions.DependencyInjection.dll
+
+
+ ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.1.1\lib\netstandard1.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
+
+
+ ..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll
+
+
+ ..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll
+
+
+ ..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.dll
+ True
+
+
+ ..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.Concurrent.dll
+ True
+
+
+ ..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.Enlightenment.dll
+ True
+
+
+ ..\packages\RestSharp.105.2.3\lib\net46\RestSharp.dll
+ True
+
+
+ ..\packages\SharpRaven.2.2.0\lib\net45\SharpRaven.dll
+
+
+
+ ..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll
+
+
+ ..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+ True
+
+
+
+ ..\packages\System.Console.4.3.0\lib\net46\System.Console.dll
+
+
+
+ ..\packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll
+
+
+
+ ..\packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll
+
+
+ ..\packages\System.Interactive.Async.3.1.1\lib\net46\System.Interactive.Async.dll
+
+
+ ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll
+ True
+
+
+
+ ..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll
+
+
+ ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll
+
+
+ ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll
+
+
+ ..\packages\System.Net.Http.4.3.0\lib\net46\System.Net.Http.dll
+
+
+ ..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll
+
+
+
+ ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll
+ True
+
+
+ ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll
+
+
+ ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll
+
+
+ ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll
+
+
+ ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll
+
+
+
+
+
+
+
+
+ ..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll
+
+
+ ..\packages\WebSocket4Net.0.14.1\lib\net45\WebSocket4Net.dll
+ True
+
+
+
+
+
+
+
+ Form
+
+
+ LoginDialog.cs
+
+
+ Form
+
+
+ FrmInternalSplash.cs
+
+
+ Form
+
+
+ MainForm.cs
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+ LoginDialog.cs
+
+
+ FrmInternalSplash.cs
+
+
+ MainForm.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+
+
+
+ {02c1f8ef-32f2-4e77-a36d-79129402af37}
+ SweetLib
+
+
+ {045eb4a1-34e7-47e0-867e-e10c40505095}
+ DML.Client
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Discord Media Loader.Application/Dialogs/LoginDialog.Designer.cs b/Discord Media Loader.Application/Dialogs/LoginDialog.Designer.cs
new file mode 100644
index 0000000..0a48921
--- /dev/null
+++ b/Discord Media Loader.Application/Dialogs/LoginDialog.Designer.cs
@@ -0,0 +1,129 @@
+namespace DML.Application.Dialogs
+{
+ partial class LoginDialog
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LoginDialog));
+ this.pnlButtons = new System.Windows.Forms.Panel();
+ this.btnAbort = new System.Windows.Forms.Button();
+ this.btnOk = new System.Windows.Forms.Button();
+ this.lbHowToToken = new System.Windows.Forms.Label();
+ this.edToken = new System.Windows.Forms.TextBox();
+ this.lbToken = new System.Windows.Forms.Label();
+ this.pnlButtons.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // pnlButtons
+ //
+ this.pnlButtons.BackColor = System.Drawing.SystemColors.ButtonShadow;
+ this.pnlButtons.Controls.Add(this.btnAbort);
+ this.pnlButtons.Controls.Add(this.btnOk);
+ this.pnlButtons.Dock = System.Windows.Forms.DockStyle.Bottom;
+ this.pnlButtons.Location = new System.Drawing.Point(0, 168);
+ this.pnlButtons.Name = "pnlButtons";
+ this.pnlButtons.Size = new System.Drawing.Size(426, 51);
+ this.pnlButtons.TabIndex = 0;
+ //
+ // btnAbort
+ //
+ this.btnAbort.Location = new System.Drawing.Point(348, 16);
+ this.btnAbort.Name = "btnAbort";
+ this.btnAbort.Size = new System.Drawing.Size(75, 23);
+ this.btnAbort.TabIndex = 1;
+ this.btnAbort.Text = "&Abort";
+ this.btnAbort.UseVisualStyleBackColor = true;
+ this.btnAbort.Click += new System.EventHandler(this.btnAbort_Click);
+ //
+ // btnOk
+ //
+ this.btnOk.Location = new System.Drawing.Point(267, 16);
+ this.btnOk.Name = "btnOk";
+ this.btnOk.Size = new System.Drawing.Size(75, 23);
+ this.btnOk.TabIndex = 0;
+ this.btnOk.Text = "&Ok";
+ this.btnOk.UseVisualStyleBackColor = true;
+ this.btnOk.Click += new System.EventHandler(this.btnOk_Click);
+ //
+ // lbHowToToken
+ //
+ this.lbHowToToken.Location = new System.Drawing.Point(7, 58);
+ this.lbHowToToken.Name = "lbHowToToken";
+ this.lbHowToToken.Size = new System.Drawing.Size(412, 87);
+ this.lbHowToToken.TabIndex = 5;
+ this.lbHowToToken.Text = resources.GetString("lbHowToToken.Text");
+ //
+ // edToken
+ //
+ this.edToken.Location = new System.Drawing.Point(79, 12);
+ this.edToken.Name = "edToken";
+ this.edToken.Size = new System.Drawing.Size(335, 20);
+ this.edToken.TabIndex = 4;
+ //
+ // lbToken
+ //
+ this.lbToken.AutoSize = true;
+ this.lbToken.Location = new System.Drawing.Point(7, 15);
+ this.lbToken.Name = "lbToken";
+ this.lbToken.Size = new System.Drawing.Size(66, 13);
+ this.lbToken.TabIndex = 3;
+ this.lbToken.Text = "Login token:";
+ //
+ // LoginDialog
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(426, 219);
+ this.Controls.Add(this.lbHowToToken);
+ this.Controls.Add(this.edToken);
+ this.Controls.Add(this.lbToken);
+ this.Controls.Add(this.pnlButtons);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "LoginDialog";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "LoginForm";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.LoginDialog_FormClosing);
+ this.Shown += new System.EventHandler(this.LoginDialog_Shown);
+ this.pnlButtons.ResumeLayout(false);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Panel pnlButtons;
+ private System.Windows.Forms.Button btnAbort;
+ private System.Windows.Forms.Button btnOk;
+ private System.Windows.Forms.Label lbHowToToken;
+ private System.Windows.Forms.TextBox edToken;
+ private System.Windows.Forms.Label lbToken;
+ }
+}
\ No newline at end of file
diff --git a/Discord Media Loader.Application/Dialogs/LoginDialog.cs b/Discord Media Loader.Application/Dialogs/LoginDialog.cs
new file mode 100644
index 0000000..a995bb1
--- /dev/null
+++ b/Discord Media Loader.Application/Dialogs/LoginDialog.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Windows.Forms;
+using DML.Application.Classes;
+using static SweetLib.Utils.Logger.Logger;
+
+namespace DML.Application.Dialogs
+{
+ public partial class LoginDialog : Form
+ {
+ public LoginDialog()
+ {
+ InitializeComponent();
+ }
+
+ private void LoginDialog_Shown(object sender, EventArgs e)
+ {
+ Trace("Login dialog shown.");
+ edToken.Text = Core.Settings.LoginToken;
+ }
+
+ private void LoginDialog_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ Trace($"Closing login dialog. Result: {DialogResult}");
+ if (DialogResult != DialogResult.OK)
+ return;
+
+ Debug("Adjusting login settings...");
+ Core.Settings.LoginToken = edToken.Text;
+
+ Core.Settings.Store();
+ }
+
+ private void btnOk_Click(object sender, EventArgs e)
+ {
+ Trace("btnOk pressed.");
+ DialogResult = DialogResult.OK;
+ }
+
+ private void btnAbort_Click(object sender, EventArgs e)
+ {
+ Trace("btnAbort pressed.");
+ DialogResult = DialogResult.Abort;
+ }
+ }
+}
diff --git a/Discord Media Loader.Application/Dialogs/LoginDialog.resx b/Discord Media Loader.Application/Dialogs/LoginDialog.resx
new file mode 100644
index 0000000..0ffe195
--- /dev/null
+++ b/Discord Media Loader.Application/Dialogs/LoginDialog.resx
@@ -0,0 +1,413 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ To find your login token please start Discord and press Ctrl + Shift + I shortcut. A browser inspector will open.
+Navigate into the "Application" tab and select "Local Storage" / "https://discordapp.com". If the right site keeps blank use "Session Storage" instead.
+Look for the token key and copy its value without the quotation marks.
+
+
+
+
+ AAABAAEAQEAAAAEAIAAoQgAAFgAAACgAAABAAAAAgAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8b////VP///3////+m////zP//
+ /+T////1//////////r////u////3f///8z///+m////f////1T///8b////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////M////5D////b////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /9v///+Q////M////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///w3///90////1v//
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////W////dP///w3///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A2K4AANiuAADYrgAA2K4AANiuAADfswAA////EP//
+ /4D////t////////////////////////////////////////////////9/zq/7XiQ/+340n/w+ho/9Pu
+ kf/m9b//+Pzt///////////////////////////////////////////////////////////t////gf//
+ /xCa2AAAmtgAAJrYAACa2AAAmtgAAJrYAAD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////ANiuAADYrgAA2K4AANiu
+ AAD///8B////Yf///+v//////////////////////////////////////////////////////////+z4
+ z/+a2AD/mtgA/5rYAP+a2AD/mtgA/6TcGf+65VL/3fKo//n98P//////////////////////////////
+ ///////////////////////r////Yf///wGa2AAAmtgAAJrYAACa2AAA////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wDYrgAA2K4AANiuAAD///8k////xP//////////////////////////////////////////////////
+ ///////////////////h87P/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+n3SD/zOt+//X7
+ 5v/////////////////////////////////////////////////////E////I5rYAACa2AAAmtgAAP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A2K4AANiuAAD///9V////8f//////////////////////////////////
+ ////////////////////////////////////////0+6Q/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+k3Bn/0e2K//v+9v//////////////////////////////////////////////
+ //H///9VmtgAAJrYAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wH///+M////////////////////////
+ /////////////////////////////////////////////////////////////8bpbv+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+u4DP/5/bD////////////////////
+ /////////////////////////////////4z///8B////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wb///+l////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //+55E//mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5zZ
+ Bv/P7Ib/////////////////////////////////////////////////////pf///wb///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wb///+3////////////////////////////////////////////////////////////////////////
+ ///////////////////+//3/rd8x/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/7zlV//5/fH/////////////////////////////////////////
+ //////+3////Bv///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wH///+k////////////////////////////////////////////////////////
+ ////////////////////////////////////////+f3v/6PcF/+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/seE7//X75v//////////////
+ /////////////////////////////////6T///8B////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///+K////////////////////////////////////////
+ /////////////////////////////////////////////////////////////+751f+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+s3y7/9Pvi////////////////////////////////////////////////i////wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///9V////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///s+M//rd8w/6XcHf+c2Qb/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/6zfLv/1++f/////////////////////////////////////////
+ //////9V////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8j////8P//
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////v/6/fL/8PnZ/97yrP/E6Gv/qd4l/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/suE8//v99P//////////////
+ ////////////////////////////8P///yP///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8B////xP//////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////v9
+ 9f/e8qz/s+JA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP/A51/////////////////////////////////////////////////E////Af///wD///8A////AP//
+ /wD///8A////AP///wD///8A////Yf//////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////f867/rN8t/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/9jwnP//////////////////////////////////////////////
+ /2H///8A////AP///wD///8A////AP///wD///8A////EP///+r/////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////r98//I6nX/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+h2xL/8/rh////////////////////
+ ///////////////////////q////Ev///wD///8A////AP///wD///8A////AP///3//////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////9/yrf+h2xL/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/8Dn
+ X////////////////////////////////////////////////4D///8A////AP///wD///8A////AP//
+ /w3////u////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////7PjQ/6reKP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+c2QX/7vjT///////////////////////////////////////////u////Df//
+ /wD///8A////AP///wD///90////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////0++L/qd4n/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/8PoaP//////////////////////////////
+ /////////////////3T///8A////AP///wD///8B////2///////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////+360P+k4g3/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+j2xb/+Pzu////
+ ///////////////////////////////////////b////Af///wD///8A////O///////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////wNCY/53dAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/9/zr////////////////////////////////////////////////zv///8A////AP//
+ /5D/////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////f39/+Puin/n+AA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP/F6W3/////////////////////////////////////////
+ //////+Q////AP///wD////Y////////////////////////////////////////////////////////
+ /////////////////////////////+3t7f+3t7f/jIyM/3Nzc/9oaGj/a2tr/35+fv+dnZ3/xsbG//Hx
+ 8f//////////////////////////////////////////////////////////////////////////////
+ ////////iZNy/5zbAP+b2QD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/s+JA////////////////////
+ ////////////////////////////2f///wD///8d////////////////////////////////////////
+ ////////////////////////////////////////9fTx/46Pk/9BQUH/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv9ERET/fn5+/8rKyv//////////////////////////////////////////////
+ /////////////////////////////4iHjP98qA3/n+AA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/6ne
+ J/////////////////////////////////////////////////////8e////Vv//////////////////
+ ////////////////////////////////////////////////////////+fDL/45/Qv8kJjH/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Xl5e/7e3t//+/v7/////////
+ //////////////////////////////////////////////////9vbXX/T2Ig/57fAP+a2QD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+l3Bz/////////////////////////////////////////////////////Vv//
+ /4T/////////////////////////////////////////////////////////////////////8+ax/+O5
+ D/92ZBv/JCYx/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/YGBg/8jIyP/////////////////////////////////////////////////09PT/QkJE/zEz
+ Lf+Mwgb/nd0A/5rYAP+a2AD/mtgA/5rYAP+a2AD/pdwb////////////////////////////////////
+ /////////////////4T///+t////////////////////////////////////////////////////////
+ ////////8+ez/9mwB//htQD/dWMb/yQnMf8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/dHR0/97e3v//////////////////////////////
+ ////////r6+v/y4uLv8nIzH/bZET/6HiAP+a2AD/mtgA/5rYAP+a2AD/mtgA/6neJv//////////////
+ //////////////////////////////////////+t////zP//////////////////////////////////
+ ////////////////////////+PHS/9qyDv/YrgD/4rUA/3lmGf8kJjH/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Ozs7/1ZWVv90dHT/jo6O/5mZmf/Hx8f//v7+////
+ ////////////////////////7+/v/0dHR/8uLi7/KCUw/1BkH/+f4AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+z4T7/////////////////////////////////////////////////////zP///+X/////////////
+ /////////////////////////////////////////v35/+C/N//YrgD/2K4A/+O2AP+Dbhf/IyYx/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/1VVVf+QkJD/xsbG/+rq6v//////////////
+ ////////////////////////////////////////+vr6/2tra/8uLi7/Li4u/yspL/86Qij/ltEC/5va
+ AP+a2AD/mtgA/5rYAP+a2AD/x+ly////////////////////////////////////////////////////
+ /+D////y//////////////////////////////////////////////////////Dfm//YrgD/2K4A/9iu
+ AP/itQD/k3oT/yUnMf8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/cHBw/8bGxv/8/Pz/////////
+ ////////////////////////////////////////////////////////7+/v/3BwcP8uLi7/Li4u/y4u
+ Lv8tLC7/Ly8u/4e7CP+e3gD/mtgA/5rYAP+a2AD/mtgA/+X1vf//////////////////////////////
+ ///////////////////////s//////////////////////////////////////////////////////79
+ +f/euyr/2K4A/9iuAP/YrgD/4LQA/6iKDf8oKTD/Li4u/y4uLv8uLi7/Li4u/y4uLv9QUFD/xMTE////
+ ////////////////////////////////////////////////////////////////////////w8PD/1BQ
+ UP8uLi7/Li4u/y4uLv8uLi7/Li4u/yknMP95pA7/n+EA/5rYAP+a2AD/mtgA/6neJ//8/vj/////////
+ ////////////////////////////////////////////+f//////////////////////////////////
+ ///////////////////168D/2K4A/9iuAP/YrgD/2K4A/92yAP+/mwf/MTAt/ywtLv8uLi7/Li4u/y4u
+ Lv9wcHD/8PDw//////////////////////////////////////////////////////////////////r6
+ +v/ExMT/bm5u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8oJDH/a44U/6HiAP+a2AD/mtgA/5rY
+ AP/W75j///////////////////////////////////////////////////////////n////y////////
+ ////////////////////////////////////////6tR3/9iuAP/YrgD/2K4A/9iuAP/arwD/06oB/0VA
+ J/8pKi//Li4u/y4uLv9ra2v/+vr6//////////////////////////////////////////////////39
+ /f/n5+f/wsLC/4yMjP9SUlL/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/JyMx/2F+
+ GP+h4wD/mtgA/5rYAP+v4DX//P74////////////////////////////////////////////////////
+ ///////s////5f///////////////////////////////////////////////+LDQv/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/+C0AP9oWh7/JCcx/y4uLv9GRkb/7u7u/////////////////////////////v7+/8fH
+ x/+VlZX/iYmJ/3BwcP9TU1P/OTk5/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/ygkMf9bdRv/oOEA/5rYAP+g2g7/7fjR////////////////////////////////////
+ ////////////////////////////4P///8z/////////////////////////////////////////////
+ ///euyj/2K4A/9iuAP/YrgD/2K4A/9iuAP/itQD/ln0S/yQnMf8uLi7/ra2t////////////////////
+ ///////////////////i4uL/e3t7/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8oJDH/WXEc/6DhAP+d2Qf/4fOy////////////////////
+ /////////////////////////////////////////////////8z///+t////////////////////////
+ ////////////////////////3Lcc/9iuAP/YrgD/2K4A/9iuAP/YrgD/3LEA/8agBf82NCz/Pj9C//T0
+ 9P/////////////////////////////////////////////////Ozs7/ZmZm/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/KCQx/1pzHP+m4w//4POx////
+ //////////////////////////////////////////////////////////////////////+t////hP//
+ /////////////////////////////////////////////9y3Hf/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/gtAD/Z1ke/2lrcv//////////////////////////////////////////////////////////////
+ //++vr7/ZGRk/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/ygk
+ Mf93i0X/7PnL////////////////////////////////////////////////////////////////////
+ ////////////hP///1T////////////////////////////////////////////////euyr/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/4LQA/66OC/+Dg4b/////////////////////////////////////////
+ ///////////////////////////////////Pz8//hISE/0hISP8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/0JCQv+RkJX/9PXy////////////////////////////////////////////////////
+ /////////////////////////////////1b///8c////////////////////////////////////////
+ ////////48RG/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9mvAP/dsgD/kopq////////////////////
+ ///////////////////////////////////////////////////////////////////09PT/y8vL/6Ki
+ ov+Dg4P/cXFx/21tbf94eHj/kJCQ/7q6uv/v7+//////////////////////////////////////////
+ //////////////////////////////////////////////////////8d////AP///9f/////////////
+ /////////////////////////////+rTdP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/4LQA/72f
+ Iv/09PT/////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////Y////AP//
+ /wD///+P///////////////////////////////////////////06Lb/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/esgD/zsKO////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////kP///wD///8A////Ov///////////////////////////////////////////fvx/9y2
+ Gv/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/+G3Cf/578j/////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////zr///8A////AP///wH////a////////////////////////
+ ///////////////////p0nD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/3bgh//r0
+ 3P//////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////9v///8B////AP///wD///8A////dP//
+ ////////////////////////////////////////+fPZ/9mxCP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/duCH/9+7I////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////90////AP//
+ /wD///8A////AP///wz////t///////////////////////////////////////////oz2n/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9qyDf/x4qT/////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////t////Df///wD///8A////AP///wD///8A////f///////////////////////////////////
+ ////////+/fm/9u1Fv/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/+nQ
+ bP/8+u7/////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////f////wD///8A////AP///wD///8A////AP///xD////q////////
+ ///////////////////////////////////x4qX/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/3ron//Hipf///v3/////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////6v///xD///8A////AP///wD///8A////AP//
+ /wD///8A////YP///////////////////////////////////////////////+jPaf/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/4cA5//HipP/9+/H/////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////2H///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wH////D////////////////////////////////////////
+ ///+/fj/4sRE/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/3bgf/+fNY//x4qX/+PHT//367//+/vv////+////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /8P///8B////AP///wD///8A////AP///wD///8A////AP///wD///8A////Iv////D/////////////
+ //////////////////////////////z57f/gvzX/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9ivA//cthj/37wr//fuyv//////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////D///8i////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///9U////////////////////////////////////////////////+/jo/+C/Nf/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/48NH/////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////9V////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///4j/////////////////////////////////////////////
+ ///8+ev/4sND/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/btBP//Pns////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////+J////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8B////pP//////////////////
+ //////////////////////////////789v/nzGD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/37wt///+/P//////////////////////////////
+ //////////////////////////////////////////////////////////////////////+k////Af//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wb///+3/////////////////////////////////////////////////////+7bj//asQr/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/+PGSv//////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////+3////Bv///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////Bv///6X/////////////////////////////////////////////
+ ////////9+7K/+HBO//YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/oz2n/////////////////////////////////////////////////////////////////////////
+ //////////////////////+l////Bv///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8B////jP//////////////////
+ ///////////////////////////////////+/fr/7t2T/924Hv/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/7dqL////////////////////////////////////////////////////
+ //////////////////////////////////////+M////Af///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A2K4AANiu
+ AAD///9V////8f/////////////////////////////////////////////////////8+ev/7dmH/966
+ Jv/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A//Plrv//////////////////////////////
+ //////////////////////////////////////////////////H///9VmtgAAJrYAAD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////ANiuAADYrgAA2K4AAP///yT////E////////////////////////////////////////
+ ///////////////////9/PT/8+av/+bLWv/duB7/2K4A/9iuAP/YrgD/2K4A/9iuAP/37sv/////////
+ /////////////////////////////////////////////////////////////////8T///8jmtgAAJrY
+ AACa2AAA////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wDYrgAA2K4AANiuAADYrgAA////Af///2D////r////////
+ /////////////////////////////////////////////////////////fvx//btxv/v3pf/6dJw/+TH
+ T//jxEX/+/jo////////////////////////////////////////////////////////////////6///
+ /2D///8BmtgAAJrYAACa2AAAmtgAAP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////EP///3/////t////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////t////f////xD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////Df///3T////V////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////9X///90////Df///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /zP///+N////1///////////////////////////////////////////////////////////////////
+ ///////////////////////X////jf///zP///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8b////VP///33///+l////y////+P////y////////
+ ///////y////4////8v///+l////ff///1T///8b////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////4Af///////wAAD//////8AAAD/////+AAAAB/////wAAAAD////8AAAAAD////gAAAAA
+ H///4AAAAAAH///AAAAAAAP//4AAAAAAAf//AAAAAAAA//4AAAAAAAB//gAAAAAAAH/8AAAAAAAAP/gA
+ AAAAAAAf+AAAAAAAAB/wAAAAAAAAD/AAAAAAAAAH4AAAAAAAAAfgAAAAAAAAB8AAAAAAAAADwAAAAAAA
+ AAOAAAAAAAAAAYAAAAAAAAABgAAAAAAAAAGAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIAAAAAAAAABgAAAAAAAAAGAAAAAAAAAAYAAAAAAAAABwAAAAAAAAAPAAAAAAAAAA+AA
+ AAAAAAAH4AAAAAAAAAfwAAAAAAAAD/AAAAAAAAAP+AAAAAAAAB/4AAAAAAAAH/wAAAAAAAA//gAAAAAA
+ AH/+AAAAAAAAf/8AAAAAAAD//4AAAAAAAf//wAAAAAAD///gAAAAAAf///gAAAAAH////AAAAAA/////
+ AAAAAP/////AAAAD//////AAAA///////AAAP///////4Af///8=
+
+
+
\ No newline at end of file
diff --git a/Discord Media Loader.Application/FrmInternalSplash.Designer.cs b/Discord Media Loader.Application/FrmInternalSplash.Designer.cs
new file mode 100644
index 0000000..23e8d02
--- /dev/null
+++ b/Discord Media Loader.Application/FrmInternalSplash.Designer.cs
@@ -0,0 +1,80 @@
+namespace DML.Application
+{
+ partial class FrmInternalSplash
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmInternalSplash));
+ this.lblName = new System.Windows.Forms.Label();
+ this.pbLogo = new System.Windows.Forms.PictureBox();
+ ((System.ComponentModel.ISupportInitialize)(this.pbLogo)).BeginInit();
+ this.SuspendLayout();
+ //
+ // lblName
+ //
+ this.lblName.Font = new System.Drawing.Font("Microsoft Sans Serif", 21.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.lblName.Location = new System.Drawing.Point(11, 129);
+ this.lblName.Name = "lblName";
+ this.lblName.Size = new System.Drawing.Size(379, 35);
+ this.lblName.TabIndex = 3;
+ this.lblName.Text = "Discord Media Loader";
+ this.lblName.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // pbLogo
+ //
+ this.pbLogo.Image = global::DML.Application.Properties.Resources.Serraniel_Logo4_NO_BG;
+ this.pbLogo.Location = new System.Drawing.Point(14, 10);
+ this.pbLogo.Name = "pbLogo";
+ this.pbLogo.Size = new System.Drawing.Size(376, 116);
+ this.pbLogo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+ this.pbLogo.TabIndex = 2;
+ this.pbLogo.TabStop = false;
+ //
+ // FrmInternalSplash
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.White;
+ this.ClientSize = new System.Drawing.Size(400, 175);
+ this.Controls.Add(this.lblName);
+ this.Controls.Add(this.pbLogo);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
+ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+ this.Name = "FrmInternalSplash";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "Discord Media Loader";
+ ((System.ComponentModel.ISupportInitialize)(this.pbLogo)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label lblName;
+ private System.Windows.Forms.PictureBox pbLogo;
+ }
+}
\ No newline at end of file
diff --git a/Discord Media Loader.Application/FrmInternalSplash.cs b/Discord Media Loader.Application/FrmInternalSplash.cs
new file mode 100644
index 0000000..22bcad6
--- /dev/null
+++ b/Discord Media Loader.Application/FrmInternalSplash.cs
@@ -0,0 +1,12 @@
+using System.Windows.Forms;
+
+namespace DML.Application
+{
+ public partial class FrmInternalSplash : Form
+ {
+ public FrmInternalSplash()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Discord Media Loader/LoginForm.resx b/Discord Media Loader.Application/FrmInternalSplash.resx
similarity index 100%
rename from Discord Media Loader/LoginForm.resx
rename to Discord Media Loader.Application/FrmInternalSplash.resx
diff --git a/Discord Media Loader.Application/MainForm.Designer.cs b/Discord Media Loader.Application/MainForm.Designer.cs
new file mode 100644
index 0000000..4b17af7
--- /dev/null
+++ b/Discord Media Loader.Application/MainForm.Designer.cs
@@ -0,0 +1,395 @@
+namespace DML.Application
+{
+ partial class MainForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
+ this.pnlSettings = new System.Windows.Forms.GroupBox();
+ this.lbThreadLimit = new System.Windows.Forms.Label();
+ this.edThreadLimit = new System.Windows.Forms.NumericUpDown();
+ this.cbSkipExisting = new System.Windows.Forms.CheckBox();
+ this.edNameScheme = new System.Windows.Forms.TextBox();
+ this.lbNameScheme = new System.Windows.Forms.Label();
+ this.btnSearchFolders = new System.Windows.Forms.Button();
+ this.edOperatingFolder = new System.Windows.Forms.TextBox();
+ this.lbOperatingFolder = new System.Windows.Forms.Label();
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.btnAddJob = new System.Windows.Forms.Button();
+ this.cbChannel = new System.Windows.Forms.ComboBox();
+ this.lbChannel = new System.Windows.Forms.Label();
+ this.cbGuild = new System.Windows.Forms.ComboBox();
+ this.lbGuild = new System.Windows.Forms.Label();
+ this.statusStrip = new System.Windows.Forms.StatusStrip();
+ this.pgbProgress = new System.Windows.Forms.ToolStripProgressBar();
+ this.lbProgress = new System.Windows.Forms.ToolStripStatusLabel();
+ this.lblVersionPlaceholder = new System.Windows.Forms.ToolStripStatusLabel();
+ this.lbVersion = new System.Windows.Forms.ToolStripStatusLabel();
+ this.btnDropDown = new System.Windows.Forms.ToolStripSplitButton();
+ this.visitGithubToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.groupBox2 = new System.Windows.Forms.GroupBox();
+ this.btnDelete = new System.Windows.Forms.Button();
+ this.lbxJobs = new System.Windows.Forms.ListBox();
+ this.tmrRefreshProgress = new System.Windows.Forms.Timer(this.components);
+ this.pnlSettings.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.edThreadLimit)).BeginInit();
+ this.groupBox1.SuspendLayout();
+ this.statusStrip.SuspendLayout();
+ this.groupBox2.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // pnlSettings
+ //
+ this.pnlSettings.Controls.Add(this.lbThreadLimit);
+ this.pnlSettings.Controls.Add(this.edThreadLimit);
+ this.pnlSettings.Controls.Add(this.cbSkipExisting);
+ this.pnlSettings.Controls.Add(this.edNameScheme);
+ this.pnlSettings.Controls.Add(this.lbNameScheme);
+ this.pnlSettings.Controls.Add(this.btnSearchFolders);
+ this.pnlSettings.Controls.Add(this.edOperatingFolder);
+ this.pnlSettings.Controls.Add(this.lbOperatingFolder);
+ this.pnlSettings.Dock = System.Windows.Forms.DockStyle.Top;
+ this.pnlSettings.Location = new System.Drawing.Point(0, 0);
+ this.pnlSettings.Name = "pnlSettings";
+ this.pnlSettings.Size = new System.Drawing.Size(553, 93);
+ this.pnlSettings.TabIndex = 0;
+ this.pnlSettings.TabStop = false;
+ this.pnlSettings.Text = "Settings";
+ //
+ // lbThreadLimit
+ //
+ this.lbThreadLimit.AutoSize = true;
+ this.lbThreadLimit.Location = new System.Drawing.Point(12, 67);
+ this.lbThreadLimit.Name = "lbThreadLimit";
+ this.lbThreadLimit.Size = new System.Drawing.Size(64, 13);
+ this.lbThreadLimit.TabIndex = 6;
+ this.lbThreadLimit.Text = "Thread limit:";
+ //
+ // edThreadLimit
+ //
+ this.edThreadLimit.Location = new System.Drawing.Point(113, 65);
+ this.edThreadLimit.Minimum = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this.edThreadLimit.Name = "edThreadLimit";
+ this.edThreadLimit.Size = new System.Drawing.Size(120, 20);
+ this.edThreadLimit.TabIndex = 7;
+ this.edThreadLimit.Value = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this.edThreadLimit.ValueChanged += new System.EventHandler(this.DoSomethingChanged);
+ //
+ // cbSkipExisting
+ //
+ this.cbSkipExisting.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.cbSkipExisting.AutoSize = true;
+ this.cbSkipExisting.Location = new System.Drawing.Point(447, 42);
+ this.cbSkipExisting.Name = "cbSkipExisting";
+ this.cbSkipExisting.Size = new System.Drawing.Size(106, 17);
+ this.cbSkipExisting.TabIndex = 5;
+ this.cbSkipExisting.Text = "Skip existing files";
+ this.cbSkipExisting.UseVisualStyleBackColor = true;
+ this.cbSkipExisting.TextChanged += new System.EventHandler(this.DoSomethingChanged);
+ //
+ // edNameScheme
+ //
+ this.edNameScheme.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.edNameScheme.Location = new System.Drawing.Point(113, 39);
+ this.edNameScheme.Name = "edNameScheme";
+ this.edNameScheme.Size = new System.Drawing.Size(328, 20);
+ this.edNameScheme.TabIndex = 4;
+ this.edNameScheme.TextChanged += new System.EventHandler(this.DoSomethingChanged);
+ //
+ // lbNameScheme
+ //
+ this.lbNameScheme.AutoSize = true;
+ this.lbNameScheme.Location = new System.Drawing.Point(12, 42);
+ this.lbNameScheme.Name = "lbNameScheme";
+ this.lbNameScheme.Size = new System.Drawing.Size(95, 13);
+ this.lbNameScheme.TabIndex = 3;
+ this.lbNameScheme.Text = "File name scheme:";
+ //
+ // btnSearchFolders
+ //
+ this.btnSearchFolders.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnSearchFolders.Location = new System.Drawing.Point(522, 11);
+ this.btnSearchFolders.Name = "btnSearchFolders";
+ this.btnSearchFolders.Size = new System.Drawing.Size(25, 23);
+ this.btnSearchFolders.TabIndex = 2;
+ this.btnSearchFolders.Text = "...";
+ this.btnSearchFolders.UseVisualStyleBackColor = true;
+ this.btnSearchFolders.Click += new System.EventHandler(this.btnSearchFolders_Click);
+ //
+ // edOperatingFolder
+ //
+ this.edOperatingFolder.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.edOperatingFolder.Location = new System.Drawing.Point(113, 13);
+ this.edOperatingFolder.Name = "edOperatingFolder";
+ this.edOperatingFolder.Size = new System.Drawing.Size(403, 20);
+ this.edOperatingFolder.TabIndex = 1;
+ this.edOperatingFolder.TextChanged += new System.EventHandler(this.DoSomethingChanged);
+ //
+ // lbOperatingFolder
+ //
+ this.lbOperatingFolder.AutoSize = true;
+ this.lbOperatingFolder.Location = new System.Drawing.Point(12, 16);
+ this.lbOperatingFolder.Name = "lbOperatingFolder";
+ this.lbOperatingFolder.Size = new System.Drawing.Size(85, 13);
+ this.lbOperatingFolder.TabIndex = 0;
+ this.lbOperatingFolder.Text = "Operating folder:";
+ //
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this.btnAddJob);
+ this.groupBox1.Controls.Add(this.cbChannel);
+ this.groupBox1.Controls.Add(this.lbChannel);
+ this.groupBox1.Controls.Add(this.cbGuild);
+ this.groupBox1.Controls.Add(this.lbGuild);
+ this.groupBox1.Dock = System.Windows.Forms.DockStyle.Top;
+ this.groupBox1.Location = new System.Drawing.Point(0, 93);
+ this.groupBox1.Name = "groupBox1";
+ this.groupBox1.Size = new System.Drawing.Size(553, 57);
+ this.groupBox1.TabIndex = 1;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "Add a job";
+ //
+ // btnAddJob
+ //
+ this.btnAddJob.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnAddJob.Location = new System.Drawing.Point(481, 19);
+ this.btnAddJob.Name = "btnAddJob";
+ this.btnAddJob.Size = new System.Drawing.Size(66, 23);
+ this.btnAddJob.TabIndex = 4;
+ this.btnAddJob.Text = "&Add";
+ this.btnAddJob.UseVisualStyleBackColor = true;
+ this.btnAddJob.Click += new System.EventHandler(this.btnAddJob_Click);
+ //
+ // cbChannel
+ //
+ this.cbChannel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.cbChannel.FormattingEnabled = true;
+ this.cbChannel.Location = new System.Drawing.Point(294, 19);
+ this.cbChannel.Name = "cbChannel";
+ this.cbChannel.Size = new System.Drawing.Size(181, 21);
+ this.cbChannel.TabIndex = 3;
+ //
+ // lbChannel
+ //
+ this.lbChannel.AutoSize = true;
+ this.lbChannel.Location = new System.Drawing.Point(239, 22);
+ this.lbChannel.Name = "lbChannel";
+ this.lbChannel.Size = new System.Drawing.Size(49, 13);
+ this.lbChannel.TabIndex = 2;
+ this.lbChannel.Text = "Channel:";
+ //
+ // cbGuild
+ //
+ this.cbGuild.FormattingEnabled = true;
+ this.cbGuild.Location = new System.Drawing.Point(52, 19);
+ this.cbGuild.Name = "cbGuild";
+ this.cbGuild.Size = new System.Drawing.Size(181, 21);
+ this.cbGuild.TabIndex = 1;
+ this.cbGuild.SelectedIndexChanged += new System.EventHandler(this.cbGuild_SelectedIndexChanged);
+ //
+ // lbGuild
+ //
+ this.lbGuild.AutoSize = true;
+ this.lbGuild.Location = new System.Drawing.Point(12, 22);
+ this.lbGuild.Name = "lbGuild";
+ this.lbGuild.Size = new System.Drawing.Size(34, 13);
+ this.lbGuild.TabIndex = 0;
+ this.lbGuild.Text = "Guild:";
+ //
+ // statusStrip
+ //
+ this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.pgbProgress,
+ this.lbProgress,
+ this.lblVersionPlaceholder,
+ this.lbVersion,
+ this.btnDropDown});
+ this.statusStrip.Location = new System.Drawing.Point(0, 311);
+ this.statusStrip.Name = "statusStrip";
+ this.statusStrip.Size = new System.Drawing.Size(553, 22);
+ this.statusStrip.TabIndex = 2;
+ this.statusStrip.Text = "statusStrip1";
+ //
+ // pgbProgress
+ //
+ this.pgbProgress.Name = "pgbProgress";
+ this.pgbProgress.Size = new System.Drawing.Size(100, 16);
+ //
+ // lbProgress
+ //
+ this.lbProgress.Name = "lbProgress";
+ this.lbProgress.Size = new System.Drawing.Size(0, 17);
+ //
+ // lblVersionPlaceholder
+ //
+ this.lblVersionPlaceholder.Name = "lblVersionPlaceholder";
+ this.lblVersionPlaceholder.Size = new System.Drawing.Size(302, 17);
+ this.lblVersionPlaceholder.Spring = true;
+ //
+ // lbVersion
+ //
+ this.lbVersion.Name = "lbVersion";
+ this.lbVersion.Size = new System.Drawing.Size(118, 17);
+ this.lbVersion.Text = "v https://github.com";
+ //
+ // btnDropDown
+ //
+ this.btnDropDown.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnDropDown.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.visitGithubToolStripMenuItem,
+ this.aboutToolStripMenuItem});
+ this.btnDropDown.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnDropDown.Name = "btnDropDown";
+ this.btnDropDown.Size = new System.Drawing.Size(16, 20);
+ this.btnDropDown.Text = "Options";
+ //
+ // visitGithubToolStripMenuItem
+ //
+ this.visitGithubToolStripMenuItem.Name = "visitGithubToolStripMenuItem";
+ this.visitGithubToolStripMenuItem.Size = new System.Drawing.Size(135, 22);
+ this.visitGithubToolStripMenuItem.Text = "Visit Github";
+ this.visitGithubToolStripMenuItem.Click += new System.EventHandler(this.visitGithubToolStripMenuItem_Click);
+ //
+ // aboutToolStripMenuItem
+ //
+ this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
+ this.aboutToolStripMenuItem.Size = new System.Drawing.Size(135, 22);
+ this.aboutToolStripMenuItem.Text = "About";
+ this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click);
+ //
+ // groupBox2
+ //
+ this.groupBox2.Controls.Add(this.btnDelete);
+ this.groupBox2.Controls.Add(this.lbxJobs);
+ this.groupBox2.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.groupBox2.Location = new System.Drawing.Point(0, 150);
+ this.groupBox2.Name = "groupBox2";
+ this.groupBox2.Size = new System.Drawing.Size(553, 161);
+ this.groupBox2.TabIndex = 3;
+ this.groupBox2.TabStop = false;
+ this.groupBox2.Text = "Jobs";
+ //
+ // btnDelete
+ //
+ this.btnDelete.Dock = System.Windows.Forms.DockStyle.Bottom;
+ this.btnDelete.Location = new System.Drawing.Point(3, 135);
+ this.btnDelete.Name = "btnDelete";
+ this.btnDelete.Size = new System.Drawing.Size(547, 23);
+ this.btnDelete.TabIndex = 1;
+ this.btnDelete.Text = "Delete selected";
+ this.btnDelete.UseVisualStyleBackColor = true;
+ this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click);
+ //
+ // lbxJobs
+ //
+ this.lbxJobs.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.lbxJobs.FormattingEnabled = true;
+ this.lbxJobs.Location = new System.Drawing.Point(6, 19);
+ this.lbxJobs.Name = "lbxJobs";
+ this.lbxJobs.Size = new System.Drawing.Size(541, 108);
+ this.lbxJobs.TabIndex = 0;
+ //
+ // tmrRefreshProgress
+ //
+ this.tmrRefreshProgress.Enabled = true;
+ this.tmrRefreshProgress.Interval = 500;
+ this.tmrRefreshProgress.Tick += new System.EventHandler(this.tmrRefreshProgress_Tick);
+ //
+ // MainForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(553, 333);
+ this.Controls.Add(this.groupBox2);
+ this.Controls.Add(this.statusStrip);
+ this.Controls.Add(this.groupBox1);
+ this.Controls.Add(this.pnlSettings);
+ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+ this.MinimumSize = new System.Drawing.Size(100, 75);
+ this.Name = "MainForm";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "Discord Medial Loader";
+ this.Shown += new System.EventHandler(this.MainForm_Shown);
+ this.pnlSettings.ResumeLayout(false);
+ this.pnlSettings.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.edThreadLimit)).EndInit();
+ this.groupBox1.ResumeLayout(false);
+ this.groupBox1.PerformLayout();
+ this.statusStrip.ResumeLayout(false);
+ this.statusStrip.PerformLayout();
+ this.groupBox2.ResumeLayout(false);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.GroupBox pnlSettings;
+ private System.Windows.Forms.GroupBox groupBox1;
+ private System.Windows.Forms.StatusStrip statusStrip;
+ private System.Windows.Forms.GroupBox groupBox2;
+ private System.Windows.Forms.Label lbThreadLimit;
+ private System.Windows.Forms.NumericUpDown edThreadLimit;
+ private System.Windows.Forms.CheckBox cbSkipExisting;
+ private System.Windows.Forms.TextBox edNameScheme;
+ private System.Windows.Forms.Label lbNameScheme;
+ private System.Windows.Forms.Button btnSearchFolders;
+ private System.Windows.Forms.TextBox edOperatingFolder;
+ private System.Windows.Forms.Label lbOperatingFolder;
+ private System.Windows.Forms.Button btnAddJob;
+ private System.Windows.Forms.ComboBox cbChannel;
+ private System.Windows.Forms.Label lbChannel;
+ private System.Windows.Forms.ComboBox cbGuild;
+ private System.Windows.Forms.Label lbGuild;
+ private System.Windows.Forms.Button btnDelete;
+ private System.Windows.Forms.ListBox lbxJobs;
+ private System.Windows.Forms.ToolStripProgressBar pgbProgress;
+ private System.Windows.Forms.ToolStripStatusLabel lbProgress;
+ private System.Windows.Forms.Timer tmrRefreshProgress;
+ private System.Windows.Forms.ToolStripStatusLabel lblVersionPlaceholder;
+ private System.Windows.Forms.ToolStripStatusLabel lbVersion;
+ private System.Windows.Forms.ToolStripSplitButton btnDropDown;
+ private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem visitGithubToolStripMenuItem;
+ }
+}
\ No newline at end of file
diff --git a/Discord Media Loader.Application/MainForm.cs b/Discord Media Loader.Application/MainForm.cs
new file mode 100644
index 0000000..20b91ba
--- /dev/null
+++ b/Discord Media Loader.Application/MainForm.cs
@@ -0,0 +1,252 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Windows.Forms;
+using Discord.WebSocket;
+using DML.AppCore.Classes;
+using DML.Application.Classes;
+using DML.Client;
+using static SweetLib.Utils.Logger.Logger;
+
+namespace DML.Application
+{
+ public partial class MainForm : Form
+ {
+ private bool IsInitialized { get; set; } = false;
+ public MainForm()
+ {
+ InitializeComponent();
+ }
+
+ private void MainForm_Shown(object sender, System.EventArgs e)
+ {
+ Trace("MainForm shown executed.");
+ RefreshComponents();
+
+ IsInitialized = true;
+ }
+
+ private void RefreshComponents()
+ {
+ Debug("Refreshing components...");
+
+ lbVersion.Text = $"v{Assembly.GetExecutingAssembly().GetName().Version} Copyright © by Serraniel";
+
+ Trace("Refreshing operating folder component...");
+ edOperatingFolder.Text = Core.Settings.OperatingFolder;
+
+ Trace("Refreshing name scheme component...");
+ edNameScheme.Text = Core.Settings.FileNameScheme;
+
+ Trace("Refreshing skip existing files component...");
+ cbSkipExisting.Checked = Core.Settings.SkipExistingFiles;
+
+ Trace("Refreshing thread limit component...");
+ edThreadLimit.Value = Core.Settings.ThreadLimit;
+
+ if (cbGuild.Items.Count == 0)
+ {
+ Trace("Adding guilds to component...");
+ cbGuild.Items.AddRange(DMLClient.Client.Guilds.OrderBy(g => g.Name).Select(g => g.Name).ToArray());
+ cbGuild.SelectedIndex = 0;
+ Trace("Guild component initialized.");
+ }
+
+ Trace("Refreshing job list component...");
+ var oldIndex = lbxJobs.SelectedIndex;
+ lbxJobs.Items.Clear();
+ foreach (var job in Core.Scheduler.JobList)
+ {
+ lbxJobs.Items.Add(
+ $"{FindServerById(job.GuildId)?.Name}:{FindChannelById(FindServerById(job.GuildId), job.ChannelId)?.Name}");
+ }
+ lbxJobs.SelectedIndex = oldIndex;
+ }
+
+ private void DoSomethingChanged(object sender, System.EventArgs e)
+ {
+ Debug($"DoSomethingChanged excuted by {sender}.");
+ if (!IsInitialized)
+ {
+ Trace("Form not initialized. Leaving DoSomethingChanged...");
+ return;
+ }
+
+ Trace("Updating operating folder...");
+ Core.Settings.OperatingFolder = edOperatingFolder.Text;
+
+ Trace("Updating name scheme...");
+ Core.Settings.FileNameScheme = edNameScheme.Text;
+
+ Trace("Updating skip existing files...");
+ Core.Settings.SkipExistingFiles = cbSkipExisting.Checked;
+
+ Trace("Updating thread limit...");
+ Core.Settings.ThreadLimit = (int)edThreadLimit.Value;
+
+ Trace("Storing new settings...");
+ Core.Settings.Store();
+
+ Info("New settings have been saved.");
+ }
+
+ private void btnSearchFolders_Click(object sender, System.EventArgs e)
+ {
+ Trace("Operating folder button pressed.");
+ using (var browserDialog = new FolderBrowserDialog())
+ {
+ Debug("Showing file browser dialog for operating folder...");
+
+ browserDialog.SelectedPath = edOperatingFolder.Text;
+ browserDialog.ShowNewFolderButton = true;
+ browserDialog.Description = "Select an operating folder...";
+
+ if (browserDialog.ShowDialog() == DialogResult.OK)
+ {
+ edOperatingFolder.Text = browserDialog.SelectedPath;
+ Debug("Updated operating folder.");
+ }
+ }
+ }
+
+ private SocketGuild FindServerByName(string name)
+ {
+ Trace($"Trying to find server by name: {name}");
+ return (from s in DMLClient.Client.Guilds where s.Name == name select s).FirstOrDefault();
+ }
+
+ private SocketTextChannel FindChannelByName(SocketGuild server, string name)
+ {
+ Trace($"Trying to find channel in {server} by name: {name}");
+ return (from c in server.TextChannels where c.Name == name select c).FirstOrDefault();
+ }
+
+ private SocketGuild FindServerById(ulong id)
+ {
+ Trace($"Trying to find server by Id: {id}");
+ return (from s in DMLClient.Client.Guilds where s.Id == id select s).FirstOrDefault();
+ }
+
+ private SocketTextChannel FindChannelById(SocketGuild server, ulong id)
+ {
+ Trace($"Trying to find channel in {server} by id: {id}");
+ return (from c in server.TextChannels where c.Id == id select c).FirstOrDefault();
+ }
+
+ private void cbGuild_SelectedIndexChanged(object sender, System.EventArgs e)
+ {
+ Trace("Guild index changed.");
+ Debug("Updating channel dropdown component...");
+
+ UseWaitCursor = true;
+ try
+ {
+ var guild = FindServerByName(cbGuild.Text);
+
+ if (guild != null)
+ {
+ Trace("Cleaning channel component from old values...");
+ cbChannel.Items.Clear();
+
+ Trace("Adding new channels...");
+ cbChannel.Items.AddRange(guild.TextChannels.OrderBy(c => c.Position).Select(c => c.Name).ToArray());
+ Trace($"Added {cbChannel.Items.Count} channels.");
+
+ cbChannel.SelectedIndex = 0;
+ }
+ else
+ {
+ Warn($"Guild {cbGuild.Text} could not be found!");
+ }
+ }
+ finally
+ {
+ UseWaitCursor = false;
+ }
+
+ Debug("Finished updating channel dropdown component.");
+ }
+
+ private void btnAddJob_Click(object sender, System.EventArgs e)
+ {
+ var job = new Job
+ {
+ GuildId = FindServerByName(cbGuild.Text).Id,
+ ChannelId = FindChannelByName(FindServerByName(cbGuild.Text), cbChannel.Text).Id
+ };
+
+ if (!(from j in Core.Scheduler.JobList
+ where j.GuildId == job.GuildId && j.ChannelId == job.ChannelId
+ select j).Any())
+ {
+ job.Store();
+ Core.Scheduler.JobList.Add(job);
+ }
+
+ RefreshComponents();
+ }
+
+ private void btnDelete_Click(object sender, System.EventArgs e)
+ {
+ Trace("Deleting job pressed.");
+
+ if (lbxJobs.SelectedIndex < 0)
+ {
+ Warn("No job selected.");
+ MessageBox.Show("No job has been seleted.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ }
+
+ var jobNameData = lbxJobs.SelectedItem.ToString().Split(':');
+
+ var guildName = "";
+ for (var i = 0; i < jobNameData.Length - 1; i++)
+ guildName += jobNameData[i] + ":";
+ guildName = guildName.Substring(0, guildName.Length - 1);
+
+ var channelName = jobNameData[jobNameData.Length - 1];
+
+ var guild = FindServerByName(guildName);
+ var channel = FindChannelByName(guild, channelName);
+
+ foreach (var job in Core.Scheduler.JobList)
+ {
+ if (job.GuildId == guild.Id && job.ChannelId == channel.Id)
+ {
+ Core.Scheduler.JobList.Remove(job);
+ Core.Scheduler.RunningJobs.Remove(job.Id);
+ job.Stop();
+ job.Delete();
+ break;
+ }
+ }
+
+ lbxJobs.SelectedIndex = -1;
+ RefreshComponents();
+ }
+
+ private void tmrRefreshProgress_Tick(object sender, System.EventArgs e)
+ {
+ var scanned = Core.Scheduler.MessagesScanned;
+ var totalAttachments = Core.Scheduler.TotalAttachments;
+ var done = Core.Scheduler.AttachmentsDownloaded;
+
+ var progress = totalAttachments > 0 ? (int)(100 * done / totalAttachments) : 0;
+ progress = Math.Min(Math.Max(0, progress), 100);
+ pgbProgress.Maximum = 100;
+ pgbProgress.Value = progress;
+
+ lbProgress.Text = $"Scanned: {scanned} Downloaded: {done} Open: {totalAttachments - done}";
+ }
+
+ private void aboutToolStripMenuItem_Click(object sender, System.EventArgs e)
+ {
+ MessageBox.Show(Properties.Resources.AboutString);
+ }
+
+ private void visitGithubToolStripMenuItem_Click(object sender, System.EventArgs e)
+ {
+ Process.Start("https://github.com/Serraniel/DiscordMediaLoader/");
+ }
+ }
+}
diff --git a/Discord Media Loader.Application/MainForm.resx b/Discord Media Loader.Application/MainForm.resx
new file mode 100644
index 0000000..7c9ffe0
--- /dev/null
+++ b/Discord Media Loader.Application/MainForm.resx
@@ -0,0 +1,414 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ 126, 17
+
+
+
+
+ AAABAAEAQEAAAAEAIAAoQgAAFgAAACgAAABAAAAAgAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8b////VP///3////+m////zP//
+ /+T////1//////////r////u////3f///8z///+m////f////1T///8b////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////M////5D////b////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /9v///+Q////M////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///w3///90////1v//
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////W////dP///w3///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A2K4AANiuAADYrgAA2K4AANiuAADfswAA////EP//
+ /4D////t////////////////////////////////////////////////9/zq/7XiQ/+340n/w+ho/9Pu
+ kf/m9b//+Pzt///////////////////////////////////////////////////////////t////gf//
+ /xCa2AAAmtgAAJrYAACa2AAAmtgAAJrYAAD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////ANiuAADYrgAA2K4AANiu
+ AAD///8B////Yf///+v//////////////////////////////////////////////////////////+z4
+ z/+a2AD/mtgA/5rYAP+a2AD/mtgA/6TcGf+65VL/3fKo//n98P//////////////////////////////
+ ///////////////////////r////Yf///wGa2AAAmtgAAJrYAACa2AAA////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wDYrgAA2K4AANiuAAD///8k////xP//////////////////////////////////////////////////
+ ///////////////////h87P/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+n3SD/zOt+//X7
+ 5v/////////////////////////////////////////////////////E////I5rYAACa2AAAmtgAAP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A2K4AANiuAAD///9V////8f//////////////////////////////////
+ ////////////////////////////////////////0+6Q/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+k3Bn/0e2K//v+9v//////////////////////////////////////////////
+ //H///9VmtgAAJrYAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wH///+M////////////////////////
+ /////////////////////////////////////////////////////////////8bpbv+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+u4DP/5/bD////////////////////
+ /////////////////////////////////4z///8B////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wb///+l////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //+55E//mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5zZ
+ Bv/P7Ib/////////////////////////////////////////////////////pf///wb///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wb///+3////////////////////////////////////////////////////////////////////////
+ ///////////////////+//3/rd8x/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/7zlV//5/fH/////////////////////////////////////////
+ //////+3////Bv///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wH///+k////////////////////////////////////////////////////////
+ ////////////////////////////////////////+f3v/6PcF/+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/seE7//X75v//////////////
+ /////////////////////////////////6T///8B////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///+K////////////////////////////////////////
+ /////////////////////////////////////////////////////////////+751f+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+s3y7/9Pvi////////////////////////////////////////////////i////wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///9V////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///s+M//rd8w/6XcHf+c2Qb/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/6zfLv/1++f/////////////////////////////////////////
+ //////9V////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8j////8P//
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////v/6/fL/8PnZ/97yrP/E6Gv/qd4l/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/suE8//v99P//////////////
+ ////////////////////////////8P///yP///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8B////xP//////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////v9
+ 9f/e8qz/s+JA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP/A51/////////////////////////////////////////////////E////Af///wD///8A////AP//
+ /wD///8A////AP///wD///8A////Yf//////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////f867/rN8t/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/9jwnP//////////////////////////////////////////////
+ /2H///8A////AP///wD///8A////AP///wD///8A////EP///+r/////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////r98//I6nX/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+h2xL/8/rh////////////////////
+ ///////////////////////q////Ev///wD///8A////AP///wD///8A////AP///3//////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////9/yrf+h2xL/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/8Dn
+ X////////////////////////////////////////////////4D///8A////AP///wD///8A////AP//
+ /w3////u////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////7PjQ/6reKP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+c2QX/7vjT///////////////////////////////////////////u////Df//
+ /wD///8A////AP///wD///90////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////0++L/qd4n/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/8PoaP//////////////////////////////
+ /////////////////3T///8A////AP///wD///8B////2///////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////+360P+k4g3/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+j2xb/+Pzu////
+ ///////////////////////////////////////b////Af///wD///8A////O///////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////wNCY/53dAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/9/zr////////////////////////////////////////////////zv///8A////AP//
+ /5D/////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////f39/+Puin/n+AA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP/F6W3/////////////////////////////////////////
+ //////+Q////AP///wD////Y////////////////////////////////////////////////////////
+ /////////////////////////////+3t7f+3t7f/jIyM/3Nzc/9oaGj/a2tr/35+fv+dnZ3/xsbG//Hx
+ 8f//////////////////////////////////////////////////////////////////////////////
+ ////////iZNy/5zbAP+b2QD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/s+JA////////////////////
+ ////////////////////////////2f///wD///8d////////////////////////////////////////
+ ////////////////////////////////////////9fTx/46Pk/9BQUH/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv9ERET/fn5+/8rKyv//////////////////////////////////////////////
+ /////////////////////////////4iHjP98qA3/n+AA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/6ne
+ J/////////////////////////////////////////////////////8e////Vv//////////////////
+ ////////////////////////////////////////////////////////+fDL/45/Qv8kJjH/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Xl5e/7e3t//+/v7/////////
+ //////////////////////////////////////////////////9vbXX/T2Ig/57fAP+a2QD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+l3Bz/////////////////////////////////////////////////////Vv//
+ /4T/////////////////////////////////////////////////////////////////////8+ax/+O5
+ D/92ZBv/JCYx/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/YGBg/8jIyP/////////////////////////////////////////////////09PT/QkJE/zEz
+ Lf+Mwgb/nd0A/5rYAP+a2AD/mtgA/5rYAP+a2AD/pdwb////////////////////////////////////
+ /////////////////4T///+t////////////////////////////////////////////////////////
+ ////////8+ez/9mwB//htQD/dWMb/yQnMf8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/dHR0/97e3v//////////////////////////////
+ ////////r6+v/y4uLv8nIzH/bZET/6HiAP+a2AD/mtgA/5rYAP+a2AD/mtgA/6neJv//////////////
+ //////////////////////////////////////+t////zP//////////////////////////////////
+ ////////////////////////+PHS/9qyDv/YrgD/4rUA/3lmGf8kJjH/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Ozs7/1ZWVv90dHT/jo6O/5mZmf/Hx8f//v7+////
+ ////////////////////////7+/v/0dHR/8uLi7/KCUw/1BkH/+f4AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+z4T7/////////////////////////////////////////////////////zP///+X/////////////
+ /////////////////////////////////////////v35/+C/N//YrgD/2K4A/+O2AP+Dbhf/IyYx/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/1VVVf+QkJD/xsbG/+rq6v//////////////
+ ////////////////////////////////////////+vr6/2tra/8uLi7/Li4u/yspL/86Qij/ltEC/5va
+ AP+a2AD/mtgA/5rYAP+a2AD/x+ly////////////////////////////////////////////////////
+ /+D////y//////////////////////////////////////////////////////Dfm//YrgD/2K4A/9iu
+ AP/itQD/k3oT/yUnMf8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/cHBw/8bGxv/8/Pz/////////
+ ////////////////////////////////////////////////////////7+/v/3BwcP8uLi7/Li4u/y4u
+ Lv8tLC7/Ly8u/4e7CP+e3gD/mtgA/5rYAP+a2AD/mtgA/+X1vf//////////////////////////////
+ ///////////////////////s//////////////////////////////////////////////////////79
+ +f/euyr/2K4A/9iuAP/YrgD/4LQA/6iKDf8oKTD/Li4u/y4uLv8uLi7/Li4u/y4uLv9QUFD/xMTE////
+ ////////////////////////////////////////////////////////////////////////w8PD/1BQ
+ UP8uLi7/Li4u/y4uLv8uLi7/Li4u/yknMP95pA7/n+EA/5rYAP+a2AD/mtgA/6neJ//8/vj/////////
+ ////////////////////////////////////////////+f//////////////////////////////////
+ ///////////////////168D/2K4A/9iuAP/YrgD/2K4A/92yAP+/mwf/MTAt/ywtLv8uLi7/Li4u/y4u
+ Lv9wcHD/8PDw//////////////////////////////////////////////////////////////////r6
+ +v/ExMT/bm5u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8oJDH/a44U/6HiAP+a2AD/mtgA/5rY
+ AP/W75j///////////////////////////////////////////////////////////n////y////////
+ ////////////////////////////////////////6tR3/9iuAP/YrgD/2K4A/9iuAP/arwD/06oB/0VA
+ J/8pKi//Li4u/y4uLv9ra2v/+vr6//////////////////////////////////////////////////39
+ /f/n5+f/wsLC/4yMjP9SUlL/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/JyMx/2F+
+ GP+h4wD/mtgA/5rYAP+v4DX//P74////////////////////////////////////////////////////
+ ///////s////5f///////////////////////////////////////////////+LDQv/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/+C0AP9oWh7/JCcx/y4uLv9GRkb/7u7u/////////////////////////////v7+/8fH
+ x/+VlZX/iYmJ/3BwcP9TU1P/OTk5/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/ygkMf9bdRv/oOEA/5rYAP+g2g7/7fjR////////////////////////////////////
+ ////////////////////////////4P///8z/////////////////////////////////////////////
+ ///euyj/2K4A/9iuAP/YrgD/2K4A/9iuAP/itQD/ln0S/yQnMf8uLi7/ra2t////////////////////
+ ///////////////////i4uL/e3t7/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8oJDH/WXEc/6DhAP+d2Qf/4fOy////////////////////
+ /////////////////////////////////////////////////8z///+t////////////////////////
+ ////////////////////////3Lcc/9iuAP/YrgD/2K4A/9iuAP/YrgD/3LEA/8agBf82NCz/Pj9C//T0
+ 9P/////////////////////////////////////////////////Ozs7/ZmZm/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/KCQx/1pzHP+m4w//4POx////
+ //////////////////////////////////////////////////////////////////////+t////hP//
+ /////////////////////////////////////////////9y3Hf/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/gtAD/Z1ke/2lrcv//////////////////////////////////////////////////////////////
+ //++vr7/ZGRk/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/ygk
+ Mf93i0X/7PnL////////////////////////////////////////////////////////////////////
+ ////////////hP///1T////////////////////////////////////////////////euyr/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/4LQA/66OC/+Dg4b/////////////////////////////////////////
+ ///////////////////////////////////Pz8//hISE/0hISP8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/0JCQv+RkJX/9PXy////////////////////////////////////////////////////
+ /////////////////////////////////1b///8c////////////////////////////////////////
+ ////////48RG/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9mvAP/dsgD/kopq////////////////////
+ ///////////////////////////////////////////////////////////////////09PT/y8vL/6Ki
+ ov+Dg4P/cXFx/21tbf94eHj/kJCQ/7q6uv/v7+//////////////////////////////////////////
+ //////////////////////////////////////////////////////8d////AP///9f/////////////
+ /////////////////////////////+rTdP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/4LQA/72f
+ Iv/09PT/////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////Y////AP//
+ /wD///+P///////////////////////////////////////////06Lb/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/esgD/zsKO////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////kP///wD///8A////Ov///////////////////////////////////////////fvx/9y2
+ Gv/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/+G3Cf/578j/////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////zr///8A////AP///wH////a////////////////////////
+ ///////////////////p0nD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/3bgh//r0
+ 3P//////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////9v///8B////AP///wD///8A////dP//
+ ////////////////////////////////////////+fPZ/9mxCP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/duCH/9+7I////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////90////AP//
+ /wD///8A////AP///wz////t///////////////////////////////////////////oz2n/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9qyDf/x4qT/////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////t////Df///wD///8A////AP///wD///8A////f///////////////////////////////////
+ ////////+/fm/9u1Fv/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/+nQ
+ bP/8+u7/////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////f////wD///8A////AP///wD///8A////AP///xD////q////////
+ ///////////////////////////////////x4qX/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/3ron//Hipf///v3/////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////6v///xD///8A////AP///wD///8A////AP//
+ /wD///8A////YP///////////////////////////////////////////////+jPaf/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/4cA5//HipP/9+/H/////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////2H///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wH////D////////////////////////////////////////
+ ///+/fj/4sRE/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/3bgf/+fNY//x4qX/+PHT//367//+/vv////+////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /8P///8B////AP///wD///8A////AP///wD///8A////AP///wD///8A////Iv////D/////////////
+ //////////////////////////////z57f/gvzX/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9ivA//cthj/37wr//fuyv//////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////D///8i////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///9U////////////////////////////////////////////////+/jo/+C/Nf/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/48NH/////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////9V////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///4j/////////////////////////////////////////////
+ ///8+ev/4sND/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/btBP//Pns////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////+J////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8B////pP//////////////////
+ //////////////////////////////789v/nzGD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/37wt///+/P//////////////////////////////
+ //////////////////////////////////////////////////////////////////////+k////Af//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wb///+3/////////////////////////////////////////////////////+7bj//asQr/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/+PGSv//////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////+3////Bv///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////Bv///6X/////////////////////////////////////////////
+ ////////9+7K/+HBO//YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/oz2n/////////////////////////////////////////////////////////////////////////
+ //////////////////////+l////Bv///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8B////jP//////////////////
+ ///////////////////////////////////+/fr/7t2T/924Hv/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/7dqL////////////////////////////////////////////////////
+ //////////////////////////////////////+M////Af///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A2K4AANiu
+ AAD///9V////8f/////////////////////////////////////////////////////8+ev/7dmH/966
+ Jv/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A//Plrv//////////////////////////////
+ //////////////////////////////////////////////////H///9VmtgAAJrYAAD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////ANiuAADYrgAA2K4AAP///yT////E////////////////////////////////////////
+ ///////////////////9/PT/8+av/+bLWv/duB7/2K4A/9iuAP/YrgD/2K4A/9iuAP/37sv/////////
+ /////////////////////////////////////////////////////////////////8T///8jmtgAAJrY
+ AACa2AAA////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wDYrgAA2K4AANiuAADYrgAA////Af///2D////r////////
+ /////////////////////////////////////////////////////////fvx//btxv/v3pf/6dJw/+TH
+ T//jxEX/+/jo////////////////////////////////////////////////////////////////6///
+ /2D///8BmtgAAJrYAACa2AAAmtgAAP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////EP///3/////t////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////t////f////xD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////Df///3T////V////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////9X///90////Df///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /zP///+N////1///////////////////////////////////////////////////////////////////
+ ///////////////////////X////jf///zP///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8b////VP///33///+l////y////+P////y////////
+ ///////y////4////8v///+l////ff///1T///8b////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////4Af///////wAAD//////8AAAD/////+AAAAB/////wAAAAD////8AAAAAD////gAAAAA
+ H///4AAAAAAH///AAAAAAAP//4AAAAAAAf//AAAAAAAA//4AAAAAAAB//gAAAAAAAH/8AAAAAAAAP/gA
+ AAAAAAAf+AAAAAAAAB/wAAAAAAAAD/AAAAAAAAAH4AAAAAAAAAfgAAAAAAAAB8AAAAAAAAADwAAAAAAA
+ AAOAAAAAAAAAAYAAAAAAAAABgAAAAAAAAAGAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIAAAAAAAAABgAAAAAAAAAGAAAAAAAAAAYAAAAAAAAABwAAAAAAAAAPAAAAAAAAAA+AA
+ AAAAAAAH4AAAAAAAAAfwAAAAAAAAD/AAAAAAAAAP+AAAAAAAAB/4AAAAAAAAH/wAAAAAAAA//gAAAAAA
+ AH/+AAAAAAAAf/8AAAAAAAD//4AAAAAAAf//wAAAAAAD///gAAAAAAf///gAAAAAH////AAAAAA/////
+ AAAAAP/////AAAAD//////AAAA///////AAAP///////4Af///8=
+
+
+
\ No newline at end of file
diff --git a/Discord Media Loader.Application/Properties/AssemblyInfo.cs b/Discord Media Loader.Application/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8bfbcd1
--- /dev/null
+++ b/Discord Media Loader.Application/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// Allgemeine Informationen über eine Assembly werden über die folgenden
+// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
+// die einer Assembly zugeordnet sind.
+[assembly: AssemblyTitle("Discord Media Loader.Application")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Serraniel")]
+[assembly: AssemblyProduct("Discord Media Loader.Application")]
+[assembly: AssemblyCopyright("Copyright © 2017 by Serraniel")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
+// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
+// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
+[assembly: ComVisible(false)]
+
+// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
+[assembly: Guid("c130de6a-3237-42b5-be9f-783d1cd104c6")]
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
+// übernehmen, indem Sie "*" eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Discord Media Loader.Application/Properties/Resources.Designer.cs b/Discord Media Loader.Application/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..971d55e
--- /dev/null
+++ b/Discord Media Loader.Application/Properties/Resources.Designer.cs
@@ -0,0 +1,92 @@
+//------------------------------------------------------------------------------
+//
+// Dieser Code wurde von einem Tool generiert.
+// Laufzeitversion:4.0.30319.42000
+//
+// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
+// der Code erneut generiert wird.
+//
+//------------------------------------------------------------------------------
+
+namespace DML.Application.Properties {
+ using System;
+
+
+ ///
+ /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
+ ///
+ // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
+ // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
+ // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
+ // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DML.Application.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
+ /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Sucht eine lokalisierte Zeichenfolge, die Discord Media Loader by Serraniel - Apache 2.0 License
+ ///https://github.com/Serraniel/DiscordMediaLoader/
+ ///
+ ///Made with:
+ ///SweetLib (Copyright (c) 2017 Serraniel - GNU General Public License v3.0)
+ ///Discord.Net (Copyright (c) 2015 RogueException - MIT License)
+ ///Newtonsoft.Json (Copyright (c) 2007 James Newton-King - MIT License)
+ ///Nito.AsyncEx (Copyright (c) 2014 StephenCleary - MIT License)
+ ///RestSharp (Copyright (c) restsharp - Apache 2.0 License)
+ ///WebSocket4Net (Copyright (c) kerryjiang - Apache 2.0 License)
+ /// [Rest der Zeichenfolge wurde abgeschnitten]"; ähnelt.
+ ///
+ internal static string AboutString {
+ get {
+ return ResourceManager.GetString("AboutString", resourceCulture);
+ }
+ }
+
+ ///
+ /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap Serraniel_Logo4_NO_BG {
+ get {
+ object obj = ResourceManager.GetObject("Serraniel_Logo4_NO_BG", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+ }
+}
diff --git a/Discord Media Loader.Application/Properties/Resources.resx b/Discord Media Loader.Application/Properties/Resources.resx
new file mode 100644
index 0000000..6c5f149
--- /dev/null
+++ b/Discord Media Loader.Application/Properties/Resources.resx
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Discord Media Loader by Serraniel - Apache 2.0 License
+https://github.com/Serraniel/DiscordMediaLoader/
+
+Made with:
+SweetLib (Copyright (c) 2017 Serraniel - GNU General Public License v3.0)
+Discord.Net (Copyright (c) 2015 RogueException - MIT License)
+Newtonsoft.Json (Copyright (c) 2007 James Newton-King - MIT License)
+Nito.AsyncEx (Copyright (c) 2014 StephenCleary - MIT License)
+RestSharp (Copyright (c) restsharp - Apache 2.0 License)
+WebSocket4Net (Copyright (c) kerryjiang - Apache 2.0 License)
+LiteDB (Copyright (c) 2014 - 2015 Mauricio David - MIT License)
+Octokit (Copyright (c) 2012 GitHub, Inc - MIT License)
+
+
+
+ ..\Resources\Serraniel-Logo4-NO-BG.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
\ No newline at end of file
diff --git a/Discord Media Loader.Application/Resources/Serraniel-Logo4-NO-BG.png b/Discord Media Loader.Application/Resources/Serraniel-Logo4-NO-BG.png
new file mode 100644
index 0000000..aeb98e3
Binary files /dev/null and b/Discord Media Loader.Application/Resources/Serraniel-Logo4-NO-BG.png differ
diff --git a/Discord Media Loader.Application/app.config b/Discord Media Loader.Application/app.config
new file mode 100644
index 0000000..d5170f1
--- /dev/null
+++ b/Discord Media Loader.Application/app.config
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Discord Media Loader.Application/packages.config b/Discord Media Loader.Application/packages.config
new file mode 100644
index 0000000..d3092d0
--- /dev/null
+++ b/Discord Media Loader.Application/packages.config
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Discord Media Loader.sln b/Discord Media Loader.sln
index d23ac3c..8124baf 100644
--- a/Discord Media Loader.sln
+++ b/Discord Media Loader.sln
@@ -1,9 +1,15 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.25123.0
+# Visual Studio 15
+VisualStudioVersion = 15.0.26730.16
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord Media Loader", "Discord Media Loader\Discord Media Loader.csproj", "{83E64057-7010-4DF3-A011-F7E536508407}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord Media Loader", "Discord Media Loader\Discord Media Loader.csproj", "{EDC92554-DBC1-4F9C-9317-379A8BF441E8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DML.Application", "Discord Media Loader.Application\DML.Application.csproj", "{C130DE6A-3237-42B5-BE9F-783D1CD104C6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SweetLib", "..\SweetLib\SweetLib\SweetLib.csproj", "{02C1F8EF-32F2-4E77-A36D-79129402AF37}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DML.Client", "DML.Client\DML.Client.csproj", "{045EB4A1-34E7-47E0-867E-E10C40505095}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -11,12 +17,27 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {83E64057-7010-4DF3-A011-F7E536508407}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {83E64057-7010-4DF3-A011-F7E536508407}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {83E64057-7010-4DF3-A011-F7E536508407}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {83E64057-7010-4DF3-A011-F7E536508407}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EDC92554-DBC1-4F9C-9317-379A8BF441E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EDC92554-DBC1-4F9C-9317-379A8BF441E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EDC92554-DBC1-4F9C-9317-379A8BF441E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EDC92554-DBC1-4F9C-9317-379A8BF441E8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C130DE6A-3237-42B5-BE9F-783D1CD104C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C130DE6A-3237-42B5-BE9F-783D1CD104C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C130DE6A-3237-42B5-BE9F-783D1CD104C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C130DE6A-3237-42B5-BE9F-783D1CD104C6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {02C1F8EF-32F2-4E77-A36D-79129402AF37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {02C1F8EF-32F2-4E77-A36D-79129402AF37}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {02C1F8EF-32F2-4E77-A36D-79129402AF37}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {02C1F8EF-32F2-4E77-A36D-79129402AF37}.Release|Any CPU.Build.0 = Release|Any CPU
+ {045EB4A1-34E7-47E0-867E-E10C40505095}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {045EB4A1-34E7-47E0-867E-E10C40505095}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {045EB4A1-34E7-47E0-867E-E10C40505095}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {045EB4A1-34E7-47E0-867E-E10C40505095}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {0B742DE0-D6AF-4033-9605-863C32A7FFD8}
+ EndGlobalSection
EndGlobal
diff --git a/Discord Media Loader/App.config b/Discord Media Loader/App.config
index 9610fd5..7cf02b2 100644
--- a/Discord Media Loader/App.config
+++ b/Discord Media Loader/App.config
@@ -1,18 +1,26 @@
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Discord Media Loader/Discord Media Loader.csproj b/Discord Media Loader/Discord Media Loader.csproj
index e6017f7..0977fa7 100644
--- a/Discord Media Loader/Discord Media Loader.csproj
+++ b/Discord Media Loader/Discord Media Loader.csproj
@@ -4,12 +4,12 @@
Debug
AnyCPU
- {83E64057-7010-4DF3-A011-F7E536508407}
+ {EDC92554-DBC1-4F9C-9317-379A8BF441E8}
WinExe
Properties
Discord_Media_Loader
Discord Media Loader
- v4.6
+ v4.6.1
512
true
@@ -32,24 +32,43 @@
TRACE
prompt
4
- True
- True
- True
- None.Increment.None.None
- None.Increment.None.None
- None.Increment.None.None
Serraniel-64x64.ico
+
+
+
-
- ..\packages\Discord.Net.0.9.6\lib\net45\Discord.Net.dll
- True
+
+ ..\packages\Discord.Net.Commands.1.0.2\lib\netstandard1.1\Discord.Net.Commands.dll
-
- ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll
- True
+
+ ..\packages\Discord.Net.Core.1.0.2\lib\net45\Discord.Net.Core.dll
+
+
+ ..\packages\Discord.Net.Rest.1.0.2\lib\net45\Discord.Net.Rest.dll
+
+
+ ..\packages\Discord.Net.Rpc.1.0.2\lib\net45\Discord.Net.Rpc.dll
+
+
+ ..\packages\Discord.Net.Webhook.1.0.2\lib\netstandard1.1\Discord.Net.Webhook.dll
+
+
+ ..\packages\Discord.Net.WebSocket.1.0.2\lib\net45\Discord.Net.WebSocket.dll
+
+
+ ..\packages\Microsoft.Extensions.DependencyInjection.1.1.1\lib\netstandard1.1\Microsoft.Extensions.DependencyInjection.dll
+
+
+ ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.1.1\lib\netstandard1.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
+
+
+ ..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll
+
+
+ ..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll
..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.dll
@@ -67,47 +86,99 @@
..\packages\Octokit.0.24.1-alpha0001\lib\net45\Octokit.dll
True
-
- ..\packages\RestSharp.105.2.3\lib\net46\RestSharp.dll
+
+
+ ..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll
+
+
+ ..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
True
-
+
+
+ ..\packages\System.Console.4.3.0\lib\net46\System.Console.dll
+
+
+ ..\packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll
+
+
+ ..\packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll
+
+
+ ..\packages\System.Interactive.Async.3.1.1\lib\net46\System.Interactive.Async.dll
+
+
+ ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll
+ True
+
+
+
+ ..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll
+
+
+ ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll
+
+
+ ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll
+
+
+ ..\packages\System.Net.Http.4.3.0\lib\net46\System.Net.Http.dll
+
+
+ ..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll
+
+
+
+ ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll
+ True
+
+
+ ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll
+
+
+ ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll
+
+
+ ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll
+
+
+ ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll
+
-
-
- ..\packages\WebSocket4Net.0.14.1\lib\net45\WebSocket4Net.dll
- True
+
+ ..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll
+
+ Form
+
+
+ FrmDownload.cs
+
+
+ Form
+
+
+ FrmSplash.cs
+
+
-
- Form
-
-
- LoginForm.cs
-
-
- Form
-
-
- MainForm.cs
-
-
- LoginForm.cs
+
+ FrmDownload.cs
-
- MainForm.cs
+
+ FrmSplash.cs
ResXFileCodeGenerator
@@ -134,7 +205,15 @@
+
+
+
+
+
+ {c130de6a-3237-42b5-be9f-783d1cd104c6}
+ DML.Application
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ AAABAAEAQEAAAAEAIAAoQgAAFgAAACgAAABAAAAAgAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8b////VP///3////+m////zP//
+ /+T////1//////////r////u////3f///8z///+m////f////1T///8b////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////M////5D////b////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /9v///+Q////M////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///w3///90////1v//
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////W////dP///w3///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A2K4AANiuAADYrgAA2K4AANiuAADfswAA////EP//
+ /4D////t////////////////////////////////////////////////9/zq/7XiQ/+340n/w+ho/9Pu
+ kf/m9b//+Pzt///////////////////////////////////////////////////////////t////gf//
+ /xCa2AAAmtgAAJrYAACa2AAAmtgAAJrYAAD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////ANiuAADYrgAA2K4AANiu
+ AAD///8B////Yf///+v//////////////////////////////////////////////////////////+z4
+ z/+a2AD/mtgA/5rYAP+a2AD/mtgA/6TcGf+65VL/3fKo//n98P//////////////////////////////
+ ///////////////////////r////Yf///wGa2AAAmtgAAJrYAACa2AAA////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wDYrgAA2K4AANiuAAD///8k////xP//////////////////////////////////////////////////
+ ///////////////////h87P/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+n3SD/zOt+//X7
+ 5v/////////////////////////////////////////////////////E////I5rYAACa2AAAmtgAAP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A2K4AANiuAAD///9V////8f//////////////////////////////////
+ ////////////////////////////////////////0+6Q/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+k3Bn/0e2K//v+9v//////////////////////////////////////////////
+ //H///9VmtgAAJrYAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wH///+M////////////////////////
+ /////////////////////////////////////////////////////////////8bpbv+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+u4DP/5/bD////////////////////
+ /////////////////////////////////4z///8B////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wb///+l////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //+55E//mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5zZ
+ Bv/P7Ib/////////////////////////////////////////////////////pf///wb///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wb///+3////////////////////////////////////////////////////////////////////////
+ ///////////////////+//3/rd8x/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/7zlV//5/fH/////////////////////////////////////////
+ //////+3////Bv///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wH///+k////////////////////////////////////////////////////////
+ ////////////////////////////////////////+f3v/6PcF/+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/seE7//X75v//////////////
+ /////////////////////////////////6T///8B////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///+K////////////////////////////////////////
+ /////////////////////////////////////////////////////////////+751f+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+s3y7/9Pvi////////////////////////////////////////////////i////wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///9V////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///s+M//rd8w/6XcHf+c2Qb/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/6zfLv/1++f/////////////////////////////////////////
+ //////9V////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8j////8P//
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////v/6/fL/8PnZ/97yrP/E6Gv/qd4l/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/suE8//v99P//////////////
+ ////////////////////////////8P///yP///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8B////xP//////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////v9
+ 9f/e8qz/s+JA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP/A51/////////////////////////////////////////////////E////Af///wD///8A////AP//
+ /wD///8A////AP///wD///8A////Yf//////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////f867/rN8t/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/9jwnP//////////////////////////////////////////////
+ /2H///8A////AP///wD///8A////AP///wD///8A////EP///+r/////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////r98//I6nX/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+h2xL/8/rh////////////////////
+ ///////////////////////q////Ev///wD///8A////AP///wD///8A////AP///3//////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////9/yrf+h2xL/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/8Dn
+ X////////////////////////////////////////////////4D///8A////AP///wD///8A////AP//
+ /w3////u////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////7PjQ/6reKP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+c2QX/7vjT///////////////////////////////////////////u////Df//
+ /wD///8A////AP///wD///90////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////0++L/qd4n/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/8PoaP//////////////////////////////
+ /////////////////3T///8A////AP///wD///8B////2///////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////+360P+k4g3/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP+j2xb/+Pzu////
+ ///////////////////////////////////////b////Af///wD///8A////O///////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////wNCY/53dAP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+a2AD/mtgA/9/zr////////////////////////////////////////////////zv///8A////AP//
+ /5D/////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////f39/+Puin/n+AA/5rY
+ AP+a2AD/mtgA/5rYAP+a2AD/mtgA/5rYAP/F6W3/////////////////////////////////////////
+ //////+Q////AP///wD////Y////////////////////////////////////////////////////////
+ /////////////////////////////+3t7f+3t7f/jIyM/3Nzc/9oaGj/a2tr/35+fv+dnZ3/xsbG//Hx
+ 8f//////////////////////////////////////////////////////////////////////////////
+ ////////iZNy/5zbAP+b2QD/mtgA/5rYAP+a2AD/mtgA/5rYAP+a2AD/s+JA////////////////////
+ ////////////////////////////2f///wD///8d////////////////////////////////////////
+ ////////////////////////////////////////9fTx/46Pk/9BQUH/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv9ERET/fn5+/8rKyv//////////////////////////////////////////////
+ /////////////////////////////4iHjP98qA3/n+AA/5rYAP+a2AD/mtgA/5rYAP+a2AD/mtgA/6ne
+ J/////////////////////////////////////////////////////8e////Vv//////////////////
+ ////////////////////////////////////////////////////////+fDL/45/Qv8kJjH/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Xl5e/7e3t//+/v7/////////
+ //////////////////////////////////////////////////9vbXX/T2Ig/57fAP+a2QD/mtgA/5rY
+ AP+a2AD/mtgA/5rYAP+l3Bz/////////////////////////////////////////////////////Vv//
+ /4T/////////////////////////////////////////////////////////////////////8+ax/+O5
+ D/92ZBv/JCYx/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/YGBg/8jIyP/////////////////////////////////////////////////09PT/QkJE/zEz
+ Lf+Mwgb/nd0A/5rYAP+a2AD/mtgA/5rYAP+a2AD/pdwb////////////////////////////////////
+ /////////////////4T///+t////////////////////////////////////////////////////////
+ ////////8+ez/9mwB//htQD/dWMb/yQnMf8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/dHR0/97e3v//////////////////////////////
+ ////////r6+v/y4uLv8nIzH/bZET/6HiAP+a2AD/mtgA/5rYAP+a2AD/mtgA/6neJv//////////////
+ //////////////////////////////////////+t////zP//////////////////////////////////
+ ////////////////////////+PHS/9qyDv/YrgD/4rUA/3lmGf8kJjH/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Ozs7/1ZWVv90dHT/jo6O/5mZmf/Hx8f//v7+////
+ ////////////////////////7+/v/0dHR/8uLi7/KCUw/1BkH/+f4AD/mtgA/5rYAP+a2AD/mtgA/5rY
+ AP+z4T7/////////////////////////////////////////////////////zP///+X/////////////
+ /////////////////////////////////////////v35/+C/N//YrgD/2K4A/+O2AP+Dbhf/IyYx/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/1VVVf+QkJD/xsbG/+rq6v//////////////
+ ////////////////////////////////////////+vr6/2tra/8uLi7/Li4u/yspL/86Qij/ltEC/5va
+ AP+a2AD/mtgA/5rYAP+a2AD/x+ly////////////////////////////////////////////////////
+ /+D////y//////////////////////////////////////////////////////Dfm//YrgD/2K4A/9iu
+ AP/itQD/k3oT/yUnMf8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/cHBw/8bGxv/8/Pz/////////
+ ////////////////////////////////////////////////////////7+/v/3BwcP8uLi7/Li4u/y4u
+ Lv8tLC7/Ly8u/4e7CP+e3gD/mtgA/5rYAP+a2AD/mtgA/+X1vf//////////////////////////////
+ ///////////////////////s//////////////////////////////////////////////////////79
+ +f/euyr/2K4A/9iuAP/YrgD/4LQA/6iKDf8oKTD/Li4u/y4uLv8uLi7/Li4u/y4uLv9QUFD/xMTE////
+ ////////////////////////////////////////////////////////////////////////w8PD/1BQ
+ UP8uLi7/Li4u/y4uLv8uLi7/Li4u/yknMP95pA7/n+EA/5rYAP+a2AD/mtgA/6neJ//8/vj/////////
+ ////////////////////////////////////////////+f//////////////////////////////////
+ ///////////////////168D/2K4A/9iuAP/YrgD/2K4A/92yAP+/mwf/MTAt/ywtLv8uLi7/Li4u/y4u
+ Lv9wcHD/8PDw//////////////////////////////////////////////////////////////////r6
+ +v/ExMT/bm5u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8oJDH/a44U/6HiAP+a2AD/mtgA/5rY
+ AP/W75j///////////////////////////////////////////////////////////n////y////////
+ ////////////////////////////////////////6tR3/9iuAP/YrgD/2K4A/9iuAP/arwD/06oB/0VA
+ J/8pKi//Li4u/y4uLv9ra2v/+vr6//////////////////////////////////////////////////39
+ /f/n5+f/wsLC/4yMjP9SUlL/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/JyMx/2F+
+ GP+h4wD/mtgA/5rYAP+v4DX//P74////////////////////////////////////////////////////
+ ///////s////5f///////////////////////////////////////////////+LDQv/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/+C0AP9oWh7/JCcx/y4uLv9GRkb/7u7u/////////////////////////////v7+/8fH
+ x/+VlZX/iYmJ/3BwcP9TU1P/OTk5/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/ygkMf9bdRv/oOEA/5rYAP+g2g7/7fjR////////////////////////////////////
+ ////////////////////////////4P///8z/////////////////////////////////////////////
+ ///euyj/2K4A/9iuAP/YrgD/2K4A/9iuAP/itQD/ln0S/yQnMf8uLi7/ra2t////////////////////
+ ///////////////////i4uL/e3t7/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8oJDH/WXEc/6DhAP+d2Qf/4fOy////////////////////
+ /////////////////////////////////////////////////8z///+t////////////////////////
+ ////////////////////////3Lcc/9iuAP/YrgD/2K4A/9iuAP/YrgD/3LEA/8agBf82NCz/Pj9C//T0
+ 9P/////////////////////////////////////////////////Ozs7/ZmZm/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/KCQx/1pzHP+m4w//4POx////
+ //////////////////////////////////////////////////////////////////////+t////hP//
+ /////////////////////////////////////////////9y3Hf/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/gtAD/Z1ke/2lrcv//////////////////////////////////////////////////////////////
+ //++vr7/ZGRk/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/y4uLv8uLi7/Li4u/ygk
+ Mf93i0X/7PnL////////////////////////////////////////////////////////////////////
+ ////////////hP///1T////////////////////////////////////////////////euyr/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/4LQA/66OC/+Dg4b/////////////////////////////////////////
+ ///////////////////////////////////Pz8//hISE/0hISP8uLi7/Li4u/y4uLv8uLi7/Li4u/y4u
+ Lv8uLi7/Li4u/0JCQv+RkJX/9PXy////////////////////////////////////////////////////
+ /////////////////////////////////1b///8c////////////////////////////////////////
+ ////////48RG/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9mvAP/dsgD/kopq////////////////////
+ ///////////////////////////////////////////////////////////////////09PT/y8vL/6Ki
+ ov+Dg4P/cXFx/21tbf94eHj/kJCQ/7q6uv/v7+//////////////////////////////////////////
+ //////////////////////////////////////////////////////8d////AP///9f/////////////
+ /////////////////////////////+rTdP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/4LQA/72f
+ Iv/09PT/////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////Y////AP//
+ /wD///+P///////////////////////////////////////////06Lb/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/esgD/zsKO////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////kP///wD///8A////Ov///////////////////////////////////////////fvx/9y2
+ Gv/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/+G3Cf/578j/////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////zr///8A////AP///wH////a////////////////////////
+ ///////////////////p0nD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/3bgh//r0
+ 3P//////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////9v///8B////AP///wD///8A////dP//
+ ////////////////////////////////////////+fPZ/9mxCP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/duCH/9+7I////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////90////AP//
+ /wD///8A////AP///wz////t///////////////////////////////////////////oz2n/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9qyDf/x4qT/////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////t////Df///wD///8A////AP///wD///8A////f///////////////////////////////////
+ ////////+/fm/9u1Fv/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/+nQ
+ bP/8+u7/////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////f////wD///8A////AP///wD///8A////AP///xD////q////////
+ ///////////////////////////////////x4qX/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/3ron//Hipf///v3/////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////6v///xD///8A////AP///wD///8A////AP//
+ /wD///8A////YP///////////////////////////////////////////////+jPaf/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/4cA5//HipP/9+/H/////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////2H///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wH////D////////////////////////////////////////
+ ///+/fj/4sRE/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/3bgf/+fNY//x4qX/+PHT//367//+/vv////+////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /8P///8B////AP///wD///8A////AP///wD///8A////AP///wD///8A////Iv////D/////////////
+ //////////////////////////////z57f/gvzX/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9ivA//cthj/37wr//fuyv//////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////D///8i////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///9U////////////////////////////////////////////////+/jo/+C/Nf/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/48NH/////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////9V////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///4j/////////////////////////////////////////////
+ ///8+ev/4sND/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/btBP//Pns////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////+J////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8B////pP//////////////////
+ //////////////////////////////789v/nzGD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/37wt///+/P//////////////////////////////
+ //////////////////////////////////////////////////////////////////////+k////Af//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wb///+3/////////////////////////////////////////////////////+7bj//asQr/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/+PGSv//////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////+3////Bv///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////Bv///6X/////////////////////////////////////////////
+ ////////9+7K/+HBO//YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/oz2n/////////////////////////////////////////////////////////////////////////
+ //////////////////////+l////Bv///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8B////jP//////////////////
+ ///////////////////////////////////+/fr/7t2T/924Hv/YrgD/2K4A/9iuAP/YrgD/2K4A/9iu
+ AP/YrgD/2K4A/9iuAP/YrgD/7dqL////////////////////////////////////////////////////
+ //////////////////////////////////////+M////Af///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A2K4AANiu
+ AAD///9V////8f/////////////////////////////////////////////////////8+ev/7dmH/966
+ Jv/YrgD/2K4A/9iuAP/YrgD/2K4A/9iuAP/YrgD/2K4A//Plrv//////////////////////////////
+ //////////////////////////////////////////////////H///9VmtgAAJrYAAD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////ANiuAADYrgAA2K4AAP///yT////E////////////////////////////////////////
+ ///////////////////9/PT/8+av/+bLWv/duB7/2K4A/9iuAP/YrgD/2K4A/9iuAP/37sv/////////
+ /////////////////////////////////////////////////////////////////8T///8jmtgAAJrY
+ AACa2AAA////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wDYrgAA2K4AANiuAADYrgAA////Af///2D////r////////
+ /////////////////////////////////////////////////////////fvx//btxv/v3pf/6dJw/+TH
+ T//jxEX/+/jo////////////////////////////////////////////////////////////////6///
+ /2D///8BmtgAAJrYAACa2AAAmtgAAP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////EP///3/////t////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////t////f////xD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////Df///3T////V////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////9X///90////Df///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /zP///+N////1///////////////////////////////////////////////////////////////////
+ ///////////////////////X////jf///zP///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8b////VP///33///+l////y////+P////y////////
+ ///////y////4////8v///+l////ff///1T///8b////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////4Af///////wAAD//////8AAAD/////+AAAAB/////wAAAAD////8AAAAAD////gAAAAA
+ H///4AAAAAAH///AAAAAAAP//4AAAAAAAf//AAAAAAAA//4AAAAAAAB//gAAAAAAAH/8AAAAAAAAP/gA
+ AAAAAAAf+AAAAAAAAB/wAAAAAAAAD/AAAAAAAAAH4AAAAAAAAAfgAAAAAAAAB8AAAAAAAAADwAAAAAAA
+ AAOAAAAAAAAAAYAAAAAAAAABgAAAAAAAAAGAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIAAAAAAAAABgAAAAAAAAAGAAAAAAAAAAYAAAAAAAAABwAAAAAAAAAPAAAAAAAAAA+AA
+ AAAAAAAH4AAAAAAAAAfwAAAAAAAAD/AAAAAAAAAP+AAAAAAAAB/4AAAAAAAAH/wAAAAAAAA//gAAAAAA
+ AH/+AAAAAAAAf/8AAAAAAAD//4AAAAAAAf//wAAAAAAD///gAAAAAAf///gAAAAAH////AAAAAA/////
+ AAAAAP/////AAAAD//////AAAA///////AAAP///////4Af///8=
+
+
+
\ No newline at end of file
diff --git a/Discord Media Loader/Helper/TaskBarProgress.cs b/Discord Media Loader/Helper/TaskBarProgress.cs
new file mode 100644
index 0000000..93331e3
--- /dev/null
+++ b/Discord Media Loader/Helper/TaskBarProgress.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Discord_Media_Loader.Helper
+{
+ internal static class TaskBarProgress
+ {
+ internal enum TaskbarStates
+ {
+ NoProgress = 0,
+ Indeterminate = 0x1,
+ Normal = 0x2,
+ Error = 0x4,
+ Paused = 0x8
+ }
+
+ [ComImport]
+ [Guid("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ private interface ITaskbarList3
+ {
+ // ITaskbarList
+ [PreserveSig]
+ void HrInit();
+ [PreserveSig]
+ void AddTab(IntPtr hwnd);
+ [PreserveSig]
+ void DeleteTab(IntPtr hwnd);
+ [PreserveSig]
+ void ActivateTab(IntPtr hwnd);
+ [PreserveSig]
+ void SetActiveAlt(IntPtr hwnd);
+
+ // ITaskbarList2
+ [PreserveSig]
+ void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);
+
+ // ITaskbarList3
+ [PreserveSig]
+ void SetProgressValue(IntPtr hwnd, UInt64 ullCompleted, UInt64 ullTotal);
+ [PreserveSig]
+ void SetProgressState(IntPtr hwnd, TaskbarStates state);
+ }
+
+ [Guid("56FDF344-FD6D-11d0-958A-006097C9A090")]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComImport]
+ private class TaskbarInstance
+ {
+ }
+
+ private static ITaskbarList3 taskbarInstance = (ITaskbarList3)new TaskbarInstance();
+ private static bool taskbarSupported = Environment.OSVersion.Version >= new Version(6, 1);
+
+ internal static void SetState(IntPtr windowHandle, TaskbarStates taskbarState)
+ {
+ if (taskbarSupported) taskbarInstance.SetProgressState(windowHandle, taskbarState);
+ }
+
+ internal static void SetValue(IntPtr windowHandle, double progressValue, double progressMax)
+ {
+ if (taskbarSupported) taskbarInstance.SetProgressValue(windowHandle, (ulong)progressValue, (ulong)progressMax);
+ }
+ }
+}
diff --git a/Discord Media Loader/Helper/VersionHelper.cs b/Discord Media Loader/Helper/VersionHelper.cs
index bbe1ab9..bce4af3 100644
--- a/Discord Media Loader/Helper/VersionHelper.cs
+++ b/Discord Media Loader/Helper/VersionHelper.cs
@@ -1,12 +1,7 @@
using System;
-using System.Collections.Generic;
using System.Linq;
-using System.Net;
-using System.Net.Http;
using System.Reflection;
-using System.Text;
using System.Threading.Tasks;
-using Newtonsoft.Json.Linq;
using Octokit;
namespace Discord_Media_Loader.Helper
@@ -15,32 +10,30 @@ namespace Discord_Media_Loader.Helper
{
internal static Version CurrentVersion => Assembly.GetExecutingAssembly().GetName().Version;
- internal static async Task GetLatestReleaseVersion()
+ internal static Version AppVersion => AssemblyName.GetAssemblyName("Discord Media Loader.Application.dll").Version;
+
+ internal static async Task GetReleaseVersion()
{
- var github = new GitHubClient(new ProductHeaderValue("DiscordMediaLoader"));
+ var github = new GitHubClient(new ProductHeaderValue("DiscordMedialLoader"));
+
var tag =
- (await github.Repository.Release.GetAll("Serraniel", "DiscordMediaLoader")).OrderBy(x => x.CreatedAt).First().TagName.Replace("v", "") ?? "";
+ (await github.Repository.Release.GetAll("Serraniel", "DiscordMediaLoader")).OrderByDescending(x => x.CreatedAt).First().TagName.Replace("v", "") ?? "";
+
var version = new Version(tag);
return version;
}
internal static async Task DownloadLatestReleaseVersion()
{
- return await DownloadReleaseVersion(await GetLatestReleaseVersion());
+ return await DownloadVersion(await GetReleaseVersion());
}
- internal static async Task DownloadReleaseVersion(Version version)
+ internal static async Task DownloadVersion(Version version)
{
var github = new GitHubClient(new ProductHeaderValue("DiscordMediaLoader"));
var releaseVersion = (from release in (await github.Repository.Release.GetAll("Serraniel", "DiscordMediaLoader")) where release.TagName == $"v{version.Major}.{version.Minor}.{version.Build}.{version.Revision}" select release).First();
- //where release.TagName == $"v{version.Major}.{version.Minor}.{version.Revision}.{version.Build}"
- /*var r = releases.ElementAt(0);
- if (r.TagName == $"v{version.Major}.{version.Minor}.{version.Build}.{version.Revision}")
- {
- var releaseVersion = releases.First();
- return releaseVersion.Url;
- }*/
- return releaseVersion.ZipballUrl;
+
+ return releaseVersion.Assets.FirstOrDefault()?.BrowserDownloadUrl;
}
}
}
diff --git a/Discord Media Loader/LoginForm.Designer.cs b/Discord Media Loader/LoginForm.Designer.cs
deleted file mode 100644
index fddb86d..0000000
--- a/Discord Media Loader/LoginForm.Designer.cs
+++ /dev/null
@@ -1,127 +0,0 @@
-namespace Discord_Media_Loader
-{
- partial class LoginForm
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LoginForm));
- this.lbEmail = new System.Windows.Forms.Label();
- this.lbPassword = new System.Windows.Forms.Label();
- this.tbxEmail = new System.Windows.Forms.TextBox();
- this.tbxPassword = new System.Windows.Forms.TextBox();
- this.btnLogin = new System.Windows.Forms.Button();
- this.btnAbort = new System.Windows.Forms.Button();
- this.SuspendLayout();
- //
- // lbEmail
- //
- this.lbEmail.AutoSize = true;
- this.lbEmail.Location = new System.Drawing.Point(12, 9);
- this.lbEmail.Name = "lbEmail";
- this.lbEmail.Size = new System.Drawing.Size(35, 13);
- this.lbEmail.TabIndex = 0;
- this.lbEmail.Text = "Email:";
- //
- // lbPassword
- //
- this.lbPassword.AutoSize = true;
- this.lbPassword.Location = new System.Drawing.Point(12, 35);
- this.lbPassword.Name = "lbPassword";
- this.lbPassword.Size = new System.Drawing.Size(56, 13);
- this.lbPassword.TabIndex = 1;
- this.lbPassword.Text = "Password:";
- //
- // tbxEmail
- //
- this.tbxEmail.Location = new System.Drawing.Point(79, 6);
- this.tbxEmail.Name = "tbxEmail";
- this.tbxEmail.Size = new System.Drawing.Size(204, 20);
- this.tbxEmail.TabIndex = 2;
- this.tbxEmail.KeyUp += new System.Windows.Forms.KeyEventHandler(this.tbx_KeyUp);
- //
- // tbxPassword
- //
- this.tbxPassword.Location = new System.Drawing.Point(79, 32);
- this.tbxPassword.Name = "tbxPassword";
- this.tbxPassword.PasswordChar = '•';
- this.tbxPassword.Size = new System.Drawing.Size(204, 20);
- this.tbxPassword.TabIndex = 3;
- this.tbxPassword.KeyUp += new System.Windows.Forms.KeyEventHandler(this.tbx_KeyUp);
- //
- // btnLogin
- //
- this.btnLogin.Location = new System.Drawing.Point(127, 78);
- this.btnLogin.Name = "btnLogin";
- this.btnLogin.Size = new System.Drawing.Size(75, 23);
- this.btnLogin.TabIndex = 4;
- this.btnLogin.Text = "&Login";
- this.btnLogin.UseVisualStyleBackColor = true;
- this.btnLogin.Click += new System.EventHandler(this.btnLogin_Click);
- //
- // btnAbort
- //
- this.btnAbort.Location = new System.Drawing.Point(208, 78);
- this.btnAbort.Name = "btnAbort";
- this.btnAbort.Size = new System.Drawing.Size(75, 23);
- this.btnAbort.TabIndex = 5;
- this.btnAbort.Text = "&Abort";
- this.btnAbort.UseVisualStyleBackColor = true;
- this.btnAbort.Click += new System.EventHandler(this.btnAbort_Click);
- //
- // LoginForm
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(296, 114);
- this.Controls.Add(this.btnAbort);
- this.Controls.Add(this.btnLogin);
- this.Controls.Add(this.tbxPassword);
- this.Controls.Add(this.tbxEmail);
- this.Controls.Add(this.lbPassword);
- this.Controls.Add(this.lbEmail);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
- this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "LoginForm";
- this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
- this.Text = "Login";
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private System.Windows.Forms.Label lbEmail;
- private System.Windows.Forms.Label lbPassword;
- private System.Windows.Forms.TextBox tbxEmail;
- private System.Windows.Forms.TextBox tbxPassword;
- private System.Windows.Forms.Button btnLogin;
- private System.Windows.Forms.Button btnAbort;
- }
-}
\ No newline at end of file
diff --git a/Discord Media Loader/LoginForm.cs b/Discord Media Loader/LoginForm.cs
deleted file mode 100644
index cf6f81e..0000000
--- a/Discord Media Loader/LoginForm.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using System;
-using System.Windows.Forms;
-using Discord_Media_Loader.Helper;
-
-namespace Discord_Media_Loader
-{
- public partial class LoginForm : Form
- {
- public static bool Exec(ref string email, out string password)
- {
- var loginForm = new LoginForm { tbxEmail = { Text = email } };
- password = "";
-
- if (loginForm.ShowDialog() == DialogResult.OK)
- {
- email = loginForm.tbxEmail.Text;
- password = loginForm.tbxPassword.Text;
- return true;
- }
-
- return false;
- }
-
- public LoginForm()
- {
- InitializeComponent();
- }
-
- private void btnAbort_Click(object sender, EventArgs e)
- {
- DialogResult = DialogResult.Abort;
- }
-
- private void btnLogin_Click(object sender, EventArgs e)
- {
- DialogResult = DialogResult.OK;
- }
-
- private void tbx_KeyUp(object sender, KeyEventArgs e)
- {
- if (e.KeyCode == Keys.Return)
- DialogResult = DialogResult.OK;
- else if (e.KeyCode == Keys.Escape)
- DialogResult = DialogResult.Abort;
- }
- }
-}
diff --git a/Discord Media Loader/MainForm.Designer.cs b/Discord Media Loader/MainForm.Designer.cs
deleted file mode 100644
index f572a18..0000000
--- a/Discord Media Loader/MainForm.Designer.cs
+++ /dev/null
@@ -1,312 +0,0 @@
-namespace Discord_Media_Loader
-{
- partial class MainForm
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
- this.lbPath = new System.Windows.Forms.Label();
- this.btnSearch = new System.Windows.Forms.Button();
- this.tbxPath = new System.Windows.Forms.TextBox();
- this.dtpLimit = new System.Windows.Forms.DateTimePicker();
- this.btnDownload = new System.Windows.Forms.Button();
- this.cbLimitDate = new System.Windows.Forms.CheckBox();
- this.lbThread = new System.Windows.Forms.Label();
- this.cbChannels = new System.Windows.Forms.ComboBox();
- this.nupThreadCount = new System.Windows.Forms.NumericUpDown();
- this.lbChannel = new System.Windows.Forms.Label();
- this.lbScanCount = new System.Windows.Forms.Label();
- this.lbUsername = new System.Windows.Forms.Label();
- this.lbDownload = new System.Windows.Forms.Label();
- this.cbGuilds = new System.Windows.Forms.ComboBox();
- this.lbGuild = new System.Windows.Forms.Label();
- this.cbSkip = new System.Windows.Forms.CheckBox();
- this.lbCopyright = new System.Windows.Forms.Label();
- this.lbGithub = new System.Windows.Forms.LinkLabel();
- this.lbAbout = new System.Windows.Forms.LinkLabel();
- this.lbVersion = new System.Windows.Forms.LinkLabel();
- ((System.ComponentModel.ISupportInitialize)(this.nupThreadCount)).BeginInit();
- this.SuspendLayout();
- //
- // lbPath
- //
- this.lbPath.AutoSize = true;
- this.lbPath.Location = new System.Drawing.Point(12, 110);
- this.lbPath.Name = "lbPath";
- this.lbPath.Size = new System.Drawing.Size(32, 13);
- this.lbPath.TabIndex = 8;
- this.lbPath.Text = "Path:";
- //
- // btnSearch
- //
- this.btnSearch.Location = new System.Drawing.Point(403, 105);
- this.btnSearch.Name = "btnSearch";
- this.btnSearch.Size = new System.Drawing.Size(25, 23);
- this.btnSearch.TabIndex = 9;
- this.btnSearch.Text = "...";
- this.btnSearch.UseVisualStyleBackColor = true;
- this.btnSearch.Click += new System.EventHandler(this.btnSearch_Click);
- //
- // tbxPath
- //
- this.tbxPath.Location = new System.Drawing.Point(50, 107);
- this.tbxPath.Name = "tbxPath";
- this.tbxPath.Size = new System.Drawing.Size(342, 20);
- this.tbxPath.TabIndex = 7;
- //
- // dtpLimit
- //
- this.dtpLimit.Format = System.Windows.Forms.DateTimePickerFormat.Short;
- this.dtpLimit.Location = new System.Drawing.Point(158, 70);
- this.dtpLimit.Name = "dtpLimit";
- this.dtpLimit.Size = new System.Drawing.Size(95, 20);
- this.dtpLimit.TabIndex = 6;
- //
- // btnDownload
- //
- this.btnDownload.Location = new System.Drawing.Point(12, 167);
- this.btnDownload.Name = "btnDownload";
- this.btnDownload.Size = new System.Drawing.Size(415, 23);
- this.btnDownload.TabIndex = 20;
- this.btnDownload.Text = "Start downloading";
- this.btnDownload.UseVisualStyleBackColor = true;
- this.btnDownload.Click += new System.EventHandler(this.btnDownload_Click);
- //
- // cbLimitDate
- //
- this.cbLimitDate.AutoSize = true;
- this.cbLimitDate.Checked = true;
- this.cbLimitDate.CheckState = System.Windows.Forms.CheckState.Checked;
- this.cbLimitDate.Location = new System.Drawing.Point(15, 73);
- this.cbLimitDate.Name = "cbLimitDate";
- this.cbLimitDate.Size = new System.Drawing.Size(137, 17);
- this.cbLimitDate.TabIndex = 5;
- this.cbLimitDate.Text = "Only media posted after";
- this.cbLimitDate.UseVisualStyleBackColor = true;
- this.cbLimitDate.CheckedChanged += new System.EventHandler(this.cbLimitDate_CheckedChanged);
- //
- // lbThread
- //
- this.lbThread.AutoSize = true;
- this.lbThread.Location = new System.Drawing.Point(12, 141);
- this.lbThread.Name = "lbThread";
- this.lbThread.Size = new System.Drawing.Size(64, 13);
- this.lbThread.TabIndex = 11;
- this.lbThread.Text = "Thread limit:";
- //
- // cbChannels
- //
- this.cbChannels.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- this.cbChannels.FormattingEnabled = true;
- this.cbChannels.Location = new System.Drawing.Point(279, 32);
- this.cbChannels.Name = "cbChannels";
- this.cbChannels.Size = new System.Drawing.Size(149, 21);
- this.cbChannels.TabIndex = 4;
- //
- // nupThreadCount
- //
- this.nupThreadCount.Location = new System.Drawing.Point(82, 139);
- this.nupThreadCount.Name = "nupThreadCount";
- this.nupThreadCount.Size = new System.Drawing.Size(70, 20);
- this.nupThreadCount.TabIndex = 12;
- this.nupThreadCount.Value = new decimal(new int[] {
- 50,
- 0,
- 0,
- 0});
- //
- // lbChannel
- //
- this.lbChannel.AutoSize = true;
- this.lbChannel.Location = new System.Drawing.Point(224, 38);
- this.lbChannel.Name = "lbChannel";
- this.lbChannel.Size = new System.Drawing.Size(49, 13);
- this.lbChannel.TabIndex = 3;
- this.lbChannel.Text = "Channel:";
- //
- // lbScanCount
- //
- this.lbScanCount.AutoSize = true;
- this.lbScanCount.Location = new System.Drawing.Point(12, 203);
- this.lbScanCount.Name = "lbScanCount";
- this.lbScanCount.Size = new System.Drawing.Size(102, 13);
- this.lbScanCount.TabIndex = 13;
- this.lbScanCount.Text = "Messages scanned:";
- //
- // lbUsername
- //
- this.lbUsername.AutoSize = true;
- this.lbUsername.Location = new System.Drawing.Point(12, 9);
- this.lbUsername.Name = "lbUsername";
- this.lbUsername.Size = new System.Drawing.Size(58, 13);
- this.lbUsername.TabIndex = 2;
- this.lbUsername.Text = "Username:";
- //
- // lbDownload
- //
- this.lbDownload.AutoSize = true;
- this.lbDownload.Location = new System.Drawing.Point(234, 203);
- this.lbDownload.Name = "lbDownload";
- this.lbDownload.Size = new System.Drawing.Size(92, 13);
- this.lbDownload.TabIndex = 14;
- this.lbDownload.Text = "Files downloaded:";
- //
- // cbGuilds
- //
- this.cbGuilds.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- this.cbGuilds.FormattingEnabled = true;
- this.cbGuilds.Location = new System.Drawing.Point(52, 32);
- this.cbGuilds.Name = "cbGuilds";
- this.cbGuilds.Size = new System.Drawing.Size(164, 21);
- this.cbGuilds.TabIndex = 1;
- this.cbGuilds.SelectedIndexChanged += new System.EventHandler(this.cbGuilds_SelectedIndexChanged);
- //
- // lbGuild
- //
- this.lbGuild.AutoSize = true;
- this.lbGuild.Location = new System.Drawing.Point(12, 35);
- this.lbGuild.Name = "lbGuild";
- this.lbGuild.Size = new System.Drawing.Size(34, 13);
- this.lbGuild.TabIndex = 0;
- this.lbGuild.Text = "Guild:";
- //
- // cbSkip
- //
- this.cbSkip.AutoSize = true;
- this.cbSkip.Checked = true;
- this.cbSkip.CheckState = System.Windows.Forms.CheckState.Checked;
- this.cbSkip.Location = new System.Drawing.Point(227, 141);
- this.cbSkip.Name = "cbSkip";
- this.cbSkip.Size = new System.Drawing.Size(106, 17);
- this.cbSkip.TabIndex = 16;
- this.cbSkip.Text = "Skip existing files";
- this.cbSkip.UseVisualStyleBackColor = true;
- //
- // lbCopyright
- //
- this.lbCopyright.AutoSize = true;
- this.lbCopyright.Location = new System.Drawing.Point(12, 274);
- this.lbCopyright.Name = "lbCopyright";
- this.lbCopyright.Size = new System.Drawing.Size(151, 13);
- this.lbCopyright.TabIndex = 22;
- this.lbCopyright.Text = "Copyright (c) 2017 by Serraniel";
- //
- // lbGithub
- //
- this.lbGithub.AutoSize = true;
- this.lbGithub.Location = new System.Drawing.Point(169, 274);
- this.lbGithub.Name = "lbGithub";
- this.lbGithub.Size = new System.Drawing.Size(40, 13);
- this.lbGithub.TabIndex = 23;
- this.lbGithub.TabStop = true;
- this.lbGithub.Text = "GitHub";
- this.lbGithub.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lbGithub_LinkClicked);
- //
- // lbAbout
- //
- this.lbAbout.AutoSize = true;
- this.lbAbout.Location = new System.Drawing.Point(223, 274);
- this.lbAbout.Name = "lbAbout";
- this.lbAbout.Size = new System.Drawing.Size(35, 13);
- this.lbAbout.TabIndex = 24;
- this.lbAbout.TabStop = true;
- this.lbAbout.Text = "About";
- this.lbAbout.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lbAbout_LinkClicked);
- //
- // lbVersion
- //
- this.lbVersion.Location = new System.Drawing.Point(328, 274);
- this.lbVersion.Name = "lbVersion";
- this.lbVersion.Size = new System.Drawing.Size(100, 15);
- this.lbVersion.TabIndex = 26;
- this.lbVersion.TabStop = true;
- this.lbVersion.Text = "version";
- this.lbVersion.TextAlign = System.Drawing.ContentAlignment.TopRight;
- this.lbVersion.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lbVersion_LinkClicked);
- //
- // MainForm
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(439, 296);
- this.Controls.Add(this.lbVersion);
- this.Controls.Add(this.lbAbout);
- this.Controls.Add(this.lbGithub);
- this.Controls.Add(this.lbCopyright);
- this.Controls.Add(this.cbSkip);
- this.Controls.Add(this.lbDownload);
- this.Controls.Add(this.lbScanCount);
- this.Controls.Add(this.nupThreadCount);
- this.Controls.Add(this.lbThread);
- this.Controls.Add(this.btnDownload);
- this.Controls.Add(this.tbxPath);
- this.Controls.Add(this.lbPath);
- this.Controls.Add(this.btnSearch);
- this.Controls.Add(this.dtpLimit);
- this.Controls.Add(this.cbLimitDate);
- this.Controls.Add(this.cbChannels);
- this.Controls.Add(this.lbChannel);
- this.Controls.Add(this.lbUsername);
- this.Controls.Add(this.cbGuilds);
- this.Controls.Add(this.lbGuild);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
- this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
- this.MaximizeBox = false;
- this.Name = "MainForm";
- this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
- this.Text = "Discord Media Loader";
- this.Shown += new System.EventHandler(this.MainForm_Shown);
- ((System.ComponentModel.ISupportInitialize)(this.nupThreadCount)).EndInit();
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private System.Windows.Forms.Label lbPath;
- private System.Windows.Forms.Button btnSearch;
- private System.Windows.Forms.TextBox tbxPath;
- private System.Windows.Forms.DateTimePicker dtpLimit;
- private System.Windows.Forms.Button btnDownload;
- private System.Windows.Forms.CheckBox cbLimitDate;
- private System.Windows.Forms.Label lbThread;
- private System.Windows.Forms.ComboBox cbChannels;
- private System.Windows.Forms.NumericUpDown nupThreadCount;
- private System.Windows.Forms.Label lbChannel;
- private System.Windows.Forms.Label lbScanCount;
- private System.Windows.Forms.Label lbUsername;
- private System.Windows.Forms.Label lbDownload;
- private System.Windows.Forms.ComboBox cbGuilds;
- private System.Windows.Forms.Label lbGuild;
- private System.Windows.Forms.CheckBox cbSkip;
- private System.Windows.Forms.Label lbCopyright;
- private System.Windows.Forms.LinkLabel lbGithub;
- private System.Windows.Forms.LinkLabel lbAbout;
- private System.Windows.Forms.LinkLabel lbVersion;
- }
-}
\ No newline at end of file
diff --git a/Discord Media Loader/MainForm.cs b/Discord Media Loader/MainForm.cs
deleted file mode 100644
index 72b1dfe..0000000
--- a/Discord Media Loader/MainForm.cs
+++ /dev/null
@@ -1,317 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Reflection;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using Discord;
-using Discord.Net;
-using Discord_Media_Loader.Helper;
-using ConnectionState = Discord.ConnectionState;
-
-namespace Discord_Media_Loader
-{
- public partial class MainForm : Form
- {
- private DiscordClient Client { get; } = new DiscordClient();
- private event EventHandler UpdateProgress;
- private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
- public MainForm()
- {
- InitializeComponent();
-
- UpdateProgress += (s, e) =>
- {
- SetControlPropertyThreadSafe(lbDownload, "Text", $"Files downloaded: {e.Downloaded}");
- SetControlPropertyThreadSafe(lbScanCount, "Text", $"Messages scanned: {e.Scanned}");
- };
- }
-
- private delegate void SetControlPropertyThreadSafeDelegate(Control control, string propertyName, object propertyValue);
-
- private static void SetControlPropertyThreadSafe(Control control, string propertyName, object propertyValue)
- {
- if (control.InvokeRequired)
- {
- control.Invoke(new SetControlPropertyThreadSafeDelegate(SetControlPropertyThreadSafe), control, propertyName, propertyValue);
-
- }
- else
- {
- control.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, control, new[] { propertyValue });
- }
- }
-
- public async Task Login()
- {
- var email = Properties.Settings.Default.email;
- var abort = false;
-
- while (Client.State != ConnectionState.Connected && !abort)
- {
- string password;
-
- if (LoginForm.Exec(ref email, out password))
- {
- try
- {
- Cursor = Cursors.WaitCursor;
- try
- {
- await Client.Connect(email, password);
-
- Properties.Settings.Default.email = email;
- Properties.Settings.Default.Save();
- }
- finally
- {
- Cursor = Cursors.Default;
- }
- }
- catch (HttpException)
- {
- // ignore http exception on invalid login
- }
- }
- else
- {
- abort = true;
- }
- }
-
- return !abort;
- }
-
- private async void MainForm_Shown(object sender, EventArgs e)
- {
- lbVersion.Text = $"v{VersionHelper.CurrentVersion}";
- SetEnabled(false);
- await CheckForUpdates();
-
- if (!await Login())
- {
- Close();
- }
- else
- {
- cbGuilds.Items.AddRange((from g in Client.Servers orderby g.Name select g.Name).ToArray());
- cbGuilds.SelectedIndex = 0;
- lbUsername.Text = $"Username: {Client.CurrentUser.Name}#{Client.CurrentUser.Discriminator}";
-
- SetEnabled(true);
- }
- }
-
- private Server FindServerByName(string name)
- {
- return (from s in Client.Servers where s.Name == name select s).FirstOrDefault();
- }
-
- private Channel FindChannelByName(Server server, string name)
- {
- return (from c in server.TextChannels where c.Name == name select c).FirstOrDefault();
- }
-
- private void SetEnabled(bool enabled)
- {
- foreach (Control c in Controls)
- {
- SetControlPropertyThreadSafe(c, "Enabled", enabled);
- }
- }
-
- private void cbGuilds_SelectedIndexChanged(object sender, EventArgs e)
- {
- Cursor = Cursors.WaitCursor;
- try
- {
- Server guild = FindServerByName(cbGuilds.Text);
-
- if (guild != null)
- {
- cbChannels.Items.Clear();
- cbChannels.Items.AddRange((from c in guild.TextChannels orderby c.Position select c.Name).ToArray());
-
- cbChannels.SelectedIndex = 0;
- }
- }
- finally
- {
- Cursor = Cursors.Default;
- }
- }
-
- private void cbLimitDate_CheckedChanged(object sender, EventArgs e)
- {
- dtpLimit.Enabled = cbLimitDate.Checked;
- }
-
- private void btnSearch_Click(object sender, EventArgs e)
- {
- var dlg = new FolderBrowserDialog();
- if (dlg.ShowDialog() == DialogResult.OK)
- {
- tbxPath.Text = dlg.SelectedPath;
- }
- }
-
- private void OnUpdateProgress(UpdateProgessEventArgs e)
- {
- EventHandler handler = UpdateProgress;
- handler?.Invoke(this, e);
- }
-
- private static long DateTimeToUnixTimeStamp(DateTime dateTime)
- {
- TimeSpan elapsedTime = dateTime - Epoch;
- return (long)elapsedTime.TotalSeconds;
- }
-
-
- private void btnDownload_Click(object sender, EventArgs e)
- {
- var path = tbxPath.Text;
- var useStopDate = cbLimitDate.Checked;
- var stopDate = dtpLimit.Value;
- var threadLimit = nupThreadCount.Value;
- var skipExisting = cbSkip.Checked;
-
- if (!Directory.Exists(path))
- {
- MessageBox.Show("Please enter an existing directory.");
- return;
- }
-
- SetEnabled(false);
-
- var guild = FindServerByName(cbGuilds.Text);
- var channel = FindChannelByName(guild, cbChannels.Text);
-
- var clients = new List();
-
- var limit = 100;
- var stop = false;
- var lastId = ulong.MaxValue;
- var isFirst = true;
-
- ulong msgScanCount = 0;
- ulong downloadCount = 0;
- var locker = new object();
-
- Task.Run(async () =>
- {
-
- while (!stop)
- {
- Discord.Message[] messages;
-
- if (isFirst)
- messages = await channel.DownloadMessages(limit, null);
- else
- messages = await channel.DownloadMessages(limit, lastId);
-
- isFirst = false;
-
- foreach (var m in messages)
- {
- if (m.Id < lastId)
- lastId = m.Id;
-
- if (useStopDate && m.Timestamp < stopDate.Date)
- {
- stop = true;
- continue;
- }
-
- foreach (var a in m.Attachments)
- {
- if (!path.EndsWith(@"\"))
- path += @"\";
-
- var fname = $"{guild.Name}_{channel.Name}_{DateTimeToUnixTimeStamp(m.Timestamp)}_{a.Filename}";
- fname = Path.GetInvalidFileNameChars().Aggregate(fname, (current, c) => current.Replace(c, '-'));
- fname = path + fname;
-
- if (skipExisting && File.Exists(fname))
- continue;
-
- while (clients.Count >= threadLimit)
- {
- // wait
- }
- var wc = new WebClient();
- clients.Add(wc);
-
- wc.DownloadFileCompleted += (wcSender, wcE) =>
- {
- clients.Remove(wc);
- lock (locker)
- {
- downloadCount++;
- OnUpdateProgress(new UpdateProgessEventArgs() { Downloaded = downloadCount, Scanned = msgScanCount });
- }
- };
-
- wc.DownloadFileAsync(new Uri(a.Url), fname);
- }
-
- msgScanCount++;
- OnUpdateProgress(new UpdateProgessEventArgs() { Downloaded = downloadCount, Scanned = msgScanCount });
- }
-
- stop = stop || messages.Length < limit;
- }
-
- await Task.Run(() =>
- {
- while (clients.Count > 0)
- {
- // wait until download finished
- }
- });
-
- Process.Start(path);
- SetEnabled(true);
- });
- }
-
- private void lbGithub_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
- {
- Process.Start("https://github.com/Serraniel/DiscordMediaLoader/releases");
- }
-
- private void lbAbout_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
- {
- MessageBox.Show(Properties.Resources.AboutString);
- }
-
- private async Task CheckForUpdates(bool manually = false)
- {
- if (VersionHelper.CurrentVersion < await VersionHelper.GetLatestReleaseVersion())
- {
- if (MessageBox.Show("A new version is available, do you want to update now?", "Update available", MessageBoxButtons.YesNo) != DialogResult.Yes)
- return;
-
- Process.Start(await VersionHelper.DownloadLatestReleaseVersion());
- }
- else if (manually)
- {
- MessageBox.Show("You already use the newest version.");
- }
- }
-
- private void lbVersion_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
- {
- CheckForUpdates(true);
- }
- }
-
- internal class UpdateProgessEventArgs : EventArgs
- {
- internal ulong Scanned { get; set; }
- internal ulong Downloaded { get; set; }
- }
-}
diff --git a/Discord Media Loader/Program.cs b/Discord Media Loader/Program.cs
index bd15ed5..7ce9201 100644
--- a/Discord Media Loader/Program.cs
+++ b/Discord Media Loader/Program.cs
@@ -1,20 +1,32 @@
using System;
using System.Windows.Forms;
-using Discord_Media_Loader.Helper;
+using DML.Application.Classes;
+using Nito.AsyncEx;
namespace Discord_Media_Loader
{
static class Program
{
- ///
- /// Der Haupteinstiegspunkt für die Anwendung.
- ///
[STAThread]
- static void Main()
- {
+ static void Main(string[] paramStrings)
+ {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
- Application.Run(new MainForm());
+
+ var splashScreen = new FrmSplash();
+ if (splashScreen.ShowDialog() == DialogResult.OK)
+ {
+ DoLaunch(paramStrings);
+ }
+ else
+ {
+ Application.Restart();
+ }
+ }
+
+ private static void DoLaunch(string[] paramStrings)
+ {
+ AsyncContext.Run(() => Core.Run(paramStrings));
}
}
}
diff --git a/Discord Media Loader/Properties/AssemblyInfo.cs b/Discord Media Loader/Properties/AssemblyInfo.cs
index 4760545..0f2431c 100644
--- a/Discord Media Loader/Properties/AssemblyInfo.cs
+++ b/Discord Media Loader/Properties/AssemblyInfo.cs
@@ -1,4 +1,5 @@
using System.Reflection;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
@@ -7,7 +8,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Discord Media Loader")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
+[assembly: AssemblyCompany("Serraniel")]
[assembly: AssemblyProduct("Discord Media Loader")]
[assembly: AssemblyCopyright("Copyright © 2017 by Serraniel")]
[assembly: AssemblyTrademark("")]
@@ -19,7 +20,7 @@ using System.Runtime.InteropServices;
[assembly: ComVisible(false)]
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
-[assembly: Guid("83e64057-7010-4df3-a011-f7e536508407")]
+[assembly: Guid("edc92554-dbc1-4f9c-9317-379a8bf441e8")]
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
@@ -31,5 +32,5 @@ using System.Runtime.InteropServices;
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
// übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.2.99.0")]
-[assembly: AssemblyFileVersion("0.2.99.0")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Discord Media Loader/Properties/Resources.Designer.cs b/Discord Media Loader/Properties/Resources.Designer.cs
index d6f62aa..aa3b55e 100644
--- a/Discord Media Loader/Properties/Resources.Designer.cs
+++ b/Discord Media Loader/Properties/Resources.Designer.cs
@@ -61,19 +61,12 @@ namespace Discord_Media_Loader.Properties {
}
///
- /// Sucht eine lokalisierte Zeichenfolge, die Discord Media Loader by Serraniel - Apache 2.0 License
- ///https://github.com/Serraniel/DiscordMediaLoader/
- ///
- ///Made with:
- ///Discord.Net (Copyright (c) 2015 RogueException - MIT License)
- ///Newtonsoft.Json (Copyright (c) 2007 James Newton-King - MIT License)
- ///Nito.AsyncEx (Copyright (c) 2014 StephenCleary - MIT License)
- ///RestSharp (Copyright (c) restsharp - Apache 2.0 License)
- ///WebSocket4Net (Copyright (c) kerryjiang - Apache 2.0 License) ähnelt.
+ /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
///
- internal static string AboutString {
+ internal static System.Drawing.Bitmap Serraniel_Logo4_NO_BG {
get {
- return ResourceManager.GetString("AboutString", resourceCulture);
+ object obj = ResourceManager.GetObject("Serraniel_Logo4_NO_BG", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
}
}
}
diff --git a/Discord Media Loader/Properties/Resources.resx b/Discord Media Loader/Properties/Resources.resx
index d6b0a66..3691894 100644
--- a/Discord Media Loader/Properties/Resources.resx
+++ b/Discord Media Loader/Properties/Resources.resx
@@ -117,15 +117,8 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
- Discord Media Loader by Serraniel - Apache 2.0 License
-https://github.com/Serraniel/DiscordMediaLoader/
-
-Made with:
-Discord.Net (Copyright (c) 2015 RogueException - MIT License)
-Newtonsoft.Json (Copyright (c) 2007 James Newton-King - MIT License)
-Nito.AsyncEx (Copyright (c) 2014 StephenCleary - MIT License)
-RestSharp (Copyright (c) restsharp - Apache 2.0 License)
-WebSocket4Net (Copyright (c) kerryjiang - Apache 2.0 License)
+
+
+ ..\Resources\Serraniel-Logo4-NO-BG.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
\ No newline at end of file
diff --git a/Discord Media Loader/Properties/Settings.Designer.cs b/Discord Media Loader/Properties/Settings.Designer.cs
index 89a3e69..8dd3b2e 100644
--- a/Discord Media Loader/Properties/Settings.Designer.cs
+++ b/Discord Media Loader/Properties/Settings.Designer.cs
@@ -12,7 +12,7 @@ namespace Discord_Media_Loader.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.1.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -22,17 +22,5 @@ namespace Discord_Media_Loader.Properties {
return defaultInstance;
}
}
-
- [global::System.Configuration.UserScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("")]
- public string email {
- get {
- return ((string)(this["email"]));
- }
- set {
- this["email"] = value;
- }
- }
}
}
diff --git a/Discord Media Loader/Properties/Settings.settings b/Discord Media Loader/Properties/Settings.settings
index 1b74a55..3964565 100644
--- a/Discord Media Loader/Properties/Settings.settings
+++ b/Discord Media Loader/Properties/Settings.settings
@@ -1,9 +1,7 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
diff --git a/Discord Media Loader/Resources/Serraniel-Logo4-NO-BG.png b/Discord Media Loader/Resources/Serraniel-Logo4-NO-BG.png
new file mode 100644
index 0000000..aeb98e3
Binary files /dev/null and b/Discord Media Loader/Resources/Serraniel-Logo4-NO-BG.png differ
diff --git a/Discord Media Loader/Serraniel-Logo4-ABGERUNDET.ico b/Discord Media Loader/Serraniel-Logo4-ABGERUNDET.ico
new file mode 100644
index 0000000..896024e
Binary files /dev/null and b/Discord Media Loader/Serraniel-Logo4-ABGERUNDET.ico differ
diff --git a/Discord Media Loader/packages.config b/Discord Media Loader/packages.config
index 6f2b978..eff2573 100644
--- a/Discord Media Loader/packages.config
+++ b/Discord Media Loader/packages.config
@@ -1,9 +1,64 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index ed3e4fa..76946ef 100644
--- a/README.md
+++ b/README.md
@@ -19,3 +19,14 @@ Apache License 2.0
## Requirements
* [.Net Framework 4.6](https://www.microsoft.com/en-us/download/details.aspx?id=48137) by Microsoft
+
+## How to use
+First things first: **Do not use if you have MFA enabled** as long as login is only supported via username and password. That might get you lost your account. A switch to a token based login will come soon™!
+
+Otherwise you may just do the following steps:
+ 1. Login
+ 2. Select a guild
+ 3. Select a channel
+ 4. Select a directory to save the files
+ 5. Do other settings if wished
+ 6. Press the magic button to download stuff