Repository: AlistGo/alist (language: go)

Issue:
PostgreSQL 数据库支持
### Description of the feature / 需求描述

看到文档里写了支持 PostgreSQL 数据库，但划上了线，应该暂时没支持，希望 Alist 支持这个数据库，这样就可以免费部署在 [Render](https://render.com) 平台了。

### Suggested solution / 实现思路

_No response_

### Additional context / 附件

_No response_


Discussion / hints:
Thanks for opening your first issue here! Be sure to follow the issue template!


Fix patch:
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 11b23fd1ba3..00ea7667f71 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -29,7 +29,7 @@ body:
         Please provide a link to a repo that can reproduce the problem you ran into.
         请提供能复现此问题的链接
     validations:
-      required: false
+      required: true
   - type: textarea
     id: logs
     attributes:
diff --git a/.github/workflows/issue_invalid.yml b/.github/workflows/issue_invalid.yml
new file mode 100644
index 00000000000..1faebadb730
--- /dev/null
+++ b/.github/workflows/issue_invalid.yml
@@ -0,0 +1,25 @@
+name: Issue Invalid
+
+on:
+  issues:
+    types: [labeled]
+
+jobs:
+  create-comment:
+    runs-on: ubuntu-latest
+    if: github.event.label.name == 'invalid'
+    steps:
+      - name: Create comment
+        uses: actions-cool/issues-helper@v2
+        with:
+          actions: 'create-comment'
+          token: ${{ secrets.GITHUB_TOKEN }}
+          issue-number: ${{ github.event.issue.number }}
+          body: |
+            Hello @${{ github.event.issue.user.login }}, your issue is invalid and will be closed.
+            你好 @${{ github.event.issue.user.login }}，你的issue无效，将被关闭。
+      - name: Close issue
+        uses: actions-cool/issues-helper@v2
+        with:
+          actions: 'close-issue'
+          token: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/issue_question.yml b/.github/workflows/issue_question.yml
index d46286fe3de..4f05d58373f 100644
--- a/.github/workflows/issue_question.yml
+++ b/.github/workflows/issue_question.yml
@@ -17,4 +17,4 @@ jobs:
           issue-number: ${{ github.event.issue.number }}
           body: |
             Hello @${{ github.event.issue.user.login }}, please input issue by template and add detail. Issues labeled by `question` will be closed if no activities in 7 days.
-            你好 @${{ github.event.issue.user.login }}，请按照issue模板填写, 并详细说明问题/复现步骤/实现思路或提供更多信息等, 7天内未回复issue自动关闭。
\ No newline at end of file
+            你好 @${{ github.event.issue.user.login }}，请按照issue模板填写, 并详细说明问题/复现步骤/复现链接/实现思路或提供更多信息等, 7天内未回复issue自动关闭。
\ No newline at end of file
diff --git a/bootstrap/setting.go b/bootstrap/setting.go
index f999703ec1e..88f2bb8cb4e 100644
--- a/bootstrap/setting.go
+++ b/bootstrap/setting.go
@@ -73,6 +73,20 @@ func InitSettings() {
 			Description: "text type extensions",
 			Group:       model.FRONT,
 		},
+		{
+			Key:         "audio types",
+			Value:       strings.Join(conf.AudioTypes, ","),
+			Type:        "string",
+			Description: "audio type extensions",
+			Group:       model.FRONT,
+		},
+		{
+			Key:         "video types",
+			Value:       strings.Join(conf.VideoTypes, ","),
+			Type:        "string",
+			Description: "video type extensions",
+			Group:       model.FRONT,
+		},
 		{
 			Key:         "d_proxy types",
 			Value:       strings.Join(conf.DProxyTypes, ","),
diff --git a/drivers/189/driver.go b/drivers/189/driver.go
index c9227dc6628..470fe9b5d62 100644
--- a/drivers/189/driver.go
+++ b/drivers/189/driver.go
@@ -10,6 +10,7 @@ import (
 	log "github.com/sirupsen/logrus"
 	"net/http"
 	"path/filepath"
+	"strings"
 )
 
 type Cloud189 struct{}
@@ -198,6 +199,7 @@ func (driver Cloud189) Link(args base.Args, account *model.Account) (*base.Link,
 	} else {
 		link.Url = resp.FileDownloadUrl
 	}
+	link.Url = strings.Replace(link.Url, "http://", "https://", 1)
 	return &link, nil
 }
 
diff --git a/drivers/189pc/driver.go b/drivers/189pc/driver.go
index 1faf28d4c34..114fe7e9c9e 100644
--- a/drivers/189pc/driver.go
+++ b/drivers/189pc/driver.go
@@ -638,7 +638,7 @@ func (driver Cloud189) uploadPerson(file *model.FileStream, parentFile *model.Fi
 		r.SetQueryParams(clientSuffix())
 		r.SetFormData(map[string]string{
 			"uploadFileId": fmt.Sprint(createUpload.UploadFileId),
-			"opertype":     "1", //5 覆盖
+			"opertype":     "5", //5 覆盖 1 重命名
 			"ResumePolicy": "1",
 			"isLog":        "0",
 		})
diff --git a/drivers/base/driver.go b/drivers/base/driver.go
index b9e3528be64..1fe72cfecc0 100644
--- a/drivers/base/driver.go
+++ b/drivers/base/driver.go
@@ -121,7 +121,7 @@ func GetDrivers() map[string][]Item {
 			{
 				Name:  "down_proxy_url",
 				Label: "down_proxy_url",
-				Type:  TypeString,
+				Type:  TypeText,
 			},
 			{
 				Name:   "extract_folder",
diff --git a/drivers/base/types.go b/drivers/base/types.go
index 5456b80008e..930ed1c6492 100644
--- a/drivers/base/types.go
+++ b/drivers/base/types.go
@@ -21,6 +21,7 @@ const (
 	TypeSelect = "select"
 	TypeBool   = "bool"
 	TypeNumber = "number"
+	TypeText   = "text"
 )
 
 const (
diff --git a/drivers/google/googledrive.go b/drivers/google/googledrive.go
index 4a3bcc6dff2..34b2f4192a9 100644
--- a/drivers/google/googledrive.go
+++ b/drivers/google/googledrive.go
@@ -73,8 +73,8 @@ func (driver GoogleDrive) FormatFile(file *File, account *model.Account) *model.
 		f.Type = utils.GetFileType(filepath.Ext(file.Name))
 	}
 	if file.ThumbnailLink != "" {
-		if account.DownProxyUrl != "" {
-			f.Thumbnail = fmt.Sprintf("%s/%s", account.DownProxyUrl, file.ThumbnailLink)
+		if account.APIProxyUrl != "" {
+			f.Thumbnail = fmt.Sprintf("%s/%s", account.APIProxyUrl, file.ThumbnailLink)
 		} else {
 			f.Thumbnail = file.ThumbnailLink
 		}
diff --git a/model/account.go b/model/account.go
index f8e189110a1..dc44c69ce4e 100644
--- a/model/account.go
+++ b/model/account.go
@@ -159,7 +159,7 @@ func GetAccountById(id uint) (*Account, error) {
 func GetAccountFiles() ([]File, error) {
 	files := make([]File, 0)
 	var accounts []Account
-	if err := conf.DB.Order("`index`").Find(&accounts).Error; err != nil {
+	if err := conf.DB.Order(columnName("index")).Find(&accounts).Error; err != nil {
 		return nil, err
 	}
 	for _, v := range accounts {
@@ -179,7 +179,7 @@ func GetAccountFiles() ([]File, error) {
 
 func GetAccounts() ([]Account, error) {
 	var accounts []Account
-	if err := conf.DB.Order("`index`").Find(&accounts).Error; err != nil {
+	if err := conf.DB.Order(columnName("index")).Find(&accounts).Error; err != nil {
 		return nil, err
 	}
 	return accounts, nil
diff --git a/model/setting.go b/model/setting.go
index 8c9fe8927b9..7cb7e26ca4c 100644
--- a/model/setting.go
+++ b/model/setting.go
@@ -50,7 +50,7 @@ func SaveSetting(item SettingItem) error {
 
 func GetSettingsPublic() ([]SettingItem, error) {
 	var items []SettingItem
-	if err := conf.DB.Where("`access` <> ?", 1).Find(&items).Error; err != nil {
+	if err := conf.DB.Where(fmt.Sprintf("%s <> ?", columnName("access")), 1).Find(&items).Error; err != nil {
 		return nil, err
 	}
 	return items, nil
@@ -58,7 +58,7 @@ func GetSettingsPublic() ([]SettingItem, error) {
 
 func GetSettingsByGroup(group int) ([]SettingItem, error) {
 	var items []SettingItem
-	if err := conf.DB.Where("`group` = ?", group).Find(&items).Error; err != nil {
+	if err := conf.DB.Where(fmt.Sprintf("%s = ?", columnName("group")), group).Find(&items).Error; err != nil {
 		return nil, err
 	}
 	items = append([]SettingItem{Version}, items...)
@@ -82,7 +82,7 @@ func DeleteSetting(key string) error {
 
 func GetSettingByKey(key string) (*SettingItem, error) {
 	var items SettingItem
-	if err := conf.DB.Where("`key` = ?", key).First(&items).Error; err != nil {
+	if err := conf.DB.Where(fmt.Sprintf("%s = ?", columnName("key")), key).First(&items).Error; err != nil {
 		return nil, err
 	}
 	return &items, nil
@@ -93,6 +93,14 @@ func LoadSettings() {
 	if err == nil {
 		conf.TextTypes = strings.Split(textTypes.Value, ",")
 	}
+	audioTypes, err := GetSettingByKey("text types")
+	if err == nil {
+		conf.AudioTypes = strings.Split(audioTypes.Value, ",")
+	}
+	videoTypes, err := GetSettingByKey("text types")
+	if err == nil {
+		conf.VideoTypes = strings.Split(videoTypes.Value, ",")
+	}
 	dProxyTypes, err := GetSettingByKey("d_proxy types")
 	if err == nil {
 		conf.DProxyTypes = strings.Split(dProxyTypes.Value, ",")
diff --git a/model/util.go b/model/util.go
new file mode 100644
index 00000000000..8852ae35276
--- /dev/null
+++ b/model/util.go
@@ -0,0 +1,13 @@
+package model
+
+import (
+	"fmt"
+	"github.com/Xhofe/alist/conf"
+)
+
+func columnName(name string) string {
+	if conf.Conf.Database.Type == "postgres" {
+		return fmt.Sprintf(`"%s"`, name)
+	}
+	return fmt.Sprintf("`%s`", name)
+}
diff --git a/server/controllers/down.go b/server/controllers/down.go
index 2797ad46dfc..1a46183d6cc 100644
--- a/server/controllers/down.go
+++ b/server/controllers/down.go
@@ -7,7 +7,6 @@ import (
 	"github.com/Xhofe/alist/utils"
 	"github.com/gin-gonic/gin"
 	log "github.com/sirupsen/logrus"
-	"path"
 )
 
 func Down(c *gin.Context) {
@@ -19,7 +18,7 @@ func Down(c *gin.Context) {
 		common.ErrorResp(c, err, 500)
 		return
 	}
-	if driver.Config().OnlyProxy || account.Proxy || utils.IsContain(conf.DProxyTypes, path.Ext(rawPath)) {
+	if driver.Config().OnlyProxy || account.Proxy || utils.IsContain(conf.DProxyTypes, utils.Ext(rawPath)) {
 		Proxy(c)
 		return
 	}
diff --git a/server/controllers/path.go b/server/controllers/path.go
index e3db698f9f8..d3cc026c361 100644
--- a/server/controllers/path.go
+++ b/server/controllers/path.go
@@ -11,6 +11,7 @@ import (
 	"github.com/Xhofe/alist/utils"
 	"github.com/gin-gonic/gin"
 	log "github.com/sirupsen/logrus"
+	"strings"
 )
 
 func Pagination(files []model.File, req *common.PathReq) (int, []model.File) {
@@ -119,7 +120,7 @@ func Path(c *gin.Context) {
 		// 对于中转文件或只能中转,将链接修改为中转链接
 		if driver.Config().OnlyProxy || account.Proxy {
 			if account.DownProxyUrl != "" {
-				file.Url = fmt.Sprintf("%s%s?sign=%s", account.DownProxyUrl, req.Path, utils.SignWithToken(file.Name, conf.Token))
+				file.Url = fmt.Sprintf("%s%s?sign=%s", strings.Split(account.DownProxyUrl, "\n")[0], req.Path, utils.SignWithToken(file.Name, conf.Token))
 			} else {
 				file.Url = fmt.Sprintf("//%s/p%s?sign=%s", c.Request.Host, req.Path, utils.SignWithToken(file.Name, conf.Token))
 			}
diff --git a/server/controllers/proxy.go b/server/controllers/proxy.go
index 892bcf37caf..8c47727ab24 100644
--- a/server/controllers/proxy.go
+++ b/server/controllers/proxy.go
@@ -11,6 +11,7 @@ import (
 	"github.com/go-resty/resty/v2"
 	log "github.com/sirupsen/logrus"
 	"path/filepath"
+	"strings"
 )
 
 func Proxy(c *gin.Context) {
@@ -29,7 +30,7 @@ func Proxy(c *gin.Context) {
 	// 4. 开启webdav中转（需要验证sign）
 	if !account.Proxy && !driver.Config().OnlyProxy &&
 		utils.GetFileType(filepath.Ext(rawPath)) != conf.TEXT &&
-		!utils.IsContain(conf.DProxyTypes, filepath.Ext(rawPath)) {
+		!utils.IsContain(conf.DProxyTypes, utils.Ext(rawPath)) {
 		// 只开启了webdav中转，验证sign
 		ok := false
 		if account.WebdavProxy {
@@ -43,7 +44,7 @@ func Proxy(c *gin.Context) {
 	// 中转时有中转机器使用中转机器，若携带标志位则表明不能再走中转机器了
 	if account.DownProxyUrl != "" && c.Query("d") != "1" {
 		name := utils.Base(rawPath)
-		link := fmt.Sprintf("%s%s?sign=%s", account.DownProxyUrl, rawPath, utils.SignWithToken(name, conf.Token))
+		link := fmt.Sprintf("%s%s?sign=%s", strings.Split(account.DownProxyUrl, "\n")[0], rawPath, utils.SignWithToken(name, conf.Token))
 		c.Redirect(302, link)
 		return
 	}
diff --git a/utils/file.go b/utils/file.go
index ce30e3b4b35..2c462969ae1 100644
--- a/utils/file.go
+++ b/utils/file.go
@@ -35,7 +35,7 @@ func GetFileType(ext string) int {
 	if ext == "" {
 		return conf.UNKNOWN
 	}
-	ext = strings.ToLower(strings.TrimLeft(ext, "."))
+	ext = strings.ToLower(strings.TrimPrefix(ext, "."))
 	if IsContain(conf.OfficeTypes, ext) {
 		return conf.OFFICE
 	}
@@ -128,10 +128,6 @@ func Split(p string) (string, string) {
 	return path.Split(p)
 }
 
-// FormatName TODO
-func FormatName(name string) string {
-	name = strings.ReplaceAll(name, "/", " ")
-	name = strings.ReplaceAll(name, "#", " ")
-	name = strings.ReplaceAll(name, "?", " ")
-	return name
+func Ext(name string) string {
+	return strings.TrimPrefix(path.Ext(name), ".")
 }
diff --git a/utils/md5.go b/utils/md5.go
index 2cd85e63cb4..92f9ebc295e 100644
--- a/utils/md5.go
+++ b/utils/md5.go
@@ -13,14 +13,12 @@ func GetSHA1Encode(data string) string {
 	return hex.EncodeToString(h.Sum(nil))
 }
 
-// GetMD5Encode
 func GetMD5Encode(data string) string {
 	h := md5.New()
 	h.Write([]byte(data))
 	return hex.EncodeToString(h.Sum(nil))
 }
 
-// Get16MD5Encode
 func Get16MD5Encode(data string) string {
 	return GetMD5Encode(data)[8:24]
 }


Test patch: