package afreeca import ( "fmt" "git.beejay.kim/tool/service/ascii" "github.com/mailru/easyjson" "github.com/spf13/cast" "strings" ) type BridgeCommand string const ( BridgeCommandInitGateway BridgeCommand = "INIT_GW" BridgeCommandInitBroadcast BridgeCommand = "INIT_BROAD" BridgeCommandKeepAlive BridgeCommand = "KEEPALIVE" BridgeCommandLogin BridgeCommand = "FLASH_LOGIN" BridgeCommandCertTicket BridgeCommand = "CERTTICKETEX" BridgeCommandUserCount BridgeCommand = "GETUSERCNT" BridgeCommandUserCountExtended BridgeCommand = "GETUSERCNTEX" BridgeCommandChannelCommon BridgeCommand = "JOINCH_COMMON" BridgeCommandChannelInfo BridgeCommand = "GETCHINFOEX" BridgeCommand_GETBJADCON BridgeCommand = "GETBJADCON" BridgeCommand_GETITEM_SELL BridgeCommand = "GETITEM_SELL" BridgeCommandClosed BridgeCommand = "CLOSECH" ) //easyjson:json type BridgeMessage struct { Command BridgeCommand `json:"SVC"` Result int `json:"RESULT"` Data map[string]any `json:"DATA"` } func (bm *BridgeMessage) AddArgument(k string, v any) { switch v.(type) { case int: bm.Data[k] = v.(int) case int8: bm.Data[k] = v.(int8) case int16: bm.Data[k] = v.(int16) case int32: bm.Data[k] = v.(int32) case int64: bm.Data[k] = v.(int64) case uint: bm.Data[k] = v.(uint) case uint8: bm.Data[k] = v.(uint8) case uint16: bm.Data[k] = v.(uint16) case uint32: bm.Data[k] = v.(uint32) case uint64: bm.Data[k] = v.(uint64) default: bm.Data[k] = cast.ToString(v) } } func (bm *BridgeMessage) MustMarshall() []byte { buf, err := easyjson.Marshal(bm) if err != nil { return nil } return buf } type BridgeMessageValue []string func (arg *BridgeMessageValue) AddTuple(k string, v any) { var list []string if list = *arg; list == nil { list = []string{} } *arg = append(list, fmt.Sprintf(`%s%s`, k, cast.ToString(v))) } func (arg BridgeMessageValue) String() string { return strings.Join(arg, "") } type BridgeMessageValueParams []string func (arg BridgeMessageValueParams) String() string { return strings.Join(arg, "") } func (arg *BridgeMessageValueParams) Add(k string, v any) { var list []string if list = *arg; list == nil { list = []string{} } ack := string([]byte{ascii.Acknowledgement}) *arg = append(list, ack, "&", ack, k, ack, "=", ack, cast.ToString(v)) } func NewBridgeInitGatewayMessage(bid string, uuid string, ch Channel, cookieGetter func(string) string) *BridgeMessage { m := NewBridgeMessage(BridgeCommandInitGateway) m.AddArgument("BJID", bid) m.AddArgument("JOINLOG", makeJoinLog(ch, cookieGetter)) m.AddArgument("QUALITY", "sd") m.AddArgument("addinfo", func() BridgeMessageValue { info := BridgeMessageValue{} info.AddTuple("ad_lang", "ko") info.AddTuple("is_auto", 0) return info }()) m.AddArgument("broadno", ch.Id) m.AddArgument("category", ch.Category) m.AddArgument("cc_cli_type", 19) m.AddArgument("cli_type", 44) m.AddArgument("cookie", "") m.AddArgument("fanticket", ch.FanToken) m.AddArgument("gate_ip", ch.GatewayIp) m.AddArgument("gate_port", ch.GatewayPort) m.AddArgument("guid", uuid) m.AddArgument("update_info", 0) return m } func NewBridgeInitBroadcastMessage(uuid string, ch Channel, cookieGetter func(string) string) *BridgeMessage { m := NewBridgeMessage(BridgeCommandInitBroadcast) m.AddArgument("JOINLOG", makeJoinLog(ch, cookieGetter)) m.AddArgument("QUALITY", "sd") m.AddArgument("cc_cli_type", 19) m.AddArgument("cli_type", 44) m.AddArgument("center_ip", ch.CenterIp) m.AddArgument("center_port", ch.CenterPort) m.AddArgument("guid", uuid) m.AddArgument("passwd", "") m.AddArgument("append_data", "") m.AddArgument("gw_ticket", "") return m } func NewBridgeMessage(cmd BridgeCommand) *BridgeMessage { return &BridgeMessage{ Command: cmd, Data: map[string]any{}, } } func makeJoinLog(ch Channel, cookieGetter func(string) string) BridgeMessageValue { joinlog := BridgeMessageValue{} joinlog.AddTuple("log", func() BridgeMessageValueParams { params := BridgeMessageValueParams{} params.Add("uuid", cookieGetter("_au")) params.Add("geo_cc", ch.GeoName) params.Add("geo_rc", ch.GeoCode) params.Add("acpt_lang", ch.AcceptLanguage) params.Add("svc_lang", ch.ServiceLanguage) params.Add("os", "mac") params.Add("is_streamer", false) params.Add("is_rejoin", false) params.Add("is_streamer", false) params.Add("is_auto", false) params.Add("is_support_adaptive", false) params.Add("uuid_3rd", cookieGetter("_au3rd")) params.Add("subscribe", -1) return params }()) joinlog.AddTuple("liveualog", func() BridgeMessageValueParams { params := BridgeMessageValueParams{} params.Add("is_clearmode", false) params.Add("lowlatency", 0) return params }()) return joinlog }