Last active
July 20, 2019 23:24
-
-
Save nathan130200/a2e791cc28dfb10cd9e15d3f30fe6b80 to your computer and use it in GitHub Desktop.
C# Discord application assets downloader using D#+. (produces a ZIP file with all assets files)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public delegate Task ApplicationAssetsDownloaderEventHandler(DiscordApplicationAsset asset); | |
class ApplicationAssetsDownloader : IDisposable | |
{ | |
private ConcurrentQueue<DiscordApplicationAsset> _a; | |
private ZipArchive _ar; | |
private MemoryStream _ms; | |
public event ApplicationAssetsDownloaderEventHandler DownloadStartedAsync; | |
public event ApplicationAssetsDownloaderEventHandler DownloadCompletedAsync; | |
public event ApplicationAssetsDownloaderEventHandler DownloadFailedAsync; | |
public ApplicationAssetsDownloader(IReadOnlyList<DiscordApplicationAsset> assets) | |
{ | |
_a = new ConcurrentQueue<DiscordApplicationAsset>(assets); | |
_ms = new MemoryStream(); | |
_ar = new ZipArchive(_ms, ZipArchiveMode.Create); | |
} | |
public async Task<MemoryStream> DownloadAsync() | |
{ | |
while (!_a.IsEmpty) | |
{ | |
if (_a.TryDequeue(out var aps)) | |
{ | |
try { await DownloadStartedAsync?.Invoke(aps); } | |
catch { /* ignored */ } | |
using (var client = new HttpClient()) | |
{ | |
try | |
{ | |
var res = await client.GetAsync(aps.Url); | |
if (res.IsSuccessStatusCode) | |
{ | |
var entry = _ar.CreateEntry(aps.Application.Id + "/" + aps.Name + ".png"); | |
using (var es = entry.Open()) // es = Entry Strema | |
using (var cs = await res.Content.ReadAsStreamAsync()) // cs = Content Stream | |
cs.CopyTo(es); | |
_ms.Flush(); | |
try { await DownloadCompletedAsync?.Invoke(aps); } | |
catch { /* ignored */ } | |
} | |
} | |
catch | |
{ | |
try { await DownloadFailedAsync?.Invoke(aps); } | |
catch { /* ignored */ } | |
} | |
} | |
} | |
} | |
_ms.Flush(); | |
_ms.Position = 0; | |
return _ms; | |
} | |
void IDisposable.Dispose() | |
{ | |
_a.Clear(); | |
_a = null; | |
_ms = null; | |
_ar = null; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class DiscordMessageQueue : IDisposable | |
{ | |
private DiscordChannel _channel; | |
private ConcurrentBag<DiscordMessage> _messages; | |
public DiscordMessageQueue(DiscordChannel channel) | |
{ | |
_channel = channel; | |
_messages = new ConcurrentBag<DiscordMessage>(); | |
} | |
public async Task<DiscordMessage> C(string content = null, bool tts = false, DiscordEmbedBuilder embed = null) | |
{ | |
var msg = await _channel.SendMessageAsync(content, tts, embed); | |
_messages.Add(msg); | |
return msg; | |
} | |
public async Task CleanupAsync() | |
{ | |
await _channel.DeleteMessagesAsync(_messages); | |
} | |
void IDisposable.Dispose() | |
{ | |
_messages = null; | |
_channel = null; | |
} | |
public static DiscordMessageQueue operator *(DiscordMessageQueue mq, DiscordMessage m) | |
{ | |
mq._messages.Add(m); | |
return mq; | |
} | |
public static DiscordMessageQueue operator *(DiscordMessageQueue mq, string content) | |
{ | |
return Task.Run(async () => await mq.C(content)) | |
.ContinueWith(t => mq) | |
.GetAwaiter() | |
.GetResult(); | |
} | |
public static DiscordMessageQueue operator *(DiscordMessageQueue mq, (string content, DiscordEmbedBuilder embed) vt) | |
{ | |
return Task.Run(async () => await mq.C(content: vt.content, embed: vt.embed)) | |
.ContinueWith(t => mq) | |
.GetAwaiter() | |
.GetResult(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Concurrent; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.IO.Compression; | |
using System.Linq; | |
using System.Net.Http; | |
using System.Reflection; | |
using System.Text; | |
using System.Threading.Tasks; | |
using DSharpPlus; | |
using DSharpPlus.CommandsNext; | |
using DSharpPlus.CommandsNext.Attributes; | |
using DSharpPlus.Entities; | |
using DSharpPlus.Interactivity; | |
namespace CSharp.Modules | |
{ | |
[Group] | |
public class DiscordModule : BaseCommandModule | |
{ | |
[Command] | |
public async Task Assets(CommandContext ctx) | |
{ | |
var assets = await ctx.Client.CurrentApplication.GetAssetsAsync(); | |
var (a, b, c) = ( | |
DiscordEmoji.FromGuildEmote(ctx.Client, 594249301295890463), | |
DiscordEmoji.FromGuildEmote(ctx.Client, 452529445899730945), | |
DiscordEmoji.FromGuildEmote(ctx.Client, 452529446214172692) | |
); | |
var mq = new DiscordMessageQueue(ctx.Channel); | |
var state = null as DiscordMessage; | |
var stream = null as MemoryStream; | |
var downloader = new ApplicationAssetsDownloader(assets); | |
var error = false; | |
downloader.DownloadStartedAsync += async e => | |
{ | |
mq *= state = await ctx.RespondAsync($"{ctx.User.Mention} {a} Asset **{e.Name}** (`{e.Id}`)..."); | |
}; | |
downloader.DownloadFailedAsync += async e => | |
{ | |
if (!error) error = true; | |
await state?.ModifyAsync($"{ctx.User.Mention} {c} Asset **{e.Name}** (`{e.Id}`) failed to download."); | |
}; | |
downloader.DownloadCompletedAsync += async e => | |
{ | |
await state?.ModifyAsync($"{ctx.User.Mention} {b} Asset **{e.Name}** (`{e.Id}`) saved to archive."); | |
}; | |
stream = await downloader.DownloadAsync(); | |
using (downloader) | |
using (stream) | |
{ | |
mq *= await ctx.RespondAsync($"{ctx.User.Mention} <:issueclosed:527890674822021137> Assets loaded" + (error ? " with errors." : ".")); | |
var w = await ctx.RespondAsync($"{ctx.User.Mention} <:issue:527890675182731274> Uploading archive."); | |
await ctx.RespondWithFileAsync("assets.zip´", stream, ctx.User.Mention); | |
} | |
await mq.CleanupAsync(); | |
mq = null; | |
stream = null; | |
downloader = null; | |
assets = null; | |
state = null; | |
error = default; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Command] | |
public async Task Assets(CommandContext ctx) | |
{ | |
var assets = await ctx.Client.CurrentApplication.GetAssetsAsync(); | |
var downloader = new ApplicationAssetsDownloader(assets); | |
var result = await downloader.DownloadAsync(); | |
// downloader.DownloadStartedAsync: notify when asset download started. | |
// downloader.DownloadFailedAsync: notify when asset download failed. | |
// downloader.DownloadCompletedAsync: notify when asset download finished. | |
using (result) | |
using (downloader) | |
await ctx.RespondWithFileAsync("assets.zip", result, ctx.User.Mention); // send file to discord as assets.zip | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment