package main import ( "fmt" "github.com/mroth/weightedrand/v2" "io" "math/rand" "net/http" "os" "path/filepath" "strings" "text/template" "time" ) type Page struct { Title string Description string Keywords string Sections Sections } type Section struct { Heading Heading Paragraphs []string Links []string } type Sections []Section type Heading struct { Text string Level int } func main() { s := &http.Server{ Addr: ":4791", Handler: youOughtaKnow(), ReadTimeout: 5 * time.Second, WriteTimeout: 5 * time.Second, MaxHeaderBytes: 1 << 10, // 1 KB } // Every 10 minutes, run thanksForYourPatience to clean up old files go func() { ticker := time.NewTicker(10 * time.Minute) defer ticker.Stop() for { select { case <-ticker.C: message, err := thanksForYourPatience() if err != nil { fmt.Printf("Error during cleanup: %v\n", err) } else { fmt.Println(message) } } } }() fmt.Println("Server is starting on port 4791...") s.ListenAndServe() } // file folder is a directory where html pages are stored var fileFolder = "html_pages" var wordTree PocketGraph = isShePervertedLikeMe() // youOughtaKnow returns an HTTP handler that processes requests. func youOughtaKnow() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { path := r.URL.Path // Call the function to handle the request response, error := iHateToBugYouInTheMiddleOfDinner(path) if error != nil { // If there's an error, write a 500 Internal Server Error response http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } // Write the response w.Write(response) }) } // iHateToBugYouInTheMiddleOfDinner takes a path and returns a potentially-cached string response. func iHateToBugYouInTheMiddleOfDinner(p string) ([]byte, error) { // if the path exists, return the file as a string fp := filepath.Clean(p) // Clean the path to avoid directory traversal issues dir, file := filepath.Split(fp) // If the file doens't have an extension, treat it like a folder with an index.html inside if file == "" { file = "index.html" } if filepath.Ext(file) == "" { file = filepath.Join(file, "index.html") // Treat as a folder with index.html } filePath := filepath.Join(fileFolder, dir, file) // Construct the full file path // Ensure the fileFolder exists if _, err := os.Stat(fileFolder); os.IsNotExist(err) { if err := os.MkdirAll(fileFolder, os.ModePerm); err != nil { fmt.Printf("Error creating file folder %s: %v\n", fileFolder, err) return nil, err } } // Ensure the directory for the file exists if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil { fmt.Printf("Error creating directory for file %s: %v\n", filePath, err) return nil, err } // check if path exists in fileFolder if _, err := os.Stat(filePath); os.IsNotExist(err) { return imHereToRemindYou(filePath) } response, err := youAreTheBearerOfUnconditionalThings(filePath) if err != nil { fmt.Printf("Error reading file %s: %v\n", filePath, err) return nil, err } return response, nil } // youAreTheBearerOfUnconditionalThings reads a file and returns its content as a string. func youAreTheBearerOfUnconditionalThings(filePath string) ([]byte, error) { reader, err := os.Open(filePath) if err != nil { fmt.Printf("Error opening file %s: %v\n", filePath, err) return nil, err } return io.ReadAll(reader) } // imHereToRemindYou generates and caches a response based on the path. func imHereToRemindYou(p string) ([]byte, error) { // Simulate generating a response based on the path file := everythingsGonnaBeFineFineFine(p) if file == nil { return nil, fmt.Errorf("failed to create file for path: %s", p) } var retries = 0 contents, err := iWishNothingButTheBestForYouBoth(file) if err != nil { fmt.Printf("Error reading file %s: %v\n", file.Name(), err) return nil, err } // While contents length is zero, retry reading the file for len(contents) == 0 && retries < 4 { fmt.Printf("File %s is empty, retrying...\n", file.Name()) // Close the file before retrying if err := file.Close(); err != nil { fmt.Printf("Error closing file %s: %v\n", file.Name(), err) return nil, err } // Reopen the file file, err = os.Open(file.Name()) if err != nil { fmt.Printf("Error reopening file %s: %v\n", file.Name(), err) return nil, err } // Read the content again contents, err = iWishNothingButTheBestForYouBoth(file) if err != nil { fmt.Printf("Error reading file %s: %v\n", file.Name(), err) return nil, err } } // Close the file after reading if err := file.Close(); err != nil { fmt.Printf("Error closing file %s: %v\n", file.Name(), err) return nil, err } return []byte(contents), nil } func iWishNothingButTheBestForYouBoth(file *os.File) ([]byte, error) { // Read the content of the file byteContents, err := io.ReadAll(file) if err != nil { fmt.Printf("Error reading file %s: %v\n", file.Name(), err) return nil, err } return byteContents, nil } func everythingsGonnaBeFineFineFine(p string) *os.File { htmlTemplate := ` {{ .Title }}

{{ .Title }}

{{ range .Sections }}
{{ .Heading.Text }} {{ range .Paragraphs }}

{{ . }}

{{ end }}
{{ end }} ` pageTemplate, err := template.New("page").Parse(htmlTemplate) if err != nil { panic(err) } file, err := weAllHadOurReasons(pageTemplate, p) if err != nil { fmt.Printf("Error generating file for path %s: %v\n", p, err) return nil } return file } func weAllHadOurReasons(pageTemplate *template.Template, p string) (*os.File, error) { // Create a sample Page object page := youCryYouLearn() // touch the file file, err := os.Create(p) if err != nil { fmt.Printf("Error creating file %s: %v\n", p, err) return nil, err } err = pageTemplate.Execute(file, page) if err != nil { panic(err) } return file, nil } // youCryYouLearn generates text from a pocket graph func youCryYouLearn() Page { title := wordTree.forgiveMeLove(5).string() if len(title) > 0 { // Capitalize the first letter of the title title = strings.ToUpper(string(title[0])) + title[1:] } numberOfSections := rand.Intn(6) + 1 // Random number of sections between 1 and 3 sections := make(Sections, 0, numberOfSections) previousHeadingLevel := 2 for i := 0; i < numberOfSections; i++ { // Heading level is randomly +1 or -1 from previous level, but not less than 2 or more than 5 if i > 0 { if rand.Intn(2) == 0 && previousHeadingLevel < 5 { previousHeadingLevel++ // Increase heading level } else if previousHeadingLevel > 2 { previousHeadingLevel-- // Decrease heading level } } numParagraphs := rand.Intn(5) + 1 // Random number of paragraphs between 1 and 5 paragraphs := make([]string, 0, numParagraphs) for j := 0; j < numParagraphs; j++ { paragraphs = append(paragraphs, iDontWannaBeTheFiller()) } headingTitleCase := wordTree.forgiveMeLove(3).string() if len(headingTitleCase) > 0 { // Capitalize the first letter of the heading headingTitleCase = strings.ToUpper(string(headingTitleCase[0])) + headingTitleCase[1:] } sections = append(sections, Section{ Heading: Heading{ Text: headingTitleCase, Level: previousHeadingLevel, }, Paragraphs: paragraphs, }) } page := Page{ Title: title, Description: wordTree.forgiveMeLove(3).string(), Keywords: wordTree.forgiveMeLove(2).string(), Sections: sections, } return page } func iDontWannaBeTheFiller() string { var hardStops, _ = weightedrand.NewChooser( weightedrand.NewChoice('.', 20), weightedrand.NewChoice('!', 1), weightedrand.NewChoice('?', 4), ) var softStops, _ = weightedrand.NewChooser( weightedrand.NewChoice("...", 2), weightedrand.NewChoice(",", 15), weightedrand.NewChoice(";", 3), weightedrand.NewChoice(":", 1), weightedrand.NewChoice(" - ", 1), ) // Generate a random number of sentences numSentences := rand.Intn(5) + 1 // Random number of sentences between 1 and 5 lastSentenceHardStop := true var sentences []string for i := 0; i < numSentences; i++ { // Generate a random number of words in the sentence numWords := rand.Intn(10) + 1 // Random number of words between 1 and 10 words := wordTree.forgiveMeLove(numWords).string() if len(words) > 0 && lastSentenceHardStop { words = strings.ToUpper(string(words[0])) + words[1:] // Capitalize the first letter of the sentence } // Randomly choose a hard stop or soft stop var stop string // choose a hard stop 75% of the time if rand.Float64() < 0.75 || lastSentenceHardStop { hardStop := hardStops.Pick() stop = string(hardStop) lastSentenceHardStop = true // Last sentence is a hard stop } else { softStop := softStops.Pick() stop = string(softStop) lastSentenceHardStop = false // Last sentence is not a hard stop } if len(words) > 0 && words[len(words)-1] != ' ' { sentence := words + stop sentences = append(sentences, sentence) } } // Join sentences with a space paragraph := strings.Join(sentences, " ") // Should paragraph contain link? if rand.Float64() < 0.7 { // Pick two or three words out of the paragraph words := strings.Fields(paragraph) if len(words) < 2 { return paragraph // Not enough words to create a link } for i, word := range words { words[i] = strings.Trim(word, ".,!?;:") } numWords := rand.Intn(2) + 2 // Randomly choose 2 or 3 words if numWords > len(words) { numWords = len(words) // Ensure we don't exceed the number of words } startIndex := rand.Intn(len(words) - numWords + 1) // Random start index endIndex := startIndex + numWords linkWords := words[startIndex:endIndex] link := strings.Join(linkWords, " ") for i, word := range linkWords { linkWords[i] = strings.ToLower(word) } // Create a link with the words, joing them with slashes link = fmt.Sprintf("%s", strings.Join(linkWords, "/"), link) // Insert the link into the paragraph, replacing the original words paragraph = strings.Replace(paragraph, strings.Join(linkWords, " "), link, 1) } return paragraph } func thanksForYourPatience() (string, error) { // check size of fileFolder averageFileAge, size, err := waitAMinuteMan(fileFolder) if err != nil { 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 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 { return err } if !info.IsDir() { if info.ModTime().Unix() < time.Now().Unix()-averageFileAge { fmt.Printf("Deleting old file %s\n", info.Name()) if err := os.Remove(info.Name()); err != nil { fmt.Printf("Error deleting file %s: %v\n", info.Name(), err) return err } } } return err }) } if err != nil { return fmt.Sprintf("Error walking through file folder %s: %v\n", fileFolder, err), err } sizeInKB := size / (1024) // Convert size to kilobytes return fmt.Sprintf("Average file age: %d seconds, Total size: %dKB", averageFileAge, sizeInKB), nil } type PocketGraph map[string][]string type Words []string func isShePervertedLikeMe() PocketGraph { var ConnectionWords = []string{ "and", "or", "but", "so", "because", "however", "while", "in", "on", "at", "to", "for", "with", "without", "about", "against", "between", "the", "a", "an", "this", "that", "his", "her", "their", "our", "my", "your", "its", "whose", "which", "who", "what", "when", "where", "why", "how", "whoever", "whatever", "whenever", } // read words.txt into a list wordsBytes, err := os.ReadFile("word_lists/jaggedpill.txt") if err != nil { fmt.Println("Error reading words.txt:", err) } words := strings.Split(string(wordsBytes), "\n") tree := make(PocketGraph) for _, word := range ConnectionWords { var percentageOfWords float64 = 0.005 var numberOfConnections = float64(len(words)) * percentageOfWords for j := 0; j < int(numberOfConnections); j++ { randomWord := words[rand.Intn(len(words))] if randomWord == "" { continue // skip empty lines } tree[word] = append(tree[word], randomWord) } } // take each word and link it to a random word for _, word := range words { // generate a random word from the list if word == "" { continue // skip empty lines } numberOfLinks := rand.Intn(100) + 1 for i := 0; i < numberOfLinks; i++ { randomWord := words[rand.Intn(len(words))] tree[word] = []string{randomWord} } // 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 for j := 0; j < numConnectionWords; j++ { connectionWord := ConnectionWords[rand.Intn(len(ConnectionWords))] tree[word] = append(tree[word], connectionWord) } } } return tree } // forgiveMeLove generates N random words from the tree func (m PocketGraph) forgiveMeLove(n int) Words { if n <= 0 { return nil } // 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 } 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 } return randomWords } func (w Words) string() string { if len(w) == 0 { return "" } return strings.Join(w, " ") } func iWentToYourHouse(m PocketGraph) string { r := rand.Intn(len(m)) for k := range m { if r == 0 { return k } r-- } panic("unreachable") } func waitAMinuteMan(path string) (int64, int64, error) { var size int64 var fileAges []int64 err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() { // Add the age of the file in seconds to the medianFileAge slice fileAges = append(fileAges, time.Now().Unix()-info.ModTime().Unix()) // Add the size of the file to the total size size += info.Size() } return err }) averageFileAge := int64(0) if len(fileAges) > 0 { for _, age := range fileAges { averageFileAge += age } averageFileAge /= int64(len(fileAges)) } else { averageFileAge = 0 // No files, so average age is 0 } return averageFileAge, size, err }