parent
44d6ca487c
commit
faf46745bc
@ -0,0 +1,54 @@
|
|||||||
|
package crontab
|
||||||
|
|
||||||
|
import (
|
||||||
|
model "github.com/HFO4/cloudreve/models"
|
||||||
|
"github.com/HFO4/cloudreve/pkg/cache"
|
||||||
|
"github.com/HFO4/cloudreve/pkg/util"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func garbageCollect() {
|
||||||
|
// 清理打包下载产生的临时文件
|
||||||
|
collectArchiveFile()
|
||||||
|
|
||||||
|
// 清理过期的内置内存缓存
|
||||||
|
if store, ok := cache.Store.(*cache.MemoStore); ok {
|
||||||
|
collectCache(store)
|
||||||
|
}
|
||||||
|
|
||||||
|
util.Log().Info("定时任务 [cron_garbage_collect] 执行完毕")
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectArchiveFile() {
|
||||||
|
// 读取有效期、目录设置
|
||||||
|
tempPath := model.GetSettingByName("temp_path")
|
||||||
|
expires := model.GetIntSetting("download_timeout", 30)
|
||||||
|
|
||||||
|
// 列出文件
|
||||||
|
root := filepath.Join(tempPath, "archive")
|
||||||
|
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if !info.IsDir() &&
|
||||||
|
strings.HasPrefix(filepath.Base(path), "archive_") &&
|
||||||
|
time.Now().Sub(info.ModTime()).Seconds() > float64(expires) {
|
||||||
|
util.Log().Debug("删除过期打包下载临时文件 [%s]", path)
|
||||||
|
// 删除符合条件的文件
|
||||||
|
if err := os.Remove(path); err != nil {
|
||||||
|
util.Log().Debug("临时文件 [%s] 删除失败 , %s", path, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
util.Log().Debug("[定时任务] 无法列取临时打包目录")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectCache(store *cache.MemoStore) {
|
||||||
|
util.Log().Debug("清理内存缓存")
|
||||||
|
store.GarbageCollect()
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package crontab
|
||||||
|
|
||||||
|
import (
|
||||||
|
model "github.com/HFO4/cloudreve/models"
|
||||||
|
"github.com/HFO4/cloudreve/pkg/util"
|
||||||
|
"github.com/robfig/cron/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cron 定时任务
|
||||||
|
var Cron *cron.Cron
|
||||||
|
|
||||||
|
// Reload 重新启动定时任务
|
||||||
|
func Reload() {
|
||||||
|
if Cron != nil {
|
||||||
|
Cron.Stop()
|
||||||
|
}
|
||||||
|
Init()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init 初始化定时任务
|
||||||
|
func Init() {
|
||||||
|
util.Log().Info("初始化定时任务...")
|
||||||
|
// 读取cron日程设置
|
||||||
|
options := model.GetSettingByNames("cron_garbage_collect", "cron_notify_user", "cron_ban_user")
|
||||||
|
Cron := cron.New()
|
||||||
|
for k, v := range options {
|
||||||
|
var handler func()
|
||||||
|
switch k {
|
||||||
|
case "cron_garbage_collect":
|
||||||
|
handler = garbageCollect
|
||||||
|
case "cron_notify_user":
|
||||||
|
handler = notifyExpiredVAS
|
||||||
|
case "cron_ban_user":
|
||||||
|
handler = banOverusedUser
|
||||||
|
default:
|
||||||
|
util.Log().Warning("未知定时任务类型 [%s],跳过", k)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := Cron.AddFunc(v, handler); err != nil {
|
||||||
|
util.Log().Warning("无法启动定时任务 [%s] , %s", k, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
banOverusedUser()
|
||||||
|
Cron.Start()
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
package crontab
|
||||||
|
|
||||||
|
import (
|
||||||
|
model "github.com/HFO4/cloudreve/models"
|
||||||
|
"github.com/HFO4/cloudreve/pkg/email"
|
||||||
|
"github.com/HFO4/cloudreve/pkg/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func notifyExpiredVAS() {
|
||||||
|
checkStoragePack()
|
||||||
|
checkUserGroup()
|
||||||
|
util.Log().Info("定时任务 [cron_notify_user] 执行完毕")
|
||||||
|
}
|
||||||
|
|
||||||
|
// banOverusedUser 封禁超出宽容期的用户
|
||||||
|
func banOverusedUser() {
|
||||||
|
users := model.GetTolerantExpiredUser()
|
||||||
|
for _, user := range users {
|
||||||
|
|
||||||
|
// 清除最后通知日期标记
|
||||||
|
user.ClearNotified()
|
||||||
|
|
||||||
|
// 检查容量是否超额
|
||||||
|
if user.Storage > user.Group.MaxStorage+user.GetAvailablePackSize() {
|
||||||
|
// 封禁用户
|
||||||
|
user.SetStatus(model.OveruseBaned)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkUserGroup 检查已过期用户组
|
||||||
|
func checkUserGroup() {
|
||||||
|
users := model.GetGroupExpiredUsers()
|
||||||
|
for _, user := range users {
|
||||||
|
|
||||||
|
// 将用户回退到初始用户组
|
||||||
|
user.GroupFallback()
|
||||||
|
|
||||||
|
// 重新加载用户
|
||||||
|
user, _ = model.GetUserByID(user.ID)
|
||||||
|
|
||||||
|
// 检查容量是否超额
|
||||||
|
if user.Storage > user.Group.MaxStorage+user.GetAvailablePackSize() {
|
||||||
|
// 如果超额,则通知用户
|
||||||
|
sendNotification(&user, "用户组过期")
|
||||||
|
// 更新最后通知日期
|
||||||
|
user.Notified()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkStoragePack 检查已过期的容量包
|
||||||
|
func checkStoragePack() {
|
||||||
|
packs := model.GetExpiredStoragePack()
|
||||||
|
for _, pack := range packs {
|
||||||
|
|
||||||
|
//找到所属用户
|
||||||
|
user, err := model.GetUserByID(pack.ID)
|
||||||
|
if err != nil {
|
||||||
|
util.Log().Warning("[定时任务] 无法获取用户 [UID=%d] 信息, %s", pack.ID, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查容量是否超额
|
||||||
|
if user.Storage > user.Group.MaxStorage+user.GetAvailablePackSize() {
|
||||||
|
// 如果超额,则通知用户
|
||||||
|
sendNotification(&user, "容量包过期")
|
||||||
|
|
||||||
|
// 删除过期的容量包
|
||||||
|
pack.Delete()
|
||||||
|
|
||||||
|
// 更新最后通知日期
|
||||||
|
user.Notified()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendNotification(user *model.User, reason string) {
|
||||||
|
title, body := email.NewOveruseNotification(user.Nick, reason)
|
||||||
|
if err := email.Send(user.Email, title, body); err != nil {
|
||||||
|
util.Log().Warning("无法发送通知邮件, %s", err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package email
|
||||||
|
|
||||||
|
import model "github.com/HFO4/cloudreve/models"
|
||||||
|
|
||||||
|
// Client 默认的邮件发送客户端
|
||||||
|
var Client Driver
|
||||||
|
|
||||||
|
// Init 初始化
|
||||||
|
func Init() {
|
||||||
|
if Client != nil {
|
||||||
|
Client.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取SMTP设置
|
||||||
|
options := model.GetSettingByNames(
|
||||||
|
"fromName",
|
||||||
|
"fromAdress",
|
||||||
|
"smtpHost",
|
||||||
|
"replyTo",
|
||||||
|
"smtpUser",
|
||||||
|
"smtpPass",
|
||||||
|
)
|
||||||
|
port := model.GetIntSetting("smtpPort", 25)
|
||||||
|
keepAlive := model.GetIntSetting("mail_keepalive", 30)
|
||||||
|
|
||||||
|
client := NewSMTPClient(SMTPConfig{
|
||||||
|
Name: options["fromName"],
|
||||||
|
Address: options["fromAdress"],
|
||||||
|
ReplyTo: options["replyTo"],
|
||||||
|
Host: options["smtpHost"],
|
||||||
|
Port: port,
|
||||||
|
User: options["smtpUser"],
|
||||||
|
Password: options["smtpPass"],
|
||||||
|
Keepalive: keepAlive,
|
||||||
|
})
|
||||||
|
|
||||||
|
Client = client
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package email
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
// Driver 邮件发送驱动
|
||||||
|
type Driver interface {
|
||||||
|
// Close 关闭驱动
|
||||||
|
Close()
|
||||||
|
// Send 发送邮件
|
||||||
|
Send(to, title, body string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrChanNotOpen 邮件队列未开启
|
||||||
|
ErrChanNotOpen = errors.New("邮件队列未开启")
|
||||||
|
// ErrNoActiveDriver 无可用邮件发送服务
|
||||||
|
ErrNoActiveDriver = errors.New("无可用邮件发送服务")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Send 发送邮件
|
||||||
|
func Send(to, title, body string) error {
|
||||||
|
if Client == nil {
|
||||||
|
return ErrNoActiveDriver
|
||||||
|
}
|
||||||
|
|
||||||
|
return Client.Send(to, title, body)
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package email
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
model "github.com/HFO4/cloudreve/models"
|
||||||
|
"github.com/HFO4/cloudreve/pkg/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewOveruseNotification 新建超额提醒邮件
|
||||||
|
func NewOveruseNotification(userName, reason string) (string, string) {
|
||||||
|
options := model.GetSettingByNames("siteName", "siteURL", "siteTitle", "over_used_template")
|
||||||
|
replace := map[string]string{
|
||||||
|
"{siteTitle}": options["siteName"],
|
||||||
|
"{userName}": userName,
|
||||||
|
"{notifyReason}": reason,
|
||||||
|
"{siteUrl}": options["siteURL"],
|
||||||
|
"{siteSecTitle}": options["siteTitle"],
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("【%s】空间容量超额提醒", options["siteName"]),
|
||||||
|
util.Replace(replace, options["over_used_template"])
|
||||||
|
}
|
Loading…
Reference in new issue