发现一个简易的使用qq推送消息的工具,原本打算用来做网盘的提醒助手,最后放弃了。
不过感觉这个玩具挺好玩的,做个记录。
Qmsg首页
qq登录即注册qmsg的账号添加对应账号机器人,获取key之后就可以用它做消息的提醒。
文档写的很简单 就做一个get/post请求即可
用go来封装 http请求
模拟http请求在线测试工具
复习相关知识 (可以直接跳过)
当然简单的操作,可以直接用curl to go将curl命令行转换为对应go代码
go http包 有简易的 get post,若是发送较长的数据 推荐使用postform发送表单 或者转为json数据post指定json格式发送
以下是通过post发送表单和解析json数据的示例代码
注意 接收的resp.Body不要忘记关闭
实现
package main
import (
"encoding/json"
"log"
"net/http"
"net/url"
"strings"
"time"
)
const key = "***" // 申请的key
const url1 = "https://qmsg.zendee.cn/send/" // 私聊消息推送接口:
// const ur2 ="https://qmsg.zendee.cn/group/" // 群消息推送接口:
type infodetail struct {
Lmyidc string
}
type QmsgResult struct {
Reason string
Success bool
Code int
// Info interface{} //嵌套类型json暂不处理直接给此类型 等价为map[string] interface{}
Info infodetail
}
func main() {
log.SetFlags(log.Ldate | log.Lshortfile)
myurl := url1 + key
client := &http.Client{Timeout: time.Second * 15}
params := url.Values{}
params.Add("msg", "有没有这么一种可能@face=172@")
// params.Add("msg", "解析json测试@face=177@")
params.Add("key2", `value:2`)
body := strings.NewReader(params.Encode())
resp, err := client.Post(myurl, "application/x-www-form-urlencoded", body)
if err != nil {
log.Println(err)
}
defer resp.Body.Close()
DataPrint(resp)
}
func DataPrint(resp *http.Response) {
if resp.StatusCode != http.StatusOK {
log.Printf("http response failed: %s\n", resp.Status)
}
var result QmsgResult
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { //底层unmarshal
log.Println(err)
}
log.Println(result.Reason, result.Code, result.Info.Lmyidc, result.Success)
}
测试无误后只需要将这一小段嵌入到业务代码即可,
很多人用法是写成js插件做到前端页面例如博客的评论区回复提醒等 基于Leancloud或javascript推送Valine评论
其他备忘
get post用法
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
)
const url = "https://baidu.com"
func main() {
// 方式一,直接通过 Get 函数
resp, err := http.Get(url)
ErrPrint(err)
defer resp.Body.Close()
// 拿到数据
bytes, err := ioutil.ReadAll(resp.Body)
ErrPrint(err)
// 这里要格式化再输出,因为 ReadAll 返回的是字节切片
fmt.Println("------------- 方法一 ---------------")
fmt.Printf("%s", bytes)
// 方式二,通过 client 结构体的 Get 方法
// client := new(http.Client) 等价下式
client := &http.Client{}
resp, err = client.Get(url)
ErrPrint(err)
defer resp.Body.Close()
res, err := ioutil.ReadAll(resp.Body)
ErrPrint(err)
fmt.Println("\n\n\n------------- 方法二 ---------------")
fmt.Printf("%s", res)
}
func ErrPrint(err error) {
if err != nil {
log.Fatalln(err)
os.Exit(1)
}
}
post 普通字串 json用法
/* post client */
package main
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
)
// json包解析变量只能解析首字母大写的
type Mytest struct {
Type int
Desc string
Name string
UserId string
}
const url = "http://localhost:8080/hello"
func main() {
// 方式一,直接通过 Post 函数
fmt.Println("------------- 方法一 ---------------")
resp, err := http.Post(url, "application/x-www-form-urlencoded",
strings.NewReader("name=Bro Qiang"))
ErrPrint(err)
defer resp.Body.Close()
DataPrint(resp.Body)
// 方式二,通过 client 结构体中的 Post 方法
fmt.Println("------------- 方法二 ---------------")
client := &http.Client{}
resp, err = client.Post(url, "application/x-www-form-urlencoded",
strings.NewReader("name=New Bro Qiang"))
ErrPrint(err)
defer resp.Body.Close()
DataPrint(resp.Body)
// 方式一发送json
fmt.Println("------------- 方法一json ---------------")
info := Mytest{
Type: 1,
UserId: "lsj",
Name: "lk233",
Desc: "test_UserInfo",
}
bytes, _ := json.Marshal(info)
resp, err = http.Post(url, "application/json", strings.NewReader(string(bytes)))
if err != nil {
log.Println("query info failed", err.Error())
}
defer resp.Body.Close()
DataPrint(resp.Body)
}
func DataPrint(body io.ReadCloser) {
bytes, err := ioutil.ReadAll(body)
ErrPrint(err)
fmt.Printf("%s", bytes)
}
func ErrPrint(err error) {
if err != nil {
log.Fatalln(err)
os.Exit(1)
}
}
/*
get 的server与 post server类似
添加 下面的类似模块
if req.Method == "GET" {
err := req.ParseForm()
if err != nil {
http.Error(w, http.StatusText(http.StatusInternalServerError),
http.StatusInternalServerError)
return
}
for k, v := range req.Form {
}
*/
/* post_server */
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
type Mytest struct {
Type int
Desc string
UserId string
Name string
}
func main() {
http.HandleFunc("/hello", func(w http.ResponseWriter, req *http.Request) {
if req.Method == "POST" {
// if req.Context()
// fmt.Fprintf(w,"Hello %s\n",req.FormValue("name")) 此函数可以直接获取对应键值 底层实际也是调用 ParseForm
err := req.ParseForm()
if err != nil {
http.Error(w, http.StatusText(http.StatusInternalServerError),
http.StatusInternalServerError)
return
}
// fmt.Println(req.Header["Content-Type"][0])
if req.Header["Content-Type"][0] == "application/x-www-form-urlencoded" {
formData := req.Form
fmt.Fprintf(w, "Hello %s\n", formData.Get("name"))
} else { //post数据是json需要其他处理
body, _ := ioutil.ReadAll(req.Body) // read req之后 req的其他解析全为空
myjson := Mytest{}
if json.Unmarshal(body, &myjson) != nil {
fmt.Fprintf(w, "error json\n")
} else {
fmt.Fprintf(w, "json Hello %s\n", myjson.Name)
}
}
return
}
http.NotFound(w, req)
})
log.Fatalf("%v", http.ListenAndServe("localhost:8080", nil))
}
postform用法
/* postform server */
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/form", MyForm)
log.Fatalf("%v",
http.ListenAndServe("localhost:8080", nil))
}
func MyForm(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if err != nil {
http.Error(w, http.StatusText(http.StatusInternalServerError),
http.StatusInternalServerError)
return
}
formData := r.Form
log.Printf("收到的数据: %v", formData)
fmt.Fprintf(w, "提交成功")
}
/* client */
package main
import (
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
)
const url = "http://localhost:8080/form"
func main() {
data := map[string][]string{"name": {"Bro|", "Qiang"}, "gender": {"male"}}
// 方法一:PostForm 函数
resp, err := http.PostForm(url, data)
ErrPrint(err)
defer resp.Body.Close()
DataPrint(resp.Body)
// 方法二:client 结构体的 PostForm 方法
client := &http.Client{}
resp, err = client.PostForm(url, data)
ErrPrint(err)
defer resp.Body.Close()
DataPrint(resp.Body)
}
func DataPrint(body io.ReadCloser) {
// 拿到数据
bytes, err := ioutil.ReadAll(body)
ErrPrint(err)
// 这里要格式化再输出,因为 ReadAll 返回的是字节切片
fmt.Printf("%s\n", bytes)
}
func ErrPrint(err error) {
if err != nil {
log.Fatalln(err)
os.Exit(1)
}
}