Skip to content

Commit

Permalink
Update solution to .NET 8
Browse files Browse the repository at this point in the history
  • Loading branch information
d4n3436 committed Jan 12, 2024
1 parent 1306a7b commit 832f84b
Show file tree
Hide file tree
Showing 37 changed files with 146 additions and 317 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
dotnet-version: 6.0.x
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Have any questions or need help with the bot? Join the [support server](https://

### 0. Prerequisites
* A Discord bot application (You can create one [here](https://discord.com/developers/applications)).
* [.NET 6 SDK](https://dotnet.microsoft.com/download)
* [.NET 8 SDK](https://dotnet.microsoft.com/download)

### 1. Build and run the bot
* Clone the repository:
Expand All @@ -45,7 +45,7 @@ Have any questions or need help with the bot? Join the [support server](https://

* Go to the build output folder:
```
cd src/bin/Release/net6.0
cd src/bin/Release/net8.0
```

* Open `appsettings.json` with a text editor and set the application token:
Expand Down
10 changes: 1 addition & 9 deletions src/Apis/Bing/BingVisualSearch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public async Task<IEnumerable<IBingReverseImageSearchResult>> ReverseImageSearch
BingSafeSearchLevel safeSearch = BingSafeSearchLevel.Moderate, string? language = null,
CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

using var request = BuildRequest(url, "SimilarImages", safeSearch, language);
Expand Down Expand Up @@ -129,12 +129,4 @@ private static HttpRequestMessage BuildRequest(string url, string invokedSkill,

return request;
}

private void EnsureNotDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(BingVisualSearch));
}
}
}
2 changes: 1 addition & 1 deletion src/Apis/Dictionary/ArrayOrStringConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public override IReadOnlyList<string> Read(ref Utf8JsonReader reader, Type typeT
return reader.TokenType switch
{
JsonTokenType.StartArray => JsonSerializer.Deserialize<IReadOnlyList<string>>(ref reader)!,
JsonTokenType.String => reader.ValueTextEquals(ReadOnlySpan<byte>.Empty) ? Array.Empty<string>() : new[] { reader.GetString()! },
JsonTokenType.String => reader.ValueTextEquals(ReadOnlySpan<byte>.Empty) ? [] : [reader.GetString()!],
JsonTokenType.Null => Array.Empty<string>(),
_ => throw new JsonException("Token type must be either array, string or null.")
};
Expand Down
16 changes: 6 additions & 10 deletions src/Apis/Dictionary/DictionaryClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,19 @@ public DictionaryClient(HttpClient httpClient)
/// <inheritdoc/>
public async Task<IReadOnlyList<IDictionaryWord>> GetSearchResultsAsync(string text, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

var response = (await _httpClient.GetFromJsonAsync<DictionarySearchResponse>(new Uri($"https://thor-graphql.dictionary.com/v2/search?searchText={Uri.EscapeDataString(text)}"), cancellationToken).ConfigureAwait(false))!;
return response.Data;
}

/// <inheritdoc/>
public async Task<IDictionaryResponse> GetDefinitionsAsync(string word, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

return (await _httpClient.GetFromJsonAsync<DictionaryResponse>(new Uri($"https://api-portal.dictionary.com/dcom/pageData/{Uri.EscapeDataString(word)}"), cancellationToken).ConfigureAwait(false))!;
}

Expand All @@ -50,12 +54,4 @@ public void Dispose()
_httpClient.Dispose();
_disposed = true;
}

private void EnsureNotDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(DictionaryClient));
}
}
}
13 changes: 3 additions & 10 deletions src/Apis/Genius/GeniusClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ public GeniusClient(HttpClient httpClient)
/// <inheritdoc/>
public async Task<IReadOnlyList<IGeniusSong>> SearchSongsAsync(string query, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ArgumentException.ThrowIfNullOrEmpty(query);
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

var model = await _httpClient.GetFromJsonAsync<GeniusResponse<GeniusSearchResponse>>(new Uri($"search?q={Uri.EscapeDataString(query)}", UriKind.Relative), cancellationToken).ConfigureAwait(false);
Expand All @@ -67,7 +68,7 @@ public async Task<IReadOnlyList<IGeniusSong>> SearchSongsAsync(string query, Can
/// <inheritdoc/>
public async Task<IGeniusSong?> GetSongAsync(int id, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

using var response = await _httpClient.GetAsync(new Uri($"songs/{id}", UriKind.Relative), HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
Expand All @@ -92,12 +93,4 @@ public void Dispose()
_httpClient.Dispose();
_disposed = true;
}

private void EnsureNotDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(GeniusClient));
}
}
}
21 changes: 7 additions & 14 deletions src/Apis/Google/GoogleLensClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -19,9 +18,9 @@ public sealed class GoogleLensClient : IGoogleLensClient, IDisposable
private readonly HttpClient _httpClient;
private bool _disposed;

private static ReadOnlySpan<byte> ResultsCallbackStart => Encoding.UTF8.GetBytes("AF_initDataCallback({key: 'ds:0'");
private static ReadOnlySpan<byte> OcrCallbackStart => Encoding.UTF8.GetBytes("AF_initDataCallback({key: 'ds:1'");
private static ReadOnlySpan<byte> CallbackEnd => Encoding.UTF8.GetBytes(", sideChannel: {}});</script>");
private static ReadOnlySpan<byte> ResultsCallbackStart => "AF_initDataCallback({key: 'ds:0'"u8;
private static ReadOnlySpan<byte> OcrCallbackStart => "AF_initDataCallback({key: 'ds:1'"u8;
private static ReadOnlySpan<byte> CallbackEnd => ", sideChannel: {}});</script>"u8;

/// <summary>
/// Initializes a new instance of the <see cref="GoogleLensClient"/> class.
Expand All @@ -47,7 +46,8 @@ public GoogleLensClient(HttpClient httpClient)
/// <inheritdoc/>
public async Task<string> OcrAsync(string url, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ArgumentNullException.ThrowIfNull(url);
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

byte[] page = await _httpClient.GetByteArrayAsync(new Uri($"https://lens.google.com/uploadbyurl?url={Uri.EscapeDataString(url)}"), cancellationToken);
Expand All @@ -64,7 +64,8 @@ public async Task<string> OcrAsync(string url, CancellationToken cancellationTok
/// <inheritdoc/>
public async Task<IReadOnlyList<IGoogleLensResult>> ReverseImageSearchAsync(string url, string? language = null, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ArgumentNullException.ThrowIfNull(url);
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

string requestUrl = $"https://lens.google.com/uploadbyurl?url={Uri.EscapeDataString(url)}";
Expand Down Expand Up @@ -149,12 +150,4 @@ public void Dispose()
_httpClient.Dispose();
_disposed = true;
}

private void EnsureNotDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(GoogleLensClient));
}
}
}
13 changes: 3 additions & 10 deletions src/Apis/Musixmatch/MusixmatchClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ public MusixmatchClient(HttpClient httpClient, MusixmatchClientState state, ILog
/// <inheritdoc/>
public async Task<IReadOnlyList<IMusixmatchSong>> SearchSongsAsync(string query, bool onlyWithLyrics = true, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ArgumentException.ThrowIfNullOrEmpty(query);
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

string url = $"https://apic-desktop.musixmatch.com/ws/1.1/track.search?q_track_artist={Uri.EscapeDataString(query)}&s_track_rating=desc&format=json&app_id={AppId}&f_has_lyrics={(onlyWithLyrics ? 1 : 0)}&f_is_instrumental={(onlyWithLyrics ? 0 : 1)}";
Expand All @@ -74,7 +75,7 @@ public async Task<IReadOnlyList<IMusixmatchSong>> SearchSongsAsync(string query,
/// <inheritdoc/>
public async Task<IMusixmatchSong?> GetSongAsync(int id, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

string url = $"https://apic-desktop.musixmatch.com/ws/1.1/macro.community.lyrics.get?track_id={id}&version=2&format=json&app_id={AppId}";
Expand Down Expand Up @@ -212,12 +213,4 @@ private async Task<JsonDocument> SendRequestAndValidateAsync(string url, Cancell

return document;
}

private void EnsureNotDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(MusixmatchClient));
}
}
}
10 changes: 1 addition & 9 deletions src/Apis/Musixmatch/MusixmatchClientState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public MusixmatchClientState(IHttpClientFactory httpClientFactory)
/// <exception cref="MusixmatchException">The API response is not successful.</exception>
public async ValueTask<string> GetUserTokenAsync(bool refresh = false)
{
EnsureNotDisposed();
ObjectDisposedException.ThrowIf(_disposed, this);

if (!refresh && _userToken is not null)
{
Expand Down Expand Up @@ -109,12 +109,4 @@ private async Task<string> FetchUserTokenAsync()

return token;
}

private void EnsureNotDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(MusixmatchClientState));
}
}
}
24 changes: 8 additions & 16 deletions src/Apis/Urban/UrbanDictionary.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -46,7 +47,7 @@ public UrbanDictionary(HttpClient httpClient)
/// <inheritdoc/>
public async Task<IReadOnlyList<UrbanDefinition>> GetDefinitionsAsync(string term, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

await using var stream = await _httpClient.GetStreamAsync(new Uri($"define?term={Uri.EscapeDataString(term)}", UriKind.Relative), cancellationToken).ConfigureAwait(false);
Expand All @@ -57,7 +58,7 @@ public async Task<IReadOnlyList<UrbanDefinition>> GetDefinitionsAsync(string ter
/// <inheritdoc/>
public async Task<IReadOnlyList<UrbanDefinition>> GetRandomDefinitionsAsync(CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

await using var stream = await _httpClient.GetStreamAsync(new Uri("random", UriKind.Relative), cancellationToken).ConfigureAwait(false);
Expand All @@ -68,7 +69,7 @@ public async Task<IReadOnlyList<UrbanDefinition>> GetRandomDefinitionsAsync(Canc
/// <inheritdoc/>
public async Task<UrbanDefinition?> GetDefinitionAsync(int id, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

await using var stream = await _httpClient.GetStreamAsync(new Uri($"define?defid={id}", UriKind.Relative), cancellationToken).ConfigureAwait(false);
Expand All @@ -81,7 +82,7 @@ public async Task<IReadOnlyList<UrbanDefinition>> GetRandomDefinitionsAsync(Canc
/// <inheritdoc/>
public async Task<IReadOnlyList<UrbanDefinition>> GetWordsOfTheDayAsync(CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

await using var stream = await _httpClient.GetStreamAsync(new Uri("words_of_the_day", UriKind.Relative), cancellationToken).ConfigureAwait(false);
Expand All @@ -92,17 +93,16 @@ public async Task<IReadOnlyList<UrbanDefinition>> GetWordsOfTheDayAsync(Cancella
/// <inheritdoc/>
public async Task<IReadOnlyList<string>> GetAutocompleteResultsAsync(string term, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

await using var stream = await _httpClient.GetStreamAsync(new Uri($"autocomplete?term={Uri.EscapeDataString(term)}", UriKind.Relative), cancellationToken).ConfigureAwait(false);
return (await JsonSerializer.DeserializeAsync<IReadOnlyList<string>>(stream, (JsonSerializerOptions?)null, cancellationToken).ConfigureAwait(false))!;
return (await _httpClient.GetFromJsonAsync<IReadOnlyList<string>>(new Uri($"autocomplete?term={Uri.EscapeDataString(term)}", UriKind.Relative), cancellationToken).ConfigureAwait(false))!;
}

/// <inheritdoc/>
public async Task<IReadOnlyList<UrbanAutocompleteResult>> GetAutocompleteResultsExtraAsync(string term, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

await using var stream = await _httpClient.GetStreamAsync(new Uri($"autocomplete-extra?term={Uri.EscapeDataString(term)}", UriKind.Relative), cancellationToken).ConfigureAwait(false);
Expand All @@ -121,12 +121,4 @@ public void Dispose()
_httpClient.Dispose();
_disposed = true;
}

private void EnsureNotDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(UrbanDictionary));
}
}
}
12 changes: 2 additions & 10 deletions src/Apis/Wikipedia/WikipediaClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public WikipediaClient(HttpClient httpClient)
/// <inheritdoc/>
public async Task<IWikipediaArticle?> GetArticleAsync(int id, string language, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

string url = $"https://{language}.wikipedia.org/w/api.php?" +
Expand Down Expand Up @@ -71,7 +71,7 @@ public WikipediaClient(HttpClient httpClient)
/// <inheritdoc/>
public async Task<IReadOnlyList<IPartialWikipediaArticle>> SearchArticlesAsync(string query, string language, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

string url = $"https://{language}.wikipedia.org/w/api.php?action=query&list=search&srsearch=intitle:{Uri.EscapeDataString(query)}&utf8&format=json&srprop=";
Expand Down Expand Up @@ -99,12 +99,4 @@ public void Dispose()
_httpClient.Dispose();
_disposed = true;
}

private void EnsureNotDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(WikipediaClient));
}
}
}
12 changes: 2 additions & 10 deletions src/Apis/WolframAlpha/WolframAlphaClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ public WolframAlphaClient(HttpClient httpClient)
/// <inheritdoc/>
public async Task<IReadOnlyList<string>> GetAutocompleteResultsAsync(string input, string language, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(language);
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

await using var stream = await _httpClient.GetStreamAsync(new Uri($"https://{GetSubdomain(language)}.wolframalpha.com/n/v1/api/autocomplete/?i={Uri.EscapeDataString(input)}&appid={AppId}"), cancellationToken).ConfigureAwait(false);
Expand All @@ -72,9 +72,9 @@ public async Task<IReadOnlyList<string>> GetAutocompleteResultsAsync(string inpu
/// <inheritdoc/>
public async Task<IWolframAlphaResult> SendQueryAsync(string input, string language, bool reinterpret = true, CancellationToken cancellationToken = default)
{
EnsureNotDisposed();
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(language);
ObjectDisposedException.ThrowIf(_disposed, this);
cancellationToken.ThrowIfCancellationRequested();

string escapedInput = Uri.EscapeDataString(input);
Expand Down Expand Up @@ -107,12 +107,4 @@ private static string GetSubdomain(string language) =>
"ja" => "ja",
_ => "www"
};

private void EnsureNotDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(WolframAlphaClient));
}
}
}
Loading

0 comments on commit 832f84b

Please sign in to comment.