This repository has been archived by the owner on Jan 21, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
454 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
version: "3.9" | ||
|
||
services: | ||
redis: | ||
image: redis | ||
ports: | ||
- "6379:6379" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
module github.com/hitsapp/api | ||
|
||
go 1.21.3 | ||
|
||
require ( | ||
github.com/gofiber/fiber/v2 v2.49.2 | ||
github.com/redis/go-redis/v9 v9.2.1 | ||
) | ||
|
||
require ( | ||
github.com/andybalholm/brotli v1.0.5 // indirect | ||
github.com/cespare/xxhash/v2 v2.2.0 // indirect | ||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect | ||
github.com/google/uuid v1.3.1 // indirect | ||
github.com/klauspost/compress v1.16.7 // indirect | ||
github.com/mattn/go-colorable v0.1.13 // indirect | ||
github.com/mattn/go-isatty v0.0.19 // indirect | ||
github.com/mattn/go-runewidth v0.0.15 // indirect | ||
github.com/philhofer/fwd v1.1.2 // indirect | ||
github.com/rivo/uniseg v0.2.0 // indirect | ||
github.com/tinylib/msgp v1.1.8 // indirect | ||
github.com/valyala/bytebufferpool v1.0.0 // indirect | ||
github.com/valyala/fasthttp v1.49.0 // indirect | ||
github.com/valyala/fasttemplate v1.2.2 // indirect | ||
github.com/valyala/tcplisten v1.0.0 // indirect | ||
golang.org/x/sys v0.12.0 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= | ||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= | ||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= | ||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | ||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= | ||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= | ||
github.com/gofiber/fiber/v2 v2.49.2 h1:ONEN3/Vc+dUCxxDgZZwpqvhISgHqb+bu+isBiEyKEQs= | ||
github.com/gofiber/fiber/v2 v2.49.2/go.mod h1:gNsKnyrmfEWFpJxQAV0qvW6l70K1dZGno12oLtukcts= | ||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= | ||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= | ||
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= | ||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= | ||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= | ||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= | ||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= | ||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= | ||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= | ||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= | ||
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= | ||
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= | ||
github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= | ||
github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= | ||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= | ||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= | ||
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= | ||
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= | ||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= | ||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= | ||
github.com/valyala/fasthttp v1.49.0 h1:9FdvCpmxB74LH4dPb7IJ1cOSsluR07XG3I1txXWwJpE= | ||
github.com/valyala/fasthttp v1.49.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= | ||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= | ||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= | ||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= | ||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= | ||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= | ||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= | ||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= | ||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= | ||
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= | ||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= | ||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | ||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= | ||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | ||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= | ||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= | ||
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= | ||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package main | ||
|
||
import ( | ||
"log" | ||
"os" | ||
|
||
"github.com/gofiber/fiber/v2" | ||
"github.com/gofiber/fiber/v2/middleware/cors" | ||
"github.com/gofiber/fiber/v2/middleware/logger" | ||
"github.com/gofiber/fiber/v2/middleware/recover" | ||
"github.com/hitsapp/api/utils" | ||
v1 "github.com/hitsapp/api/v1" | ||
) | ||
|
||
func main() { | ||
app := fiber.New(fiber.Config{ | ||
CaseSensitive: false, | ||
StrictRouting: true, | ||
ServerHeader: "hits", | ||
BodyLimit: 1024 * 1024, | ||
GETOnly: true, | ||
ProxyHeader: os.Getenv("PROXY_HEADER"), | ||
}) | ||
|
||
app.Use(logger.New()) | ||
app.Use(recover.New()) | ||
app.Use(cors.New(cors.Config{ | ||
AllowOrigins: "*", | ||
})) | ||
|
||
utils.ConnectRedis() | ||
|
||
app.Get("/", func(c *fiber.Ctx) error { | ||
return c.JSON(fiber.Map{ | ||
"success": true, | ||
"message": "sponsored by https://hop.io", | ||
}) | ||
}) | ||
|
||
v1Group := app.Group("/v1") | ||
v1Group.Get("/leaderboard", utils.RateLimit(50), v1.Leaderboard) | ||
v1Group.Get("/hits", utils.RateLimit(1200), v1.Hits) | ||
|
||
log.Fatal(app.Listen(":8080")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
exit status 2exit status 2exit status 2exit status 2exit status 0xc000013aexit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 0xc000013aexit status 1exit status 1exit status 1exit status 0xc000013a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package utils | ||
|
||
import ( | ||
"io" | ||
|
||
"github.com/valyala/bytebufferpool" | ||
"github.com/valyala/fasttemplate" | ||
) | ||
|
||
var badgeSVG = Trim(` | ||
<svg | ||
xmlns="http://www.w3.org/2000/svg" | ||
xmlns:xlink="http://www.w3.org/1999/xlink" width="{{rectWidth}}" height="20" role="img" aria-label="{{label}}: {{count}} hits"> | ||
<title>{{label}}: {{count}} hits</title> | ||
<linearGradient id="s" x2="0" y2="100%"> | ||
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/> | ||
<stop offset="1" stop-opacity=".1"/> | ||
</linearGradient> | ||
<clipPath id="r"> | ||
<rect width="100" height="20" rx="{{border}}" fill="#fff"/> | ||
</clipPath> | ||
<g clip-path="url(#r)"> | ||
<rect width="38" height="20" fill="{{leftBgColor}}"/> | ||
<rect x="38" width="62" height="20" fill="{{rightBgColor}}"/> | ||
<rect width="{{rectWidth}}" height="20" fill="url(#s)"/> | ||
</g> | ||
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" font-size="110"> | ||
<text x="195" y="140" transform="scale(.1)" fill="{{color}}">{{label}}</text> | ||
<text x="695" y="140" transform="scale(.1)" fill="{{color}}">{{count}}</text> | ||
</g> | ||
</svg> | ||
`) | ||
|
||
func GenerateBadge(label, count, color, leftBgColor, rightBgColor, border string) (badge []byte) { | ||
const rectWidth = "150" | ||
var tmpl = fasttemplate.New(badgeSVG, "{{", "}}") | ||
buf := bytebufferpool.Get() | ||
|
||
if border == "square" { | ||
border = "0" | ||
} else { | ||
border = "3" | ||
} | ||
|
||
if label == "" { | ||
label = "hits" | ||
} | ||
|
||
_, _ = tmpl.ExecuteFunc(buf, func(w io.Writer, tag string) (int, error) { | ||
switch tag { | ||
case "label": | ||
return buf.WriteString(label) | ||
case "count": | ||
return buf.WriteString(count) | ||
case "color": | ||
return buf.WriteString(color) | ||
case "leftBgColor": | ||
return buf.WriteString(leftBgColor) | ||
case "rightBgColor": | ||
return buf.WriteString(rightBgColor) | ||
case "rectWidth": | ||
return buf.WriteString(rectWidth) | ||
case "border": | ||
return buf.WriteString(border) | ||
} | ||
return 0, nil | ||
}) | ||
badge = buf.Bytes() | ||
bytebufferpool.Put(buf) | ||
return badge | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package utils | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/gofiber/fiber/v2" | ||
"github.com/gofiber/fiber/v2/middleware/limiter" | ||
) | ||
|
||
func RateLimit(amount int) fiber.Handler { | ||
return limiter.New(limiter.Config{ | ||
Next: func(c *fiber.Ctx) bool { | ||
return c.IP() == "127.0.0.1" || c.IP() == "localhost" | ||
}, | ||
Max: amount, | ||
Expiration: 1 * time.Minute, | ||
KeyGenerator: func(c *fiber.Ctx) string { | ||
return c.IP() | ||
}, | ||
LimitReached: func(c *fiber.Ctx) error { | ||
return c.Status(429).JSON(Response[*any]{ | ||
Success: false, | ||
Error: &Error{ | ||
Code: "rate_limit_reached", | ||
Message: "You have reached the rate limit, please try again in one minute", | ||
}, | ||
}) | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package utils | ||
|
||
import ( | ||
"context" | ||
"os" | ||
"time" | ||
|
||
"github.com/redis/go-redis/v9" | ||
) | ||
|
||
var RedisClient *redis.Client | ||
|
||
func ConnectRedis() { | ||
RedisClient = redis.NewClient(&redis.Options{ | ||
Addr: os.Getenv("REDIS_URL"), | ||
Password: os.Getenv("REDIS_PASSWORD"), | ||
DB: 0, | ||
}) | ||
|
||
_, err := RedisClient.Ping(context.Background()).Result() | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func GetKey(key string) string { | ||
return RedisClient.Get(context.Background(), key).Val() | ||
} | ||
|
||
func AddKey(key string, value string, expiration int) { | ||
RedisClient.Set(context.Background(), key, value, 0).Val() | ||
RedisClient.Expire(context.Background(), key, time.Duration(time.Second*time.Duration(expiration))).Val() | ||
} | ||
|
||
func GetHit(url string) float64 { | ||
return RedisClient.ZScore(context.Background(), "hits", url).Val() | ||
} | ||
|
||
func GetHits(limit int64) []redis.Z { | ||
return RedisClient.ZRevRangeWithScores(context.Background(), "hits", 0, limit).Val() | ||
} | ||
|
||
func AddHit(url string) { | ||
RedisClient.ZAdd(context.Background(), "hits", redis.Z{ | ||
Score: 1, | ||
Member: url, | ||
}) | ||
} | ||
|
||
func IncrementHit(url string) { | ||
RedisClient.ZIncrBy(context.Background(), "hits", 1, url) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package utils | ||
|
||
import ( | ||
"fmt" | ||
"regexp" | ||
"strings" | ||
) | ||
|
||
func Trim(str string) string { | ||
trimmed := strings.TrimSpace(regexp.MustCompile(`\s+`).ReplaceAllString(str, " ")) | ||
trimmed = strings.Replace(trimmed, " <", "<", -1) | ||
trimmed = strings.Replace(trimmed, "> ", ">", -1) | ||
return trimmed | ||
} | ||
|
||
func TransformToHex(text string) string { | ||
var output = fmt.Sprintf("#%s", strings.Trim(text, "\"")) | ||
return output | ||
} | ||
|
||
func TrimQuotes(text string) string { | ||
return strings.Trim(text, "\"") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package utils | ||
|
||
type Response[T any] struct { | ||
Success bool `json:"success"` | ||
Message string `json:"message,omitempty"` | ||
Error *Error `json:"error,omitempty"` | ||
Data T `json:"data,omitempty"` | ||
} | ||
|
||
type Error struct { | ||
Code string `json:"code"` | ||
Message string `json:"message"` | ||
} | ||
|
||
type Leaderboard struct { | ||
URL string `json:"url"` | ||
Hits int `json:"hits"` | ||
} |
Oops, something went wrong.