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);
|
||||
|
||||
// Services
|
||||
SimpleIoc.Default.Register<IDataService, DataService>();
|
||||
SimpleIoc.Default.Register<IExportService, ExportService>();
|
||||
SimpleIoc.Default.Register<ISettingsService, SettingsService>();
|
||||
SimpleIoc.Default.Register<IDataService, DataService>(true);
|
||||
SimpleIoc.Default.Register<IExportService, ExportService>(true);
|
||||
SimpleIoc.Default.Register<ISettingsService, SettingsService>(true);
|
||||
|
||||
// View models
|
||||
SimpleIoc.Default.Register<IMainViewModel, MainViewModel>();
|
||||
SimpleIoc.Default.Register<ISettingsViewModel, SettingsViewModel>();
|
||||
SimpleIoc.Default.Register<IErrorViewModel, ErrorViewModel>(true);
|
||||
SimpleIoc.Default.Register<IMainViewModel, MainViewModel>(true);
|
||||
SimpleIoc.Default.Register<ISettingsViewModel, SettingsViewModel>(true);
|
||||
|
||||
// Load settings
|
||||
ServiceLocator.Current.GetInstance<ISettingsService>().Load();
|
||||
|
@ -30,6 +31,7 @@ namespace DiscordChatExporter
|
|||
ServiceLocator.Current.GetInstance<ISettingsService>().Save();
|
||||
}
|
||||
|
||||
public IErrorViewModel ErrorViewModel => ServiceLocator.Current.GetInstance<IErrorViewModel>();
|
||||
public IMainViewModel MainViewModel => ServiceLocator.Current.GetInstance<IMainViewModel>();
|
||||
public ISettingsViewModel SettingsViewModel => ServiceLocator.Current.GetInstance<ISettingsViewModel>();
|
||||
}
|
||||
|
|
|
@ -84,12 +84,19 @@
|
|||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Exceptions\UnathorizedException.cs" />
|
||||
<Compile Include="Messages\ShowErrorMessage.cs" />
|
||||
<Compile Include="Messages\ShowSettingsMessage.cs" />
|
||||
<Compile Include="Models\AttachmentType.cs" />
|
||||
<Compile Include="Models\ChannelChatLog.cs" />
|
||||
<Compile Include="Models\ChannelType.cs" />
|
||||
<Compile Include="ViewModels\ErrorViewModel.cs" />
|
||||
<Compile Include="ViewModels\IErrorViewModel.cs" />
|
||||
<Compile Include="ViewModels\ISettingsViewModel.cs" />
|
||||
<Compile Include="ViewModels\SettingsViewModel.cs" />
|
||||
<Compile Include="Views\ErrorDialog.ammy.cs">
|
||||
<DependentUpon>ErrorDialog.ammy</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsDialog.ammy.cs">
|
||||
<DependentUpon>SettingsDialog.ammy</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -98,6 +105,11 @@
|
|||
<Generator>XamlIntelliSenseFileGenerator</Generator>
|
||||
<DependentUpon>App.ammy</DependentUpon>
|
||||
</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">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
@ -150,6 +162,7 @@
|
|||
<None Include="packages.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="Views\ErrorDialog.ammy" />
|
||||
<None Include="Views\MainWindow.ammy" />
|
||||
<None Include="Views\SettingsDialog.ammy" />
|
||||
</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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using DiscordChatExporter.Exceptions;
|
||||
using DiscordChatExporter.Models;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Tyrrrz.Extensions;
|
||||
|
@ -14,16 +16,30 @@ namespace DiscordChatExporter.Services
|
|||
private const string ApiRoot = "https://discordapp.com/api/v6";
|
||||
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)
|
||||
{
|
||||
// Form request url
|
||||
var url = $"{ApiRoot}/users/@me/guilds?token={token}&limit=100";
|
||||
|
||||
// Get response
|
||||
var response = await _httpClient.GetStringAsync(url);
|
||||
var content = await GetStringAsync(url);
|
||||
|
||||
// Parse
|
||||
var guilds = JArray.Parse(response).Select(ParseGuild);
|
||||
var guilds = JArray.Parse(content).Select(ParseGuild);
|
||||
|
||||
return guilds;
|
||||
}
|
||||
|
@ -34,10 +50,10 @@ namespace DiscordChatExporter.Services
|
|||
var url = $"{ApiRoot}/users/@me/channels?token={token}";
|
||||
|
||||
// Get response
|
||||
var response = await _httpClient.GetStringAsync(url);
|
||||
var content = await GetStringAsync(url);
|
||||
|
||||
// Parse
|
||||
var channels = JArray.Parse(response).Select(ParseChannel);
|
||||
var channels = JArray.Parse(content).Select(ParseChannel);
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
@ -48,10 +64,10 @@ namespace DiscordChatExporter.Services
|
|||
var url = $"{ApiRoot}/guilds/{guildId}/channels?token={token}";
|
||||
|
||||
// Get response
|
||||
var response = await _httpClient.GetStringAsync(url);
|
||||
var content = await GetStringAsync(url);
|
||||
|
||||
// Parse
|
||||
var channels = JArray.Parse(response).Select(ParseChannel);
|
||||
var channels = JArray.Parse(content).Select(ParseChannel);
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
@ -71,10 +87,10 @@ namespace DiscordChatExporter.Services
|
|||
url += $"&before={beforeId}";
|
||||
|
||||
// Get response
|
||||
var response = await _httpClient.GetStringAsync(url);
|
||||
var content = await GetStringAsync(url);
|
||||
|
||||
// Parse
|
||||
var messages = JArray.Parse(response).Select(ParseMessage);
|
||||
var messages = JArray.Parse(content).Select(ParseMessage);
|
||||
|
||||
// Add messages to list
|
||||
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.IO;
|
||||
using System.Linq;
|
||||
using DiscordChatExporter.Exceptions;
|
||||
using DiscordChatExporter.Messages;
|
||||
using DiscordChatExporter.Models;
|
||||
using DiscordChatExporter.Services;
|
||||
|
@ -107,6 +108,8 @@ namespace DiscordChatExporter.ViewModels
|
|||
// Clear existing
|
||||
_guildChannelsMap.Clear();
|
||||
|
||||
try
|
||||
{
|
||||
// Get DM channels
|
||||
{
|
||||
var channels = await _dataService.GetDirectMessageChannelsAsync(_cachedToken);
|
||||
|
@ -124,6 +127,11 @@ namespace DiscordChatExporter.ViewModels
|
|||
_guildChannelsMap[guild] = channels.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (UnathorizedException)
|
||||
{
|
||||
MessengerInstance.Send(new ShowErrorMessage("Failed to authorize. Make sure the token is valid."));
|
||||
}
|
||||
|
||||
AvailableGuilds = _guildChannelsMap.Keys.ToArray();
|
||||
SelectedGuild = AvailableGuilds.FirstOrDefault();
|
||||
|
@ -135,13 +143,13 @@ namespace DiscordChatExporter.ViewModels
|
|||
IsBusy = true;
|
||||
|
||||
// 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(), '_');
|
||||
|
||||
// Ask for path
|
||||
var sfd = new SaveFileDialog
|
||||
{
|
||||
FileName = $"{safeGroupName} - {safeChannelName}.html",
|
||||
FileName = $"{safeGuildName} - {safeChannelName}.html",
|
||||
Filter = "HTML files (*.html)|*.html|All files (*.*)|*.*",
|
||||
DefaultExt = "html",
|
||||
AddExtension = true
|
||||
|
@ -152,6 +160,9 @@ namespace DiscordChatExporter.ViewModels
|
|||
return;
|
||||
}
|
||||
|
||||
// Export
|
||||
try
|
||||
{
|
||||
// Get messages
|
||||
var messages = await _dataService.GetChannelMessagesAsync(_cachedToken, channel.Id);
|
||||
|
||||
|
@ -160,6 +171,11 @@ namespace DiscordChatExporter.ViewModels
|
|||
|
||||
// Export
|
||||
_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;
|
||||
}
|
||||
|
|
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();
|
||||
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());
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue