badprofanity/profanity.go

111 lines
2.4 KiB
Go

package profanity
import (
"bufio"
"os"
"profanity/common"
"profanity/common/decanter"
"strings"
)
type Filter struct {
words map[string]string
Decanter decanter.Decanter
transforms []common.TransformFunc
}
func New() *Filter {
dec := decanter.NewDefaultDecanter()
return &Filter{
words: make(map[string]string, 3000),
Decanter: dec,
transforms: []common.TransformFunc{dec.DecantTransform},
}
}
//FilterWord
//curse is "" if bad == false, else curse is populated with the match
func (F *Filter) FilterWord(s string) (bad bool, curse string, form string) {
forms := common.FlattenTransformFunc(F.transforms)(s)
for _, form := range forms {
if curse, ok := F.words[form]; ok {
return true, curse, form
}
for _, v := range F.words {
if strings.Contains(form, v) {
return true, curse, form
}
}
}
return false, "", ""
}
func (F *Filter) CensorSentence(s string, replacer string) (censored string) {
return F.CensorSentenceN(s, replacer, 0)
}
func (F *Filter) CensorSentenceMany(s string, replacer string, widths ...uint8) (censored string) {
sentence := s
for _, width := range widths {
sentence = F.CensorSentenceN(sentence, replacer, width)
}
return sentence
}
func (F *Filter) CensorSentenceToN(s string, replacer string, maxwidth uint8) (censored string) {
sentence := s
for width := uint8(0); width < maxwidth; width++ {
sentence = F.CensorSentenceN(sentence, replacer, width)
}
return sentence
}
func (F *Filter) CensorSentenceN(s string, replacer string, width uint8) (censored string) {
sep := " "
sb := new(strings.Builder)
words := strings.Split(s, sep)
for idx := 0; idx < len(words); idx++ {
original := words[idx]
word := words[idx]
for i := 1; i <= int(width); i++ {
if len(words) > (idx + i) {
word = word + " " + words[idx+i]
}
}
if bad, _, form := F.FilterWord(word); bad {
idx = idx + int(width)
sb.WriteString(strings.Repeat(replacer, len(form)))
} else {
sb.WriteString(original)
}
sb.WriteString(sep)
}
return strings.TrimSpace(sb.String())
}
func (F *Filter) MustAddFile(file *os.File, err error) {
if err != nil {
panic(err)
}
F.AddFile(file)
}
func (F *Filter) AddFile(file *os.File) {
scanner := bufio.NewScanner(file)
for scanner.Scan() {
txt := scanner.Text()
F.AddWord(txt)
}
}
func (F *Filter) AddWords(wx []string) {
for _, w := range wx {
F.AddWord(w)
}
}
func (F *Filter) AddWord(w string) {
F.words[w] = w
}