git.sophuwu.com > urlshort   
              121
            
             package main

import (
	"encoding/json"
	bolt "go.etcd.io/bbolt"
	"math/rand"
	"net/http"
	"os"
	"strings"
	"time"
)

var urlDB *bolt.DB
var wordList []string

type urlStruc struct {
	isCustom bool
	creator  string
	date     time.Time
	path     string
	url      string
	uses     int
}

func fec(err error) { // fatal error check
	if err != nil {
		println(err.Error())
		urlDB.Close()
		os.Exit(1)
	}
}

func openFiles() {
	b, err := os.ReadFile("wordlist")
	fec(err)
	if len(b) == 0 {
		println("wordlist is empty")
		os.Exit(1)
	}
	wordList = strings.Split(string(b), "\n")

	var db *bolt.DB
	db, err = bolt.Open("urls.db", 0600, nil)
	fec(err)
	fec(db.Update(func(tx *bolt.Tx) error {
		_, err = tx.CreateBucketIfNotExists([]byte("urls"))
		return err
	}))
	urlDB = db
}

func getWords() string {
	word := func() string {
		return wordList[rand.Intn(len(wordList))]
	}
	return word() + "-" + word() + "-" + word()
}

func readURL(words string) (urlStruc, error) {
	var url urlStruc
	var err error
	err = urlDB.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("urls"))
		return json.Unmarshal(b.Get([]byte(words)), &url)
	})
	return url, err
}

func checkURL(words string) bool {
	url, err := readURL(words)
	if err == nil && url.url != "" {
		return true
	}
	return false
}

func writeURL(url urlStruc) error {
	jsonUrl, err := json.Marshal(url)
	if err != nil {
		return err
	}
	return urlDB.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("urls"))
		return b.Put([]byte(url.path), jsonUrl)
	})
}

func http404(w http.ResponseWriter) {
	w.WriteHeader(404)
	b, err := os.ReadFile("404.html")
	if err != nil {
		b = []byte("404 not found")
		w.Header().Set("Content-Type", "text/plain")
	} else {
		w.Header().Set("Content-Type", "text/html")
	}
	w.Write(b)
}

func httpHandler(w http.ResponseWriter, r *http.Request) {
	if len(r.URL.Path) > 1 {
		path := strings.TrimSuffix(r.URL.Path[1:], "/")
		var info bool = false
		if strings.HasSuffix(path, "/info") {
			info = true
			path = strings.TrimSuffix(path, "/info")
		}
		url, err := readURL(path)
		if url != "" {
			http.Redirect(w, r, url, http.StatusFound)
			return
		}
		http.Error(w, "404 not found", http.StatusNotFound)
		return
	}
}

func main() {
	openFiles()

}