package main
import (
"crypto/sha1"
"errors"
"fmt"
"log"
"math/rand"
"sort"
"strings"
"time"
)
//Article is one item in News Message
// one such message can contains upto 10 Articles
type Article struct {
title, description, picURL, url string
}
//BuildTextMsg Given a text message send it to wechat client
func BuildTextMsg(txt string, ToUserName string) (xml string, err error) {
if txt == "" || ToUserName == "" {
err = errors.New("Empty text body or Empty destination")
xml = ""
return
}
msg := fmt.Sprintf(txtMsgTemplate(), ToUserName, APIConfig.PublicAccountID, int32(time.Now().Unix()), txt)
e := Encode(msg)
xml, _, _, _ = signMsg(e)
return
}
//BuildLocationMsg doesn't work for build location message
func BuildLocationMsg(long, lat, precision float64, ToUserName string) (xml string) {
msg := buildLocationMsg()
e := Encode(msg)
xml, _, _, _ = signMsg(e)
return
}
func signMsg(content string) (xml string, timestamp int32, nonce int32, signature string) {
timestamp = int32(time.Now().Unix())
nonce = rand.Int31()
strTimestamp := fmt.Sprintf("%d", timestamp)
strNonce := fmt.Sprintf("%d", nonce)
signature = getSignature(APIConfig.Token, strTimestamp, strNonce, content)
xml = "" +
"" + content + "" +
"" + signature + "" +
"" + strTimestamp + "" +
"" + strNonce + "" +
""
return
}
func getSignature(token string, timestamp string, nonce string, content string) (signature string) {
strs := []string{token, timestamp, nonce, content}
sort.Strings(strs)
s := strings.Join(strs, "")
h := sha1.New()
h.Write([]byte(s))
signature = fmt.Sprintf("%x", h.Sum(nil))
return
}
func buildTxtMsg(ToUserName, content string) (msg string) {
msg = fmt.Sprintf(txtMsgTemplate(), ToUserName, APIConfig.PublicAccountID, int32(time.Now().Unix()), content)
return
}
func txtMsgTemplate() string {
return `
%d
`
}
//upload image to media as temp data, get mediaid and send it out
func buildUploadPicMsg(ToUserName, path string) (msg string) {
mediaID := uploadImage(path)
msg = buildPicMsg(ToUserName, mediaID)
return
}
func buildPicMsg(ToUserName, mediaID string) (msg string) {
msg = fmt.Sprintf(picMsgTemplate(), ToUserName, APIConfig.PublicAccountID, int32(time.Now().Unix()), mediaID)
return
}
func picMsgTemplate() string {
return `
%d
`
}
func buildUploadVoiceMsg(ToUserName, path string) (msg string) {
mediaID := uploadVoice(path)
log.Println("get media id " + mediaID)
msg = buildVoiceMsg(ToUserName, mediaID)
return
}
func buildVoiceMsg(ToUserName, mediaID string) (msg string) {
msg = fmt.Sprintf(voiceMsgTemplate(), ToUserName, APIConfig.PublicAccountID, int32(time.Now().Unix()), mediaID)
return
}
func voiceMsgTemplate() string {
return `
%d
`
}
func buildVideoMsg(ToUserName, mediaID, title, description string) (msg string) {
msg = fmt.Sprintf(videoMsgTemplate(), ToUserName, APIConfig.PublicAccountID, int32(time.Now().Unix()), mediaID, title, description)
return
}
func videoMsgTemplate() string {
return `
%d
`
}
func bulidMusicMsg(ToUserName, mediaID, title, description, url, hqURL string) (msg string) {
msg = fmt.Sprintf(musicMsgTemplate(),
ToUserName,
APIConfig.PublicAccountID,
int32(time.Now().Unix()),
title,
description,
url,
hqURL,
mediaID)
return
}
func musicMsgTemplate() string {
return `
%d
`
}
func buildNewsMsg(ToUserName, title, description string, articles []Article) (msg string) {
count := 0
items := []string{}
for _, a := range articles {
if count >= 8 {
err := errors.New("too many articles, only take first 8")
log.Println(err)
break
}
s := buildArticleItem(a)
items = append(items, s)
count++
}
strItems := strings.Join(items, "")
msg = fmt.Sprintf(newsMsgTemplate(),
ToUserName,
APIConfig.PublicAccountID,
int32(time.Now().Unix()),
count,
strItems)
return
}
func buildArticleItem(item Article) (article string) {
template := `-
`
article = fmt.Sprintf(template,
item.title, item.description, item.picURL, item.url)
return article
}
func newsMsgTemplate() string {
return `
%d
%d
%s
`
}
func buildLocationMsg() string {
template := `
1494124221
23.134521
113.358803
20
`
return template
}