diff --git a/docker-stack.yml b/docker-stack.yml index 4ca08c3fe..3103c58e2 100644 --- a/docker-stack.yml +++ b/docker-stack.yml @@ -39,7 +39,7 @@ services: image: ghcr.io/discord-csharp/csharprepl:latest read_only: true user: www-data - environment: + environment: - ASPNETCORE_URLS=http://+:31337 - Logging__LogLevel__Microsoft=Warning - Logging__LogLevel__CSDiscordService=Trace @@ -90,8 +90,6 @@ services: target: DiscordToken - source: discord-client-secret target: DiscordClientSecret - - source: stackoverflow-token - target: StackoverflowToken - source: db-connection-string target: DbConnection - source: log-webhook-token @@ -103,7 +101,7 @@ services: - proxy - repl - modix - + # the translation feature of the modix bot modix-translator: image: ghcr.io/discord-csharp/modix-translator:latest @@ -144,7 +142,7 @@ services: - pgadmin-data:/var/lib/pgadmin networks: - proxy - + # grafana instance with access to the modix database stats: image: grafana/grafana:latest @@ -169,7 +167,7 @@ services: - grafana-data:/gfdata:rw networks: - proxy - + # monitors the health check (specifically of REPL) and restarts the container autoheal: image: willfarrell/autoheal @@ -177,7 +175,7 @@ services: mode: global volumes: - /var/run/docker.sock:/var/run/docker.sock - + networks: proxy: repl: @@ -218,7 +216,7 @@ volumes: modix-keys: modix-logs: modix-20-keys: - + #workaround for swarm not supporting tmpfs mounts repl-tmp: driver_opts: diff --git a/src/Modix.Bot/Modules/StackExchangeModule.cs b/src/Modix.Bot/Modules/StackExchangeModule.cs deleted file mode 100644 index 0e12284c9..000000000 --- a/src/Modix.Bot/Modules/StackExchangeModule.cs +++ /dev/null @@ -1,95 +0,0 @@ -#nullable enable - -using System; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using Discord; -using Discord.Interactions; -using Microsoft.Extensions.Options; -using Modix.Data.Models.Core; -using Modix.Services.CommandHelp; -using Modix.Services.StackExchange; - -namespace Modix.Modules -{ - [ModuleHelp("Stack Exchange", "Query any site from Stack Exchange.")] - public class StackExchangeModule : InteractionModuleBase - { - private readonly StackExchangeService _stackExchangeService; - private readonly string? _stackOverflowToken; - - public StackExchangeModule( - IOptions config, - StackExchangeService stackExchangeService) - { - _stackExchangeService = stackExchangeService; - _stackOverflowToken = config.Value.StackoverflowToken; - } - - [SlashCommand("stackexchange", "Returns top results from a Stack Exchange site.")] - public async Task RunAsync( - [Summary(description: "The phrase to search Stack Exchange for.")] - string phrase) - { - var startLocation = phrase.IndexOf("["); - var endLocation = phrase.IndexOf("]"); - - string? site = null; - string? tags = null; - - if (startLocation > 0 && endLocation > 0) - { - var query = phrase.Substring(startLocation, endLocation - (startLocation - 1)); - var parts = query.Replace("[", "").Replace("]", "").Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); - - foreach (var part in parts) - { - if (part.Contains("site=", StringComparison.OrdinalIgnoreCase)) - { - site = part.Split(new[] { "site=" }, StringSplitOptions.None)[1]; - } - else if (part.Contains("tags=", StringComparison.OrdinalIgnoreCase)) - { - tags = part.Split(new[] { "tags=" }, StringSplitOptions.None)[1]; - } - } - - phrase = phrase.Remove(startLocation, endLocation - (startLocation - 1)).Trim(); - } - - site ??= "stackoverflow"; - tags ??= "c#"; - - var response = await _stackExchangeService.GetStackExchangeResultsAsync(_stackOverflowToken, phrase, site, tags); - var filteredRes = response.Items.Where(x => x.Tags.Contains(tags)); - - var firstResponse = true; - - foreach (var res in filteredRes.Take(3)) - { - var builder = new EmbedBuilder() - .WithColor(new Color(95, 186, 125)) - .WithTitle($"{res.Score}: {WebUtility.HtmlDecode(res.Title)}") - .WithUrl(res.Link); - - if (firstResponse) - { - await FollowupAsync(embed: builder.Build()); - firstResponse = false; - } - else - { - await ReplyAsync(embed: builder.Build()); - } - } - - var footer = new EmbedBuilder() - .WithColor(new Color(50, 50, 50)) - .WithFooter( - new EmbedFooterBuilder().WithText($"tags: {tags} | site: {site}. !stack foobar [site=stackexchange tags=c#]")); - - await ReplyAsync(embed: footer.Build()); - } - } -} diff --git a/src/Modix.Data/Models/Core/ModixConfig.cs b/src/Modix.Data/Models/Core/ModixConfig.cs index 3138e878c..f407aacc8 100644 --- a/src/Modix.Data/Models/Core/ModixConfig.cs +++ b/src/Modix.Data/Models/Core/ModixConfig.cs @@ -4,8 +4,6 @@ public class ModixConfig { public string? DiscordToken { get; set; } = null; - public string? StackoverflowToken { get; set; } = null; - public string? DbConnection { get; set; } = null; public string? LogWebhookToken { get; set; } = null; diff --git a/src/Modix.Services/StackExchange/StackExchangeResponse.cs b/src/Modix.Services/StackExchange/StackExchangeResponse.cs deleted file mode 100644 index c428fba68..000000000 --- a/src/Modix.Services/StackExchange/StackExchangeResponse.cs +++ /dev/null @@ -1,92 +0,0 @@ -using Newtonsoft.Json; -using System.Collections.Generic; - -namespace Modix.Services.StackExchange -{ - [JsonObject] - public class StackExchangeResponse - { - [JsonProperty("has_more")] - public bool HasMore { get; set; } - - [JsonProperty("quota_max")] - public int QuotaMax { get; set; } - - [JsonProperty("quota_remaining")] - public int QuotaRemaining { get; set; } - - [JsonProperty("items")] - public ICollection Items { get; set; } - } - - [JsonObject] - public class StackExchangeResponseItem - { - [JsonProperty("tags")] - public ICollection Tags { get; set; } - - [JsonProperty("owner")] - public StackExchangeResponseOwner Owner { get; set; } - - [JsonProperty("is_answered")] - public bool IsAnswered { get; set; } - - [JsonProperty("view_count")] - public int ViewCount { get; set; } - - [JsonProperty("protected_date")] - public int ProtectedDate { get; set; } - - [JsonProperty("accepted_answer_id")] - public int AcceptedAnswerId { get; set; } - - [JsonProperty("answer_count")] - public int AnswerCount { get; set; } - - [JsonProperty("score")] - public int Score { get; set; } - - [JsonProperty("last_activity_date")] - public long LastActivityDate { get; set; } - - [JsonProperty("creation_date")] - public long CreationDate { get; set; } - - [JsonProperty("last_edit_date")] - public long LastEditDate { get; set; } - - [JsonProperty("question_id")] - public int QuestionId { get; set; } - - [JsonProperty("link")] - public string Link { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - } - - [JsonObject] - public class StackExchangeResponseOwner - { - [JsonProperty("reputation")] - public int Reputation { get; set; } - - [JsonProperty("user_id")] - public int UserId { get; set; } - - [JsonProperty("user_type")] - public string UserType { get; set; } - - [JsonProperty("accept_rate")] - public int AcceptRate { get; set; } - - [JsonProperty("profile_image")] - public string ProfileImage { get; set; } - - [JsonProperty("display_name")] - public string DisplayName { get; set; } - - [JsonProperty("link")] - public string Link { get; set; } - } -} diff --git a/src/Modix.Services/StackExchange/StackExchangeService.cs b/src/Modix.Services/StackExchange/StackExchangeService.cs deleted file mode 100644 index bd03be905..000000000 --- a/src/Modix.Services/StackExchange/StackExchangeService.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Modix.Services.Utilities; -using Newtonsoft.Json; -using System; -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; - -namespace Modix.Services.StackExchange -{ - public class StackExchangeService - { - private string _apiReferenceUrl = - "http://api.stackexchange.com/2.2/search/advanced" + - "?key={0}" + - "&order=desc" + - "&sort=votes" + - "&filter=default"; - - public StackExchangeService(IHttpClientFactory httpClientFactory) - { - HttpClientFactory = httpClientFactory; - } - - public async Task GetStackExchangeResultsAsync(string token, string phrase, string site, string tags) - { - _apiReferenceUrl = string.Format(_apiReferenceUrl, token); - phrase = Uri.EscapeDataString(phrase); - site = Uri.EscapeDataString(site); - tags = Uri.EscapeDataString(tags); - var query = _apiReferenceUrl += $"&site={site}&tags={tags}&q={phrase}"; - - var client = HttpClientFactory.CreateClient(HttpClientNames.AutomaticGZipDecompression); - - var response = await client.GetAsync(query); - - if (!response.IsSuccessStatusCode) - { - throw new WebException("Something failed while querying the Stack Exchange API."); - } - - var jsonResponse = await response.Content.ReadAsStringAsync(); - return JsonConvert.DeserializeObject(jsonResponse); - } - - protected IHttpClientFactory HttpClientFactory { get; } - } -} diff --git a/src/Modix/Extensions/ServiceCollectionExtensions.cs b/src/Modix/Extensions/ServiceCollectionExtensions.cs index 0ad55a812..6f107f37e 100644 --- a/src/Modix/Extensions/ServiceCollectionExtensions.cs +++ b/src/Modix/Extensions/ServiceCollectionExtensions.cs @@ -32,7 +32,6 @@ using Modix.Services.Moderation; using Modix.Services.Promotions; using Modix.Services.Quote; -using Modix.Services.StackExchange; using Modix.Services.Starboard; using Modix.Services.Tags; using Modix.Services.Utilities; @@ -51,7 +50,7 @@ public static IServiceCollection AddModixHttpClients(this IServiceCollection ser services.AddHttpClient(HttpClientNames.RetryOnTransientErrorPolicy) .AddPolicyHandler(HttpPolicyExtensions.HandleTransientHttpError() - .WaitAndRetryAsync(2, retryAttempt => TimeSpan.FromSeconds(5))); + .WaitAndRetryAsync(2, retryAttempt => TimeSpan.FromSeconds(5))); services.AddHttpClient(HttpClientNames.TimeoutFiveSeconds) .ConfigureHttpClient(client => @@ -172,7 +171,6 @@ public static IServiceCollection AddModix( services.AddMemoryCache(); services.AddScoped(); - services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/src/Modix/appsettings.json b/src/Modix/appsettings.json index 26acc66cc..910d3341f 100644 --- a/src/Modix/appsettings.json +++ b/src/Modix/appsettings.json @@ -16,7 +16,6 @@ "LogWebhookId": "", "LogWebhookToken": "", "DiscordToken": "", - "StackoverflowToken": "", "MessageCacheSize": 0, "ReplUrl": "", "IlUrl": "", diff --git a/wiki/Developers.md b/wiki/Developers.md index 542a9cdb0..3fe84998f 100644 --- a/wiki/Developers.md +++ b/wiki/Developers.md @@ -9,7 +9,7 @@ To work on Modix, you need a few things: - [PostgreSQL database server](https://www.postgresql.org/download/). A docker container also works. - **Optional**: [Docker](https://www.docker.com/get-docker). You **do not** need Docker if you're just developing locally - it's mostly just to test if your changes are significant enough that they might break CI, or if you prefer to keep your dev environment clean. If you're on Windows, make sure you switch to Linux containers. -If you're working on a feature that involves Modix's core services, and only needs to work with the Discord bot frontend, then you can proceed to opening `Modix.sln`. +If you're working on a feature that involves Modix's core services, and only needs to work with the Discord bot frontend, then you can proceed to opening `Modix.sln`. # Setting Configuration ### Config file @@ -28,11 +28,10 @@ If you prefer to use environment variables for configuration, they must all be p - `DiscordClientSecret` - same as above. - **Optional** - `MessageCacheSize` - An integer value defining the internal Discord.Net message cache size - used for logging deleted messages. Should be around 10 or more, and will default to that if unset, but you don't need it unless you're testing message deletion. - - `LogWebhookId` - The ID of the Discord webhook to log to. Only necessary if you want log messages to appear in a channel on the server. + - `LogWebhookId` - The ID of the Discord webhook to log to. Only necessary if you want log messages to appear in a channel on the server. - `https://discord.com/api/webhooks/[this part]/asda2ed2klkm5lkn42n34jk` - `LogWebhookToken` - Same as above, but the token of the webhook. - `https://discord.com/api/webhooks/000000000000000000/[this part]` - - `StackoverflowToken` - A token for the StackOverflow API, if you need to use the StackOverflow module. - `ReplUrl` - The URL of the endpoint that will be receiving REPL (`!eval`/`!exec`) requests - required if you want to test the REPL, and requires you to host the [repl](https://github.com/discord-csharp/CSDiscord). - `IlUrl` - The URL of the endpoint that will be receiving IL (`!il`) requests. Same as above, and will likely be the same URL.