2
0

chat_message.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package afreeca
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "git.beejay.kim/tool/service/ascii"
  7. "github.com/samber/lo"
  8. "strconv"
  9. "time"
  10. )
  11. type kind []byte
  12. func newKind(category, index int) kind {
  13. return []byte(
  14. fmt.Sprintf("%04d%03d", category, index))
  15. }
  16. type kindList struct {
  17. Ping kind
  18. Authorize kind
  19. Authenticate kind
  20. Authenticated kind
  21. Roster struct {
  22. List kind
  23. Change kind
  24. Status kind
  25. }
  26. Chat kind
  27. ChatEmoticon kind
  28. Donation kind
  29. }
  30. var (
  31. Kind = &kindList{
  32. Ping: newKind(0, 0),
  33. Authorize: newKind(1, 0),
  34. Authenticate: newKind(2, 0),
  35. Authenticated: newKind(94, 0),
  36. Chat: newKind(5, 0),
  37. ChatEmoticon: newKind(109, 0),
  38. Donation: newKind(18, 0),
  39. Roster: struct {
  40. List kind
  41. Change kind
  42. Status kind
  43. }{
  44. List: newKind(4, 1),
  45. Change: newKind(4, 0),
  46. Status: newKind(13, 0),
  47. },
  48. }
  49. )
  50. type ChatMessage struct {
  51. raw []byte
  52. kind kind
  53. data []string
  54. at time.Time
  55. }
  56. func (m *ChatMessage) Unmarshall(buf []byte) error {
  57. m.at = time.Now()
  58. m.raw = buf
  59. if buf == nil || len(buf) < 14 {
  60. return errors.New("empty data")
  61. }
  62. if buf[0] != ascii.Escape ||
  63. buf[1] != ascii.HorizontalTab ||
  64. buf[14] != ascii.FormFeed {
  65. return errors.New("illegal data format")
  66. }
  67. m.data = []string{}
  68. m.kind = buf[2:9]
  69. var (
  70. size = 0
  71. data bytes.Buffer
  72. err error
  73. )
  74. if size, err = strconv.Atoi(string(buf[9:12])); err != nil {
  75. return errors.New("illegal data size")
  76. }
  77. for i := range buf[15:] {
  78. last := i == size-2
  79. b := buf[15+i : 16+i]
  80. if ascii.FormFeed == b[0] {
  81. m.data = append(m.data, data.String())
  82. data.Reset()
  83. continue
  84. }
  85. data.Write(b)
  86. if last {
  87. m.data = append(m.data, data.String())
  88. }
  89. }
  90. return nil
  91. }
  92. func (m *ChatMessage) Build() []byte {
  93. var (
  94. buf bytes.Buffer
  95. size = lo.SumBy(m.data, func(item string) int {
  96. return len(item)
  97. })
  98. )
  99. buf.WriteByte(ascii.Escape)
  100. buf.WriteByte(ascii.HorizontalTab)
  101. buf.Write(m.kind)
  102. buf.WriteString(fmt.Sprintf("%03d00", size+len(m.data)))
  103. for i := range m.data {
  104. buf.WriteByte(ascii.FormFeed)
  105. buf.WriteString(m.data[i])
  106. }
  107. return buf.Bytes()
  108. }
  109. func (m ChatMessage) Is(k kind) bool {
  110. return bytes.Compare(m.kind, k) == 0
  111. }
  112. func (m ChatMessage) Kind() []byte {
  113. return m.kind
  114. }
  115. func (m ChatMessage) Data() []string {
  116. return m.data
  117. }
  118. func NewChatMessage(k kind, args ...string) *ChatMessage {
  119. return &ChatMessage{
  120. kind: k,
  121. data: args,
  122. at: time.Now(),
  123. }
  124. }
  125. func NewChatAuthorizeMessage(token string, withQuickView bool) *ChatMessage {
  126. flag := "16"
  127. if withQuickView {
  128. flag = "524304"
  129. }
  130. return NewChatMessage(Kind.Authorize, token, "", flag, "")
  131. }
  132. func NewChatPingMessage() []byte {
  133. return NewChatMessage(Kind.Ping, "").Build()
  134. }
  135. func NewChatRosterRequestMessage() []byte {
  136. return NewChatMessage(Kind.Roster.Change, "").Build()
  137. }