package main import ( "flag" "fmt" "io" "net/http" "strings" "codeberg.org/rimgo/rimgo/pages" "codeberg.org/rimgo/rimgo/render" "codeberg.org/rimgo/rimgo/static" "codeberg.org/rimgo/rimgo/utils" "codeberg.org/rimgo/rimgo/views" "github.com/joho/godotenv" ) // a handler that returns error if it can't respond type handler func(w http.ResponseWriter, r *http.Request) error func wrapHandler(h handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { err := h(w, r) if err != nil { fmt.Println(err) http.Error(w, http.StatusText(500), 500) } }) } func main() { envPath := flag.String("c", ".env", "Path to env file") godotenv.Load(*envPath) utils.LoadConfig() pages.InitializeApiClient() views := views.GetFiles() static := static.GetFiles() render.Initialize(views) app := http.NewServeMux() app.Handle("GET /static/", http.StripPrefix("/static/", http.FileServerFS(static))) app.Handle("GET /robots.txt", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { file, _ := static.Open("robots.txt") defer file.Close() io.Copy(w, file) })) app.Handle("GET /favicon.ico", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { file, _ := static.Open("favicon/favicon.ico") defer file.Close() io.Copy(w, file) })) app.Handle("GET /{$}", wrapHandler(pages.HandleFrontpage)) // app.Handle("GET /{postID}/embed", wrapHandler(pages.HandleEmbed)) // fix this conflict app.Handle("GET /a/{postID}", wrapHandler(pages.HandlePost)) app.Handle("GET /a/{postID}/embed", wrapHandler(pages.HandleEmbed)) // app.Handle("GET /t/:tag.:type", pages.HandleTagRSS) app.Handle("GET /t/{tag}", wrapHandler(func(w http.ResponseWriter, r *http.Request) error { name, ext := utils.SplitNameExt(r.PathValue("tag")) if ext != "" { r.SetPathValue("tag", name[0:len(name)-1]) r.SetPathValue("type", ext) return pages.HandleTagRSS(w, r) } return pages.HandleTag(w, r) })) app.Handle("GET /t/{tag}/{postID}", wrapHandler(pages.HandlePost)) app.Handle("GET /r/{sub}/{postID}", wrapHandler(pages.HandlePost)) app.Handle("GET /user/{userID}", wrapHandler(func(w http.ResponseWriter, r *http.Request) error { name, ext := utils.SplitNameExt(r.PathValue("userID")) if ext != "" { r.SetPathValue("userID", name[0:len(name)-1]) r.SetPathValue("type", ext) return pages.HandleUserRSS(w, r) } return pages.HandleUser(w, r) })) app.Handle("GET /user/{userID}/favorites", wrapHandler(pages.HandleUserFavorites)) app.Handle("GET /user/{userID}/comments", wrapHandler(pages.HandleUserComments)) app.Handle("GET /user/{userID}/cover", wrapHandler(pages.HandleUserCover)) app.Handle("GET /user/{userID}/avatar", wrapHandler(pages.HandleUserAvatar)) app.Handle("GET /gallery/{postID}", wrapHandler(pages.HandlePost)) app.Handle("GET /gallery/{postID}/embed", wrapHandler(pages.HandleEmbed)) app.Handle("GET /{component}", wrapHandler(func(w http.ResponseWriter, r *http.Request) error { component := r.PathValue("component") switch { case component == "about": return pages.HandleAbout(w, r) case component == "privacy": return pages.HandlePrivacy(w, r) case component == "search": return pages.HandleSearch(w, r) case component == "trending": return pages.HandleTrending(w, r) case strings.HasPrefix(component, "trending."): _, ext := utils.SplitNameExt(component) r.SetPathValue("type", ext) return pages.HandleTrendingRSS(w, r) case strings.HasSuffix(component, ".gifv"): r.SetPathValue("postID", component) return pages.HandleGifv(w, r) case strings.Contains(component, "."): return pages.HandleMedia(w, r) default: r.SetPathValue("postID", component) return pages.HandlePost(w, r) } })) app.Handle("GET /stack/{component}", wrapHandler(pages.HandleMedia)) // matches anything with no more specific route app.Handle("GET /", wrapHandler(func(w http.ResponseWriter, r *http.Request) error { err := render.Render(w, "errors/404", nil) return err })) addr := utils.Config.Addr + ":" + utils.Config.Port fmt.Println("listening on " + addr) err := http.ListenAndServe(addr, app) if err != nil { fmt.Println(err) } }