-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3544eb8
commit e4b0149
Showing
24 changed files
with
373 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
{ | ||
"sdk": { | ||
"version": "8.0.200" | ||
"version": "8.0.301" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
120 changes: 120 additions & 0 deletions
120
src/ProfanityFilter.WebApi/Endpoints/ProfanityFilterEndpointExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// Copyright (c) David Pine. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
namespace ProfanityFilter.WebApi.Endpoints; | ||
|
||
internal static class ProfanityFilterEndpointExtensions | ||
{ | ||
internal static WebApplication MapProfanityFilterEndpoints(this WebApplication app) | ||
{ | ||
var profanity = app.MapGroup("profanity"); | ||
|
||
profanity.MapPost("filter", OnApplyFilterAsync) | ||
.WithOpenApi() | ||
.WithRequestTimeout(TimeSpan.FromSeconds(10)) | ||
.WithSummary(""" | ||
Use this endpoint to attempt applying a profanity-filter. The response is returned as Markdown. | ||
""") | ||
.WithHttpLogging(HttpLoggingFields.All); | ||
|
||
profanity.MapGet("strategies", OnGetStrategies) | ||
.WithOpenApi() | ||
.WithRequestTimeout(TimeSpan.FromSeconds(10)) | ||
.CacheOutput() | ||
.WithSummary(""" | ||
Returns an array of the possible replacement strategies available. See https://github.com/IEvangelist/profanity-filter?tab=readme-ov-file#-replacement-strategies | ||
""") | ||
.WithHttpLogging(HttpLoggingFields.All); | ||
|
||
var data = profanity.MapGroup("data"); | ||
|
||
data.MapGet("names", OnGetDataNamesAsync) | ||
.WithOpenApi() | ||
.WithRequestTimeout(TimeSpan.FromSeconds(10)) | ||
.CacheOutput() | ||
.WithSummary(""" | ||
Returns an array of the data names. | ||
""") | ||
.WithHttpLogging(HttpLoggingFields.All); | ||
|
||
data.MapGet("{name}", OnGetDataByNameAsync) | ||
.WithOpenApi() | ||
.WithRequestTimeout(TimeSpan.FromSeconds(10)) | ||
.CacheOutput() | ||
.WithSummary(""" | ||
Returns an array of the profane words for a given data name. | ||
""") | ||
.WithHttpLogging(HttpLoggingFields.All); | ||
|
||
return app; | ||
} | ||
|
||
private static async Task<IResult> OnApplyFilterAsync( | ||
[FromBody] ProfanityFilterRequest request, | ||
[FromServices] IProfaneContentFilterService filterService) | ||
{ | ||
if (request is null || string.IsNullOrWhiteSpace(request.Text)) | ||
{ | ||
return Results.BadRequest($""" | ||
You need to provide a valid request. | ||
"""); | ||
} | ||
|
||
var parameters = new FilterParameters( | ||
request.Strategy, FilterTarget.Body); | ||
|
||
var filterResult = | ||
await filterService.FilterProfanityAsync(request.Text, parameters); | ||
|
||
var response = new ProfanityFilterResponse( | ||
ContainsProfanity: filterResult.IsFiltered, | ||
InputText: filterResult.Input, | ||
FilteredText: filterResult.FinalOutput, | ||
ReplacementStrategy: request.Strategy, | ||
FiltrationSteps: [.. filterResult.Steps?.Where(static s => s.IsFiltered)], | ||
Matches: [.. filterResult.Matches] | ||
); | ||
|
||
return TypedResults.Json( | ||
response, | ||
SourceGenerationContext.Default.ProfanityFilterResponse); | ||
} | ||
|
||
private static IResult OnGetStrategies() => | ||
TypedResults.Json([ | ||
.. Enum.GetValues<ReplacementStrategy>() | ||
], | ||
SourceGenerationContext.Default.StrategyResponseArray | ||
); | ||
|
||
private static async Task<IResult> OnGetDataNamesAsync( | ||
[FromServices] IProfaneContentFilterService filterService) | ||
{ | ||
var map = await filterService.ReadAllProfaneWordsAsync(); | ||
|
||
return TypedResults.Json([ | ||
.. map.Keys.Select(static key => Path.GetFileNameWithoutExtension(key)) | ||
], | ||
SourceGenerationContext.Default.StringArray); | ||
} | ||
|
||
private static async Task<IResult> OnGetDataByNameAsync( | ||
[FromRoute] string name, | ||
[FromServices] IProfaneContentFilterService filterService) | ||
{ | ||
var map = await filterService.ReadAllProfaneWordsAsync(); | ||
|
||
foreach (var (key, value) in map) | ||
{ | ||
if (Path.GetFileNameWithoutExtension(key) == name) | ||
{ | ||
return TypedResults.Json([ | ||
.. value.ProfaneWords | ||
], | ||
SourceGenerationContext.Default.StringArray); | ||
} | ||
} | ||
|
||
return TypedResults.NotFound(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// Copyright (c) David Pine. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
global using System.Diagnostics.CodeAnalysis; | ||
|
||
global using System.Text.Json; | ||
global using System.Text.Json.Serialization; | ||
|
||
global using Microsoft.AspNetCore.Mvc; | ||
global using Microsoft.AspNetCore.HttpLogging; | ||
|
||
global using ProfanityFilter.Services; | ||
global using ProfanityFilter.Services.Extensions; | ||
global using ProfanityFilter.Services.Filters; | ||
global using ProfanityFilter.Services.Results; | ||
|
||
global using ProfanityFilter.WebApi.Endpoints; | ||
global using ProfanityFilter.WebApi.Models; | ||
global using ProfanityFilter.WebApi.Serialization; |
13 changes: 13 additions & 0 deletions
13
src/ProfanityFilter.WebApi/Models/ProfanityFilterRequest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// Copyright (c) David Pine. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
namespace ProfanityFilter.WebApi.Models; | ||
|
||
/// <summary> | ||
/// A representation of a profanity-filter request. | ||
/// </summary> | ||
/// <param name="Text">The text to evaluate for profanity.</param> | ||
/// <param name="ReplacementStrategy">The desired replacement strategy to use. Defaults to <c>*</c>.</param> | ||
public sealed record class ProfanityFilterRequest( | ||
string Text, | ||
ReplacementStrategy Strategy = ReplacementStrategy.Asterisk); |
27 changes: 27 additions & 0 deletions
27
src/ProfanityFilter.WebApi/Models/ProfanityFilterResponse.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// Copyright (c) David Pine. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
namespace ProfanityFilter.WebApi.Models; | ||
|
||
/// <summary> | ||
/// A representation of a profanity-filter response object. | ||
/// </summary> | ||
/// <param name="ContainsProfanity">A boolean value indicating whether or | ||
/// not the the <see cref="InputText"/> contains profanity.</param> | ||
/// <param name="InputText">The original input text.</param> | ||
/// <param name="FilteredText">The final output text, after filters have been applied.</param> | ||
/// <param name="ReplacementStrategy">The replacement strategy used.</param> | ||
/// <param name="FiltrationSteps">An array of steps representing the | ||
/// filtration process, step-by-step.</param> | ||
public sealed record class ProfanityFilterResponse( | ||
[property:MemberNotNullWhen( | ||
true, | ||
nameof(ProfanityFilterResponse.FilteredText), | ||
nameof(ProfanityFilterResponse.FiltrationSteps), | ||
nameof(ProfanityFilterResponse.Matches))] | ||
bool ContainsProfanity, | ||
string InputText, | ||
string? FilteredText, | ||
ReplacementStrategy ReplacementStrategy, | ||
ProfanityFilterStep[]? FiltrationSteps = default, | ||
string[]? Matches = default); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// Copyright (c) David Pine. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
namespace ProfanityFilter.WebApi.Models; | ||
|
||
/// <summary> | ||
/// A representation of a profanity-filter step, detailing | ||
/// each step applied to a filter operation. | ||
/// </summary> | ||
/// <param name="Input">The input before the step ran.</param> | ||
/// <param name="Output">The output after the step ran.</param> | ||
/// <param name="ProfaneSourceData">The profane source data for the step. For example, <i>Data/SwearWordList.txt</i>.</param> | ||
public sealed record class ProfanityFilterStep( | ||
string Input, | ||
string Output, | ||
string ProfaneSourceData) | ||
{ | ||
public static implicit operator ProfanityFilterStep(FilterStep step) => | ||
new(step.Input, step.Output!, step.ProfaneSourceData); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright (c) David Pine. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
namespace ProfanityFilter.WebApi.Models; | ||
|
||
/// <summary> | ||
/// A representation of a strategy response object. | ||
/// </summary> | ||
/// <param name="StrategyName">The name of the strategy.</param> | ||
/// <param name="StrategyValue">The <c>int</c> value of the strategy.</param> | ||
/// <param name="Description">The description of the strategy.</param> | ||
public sealed record class StrategyResponse( | ||
string StrategyName, | ||
int StrategyValue, | ||
string Description) | ||
{ | ||
public static implicit operator StrategyResponse(ReplacementStrategy strategy) | ||
{ | ||
var description = strategy switch | ||
{ | ||
ReplacementStrategy.Asterisk => "Replaces the profanity word with asterisk.", | ||
ReplacementStrategy.Emoji => "Replaces the profanity word with an emoji.", | ||
ReplacementStrategy.AngerEmoji => "Replaces the profanity word with the one of the anger emoji.", | ||
ReplacementStrategy.MiddleSwearEmoji => "Represents a replacement strategy where the middle of the swear word is replaced with an emoji.", | ||
ReplacementStrategy.RandomAsterisk => "Represents a replacement strategy where the profanity is replaced with a random number of asterisk.", | ||
ReplacementStrategy.MiddleAsterisk => "Represents the middle asterisk replacement strategy, which replaces the characters in the middle of the profanity with asterisk.", | ||
ReplacementStrategy.FirstLetterThenAsterisk => "Represents the first letter then asterisk replacement strategy, which replaces everything after the first letter of the profanity with asterisk.", | ||
ReplacementStrategy.VowelAsterisk => "Represents a replacement strategy where vowels in a profane wordare replaced with asterisk.", | ||
ReplacementStrategy.Bleep => "Represents a replacement strategy where the profanity is replaced with athe word \"bleep\".", | ||
ReplacementStrategy.RedactedRectangle => "Represents a replacement strategy where the profane word has each letterreplaced with the rectangle symbol <c>█</c>.", | ||
ReplacementStrategy.StrikeThrough => "Represents a replacement strategy where the profane word is <c>~~struck through~~</c>.", | ||
ReplacementStrategy.Underscores => "Represents a replacement strategy where the profane word is replaced by underscores.", | ||
ReplacementStrategy.Grawlix => "Represents a replacement strategy where the profane word is replaced by grawlix, for example <c>\"#$@!\"</c>.", | ||
ReplacementStrategy.BoldGrawlix => "Represents a replacement strategy where the profane word is replaced by bold grawlix, for example <c>\"#$@!\"</c>.", | ||
_ => "", | ||
}; | ||
|
||
return new StrategyResponse( | ||
StrategyName: Enum.GetName(strategy) ?? strategy.ToString(), | ||
StrategyValue: (int)strategy, | ||
Description: description); | ||
} | ||
} |
Oops, something went wrong.