package main import ( "context" "log" "os" "github.com/gofiber/fiber/v2" "github.com/gofiber/template/html" "codeberg.org/gothub/gothub/pages" "github.com/gofiber/fiber/v2/middleware/cache" "time" "github.com/gofiber/fiber/v2/middleware/proxy" "github.com/gofiber/fiber/v2/middleware/compress" "github.com/gofiber/fiber/v2/middleware/recover" "github.com/gofiber/fiber/v2/middleware/limiter" "html/template" "github.com/carlmjohnson/requests" ) func main() { engine := html.New("./views", ".html") engine.AddFunc( // add unescape function "unescape", func(s string) template.HTML { return template.HTML(s) }, ) app := fiber.New(fiber.Config{ Views: engine, Prefork: false, AppName: "GotHub", // fucked up way to fix rate limits EnableTrustedProxyCheck: true, TrustedProxies: []string{"0.0.0.0/0"}, ProxyHeader: fiber.HeaderXForwardedFor, ErrorHandler: func(ctx *fiber.Ctx, err error) error { code := fiber.StatusInternalServerError if e, ok := err.(*fiber.Error); ok { code = e.Code } err = ctx.Status(code).Render("error", fiber.Map{ "error": err, }) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString("Internal Server Error") } return nil }, }) app.Use(cache.New(cache.Config{ Expiration: 5 * time.Minute, })) app.Get("/", func(c *fiber.Ctx) error { return c.Render("index", fiber.Map{ "host": c.Hostname(), }) }) app.Use(compress.New(compress.Config{ Level: compress.LevelBestSpeed, // 1 })) app.Use(recover.New()) ratelimiter := limiter.New(limiter.Config{ Max: 5, Expiration: 5 * time.Minute, LimitReached: func(c *fiber.Ctx) error { return c.Status(429).Render("ratelimit_gt", fiber.Map{ "Title": "Rate limit exceeded", }) }, }) app.Static("/css", "./public/css") app.Static("/fonts", "./public/fonts") app.Static("/robots.txt", "./public/robots.txt") app.Static("/favicon.ico", "./public/assets/favicon.ico") app.Static("/logo.svg", "./public/assets/logo.svg") app.Get("/explore", ratelimiter, pages.HandleExplore) app.Get("/:user", ratelimiter, pages.HandleUser) app.Get("/:user/:repo", ratelimiter, pages.HandleRepo) app.Get("/file/:user/:repo/:branch/:file", func(c *fiber.Ctx) error { var file string url := "https://raw.githubusercontent.com/" + c.Params("user") + "/" + c.Params("repo") + "/" + c.Params("branch") + "/" + c.Params("file") err := requests. URL(url). ToString(&file). Fetch(context.Background()) if err != nil { return c.Status(404).Render("error", fiber.Map{ "error": err, }) } return c.Render("file", fiber.Map{ "file": file, "fullname": c.Params("user") + "/" + c.Params("repo"), "name": c.Params("file"), "branch": c.Params("branch"), }) }) app.Get("/avatar/:id", func(c *fiber.Ctx) error { url := "https://avatars.githubusercontent.com/u/" + c.Params("id") + "?v=4" if err := proxy.Do(c, url); err != nil { return err } // Remove Server header from response c.Response().Header.Del(fiber.HeaderServer) return nil }) app.Get("/download/:user/:repo/:branch", ratelimiter, func(c *fiber.Ctx) error { url := "https://github.com/" + c.Params("user") + "/" + c.Params("repo") + "/archive/" + c.Params("branch") + ".zip" if err := proxy.Do(c, url); err != nil { return err } // Remove Server header from response c.Response().Header.Del(fiber.HeaderServer) return nil }) app.Get("/raw/:user/:repo/:branch/:file", ratelimiter, func(c *fiber.Ctx) error { url := "https://raw.githubusercontent.com/" + c.Params("user") + "/" + c.Params("repo") + "/" + c.Params("branch") + "/" + c.Params("file") if err := proxy.Do(c, url); err != nil { return err } // Remove Server header from response c.Response().Header.Del(fiber.HeaderServer) return nil }) val, ok := os.LookupEnv("GOTHUB_PORT") if !ok { val = "3000" } else { log.Println("Using port from env variable") } log.Fatal(app.Listen(":" + val)) }