mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2025-05-23 19:26:57 -04:00
Add some error handling
This commit is contained in:
parent
f2178a0445
commit
8afe9852fb
11 changed files with 165 additions and 34 deletions
|
@ -12,13 +12,14 @@ namespace DiscordChatExporter
|
||||||
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
|
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
|
||||||
|
|
||||||
// Services
|
// Services
|
||||||
SimpleIoc.Default.Register<IDataService, DataService>();
|
SimpleIoc.Default.Register<IDataService, DataService>(true);
|
||||||
SimpleIoc.Default.Register<IExportService, ExportService>();
|
SimpleIoc.Default.Register<IExportService, ExportService>(true);
|
||||||
SimpleIoc.Default.Register<ISettingsService, SettingsService>();
|
SimpleIoc.Default.Register<ISettingsService, SettingsService>(true);
|
||||||
|
|
||||||
// View models
|
// View models
|
||||||
SimpleIoc.Default.Register<IMainViewModel, MainViewModel>();
|
SimpleIoc.Default.Register<IErrorViewModel, ErrorViewModel>(true);
|
||||||
SimpleIoc.Default.Register<ISettingsViewModel, SettingsViewModel>();
|
SimpleIoc.Default.Register<IMainViewModel, MainViewModel>(true);
|
||||||
|
SimpleIoc.Default.Register<ISettingsViewModel, SettingsViewModel>(true);
|
||||||
|
|
||||||
// Load settings
|
// Load settings
|
||||||
ServiceLocator.Current.GetInstance<ISettingsService>().Load();
|
ServiceLocator.Current.GetInstance<ISettingsService>().Load();
|
||||||
|
@ -30,6 +31,7 @@ namespace DiscordChatExporter
|
||||||
ServiceLocator.Current.GetInstance<ISettingsService>().Save();
|
ServiceLocator.Current.GetInstance<ISettingsService>().Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IErrorViewModel ErrorViewModel => ServiceLocator.Current.GetInstance<IErrorViewModel>();
|
||||||
public IMainViewModel MainViewModel => ServiceLocator.Current.GetInstance<IMainViewModel>();
|
public IMainViewModel MainViewModel => ServiceLocator.Current.GetInstance<IMainViewModel>();
|
||||||
public ISettingsViewModel SettingsViewModel => ServiceLocator.Current.GetInstance<ISettingsViewModel>();
|
public ISettingsViewModel SettingsViewModel => ServiceLocator.Current.GetInstance<ISettingsViewModel>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,12 +84,19 @@
|
||||||
<Reference Include="PresentationFramework" />
|
<Reference Include="PresentationFramework" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Exceptions\UnathorizedException.cs" />
|
||||||
|
<Compile Include="Messages\ShowErrorMessage.cs" />
|
||||||
<Compile Include="Messages\ShowSettingsMessage.cs" />
|
<Compile Include="Messages\ShowSettingsMessage.cs" />
|
||||||
<Compile Include="Models\AttachmentType.cs" />
|
<Compile Include="Models\AttachmentType.cs" />
|
||||||
<Compile Include="Models\ChannelChatLog.cs" />
|
<Compile Include="Models\ChannelChatLog.cs" />
|
||||||
<Compile Include="Models\ChannelType.cs" />
|
<Compile Include="Models\ChannelType.cs" />
|
||||||
|
<Compile Include="ViewModels\ErrorViewModel.cs" />
|
||||||
|
<Compile Include="ViewModels\IErrorViewModel.cs" />
|
||||||
<Compile Include="ViewModels\ISettingsViewModel.cs" />
|
<Compile Include="ViewModels\ISettingsViewModel.cs" />
|
||||||
<Compile Include="ViewModels\SettingsViewModel.cs" />
|
<Compile Include="ViewModels\SettingsViewModel.cs" />
|
||||||
|
<Compile Include="Views\ErrorDialog.ammy.cs">
|
||||||
|
<DependentUpon>ErrorDialog.ammy</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Views\SettingsDialog.ammy.cs">
|
<Compile Include="Views\SettingsDialog.ammy.cs">
|
||||||
<DependentUpon>SettingsDialog.ammy</DependentUpon>
|
<DependentUpon>SettingsDialog.ammy</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -98,6 +105,11 @@
|
||||||
<Generator>XamlIntelliSenseFileGenerator</Generator>
|
<Generator>XamlIntelliSenseFileGenerator</Generator>
|
||||||
<DependentUpon>App.ammy</DependentUpon>
|
<DependentUpon>App.ammy</DependentUpon>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="Views\ErrorDialog.g.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<DependentUpon>ErrorDialog.ammy</DependentUpon>
|
||||||
|
</Page>
|
||||||
<Page Include="Views\MainWindow.g.xaml">
|
<Page Include="Views\MainWindow.g.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
@ -150,6 +162,7 @@
|
||||||
<None Include="packages.config">
|
<None Include="packages.config">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="Views\ErrorDialog.ammy" />
|
||||||
<None Include="Views\MainWindow.ammy" />
|
<None Include="Views\MainWindow.ammy" />
|
||||||
<None Include="Views\SettingsDialog.ammy" />
|
<None Include="Views\SettingsDialog.ammy" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
8
DiscordChatExporter/Exceptions/UnathorizedException.cs
Normal file
8
DiscordChatExporter/Exceptions/UnathorizedException.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Exceptions
|
||||||
|
{
|
||||||
|
public class UnathorizedException : Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
12
DiscordChatExporter/Messages/ShowErrorMessage.cs
Normal file
12
DiscordChatExporter/Messages/ShowErrorMessage.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace DiscordChatExporter.Messages
|
||||||
|
{
|
||||||
|
public class ShowErrorMessage
|
||||||
|
{
|
||||||
|
public string Message { get; }
|
||||||
|
|
||||||
|
public ShowErrorMessage(string message)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using DiscordChatExporter.Exceptions;
|
||||||
using DiscordChatExporter.Models;
|
using DiscordChatExporter.Models;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Tyrrrz.Extensions;
|
using Tyrrrz.Extensions;
|
||||||
|
@ -14,16 +16,30 @@ namespace DiscordChatExporter.Services
|
||||||
private const string ApiRoot = "https://discordapp.com/api/v6";
|
private const string ApiRoot = "https://discordapp.com/api/v6";
|
||||||
private readonly HttpClient _httpClient = new HttpClient();
|
private readonly HttpClient _httpClient = new HttpClient();
|
||||||
|
|
||||||
|
private async Task<string> GetStringAsync(string url)
|
||||||
|
{
|
||||||
|
using (var response = await _httpClient.GetAsync(url))
|
||||||
|
{
|
||||||
|
// Check status code
|
||||||
|
if (response.StatusCode.IsEither(HttpStatusCode.Unauthorized, HttpStatusCode.Forbidden))
|
||||||
|
throw new UnathorizedException();
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
// Get content
|
||||||
|
return await response.Content.ReadAsStringAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<Guild>> GetGuildsAsync(string token)
|
public async Task<IEnumerable<Guild>> GetGuildsAsync(string token)
|
||||||
{
|
{
|
||||||
// Form request url
|
// Form request url
|
||||||
var url = $"{ApiRoot}/users/@me/guilds?token={token}&limit=100";
|
var url = $"{ApiRoot}/users/@me/guilds?token={token}&limit=100";
|
||||||
|
|
||||||
// Get response
|
// Get response
|
||||||
var response = await _httpClient.GetStringAsync(url);
|
var content = await GetStringAsync(url);
|
||||||
|
|
||||||
// Parse
|
// Parse
|
||||||
var guilds = JArray.Parse(response).Select(ParseGuild);
|
var guilds = JArray.Parse(content).Select(ParseGuild);
|
||||||
|
|
||||||
return guilds;
|
return guilds;
|
||||||
}
|
}
|
||||||
|
@ -34,10 +50,10 @@ namespace DiscordChatExporter.Services
|
||||||
var url = $"{ApiRoot}/users/@me/channels?token={token}";
|
var url = $"{ApiRoot}/users/@me/channels?token={token}";
|
||||||
|
|
||||||
// Get response
|
// Get response
|
||||||
var response = await _httpClient.GetStringAsync(url);
|
var content = await GetStringAsync(url);
|
||||||
|
|
||||||
// Parse
|
// Parse
|
||||||
var channels = JArray.Parse(response).Select(ParseChannel);
|
var channels = JArray.Parse(content).Select(ParseChannel);
|
||||||
|
|
||||||
return channels;
|
return channels;
|
||||||
}
|
}
|
||||||
|
@ -48,10 +64,10 @@ namespace DiscordChatExporter.Services
|
||||||
var url = $"{ApiRoot}/guilds/{guildId}/channels?token={token}";
|
var url = $"{ApiRoot}/guilds/{guildId}/channels?token={token}";
|
||||||
|
|
||||||
// Get response
|
// Get response
|
||||||
var response = await _httpClient.GetStringAsync(url);
|
var content = await GetStringAsync(url);
|
||||||
|
|
||||||
// Parse
|
// Parse
|
||||||
var channels = JArray.Parse(response).Select(ParseChannel);
|
var channels = JArray.Parse(content).Select(ParseChannel);
|
||||||
|
|
||||||
return channels;
|
return channels;
|
||||||
}
|
}
|
||||||
|
@ -71,10 +87,10 @@ namespace DiscordChatExporter.Services
|
||||||
url += $"&before={beforeId}";
|
url += $"&before={beforeId}";
|
||||||
|
|
||||||
// Get response
|
// Get response
|
||||||
var response = await _httpClient.GetStringAsync(url);
|
var content = await GetStringAsync(url);
|
||||||
|
|
||||||
// Parse
|
// Parse
|
||||||
var messages = JArray.Parse(response).Select(ParseMessage);
|
var messages = JArray.Parse(content).Select(ParseMessage);
|
||||||
|
|
||||||
// Add messages to list
|
// Add messages to list
|
||||||
string currentMessageId = null;
|
string currentMessageId = null;
|
||||||
|
|
15
DiscordChatExporter/ViewModels/ErrorViewModel.cs
Normal file
15
DiscordChatExporter/ViewModels/ErrorViewModel.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using DiscordChatExporter.Messages;
|
||||||
|
using GalaSoft.MvvmLight;
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.ViewModels
|
||||||
|
{
|
||||||
|
public class ErrorViewModel : ViewModelBase, IErrorViewModel
|
||||||
|
{
|
||||||
|
public string Message { get; private set; }
|
||||||
|
|
||||||
|
public ErrorViewModel()
|
||||||
|
{
|
||||||
|
MessengerInstance.Register<ShowErrorMessage>(this, m => Message = m.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
DiscordChatExporter/ViewModels/IErrorViewModel.cs
Normal file
7
DiscordChatExporter/ViewModels/IErrorViewModel.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace DiscordChatExporter.ViewModels
|
||||||
|
{
|
||||||
|
public interface IErrorViewModel
|
||||||
|
{
|
||||||
|
string Message { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using DiscordChatExporter.Exceptions;
|
||||||
using DiscordChatExporter.Messages;
|
using DiscordChatExporter.Messages;
|
||||||
using DiscordChatExporter.Models;
|
using DiscordChatExporter.Models;
|
||||||
using DiscordChatExporter.Services;
|
using DiscordChatExporter.Services;
|
||||||
|
@ -107,6 +108,8 @@ namespace DiscordChatExporter.ViewModels
|
||||||
// Clear existing
|
// Clear existing
|
||||||
_guildChannelsMap.Clear();
|
_guildChannelsMap.Clear();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
// Get DM channels
|
// Get DM channels
|
||||||
{
|
{
|
||||||
var channels = await _dataService.GetDirectMessageChannelsAsync(_cachedToken);
|
var channels = await _dataService.GetDirectMessageChannelsAsync(_cachedToken);
|
||||||
|
@ -124,6 +127,11 @@ namespace DiscordChatExporter.ViewModels
|
||||||
_guildChannelsMap[guild] = channels.ToArray();
|
_guildChannelsMap[guild] = channels.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch (UnathorizedException)
|
||||||
|
{
|
||||||
|
MessengerInstance.Send(new ShowErrorMessage("Failed to authorize. Make sure the token is valid."));
|
||||||
|
}
|
||||||
|
|
||||||
AvailableGuilds = _guildChannelsMap.Keys.ToArray();
|
AvailableGuilds = _guildChannelsMap.Keys.ToArray();
|
||||||
SelectedGuild = AvailableGuilds.FirstOrDefault();
|
SelectedGuild = AvailableGuilds.FirstOrDefault();
|
||||||
|
@ -135,13 +143,13 @@ namespace DiscordChatExporter.ViewModels
|
||||||
IsBusy = true;
|
IsBusy = true;
|
||||||
|
|
||||||
// Get safe file names
|
// Get safe file names
|
||||||
var safeGroupName = SelectedGuild.Name.Replace(Path.GetInvalidFileNameChars(), '_');
|
var safeGuildName = SelectedGuild.Name.Replace(Path.GetInvalidFileNameChars(), '_');
|
||||||
var safeChannelName = channel.Name.Replace(Path.GetInvalidFileNameChars(), '_');
|
var safeChannelName = channel.Name.Replace(Path.GetInvalidFileNameChars(), '_');
|
||||||
|
|
||||||
// Ask for path
|
// Ask for path
|
||||||
var sfd = new SaveFileDialog
|
var sfd = new SaveFileDialog
|
||||||
{
|
{
|
||||||
FileName = $"{safeGroupName} - {safeChannelName}.html",
|
FileName = $"{safeGuildName} - {safeChannelName}.html",
|
||||||
Filter = "HTML files (*.html)|*.html|All files (*.*)|*.*",
|
Filter = "HTML files (*.html)|*.html|All files (*.*)|*.*",
|
||||||
DefaultExt = "html",
|
DefaultExt = "html",
|
||||||
AddExtension = true
|
AddExtension = true
|
||||||
|
@ -152,6 +160,9 @@ namespace DiscordChatExporter.ViewModels
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Export
|
||||||
|
try
|
||||||
|
{
|
||||||
// Get messages
|
// Get messages
|
||||||
var messages = await _dataService.GetChannelMessagesAsync(_cachedToken, channel.Id);
|
var messages = await _dataService.GetChannelMessagesAsync(_cachedToken, channel.Id);
|
||||||
|
|
||||||
|
@ -160,6 +171,11 @@ namespace DiscordChatExporter.ViewModels
|
||||||
|
|
||||||
// Export
|
// Export
|
||||||
_exportService.Export(sfd.FileName, chatLog, _settingsService.Theme);
|
_exportService.Export(sfd.FileName, chatLog, _settingsService.Theme);
|
||||||
|
}
|
||||||
|
catch (UnathorizedException)
|
||||||
|
{
|
||||||
|
MessengerInstance.Send(new ShowErrorMessage("Failed to export. You don't have access to that channel."));
|
||||||
|
}
|
||||||
|
|
||||||
IsBusy = false;
|
IsBusy = false;
|
||||||
}
|
}
|
||||||
|
|
25
DiscordChatExporter/Views/ErrorDialog.ammy
Normal file
25
DiscordChatExporter/Views/ErrorDialog.ammy
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
using MaterialDesignThemes.Wpf
|
||||||
|
|
||||||
|
UserControl "DiscordChatExporter.Views.ErrorDialog" {
|
||||||
|
DataContext: bind ErrorViewModel from $resource Container
|
||||||
|
Width: 250
|
||||||
|
|
||||||
|
StackPanel {
|
||||||
|
// Message
|
||||||
|
TextBlock {
|
||||||
|
Margin: 8
|
||||||
|
FontSize: 16
|
||||||
|
HorizontalAlignment: Center
|
||||||
|
TextWrapping: WrapWithOverflow
|
||||||
|
Text: bind Message
|
||||||
|
}
|
||||||
|
|
||||||
|
// OK
|
||||||
|
Button {
|
||||||
|
Command: DialogHost.CloseDialogCommand
|
||||||
|
Content: "OK"
|
||||||
|
Margin: 8
|
||||||
|
Style: resource dyn "MaterialDesignFlatButton"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
DiscordChatExporter/Views/ErrorDialog.ammy.cs
Normal file
16
DiscordChatExporter/Views/ErrorDialog.ammy.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Views
|
||||||
|
{
|
||||||
|
public partial class ErrorDialog
|
||||||
|
{
|
||||||
|
public ErrorDialog()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ namespace DiscordChatExporter.Views
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Title += $" v{Assembly.GetExecutingAssembly().GetName().Version}";
|
Title += $" v{Assembly.GetExecutingAssembly().GetName().Version}";
|
||||||
|
|
||||||
|
Messenger.Default.Register<ShowErrorMessage>(this, m => DialogHost.Show(new ErrorDialog()).Forget());
|
||||||
Messenger.Default.Register<ShowSettingsMessage>(this, m => DialogHost.Show(new SettingsDialog()).Forget());
|
Messenger.Default.Register<ShowSettingsMessage>(this, m => DialogHost.Show(new SettingsDialog()).Forget());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue