Wega's Blog

Server酱加云函数实现留言监控

本博客的留言板功能过于简单,只能留言,无法做到消息提醒

由于是纯静态网站,想再增强下留言板功能还是有办法的,可以实现有新留言推送到自己的微信上,需要用到 Server 酱和腾讯云的云函数

Server 酱:利用微信服务号的模板消息做消息推送的服务,免费

云函数:腾讯云的无服务器云函数服务,支持各种语言,支持多种触发方式,免费

Bmob 云:云数据库,本博客在用的,免费

准备

注册 Server 酱,阅读下接口文档,很简单就是一个 Post 请求

注册腾讯云,阅读下云函数的文档和部署流程

注册 Bmob 云,阅读 JavaScript 的 SDK 和 REST API 的使用

代码

这里使用 Go 实现

在使用云服务的时候发现外部传参无法获取到,只好将参数在代码硬编码

先安装下云函数的 SDK

go get -u github.com/tencentyun/scf-go-lib/cloudfunction

// 参数定义
// BmobTableName : 表名
// Period : 查询多少分钟前的数据
const (
	BmobAPIURL    = "https://api2.bmob.cn/1/classes/"
	BmobTableName = "Comment"
	BmobAPPId     = "****************"
	BmobAppKey    = "**********************************"
	PushURL       = "https://sc.ftqq.com/********.send"
	Period        = 5
)

使用 Server 酱推送消息到微信,一个 Post 请求

func notice(title, text string) error {
	resp, err := http.PostForm(PushURL, url.Values{"desp": {text}, "text": {title}})
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	return nil
}

获取多少分钟内的留言,使用 Bmob 的 REST API 实现

因为要自定义请求和解析 Json 代码有点长,另外吐槽下 Go 的异常处理

部署的过程中出现了 8 小时差的 BUG,统一时区就解决了

func getRecentComment() ([]string, error) {
	resultList := make([]string, 0)
	req, _ := http.NewRequest("GET", BmobAPIURL+BmobTableName, nil)

	// 请求头
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("X-Bmob-Application-Id", BmobAPPId)
	req.Header.Add("X-Bmob-REST-API-Key", BmobAppKey)

	// 请求参数
	q := req.URL.Query()
	q.Add("order", "-createdAt")
	// 统一时区,避免8小时差的BUG
	var cstSh, _ = time.LoadLocation("Asia/Shanghai")
	// 当前时间减去parms.Period分钟
	sDate := time.Now().In(cstSh).Add(-1 * time.Duration(Period) * time.Minute).Format("2006-01-02 15:04:05")
	q.Add("where", `{"createdAt":{"$gte":{"__type": "Date", "iso": "`+sDate+`"}}}`)
	req.URL.RawQuery = q.Encode()

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return resultList, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return resultList, err
	}

	var result map[string]interface{}
	json.Unmarshal(body, &result)
	if result["error"] != nil {
		return resultList, errors.New("返回错误结果:" + result["error"].(string))
	}
	list := result["results"].([](interface{}))
	for _, v := range list {
		detail := v.(map[string]interface{})
		resultList = append(resultList, detail["content"].(string)+"@"+detail["nickName"].(string))
	}
	return resultList, nil
}

最后的 main 函数

func main() {
	cloudfunction.Start(func(ctx context.Context) (string, error) {
		comments, err := getRecentComment()
		if err != nil {
			return "", err
		}
		if len(comments) == 0 {
			return "没有新消息", nil
		}

		err = notice("您有新的留言", fmt.Sprintf("%v", comments))
		if err != nil {
			return "", err
		}
		return fmt.Sprintf("%v", comments), nil
	})
}

打包部署

使用 Go 的交叉编译打包 linux 版本,然后打包上传到腾讯云函数上

测试通过

01

02

最后设置定时任务,每隔五分钟检测一次,然后把留言推送到我的微信

03

总结

想要为静态博客加点功能真的是麻烦