123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- package afreeca
- import (
- "bytes"
- "errors"
- "fmt"
- "git.beejay.kim/tool/service/ascii"
- "github.com/samber/lo"
- "strconv"
- "time"
- )
- type kind []byte
- func newKind(category, index int) kind {
- return []byte(
- fmt.Sprintf("%04d%03d", category, index))
- }
- type kindList struct {
- Ping kind
- Authorize kind
- Authenticate kind
- Authenticated kind
- Roster struct {
- List kind
- Change kind
- Status kind
- }
- Chat kind
- ChatEmoticon kind
- Donation kind
- }
- var (
- Kind = &kindList{
- Ping: newKind(0, 0),
- Authorize: newKind(1, 0),
- Authenticate: newKind(2, 0),
- Authenticated: newKind(94, 0),
- Chat: newKind(5, 0),
- ChatEmoticon: newKind(109, 0),
- Donation: newKind(18, 0),
- Roster: struct {
- List kind
- Change kind
- Status kind
- }{
- List: newKind(4, 1),
- Change: newKind(4, 0),
- Status: newKind(13, 0),
- },
- }
- )
- type ChatMessage struct {
- raw []byte
- kind kind
- data []string
- at time.Time
- }
- func (m *ChatMessage) Unmarshall(buf []byte) error {
- m.at = time.Now()
- m.raw = buf
- if buf == nil || len(buf) < 14 {
- return errors.New("empty data")
- }
- if buf[0] != ascii.Escape ||
- buf[1] != ascii.HorizontalTab ||
- buf[14] != ascii.FormFeed {
- return errors.New("illegal data format")
- }
- m.data = []string{}
- m.kind = buf[2:9]
- var (
- size = 0
- data bytes.Buffer
- err error
- )
- if size, err = strconv.Atoi(string(buf[9:12])); err != nil {
- return errors.New("illegal data size")
- }
- for i := range buf[15:] {
- last := i == size-2
- b := buf[15+i : 16+i]
- if ascii.FormFeed == b[0] {
- m.data = append(m.data, data.String())
- data.Reset()
- continue
- }
- data.Write(b)
- if last {
- m.data = append(m.data, data.String())
- }
- }
- return nil
- }
- func (m *ChatMessage) Build() []byte {
- var (
- buf bytes.Buffer
- size = lo.SumBy(m.data, func(item string) int {
- return len(item)
- })
- )
- buf.WriteByte(ascii.Escape)
- buf.WriteByte(ascii.HorizontalTab)
- buf.Write(m.kind)
- buf.WriteString(fmt.Sprintf("%03d00", size+len(m.data)))
- for i := range m.data {
- buf.WriteByte(ascii.FormFeed)
- buf.WriteString(m.data[i])
- }
- return buf.Bytes()
- }
- func (m ChatMessage) Is(k kind) bool {
- return bytes.Compare(m.kind, k) == 0
- }
- func (m ChatMessage) Kind() []byte {
- return m.kind
- }
- func (m ChatMessage) Data() []string {
- return m.data
- }
- func NewChatMessage(k kind, args ...string) *ChatMessage {
- return &ChatMessage{
- kind: k,
- data: args,
- at: time.Now(),
- }
- }
- func NewChatAuthorizeMessage(token string, withQuickView bool) *ChatMessage {
- flag := "16"
- if withQuickView {
- flag = "524304"
- }
- return NewChatMessage(Kind.Authorize, token, "", flag, "")
- }
- func NewChatPingMessage() []byte {
- return NewChatMessage(Kind.Ping, "").Build()
- }
- func NewChatRosterRequestMessage() []byte {
- return NewChatMessage(Kind.Roster.Change, "").Build()
- }
|