Compare commits
39 commits
master
...
feature/#2
Author | SHA1 | Date | |
---|---|---|---|
20f58e16c3 | |||
d3aa91f826 | |||
c5ab4a73a6 | |||
8923659610 | |||
dfcc430ab1 | |||
2f68a3d7a9 | |||
f4e4b9c02d | |||
7a90260207 | |||
4fdb226a21 | |||
2ebae762f0 | |||
321c116f34 | |||
fc359fe226 | |||
c1c0c372c7 | |||
f29e9e2b8a | |||
0772edd354 | |||
9c141e9f5c | |||
3eb8750df7 | |||
b52b6b4189 | |||
ec4ee45182 | |||
5cd9a0c200 | |||
3b8f440bb2 | |||
7358be85e3 | |||
8ca2ec9b27 | |||
c36acc0750 | |||
842266f338 | |||
6a6a2e7c9a | |||
051b0713ee | |||
2add4afa24 | |||
8aa1296887 | |||
fc27243c1e | |||
9278a804cf | |||
27ed4a00ba | |||
d7bbbeade9 | |||
a867b35cad | |||
c2cfe54bee | |||
fb364f154d | |||
b022306cfd | |||
4d6cc85732 | |||
698729cec7 |
|
@ -1,305 +0,0 @@
|
||||||
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.Extensions;
|
|
||||||
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<Job> JobList { get; set; } = new List<Job>();
|
|
||||||
public Dictionary<int, Queue<IMessage>> RunningJobs = new Dictionary<int, Queue<IMessage>>();
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
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<IMessage>();
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.Error(ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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<IMessage> 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%", message.CreatedAt.UtcDateTime.ToUnixTimeStamp().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 = message.CreatedAt.UtcDateTime.ToUnixTimeStamp();
|
|
||||||
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.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
namespace DML.Application
|
|
||||||
{
|
|
||||||
public partial class FrmInternalSplash : Form
|
|
||||||
{
|
|
||||||
public FrmInternalSplash()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace DML.Application.Helper
|
|
||||||
{
|
|
||||||
internal class IdentifiedString<T>
|
|
||||||
{
|
|
||||||
internal T Id { get; set; }
|
|
||||||
internal string Caption { get; set; }
|
|
||||||
|
|
||||||
internal IdentifiedString(T id, string caption)
|
|
||||||
{
|
|
||||||
Id = id;
|
|
||||||
Caption = caption;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() => Caption;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using DML.Application.Classes;
|
|
||||||
using Nito.AsyncEx;
|
|
||||||
|
|
||||||
namespace Discord_Media_Loader
|
|
||||||
{
|
|
||||||
static class Program
|
|
||||||
{
|
|
||||||
[STAThread]
|
|
||||||
static void Main(string[] paramStrings)
|
|
||||||
{
|
|
||||||
Application.EnableVisualStyles();
|
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
26
Discord Media Loader/Properties/Settings.Designer.cs
generated
|
@ -1,26 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// 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.
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace Discord_Media_Loader.Properties {
|
|
||||||
|
|
||||||
|
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
|
||||||
[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())));
|
|
||||||
|
|
||||||
public static Settings Default {
|
|
||||||
get {
|
|
||||||
return defaultInstance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,19 @@
|
||||||
using System.Threading.Tasks;
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Client".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Client" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited DMLClient.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
|
|
@ -1,31 +1,53 @@
|
||||||
using System;
|
#region LICENSE
|
||||||
using System.Collections.Generic;
|
/**********************************************************************************************
|
||||||
using System.Linq;
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
using System.Threading.Tasks;
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited Job.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using DML.Application.Classes;
|
using DML.Application.Classes;
|
||||||
using DML.Client;
|
using DML.Client;
|
||||||
using SweetLib.Utils;
|
|
||||||
using SweetLib.Utils.Extensions;
|
using SweetLib.Utils.Extensions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using static SweetLib.Utils.Logger.Logger;
|
using static SweetLib.Utils.Logger.Logger;
|
||||||
|
|
||||||
namespace DML.AppCore.Classes
|
namespace DML.AppCore.Classes
|
||||||
{
|
{
|
||||||
|
internal enum JobState
|
||||||
|
{
|
||||||
|
Idle,
|
||||||
|
Scanning,
|
||||||
|
Listening
|
||||||
|
}
|
||||||
|
|
||||||
public class Job
|
public class Job
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public ulong GuildId { get; set; }
|
public ulong GuildId { get; set; }
|
||||||
public ulong ChannelId { get; set; }
|
public ulong ChannelId { get; set; }
|
||||||
public double KnownTimestamp { get; set; } = 0;
|
public ulong LastMessageId { get; set; } = 0;
|
||||||
private double StopTimestamp { get; set; } = 0;
|
|
||||||
private bool IsValid { get; set; } = true;
|
private bool IsValid { get; set; } = true;
|
||||||
|
internal JobState State { get; set; } = JobState.Idle;
|
||||||
|
|
||||||
|
|
||||||
internal void Store()
|
internal void Store()
|
||||||
{
|
{
|
||||||
Debug("Storing job to database...");
|
Debug("Storing job to database...");
|
||||||
Trace("Getting jobs collection...");
|
Trace("Getting jobs collection...");
|
||||||
var jobDb = Core.Database.GetCollection<Job>("jobs");
|
var jobDb = Application.Core.Core.Database.GetCollection<Job>("jobs");
|
||||||
|
|
||||||
Trace("Adding new value...");
|
Trace("Adding new value...");
|
||||||
|
|
||||||
|
@ -43,7 +65,7 @@ namespace DML.AppCore.Classes
|
||||||
{
|
{
|
||||||
Debug("Deleting job from database...");
|
Debug("Deleting job from database...");
|
||||||
Trace("Getting jobs collection...");
|
Trace("Getting jobs collection...");
|
||||||
var jobDb = Core.Database.GetCollection<Job>("jobs");
|
var jobDb = Application.Core.Core.Database.GetCollection<Job>("jobs");
|
||||||
|
|
||||||
Trace("Deleting value...");
|
Trace("Deleting value...");
|
||||||
jobDb.Delete(Id);
|
jobDb.Delete(Id);
|
||||||
|
@ -61,115 +83,96 @@ namespace DML.AppCore.Classes
|
||||||
return (from c in server.TextChannels where c.Id == id select c).FirstOrDefault();
|
return (from c in server.TextChannels where c.Id == id select c).FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task<List<IMessage>> Scan()
|
/// <summary>
|
||||||
|
/// Performs scanning task of the job.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns true if the newest messages have been scanned.</returns>
|
||||||
|
internal async Task<bool> Scan()
|
||||||
{
|
{
|
||||||
Debug($"Starting scan of guild {GuildId} channel {ChannelId}...");
|
Debug($"Starting scan of guild {GuildId} channel {ChannelId}...");
|
||||||
var result = new List<IMessage>();
|
var result = new List<IMessage>();
|
||||||
|
const ushort limit = 100;
|
||||||
|
State = JobState.Scanning;
|
||||||
|
|
||||||
var limit = 100;
|
|
||||||
var lastId = ulong.MaxValue;
|
|
||||||
var isFirst = true;
|
|
||||||
var finished = false;
|
var finished = false;
|
||||||
|
var scanStartTimeStamp = DateTime.UtcNow;
|
||||||
|
|
||||||
var guild = FindServerById(GuildId);
|
var guild = FindServerById(GuildId);
|
||||||
var channel = FindChannelById(guild, ChannelId);
|
var channel = FindChannelById(guild, ChannelId);
|
||||||
|
|
||||||
Debug("Checking channel access");
|
Debug("Checking channel access");
|
||||||
//channel.GetUser(channel.Guild.CurrentUser.Id);
|
|
||||||
if (channel.GetUser(channel.Guild.CurrentUser.Id) == null)
|
if (channel.GetUser(channel.Guild.CurrentUser.Id) == null)
|
||||||
{
|
{
|
||||||
Info("Skipping channel without access");
|
Info("Skipping channel without access");
|
||||||
return result;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.Abs(StopTimestamp) < 0.4)
|
|
||||||
StopTimestamp = KnownTimestamp;
|
|
||||||
Trace("Initialized scanning parameters.");
|
Trace("Initialized scanning parameters.");
|
||||||
|
|
||||||
while (!finished)
|
while (!finished)
|
||||||
{
|
{
|
||||||
Trace("Entering scanning loop...");
|
Trace("Entering scanning loop...");
|
||||||
var messages = new List<IMessage>();
|
var messages = new List<IMessage>();
|
||||||
|
|
||||||
Trace($"Downloading next {limit} messages...");
|
Trace($"Downloading next {limit} messages...");
|
||||||
if (isFirst)
|
messages.AddRange((await channel.GetMessagesAsync(LastMessageId, Direction.After, limit).ToArray()).SelectMany(collection => collection));
|
||||||
{
|
|
||||||
//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;
|
|
||||||
|
|
||||||
|
Debug($"Downloaded {messages.Count} messages.");
|
||||||
|
Trace("Iterating messages...");
|
||||||
foreach (var m in messages)
|
foreach (var m in messages)
|
||||||
{
|
{
|
||||||
if (!IsValid)
|
if (!IsValid)
|
||||||
return null;
|
|
||||||
|
|
||||||
Core.Scheduler.MessagesScanned++;
|
|
||||||
|
|
||||||
Debug($"Processing message {m.Id}");
|
|
||||||
if (m.Id < lastId)
|
|
||||||
{
|
{
|
||||||
Trace($"Updating lastId ({lastId}) to {m.Id}");
|
return false;
|
||||||
lastId = m.Id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m.CreatedAt.UtcDateTime.ToUnixTimeStamp() <= StopTimestamp)
|
Application.Core.Core.Scheduler.MessagesScanned++;
|
||||||
|
|
||||||
|
Debug($"Processing message {m.Id}");
|
||||||
|
if (m.Id > LastMessageId)
|
||||||
{
|
{
|
||||||
Debug("Found a message with a known timestamp...Stopping scan.");
|
Trace($"Updating lastId ({LastMessageId}) to {m.Id}");
|
||||||
finished = true;
|
LastMessageId = m.Id;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Trace($"Message {m.Id} has {m.Attachments.Count} attachments.");
|
Trace($"Message {m.Id} has {m.Attachments.Count} attachments.");
|
||||||
if (m.Attachments.Count > 0)
|
if (m.Attachments.Count > 0)
|
||||||
{
|
{
|
||||||
result.Add(m);
|
result.Add(m);
|
||||||
Core.Scheduler.TotalAttachments += (ulong)m.Attachments.Count;
|
Application.Core.Core.Scheduler.TotalAttachments += (ulong)m.Attachments.Count;
|
||||||
Trace($"Added message {m.Id}");
|
Trace($"Added message {m.Id}");
|
||||||
}
|
}
|
||||||
Debug($"Finished message {m.Id}");
|
Debug($"Finished message {m.Id}");
|
||||||
}
|
}
|
||||||
|
|
||||||
finished = finished || messages.Count < limit;
|
finished = messages.Count < limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
Trace($"Downloaded all messages for guild {GuildId} channel {ChannelId}.");
|
Trace($"Downloaded all messages for guild {GuildId} channel {ChannelId}.");
|
||||||
|
|
||||||
Trace("Sorting messages...");
|
Trace("Sorting messages...");
|
||||||
result.Sort((a, b) => DateTime.Compare(a.CreatedAt.UtcDateTime, b.CreatedAt.UtcDateTime));
|
result.Sort((a, b) => DateTime.Compare(a.CreatedAt.UtcDateTime, b.CreatedAt.UtcDateTime));
|
||||||
|
|
||||||
if (result.Count > 0)
|
foreach (var message in result)
|
||||||
{
|
{
|
||||||
Trace("Updating StopTimestamp for next scan...");
|
foreach (var attachment in message.Attachments)
|
||||||
StopTimestamp = result[result.Count - 1].CreatedAt.UtcDateTime.ToUnixTimeStamp();
|
{
|
||||||
|
var mediaData = new MediaData
|
||||||
|
{
|
||||||
|
Id = attachment.Id,
|
||||||
|
GuildId = (message.Channel as SocketTextChannel)?.Guild?.Id ?? 0,
|
||||||
|
ChannelId = message.Channel.Id,
|
||||||
|
DownloadSource = attachment.Url,
|
||||||
|
Filename = attachment.Filename,
|
||||||
|
TimeStamp = message.CreatedAt.UtcDateTime.ToUnixTimeStamp(),
|
||||||
|
FileSize = attachment.Size
|
||||||
|
};
|
||||||
|
mediaData.Store();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Debug($"Fisnished scan of guild {GuildId} channel {ChannelId}.");
|
Debug($"Fisnished scan of guild {GuildId} channel {ChannelId}.");
|
||||||
|
return true;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
|
@ -181,7 +184,7 @@ namespace DML.AppCore.Classes
|
||||||
{
|
{
|
||||||
Debug("Restoring jobs...");
|
Debug("Restoring jobs...");
|
||||||
Trace("Getting jobs collection...");
|
Trace("Getting jobs collection...");
|
||||||
var jobDb = Core.Database.GetCollection<Job>("jobs");
|
var jobDb = Application.Core.Core.Database.GetCollection<Job>("jobs");
|
||||||
|
|
||||||
Trace("Creating new empty job list");
|
Trace("Creating new empty job list");
|
||||||
return jobDb.FindAll();
|
return jobDb.FindAll();
|
172
src/Discord Media Loader.Application/Classes/JobScheduler.cs
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited JobScheduler.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using DML.AppCore.Classes;
|
||||||
|
using SweetLib.Utils.Extensions;
|
||||||
|
using SweetLib.Utils.Logger;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DML.Application.Classes
|
||||||
|
{
|
||||||
|
public class JobScheduler
|
||||||
|
{
|
||||||
|
private ulong messageScanned = 0;
|
||||||
|
private ulong totalAttachments = 0;
|
||||||
|
private ulong attachmentsDownloaded = 0;
|
||||||
|
|
||||||
|
private bool Run { get; set; } = false;
|
||||||
|
public List<Job> JobList { get; set; } = new List<Job>();
|
||||||
|
public Dictionary<int, Queue<IMessage>> RunningJobs { get; } = new Dictionary<int, Queue<IMessage>>();
|
||||||
|
internal int RunningThreads { get; set; } = 0;
|
||||||
|
internal Task SchedulerTask { get; private set; }
|
||||||
|
internal Task DownloadTask { get; private set; }
|
||||||
|
|
||||||
|
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 StartScheduler()
|
||||||
|
{
|
||||||
|
Logger.Info("Starting scheduler jobs");
|
||||||
|
SchedulerTask = Task.Run(() =>
|
||||||
|
{
|
||||||
|
PerformSchedulerTask();
|
||||||
|
});
|
||||||
|
|
||||||
|
DownloadTask = Task.Run(() =>
|
||||||
|
{
|
||||||
|
PerformDownloads();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
Run = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void PerformSchedulerTask()
|
||||||
|
{
|
||||||
|
Logger.Trace("SchedulerTask started");
|
||||||
|
foreach (var job in JobList)
|
||||||
|
{
|
||||||
|
if (job.State == JobState.Idle)
|
||||||
|
{
|
||||||
|
// scan all old messages first
|
||||||
|
Logger.Debug($"Starting scan for job {job.Id}");
|
||||||
|
await job.Scan();
|
||||||
|
job.State = JobState.Listening; // set to listening now
|
||||||
|
Logger.Debug($"Scan for job {job.Id} finished");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Logger.Trace("All jobs have been scanned");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void PerformDownloads()
|
||||||
|
{
|
||||||
|
Logger.Trace("SchedulerTask started");
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task HandleMessageReceived(SocketMessage msg)
|
||||||
|
{
|
||||||
|
Logger.Trace($"Received message: Id: {msg.Id}, Channel: {msg.Channel.Id}, Attachments: {msg.Attachments.Count}");
|
||||||
|
|
||||||
|
if (msg.Attachments.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var job in JobList)
|
||||||
|
{
|
||||||
|
if (job.State != JobState.Listening || job.ChannelId != msg.Channel.Id)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Debug($"Job found [{job.Id}]");
|
||||||
|
foreach (var attachment in msg.Attachments)
|
||||||
|
{
|
||||||
|
var mediaData = new MediaData
|
||||||
|
{
|
||||||
|
Id = attachment.Id,
|
||||||
|
GuildId = (msg.Channel as SocketTextChannel)?.Guild?.Id ?? 0,
|
||||||
|
ChannelId = msg.Channel.Id,
|
||||||
|
DownloadSource = attachment.Url,
|
||||||
|
Filename = attachment.Filename,
|
||||||
|
TimeStamp = msg.CreatedAt.UtcDateTime.ToUnixTimeStamp(),
|
||||||
|
FileSize = attachment.Size
|
||||||
|
};
|
||||||
|
mediaData.Store();
|
||||||
|
}
|
||||||
|
|
||||||
|
job.LastMessageId = msg.Id;
|
||||||
|
job.Store();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
112
src/Discord Media Loader.Application/Classes/MediaData.cs
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited MediaData.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using DML.Client;
|
||||||
|
using SweetLib.Utils.Logger;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using static SweetLib.Utils.Logger.Logger;
|
||||||
|
|
||||||
|
namespace DML.Application.Classes
|
||||||
|
{
|
||||||
|
public class MediaData
|
||||||
|
{
|
||||||
|
public ulong Id { get; set; }
|
||||||
|
public string DownloadSource { get; set; }
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
|
public ulong ChannelId { get; set; }
|
||||||
|
public double TimeStamp { get; set; }
|
||||||
|
public string Filename { get; set; }
|
||||||
|
public int FileSize { get; set; }
|
||||||
|
|
||||||
|
internal void Store()
|
||||||
|
{
|
||||||
|
Debug("Storing job to database...");
|
||||||
|
Trace("Getting jobs collection...");
|
||||||
|
var db = Core.Core.Database.GetCollection<MediaData>("media");
|
||||||
|
|
||||||
|
Trace("Adding new value...");
|
||||||
|
|
||||||
|
if (db.Find(x => x.Id == Id).Any())
|
||||||
|
{
|
||||||
|
db.Update(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
db.Insert(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Delete()
|
||||||
|
{
|
||||||
|
Debug("Deleting job from database...");
|
||||||
|
Trace("Getting jobs collection...");
|
||||||
|
var db = Core.Core.Database.GetCollection<MediaData>("media");
|
||||||
|
|
||||||
|
Trace("Deleting value...");
|
||||||
|
db.Delete(Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task Download()
|
||||||
|
{
|
||||||
|
Trace("Beginning attachment download...");
|
||||||
|
|
||||||
|
Debug("Building filename...");
|
||||||
|
var fileName = Path.Combine(Core.Core.Settings.OperatingFolder, Core.Core.Settings.FileNameScheme);
|
||||||
|
|
||||||
|
Debug($"Base filename: {fileName}");
|
||||||
|
|
||||||
|
Trace("Determining if extension is required");
|
||||||
|
var extensionRequired = !fileName.EndsWith("%name%");
|
||||||
|
Trace($"Extension required: {extensionRequired}");
|
||||||
|
|
||||||
|
Trace("Replacing filename placeholders...");
|
||||||
|
var guildName = DMLClient.Client.GetGuild(GuildId)?.Name ?? GuildId.ToString();
|
||||||
|
var channelName = DMLClient.Client.GetGuild(GuildId)?.GetChannel(ChannelId)?.Name ?? ChannelId.ToString();
|
||||||
|
|
||||||
|
fileName =
|
||||||
|
fileName.Replace("%guild%", guildName)
|
||||||
|
.Replace("%channel%", channelName)
|
||||||
|
.Replace("%timestamp%", TimeStamp.ToString("####"))
|
||||||
|
.Replace("%name%", Filename)
|
||||||
|
.Replace("%id%", Id.ToString());
|
||||||
|
|
||||||
|
Trace("Adding extension if required");
|
||||||
|
if (extensionRequired)
|
||||||
|
{
|
||||||
|
fileName += Path.GetExtension(Filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug($"Final filename: {fileName}");
|
||||||
|
|
||||||
|
if (File.Exists(fileName) && new FileInfo(fileName).Length == FileSize)
|
||||||
|
{
|
||||||
|
Logger.Debug($"{fileName} already existing with its estimated size. Skipping...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var wc = new WebClient();
|
||||||
|
Logger.Debug($"Starting downloading of attachment {Id}...");
|
||||||
|
wc.DownloadFile(new Uri(DownloadSource), fileName);
|
||||||
|
Logger.Debug($"Downloaded attachment {Id}.");
|
||||||
|
|
||||||
|
|
||||||
|
Core.Core.Scheduler.AttachmentsDownloaded++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited DiscordRpc.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace DML.Application.Classes.RPC
|
||||||
|
{
|
||||||
|
// https://github.com/discordapp/discord-rpc/blob/master/examples/button-clicker/Assets/DiscordRpc.cs
|
||||||
|
// Give that man a cookie ^.^
|
||||||
|
|
||||||
|
public class DiscordRpc
|
||||||
|
{
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
public delegate void ReadyCallback();
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
public delegate void DisconnectedCallback(int errorCode, string message);
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
public delegate void ErrorCallback(int errorCode, string message);
|
||||||
|
|
||||||
|
public struct EventHandlers
|
||||||
|
{
|
||||||
|
public ReadyCallback readyCallback;
|
||||||
|
public DisconnectedCallback disconnectedCallback;
|
||||||
|
public ErrorCallback errorCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values explanation and example: https://discordapp.com/developers/docs/rich-presence/how-to#updating-presence-update-presence-payload-fields
|
||||||
|
[System.Serializable]
|
||||||
|
public struct RichPresence
|
||||||
|
{
|
||||||
|
public string state; /* max 128 bytes */
|
||||||
|
public string details; /* max 128 bytes */
|
||||||
|
public long startTimestamp;
|
||||||
|
public long endTimestamp;
|
||||||
|
public string largeImageKey; /* max 32 bytes */
|
||||||
|
public string largeImageText; /* max 128 bytes */
|
||||||
|
public string smallImageKey; /* max 32 bytes */
|
||||||
|
public string smallImageText; /* max 128 bytes */
|
||||||
|
public string partyId; /* max 128 bytes */
|
||||||
|
public int partySize;
|
||||||
|
public int partyMax;
|
||||||
|
public string matchSecret; /* max 128 bytes */
|
||||||
|
public string joinSecret; /* max 128 bytes */
|
||||||
|
public string spectateSecret; /* max 128 bytes */
|
||||||
|
public bool instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport(RpcWrapper.Dll, EntryPoint = "Discord_Initialize", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern void Initialize(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId);
|
||||||
|
|
||||||
|
[DllImport(RpcWrapper.Dll, EntryPoint = "Discord_UpdatePresence", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern void UpdatePresence(ref RichPresence presence);
|
||||||
|
|
||||||
|
[DllImport(RpcWrapper.Dll, EntryPoint = "Discord_RunCallbacks", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern void RunCallbacks();
|
||||||
|
|
||||||
|
[DllImport(RpcWrapper.Dll, EntryPoint = "Discord_Shutdown", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern void Shutdown();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited DiscordRpcHelper.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DML.Application.Classes.RPC
|
||||||
|
{
|
||||||
|
public static class DiscordRpcHelper
|
||||||
|
{
|
||||||
|
public static long DateTimeToTimestamp(DateTime dt)
|
||||||
|
{
|
||||||
|
return (dt.Ticks - 621355968000000000) / 10000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited RpcWrapper.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace DML.Application.Classes.RPC
|
||||||
|
{
|
||||||
|
public class RpcWrapper
|
||||||
|
{
|
||||||
|
public const string Dll = "discord-rpc-win32";
|
||||||
|
|
||||||
|
public RpcWrapper()
|
||||||
|
{
|
||||||
|
if (!File.Exists(Dll + ".dll"))
|
||||||
|
{
|
||||||
|
MessageBox.Show(
|
||||||
|
"Missing " + Dll + ".dll\n\n" +
|
||||||
|
"Grab it from the release on GitHub or from the DiscordRpcDemo/lib/ folder in the repo then put it alongside DiscordRpcDemo.exe.\n\n" +
|
||||||
|
"https://github.com/nostrenz/cshap-discord-rpc-demo"
|
||||||
|
);
|
||||||
|
|
||||||
|
System.Windows.Forms.Application.Exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,19 @@
|
||||||
using SweetLib.Utils.Logger;
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited Settings.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using SweetLib.Utils.Logger;
|
||||||
|
|
||||||
namespace DML.Application.Classes
|
namespace DML.Application.Classes
|
||||||
{
|
{
|
||||||
|
@ -16,11 +31,13 @@ namespace DML.Application.Classes
|
||||||
public bool SkipExistingFiles { get; set; } = true;
|
public bool SkipExistingFiles { get; set; } = true;
|
||||||
public int ThreadLimit { get; set; } = 50;
|
public int ThreadLimit { get; set; } = 50;
|
||||||
public bool ShowStartUpHints { get; set; } = true;
|
public bool ShowStartUpHints { get; set; } = true;
|
||||||
|
public bool RescanRequired { get; set; } = false;
|
||||||
|
public bool UseRPC { get; set; } = false;
|
||||||
|
|
||||||
public void Store()
|
public void Store()
|
||||||
{
|
{
|
||||||
Logger.Trace("Getting settings collection...");
|
Logger.Trace("Getting settings collection...");
|
||||||
var settingsDB = Core.Database.GetCollection<Settings>("settings");
|
var settingsDB = Core.Core.Database.GetCollection<Settings>("settings");
|
||||||
|
|
||||||
Logger.Debug("Storing settings to database...");
|
Logger.Debug("Storing settings to database...");
|
||||||
|
|
|
@ -1,7 +1,24 @@
|
||||||
using Discord;
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited Core.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using Discord;
|
||||||
using Discord.Net;
|
using Discord.Net;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using DML.AppCore.Classes;
|
using DML.AppCore.Classes;
|
||||||
|
using DML.Application.Classes;
|
||||||
|
using DML.Application.Classes.RPC;
|
||||||
using DML.Application.Dialogs;
|
using DML.Application.Dialogs;
|
||||||
using DML.Client;
|
using DML.Client;
|
||||||
using LiteDB;
|
using LiteDB;
|
||||||
|
@ -19,7 +36,7 @@ using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Logger = SweetLib.Utils.Logger.Logger;
|
using Logger = SweetLib.Utils.Logger.Logger;
|
||||||
|
|
||||||
namespace DML.Application.Classes
|
namespace DML.Application.Core
|
||||||
{
|
{
|
||||||
public static class Core
|
public static class Core
|
||||||
{
|
{
|
||||||
|
@ -27,11 +44,14 @@ namespace DML.Application.Classes
|
||||||
internal static LiteDatabase Database { get; set; }
|
internal static LiteDatabase Database { get; set; }
|
||||||
internal static Settings Settings { get; set; }
|
internal static Settings Settings { get; set; }
|
||||||
internal static JobScheduler Scheduler { get; } = new JobScheduler();
|
internal static JobScheduler Scheduler { get; } = new JobScheduler();
|
||||||
internal static RavenClient Raven = new RavenClient("https://0de964231669473e9098b9f6cc1d6278:79d9f2eb24034de199b2a37cc058e0f2@sentry.io/257114");
|
internal static RavenClient Raven { get; } = new RavenClient("https://0de964231669473e9098b9f6cc1d6278:79d9f2eb24034de199b2a37cc058e0f2@sentry.io/257114");
|
||||||
|
internal static bool ShuttingDown { get; private set; } = false;
|
||||||
internal static string DataDirectory
|
internal static string DataDirectory
|
||||||
=> Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Serraniel\Discord Media Loader");
|
=> Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Serraniel\Discord Media Loader");
|
||||||
|
|
||||||
|
internal static DiscordRpc.RichPresence RpcPresence;
|
||||||
|
internal static DiscordRpc.EventHandlers RpcHandlers = new DiscordRpc.EventHandlers();
|
||||||
|
|
||||||
public static async Task Run(string[] paramStrings)
|
public static async Task Run(string[] paramStrings)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -91,10 +111,16 @@ namespace DML.Application.Classes
|
||||||
logMemory.ArchiveFile = logFile;
|
logMemory.ArchiveFile = logFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var databasePath = Path.Combine(DataDirectory, "config.db");
|
||||||
|
#if DEBUG
|
||||||
|
databasePath = Path.Combine(DataDirectory, "config.debug.db");
|
||||||
|
#endif
|
||||||
Logger.Debug("Loading database...");
|
Logger.Debug("Loading database...");
|
||||||
Database = new LiteDatabase(Path.Combine(DataDirectory, "config.db"));
|
Database = new LiteDatabase(databasePath);
|
||||||
Database.Log.Logging += (message) => Logger.Trace($"LiteDB: {message}");
|
Database.Log.Logging += (message) => Logger.Trace($"LiteDB: {message}");
|
||||||
|
|
||||||
|
Migrator.CheckMigrations();
|
||||||
|
|
||||||
Logger.Debug("Loading settings collection out of database...");
|
Logger.Debug("Loading settings collection out of database...");
|
||||||
var settingsDB = Database.GetCollection<Settings>("settings");
|
var settingsDB = Database.GetCollection<Settings>("settings");
|
||||||
if (settingsDB.Count() > 1)
|
if (settingsDB.Count() > 1)
|
||||||
|
@ -245,17 +271,59 @@ namespace DML.Application.Classes
|
||||||
job.Stop();
|
job.Stop();
|
||||||
job.Delete();
|
job.Delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Settings.RescanRequired)
|
||||||
|
{
|
||||||
|
Logger.Info("Restting timestamps");
|
||||||
|
job.LastMessageId = 0;
|
||||||
|
job.Store();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// Settings.RescanRequired = false;
|
||||||
|
// Settings.Store();
|
||||||
|
|
||||||
|
if (Settings.UseRPC)
|
||||||
|
{
|
||||||
|
Logger.Info("Initializing RPC client");
|
||||||
|
Logger.Trace("Registering RPC handlers");
|
||||||
|
RpcHandlers.readyCallback += RpcReadyCallback;
|
||||||
|
RpcHandlers.disconnectedCallback += RpcDisconnectedCallback;
|
||||||
|
RpcHandlers.errorCallback += RpcErrorCallback;
|
||||||
|
RpcPresence.startTimestamp = DiscordRpcHelper.DateTimeToTimestamp(DateTime.UtcNow);
|
||||||
|
|
||||||
|
Logger.Debug("Calling RPC initialize");
|
||||||
|
DiscordRpc.Initialize("430025401851707393", ref RpcHandlers, true, null);
|
||||||
|
|
||||||
|
// Do not await ;)
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
while (!ShuttingDown)
|
||||||
|
{
|
||||||
|
Logger.Trace("Running RPC callbacks");
|
||||||
|
await Task.Delay(5000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DMLClient.Client.MessageReceived += Scheduler.HandleMessageReceived;
|
||||||
|
|
||||||
splash.Close();
|
splash.Close();
|
||||||
|
|
||||||
Logger.Info("Starting scheduler...");
|
Logger.Info("Starting scheduler...");
|
||||||
Scheduler.Start();
|
Scheduler.StartScheduler();
|
||||||
|
|
||||||
System.Windows.Forms.Application.Run(new MainForm());
|
System.Windows.Forms.Application.Run(new MainForm());
|
||||||
|
|
||||||
|
// shutting down
|
||||||
|
ShuttingDown = true;
|
||||||
|
|
||||||
Logger.Info("Stopping scheduler...");
|
Logger.Info("Stopping scheduler...");
|
||||||
Scheduler.Stop();
|
Scheduler.Stop();
|
||||||
|
|
||||||
|
Logger.Info("Shutting down RPC client");
|
||||||
|
DiscordRpc.Shutdown();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -285,5 +353,26 @@ namespace DML.Application.Classes
|
||||||
Logger.Trace($"Trying to find channel in {server} by id: {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();
|
return (from c in server.TextChannels where c.Id == id select c).FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void RpcUpdatePresence()
|
||||||
|
{
|
||||||
|
Logger.Debug("Updating RPC presence");
|
||||||
|
DiscordRpc.UpdatePresence(ref RpcPresence);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RpcReadyCallback()
|
||||||
|
{
|
||||||
|
Logger.Debug("RpcReady");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RpcDisconnectedCallback(int errorCode, string message)
|
||||||
|
{
|
||||||
|
Logger.Warn($"RPC disconnect received: {errorCode} - {message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RpcErrorCallback(int errorCode, string message)
|
||||||
|
{
|
||||||
|
Logger.Error($"RPC error received: {errorCode} - {message}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
70
src/Discord Media Loader.Application/Core/Migrator.cs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited Migrator.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DML.AppCore.Classes;
|
||||||
|
using LiteDB;
|
||||||
|
|
||||||
|
namespace DML.Application.Core
|
||||||
|
{
|
||||||
|
internal static class Migrator
|
||||||
|
{
|
||||||
|
internal static ushort Version => 1;
|
||||||
|
|
||||||
|
internal static void CheckMigrations()
|
||||||
|
{
|
||||||
|
var baseVersion = Core.Database.Engine.UserVersion;
|
||||||
|
|
||||||
|
for (var step = (ushort)(baseVersion + 1); step <= Version; step++)
|
||||||
|
{
|
||||||
|
Migrate(step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Migrate(ushort step)
|
||||||
|
{
|
||||||
|
switch (step)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
// base database
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
foreach (var jobDoc in Core.Database.Engine.Find("jobs", Query.All()))
|
||||||
|
{
|
||||||
|
// pseudo datetime snowflake conversion https://discordapp.com/developers/docs/reference#convert-snowflake-to-datetime
|
||||||
|
var pseudoId = 0UL;
|
||||||
|
var timestamp = (ulong)jobDoc["KnownTimestamp"].AsDouble * 1000; // milliseconds have not been stored
|
||||||
|
|
||||||
|
if (timestamp > 0)
|
||||||
|
{
|
||||||
|
pseudoId = timestamp - 1420070400000 << 22;
|
||||||
|
pseudoId = pseudoId - (1000UL * 60 * 60 * 24 << 22); // substract one random day of pseudo id just in case the timestamp has errors
|
||||||
|
}
|
||||||
|
|
||||||
|
jobDoc["LastMessageId"] = Convert.ToInt64(pseudoId); // LiteDB maps (u)long to Int64
|
||||||
|
jobDoc.Remove("KnownTimestamp");
|
||||||
|
|
||||||
|
Core.Database.Engine.Update("jobs", jobDoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Core.Database.Engine.UserVersion = step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -164,9 +164,14 @@
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Classes\Core.cs" />
|
<Compile Include="Core\Core.cs" />
|
||||||
<Compile Include="Classes\Job.cs" />
|
<Compile Include="Classes\Job.cs" />
|
||||||
<Compile Include="Classes\JobScheduler.cs" />
|
<Compile Include="Classes\JobScheduler.cs" />
|
||||||
|
<Compile Include="Classes\RPC\DiscordRpc.cs" />
|
||||||
|
<Compile Include="Classes\RPC\DiscordRpcHelper.cs" />
|
||||||
|
<Compile Include="Classes\RPC\RpcWrapper.cs" />
|
||||||
|
<Compile Include="Classes\MediaData.cs" />
|
||||||
|
<Compile Include="Core\Migrator.cs" />
|
||||||
<Compile Include="Dialogs\LoginDialog.cs">
|
<Compile Include="Dialogs\LoginDialog.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
|
@ -1,4 +1,19 @@
|
||||||
namespace DML.Application.Dialogs
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited LoginDialog.Designer.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace DML.Application.Dialogs
|
||||||
{
|
{
|
||||||
partial class LoginDialog
|
partial class LoginDialog
|
||||||
{
|
{
|
|
@ -1,4 +1,19 @@
|
||||||
using System;
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited LoginDialog.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using DML.Application.Classes;
|
using DML.Application.Classes;
|
||||||
using static SweetLib.Utils.Logger.Logger;
|
using static SweetLib.Utils.Logger.Logger;
|
||||||
|
@ -15,7 +30,7 @@ namespace DML.Application.Dialogs
|
||||||
private void LoginDialog_Shown(object sender, EventArgs e)
|
private void LoginDialog_Shown(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Trace("Login dialog shown.");
|
Trace("Login dialog shown.");
|
||||||
edToken.Text = Core.Settings.LoginToken;
|
edToken.Text = Core.Core.Settings.LoginToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoginDialog_FormClosing(object sender, FormClosingEventArgs e)
|
private void LoginDialog_FormClosing(object sender, FormClosingEventArgs e)
|
||||||
|
@ -25,9 +40,9 @@ namespace DML.Application.Dialogs
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug("Adjusting login settings...");
|
Debug("Adjusting login settings...");
|
||||||
Core.Settings.LoginToken = edToken.Text;
|
Core.Core.Settings.LoginToken = edToken.Text;
|
||||||
|
|
||||||
Core.Settings.Store();
|
Core.Core.Settings.Store();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnOk_Click(object sender, EventArgs e)
|
private void btnOk_Click(object sender, EventArgs e)
|
|
@ -1,4 +1,19 @@
|
||||||
namespace DML.Application
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited FrmInternalSplash.Designer.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace DML.Application
|
||||||
{
|
{
|
||||||
partial class FrmInternalSplash
|
partial class FrmInternalSplash
|
||||||
{
|
{
|
27
src/Discord Media Loader.Application/FrmInternalSplash.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited FrmInternalSplash.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace DML.Application
|
||||||
|
{
|
||||||
|
public partial class FrmInternalSplash : Form
|
||||||
|
{
|
||||||
|
public FrmInternalSplash()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited IdentifiedString.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DML.Application.Helper
|
||||||
|
{
|
||||||
|
internal class IdentifiedString<T>
|
||||||
|
{
|
||||||
|
internal T Id { get; set; }
|
||||||
|
internal string Caption { get; set; }
|
||||||
|
|
||||||
|
internal IdentifiedString(T id, string caption)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
Caption = caption;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() => Caption;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,19 @@
|
||||||
namespace DML.Application
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited MainForm.Designer.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace DML.Application
|
||||||
{
|
{
|
||||||
partial class MainForm
|
partial class MainForm
|
||||||
{
|
{
|
|
@ -1,4 +1,19 @@
|
||||||
using System;
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited MainForm.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -10,6 +25,7 @@ using Discord.WebSocket;
|
||||||
using DML.AppCore.Classes;
|
using DML.AppCore.Classes;
|
||||||
using DML.Application.Classes;
|
using DML.Application.Classes;
|
||||||
using DML.Application.Helper;
|
using DML.Application.Helper;
|
||||||
|
using DML.Application.Classes.RPC;
|
||||||
using DML.Client;
|
using DML.Client;
|
||||||
using static DML.Client.DMLClient;
|
using static DML.Client.DMLClient;
|
||||||
using static SweetLib.Utils.Logger.Logger;
|
using static SweetLib.Utils.Logger.Logger;
|
||||||
|
@ -26,6 +42,8 @@ namespace DML.Application
|
||||||
public partial class MainForm : Form
|
public partial class MainForm : Form
|
||||||
{
|
{
|
||||||
private bool IsInitialized { get; set; } = false;
|
private bool IsInitialized { get; set; } = false;
|
||||||
|
private DiscordRpc.RichPresence Presence { get; }
|
||||||
|
|
||||||
public MainForm()
|
public MainForm()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
@ -46,16 +64,16 @@ namespace DML.Application
|
||||||
lbVersion.Text = $"v{Assembly.GetExecutingAssembly().GetName().Version} Copyright © by Serraniel";
|
lbVersion.Text = $"v{Assembly.GetExecutingAssembly().GetName().Version} Copyright © by Serraniel";
|
||||||
|
|
||||||
Trace("Refreshing operating folder component...");
|
Trace("Refreshing operating folder component...");
|
||||||
edOperatingFolder.Text = Core.Settings.OperatingFolder;
|
edOperatingFolder.Text = Core.Core.Settings.OperatingFolder;
|
||||||
|
|
||||||
Trace("Refreshing name scheme component...");
|
Trace("Refreshing name scheme component...");
|
||||||
edNameScheme.Text = Core.Settings.FileNameScheme;
|
edNameScheme.Text = Core.Core.Settings.FileNameScheme;
|
||||||
|
|
||||||
Trace("Refreshing skip existing files component...");
|
Trace("Refreshing skip existing files component...");
|
||||||
cbSkipExisting.Checked = Core.Settings.SkipExistingFiles;
|
cbSkipExisting.Checked = Core.Core.Settings.SkipExistingFiles;
|
||||||
|
|
||||||
Trace("Refreshing thread limit component...");
|
Trace("Refreshing thread limit component...");
|
||||||
edThreadLimit.Value = Core.Settings.ThreadLimit;
|
edThreadLimit.Value = Core.Core.Settings.ThreadLimit;
|
||||||
|
|
||||||
if (cbGuild.Items.Count == 0)
|
if (cbGuild.Items.Count == 0)
|
||||||
{
|
{
|
||||||
|
@ -70,7 +88,7 @@ namespace DML.Application
|
||||||
Trace("Refreshing job list component...");
|
Trace("Refreshing job list component...");
|
||||||
var oldIndex = lbxJobs.SelectedIndex;
|
var oldIndex = lbxJobs.SelectedIndex;
|
||||||
lbxJobs.Items.Clear();
|
lbxJobs.Items.Clear();
|
||||||
foreach (var job in Core.Scheduler.JobList)
|
foreach (var job in Core.Core.Scheduler.JobList)
|
||||||
{
|
{
|
||||||
lbxJobs.Items.Add(new IdentifiedString<int>(job.Id, $"{FindServerById(job.GuildId)?.Name}:{FindChannelById(FindServerById(job.GuildId), job.ChannelId)?.Name}"));
|
lbxJobs.Items.Add(new IdentifiedString<int>(job.Id, $"{FindServerById(job.GuildId)?.Name}:{FindChannelById(FindServerById(job.GuildId), job.ChannelId)?.Name}"));
|
||||||
}
|
}
|
||||||
|
@ -89,19 +107,19 @@ namespace DML.Application
|
||||||
}
|
}
|
||||||
|
|
||||||
Trace("Updating operating folder...");
|
Trace("Updating operating folder...");
|
||||||
Core.Settings.OperatingFolder = edOperatingFolder.Text;
|
Core.Core.Settings.OperatingFolder = edOperatingFolder.Text;
|
||||||
|
|
||||||
Trace("Updating name scheme...");
|
Trace("Updating name scheme...");
|
||||||
Core.Settings.FileNameScheme = edNameScheme.Text;
|
Core.Core.Settings.FileNameScheme = edNameScheme.Text;
|
||||||
|
|
||||||
Trace("Updating skip existing files...");
|
Trace("Updating skip existing files...");
|
||||||
Core.Settings.SkipExistingFiles = cbSkipExisting.Checked;
|
Core.Core.Settings.SkipExistingFiles = cbSkipExisting.Checked;
|
||||||
|
|
||||||
Trace("Updating thread limit...");
|
Trace("Updating thread limit...");
|
||||||
Core.Settings.ThreadLimit = (int)edThreadLimit.Value;
|
Core.Core.Settings.ThreadLimit = (int)edThreadLimit.Value;
|
||||||
|
|
||||||
Trace("Storing new settings...");
|
Trace("Storing new settings...");
|
||||||
Core.Settings.Store();
|
Core.Core.Settings.Store();
|
||||||
|
|
||||||
Info("New settings have been saved.");
|
Info("New settings have been saved.");
|
||||||
}
|
}
|
||||||
|
@ -193,12 +211,12 @@ namespace DML.Application
|
||||||
ChannelId = ((IdentifiedString<ulong>)cbChannel.SelectedItem).Id
|
ChannelId = ((IdentifiedString<ulong>)cbChannel.SelectedItem).Id
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!(from j in Core.Scheduler.JobList
|
if (!(from j in Core.Core.Scheduler.JobList
|
||||||
where j.GuildId == job.GuildId && j.ChannelId == job.ChannelId
|
where j.GuildId == job.GuildId && j.ChannelId == job.ChannelId
|
||||||
select j).Any())
|
select j).Any())
|
||||||
{
|
{
|
||||||
job.Store();
|
job.Store();
|
||||||
Core.Scheduler.JobList.Add(job);
|
Core.Core.Scheduler.JobList.Add(job);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefreshComponents();
|
RefreshComponents();
|
||||||
|
@ -216,11 +234,11 @@ namespace DML.Application
|
||||||
|
|
||||||
var jobId = ((IdentifiedString<int>)lbxJobs.SelectedItem).Id;
|
var jobId = ((IdentifiedString<int>)lbxJobs.SelectedItem).Id;
|
||||||
|
|
||||||
var job = Core.Scheduler.JobList.FirstOrDefault(j => j.Id == jobId);
|
var job = Core.Core.Scheduler.JobList.FirstOrDefault(j => j.Id == jobId);
|
||||||
if (job != null)
|
if (job != null)
|
||||||
{
|
{
|
||||||
Core.Scheduler.JobList.Remove(job);
|
Core.Core.Scheduler.JobList.Remove(job);
|
||||||
Core.Scheduler.RunningJobs.Remove(job.Id);
|
Core.Core.Scheduler.RunningJobs.Remove(job.Id);
|
||||||
job.Stop();
|
job.Stop();
|
||||||
job.Delete();
|
job.Delete();
|
||||||
}
|
}
|
||||||
|
@ -231,9 +249,9 @@ namespace DML.Application
|
||||||
|
|
||||||
private void tmrRefreshProgress_Tick(object sender, System.EventArgs e)
|
private void tmrRefreshProgress_Tick(object sender, System.EventArgs e)
|
||||||
{
|
{
|
||||||
var scanned = Core.Scheduler.MessagesScanned;
|
var scanned = Core.Core.Scheduler.MessagesScanned;
|
||||||
var totalAttachments = Core.Scheduler.TotalAttachments;
|
var totalAttachments = Core.Core.Scheduler.TotalAttachments;
|
||||||
var done = Core.Scheduler.AttachmentsDownloaded;
|
var done = Core.Core.Scheduler.AttachmentsDownloaded;
|
||||||
|
|
||||||
var progress = totalAttachments > 0 ? (int)(100 * done / totalAttachments) : 0;
|
var progress = totalAttachments > 0 ? (int)(100 * done / totalAttachments) : 0;
|
||||||
progress = Math.Min(Math.Max(0, progress), 100);
|
progress = Math.Min(Math.Max(0, progress), 100);
|
||||||
|
@ -241,6 +259,18 @@ namespace DML.Application
|
||||||
pgbProgress.Value = progress;
|
pgbProgress.Value = progress;
|
||||||
|
|
||||||
lbProgress.Text = $"Scanned: {scanned} Downloaded: {done} Open: {totalAttachments - done}";
|
lbProgress.Text = $"Scanned: {scanned} Downloaded: {done} Open: {totalAttachments - done}";
|
||||||
|
|
||||||
|
if (Core.Core.Settings.UseRPC)
|
||||||
|
{
|
||||||
|
Core.Core.RpcPresence.details = "Downloading media files";
|
||||||
|
Core.Core.RpcPresence.state = $"{done} / {totalAttachments} ({pgbProgress.Value}%)";
|
||||||
|
Core.Core.RpcPresence.largeImageKey = "main";
|
||||||
|
Core.Core.RpcPresence.largeImageText = "Visit discordmedialoader.net";
|
||||||
|
Core.Core.RpcPresence.smallImageKey = "author";
|
||||||
|
Core.Core.RpcPresence.smallImageText = "Made by Serraniel";
|
||||||
|
|
||||||
|
Core.Core.RpcUpdatePresence();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void aboutToolStripMenuItem_Click(object sender, System.EventArgs e)
|
private void aboutToolStripMenuItem_Click(object sender, System.EventArgs e)
|
||||||
|
@ -285,7 +315,7 @@ namespace DML.Application
|
||||||
|
|
||||||
private void showTokenToolStripMenuItem_Click(object sender, EventArgs e)
|
private void showTokenToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Clipboard.SetText(Core.Settings.LoginToken);
|
Clipboard.SetText(Core.Core.Settings.LoginToken);
|
||||||
MessageBox.Show(this, "Your login token has been copied to your clipboard.", "Discord Media Loader",
|
MessageBox.Show(this, "Your login token has been copied to your clipboard.", "Discord Media Loader",
|
||||||
MessageBoxButtons.OK);
|
MessageBoxButtons.OK);
|
||||||
}
|
}
|
|
@ -1,5 +1,19 @@
|
||||||
using System.Reflection;
|
#region LICENSE
|
||||||
using System.Runtime.CompilerServices;
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "DML.Application".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited AssemblyInfo.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
|
@ -1,12 +1,17 @@
|
||||||
//------------------------------------------------------------------------------
|
#region LICENSE
|
||||||
// <auto-generated>
|
/**********************************************************************************************
|
||||||
// Dieser Code wurde von einem Tool generiert.
|
* Copyright (C) 2017-2019 - All Rights Reserved
|
||||||
// Laufzeitversion:4.0.30319.42000
|
*
|
||||||
//
|
* This file is part of "DML.Application".
|
||||||
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
// der Code erneut generiert wird.
|
*
|
||||||
// </auto-generated>
|
* "DML.Application" is licensed under Apache 2.0.
|
||||||
//------------------------------------------------------------------------------
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited Resources.Designer.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
namespace DML.Application.Properties {
|
namespace DML.Application.Properties {
|
||||||
using System;
|
using System;
|
Before Width: | Height: | Size: 300 KiB After Width: | Height: | Size: 300 KiB |
15
src/Discord Media Loader.sln.licenseheader
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
extensions: .cs .cpp .h
|
||||||
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2017-%CurrentYear% - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "%Project%".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/DiscordMediaLoader
|
||||||
|
*
|
||||||
|
* "%Project%" is licensed under Apache 2.0.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited %FileName% under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
|
@ -1,4 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Sample license text.
|
||||||
|
-->
|
||||||
<configuration>
|
<configuration>
|
||||||
<startup>
|
<startup>
|
||||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
|
|
@ -190,6 +190,9 @@
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<None Include="..\..\Darkorbit Helper Program\src\Darkorbit Helper Program\Darkorbit Helper Program.licenseheader">
|
||||||
|
<Link>Darkorbit Helper Program.licenseheader</Link>
|
||||||
|
</None>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
<None Include="Properties\Settings.settings">
|
<None Include="Properties\Settings.settings">
|
||||||
<Generator>SettingsSingleFileGenerator</Generator>
|
<Generator>SettingsSingleFileGenerator</Generator>
|
|
@ -1,4 +1,19 @@
|
||||||
namespace Discord_Media_Loader
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2019-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "Discord Media Loader".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/Darkorbit-Helper-Program
|
||||||
|
*
|
||||||
|
* "Discord Media Loader" is licensed under European Union Public Licence V. 1.2.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited FrmDownload.Designer.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace Discord_Media_Loader
|
||||||
{
|
{
|
||||||
partial class FrmDownload
|
partial class FrmDownload
|
||||||
{
|
{
|
|
@ -1,4 +1,19 @@
|
||||||
using System;
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2019-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "Discord Media Loader".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/Darkorbit-Helper-Program
|
||||||
|
*
|
||||||
|
* "Discord Media Loader" is licensed under European Union Public Licence V. 1.2.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited FrmDownload.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Net;
|
using System.Net;
|
|
@ -1,4 +1,19 @@
|
||||||
namespace Discord_Media_Loader
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2019-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "Discord Media Loader".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/Darkorbit-Helper-Program
|
||||||
|
*
|
||||||
|
* "Discord Media Loader" is licensed under European Union Public Licence V. 1.2.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited FrmSplash.Designer.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace Discord_Media_Loader
|
||||||
{
|
{
|
||||||
partial class FrmSplash
|
partial class FrmSplash
|
||||||
{
|
{
|
|
@ -1,4 +1,19 @@
|
||||||
using System;
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2019-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "Discord Media Loader".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/Darkorbit-Helper-Program
|
||||||
|
*
|
||||||
|
* "Discord Media Loader" is licensed under European Union Public Licence V. 1.2.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited FrmSplash.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
@ -15,6 +30,7 @@ namespace Discord_Media_Loader
|
||||||
|
|
||||||
private async void FrmSplash_Shown(object sender, EventArgs e)
|
private async void FrmSplash_Shown(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
#if !DEBUG
|
||||||
UseWaitCursor = true;
|
UseWaitCursor = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -52,6 +68,7 @@ namespace Discord_Media_Loader
|
||||||
{
|
{
|
||||||
UseWaitCursor = false;
|
UseWaitCursor = false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
DialogResult = DialogResult.OK;
|
DialogResult = DialogResult.OK;
|
||||||
}
|
}
|
|
@ -1,4 +1,19 @@
|
||||||
using System;
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2019-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "Discord Media Loader".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/Darkorbit-Helper-Program
|
||||||
|
*
|
||||||
|
* "Discord Media Loader" is licensed under European Union Public Licence V. 1.2.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited TaskBarProgress.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Discord_Media_Loader.Helper
|
namespace Discord_Media_Loader.Helper
|
|
@ -1,4 +1,19 @@
|
||||||
using System;
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2019-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "Discord Media Loader".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/Darkorbit-Helper-Program
|
||||||
|
*
|
||||||
|
* "Discord Media Loader" is licensed under European Union Public Licence V. 1.2.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited VersionHelper.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
47
src/Discord Media Loader/Program.cs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2019-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "Discord Media Loader".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/Darkorbit-Helper-Program
|
||||||
|
*
|
||||||
|
* "Discord Media Loader" is licensed under European Union Public Licence V. 1.2.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited Program.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using DML.Application.Core;
|
||||||
|
using Nito.AsyncEx;
|
||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Discord_Media_Loader
|
||||||
|
{
|
||||||
|
static class Program
|
||||||
|
{
|
||||||
|
[STAThread]
|
||||||
|
static void Main(string[] paramStrings)
|
||||||
|
{
|
||||||
|
Application.EnableVisualStyles();
|
||||||
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,19 @@
|
||||||
using System.Reflection;
|
#region LICENSE
|
||||||
using System.Runtime.CompilerServices;
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2019-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "Discord Media Loader".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/Darkorbit-Helper-Program
|
||||||
|
*
|
||||||
|
* "Discord Media Loader" is licensed under European Union Public Licence V. 1.2.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited AssemblyInfo.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
|
@ -1,12 +1,17 @@
|
||||||
//------------------------------------------------------------------------------
|
#region LICENSE
|
||||||
// <auto-generated>
|
/**********************************************************************************************
|
||||||
// Dieser Code wurde von einem Tool generiert.
|
* Copyright (C) 2019-2019 - All Rights Reserved
|
||||||
// Laufzeitversion:4.0.30319.42000
|
*
|
||||||
//
|
* This file is part of "Discord Media Loader".
|
||||||
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
|
* The official repository is hosted at https://github.com/Serraniel/Darkorbit-Helper-Program
|
||||||
// der Code erneut generiert wird.
|
*
|
||||||
// </auto-generated>
|
* "Discord Media Loader" is licensed under European Union Public Licence V. 1.2.
|
||||||
//------------------------------------------------------------------------------
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited Resources.Designer.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
namespace Discord_Media_Loader.Properties {
|
namespace Discord_Media_Loader.Properties {
|
||||||
using System;
|
using System;
|
31
src/Discord Media Loader/Properties/Settings.Designer.cs
generated
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#region LICENSE
|
||||||
|
/**********************************************************************************************
|
||||||
|
* Copyright (C) 2019-2019 - All Rights Reserved
|
||||||
|
*
|
||||||
|
* This file is part of "Discord Media Loader".
|
||||||
|
* The official repository is hosted at https://github.com/Serraniel/Darkorbit-Helper-Program
|
||||||
|
*
|
||||||
|
* "Discord Media Loader" is licensed under European Union Public Licence V. 1.2.
|
||||||
|
* Full license is included in the project repository.
|
||||||
|
*
|
||||||
|
* Users who edited Settings.Designer.cs under the condition of the used license:
|
||||||
|
* - Serraniel (https://github.com/Serraniel)
|
||||||
|
**********************************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace Discord_Media_Loader.Properties {
|
||||||
|
|
||||||
|
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
[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())));
|
||||||
|
|
||||||
|
public static Settings Default {
|
||||||
|
get {
|
||||||
|
return defaultInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Before Width: | Height: | Size: 300 KiB After Width: | Height: | Size: 300 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 412 KiB After Width: | Height: | Size: 412 KiB |
|
@ -1,4 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Sample license text.
|
||||||
|
-->
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Discord.Net" version="1.0.2" targetFramework="net461" />
|
<package id="Discord.Net" version="1.0.2" targetFramework="net461" />
|
||||||
<package id="Discord.Net.Commands" version="1.0.2" targetFramework="net461" />
|
<package id="Discord.Net.Commands" version="1.0.2" targetFramework="net461" />
|