added caching (not updating yet)

This commit is contained in:
Yannik
2023-08-29 12:44:29 +02:00
parent aa486d39c9
commit 0686fad440
4 changed files with 128 additions and 53 deletions

View File

@@ -3,10 +3,12 @@ package main
import (
"encoding/json"
"io"
"io/ioutil"
"net/http"
"os"
"strconv"
"strings"
"sync"
"time"
"github.com/gin-gonic/gin"
@@ -23,6 +25,45 @@ type User struct {
BannerColor string `json:"banner_color"`
}
var cacheMutex sync.Mutex
const cacheFilePath = "user_cache.json"
func readCacheFile() (map[string]User, error) {
cacheMutex.Lock()
defer cacheMutex.Unlock()
data, err := ioutil.ReadFile(cacheFilePath)
if err != nil {
return nil, err
}
var cacheData map[string]User
err = json.Unmarshal(data, &cacheData)
if err != nil {
return nil, err
}
return cacheData, nil
}
func writeCacheFile(cacheData map[string]User) error {
cacheMutex.Lock()
defer cacheMutex.Unlock()
data, err := json.Marshal(cacheData)
if err != nil {
return err
}
err = ioutil.WriteFile(cacheFilePath, data, 0644)
if err != nil {
return err
}
return nil
}
func main() {
r := gin.Default()
r.GET("/:userIDs", func(c *gin.Context) {
@@ -33,71 +74,93 @@ func main() {
return
}
// Load cached data if available
userResponses := make(map[string]User)
cacheData, err := readCacheFile()
if err == nil {
userResponses = cacheData
}
godotenv.Load()
botToken := os.Getenv("BOT_TOKEN")
client := &http.Client{}
userResponses := make(map[string]User)
for _, userID := range userIDs {
for {
req, err := http.NewRequest("GET", "https://discord.com/api/v10/users/"+userID, nil)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
req.Header.Add("Authorization", "Bot "+botToken)
req.Header.Add("Content-Type", "application/json")
res, err := client.Do(req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
defer res.Body.Close()
if res.StatusCode == http.StatusTooManyRequests {
retryAfter := parseRetryAfterHeader(res.Header)
if retryAfter > 0 {
time.Sleep(retryAfter)
continue // Retry the request after waiting
if cachedUser, found := userResponses[userID]; found {
userResponses[userID] = cachedUser
} else {
for {
req, err := http.NewRequest("GET", "https://discord.com/api/v10/users/"+userID, nil)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
}
req.Header.Add("Authorization", "Bot "+botToken)
req.Header.Add("Content-Type", "application/json")
body, err := io.ReadAll(res.Body)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
res, err := client.Do(req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
defer res.Body.Close()
var jsonMap map[string]interface{}
if err := json.Unmarshal(body, &jsonMap); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if res.StatusCode == http.StatusTooManyRequests {
retryAfter := parseRetryAfterHeader(res.Header)
if retryAfter > 0 {
time.Sleep(retryAfter)
continue // Retry the request after waiting
}
}
user := User{
GlobalName: getStringFromMap(jsonMap, "global_name"),
PublicFlags: getIntFromMap(jsonMap, "public_flags"),
Flags: getIntFromMap(jsonMap, "flags"),
AccentColor: getStringFromMap(jsonMap, "accent_color"),
BannerColor: getStringFromMap(jsonMap, "banner_color"),
}
body, err := io.ReadAll(res.Body)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if avatarDecoration, ok := jsonMap["avatar_decoration"].(string); ok {
user.AvatarDecorationURL = "https://cdn.discordapp.com/avatar-decorations/" + userID + "/" + avatarDecoration + ".png"
}
var jsonMap map[string]interface{}
if err := json.Unmarshal(body, &jsonMap); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if banner, ok := jsonMap["banner"].(string); ok {
user.BannerURL = "https://cdn.discordapp.com/banners/" + userID + "/" + banner + ".png"
}
user := User{
GlobalName: getStringFromMap(jsonMap, "global_name"),
PublicFlags: getIntFromMap(jsonMap, "public_flags"),
Flags: getIntFromMap(jsonMap, "flags"),
AccentColor: getStringFromMap(jsonMap, "accent_color"),
BannerColor: getStringFromMap(jsonMap, "banner_color"),
}
userResponses[userID] = user
break // Exit the loop and process the next user ID
if avatarDecoration, ok := jsonMap["avatar_decoration"].(string); ok {
user.AvatarDecorationURL = "https://cdn.discordapp.com/avatar-decorations/" + userID + "/" + avatarDecoration + ".png"
}
if banner, ok := jsonMap["banner"].(string); ok {
user.BannerURL = "https://cdn.discordapp.com/banners/" + userID + "/" + banner + ".png"
}
userResponses[userID] = user
break // Exit the loop and process the next user ID
}
}
}
c.JSON(http.StatusOK, userResponses)
// Save the cache data to file
err = writeCacheFile(userResponses)
if err != nil {
// Handle error
}
responseData := make(map[string]User)
for _, userID := range userIDs {
if user, found := userResponses[userID]; found {
responseData[userID] = user
}
}
c.JSON(http.StatusOK, responseData)
})
r.GET("/", func(c *gin.Context) {