func (seg *MessageSegment) ParseMedia(media Media) error {
	_, ok := media.(*MessageSegment)
	if ok {
		reflect.ValueOf(media).Elem().Set(reflect.ValueOf(seg).Elem())
		return nil
	}
	err := decode(seg.Data, media)
	if seg.Type != media.FunctionName() {
		if err != nil {
			err = errors.Wrap(err, "wrong media type")
		} else {
			err = errors.New("wrong media type")
		}
	}
	return err
}
ParseMedia parses a MessageSegment to a specified type of Media.
package cqcode
import (
	"fmt"
	"github.com/mitchellh/mapstructure"
	"github.com/pkg/errors"
	"reflect"
	"regexp"
	"strconv"
	"strings"
)
var StrictCommand = false
var CommandPrefix = "/"
type Message []Media
type MessageSegment struct {
	Type string                 `json:"type"`
	Data map[string]interface{} `json:"data"`
}
func (seg *MessageSegment) FunctionName() string {
	return seg.Type
}
func NewMessageSegment(media Media) (MessageSegment, error) {
	seg := MessageSegment{}
	seg.Type = media.FunctionName()
	seg.Data = make(map[string]interface{})
	err := decode(media, &seg.Data)
	return seg, err
}
func NewMessageSegmentFromCQCode(str string) (MessageSegment, error) {
	seg := MessageSegment{}
	seg.Data = make(map[string]interface{})
	err := ParseCQCode(str, &seg)
	return seg, err
}
func decode(input, output interface{}) error {
	config := &mapstructure.DecoderConfig{
		Metadata:         nil,
		Result:           output,
		WeaklyTypedInput: true,
		TagName:          "cq",
	}
	decoder, err := mapstructure.NewDecoder(config)
	if err != nil {
		return err
	}
	return decoder.Decode(input)
}
func NewMessage() Message {
	return make(Message, 0)
}
func ParseMessageSegments(msg interface{}) ([]MessageSegment, error) {
	switch x := msg.(type) {
	case string:
		return ParseMessageSegmentsFromString(x)
	default:
		return ParseMessageSegmentsFromArray(x)
	}
}
func ParseMessage(msg interface{}) (Message, error) {
	switch x := msg.(type) {
	case string:
		return ParseMessageFromString(x)
	default:
		return ParseMessageFromArray(x)
	}
}
func ParseMessageSegmentsFromArray(msg interface{}) ([]MessageSegment, error) {
	segs := make([]MessageSegment, 0)
	err := decode(msg, &segs)
	return segs, err
}
func ParseMessageFromArray(msg interface{}) (Message, error) {
	segs, err := ParseMessageSegmentsFromArray(msg)
	if err != nil {
		return NewMessage(), err
	}
	return ParseMessageFromMessageSegments(segs), nil
}
func ParseMessageSegmentsFromString(str string) ([]MessageSegment, error) {
	segs := make([]MessageSegment, 0)
	res := regexp.MustCompile(`\[CQ:[\s\S]*?\]`).FindAllStringSubmatchIndex(str, -1)
	i := 0
	for _, cqc := range res {
		if cqc[0] > i {
			seg := MessageSegment{
				Type: "text",
				Data: map[string]interface{}{
					"text": DecodeCQCodeText(str[i:cqc[0]]),
				},
			}
			segs = append(segs, seg)
		}
		i = cqc[1]
		seg, err := NewMessageSegmentFromCQCode(str[cqc[0]:cqc[1]])
		if err != nil {
			continue
		}
		segs = append(segs, seg)
	}
	if len(str) > i {
		seg := MessageSegment{
			Type: "text",
			Data: map[string]interface{}{
				"text": DecodeCQCodeText(str[i:]),
			},
		}
		segs = append(segs, seg)
	}
	return segs, nil
}
func ParseMessageFromString(str string) (Message, error) {
	segs, _ := ParseMessageSegmentsFromString(str)
	return ParseMessageFromMessageSegments(segs), nil
}
func ParseMessageFromMessageSegments(segs []MessageSegment) Message {
	message := NewMessage()
	for _, seg := range segs {
		switch seg.Type {
		case "text":
			text := Text{}
			seg.ParseMedia(&text)
			message = append(message, &text)
		case "at":
			at := At{}
			seg.ParseMedia(&at)
			message = append(message, &at)
		case "face":
			face := Face{}
			seg.ParseMedia(&face)
			message = append(message, &face)
		case "emoji":
			emoji := Emoji{}
			seg.ParseMedia(&emoji)
			message = append(message, &emoji)
		case "bface":
			bface := Bface{}
			seg.ParseMedia(&bface)
			message = append(message, &bface)
		case "sface":
			sface := Sface{}
			seg.ParseMedia(&sface)
			message = append(message, &sface)
		case "image":
			image := Image{}
			seg.ParseMedia(&image)
			message = append(message, &image)
		case "record":
			record := Record{}
			seg.ParseMedia(&record)
			message = append(message, &record)
		case "rps":
			rps := Rps{}
			seg.ParseMedia(&rps)
			message = append(message, &rps)
		case "dice":
			dice := Dice{}
			seg.ParseMedia(&dice)
			message = append(message, &dice)
		case "shake":
			shake := Shake{}
			seg.ParseMedia(&shake)
			message = append(message, &shake)
		case "music":
			music := Music{}
			seg.ParseMedia(&music)
			message = append(message, &music)
		case "share":
			share := Share{}
			seg.ParseMedia(&share)
			message = append(message, &share)
		case "location":
			location := Location{}
			seg.ParseMedia(&location)
			message = append(message, &location)
		case "show":
			show := Show{}
			seg.ParseMedia(&show)
			message = append(message, &show)
		case "sign":
			sign := Sign{}
			seg.ParseMedia(&sign)
			message = append(message, &sign)
		case "rich":
			rich := Rich{}
			seg.ParseMedia(&rich)
			message = append(message, &rich)
		case "hb":
			hb := RedPack{}
			seg.ParseMedia(&hb)
			message = append(message, &hb)
		default:
			s := seg
			message = append(message, &s)
		}
	}
	return message
}
func (m *Message) IsCommand() bool {
	str := m.CQString()
	return IsCommand(str)
}
func (m *Message) Command() (cmd string, args []string) {
	str := m.CQString()
	return Command(str)
}
func IsCommand(str string) bool {
	if len(str) == 0 {
		return false
	}
	if StrictCommand && (len(str) < len(CommandPrefix) || str[:len(CommandPrefix)] != CommandPrefix) {
		return false
	}
	return true
}
func Command(str string) (cmd string, args []string) {
	lcp := len(CommandPrefix)
	str = strings.Replace(str, `\\`, `\0x5c`, -1)
	str = strings.Replace(str, `\"`, `\0x22`, -1)
	str = strings.Replace(str, `\'`, `\0x27`, -1)
	strs := regexp.MustCompile(`'[\s\S]*?'|"[\s\S]*?"|\S*\[CQ:[\s\S]*?\]\S*|\S+`).FindAllString(str, -1)
	if len(strs) == 0 || len(strs[0]) == 0 {
		return
	}
	if StrictCommand {
		if len(strs[0]) < lcp || strs[0][:lcp] != CommandPrefix {
			return
		}
		cmd = strs[0][lcp:]
	} else {
		cmd = strs[0]
	}
	for _, arg := range strs[1:] {
		arg = strings.Trim(arg, `'"`)
		arg = strings.Replace(arg, `\0x27`, `'`, -1)
		arg = strings.Replace(arg, `\0x22`, `"`, -1)
		arg = strings.Replace(arg, `\0x5c`, `\`, -1)
		args = append(args, arg)
	}
	return
}
func (m *Message) CQString() string {
	var str string
	for _, media := range *m {
		str += FormatCQCode(media)
	}
	return str
}
func (m *Message) MessageSegments() []MessageSegment {
	segs := make([]MessageSegment, 0)
	for _, media := range *m {
		seg, err := NewMessageSegment(media)
		if err != nil {
			continue
		}
		segs = append(segs, seg)
	}
	return segs
}
func (m *Message) Append(media Media) error {
	*m = append(*m, media)
	return nil
}