-
-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathmain.go
161 lines (134 loc) · 4.14 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
* @Author: Vincent Yang
* @Date: 2024-04-09 03:35:57
* @LastEditors: Vincent Yang
* @LastEditTime: 2024-04-09 20:28:44
* @FilePath: /discord-image/main.go
* @Telegram: https://t.me/missuo
* @GitHub: https://github.com/missuo
*
* Copyright © 2024 by Vincent, All Rights Reserved.
*/
package main
import (
"fmt"
"log"
"net/http"
"os"
"path/filepath"
"regexp"
"strings"
"time"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/missuo/discord-image/bot"
"github.com/spf13/viper"
)
func main() {
// Set default values for configuration
viper.SetDefault("bot.token", "")
viper.SetDefault("bot.channel_id", "")
viper.SetDefault("upload.temp_dir", "uploads")
viper.SetDefault("proxy_url", "")
viper.SetDefault("auto_delete", true)
// Read configuration from environment variables
viper.AutomaticEnv()
viper.BindEnv("bot.token", "BOT_TOKEN")
viper.BindEnv("bot.channel_id", "CHANNEL_ID")
viper.BindEnv("upload.temp_dir", "UPLOAD_DIR")
viper.BindEnv("proxy_url", "PROXY_URL")
viper.BindEnv("auto_delete", "AUTO_DELETE")
// Read configuration from config.yaml if it exists
viper.SetConfigFile("config.yaml")
if err := viper.ReadInConfig(); err == nil {
log.Println("Using config file:", viper.ConfigFileUsed())
}
botToken := viper.GetString("bot.token")
channelID := viper.GetString("bot.channel_id")
uploadDir := viper.GetString("upload.temp_dir")
proxyUrl := viper.GetString("proxy_url")
autoDelete := viper.GetBool("auto_delete")
// Make sure the required configuration values are set
if botToken == "" {
log.Fatal("BOT_TOKEN environment variable or bot.token in config.yaml is not set")
}
if channelID == "" {
log.Fatal("CHANNEL_ID environment variable or bot.channel_id in config.yaml is not set")
}
bot.BotToken = botToken
// Make sure the upload directory exists
if err := os.MkdirAll(uploadDir, os.ModePerm); err != nil {
log.Fatalf("Failed to create upload directory: %v", err)
}
// Start the bot
go bot.Run()
// Create Gin server
gin.SetMode(gin.ReleaseMode)
r := gin.Default()
r.Use(cors.Default())
r.GET("/", func(c *gin.Context) {
c.File("./static/index.html")
})
// Upload image API
r.POST("/upload", func(c *gin.Context) {
host := c.Request.Host
ipPortRegex := regexp.MustCompile(`^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(:\d{1,5})?$`)
var linkPrefix string
if ipPortRegex.MatchString(host) {
linkPrefix = "http://" + host
} else {
linkPrefix = "https://" + host
}
file, err := c.FormFile("image")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Check if the image size exceeds 25MB
if file.Size > 25*1024*1024 {
c.JSON(http.StatusBadRequest, gin.H{"error": "Image size exceeds the maximum limit of 25MB"})
return
}
// Generate a unique filename
ext := filepath.Ext(file.Filename)
filename := fmt.Sprintf("%d_%s%s", time.Now().UnixNano(), uuid.New().String(), ext)
// Save the file to the specified directory
filePath := filepath.Join(uploadDir, filename)
if err := c.SaveUploadedFile(file, filePath); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Trigger the bot to send the image to the group
message, err := bot.SendImage(channelID, filePath)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Delete the uploaded image if auto_delete is true
if autoDelete {
os.Remove(filePath)
}
// Return the URL to access the image
c.JSON(http.StatusOK, gin.H{"url": fmt.Sprintf("%s/file/%s", linkPrefix, message.ID)})
})
// API for accessing images
r.GET("/file/:id", func(c *gin.Context) {
messageID := c.Param("id")
// Query the bot to get the image URL
url, err := bot.GetImageURL(channelID, messageID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if proxyUrl != "" {
url = strings.Replace(url, "https://cdn.discordapp.com", "https://"+proxyUrl, 1)
}
// Redirect to the image URL
c.Redirect(http.StatusFound, url)
})
// Start Gin server
if err := r.Run(":8080"); err != nil {
log.Fatal(err)
}
}