diff --git a/.gitea/ISSUE_TEMPLATE/bug_report.md b/.gitea/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..742ebc5
--- /dev/null
+++ b/.gitea/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,46 @@
+---
+name: Bug report
+about: Create a bug report to help us improve Invidious
+title: "[Bug] "
+labels: bug
+assignees: ""
+---
+
+
+
+### Describe the bug
+
+
+
+### Steps to Reproduce
+
+
+
+### Logs
+
+
+
+### Screenshots
+
+
+
+### Additional context
+
+
diff --git a/.gitea/ISSUE_TEMPLATE/enhancement.md b/.gitea/ISSUE_TEMPLATE/enhancement.md
new file mode 100644
index 0000000..9c6bcbf
--- /dev/null
+++ b/.gitea/ISSUE_TEMPLATE/enhancement.md
@@ -0,0 +1,27 @@
+---
+name: Enhancement
+about: Suggest an enhancement for an existing feature
+title: "[Enhancement] "
+labels: enhancement
+assignees: ""
+---
+
+
+
+
+
+### Is your enhancement request related to a problem? Please describe.
+
+
+
+### Describe the solution you'd like
+
+
+
+### Describe alternatives you've considered
+
+
+
+### Additional context
+
+
diff --git a/.gitea/ISSUE_TEMPLATE/feature_request.md b/.gitea/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..035f2d6
--- /dev/null
+++ b/.gitea/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,27 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: "[Feature request] "
+labels: feature
+assignees: ""
+---
+
+
+
+
+
+### Is your feature request related to a problem? Please describe.
+
+
+
+### Describe the solution you'd like
+
+
+
+### Describe alternatives you've considered
+
+
+
+### Additional context
+
+
diff --git a/.gitea/ISSUE_TEMPLATE/instance.yml b/.gitea/ISSUE_TEMPLATE/instance.yml
index a96f3a6..60cf08d 100644
--- a/.gitea/ISSUE_TEMPLATE/instance.yml
+++ b/.gitea/ISSUE_TEMPLATE/instance.yml
@@ -48,4 +48,9 @@ body:
label: Contact details
description: Input your contact information should we need to contact you privately. We recommend Matrix. If you don't have a contact method, or don't want your contact method public, tell us.
placeholder: "@foo:example.org"
-
\ No newline at end of file
+ - type: checkboxes
+ attributes:
+ label: Instance Rules
+ description: I have read and accepted the [instance rules](https://codeberg.org/gothub/gothub#instance-rules)
+ options:
+ - label: I have read and accepted the instance rules
diff --git a/Dockerfile b/Dockerfile
index 5321429..6fc8ccd 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -5,6 +5,7 @@ ARG TARGETARCH
WORKDIR /src
RUN apk --no-cache add git
RUN git clone https://codeberg.org/gothub/gothub .
+RUN git checkout master
RUN go mod download
RUN GOOS=linux GOARCH=$TARGETARCH go build -o /src/gothub -ldflags="-X codeberg.org/gothub/gothub/utils.Branch=master"
diff --git a/DockerfileDev b/DockerfileDev
index 4ac8748..fec2469 100644
--- a/DockerfileDev
+++ b/DockerfileDev
@@ -5,6 +5,7 @@ ARG TARGETARCH
WORKDIR /src
RUN apk --no-cache add git
RUN git clone https://codeberg.org/gothub/gothub .
+RUN git checkout dev
RUN go mod download
RUN GOOS=linux GOARCH=$TARGETARCH go build -o /src/gothub -ldflags="-X codeberg.org/gothub/gothub/utils.Branch=dev"
diff --git a/README.md b/README.md
index cf3ab0f..58d7c9e 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,15 @@
# GotHub
+**GotHub is looking for new maintainers. If you are interested, please checkout [#131](https://codeberg.org/gothub/gothub/issues/131).**
+
Alternative front-end for GitHub written with Go. (WIP)
-[Matrix](https://matrix.to/#/#gothub:matrix.org)
+[](https://matrix.to/#/#gothub:matrix.org)
[](https://goreportcard.com/report/codeberg.org/gothub/gothub)
[](https://gothub.app)
## Features
+
- Lightweight - for both you and the instance host
- No JavaScript - pure HTML and CSS goodness
- No requests made to GitHub from the client side - they won't even know you made a request!
@@ -17,45 +20,62 @@ Alternative front-end for GitHub written with Go. (WIP)
Tested with PageSpeed Insights. Using ansible/ansible as a test repo.
-| | [GotHub](https://pagespeed.web.dev/analysis/https-gh-dev-odyssey346-dev-ansible-ansible/2430mn1ece?form_factor=mobile) | [GitHub](https://pagespeed.web.dev/analysis/https-github-com-ansible-ansible/maetxu2zat?form_factor=mobile) |
-| -------- | ---------- | ----------- |
-| Performance | 100 | 81 |
-| Requests | 3 | 88 |
-| Resource Size | 8kb | 629kb |
-| Time to Interactive | 0.9s | 2.7s |
+| | [GotHub](https://pagespeed.web.dev/analysis/https-gh-psf-lt-ansible-ansible/6ssup87ipo?form_factor=mobile) | [GitHub](https://pagespeed.web.dev/analysis/https-github-com-ansible-ansible/maetxu2zat?form_factor=mobile) |
+| ------------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
+| Performance | 100 | 81 |
+| Requests | 3 | 88 |
+| Resource Size | 8kb | 629kb |
+| Time to Interactive | 0.9s | 2.7s |
Quite the difference, isn't it?
## Instances
-### Difference between branches
-The ``master`` branch runs on the master branch of GotHub. This means that the instance is running a stable, tested version of GotHub that doesn't get updated as much as ``dev``. Doesn't mean they're bad, though.
-``dev`` instances run on the dev branch of GotHub. This might mean they are more up-to-date than other instances, but at the same time, they might not be (instance admin might not always update their instance, no auto-updates etc.). You can get the latest and greatest straight out of Git, but you could meet on bugs and other nasty things.
-| Link | Cloudflare | Country | ISP | Branch |
-| -------- | ---------- | ----------- | ----- | ----- |
-| [gh.akisblack.dev](https://gh.akisblack.dev) | No | Germany | OVHcloud | master |
-| [gh.odyssey346.dev](https://gh.odyssey346.dev) | No | France | OVHcloud (Trolling Solutions) | master |
-| [gh.phreedom.club](https://gh.phreedom.club) | No | Iceland | Flokinet | master |
-| [gothub.projectsegfau.lt](https://gothub.projectsegfau.lt) | No | GeoDNS (Luxembourg/USA/India) | BuyVM/Digital Ocean/Airtel | master |
-| [gh.riverside.rocks](https://gh.riverside.rocks) | No | USA | Comcast | master |
-| [gh.fascinated.cc](https://gh.fascinated.cc) | Yes | Germany | Contabo | master |
-| [gothub.lunar.icu](https://gothub.lunar.icu) | Yes | Germany | Unesty | master |
-| [gothub.xbdm.fun](https://gothub.xbdm.fun) | Yes | Germany | Hetzner | master |
-| [dev.gh.akisblack.dev](https://dev.gh.akisblack.dev) | No | Germany | OVHcloud | dev |
-| [gh.creller.net](https://gh.creller.net) | No | Scotland | British Telecommunications PLC | dev |
-| [gothub.esmailelbob.xyz](https://gothub.esmailelbob.xyz) | No | Canada | OVHcloud | dev |
-| [gothub.no-logs.com](https://gothub.no-logs.com/) | No | Sweden | Vultr | dev |
-| [gh.dev.odyssey346.dev](https://gh.dev.odyssey346.dev) | No | France | OVHcloud (Trolling Solutions) | dev |
-| [gothub.dev.projectsegfau.lt](https://gothub.dev.projectsegfau.lt) | No | Luxembourg | BuyVM | dev |
+### Difference between branches
+
+The `master` branch runs on the master branch of GotHub. This means that the instance is running a stable, tested version of GotHub that doesn't get updated as much as `dev`. Doesn't mean they're bad, though.
+
+`dev` instances run on the dev branch of GotHub. This might mean they are more up-to-date than other instances, but at the same time, they might not be (instance admin might not always update their instance, no auto-updates etc.). You can get the latest and greatest straight out of Git, but you could meet on bugs and other nasty things.
+| Link | Tor | Cloudflare | Country | ISP | Branch |
+| -------- | -------- | ---------- | ----------- | ----- | ----- |
+| [gh.bloatcat.tk](https://gh.bloatcat.tk) | No | No | Iceland | 1984 | master |
+| [gothub.frontendfriendly.xyz](https://gothub.frontendfriendly.xyz) | No | No | USA | Hetzner | master |
+| [gothub.hyperreal.coffee](https://gh.hyperreal.coffee) | No | No | USA | Linode | master |
+| [gothub.lunar.icu](https://gothub.lunar.icu) | No | No | Germany | Avoro | master |
+| [gothub.no-logs.com](https://gothub.no-logs.com/) | No | No | Sweden | Vultr | master |
+| [g.opnxng.com](https://g.opnxng.com/) | No | No | Singapore | Vultr | master |
+| [gh.owo.si](https://gh.owo.si/) | [Yes](http://gh.pk47sgwhncn5cgidm7bofngmh7lc7ukjdpk5bjwfemmyp27ovl25ikyd.onion/) | No | Germany | Contabo | master |
+| [gothub.projectsegfau.lt](https://gothub.projectsegfau.lt) | [Yes](http://gothub.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion/) | No | GeoDNS (Germany/USA/India) | Avoro/Racknerd/Airtel | master |
+| [gh.whateveritworks.org](https://gh.whateveritworks.org) | No | No | Germany | Hetzner | master |
+| [gothub.r4fo.com](https://gothub.r4fo.com) | [Yes](http://gothub.r4focoma7gu2zdwwcjjad47ysxt634lg73sxmdbkdozanwqslho5ohyd.onion/) | No | Netherlands | Oracle | master |
+| [gothub.dev.projectsegfau.lt](https://gothub.dev.projectsegfau.lt) | [Yes](http://gothub.dev.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion/) | No | India | Airtel | dev |
+| [gh.phreedom.club](https://gh.phreedom.club/) | No | No | Iceland | Flokinet | dev |
+| [gothub.ducks.party](https://gothub.ducks.party) | No | No | Netherlands | Timeweb | dev |
Have an instance you want on the list? Make an issue or PR!
You can find a json-list of the same in [gothub/gothub-instances](https://codeberg.org/gothub/gothub-instances).
+### Instance rules
+
+These are the rules an instance must follow to be in our official instance list.
+
+Most of these rules have been copied from the [invidious project](https://docs.invidious.io/instances).
+
+- Instance MUST have been updated in the last month.
+- Instances using any EXTERNAL DDoS Protection / MITM / Anti-Bot protection MUST be marked as such.
+- Instances MUST NOT use any sort of web analytics
+- Instances MUST NOT serve ads
+- Instances MUST NOT restrict or disallow the access / usage to any natural person (eg. a country's IP range MUST NOT be blocked, access by a natural person MUST NOT be disallowed for arbirary reason) - this rule doesn't apply to juridical persons.
+
+These rules may change at any time, we will inform the current hosters in the list, and give them 2 weeks so they can correct it
+
## Setup
+
See [gothub.app/docs](https://gothub.app/docs) for information about setting up GotHub.
## Scraping
+
GotHub utilizes scraping powered by [Colly](http://go-colly.org/) to retrieve information from GitHub for everything except the explore page. By default, GotHub uses Chrome on Windows 10 as the user agent, but you can change it by setting the `GOTHUB_USER_AGENT` environment variable.
## Funding
@@ -67,8 +87,3 @@ Our domain [gothub.app](https://gothub.app) is funded by the [Project Segfault](
All content shown on a GotHub instance is from GitHub. Any issues with content shown on a GotHub instance need to be reported to GitHub, not the instance host's internet or domain provider.
GitHub is a registered trademark of GitHub, Inc. GotHub is not affiliated with GitHub, Inc.
-
-## Credits
-- [Arya](https://aryak.me) - Main maintainer
-- [Midou](https://midou.dev) - GotHub logo and many parts of the frontend
-- [Odyssey346](https://odyssey346.dev) - Creator and ex-maintainer
diff --git a/cmd/gothub/env.go b/cmd/gothub/env.go
index c286fb3..8c37e6b 100644
--- a/cmd/gothub/env.go
+++ b/cmd/gothub/env.go
@@ -29,6 +29,8 @@ func env() {
} else {
fmt.Println("Docker: false")
}
+ // Proxying
+ fmt.Println("Proxying: " + os.Getenv("GOTHUB_PROXYING_ENABLED"))
// IP logging
fmt.Println("IP logging: " + os.Getenv("GOTHUB_IP_LOGGED"))
// URL request logging
diff --git a/cmd/gothub/setup.go b/cmd/gothub/setup.go
index 08b35e5..734a6e1 100644
--- a/cmd/gothub/setup.go
+++ b/cmd/gothub/setup.go
@@ -29,6 +29,7 @@ type Vars struct {
InstanceCountry string
InstanceProvider string
CloudflareStatus string
+ Proxying string
}
func setup() {
@@ -130,6 +131,16 @@ func setup() {
vars.CloudflareStatus = "false"
}
+ // ask user whether they want proxying enabled
+ fmt.Print("Do you want proxying enabled? (y/n) ")
+ var proxying string
+ fmt.Scanln(&proxying)
+ if proxying == "y" {
+ vars.Proxying = "true"
+ } else {
+ vars.Proxying = "false"
+ }
+
// save to .env file
fmt.Println("Saving environment variables to .env file...")
f, err := os.Create(".env")
@@ -150,7 +161,8 @@ func setup() {
f.WriteString("GOTHUB_INSTANCE_PRIVACY_POLICY=" + vars.PrivacyPolicy + "\n")
f.WriteString("GOTHUB_INSTANCE_COUNTRY=" + vars.InstanceCountry + "\n")
f.WriteString("GOTHUB_INSTANCE_PROVIDER=" + vars.InstanceProvider + "\n")
- f.WriteString("GOTHUB_INSTANCE_CLOUDFLARE=" + vars.CloudflareStatus)
+ f.WriteString("GOTHUB_INSTANCE_CLOUDFLARE=" + vars.CloudflareStatus + "\n")
+ f.WriteString("GOTHUB_PROXYING_ENABLED=" + vars.Proxying)
println("All done! You can now start your GotHub instance with 'gothub serve'.")
println("You can review the environment variables with 'gothub env'.")
diff --git a/compose.yml b/compose.yml
index a64c0db..ae3ec24 100644
--- a/compose.yml
+++ b/compose.yml
@@ -1,7 +1,7 @@
version: "3"
services:
gothub:
- image: codeberg.org/gothub/gothub:latest
+ image: codeberg.org/gothub/gothub:latest # Master branch
# image: codeberg.org/gothub/gothub:dev # Dev branch
restart: unless-stopped
ports:
@@ -9,6 +9,7 @@ services:
environment:
- DOCKER=true
- GOTHUB_SETUP_COMPLETE=false
+ - GOTHUB_PROXYING_ENABLED=true/false
- GOTHUB_IP_LOGGED=true/false
- GOTHUB_REQUEST_URL_LOGGED=true/false
- GOTHUB_USER_AGENT_LOGGED=true/false
@@ -21,4 +22,4 @@ services:
test: wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/version || exit 1
interval: 30s
timeout: 5s
- retries: 2
+ retries: 2
\ No newline at end of file
diff --git a/go.mod b/go.mod
index 1393fe4..9dc1a79 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module codeberg.org/gothub/gothub
-go 1.19
+go 1.20
require (
github.com/alecthomas/chroma/v2 v2.7.0
diff --git a/pages/about.go b/pages/about.go
index e7ce9bd..fde51c4 100644
--- a/pages/about.go
+++ b/pages/about.go
@@ -8,6 +8,7 @@ import (
)
type PrivacyInfo struct {
+ ProxyEnabled string
IPAddr string
ReqURL string
UserAgent string
@@ -24,6 +25,7 @@ type PrivacyInfo struct {
func HandleAbout(c *fiber.Ctx) error {
var privacyInfoArray []PrivacyInfo
privacyInfoArray = append(privacyInfoArray, PrivacyInfo{
+ ProxyEnabled: os.Getenv("GOTHUB_PROXYING_ENABLED"),
IPAddr: os.Getenv("GOTHUB_IP_LOGGED"),
ReqURL: os.Getenv("GOTHUB_REQUEST_URL_LOGGED"),
UserAgent: os.Getenv("GOTHUB_USER_AGENT_LOGGED"),
diff --git a/pages/commit.go b/pages/commit.go
new file mode 100644
index 0000000..c270d8f
--- /dev/null
+++ b/pages/commit.go
@@ -0,0 +1,123 @@
+package pages
+
+import (
+ "bufio"
+ "bytes"
+ "context"
+ htmlfmt "github.com/alecthomas/chroma/v2/formatters/html"
+ "github.com/alecthomas/chroma/v2/lexers"
+ "github.com/alecthomas/chroma/v2/styles"
+ "github.com/carlmjohnson/requests"
+ "github.com/gocolly/colly"
+ "github.com/gofiber/fiber/v2"
+ "html/template"
+ "log"
+ "net/http"
+ "os"
+ "regexp"
+ "strings"
+)
+
+type Commit struct {
+ CommitName string
+ CommitDesc string
+ CommitHashShortened string
+ CommitDate string
+ Commiter []string
+ CommitToBranch string
+ PreviousCommit string
+ Additions int64
+ Deletions int64
+ ChangedFiles int64
+ FullName string
+}
+
+func HandleCommit(c *fiber.Ctx) error {
+ var commitArray []Commit
+
+ resp, statusErr := http.Get("https://github.com/" + c.Params("user") + "/" + c.Params("repo") + "/commit/" + c.Params("commit") + "/")
+ if statusErr != nil {
+ log.Println(statusErr)
+ }
+ if resp.StatusCode == 404 {
+ // I need a better way to do this
+ return c.Status(404).Render("error", fiber.Map{
+ "title": "Error",
+ "error": "Commit" + c.Params("commit") + "not found",
+ })
+ }
+ var file string
+ url := "https://github.com/" + c.Params("user") + "/" + c.Params("repo") + "/commit/" + c.Params("commit") + ".patch"
+ err := requests.
+ URL(url).
+ ToString(&file).
+ Fetch(context.Background())
+ if err != nil {
+ return c.Status(404).Render("error", fiber.Map{
+ "error": err,
+ })
+ }
+ re := regexp.MustCompile("\\A(?s).*?---(?-s).*\\n")
+ file = re.ReplaceAllString(file, "---\n")
+ lexer := lexers.Match("something.diff")
+ if lexer == nil {
+ lexer = lexers.Fallback
+ }
+ formatter := htmlfmt.New(
+ htmlfmt.WithClasses(true),
+ htmlfmt.WithLineNumbers(true),
+ htmlfmt.PreventSurroundingPre(false),
+ )
+
+ buf := bytes.Buffer{}
+ writer := bufio.NewWriter(&buf)
+ style := styles.Get("native")
+ tokens, err := lexer.Tokenise(nil, file)
+ if err != nil {
+ return c.Status(500).Render("error", fiber.Map{
+ "error": err,
+ })
+ }
+ formatter.Format(writer, style, tokens)
+
+ cssbuf := bytes.Buffer{}
+ cssw := bufio.NewWriter(&cssbuf)
+ formatter.WriteCSS(cssw, style)
+ writer.Flush()
+ cssw.Flush()
+
+ // Scraping
+ Scrape := Commit{}
+ UserAgent, ok := os.LookupEnv("GOTHUB_USER_AGENT")
+ if !ok {
+ UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
+ }
+
+ sc := colly.NewCollector(colly.AllowedDomains("github.com"), colly.UserAgent(UserAgent))
+ sc.OnHTML("div.commit", func(e *colly.HTMLElement) {
+ Scrape.CommitName = e.ChildText("div.commit-title")
+ Scrape.CommitDesc = e.ChildText("div.commit-desc pre")
+ Scrape.CommitHashShortened = e.ChildText("div.text-lg-right span.m-0 span.sha")
+ Scrape.PreviousCommit = e.ChildText("div.text-lg-right span.ml-0 a.sha")
+ Scrape.CommitDate = e.ChildText("div.flex-self-start relative-time")
+ Scrape.CommitToBranch = e.ChildText("ul.branches-list li.branch a")
+ e.ForEach("div.flex-self-start .commit-author", func(i int, el *colly.HTMLElement) {
+ Scrape.Commiter = append(Scrape.Commiter, strings.TrimPrefix(el.Attr("title"), "View all commits by "))
+ })
+ })
+ Scrape.FullName = c.Params("user") + "/" + c.Params("repo")
+ sc.Visit("https://github.com/" + c.Params("user") + "/" + c.Params("repo") + "/commit/" + c.Params("commit") + "/")
+ if len(Scrape.PreviousCommit) > 7 {
+ Minus := len(Scrape.PreviousCommit) - 7
+ Scrape.PreviousCommit = Scrape.PreviousCommit[:len(Scrape.PreviousCommit)-Minus]
+ }
+ // Add scrape-based info to commitArray
+ commitArray = append(commitArray, Scrape)
+
+ return c.Render("commit", fiber.Map{
+ "title": "Commit " + Scrape.CommitName + " | " + c.Params("user") + "/" + c.Params("repo"),
+ "commit": commitArray,
+ "file": template.HTML(buf.String()),
+ "css": template.CSS(cssbuf.String()),
+ })
+}
diff --git a/pages/dirview.go b/pages/dirview.go
index baf4c7f..3fbb875 100644
--- a/pages/dirview.go
+++ b/pages/dirview.go
@@ -4,7 +4,8 @@ import (
"log"
"net/http"
"os"
- "strings"
+
+ "github.com/tidwall/gjson"
"codeberg.org/gothub/gothub/utils"
"github.com/gocolly/colly"
@@ -12,21 +13,52 @@ import (
)
type Dir struct {
- Readme string
- Fullname string
- DirName string
- Branch string
+ Readme string
+ Fullname string
+ DirName string
+ Branch string
+// TruncationWarning string
}
+// TODO: Handle repository truncation warning.
+// Example text: "Sorry, we had to truncate this directory to 1,000 files.
+// 718 entries were omitted from the list. Latest commit info may be omitted."
+
type DirFiles struct {
Name string
Path string
Type string
Branch string
Fullname string
- DirName string
}
+// Given a gjson object, as well as branch name and fullname ('user/repository' format),
+// return an array of directory files
+func return_dir_files_array(dirList gjson.Result, branch string, fullname string) []DirFiles {
+ var dirFilesArray []DirFiles
+
+ dirList.ForEach(func(i, e gjson.Result) bool {
+ var FileType string
+ if e.Get("contentType").Str == "directory" {
+ FileType = "dir"
+ } else {
+ FileType = "file"
+ }
+
+ dirFilesArray = append(dirFilesArray, DirFiles{
+ Name: e.Get("name").Str,
+ // Path is the path to the file/folder from the repository root
+ Path: e.Get("path").Str,
+ Type: FileType,
+ Branch: branch,
+ Fullname: fullname,
+ })
+
+ return true //keep iterating
+ })
+ return dirFilesArray
+
+}
func DirView(c *fiber.Ctx) error {
var dirArray []Dir
var dirFilesArray []DirFiles
@@ -40,7 +72,7 @@ func DirView(c *fiber.Ctx) error {
// I need a better way to do this
return c.Status(404).Render("error", fiber.Map{
"title": "Error",
- "error": "Directory" + c.Params("+") + "not found",
+ "error": "Directory " + c.Params("+") + " not found",
})
}
@@ -56,33 +88,21 @@ func DirView(c *fiber.Ctx) error {
}
sc := colly.NewCollector(colly.AllowedDomains("github.com"), colly.UserAgent(UserAgent))
- sc.OnHTML("div#readme", func(e *colly.HTMLElement) {
- Scrape.Readme = e.ChildText("a[href='#readme']")
+
+ sc.OnHTML("react-app script[data-target]", func(e *colly.HTMLElement) {
+ jsonMess := e.Text
+ dirList := gjson.Get(jsonMess, "payload.tree.items")
+ dirFilesArray = return_dir_files_array(dirList, Scrape.Branch, Scrape.Fullname)
})
- sc.OnHTML("div#readme div.Box-body", func(e *colly.HTMLElement) {
- Content, _ := e.DOM.Html()
- readmeOutput = strings.Replace(strings.Replace(strings.Replace(strings.Replace(string(utils.UGCPolicy().SanitizeBytes([]byte(Content))), "https://github.com", "", -1), "user-content-", "", -1), "https://camo.githubusercontent.com", "/camo", -1), "https://raw.githubusercontent.com", "/raw", -1)
- })
- sc.OnHTML("div.js-details-container div.Details-content--hidden-not-important", func(e *colly.HTMLElement) {
- e.ForEach("div.js-navigation-item", func(i int, el *colly.HTMLElement) {
- var FileType string
- if el.ChildAttr("div.flex-shrink-0 svg", "aria-label") == "Directory" {
- FileType = "dir"
- } else {
- FileType = "file"
- }
- if el.ChildText("div.flex-auto span.d-block a.js-navigation-open") != "" {
- dirFilesArray = append(dirFilesArray, DirFiles{
- Name: el.ChildText("div.flex-auto span.d-block a.js-navigation-open"),
- Path: el.ChildText("div.flex-auto span.d-block a.js-navigation-open"),
- Type: FileType,
- Fullname: Scrape.Fullname,
- DirName: Scrape.DirName,
- Branch: Scrape.Branch,
- })
- }
+
+ // Get repository truncation warning. This only works with js enabled, so it does not work with colly
+ /*
+ sc.OnHTML("[data-testid='repo-truncation-warning']", func(e *colly.HTMLElement) {
+ fmt.Printf("Truncation warning: %s", e.Text)
+ Scrape.TruncationWarning = e.Text
})
- })
+ */
+
sc.Visit("https://github.com/" + c.Params("user") + "/" + c.Params("repo") + "/tree/" + c.Params("branch") + "/" + c.Params("+"))
// Add scrape-based info to dirArray
dirArray = append(dirArray, Scrape)
diff --git a/pages/fileview.go b/pages/fileview.go
index 0f46016..320babb 100644
--- a/pages/fileview.go
+++ b/pages/fileview.go
@@ -5,12 +5,15 @@ import (
"bytes"
"codeberg.org/gothub/gothub/utils"
"context"
+ "encoding/base64"
htmlfmt "github.com/alecthomas/chroma/v2/formatters/html"
"github.com/alecthomas/chroma/v2/lexers"
"github.com/alecthomas/chroma/v2/styles"
"github.com/carlmjohnson/requests"
"github.com/gofiber/fiber/v2"
"html/template"
+ "net/http"
+ "path/filepath"
)
// FileView is the file view page
@@ -27,6 +30,35 @@ func FileView(c *fiber.Ctx) error {
})
}
+ ext := filepath.Ext(c.Params("+"))
+ // Make an issue for other formats thanks
+ if ext == ".jpeg" || ext == ".jpg" || ext == ".png" || ext == ".svg" || ext == ".gif" || ext == ".webp" {
+ data := []byte(file)
+ dst := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
+ base64.StdEncoding.Encode(dst, data)
+ dstStr := string(dst)
+ // Detect content-type since base64 encoding needs content-type
+ mimeType := http.DetectContentType(data)
+ if ext == ".svg" {
+ mimeType = "image/svg+xml"
+ }
+ css := `img {
+ object-fit: cover;
+ width: 100%;
+ height: 250px;
+ }`
+ html := "
"
+ return c.Render("file", fiber.Map{
+ "title": c.Params("+") + " | " + c.Params("user") + "/" + c.Params("repo"),
+ "branch": utils.Branch,
+ "file": html,
+ "css": css,
+ "fullname": c.Params("user") + "/" + c.Params("repo"),
+ "name": c.Params("+"),
+ "fileBranch": c.Params("branch"),
+ "type": "img",
+ })
+ }
lexer := lexers.Match(c.Params("+"))
if lexer == nil {
lexer = lexers.Fallback
@@ -64,5 +96,6 @@ func FileView(c *fiber.Ctx) error {
"fullname": c.Params("user") + "/" + c.Params("repo"),
"name": c.Params("+"),
"fileBranch": c.Params("branch"),
+ "type": "code",
})
}
diff --git a/pages/repo.go b/pages/repo.go
index c7dc8d6..f10b0a7 100644
--- a/pages/repo.go
+++ b/pages/repo.go
@@ -6,11 +6,19 @@ import (
"os"
"strings"
+ "github.com/tidwall/gjson"
+
"codeberg.org/gothub/gothub/utils"
"github.com/gocolly/colly"
"github.com/gofiber/fiber/v2"
)
+type Languages struct {
+ Name string
+ Percent string
+ Color string
+}
+
type Repo struct {
Fullname string
Description string
@@ -18,8 +26,9 @@ type Repo struct {
Stars string
Forks string
CommitsBehind string
+ CommitsAhead string
Watchers string
- Language []string
+ Language []Languages
License string
DefaultBranch string
Readme string
@@ -56,7 +65,6 @@ func HandleRepo(c *fiber.Ctx) error {
"error": "Repository " + c.Params("user") + "/" + repoUrl + branchExists + " not found",
})
}
-
// Scraping
Scrape := Repo{}
@@ -79,18 +87,55 @@ func HandleRepo(c *fiber.Ctx) error {
})
})
sc.OnHTML("div.Box-body div.d-flex div span", func(e *colly.HTMLElement) {
- Scrape.CommitsBehind = strings.TrimSuffix(e.ChildText("a"), " commits behind")
+ Scrape.CommitsBehind = strings.TrimSuffix(e.ChildText("a[data-analytics-event*='Behind Compare']"), " commits behind")
+ Scrape.CommitsAhead = strings.TrimSuffix(e.ChildText("a[data-analytics-event*='Ahead Compare']"), " commits ahead")
})
sc.OnHTML("div#readme", func(e *colly.HTMLElement) {
Scrape.Readme = e.ChildText("a[href='#readme']")
})
- sc.OnHTML("div#readme div.Box-body", func(e *colly.HTMLElement) {
- Content, _ := e.DOM.Html()
- readmeOutput = strings.Replace(strings.Replace(strings.Replace(strings.Replace(string(utils.UGCPolicy().SanitizeBytes([]byte(Content))), "https://github.com", "", -1), "user-content-", "", -1), "https://camo.githubusercontent.com", "/camo", -1), "https://raw.githubusercontent.com", "/raw", -1)
+
+ // jq '.props.initialPayload.overview.overviewFiles[]|select(.tabName == "README").richText'
+ sc.OnHTML("div.Layout-main react-partial script", func(e *colly.HTMLElement) {
+ jsonMess := e.Text
+
+ result := gjson.Get(jsonMess, "props.initialPayload.overview.overviewFiles")
+ result.ForEach(func(i, e gjson.Result) bool {
+ if e.Get("tabName").Str == "README" {
+ unsanitizedOutput := e.Get("richText").Str
+ readmeOutput = strings.Replace(strings.Replace(strings.Replace(strings.Replace(strings.Replace(string(utils.UGCPolicy().SanitizeBytes([]byte(unsanitizedOutput))), "https://github.com", "", -1), "user-content-", "", -1), "https://camo.githubusercontent.com", "/camo", -1), "https://raw.githubusercontent.com", "/raw", -1), "https://user-images.githubusercontent.com", "/user-images", -1)
+ return false
+ }
+ return true // keep iterating
+ })
+ result = gjson.Get(jsonMess, "props.initialPayload.tree.items")
+ //jq '.props.initialPayload.tree.items'
+ result.ForEach(func(i, e gjson.Result) bool {
+ var FileType string
+ if e.Get("contentType").Str == "directory" {
+ FileType = "dir"
+ } else {
+ FileType = "file"
+ }
+
+ repoFilesArray = append(repoFilesArray, RepoFiles{
+ Name: e.Get("name").Str,
+ Path: e.Get("path").Str,
+ Type: FileType,
+ DefaultBranch: gjson.Get(jsonMess, "props.initialPayload.repo.defaultBranch").Str,
+ Fullname: Scrape.Fullname,
+ })
+
+ return true //keep iterating
+ })
})
+
sc.OnHTML("div.BorderGrid-cell ul.list-style-none", func(e *colly.HTMLElement) {
e.ForEach("li.d-inline .d-inline-flex", func(i int, el *colly.HTMLElement) {
- Scrape.Language = append(Scrape.Language, el.ChildText("span.text-bold")+" "+el.ChildText("span:contains('%')"))
+ var lang Languages
+ lang.Name = el.ChildText("span.text-bold")
+ lang.Percent = el.ChildText("span:contains('%')")
+ lang.Color = strings.ReplaceAll(strings.ReplaceAll(el.ChildAttr("svg", "style"), "color:", ""), ";", "")
+ Scrape.Language = append(Scrape.Language, lang)
})
})
sc.OnHTML("div#repository-container-header", func(e *colly.HTMLElement) {
@@ -99,24 +144,8 @@ func HandleRepo(c *fiber.Ctx) error {
sc.OnHTML("summary[title*='Switch branches or tags']", func(e *colly.HTMLElement) {
Scrape.DefaultBranch = e.ChildText("span.css-truncate-target")
})
- sc.OnHTML("div.js-details-container div.Details-content--hidden-not-important", func(e *colly.HTMLElement) {
- e.ForEach("div.js-navigation-item", func(i int, el *colly.HTMLElement) {
- var FileType string
- if el.ChildAttr("div.flex-shrink-0 svg", "aria-label") == "Directory" {
- FileType = "dir"
- } else {
- FileType = "file"
- }
- repoFilesArray = append(repoFilesArray, RepoFiles{
- Name: el.ChildText("div.flex-auto span.d-block a.js-navigation-open"),
- Path: el.ChildText("div.flex-auto span.d-block a.js-navigation-open"),
- Type: FileType,
- Fullname: Scrape.Fullname,
- DefaultBranch: Scrape.DefaultBranch,
- })
- })
- })
sc.Visit("https://github.com/" + c.Params("user") + "/" + repoUrl + branchExists)
+
// Add scrape-based info to repoArray
repoArray = append(repoArray, Scrape)
return c.Render("repo", fiber.Map{
diff --git a/pages/user.go b/pages/user.go
index a96b2ce..562f1db 100644
--- a/pages/user.go
+++ b/pages/user.go
@@ -158,6 +158,7 @@ func HandleUser(c *fiber.Ctx) error {
sc.OnHTML("article.markdown-body", func(e *colly.HTMLElement) {
Content, _ := e.DOM.Html()
Scrape.Readme = strings.Replace(strings.Replace(strings.Replace(strings.Replace(string(utils.UGCPolicy().SanitizeBytes([]byte(Content))), "https://github.com", "", -1), "user-content-", "", -1), "https://camo.githubusercontent.com", "/camo", -1), "https://raw.githubusercontent.com", "/raw", -1)
+
})
sc.OnHTML("div.text-mono", func(e *colly.HTMLElement) {
Scrape.ReadmeUrl = strings.Replace(e.ChildAttr("a", "href"), "tree", "blob", -1)
diff --git a/pages/wiki.go b/pages/wiki.go
new file mode 100644
index 0000000..543b500
--- /dev/null
+++ b/pages/wiki.go
@@ -0,0 +1,87 @@
+package pages
+
+import (
+ "codeberg.org/gothub/gothub/utils"
+ "github.com/gocolly/colly"
+ "github.com/gofiber/fiber/v2"
+ "log"
+ "net/http"
+ "os"
+ "regexp"
+ "strings"
+)
+
+type Wiki struct {
+ RepoUser string
+ RepoName string
+ Title string
+ LastEdit string
+ LastEditor string
+ RevisionNum string
+ PageNum string
+ PageContent string
+ Sidebar []Sidebar
+}
+type Sidebar struct {
+ Name string
+ Link string
+}
+
+func WikiView(c *fiber.Ctx) error {
+ var wikiArray []Wiki
+
+ resp, statusErr := http.Get("https://github.com/" + c.Params("user") + "/" + c.Params("repo") + "/wiki/" + c.Params("page"))
+ if statusErr != nil {
+ log.Println(statusErr)
+ }
+ if resp.StatusCode == 404 {
+ // I need a better way to do this
+ return c.Status(404).Render("error", fiber.Map{
+ "title": "Error",
+ "error": "Wiki" + c.Params("page") + "not found",
+ })
+ }
+
+ // Scraping
+ Scrape := Wiki{}
+
+ UserAgent, ok := os.LookupEnv("GOTHUB_USER_AGENT")
+ if !ok {
+ UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
+ }
+
+ sc := colly.NewCollector(colly.AllowedDomains("github.com"), colly.UserAgent(UserAgent))
+ sc.OnHTML("div#repository-container-header", func(e *colly.HTMLElement) {
+ Scrape.RepoUser = e.ChildText("span.author a")
+ Scrape.RepoName = e.ChildText("strong a")
+ })
+ sc.OnHTML("div#wiki-wrapper", func(e *colly.HTMLElement) {
+ Scrape.Title = e.ChildText("div.d-flex h1")
+ Scrape.LastEdit = e.ChildText("div.gh-header-meta relative-time")
+ re := regexp.MustCompile(`\ edited.*`)
+ Scrape.LastEditor = re.ReplaceAllString(strings.Replace(e.ChildText("div.gh-header-meta"), "\n", "", -1), "${1}")
+ Scrape.RevisionNum = strings.TrimSuffix(e.ChildText("a.Link--muted"), " revisions")
+ })
+ sc.OnHTML("div.wiki-pages-box div.Box--condensed", func(e *colly.HTMLElement) {
+ Scrape.PageNum = e.ChildText("span.Counter--primary")
+ e.ForEach("ul.list-style-none li.Box-row", func(i int, el *colly.HTMLElement) {
+ Scrape.Sidebar = append(Scrape.Sidebar, Sidebar{
+ Name: el.ChildText("summary span a.Truncate-text"),
+ Link: el.ChildAttr("summary span a.Truncate-text", "href"),
+ })
+ })
+ })
+ sc.OnHTML("div#wiki-body > div.markdown-body", func(e *colly.HTMLElement) {
+ Content, _ := e.DOM.Html()
+ Scrape.PageContent = strings.Replace(strings.Replace(strings.Replace(strings.Replace(strings.Replace(string(utils.UGCPolicy().SanitizeBytes([]byte(Content))), "https://github.com", "", -1), "user-content-", "", -1), "https://camo.githubusercontent.com", "/camo", -1), "https://raw.githubusercontent.com", "/raw", -1), "https://user-images.githubusercontent.com", "/user-images", -1)
+
+ })
+ sc.Visit("https://github.com/" + c.Params("user") + "/" + c.Params("repo") + "/wiki/" + c.Params("page"))
+ // Add scrape-based info to wikiArray
+ wikiArray = append(wikiArray, Scrape)
+
+ return c.Render("wiki", fiber.Map{
+ "title": "Wiki page " + c.Params("page") + " | " + c.Params("user") + "/" + c.Params("repo"),
+ "wiki": wikiArray,
+ })
+}
diff --git a/public/css/global.css b/public/css/global.css
index b01effb..f89f031 100644
--- a/public/css/global.css
+++ b/public/css/global.css
@@ -6,12 +6,14 @@
--secondary-background: #353535;
--background-darker: #151515;
--accent: #00b7c3;
- --yellow: #8B8000;
+ --yellow: #8b8000;
color-scheme: dark;
}
body {
- font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
+ font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui,
+ helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial,
+ sans-serif;
color: var(--text);
background-color: var(--background-darker);
transition: ease-in-out 0.25s;
@@ -32,6 +34,20 @@ main {
margin: 0 24vw;
}
+.margin-ow {
+ margin: 0 12vw;
+}
+
+pre {
+ overflow: scroll;
+ background: var(--secondary-background);
+ border-radius: 4px;
+ padding: 4px;
+}
+
+#wrap {
+ display: flex;
+}
.navbar {
display: flex;
align-items: center;
@@ -73,7 +89,9 @@ main {
background-color: var(--background);
padding: 8px;
border-radius: 4px;
- font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
+ font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui,
+ helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial,
+ sans-serif;
color: var(--text);
}
@@ -95,7 +113,9 @@ a:hover {
background-color: var(--yellow);
padding: 8px;
border-radius: 4px;
- font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
+ font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui,
+ helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial,
+ sans-serif;
color: var(--text);
}
@@ -111,7 +131,8 @@ a:hover {
/* URI: /explore */
-.explore-card, .user-repo-card {
+.explore-card,
+.user-repo-card {
background-color: var(--background);
padding: 8px;
border-radius: 4px;
@@ -125,7 +146,8 @@ a:hover {
transition: ease-in-out 0.25s;
}
-.explore-card:hover, .user-repo-card:hover {
+.explore-card:hover,
+.user-repo-card:hover {
background-color: var(--secondary-background);
color: var(--text);
}
@@ -147,6 +169,7 @@ a:hover {
margin: 4px;
word-wrap: nowrap;
text-overflow: ellipsis;
+ overflow-wrap: anywhere;
}
.user-profile h2 {
@@ -211,6 +234,20 @@ a:hover {
color: var(--text);
}
+.lang-bar:last-child {
+ margin-bottom: 0;
+}
+
+.lang-bar {
+ width: 100%;
+ display: inherit;
+ height: 10px;
+ border-radius:4px;
+ overflow: hidden; /* To force the corners to be round. */
+ user-select: none; /* Prevent the selection */
+ -webkit-user-select: none; /* Safari specific fix. */
+}
+
/* URI: /:user/:repo */
.button {
background-color: var(--background);
@@ -266,6 +303,23 @@ a:hover {
background-color: var(--secondary-background);
}
+/* Overwrite */
+
+.no-margin {
+ margin: 0;
+}
+
+.no-padding {
+ padding: 0;
+}
+
+.float-right {
+ float: right;
+ display: grid;
+ flex: none;
+ align-self: flex-start;
+}
+
@media screen and (prefers-color-scheme: light) {
:root {
--text: #000;
@@ -293,6 +347,16 @@ a:hover {
margin: 8px;
}
+ #wrap {
+ display: flex;
+ flex-direction: column;
+ }
+
+ .float-right {
+ float: none;
+ display: inline-grid;
+ }
+
.navbar-slogan {
display: none;
}
@@ -312,5 +376,5 @@ a:hover {
}
}
.cl {
- padding-left: 8px
+ padding-left: 8px;
}
diff --git a/serve/serve.go b/serve/serve.go
index 3c0fcdc..d2091ef 100644
--- a/serve/serve.go
+++ b/serve/serve.go
@@ -15,6 +15,8 @@ import (
"github.com/gofiber/fiber/v2/middleware/cache"
"github.com/gofiber/fiber/v2/middleware/compress"
"github.com/gofiber/fiber/v2/middleware/limiter"
+ // For debugging purposes
+ // "github.com/gofiber/fiber/v2/middleware/logger"
"github.com/gofiber/fiber/v2/middleware/recover"
"github.com/gofiber/template/html"
@@ -62,6 +64,10 @@ func Serve(port string) {
app.Use(cache.New(cache.Config{
Expiration: 5 * time.Minute,
}))
+ // For debugging purposes
+ // app.Use(logger.New(logger.Config{
+ // Format: "[${ip}]:${port} ${status} - ${method} ${path} ${queryParams}\n",
+ // }))
app.Use(compress.New(compress.Config{
Level: compress.LevelBestSpeed, // 1
@@ -86,13 +92,21 @@ func Serve(port string) {
MaxAge: 31536000,
}
+ proxying, ok := os.LookupEnv("GOTHUB_PROXYING_ENABLED")
+ if !ok {
+ proxying = "true"
+ }
// add global headers
app.Use(func(c *fiber.Ctx) error {
c.Set("X-Frame-Options", "SAMEORIGIN")
c.Set("X-XSS-Protection", "1; mode=block")
c.Set("X-Content-Type-Options", "nosniff")
c.Set("Referrer-Policy", "no-referrer")
- c.Set("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data; font-src 'self'; script-src 'self'; frame-ancestors 'self'; form-action 'self'; base-uri 'self'; connect-src 'self';")
+ if proxying == "true" {
+ c.Set("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; script-src 'self'; frame-ancestors 'self'; form-action 'self'; base-uri 'self'; connect-src 'self';")
+ } else {
+ c.Set("Content-Security-Policy", "default-src 'self' https://camo.githubusercontent.com https://avatars.githubusercontent.com https://user-images.githubusercontent.com https://github.com https://raw.githubusercontent.com https://gist.github.com; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://user-images.githubusercontent.com https://camo.githubusercontent.com https://avatars.githubusercontent.com https://gist.github.com; font-src 'self'; connect-src 'self' https://user-images.githubusercontent.com https://camo.githubusercontent.com https://avatars.githubusercontent.com https://github.com https://raw.githubusercontent.com https://gist.github.com; frame-ancestors 'self'; form-action 'self'; base-uri 'self'")
+ }
c.Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
return c.Next()
@@ -107,30 +121,98 @@ func Serve(port string) {
app.Get("/explore", ratelimiter, pages.HandleExplore)
app.Get("/:user", pages.HandleUser)
app.Get("/avatar/:id", func(c *fiber.Ctx) error {
- utils.ProxyRequest(c, "https://avatars.githubusercontent.com/u/"+c.Params("id")+"?v=4")
- return nil
+ if proxying == "true" {
+ utils.ProxyRequest(c, "https://avatars.githubusercontent.com/u/"+c.Params("id")+"?v=4")
+ return nil
+ } else {
+ c.Redirect("https://avatars.githubusercontent.com/u/" + c.Params("id") + "?v=4")
+ return nil
+ }
+ })
+ app.Get("/user-images/:id/:img", func(c *fiber.Ctx) error {
+ if proxying == "true" {
+ utils.ProxyRequest(c, "https://user-images.githubusercontent.com/"+c.Params("id")+"/"+c.Params("img")+"?v=4")
+ return nil
+ } else {
+ c.Redirect("https://user-images.githubusercontent.com/" + c.Params("id") + "/" + c.Params("img") + "?v=4")
+ return nil
+ }
})
app.Get("/:user/:repo", pages.HandleRepo)
+ app.Get("/:user/:repo/commit/:commit", pages.HandleCommit)
+ app.Get("/diff/:user/:repo/commit/:commit", func(c *fiber.Ctx) error {
+ if proxying == "true" {
+ utils.ProxyRequest(c, "https://github.com/"+c.Params("user")+"/"+c.Params("repo")+"/commit/"+c.Params("commit")+".diff")
+ return nil
+ } else {
+ c.Redirect("https://github.com/" + c.Params("user") + "/" + c.Params("repo") + "/commit/" + c.Params("commit") + ".diff")
+ return nil
+ }
+ })
+ app.Get("/:user/:repo/info/+", func(c *fiber.Ctx) error {
+ // This is needed but it looks like git doesn't send it. Or maybe i just shouldn't program at midnight
+ param := "?service=git-upload-pack"
+ if proxying == "true" {
+ utils.ProxyRequest(c, "https://github.com/"+c.Params("user")+"/"+c.Params("repo")+".git/info/"+c.Params("+")+param)
+ return nil
+ } else {
+ c.Redirect("https://github.com/" + c.Params("user") + "/" + c.Params("repo") + ".git/info/" + c.Params("+") + param)
+ return nil
+ }
+ })
+ app.Post("/:user/:repo/git-upload-pack", func(c *fiber.Ctx) error {
+ if proxying == "true" {
+ utils.ProxyRequest(c, "https://github.com/"+c.Params("user")+"/"+c.Params("repo")+".git/git-upload-pack")
+ return nil
+ } else {
+ c.Redirect("https://github.com/" + c.Params("user") + "/" + c.Params("repo") + ".git/git-upload-pack")
+ return nil
+ }
+ })
app.Get("/:user/:repo/blob/:branch/+", pages.FileView)
app.Get("/:user/:repo/tree/:branch/+", pages.DirView)
- app.Get("/:user/:repo/tree/:branch", pages.HandleRepo)
- app.Get("/download/:user/:repo/:branch", func(c *fiber.Ctx) error {
- utils.ProxyRequest(c, "https://github.com/"+c.Params("user")+"/"+c.Params("repo")+"/archive/"+c.Params("branch")+".zip")
+ app.Get("/:user/:repo/wiki", func(c *fiber.Ctx) error {
+ c.Redirect("/" + c.Params("user") + "/" + c.Params("repo") + "/wiki/Home")
return nil
})
+ app.Get("/:user/:repo/wiki/:page", pages.WikiView)
+ app.Get("/:user/:repo/tree/:branch", pages.HandleRepo)
+ app.Get("/:user/:repo/archive/:branch", func(c *fiber.Ctx) error {
+ if proxying == "true" {
+ utils.ProxyRequest(c, "https://github.com/"+c.Params("user")+"/"+c.Params("repo")+"/archive/"+c.Params("branch"))
+ return nil
+ } else {
+ c.Redirect("https://github.com/" + c.Params("user") + "/" + c.Params("repo") + "/archive/" + c.Params("branch"))
+ return nil
+ }
+ })
+ app.Get("/raw/:user/:repo/:branch/+", func(c *fiber.Ctx) error {
+ if proxying == "true" {
+ utils.ProxyRequest(c, "https://raw.githubusercontent.com/"+c.Params("user")+"/"+c.Params("repo")+"/"+c.Params("branch")+"/"+c.Params("+"))
+ return nil
+ } else {
+ c.Redirect("https://raw.githubusercontent.com/" + c.Params("user") + "/" + c.Params("repo") + "/" + c.Params("branch") + "/" + c.Params("+"))
+ return nil
+ }
+ })
app.Get("/camo/:p1/:p2", func(c *fiber.Ctx) error {
- utils.ProxyRequest(c, "https://camo.githubusercontent.com/"+c.Params("p1")+"/"+c.Params("p2"))
- return nil
+ if proxying == "true" {
+ utils.ProxyRequest(c, "https://camo.githubusercontent.com/"+c.Params("p1")+"/"+c.Params("p2"))
+ return nil
+ } else {
+ c.Redirect("https://camo.githubusercontent.com/" + c.Params("p1") + "/" + c.Params("p2"))
+ return nil
+ }
})
app.Get("/gist/:user/:gistID", pages.HandleGist)
app.Get("/download/gist/:user/:gistID/:revision", func(c *fiber.Ctx) error {
- utils.ProxyRequest(c, "https://gist.github.com/"+c.Params("user")+"/"+c.Params("gistID")+"/archive/"+c.Params("revision")+".zip")
- return nil
- })
-
- app.Get("/raw/:user/:repo/:branch/:file", func(c *fiber.Ctx) error {
- utils.ProxyRequest(c, "https://raw.githubusercontent.com/"+c.Params("user")+"/"+c.Params("repo")+"/"+c.Params("branch")+"/"+c.Params("file"))
- return nil
+ if proxying == "true" {
+ utils.ProxyRequest(c, "https://gist.github.com/"+c.Params("user")+"/"+c.Params("gistID")+"/archive/"+c.Params("revision")+".zip")
+ return nil
+ } else {
+ c.Redirect("https://gist.github.com/" + c.Params("user") + "/" + c.Params("gistID") + "/archive/" + c.Params("revision") + ".zip")
+ return nil
+ }
})
api := app.Group("/api")
diff --git a/views/about.html b/views/about.html
index abf80a0..fe30323 100644
--- a/views/about.html
+++ b/views/about.html
@@ -10,6 +10,7 @@
If this page isn't filled, please contact your instance's maintainer.
+ - Proxying enabled: {{.ProxyEnabled}}
- IP Address logged: {{.IPAddr}}
- Request URL logged: {{.ReqURL}}
- User Agent logged: {{.UserAgent}}
diff --git a/views/commit.html b/views/commit.html
new file mode 100644
index 0000000..f58f614
--- /dev/null
+++ b/views/commit.html
@@ -0,0 +1,46 @@
+{{ template "header" .}}
+
+
+ {{ if.commit }}
+
+ {{ range $key, $value := .commit}}
+
+
+
+
+
{{.CommitHashShortened}} | {{.CommitName}}
+
Raw
+
+ {{.CommitName}} {{ if .CommitDesc }}
+
{{.CommitDesc}}
+ {{end}}
+
+ Commited on {{.CommitDate}} by {{range .Commiter}}
+ @{{.}}{{ end }}
+
+
+ Previous Commit:
+ {{.PreviousCommit}}
+
+
+ {{end}} {{ .file}} {{ else }}
+ Commit not found
+ That commit doesn't exist.
+ {{ end }}
+
+{{ template "footer" .}}
diff --git a/views/dir.html b/views/dir.html
index 151210f..215895c 100644
--- a/views/dir.html
+++ b/views/dir.html
@@ -1,57 +1,63 @@
{{ template "header" .}}
- {{ if .dir }} {{ range $key, $value := .dir}}
-
-
-
-
{{.Fullname}} | {{.DirName}}
-
- {{end}} {{ if .files}}
-
-
Files
-
-
- {{ range $key, $value := .files}} {{ if eq .Type "dir" }}
- -
- ๐
- {{.Path}}
-
- {{ else }}
- -
- ๐๏ธ
- {{.Path}}
-
- {{ end }} {{ end }}
-
+ {{ if .dir }} {{ range $key, $value := .dir}}
+
-
- {{ end }} {{ if .readme}}
-
- {{ if .dir }} {{ range $key, $value := .dir }}
-
{{.Readme}}
- {{end}} {{end}}
-
{{ unescape .readme}}
-
- {{ end }} {{ else }}
-
Directory not found
-
That directory doesn't exist.
- {{ end }}
+
+
+
{{.Fullname}} | {{.DirName}}
+
+ {{end}}
+
+ {{ if .TruncationWarning }}
+
{{.TruncationWarning}}
+ {{ end }}
+
+ {{ if .files}}
+
+
Files
+
+
+ {{ range $key, $value := .files}} {{ if eq .Type "dir" }}
+ -
+ ๐
+ {{.Name}}
+
+ {{ else }}
+ -
+ ๐๏ธ
+ {{.Name}}
+
+ {{ end }} {{ end }}
+
+
+
+ {{ end }} {{ if .readme}}
+
+ {{ if .dir }} {{ range $key, $value := .dir }}
+
{{.Readme}}
+ {{end}} {{end}}
+
{{ unescape .readme}}
+
+ {{ end }} {{ else }}
+
Directory not found
+
That directory doesn't exist.
+ {{ end }}
{{ template "footer" .}}
diff --git a/views/file.html b/views/file.html
index 75be538..8f7c75d 100644
--- a/views/file.html
+++ b/views/file.html
@@ -9,6 +9,11 @@
white-space: pre-wrap;
word-wrap: break-word;
}
+ div.user-readme img {
+ display: block;
+ width: 100%;
+ height: auto;
+ }
- {{ .file}}
+ {{ if eq .type "img" }} {{ unescape .file }} {{else}} {{ .file }} {{end}}
{{end}}
diff --git a/views/index.html b/views/index.html
index 3171779..37c51e1 100644
--- a/views/index.html
+++ b/views/index.html
@@ -60,6 +60,14 @@
using a VPN if you have to clone a GitHub repository and want to keep
yourself private from them instead.
+ Credits
+
+ Midou36O - designing the GotHub logo
+
+
+ Arya - code contributions and
+ maintainer
+
Info
{{ if eq .version "unknown, please build with Go 1.13+ or use Git"}} GotHub
version: unknown {{ else }} GotHub version:
diff --git a/views/repo.html b/views/repo.html
index 0fb36ae..52bd455 100644
--- a/views/repo.html
+++ b/views/repo.html
@@ -3,7 +3,7 @@
{{ if .repo }} {{ range $key, $value := .repo}}
{{end}} {{ if .files}}
diff --git a/views/user.html b/views/user.html
index 90b6674..3e3f9ae 100644
--- a/views/user.html
+++ b/views/user.html
@@ -74,27 +74,38 @@
{{ end }} {{ if .MainRepos }}
{{.PinOrPopular}} repositories
- {{range .MainRepos}}
-
-
- {{if .ForkOf}} Forked from: {{.ForkOf}}
- {{else}} {{end}} {{if .Desc}} {{if eq .Type "Gist"}}
-
-
{{.Desc}}
+ {{range .MainRepos}} {{ if .ForkOf }}
+
+ {{end}} {{ end }}
{{ end }} {{ end }} {{ else }}
User not found
diff --git a/views/wiki.html b/views/wiki.html
new file mode 100644
index 0000000..ef484a1
--- /dev/null
+++ b/views/wiki.html
@@ -0,0 +1,34 @@
+{{ template "header" .}}
+
+
+
+ {{ if .wiki }} {{ range $key, $value := .wiki}}
+
+
+
{{.Title}}
+
{{.RepoUser}}/{{.RepoName}}
+
+ {{.LastEditor}} edited this page on {{.LastEdit}} ยท {{.RevisionNum}} revisions
+
+
+
+ {{ unescape .PageContent }}
+
+
+
+
{{.PageNum}} pages
+
+ {{ range $key, $value := .Sidebar }}
+
+
{{.Name}}
+ {{end}}
+
+
+
+ {{ end }}
+ {{ else }}
+ Wiki not found
+ That wiki doesn't exist.
+ {{ end }}
+
+{{ template "footer" .}}