Library Go untuk deteksi kata kotor Bahasa Indonesia. Ringan, cepet, paham imbuhan, zero dependency.
go get -u github.com/yumiodd/bacot/srcpackage main
import bacot "github.com/yumiodd/bacot/src"
func main() {
b := bacot.New()
// Cek: kasar apa nggak?
b.Text("mebabi").Scan().IsProfane() // true
b.Text("kelas").Scan().IsProfane() // false
// Sensor: biar keliatan sopan
b.Text("babi dan anjing").Collect(true).Scan().Censor()
// "**** dan ******"
// Ekstrak: siapa aja yang kena?
res := b.Text("asu babi bacot").Collect(true).Scan()
res.Extract() // ["asu", "babi", "bacot"]
res.Count() // 3
}Catatan: New() itu berat karena precompute semua varian imbuhan. Panggil sekali aja, simpan sebagai singleton, jangan bikin baru tiap request.
| Masalah | Contoh | Bacot |
|---|---|---|
| Imbuhan | mebabi |
Sok pake imbuhan? ketauan babi-nya |
| Leet speak | 4njing |
Ganti angka percuma, tetep kecium |
| Stack karakter | anjiiiiing |
Udah di-unstack, tetep anjing |
| False positive | babiru |
ru bukan suffix, skip (OK) |
| Suffix valid | memakan |
stem preffix me+makan, bersih, skip (OK) |
| Speed | Sensor 10Kb | 172 microsecond |
Bacot paham imbuhan Indonesia native. Nggak perlu bikin pattern manual.
b.Text("mebabi").Scan().IsProfane() // true
b.Text("penganjing").Scan().IsProfane() // true
b.Text("dimakani").Scan().IsProfane() // false -- di-makan-i
b.Text("mebabi").Affix(false).Scan()... // false -- exact match ajaPrefix yang didukung: me-, pe-, di-, te-, be-, ber-, ter-, per-, meng-, peng-, men-, pen-, meny-, peny-, mem-, pem-, ng-, ny-.
Plus nasal fusion: memukul = mem- + pukul. Kamus isi pukul, Bacot ngerti sendiri.
b.Text("4njing").WithLeetSpeak().Scan().IsProfane() // true -- nice tryb.Text("anjiiiiing").Scan().IsProfane() // trueMendeteksi kata kotor yang nempel di substring. xbabi tetap ketemu babi.
b.Text("xbabi").RecursiveScan().IsProfane() // trueb.AddWord("setan") // varian imbuhan digenerate otomatis
b.Dict.DelWords("anjing") // hapus dari kamus
b.AddFalsePositive("kelas") // cegah false matchPipeline bisa diatur sendiri lewat ModalScanConfig:
b.Config(&bacot.ModalScanConfig{
Affix: false, // exact match aja
Collect: true, // kumpulin semua
Order: []bacot.SanitizeOrder{
bacot.WithLeetSpeak,
bacot.UnstackChar,
},
})Default pipeline: Emoji -> ReplaceWhiteSpace -> SanitizeReadSign -> ReplaceWhiteSpace -> UnstackChar -> Affix(true)
-
Varian imbuhan precomputed -- pas
New(), semua kata dasar + varianme-,ber-,meng-, dll udah masuk map. Scan = O(1) lookup. Nggak ada stemming di runtime. -
Length histogram pre-filter -- kalau dictionary cuma punya kata 3-8 karakter, token 11 karakter langsung di-skip tanpa lookup.
-
False positive filter -- sisa stripping dicek: kalau suffix dikenal (
-kan,-an,-i,-nya) dianggap valid. Cuma sisa non-suffix <=1 suku kata yang di-skip (babiru->ru).
| Operasi | Waktu |
|---|---|
| Cek kata | ~6 ns |
| Scan kalimat | ~531 ns |
| Sensor 10Kb | ~172 us |
