diff --git a/src/NadekoBot.Coordinator/Services/CoordinatorRunner.cs b/src/NadekoBot.Coordinator/Services/CoordinatorRunner.cs index 08784f4f0..d7b23566d 100644 --- a/src/NadekoBot.Coordinator/Services/CoordinatorRunner.cs +++ b/src/NadekoBot.Coordinator/Services/CoordinatorRunner.cs @@ -286,7 +286,7 @@ namespace NadekoBot.Coordinator for (var shardId = 0; shardId < _shardStatuses.Length; shardId++) { var status = _shardStatuses[shardId]; - if (status.Process is { } p) + if (status.Process is Process p) { try{p.Kill();} catch {} try{p.Dispose();} catch {} diff --git a/src/NadekoBot/Modules/Gambling/AnimalRacing/AnimalRacingCommands.cs b/src/NadekoBot/Modules/Gambling/AnimalRacing/AnimalRacingCommands.cs index 461dce361..dc11b272f 100644 --- a/src/NadekoBot/Modules/Gambling/AnimalRacing/AnimalRacingCommands.cs +++ b/src/NadekoBot/Modules/Gambling/AnimalRacing/AnimalRacingCommands.cs @@ -76,6 +76,7 @@ public partial class Gambling (race.FinishedUsers[0].Bet * (race.Users.Count - 1)) + CurrencySign))); } + ar.Dispose(); return SendConfirmAsync(GetText(strs.animal_race), GetText(strs.animal_race_won(Format.Bold(winner.Username), winner.Animal.Icon))); } @@ -127,6 +128,7 @@ public partial class Gambling private Task Ar_OnStartingFailed(AnimalRace race) { _service.AnimalRaces.TryRemove(ctx.Guild.Id, out _); + race.Dispose(); return ReplyErrorLocalizedAsync(strs.animal_race_failed); } diff --git a/src/NadekoBot/Modules/Gambling/VoteRewardService.cs b/src/NadekoBot/Modules/Gambling/VoteRewardService.cs index 0a8d7ae4c..1a92cefdb 100644 --- a/src/NadekoBot/Modules/Gambling/VoteRewardService.cs +++ b/src/NadekoBot/Modules/Gambling/VoteRewardService.cs @@ -35,7 +35,7 @@ public class VoteRewardService : INService, IReadyExecutor if (_client.ShardId != 0) return; - var http = new HttpClient(new HttpClientHandler + using var http = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false, ServerCertificateCustomValidationCallback = delegate { return true; } diff --git a/src/NadekoBot/Modules/Help/Help.cs b/src/NadekoBot/Modules/Help/Help.cs index 4576904ab..2f6aace34 100644 --- a/src/NadekoBot/Modules/Help/Help.cs +++ b/src/NadekoBot/Modules/Help/Help.cs @@ -359,7 +359,7 @@ public partial class Help : NadekoModule }; using var dlClient = new AmazonS3Client(accessKey, secretAcccessKey, config); - var oldVersionObject = await dlClient.GetObjectAsync(new() + using var oldVersionObject = await dlClient.GetObjectAsync(new() { BucketName = "nadeko-pictures", Key = "cmds/versions.json" diff --git a/src/NadekoBot/Modules/Music/Services/extractor/YtLoader.cs b/src/NadekoBot/Modules/Music/Services/extractor/YtLoader.cs index 4f2aece64..eab4ebfca 100644 --- a/src/NadekoBot/Modules/Music/Services/extractor/YtLoader.cs +++ b/src/NadekoBot/Modules/Music/Services/extractor/YtLoader.cs @@ -76,7 +76,7 @@ public sealed partial class YtLoader var mem = GetScriptResponseSpan(response); var root = JsonDocument.Parse(mem).RootElement; - var tracksJsonItems = root + using var tracksJsonItems = root .GetProperty("contents") .GetProperty("twoColumnSearchResultsRenderer") .GetProperty("primaryContents") diff --git a/src/NadekoBot/Modules/Searches/Crypto/CryptoCommands.cs b/src/NadekoBot/Modules/Searches/Crypto/CryptoCommands.cs index 8016d6add..fe887f6e7 100644 --- a/src/NadekoBot/Modules/Searches/Crypto/CryptoCommands.cs +++ b/src/NadekoBot/Modules/Searches/Crypto/CryptoCommands.cs @@ -98,15 +98,16 @@ public partial class Searches return; var fileName = $"{query}-sparkline.{imageData.Extension}"; + using var attachment = new FileAttachment( + imageData.FileData, + fileName + ); await message.ModifyAsync(mp => { mp.Attachments = new(new[] { - new FileAttachment( - imageData.FileData, - fileName - ) + attachment }); mp.Embed = eb.WithImageUrl($"attachment://{fileName}").Build(); diff --git a/src/NadekoBot/Modules/Searches/Crypto/Polygon/PolygonApiClient.cs b/src/NadekoBot/Modules/Searches/Crypto/Polygon/PolygonApiClient.cs index 1ba955120..6c50a3c08 100644 --- a/src/NadekoBot/Modules/Searches/Crypto/Polygon/PolygonApiClient.cs +++ b/src/NadekoBot/Modules/Searches/Crypto/Polygon/PolygonApiClient.cs @@ -1,55 +1,55 @@ -using System.Net.Http.Json; - -namespace NadekoBot.Modules.Searches; - -public sealed class PolygonApiClient : IDisposable -{ - private const string BASE_URL = "https://api.polygon.io/v3"; - - private readonly HttpClient _httpClient; - private readonly string _apiKey; - - public PolygonApiClient(HttpClient httpClient, string apiKey) - { - _httpClient = httpClient; - _apiKey = apiKey; - } - - public async Task> TickersAsync(string? ticker = null, string? query = null) - { - if (string.IsNullOrWhiteSpace(query)) - query = null; - - if(query is not null) - query = Uri.EscapeDataString(query); - - var requestString = $"{BASE_URL}/reference/tickers" - + "?type=CS" - + "&active=true" - + "&order=asc" - + "&limit=1000" - + $"&apiKey={_apiKey}"; - - if (!string.IsNullOrWhiteSpace(ticker)) - requestString += $"&ticker={ticker}"; - - if (!string.IsNullOrWhiteSpace(query)) - requestString += $"&search={query}"; - - - var response = await _httpClient.GetFromJsonAsync(requestString); - - if (response is null) - return Array.Empty(); - - return response.Results; - } - - // public async Task TickerDetailsV3Async(string ticker) - // { - // return new(); - // } - - public void Dispose() - => _httpClient.Dispose(); -} \ No newline at end of file +// using System.Net.Http.Json; +// +// namespace NadekoBot.Modules.Searches; +// +// public sealed class PolygonApiClient : IDisposable +// { +// private const string BASE_URL = "https://api.polygon.io/v3"; +// +// private readonly HttpClient _httpClient; +// private readonly string _apiKey; +// +// public PolygonApiClient(HttpClient httpClient, string apiKey) +// { +// _httpClient = httpClient; +// _apiKey = apiKey; +// } +// +// public async Task> TickersAsync(string? ticker = null, string? query = null) +// { +// if (string.IsNullOrWhiteSpace(query)) +// query = null; +// +// if(query is not null) +// query = Uri.EscapeDataString(query); +// +// var requestString = $"{BASE_URL}/reference/tickers" +// + "?type=CS" +// + "&active=true" +// + "&order=asc" +// + "&limit=1000" +// + $"&apiKey={_apiKey}"; +// +// if (!string.IsNullOrWhiteSpace(ticker)) +// requestString += $"&ticker={ticker}"; +// +// if (!string.IsNullOrWhiteSpace(query)) +// requestString += $"&search={query}"; +// +// +// var response = await _httpClient.GetFromJsonAsync(requestString); +// +// if (response is null) +// return Array.Empty(); +// +// return response.Results; +// } +// +// // public async Task TickerDetailsV3Async(string ticker) +// // { +// // return new(); +// // } +// +// public void Dispose() +// => _httpClient.Dispose(); +// } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Searches/MemegenCommands.cs b/src/NadekoBot/Modules/Searches/MemegenCommands.cs index 48c3d4fad..10d471e27 100644 --- a/src/NadekoBot/Modules/Searches/MemegenCommands.cs +++ b/src/NadekoBot/Modules/Searches/MemegenCommands.cs @@ -34,7 +34,7 @@ public partial class Searches return; using var http = _httpFactory.CreateClient("memelist"); - var res = await http.GetAsync("https://api.memegen.link/templates/"); + using var res = await http.GetAsync("https://api.memegen.link/templates/"); var rawJson = await res.Content.ReadAsStringAsync(); diff --git a/src/NadekoBot/Modules/Searches/SearchesService.cs b/src/NadekoBot/Modules/Searches/SearchesService.cs index 4cc700b1f..9d5612da7 100644 --- a/src/NadekoBot/Modules/Searches/SearchesService.cs +++ b/src/NadekoBot/Modules/Searches/SearchesService.cs @@ -109,7 +109,8 @@ public class SearchesService : INService using (var avatarImg = Image.Load(data)) { avatarImg.Mutate(x => x.Resize(85, 85).ApplyRoundedCorners(42)); - data = avatarImg.ToStream().ToArray(); + await using var avStream = avatarImg.ToStream(); + data = avStream.ToArray(); DrawAvatar(bg, avatarImg); } @@ -141,7 +142,8 @@ public class SearchesService : INService bg.Mutate(x => x.DrawImage(flowers, new(0, 0), new GraphicsOptions())); } - return bg.ToStream().ToArray(); + await using var stream = bg.ToStream(); + return stream.ToArray(); } public Task GetWeatherDataAsync(string query) @@ -532,7 +534,7 @@ public class SearchesService : INService http.DefaultRequestHeaders.Clear(); using var response = await http.SendAsync(msg); - var content = await response.Content.ReadAsStreamAsync(); + await using var content = await response.Content.ReadAsStreamAsync(); using var document = await _googleParser.ParseDocumentAsync(content); var elems = document.QuerySelectorAll("div.g > div > div"); diff --git a/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/Providers/PicartoProvider.cs b/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/Providers/PicartoProvider.cs index 67f438593..f56b09e9e 100644 --- a/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/Providers/PicartoProvider.cs +++ b/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/Providers/PicartoProvider.cs @@ -62,7 +62,7 @@ public class PicartoProvider : Provider { http.DefaultRequestHeaders.Accept.Add(new("application/json")); // get id based on the username - var res = await http.GetAsync($"https://api.picarto.tv/v1/channel/name/{login}"); + using var res = await http.GetAsync($"https://api.picarto.tv/v1/channel/name/{login}"); if (!res.IsSuccessStatusCode) continue; diff --git a/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/Providers/TrovoProvider.cs b/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/Providers/TrovoProvider.cs index 80306858a..f0ebdbb7a 100644 --- a/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/Providers/TrovoProvider.cs +++ b/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/Providers/TrovoProvider.cs @@ -59,7 +59,7 @@ If you are experiencing ratelimits, you should create your own application at: h // so there is no need for ratelimit checks atm try { - var res = await http.PostAsJsonAsync( + using var res = await http.PostAsJsonAsync( $"https://open-api.trovo.live/openplatform/channels/id", new TrovoRequestData() { diff --git a/src/NadekoBot/Modules/Utility/Patreon/PatreonRewardsService.cs b/src/NadekoBot/Modules/Utility/Patreon/PatreonRewardsService.cs index 83944c32b..00fb3cc62 100644 --- a/src/NadekoBot/Modules/Utility/Patreon/PatreonRewardsService.cs +++ b/src/NadekoBot/Modules/Utility/Patreon/PatreonRewardsService.cs @@ -84,12 +84,13 @@ public class PatreonRewardsService : INService, IReadyExecutor try { using var http = _httpFactory.CreateClient(); - var res = await http.PostAsync("https://www.patreon.com/api/oauth2/token" + using var content = new StringContent(string.Empty); + using var res = await http.PostAsync("https://www.patreon.com/api/oauth2/token" + "?grant_type=refresh_token" + $"&refresh_token={creds.Patreon.RefreshToken}" + $"&client_id={creds.Patreon.ClientId}" + $"&client_secret={creds.Patreon.ClientSecret}", - new StringContent(string.Empty)); + content); res.EnsureSuccessStatusCode(); diff --git a/src/NadekoBot/Modules/Utility/Repeater/RepeaterService.cs b/src/NadekoBot/Modules/Utility/Repeater/RepeaterService.cs index 94ae543dc..81b7feff1 100644 --- a/src/NadekoBot/Modules/Utility/Repeater/RepeaterService.cs +++ b/src/NadekoBot/Modules/Utility/Repeater/RepeaterService.cs @@ -27,7 +27,7 @@ public sealed class RepeaterService : IReadyExecutor, INService _creds = creds; _client = client; - var uow = _db.GetDbContext(); + using var uow = _db.GetDbContext(); var shardRepeaters = uow.Set() .Where(x => (int)(x.GuildId / Math.Pow(2, 22)) % _creds.TotalShards == _client.ShardId) diff --git a/src/NadekoBot/Modules/Utility/Utility.cs b/src/NadekoBot/Modules/Utility/Utility.cs index 5d039ae0a..76160c39a 100644 --- a/src/NadekoBot/Modules/Utility/Utility.cs +++ b/src/NadekoBot/Modules/Utility/Utility.cs @@ -336,7 +336,7 @@ public partial class Utility : NadekoModule return; using var http = _httpFactory.CreateClient(); - var res = await http.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); + using var res = await http.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); if (!res.IsImage() || res.GetImageSize() is null or > 262_144) { await ReplyErrorLocalizedAsync(strs.invalid_emoji_link); diff --git a/src/NadekoBot/NadekoBot.csproj b/src/NadekoBot/NadekoBot.csproj index 5439168e6..47a96abdc 100644 --- a/src/NadekoBot/NadekoBot.csproj +++ b/src/NadekoBot/NadekoBot.csproj @@ -35,6 +35,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -77,6 +78,12 @@ + + + + + + diff --git a/src/NadekoBot/Services/Currency/CurrencyService.cs b/src/NadekoBot/Services/Currency/CurrencyService.cs index 58441a356..1731f8a07 100644 --- a/src/NadekoBot/Services/Currency/CurrencyService.cs +++ b/src/NadekoBot/Services/Currency/CurrencyService.cs @@ -14,7 +14,7 @@ public class CurrencyService : ICurrencyService, INService public Task GetWalletAsync(ulong userId, CurrencyType type = CurrencyType.Default) { if (type == CurrencyType.Default) - return Task.FromResult(new DefaultWallet(userId, _db.GetDbContext())); + return Task.FromResult(new DefaultWallet(userId, _db)); throw new ArgumentOutOfRangeException(nameof(type)); } @@ -29,7 +29,7 @@ public class CurrencyService : ICurrencyService, INService { foreach (var userId in userIds) { - await using var wallet = await GetWalletAsync(userId); + var wallet = await GetWalletAsync(userId); await wallet.Add(amount, txData); } @@ -68,7 +68,7 @@ public class CurrencyService : ICurrencyService, INService long amount, TxData txData) { - await using var wallet = await GetWalletAsync(userId); + var wallet = await GetWalletAsync(userId); await wallet.Add(amount, txData); } @@ -77,7 +77,7 @@ public class CurrencyService : ICurrencyService, INService long amount, TxData txData) { - await using var wallet = await GetWalletAsync(user.Id); + var wallet = await GetWalletAsync(user.Id); await wallet.Add(amount, txData); } @@ -86,7 +86,7 @@ public class CurrencyService : ICurrencyService, INService long amount, TxData txData) { - await using var wallet = await GetWalletAsync(userId); + var wallet = await GetWalletAsync(userId); return await wallet.Take(amount, txData); } @@ -95,7 +95,7 @@ public class CurrencyService : ICurrencyService, INService long amount, TxData txData) { - await using var wallet = await GetWalletAsync(user.Id); + var wallet = await GetWalletAsync(user.Id); return await wallet.Take(amount, txData); } } \ No newline at end of file diff --git a/src/NadekoBot/Services/Currency/CurrencyServiceExtensions.cs b/src/NadekoBot/Services/Currency/CurrencyServiceExtensions.cs index 8bbafdcb5..f0cf631a1 100644 --- a/src/NadekoBot/Services/Currency/CurrencyServiceExtensions.cs +++ b/src/NadekoBot/Services/Currency/CurrencyServiceExtensions.cs @@ -6,7 +6,7 @@ public static class CurrencyServiceExtensions { public static async Task GetBalanceAsync(this ICurrencyService cs, ulong userId) { - await using var wallet = await cs.GetWalletAsync(userId); + var wallet = await cs.GetWalletAsync(userId); return await wallet.GetBalance(); } @@ -18,8 +18,8 @@ public static class CurrencyServiceExtensions string fromName, string note) { - await using var fromWallet = await cs.GetWalletAsync(fromId); - await using var toWallet = await cs.GetWalletAsync(toId); + var fromWallet = await cs.GetWalletAsync(fromId); + var toWallet = await cs.GetWalletAsync(toId); var extra = new TxData("gift", fromName, note, fromId); diff --git a/src/NadekoBot/Services/Currency/DefaultWallet.cs b/src/NadekoBot/Services/Currency/DefaultWallet.cs index f32bcd8b1..3e7f08ddd 100644 --- a/src/NadekoBot/Services/Currency/DefaultWallet.cs +++ b/src/NadekoBot/Services/Currency/DefaultWallet.cs @@ -7,48 +7,53 @@ namespace NadekoBot.Services.Currency; public class DefaultWallet : IWallet { + private readonly DbService _db; public ulong UserId { get; } - private readonly NadekoContext _ctx; - - public DefaultWallet(ulong userId, NadekoContext ctx) + public DefaultWallet(ulong userId, DbService db) { UserId = userId; - _ctx = ctx; + _db = db; } - public Task GetBalance() - => _ctx.DiscordUser - .ToLinqToDBTable() - .Where(x => x.UserId == UserId) - .Select(x => x.CurrencyAmount) - .FirstOrDefaultAsync(); + public async Task GetBalance() + { + await using var ctx = _db.GetDbContext(); + return await ctx.DiscordUser + .ToLinqToDBTable() + .Where(x => x.UserId == UserId) + .Select(x => x.CurrencyAmount) + .FirstOrDefaultAsync(); + } public async Task Take(long amount, TxData txData) { if (amount < 0) throw new ArgumentOutOfRangeException(nameof(amount), "Amount to take must be non negative."); - var changed = await _ctx.DiscordUser - .Where(x => x.UserId == UserId && x.CurrencyAmount >= amount) - .UpdateAsync(x => new() - { - CurrencyAmount = x.CurrencyAmount - amount - }); + await using var ctx = _db.GetDbContext(); + + var changed = await ctx.DiscordUser + .Where(x => x.UserId == UserId && x.CurrencyAmount >= amount) + .UpdateAsync(x => new() + { + CurrencyAmount = x.CurrencyAmount - amount + }); if (changed == 0) return false; - await _ctx.CreateLinqToDbContext() - .InsertAsync(new CurrencyTransaction() - { - Amount = -amount, - Note = txData.Note, - UserId = UserId, - Type = txData.Type, - Extra = txData.Extra, - OtherId = txData.OtherId - }); + await using var ctx2 = ctx.CreateLinqToDbContext(); + await ctx2 + .InsertAsync(new CurrencyTransaction() + { + Amount = -amount, + Note = txData.Note, + UserId = UserId, + Type = txData.Type, + Extra = txData.Extra, + OtherId = txData.OtherId + }); return true; } @@ -58,9 +63,11 @@ public class DefaultWallet : IWallet if (amount <= 0) throw new ArgumentOutOfRangeException(nameof(amount), "Amount must be greater than 0."); - await using (var tran = await _ctx.Database.BeginTransactionAsync()) + await using var ctx = _db.GetDbContext(); + + await using (var tran = await ctx.Database.BeginTransactionAsync()) { - var changed = await _ctx.DiscordUser + var changed = await ctx.DiscordUser .Where(x => x.UserId == UserId) .UpdateAsync(x => new() { @@ -69,7 +76,7 @@ public class DefaultWallet : IWallet if (changed == 0) { - await _ctx.DiscordUser + await ctx.DiscordUser .ToLinqToDBTable() .Value(x => x.UserId, UserId) .Value(x => x.Username, "Unknown") @@ -91,19 +98,7 @@ public class DefaultWallet : IWallet OtherId = txData.OtherId }; - await _ctx.CreateLinqToDbContext() - .InsertAsync(ct); - } - - public void Dispose() - { - _ctx.SaveChanges(); - _ctx.Dispose(); - } - - public async ValueTask DisposeAsync() - { - await _ctx.SaveChangesAsync(); - await _ctx.DisposeAsync(); + await using var ctx2 = ctx.CreateLinqToDbContext(); + await ctx2.InsertAsync(ct); } } \ No newline at end of file diff --git a/src/NadekoBot/Services/Currency/IWallet.cs b/src/NadekoBot/Services/Currency/IWallet.cs index 15bd2ebb3..6cbe4d980 100644 --- a/src/NadekoBot/Services/Currency/IWallet.cs +++ b/src/NadekoBot/Services/Currency/IWallet.cs @@ -1,6 +1,6 @@ namespace NadekoBot.Services.Currency; -public interface IWallet : IDisposable, IAsyncDisposable +public interface IWallet { public ulong UserId { get; } diff --git a/src/NadekoBot/Services/DbService.cs b/src/NadekoBot/Services/DbService.cs index b8ea8ef0f..d5dbb9e3d 100644 --- a/src/NadekoBot/Services/DbService.cs +++ b/src/NadekoBot/Services/DbService.cs @@ -32,10 +32,9 @@ public class DbService using var context = new NadekoContext(_options); if (context.Database.GetPendingMigrations().Any()) { - var mContext = new NadekoContext(_migrateOptions); + using var mContext = new NadekoContext(_migrateOptions); mContext.Database.Migrate(); mContext.SaveChanges(); - mContext.Dispose(); } context.Database.ExecuteSqlRaw("PRAGMA journal_mode=WAL"); diff --git a/src/NadekoBot/Services/Impl/BotCredsProvider.cs b/src/NadekoBot/Services/Impl/BotCredsProvider.cs index 16bbc5f51..cdb43c12c 100644 --- a/src/NadekoBot/Services/Impl/BotCredsProvider.cs +++ b/src/NadekoBot/Services/Impl/BotCredsProvider.cs @@ -32,6 +32,7 @@ public sealed class BotCredsProvider : IBotCredsProvider private readonly object _reloadLock = new(); + private readonly IDisposable _changeToken; public BotCredsProvider(int? totalShards = null) { @@ -52,9 +53,9 @@ public sealed class BotCredsProvider : IBotCredsProvider _config = new ConfigurationBuilder().AddYamlFile(CredsPath, false, true) .AddEnvironmentVariables("NadekoBot_") .Build(); - - ChangeToken.OnChange(() => _config.GetReloadToken(), Reload); - +#if !GLOBAL_NADEKO + _changeToken = ChangeToken.OnChange(() => _config.GetReloadToken(), Reload); +#endif Reload(); } diff --git a/src/NadekoBot/Services/Impl/StatsService.cs b/src/NadekoBot/Services/Impl/StatsService.cs index 7c35fec98..20b459281 100644 --- a/src/NadekoBot/Services/Impl/StatsService.cs +++ b/src/NadekoBot/Services/Impl/StatsService.cs @@ -5,7 +5,7 @@ using System.Diagnostics; namespace NadekoBot.Services; -public class StatsService : IStatsService, IReadyExecutor, INService, IDisposable +public sealed class StatsService : IStatsService, IReadyExecutor, INService, IDisposable { public const string BOT_VERSION = "4.0.4"; diff --git a/src/NadekoBot/_Extensions/ProcessExtensions.cs b/src/NadekoBot/_Extensions/ProcessExtensions.cs index 9ed8d18f2..f160608a8 100644 --- a/src/NadekoBot/_Extensions/ProcessExtensions.cs +++ b/src/NadekoBot/_Extensions/ProcessExtensions.cs @@ -1,87 +1,87 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -// https://github.com/aspnet/Common/blob/dev/shared/Microsoft.Extensions.Process.Sources/ProcessHelper.cs - -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace NadekoBot.Extensions; - -public static class ProcessExtensions -{ - private static readonly bool _isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(10); - - public static void KillTree(this Process process) - => process.KillTree(_defaultTimeout); - - public static void KillTree(this Process process, TimeSpan timeout) - { - if (_isWindows) - RunProcessAndWaitForExit("taskkill", $"/T /F /PID {process.Id}", timeout, out _); - else - { - var children = new HashSet(); - GetAllChildIdsUnix(process.Id, children, timeout); - foreach (var childId in children) - KillProcessUnix(childId, timeout); - - KillProcessUnix(process.Id, timeout); - } - } - - private static void GetAllChildIdsUnix(int parentId, ISet children, TimeSpan timeout) - { - var exitCode = RunProcessAndWaitForExit("pgrep", $"-P {parentId}", timeout, out var stdout); - - if (exitCode == 0 && !string.IsNullOrEmpty(stdout)) - { - using var reader = new StringReader(stdout); - while (true) - { - var text = reader.ReadLine(); - if (text is null) - return; - - if (int.TryParse(text, out var id)) - { - children.Add(id); - // Recursively get the children - GetAllChildIdsUnix(id, children, timeout); - } - } - } - } - - private static void KillProcessUnix(int processId, TimeSpan timeout) - => RunProcessAndWaitForExit("kill", $"-TERM {processId}", timeout, out _); - - private static int RunProcessAndWaitForExit( - string fileName, - string arguments, - TimeSpan timeout, - out string? stdout) - { - stdout = null; - - var startInfo = new ProcessStartInfo - { - FileName = fileName, - Arguments = arguments, - RedirectStandardOutput = true, - UseShellExecute = false - }; - - var process = Process.Start(startInfo); - - if (process is null) - return -1; - - if (process.WaitForExit((int)timeout.TotalMilliseconds)) - stdout = process.StandardOutput.ReadToEnd(); - else - process.Kill(); - - return process.ExitCode; - } -} \ No newline at end of file +// // Copyright (c) .NET Foundation. All rights reserved. +// // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// // https://github.com/aspnet/Common/blob/dev/shared/Microsoft.Extensions.Process.Sources/ProcessHelper.cs +// +// using System.Diagnostics; +// using System.Runtime.InteropServices; +// +// namespace NadekoBot.Extensions; +// +// public static class ProcessExtensions +// { +// private static readonly bool _isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); +// private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(10); +// +// public static void KillTree(this Process process) +// => process.KillTree(_defaultTimeout); +// +// public static void KillTree(this Process process, TimeSpan timeout) +// { +// if (_isWindows) +// RunProcessAndWaitForExit("taskkill", $"/T /F /PID {process.Id}", timeout, out _); +// else +// { +// var children = new HashSet(); +// GetAllChildIdsUnix(process.Id, children, timeout); +// foreach (var childId in children) +// KillProcessUnix(childId, timeout); +// +// KillProcessUnix(process.Id, timeout); +// } +// } +// +// private static void GetAllChildIdsUnix(int parentId, ISet children, TimeSpan timeout) +// { +// var exitCode = RunProcessAndWaitForExit("pgrep", $"-P {parentId}", timeout, out var stdout); +// +// if (exitCode == 0 && !string.IsNullOrEmpty(stdout)) +// { +// using var reader = new StringReader(stdout); +// while (true) +// { +// var text = reader.ReadLine(); +// if (text is null) +// return; +// +// if (int.TryParse(text, out var id)) +// { +// children.Add(id); +// // Recursively get the children +// GetAllChildIdsUnix(id, children, timeout); +// } +// } +// } +// } +// +// private static void KillProcessUnix(int processId, TimeSpan timeout) +// => RunProcessAndWaitForExit("kill", $"-TERM {processId}", timeout, out _); +// +// private static int RunProcessAndWaitForExit( +// string fileName, +// string arguments, +// TimeSpan timeout, +// out string? stdout) +// { +// stdout = null; +// +// var startInfo = new ProcessStartInfo +// { +// FileName = fileName, +// Arguments = arguments, +// RedirectStandardOutput = true, +// UseShellExecute = false +// }; +// +// using var process = Process.Start(startInfo); +// +// if (process is null) +// return -1; +// +// if (process.WaitForExit((int)timeout.TotalMilliseconds)) +// stdout = process.StandardOutput.ReadToEnd(); +// else +// process.Kill(); +// +// return process.ExitCode; +// } +// } \ No newline at end of file diff --git a/src/NadekoBot/_Extensions/Rgba32Extensions.cs b/src/NadekoBot/_Extensions/Rgba32Extensions.cs index abd4565ab..d4dfe2bcf 100644 --- a/src/NadekoBot/_Extensions/Rgba32Extensions.cs +++ b/src/NadekoBot/_Extensions/Rgba32Extensions.cs @@ -21,7 +21,7 @@ public static class Rgba32Extensions var xOffset = 0; for (var i = 0; i < imgArray.Count; i++) { - var frame = imgArray[i].Frames.CloneFrame(frameNumber % imgArray[i].Frames.Count); + using var frame = imgArray[i].Frames.CloneFrame(frameNumber % imgArray[i].Frames.Count); var offset = xOffset; imgFrame.Mutate(x => x.DrawImage(frame, new(offset, 0), new GraphicsOptions())); xOffset += imgArray[i].Bounds().Width; diff --git a/src/NadekoBot/_Extensions/StringExtensions.cs b/src/NadekoBot/_Extensions/StringExtensions.cs index c59ebb1a0..3c6532b6e 100644 --- a/src/NadekoBot/_Extensions/StringExtensions.cs +++ b/src/NadekoBot/_Extensions/StringExtensions.cs @@ -89,7 +89,7 @@ public static class StringExtensions public static async Task ToStream(this string str) { var ms = new MemoryStream(); - var sw = new StreamWriter(ms); + await using var sw = new StreamWriter(ms); await sw.WriteAsync(str); await sw.FlushAsync(); ms.Position = 0;