Compare commits

..

1 Commits

Author SHA1 Message Date
Isaac Lewis
8af43099d9 wip 2025-08-27 13:00:21 -07:00
7 changed files with 263 additions and 124 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -1,25 +0,0 @@
![jaggedpill](jaggedpill.jpg)
# Jagged Pill
Jagged Pill is a webserver that responds to any request with a generated
HTML page containing random text and links. The generator is tuned to be very
nonsensical, but ends up creating some weirdly strange and poetic prose...
keep following links to find more!
I use this as an AI scraper labyrinth (or poison pill), with the following NGINX config:
```
# No AI Bots
if ($http_user_agent ~* '(AIBot|AnotherBot|YetAnotherBot)') {
rewrite ^(.*)$ /clank/$1;
}
location /clank/ {
rewrite ^/clank/(.*)$ $1 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://localhost:4791;
}
```

12
go.mod
View File

@ -2,4 +2,14 @@ module jaggedpill
go 1.22.1
require github.com/mroth/weightedrand/v2 v2.1.0
require (
github.com/mroth/weightedrand/v2 v2.1.0
github.com/schollz/progressbar/v3 v3.18.0
)
require (
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/rivo/uniseg v0.4.7 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/term v0.28.0 // indirect
)

22
go.sum
View File

@ -1,2 +1,24 @@
github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM=
github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
github.com/mroth/weightedrand/v2 v2.1.0 h1:o1ascnB1CIVzsqlfArQQjeMy1U0NcIbBO5rfd5E/OeU=
github.com/mroth/weightedrand/v2 v2.1.0/go.mod h1:f2faGsfOGOwc1p94wzHKKZyTpcJUW7OJ/9U4yfiNAOU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA=
github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

110
main.go
View File

@ -3,11 +3,13 @@ package main
import (
"fmt"
"github.com/mroth/weightedrand/v2"
"github.com/schollz/progressbar/v3"
"io"
"math/rand"
"net/http"
"os"
"path/filepath"
"slices"
"strings"
"text/template"
"time"
@ -67,6 +69,7 @@ func main() {
var fileFolder = "html_pages"
var wordTree PocketGraph = isShePervertedLikeMe()
var distances DelusionGraph = weAllHadDelusions(wordTree)
// youOughtaKnow returns an HTTP handler that processes requests.
func youOughtaKnow() http.Handler {
@ -342,7 +345,7 @@ func iDontWannaBeTheFiller() string {
paragraph := strings.Join(sentences, " ")
// Should paragraph contain link?
if rand.Float64() < 0.7 {
if rand.Float64() < 0.5 {
// Pick two or three words out of the paragraph
words := strings.Fields(paragraph)
if len(words) < 2 {
@ -381,7 +384,7 @@ func thanksForYourPatience() (string, error) {
return fmt.Sprintf("Error calculating size of file folder %s: %v\n", fileFolder, err), err
}
if size > 10*1024*1024 { // If the size of the folder is greater than 100 MB
if size > 10*1024*1024 { // If the size of the folder is greater than 10 MB
// If the file is older than the average file age, delete it
err = filepath.Walk(fileFolder, func(_ string, info os.FileInfo, err error) error {
if err != nil {
@ -424,7 +427,11 @@ func isShePervertedLikeMe() PocketGraph {
}
// read words.txt into a list
wordsBytes, err := os.ReadFile("word_lists/jaggedpill.txt")
longmanBytes, err := os.ReadFile("word_lists/longman9000.txt")
jaggedLittlePillBytes, err := os.ReadFile("word_lists/jaggedlittlepill.txt")
wordsBytes := append(longmanBytes, jaggedLittlePillBytes...)
if err != nil {
fmt.Println("Error reading words.txt:", err)
}
@ -433,7 +440,7 @@ func isShePervertedLikeMe() PocketGraph {
tree := make(PocketGraph)
for _, word := range ConnectionWords {
var percentageOfWords float64 = 0.005
var percentageOfWords float64 = 0.02
var numberOfConnections = float64(len(words)) * percentageOfWords
for j := 0; j < int(numberOfConnections); j++ {
randomWord := words[rand.Intn(len(words))]
@ -458,7 +465,7 @@ func isShePervertedLikeMe() PocketGraph {
// connect word to connector words?
shouldConnect := rand.Intn(2) == 0
if shouldConnect {
numConnectionWords := rand.Intn(len(ConnectionWords)) + 1 // Random number of connection words between 1 and 3
numConnectionWords := rand.Intn(2) + 1
for j := 0; j < numConnectionWords; j++ {
connectionWord := ConnectionWords[rand.Intn(len(ConnectionWords))]
tree[word] = append(tree[word], connectionWord)
@ -468,6 +475,50 @@ func isShePervertedLikeMe() PocketGraph {
return tree
}
type DelusionGraph map[string]map[string]int
func weAllHadDelusions(m PocketGraph) DelusionGraph {
distances := make(DelusionGraph)
bar := progressbar.Default(int64(len(m)*len(m)), "Calculating distances...")
// Initialize distances for each word
for word := range m {
distances[word] = make(map[string]int)
for otherWord := range m {
if word == otherWord {
distances[word][otherWord] = 0 // Distance to itself is 0
} else if slices.Contains(m[word], otherWord) {
distances[word][otherWord] = 1 // Direct connection
}
bar.Add(1)
}
}
for word, linkedWords := range m {
for _, linkedWord := range linkedWords {
if _, exists := distances[word][linkedWord]; !exists {
distances[word][linkedWord] = 1 // Direct connection
}
for otherWord, distance := range distances[linkedWord] {
if otherWord == word {
continue // Skip self-distance
}
if _, exists := distances[word][otherWord]; !exists {
distances[word][otherWord] = distance + 1 // Update distance
} else {
// If the distance is shorter, update it
if distance+1 < distances[word][otherWord] {
distances[word][otherWord] = distance + 1
}
}
}
}
}
return distances
}
// forgiveMeLove generates N random words from the tree
func (m PocketGraph) forgiveMeLove(n int) Words {
if n <= 0 {
@ -477,18 +528,49 @@ func (m PocketGraph) forgiveMeLove(n int) Words {
// Create a slice to hold the random words
randomWords := make(Words, 0, n)
// Generate N random words from the tree
word := m[iWentToYourHouse(m)] // Start with a random word from the tree
for i := 0; i < n-1; i++ {
if len(word) == 0 {
break
// Pick 30% of N words out of the tree at random
numWords := int(float64(n) * 0.3)
for i := 0; i < numWords; i++ {
randomWord := iWentToYourHouse(m)
if randomWord == "" {
continue // Skip if the word is empty
}
random := rand.Intn(len(word))
nextWord := word[random] // Randomly select a word from the current word's linked words
randomWords = append(randomWords, nextWord)
word = m[nextWord] // Update the word to the next linked word
randomWords = append(randomWords, randomWord)
}
// Connect the randomWords together using words that are linked to them, refering to distance
for i := 0; i < len(randomWords) && len(randomWords) <= n; i++ {
if len(randomWords) >= n {
break
}
if len(randomWords[i]) == 0 {
continue // Skip empty words
}
// Get the linked words for the random word
wordDistances := distances[randomWords[i]]
if len(wordDistances) == 0 {
continue // Skip if there are no linked words
}
// do any of the random words link to each other?
for j := 0; j < len(randomWords); j++ {
if i == j || len(randomWords[j]) == 0 {
continue // Skip self or empty words
}
// Check if the random word links to the other random word
if distance, exists := wordDistances[randomWords[j]]; exists && distance > 0 {
// If they are linked, connect them by adding the other random word to the slice
if !slices.Contains(randomWords, randomWords[j]) {
randomWords = append(randomWords, randomWords[j])
}
}
for linkedWord, dist := range distances[randomWords[j]] {
if dist > 0 && !slices.Contains(randomWords, linkedWord) {
randomWords = append(randomWords, linkedWord)
}
}
}
}
return randomWords
}

View File

@ -1,24 +1,22 @@
a
able
about
abvious
adored
advice
afraid
afternoon
again
ah
air
alarmed
alive
All
Alleluia
all
alleluia
along
already
alright
am
ammunition
amount
An
an
and
angry
any
@ -46,17 +44,21 @@ back
back-loaded
backwards
bandage
bath
be
bear
bearer
beat
beautiful
bed
been
before
believe
bell
bend
benefits
best
better
big
bills
biting
@ -79,7 +81,8 @@ broke
brothers
bruises
bug
But
burned
but
by
cab
calm
@ -90,13 +93,14 @@ carry
cars
case
catch
Catholic
Cause
catholic
cause
caution
cds
censor
certainly
chance
Chardonnay
chardonnay
chew
chicken
child
@ -106,16 +110,18 @@ choir
choke
choose
cigarette
ck
clears
cling
close
clothes
coaster
cologne
come
comes
comfort
coming
common
Compared
compared
concept
confessed
conflicts
@ -136,6 +142,7 @@ cry
crying
damn
dance
danced
darkest
day
deadlines
@ -145,8 +152,10 @@ deeds
deeper
deliverance
delusions
den
deny
Did
desk
did
didn't
die
died
@ -157,31 +166,33 @@ direction
dissect
distraction
disturb
Do
Doctor
Does
do
doctor
does
doesn't
doing
don't
door
down
drawer
drawers
dream
dreams
drift
drunk
dry
Duplicity
duplicity
dust
easier
easy
egg
eloquently
else
else's
empty
Enough
enough
envious
Estella
estella
eventually
ever
every
@ -190,19 +201,21 @@ everything's
ex
excellent
excuse
eyes
face
fade
fair
fall
falling
farther
fascinated
fast
Father
father
fault
feel
feelings
feels
Feet
feet
fell
felt
few
@ -226,8 +239,10 @@ food
foot
for
forget
Forgiven
forgive
forgiven
forgot
found
fountain
fractured
free
@ -240,6 +255,7 @@ friends
frightened
from
frustrated
fuck
full
fun
fundamental
@ -274,7 +290,8 @@ gunshot
had
hailing
half
Hand
hall
hand
handle
hands
happy
@ -284,21 +301,22 @@ has
hate
have
haven't
He
he
head
heading
heads
healthy
hear
heart
heights
held
Hello
hello
help
helping
her
Here
Hey
Hidden
here
hey
hidden
high
him
his
@ -306,9 +324,12 @@ hold
holds
hole
holes
home
honest
hope
hopeful
hours
house
how
humble
humbled
@ -317,33 +338,37 @@ hunt
hunter
hurry
hurt
I
I'd
I'll
I'm
I've
i
i'd
i'll
i'm
i've
idol
if
impatient
in
incense
information
inhaling
innocent
inquisition
inside
insist
insistance
insistence
intellectual
intercourse
Ironic
into
ironic
is
isn't
it
It's
it's
its
jagged
jam
Jane
jane
joke
joni
jump
jumping
just
@ -357,7 +382,8 @@ kindred
kissed
knife
knock
Know
know
laid
land
last
late
@ -367,8 +393,9 @@ learn
learned
least
left
Lend
lend
let's
letter
life
light
like
@ -394,8 +421,7 @@ maker
malt
man
many
Mary
mate
mary
matter
matters
may
@ -406,19 +432,20 @@ mean
measure
meet
meeting
Melt
melt
merely
mess
met
middle
midnight
Mind
might
mind
minds
mine
minute
minutes
mispronounced
Miss
miss
moment
money
months
@ -426,10 +453,11 @@ more
mother
motto
mouth
Mr
mr
much
must
My
my
nails
naked
name
nature
@ -443,12 +471,13 @@ ninety-eight
no
not
nothing
noticed
now
obvious
occasion
of
off
Oh
oh
okay
old
older
@ -457,13 +486,13 @@ one
one's
only
open
Or
opened
or
other
Oughta
oughta
our
out
outta
Over
over
overwhelmed
own
packed
@ -477,7 +506,8 @@ patience
peace
peaceful
pedestal
Perfect
perfect
permission
perverted
petrified
piano
@ -487,11 +517,11 @@ pill
pity
place
plane
Play
play-it-safe
played
playing
Please
Pocket
please
pocket
point
poor
pray
@ -503,16 +533,18 @@ problem
proud
prouder
puppet
Push
push
put
question
quickly
quiet
quite
rain
Raising
raising
ran
rational
rays
Really
really
reasons
receive
recommend
@ -526,20 +558,24 @@ resistance
responsible
restless
ride
Right
right
ringing
robe
roller
room
rose
row
ruler
sad
Safe
said
salt
sane
sang
sat
saviors
say
scan
scratch
scream
screw
see
@ -556,7 +592,9 @@ shells
shit
short
should
shouldn't
show
shower
sick
sign
silence
@ -565,8 +603,10 @@ single
sinners
sir
sit
Skeptic
Slap
six
skeptic
slap
smell
smile
smoke
smoking
@ -579,12 +619,14 @@ solely
solitary
some
someday
Someone
someone
something
Sometimes
Son
sometimes
son
soon
sorry
soul
soulmate
sound
speak
speed
@ -593,7 +635,9 @@ spit
spite
splintered
spoons
stairs
stated
stay
sticking
still
stomach
@ -604,10 +648,10 @@ stupid
substitute
suffer
suitcase
Sunday
sunday
sure
surprised
Swallow
swallow
swallowed
sweater
sweeper
@ -623,29 +667,29 @@ tell
ten
than
thank
Thanks
thanks
that
That's
that's
the
theatre
then
there
There's
there's
they
thick
Thing
thing
things
think
thinkin'
thinking
this
thought
thousand
three-year-old
thrill
through
Throw
throw
ticket
Til
til
time
times
tired
@ -662,7 +706,7 @@ trampled
treat
trembling
trucks
Try
try
trying
turned
two
@ -679,15 +723,17 @@ value
version
very
vicarious
Visiting
visiting
voice
void
Wait
wait
waited
Wake
wake
walk
walked
walking
Want
wanna
want
wanted
warm
was
@ -696,7 +742,7 @@ wavelength
way
ways
we
We'll
we'll
wear
wedding
week
@ -704,8 +750,9 @@ weight
well
went
what
What's
what's
when
where
while
whiskey
who
@ -721,25 +768,28 @@ wine
wise
wish
with
without
womb
won
wonder
woo
word
working
Worry
worry
would
would've
wouldn't
wound
wounded
writing
wrong
yeah
yet
you
You'd
you'd
you'll
you're
You've
you've
young
your
yours