defmodule Expletive do @moduledoc """ A profanity detection and sanitization library. """ alias Expletive.Configuration, as: Configuration alias Expletive.Replacement, as: Replacement @type replacement :: :default | :garbled | :stars | :vowels | :nonconsonants | String.t() | {:repeat, String.t()} | :keep_first_letter | {:keep_first_letter, String.t()} @doc """ Returns a configuration to pass to other functions. * `:blacklist` - A list of words which are considered profane (if a string is given, it will be split on whitespace to create the world list) * `:whitelist` - A list of words which are allowed even if they're also present in the blacklist (if a string is given, it will be split on whitespace to create the world list) * `:match_substrings` - Whether to match substrings within words (default: `false`). When `true`, enables substring matching. * `:replacement` - A replacement strategy: * `:garbled` - Replace by a random permutation of `$@!#%` (default) * `:stars` - Replace all characters by `*` * `:vowels` - Replace all vowels of the offending word by `*` * `:nonconsonants` - Replace all non-consonants of the offending word by `*` * `string` - Replace the occurence by the given string * `{:repeat, string}` - Replace all characters by the given string * `:keep_first_letter` - Replace all characters but the first one by `*` * `{:keep_first_letter, string}` - Replace all characters but the first one by the given string """ @spec configure(list) :: Configuration.t() def configure(options) do Configuration.new(options) end @doc """ Updates the configuration. Accepts the same options as `configure/1` """ @spec configure(Configuration.t(), list) :: Configuration.t() def configure(config, options) do Configuration.update(config, options) end @doc """ Returns `true` if the given string contains a word considered profane by the given configuration. """ @spec profane?(String.t(), Configuration.t()) :: boolean def profane?(string, config) do Regex.match?(config.regex, string) end @doc """ Returns a list of profanities found in the given string. All occurences are returned, duplicates may thus occur """ @spec profanities(String.t(), Configuration.t()) :: [String.t()] def profanities(string, config) do config.regex |> Regex.scan(string) |> Enum.map(fn [match] -> match end) end @doc """ Replace all profanities by a placeholder as defined by the `replacement` option of the current configuration """ @spec sanitize(String.t(), Configuration.t()) :: String.t() def sanitize(string, config) do config.regex |> Regex.replace(string, fn word -> Replacement.replace(word, config.replacement) end) end @doc """ Replace all profanities by a placeholder as defined by the given `replacement` strategy """ @spec sanitize(String.t(), Configuration.t(), replacement) :: String.t() def sanitize(string, config, replacement) do sanitize(string, %{config | replacement: replacement}) end end