diff --git a/pkg/ami/ami_callback.go b/pkg/ami/ami_callback.go index d8dd318..5e75358 100644 --- a/pkg/ami/ami_callback.go +++ b/pkg/ami/ami_callback.go @@ -7,7 +7,6 @@ import ( "time" "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) type AMICallbackService interface { @@ -72,7 +71,7 @@ func (a *AMICallbackHandler) AppendIgnoredEvents(values ...string) *AMICallbackH } func (a *AMICallbackHandler) Json() string { - return utils.ToJson(a) + return ToJson(a) } func (h *AMICallbackHandler) Send() (AMIResultRaw, error) { diff --git a/pkg/ami/ami_cdr.go b/pkg/ami/ami_cdr.go index ff6b420..a326d8d 100644 --- a/pkg/ami/ami_cdr.go +++ b/pkg/ami/ami_cdr.go @@ -8,7 +8,6 @@ import ( "time" "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) func NewAMICdr() *AMICdr { @@ -19,27 +18,27 @@ func NewAMICdr() *AMICdr { } func (r *AMICdr) SetEvent(value string) *AMICdr { - r.Event = utils.TrimAllSpace(value) + r.Event = TrimAllSpace(value) return r } func (r *AMICdr) SetAccountCode(value string) *AMICdr { - r.AccountCode = utils.TrimAllSpace(value) + r.AccountCode = TrimAllSpace(value) return r } func (r *AMICdr) SetSource(value string) *AMICdr { - r.Source = utils.TrimAllSpace(value) + r.Source = TrimAllSpace(value) return r } func (r *AMICdr) SetDestination(value string) *AMICdr { - r.Destination = utils.TrimAllSpace(value) + r.Destination = TrimAllSpace(value) return r } func (r *AMICdr) SetDestinationContext(value string) *AMICdr { - r.DestinationContext = utils.TrimAllSpace(value) + r.DestinationContext = TrimAllSpace(value) return r } @@ -49,22 +48,22 @@ func (r *AMICdr) SetCallerId(value string) *AMICdr { } func (r *AMICdr) SetChannel(value string) *AMICdr { - r.Channel = utils.TrimAllSpace(value) + r.Channel = TrimAllSpace(value) return r } func (r *AMICdr) SetDestinationChannel(value string) *AMICdr { - r.DestinationChannel = utils.TrimAllSpace(value) + r.DestinationChannel = TrimAllSpace(value) return r } func (r *AMICdr) SetLastApplication(value string) *AMICdr { - r.LastApplication = utils.TrimAllSpace(value) + r.LastApplication = TrimAllSpace(value) return r } func (r *AMICdr) SetLastData(value string) *AMICdr { - r.LastData = utils.TrimAllSpace(value) + r.LastData = TrimAllSpace(value) return r } @@ -162,12 +161,12 @@ func (r *AMICdr) SetBillableSecondWith(value string) *AMICdr { } func (r *AMICdr) SetDisposition(value string) *AMICdr { - r.Disposition = utils.TrimAllSpace(value) + r.Disposition = TrimAllSpace(value) return r } func (r *AMICdr) SetAmaFlag(value string) *AMICdr { - r.AmaFlags = utils.TrimAllSpace(value) + r.AmaFlags = TrimAllSpace(value) return r } @@ -200,7 +199,7 @@ func (r *AMICdr) SetPrivilege(value string) *AMICdr { } func (r *AMICdr) SetDirection(value string) *AMICdr { - r.Direction = utils.TrimAllSpace(value) + r.Direction = TrimAllSpace(value) return r } @@ -210,22 +209,22 @@ func (r *AMICdr) SetFlowCall(value string) *AMICdr { } func (r *AMICdr) SetTypeDirection(value string) *AMICdr { - r.TypeDirection = utils.TrimAllSpace(value) + r.TypeDirection = TrimAllSpace(value) return r } func (r *AMICdr) SetUserExten(value string) *AMICdr { - r.UserExtension = utils.TrimAllSpace(value) + r.UserExtension = TrimAllSpace(value) return r } func (r *AMICdr) SetPhoneNumber(value string) *AMICdr { - r.PhoneNumber = utils.TrimAllSpace(value) + r.PhoneNumber = TrimAllSpace(value) return r } func (r *AMICdr) SetExtenSplitterSymbol(value string) *AMICdr { - r.ExtenSplitterSymbol = utils.TrimAllSpace(value) + r.ExtenSplitterSymbol = TrimAllSpace(value) return r } @@ -235,7 +234,7 @@ func (r *AMICdr) SetPlaybackUrl(value string) *AMICdr { } func (r *AMICdr) Json() string { - return utils.ToJson(r) + return ToJson(r) } func (r *AMICdr) IsCdrNoAnswer() bool { @@ -346,7 +345,7 @@ func ParseCdr(e *AMIMessage, d *AMIDictionary) *AMICdr { // detect outbound, inbound // if the field destination is phone number, so mark this cdr belong to outbound, otherwise mark as inbound form := "flow_call_from_'%v'_to_'%v'" - phone := utils.RemovePrefix(r.Destination, e.PhonePrefix...) + phone := RemovePrefix(r.Destination, e.PhonePrefix...) if IsPhoneNumberAbsolute(phone, e.Region) { flow := fmt.Sprintf(form, r.Channel, phone) r.SetFlowCall(flow) @@ -386,7 +385,7 @@ func ParseCdr(e *AMIMessage, d *AMIDictionary) *AMICdr { r.SetPhoneNumber(r.Source) } if !inCase { - log.Printf("ParseCdr, CDR exception case = %v", utils.ToJson(r)) + log.Printf("ParseCdr, CDR exception case = %v", ToJson(r)) } } return r diff --git a/pkg/ami/ami_channel.go b/pkg/ami/ami_channel.go index 9f85854..e47d516 100644 --- a/pkg/ami/ami_channel.go +++ b/pkg/ami/ami_channel.go @@ -9,7 +9,6 @@ import ( "strings" "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) func NewChannel() *AMIChannel { @@ -18,7 +17,7 @@ func NewChannel() *AMIChannel { func (c *AMIChannel) SetChannelProtocol(protocol string) *AMIChannel { if ok := config.AmiChannelProtocols[protocol]; !ok { - msg := fmt.Sprintf(config.AmiErrorProtocolMessage, strings.Join(utils.Keys(config.AmiChannelProtocols), ",")) + msg := fmt.Sprintf(config.AmiErrorProtocolMessage, strings.Join(Keys(config.AmiChannelProtocols), ",")) log.Panic(config.AmiErrorInvalidProtocol, "\n", msg) } c.ChannelProtocol = protocol @@ -66,10 +65,10 @@ func (c *AMIChannel) ValidWith(channelProtocol string, regex string, digitsExten if len(digitsExten) == 0 { return false } - if utils.IsEmptyAbsolute(extension) { + if IsEmptyAbsolute(extension) { return false } - if utils.IsEmptyAbsolute(regex) { + if IsEmptyAbsolute(regex) { return false } c.SetChannelProtocol(channelProtocol) @@ -103,7 +102,7 @@ func (c *AMIChannel) ValidSIPDefaultWith(digitsExten []interface{}, extension st // Return as form sip@127.0.0.1 func (c *AMIChannel) JoinHostChannel(protocol, ip string) string { c.SetChannelProtocol(protocol) - host, _, _ := utils.IPDecode(ip) + host, _, _ := IPDecode(ip) form := "%v@%v" if len(host) > 0 { diff --git a/pkg/ami/ami_chanspy.go b/pkg/ami/ami_chanspy.go index 67eb393..0fe112f 100644 --- a/pkg/ami/ami_chanspy.go +++ b/pkg/ami/ami_chanspy.go @@ -7,7 +7,6 @@ import ( "strings" "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) func NewAMIPayloadChanspy() *AMIPayloadChanspy { @@ -18,20 +17,20 @@ func NewAMIPayloadChanspy() *AMIPayloadChanspy { func (s *AMIPayloadChanspy) SetJoin(value string) *AMIPayloadChanspy { ok := config.AmiChanspy[value] if !ok { - msg := fmt.Sprintf(config.AmiErrorChanspyMessage, strings.Join(utils.Keys(config.AmiChanspy), ",")) + msg := fmt.Sprintf(config.AmiErrorChanspyMessage, strings.Join(Keys(config.AmiChanspy), ",")) log.Panic(config.AmiErrorInvalidChanspy, "\n", msg) } - s.Join = utils.TrimAllSpace(value) + s.Join = TrimAllSpace(value) return s } func (s *AMIPayloadChanspy) SetSourceExten(value string) *AMIPayloadChanspy { - s.SourceExten = utils.TrimAllSpace(value) + s.SourceExten = TrimAllSpace(value) return s } func (s *AMIPayloadChanspy) SetCurrentExten(value string) *AMIPayloadChanspy { - s.CurrentExten = utils.TrimAllSpace(value) + s.CurrentExten = TrimAllSpace(value) return s } @@ -47,10 +46,10 @@ func (s *AMIPayloadChanspy) SetAllowDebug(value bool) *AMIPayloadChanspy { } func (s *AMIPayloadChanspy) CommandChanspy(channelExten string) string { - if utils.IsEmptyAbsolute(s.Join) { + if IsEmptyAbsolute(s.Join) { return "" } - if utils.IsEmptyAbsolute(channelExten) { + if IsEmptyAbsolute(channelExten) { return "" } if strings.EqualFold(s.Join, config.AmiChanspySpy) { @@ -69,13 +68,13 @@ func (s *AMIPayloadChanspy) CommandChanspy(channelExten string) string { func Chanspy(ctx context.Context, s AMISocket, ch AMIPayloadChanspy) (AMIResultRawLevel, error) { ok := config.AmiChanspy[ch.Join] if !ok { - msg := fmt.Sprintf(config.AmiErrorChanspyMessage, strings.Join(utils.Keys(config.AmiChanspy), ",")) + msg := fmt.Sprintf(config.AmiErrorChanspyMessage, strings.Join(Keys(config.AmiChanspy), ",")) log.Panic(config.AmiErrorInvalidChanspy, "\n", msg) } - if utils.IsEmptyAbsolute(ch.SourceExten) { + if IsEmptyAbsolute(ch.SourceExten) { return AMIResultRawLevel{}, fmt.Errorf("Source exten is required") } - if utils.IsEmptyAbsolute(ch.CurrentExten) { + if IsEmptyAbsolute(ch.CurrentExten) { return AMIResultRawLevel{}, fmt.Errorf("Current exten is required") } sourceValid, err := HasSIPPeerStatus(ctx, s, ch.SourceExten) diff --git a/pkg/ami/ami_class.go b/pkg/ami/ami_class.go index 2b44d12..959b410 100644 --- a/pkg/ami/ami_class.go +++ b/pkg/ami/ami_class.go @@ -2,7 +2,6 @@ package ami import ( "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) var chargingEvents *map[string]string = &map[string]string{} @@ -16,20 +15,20 @@ func (e *AMIEvent) SnapChargingEvent() *map[string]string { _merged := make(map[string]string) - _merged = utils.MergeMaps(_merged, e.SwapCharging(config.AmiClassCommands)) - _merged = utils.MergeMaps(_merged, e.SwapCharging(config.AmiClassSecurities)) - _merged = utils.MergeMaps(_merged, e.SwapCharging(config.AmiClassCalls)) - _merged = utils.MergeMaps(_merged, e.SwapCharging(config.AmiClassSystems)) - _merged = utils.MergeMaps(_merged, e.SwapCharging(config.AmiClassUsers)) - _merged = utils.MergeMaps(_merged, e.SwapCharging(config.AmiClassDialPlans)) - _merged = utils.MergeMaps(_merged, e.SwapCharging(config.AmiClassAgents)) - _merged = utils.MergeMaps(_merged, e.SwapCharging(config.AmiClassAgis)) - _merged = utils.MergeMaps(_merged, e.SwapCharging(config.AmiClassAocs)) - _merged = utils.MergeMaps(_merged, e.SwapCharging(config.AmiClassCallDetailRecords)) - _merged = utils.MergeMaps(_merged, e.SwapCharging(config.AmiClassChannelEventLoggings)) - _merged = utils.MergeMaps(_merged, e.SwapCharging(config.AmiClasses)) - _merged = utils.MergeMaps(_merged, e.SwapCharging(config.AmiClassReports)) - _merged = utils.MergeMaps(_merged, e.SwapCharging(config.AmiClassDualToneMultiFrequencies)) + _merged = MergeMaps(_merged, e.SwapCharging(config.AmiClassCommands)) + _merged = MergeMaps(_merged, e.SwapCharging(config.AmiClassSecurities)) + _merged = MergeMaps(_merged, e.SwapCharging(config.AmiClassCalls)) + _merged = MergeMaps(_merged, e.SwapCharging(config.AmiClassSystems)) + _merged = MergeMaps(_merged, e.SwapCharging(config.AmiClassUsers)) + _merged = MergeMaps(_merged, e.SwapCharging(config.AmiClassDialPlans)) + _merged = MergeMaps(_merged, e.SwapCharging(config.AmiClassAgents)) + _merged = MergeMaps(_merged, e.SwapCharging(config.AmiClassAgis)) + _merged = MergeMaps(_merged, e.SwapCharging(config.AmiClassAocs)) + _merged = MergeMaps(_merged, e.SwapCharging(config.AmiClassCallDetailRecords)) + _merged = MergeMaps(_merged, e.SwapCharging(config.AmiClassChannelEventLoggings)) + _merged = MergeMaps(_merged, e.SwapCharging(config.AmiClasses)) + _merged = MergeMaps(_merged, e.SwapCharging(config.AmiClassReports)) + _merged = MergeMaps(_merged, e.SwapCharging(config.AmiClassDualToneMultiFrequencies)) chargingEvents = &_merged return chargingEvents @@ -37,7 +36,7 @@ func (e *AMIEvent) SnapChargingEvent() *map[string]string { // SnapChargingEventWith func (e *AMIEvent) SnapChargingEventWith(ls map[string][]string) *map[string]string { - chargingEvents := utils.MergeMaps(*chargingEvents, e.SwapCharging(ls)) + chargingEvents := MergeMaps(*chargingEvents, e.SwapCharging(ls)) return &chargingEvents } diff --git a/pkg/ami/ami_conf.go b/pkg/ami/ami_conf.go index dd97ad5..8e8306f 100644 --- a/pkg/ami/ami_conf.go +++ b/pkg/ami/ami_conf.go @@ -5,7 +5,6 @@ import ( "time" "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) var ( @@ -113,27 +112,27 @@ func (e *AMIExtensionStatus) SetActionId(value string) *AMIExtensionStatus { } func (e *AMIExtensionStatus) SetResponse(value string) *AMIExtensionStatus { - e.Response = utils.TrimAllSpace(value) + e.Response = TrimAllSpace(value) return e } func (e *AMIExtensionStatus) SetMessage(value string) *AMIExtensionStatus { - e.Message = utils.TrimAllSpace(value) + e.Message = TrimAllSpace(value) return e } func (e *AMIExtensionStatus) SetContext(value string) *AMIExtensionStatus { - e.Context = utils.TrimAllSpace(value) + e.Context = TrimAllSpace(value) return e } func (e *AMIExtensionStatus) SetExtension(value string) *AMIExtensionStatus { - e.Extension = utils.TrimAllSpace(value) + e.Extension = TrimAllSpace(value) return e } func (e *AMIExtensionStatus) SetHint(value string) *AMIExtensionStatus { - e.Hint = utils.TrimAllSpace(value) + e.Hint = TrimAllSpace(value) return e } @@ -149,7 +148,7 @@ func (e *AMIExtensionStatus) SetStatusInt(value int) *AMIExtensionStatus { } func (e *AMIExtensionStatus) SetStatusText(value string) *AMIExtensionStatus { - e.StatusText = utils.TrimAllSpace(value) + e.StatusText = TrimAllSpace(value) return e } @@ -189,27 +188,27 @@ func (e *AMIPeerStatus) SetActionId(value string) *AMIPeerStatus { } func (e *AMIPeerStatus) SetChannelType(value string) *AMIPeerStatus { - e.ChannelType = utils.TrimAllSpace(value) + e.ChannelType = TrimAllSpace(value) return e } func (e *AMIPeerStatus) SetEvent(value string) *AMIPeerStatus { - e.Event = utils.TrimAllSpace(value) + e.Event = TrimAllSpace(value) return e } func (e *AMIPeerStatus) SetPeer(value string) *AMIPeerStatus { - e.Peer = utils.TrimAllSpace(value) + e.Peer = TrimAllSpace(value) return e } func (e *AMIPeerStatus) SetPeerStatus(value string) *AMIPeerStatus { - e.PeerStatus = utils.TrimAllSpace(value) + e.PeerStatus = TrimAllSpace(value) return e } func (e *AMIPeerStatus) SetPrivilege(value string) *AMIPeerStatus { - e.Privilege = utils.TrimAllSpace(value) + e.Privilege = TrimAllSpace(value) return e } @@ -229,7 +228,7 @@ func (e *AMIPeerStatus) SetTimeInMsInt(value int) *AMIPeerStatus { } func (e *AMIPeerStatus) SetPrePublishedAt(value string) *AMIPeerStatus { - e.PrePublishedAt = utils.TrimAllSpace(value) + e.PrePublishedAt = TrimAllSpace(value) return e } @@ -239,11 +238,11 @@ func (e *AMIPeerStatus) SetPublishedAt(value time.Time) *AMIPeerStatus { } func (e *AMIPeerStatusGuard) SetDateTimeLayout(value string) *AMIPeerStatusGuard { - e.DateTimeLayout = utils.TrimAllSpace(value) + e.DateTimeLayout = TrimAllSpace(value) return e } func (e *AMIPeerStatusGuard) SetTimezone(value string) *AMIPeerStatusGuard { - e.Timezone = utils.TrimAllSpace(value) + e.Timezone = TrimAllSpace(value) return e } diff --git a/pkg/ami/ami_dialplan.go b/pkg/ami/ami_dialplan.go index eee3ee2..b5367e5 100644 --- a/pkg/ami/ami_dialplan.go +++ b/pkg/ami/ami_dialplan.go @@ -4,7 +4,6 @@ import ( "context" "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) func NewAMIPayloadExtension() *AMIPayloadExtension { @@ -43,7 +42,7 @@ func (e *AMIPayloadExtension) SetReplace(value string) *AMIPayloadExtension { } func (e *AMIPayloadExtension) SetApplicationDataWith(v interface{}) *AMIPayloadExtension { - e.SetApplicationData(utils.ToJson(v)) + e.SetApplicationData(ToJson(v)) return e } diff --git a/pkg/ami/ami_dictionary.go b/pkg/ami/ami_dictionary.go index 8ad711c..fb62a40 100644 --- a/pkg/ami/ami_dictionary.go +++ b/pkg/ami/ami_dictionary.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) var overlapDictionaries *[]AMIEventDictionary = &[]AMIEventDictionary{} @@ -269,7 +268,7 @@ func (d *AMIDictionary) TranslateField(field string) string { return strings.ToLower(value) } else { if d.AllowForceTranslate { - value = utils.TakeValueFromKey(dictionary.Dictionaries, field) + value = TakeValueFromKey(dictionary.Dictionaries, field) if len(value) > 0 { return value } @@ -289,7 +288,7 @@ func (d *AMIDictionary) TranslateFieldWith(field string, dictionaries []AMIEvent return strings.ToLower(v) } else { if d.AllowForceTranslate { - value := utils.TakeValueFromKey(e.Dictionaries, field) + value := TakeValueFromKey(e.Dictionaries, field) if len(value) > 0 { return value } @@ -303,7 +302,7 @@ func (d *AMIDictionary) TranslateFieldWith(field string, dictionaries []AMIEvent func (d *AMIDictionary) TranslateKey(value string) string { dictionary, _ := d.FindDictionaryByKey(config.AmiListenerEventCommon) - _key := utils.TakeKeyFromValue(dictionary.Dictionaries, value) + _key := TakeKeyFromValue(dictionary.Dictionaries, value) if !strings.EqualFold(_key, value) { return _key @@ -318,7 +317,7 @@ func (d *AMIDictionary) TranslateKeyWith(value string, dictionaries []AMIEventDi } for _, e := range dictionaries { - _key := utils.TakeKeyFromValue(e.Dictionaries, value) + _key := TakeKeyFromValue(e.Dictionaries, value) if !strings.EqualFold(_key, value) { return _key } @@ -337,7 +336,7 @@ func (d *AMIDictionary) Reset() { } func (d *AMIDictionary) Json() string { - return utils.ToJson(*overlapDictionaries) + return ToJson(*overlapDictionaries) } func (d *AMIDictionary) LenTranslatorCommon() int { @@ -379,7 +378,7 @@ func (d *AMIDictionary) AddKeysTranslator(script map[string]string) *AMIDictiona // Example: // https://raw.githubusercontent.com/pnguyen215/gear-insights-free/master/ami.dictionaries.json func (d *AMIDictionary) AddKeyLinkTranslator(link string) *AMIDictionary { - keys, err := utils.ForkDictionaryFromLink(link, false) + keys, err := ForkDictionaryFromLink(link, false) if err != nil { return d diff --git a/pkg/ami/ami_event.go b/pkg/ami/ami_event.go index af52b45..3a797a9 100644 --- a/pkg/ami/ami_event.go +++ b/pkg/ami/ami_event.go @@ -5,7 +5,6 @@ import ( "strings" "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) func NewEventListener() *AMIEvent { @@ -31,7 +30,7 @@ func (m *AMIEvent) AppendPhonePrefix(values ...string) *AMIEvent { } func (m *AMIEvent) SetRegion(value string) *AMIEvent { - m.Region = utils.TrimAllSpace(value) + m.Region = TrimAllSpace(value) return m } diff --git a/pkg/ami/ami_tool.go b/pkg/ami/ami_helper.go similarity index 63% rename from pkg/ami/ami_tool.go rename to pkg/ami/ami_helper.go index 40bea45..4a50075 100644 --- a/pkg/ami/ami_tool.go +++ b/pkg/ami/ami_helper.go @@ -4,22 +4,342 @@ import ( "bufio" "bytes" "context" + "encoding/base64" "fmt" "log" "net" + "net/http" "net/textproto" + "net/url" "os" "reflect" "regexp" "strconv" "strings" + "time" + "unicode" + "github.com/go-resty/resty/v2" "github.com/nyaruka/phonenumbers" "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" "github.com/pnguyen215/gobase-voip-core/pkg/ami/fatal" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" + + jsonI "github.com/json-iterator/go" ) +var _json = jsonI.ConfigCompatibleWithStandardLibrary + +func VarsMap(values []string) map[string]string { + r := make(map[string]string) + + for _, value := range values { + k, v := VarsSplit(value) + r[k] = v + } + + return r +} + +func VarsSplit(value string) (string, string) { + s := strings.SplitN(value, "=", 2) + k := s[0] + + if len(s) == 1 { + return k, "" + } + + return k, s[1] +} + +func HasRawConnection(ip string, port int) (bool, error) { + timeout := time.Second + conn, err := net.DialTimeout(config.AmiNetworkTcpKey, net.JoinHostPort(ip, strconv.Itoa(port)), timeout) + + if err != nil { + log.Printf("Connecting error: %v", err) + return false, err + } + + if conn != nil { + defer conn.Close() + log.Printf("Opened on: %s", net.JoinHostPort(ip, strconv.Itoa(port))) + return true, nil + } + + return false, nil +} + +func HasRawConnectionWith(ip string, ports []int) (bool, error) { + for _, port := range ports { + + if ok, err := HasRawConnection(ip, port); err != nil { + return ok, err + } + } + + return true, nil +} + +func IPDecode(ip string) (string, string, error) { + u, err := url.Parse(ip) + + if err != nil { + log.Printf("IP parse has error occurred = %v", err) + return "", "", err + } + + host, port, err := net.SplitHostPort(u.Host) + return host, port, err +} + +func ToJson(data interface{}) string { + s, ok := data.(string) + + if ok { + return s + } + + // result, err := json.Marshal(data) + result, err := MarshalToString(data) + + if err != nil { + log.Printf(err.Error()) + return "" + } + + return string(result) +} + +func ToJsonPretty(data interface{}) string { + s, ok := data.(string) + + if ok { + return s + } + + result, err := MarshalIndent(data, "", " ") + + if err != nil { + log.Printf(err.Error()) + return "" + } + + return string(result) +} + +func TakeKeyFromValue(collection map[string]string, value string) string { + if len(collection) <= 0 { + return value + } + + for k, v := range collection { + if strings.EqualFold(v, value) { + return k + } + } + + return value +} + +func TakeValueFromKey(collection map[string]string, key string) string { + if len(collection) <= 0 { + return key + } + + for k, v := range collection { + if strings.EqualFold(k, key) { + return v + } + } + + return "" +} + +func Keys(in interface{}) (keys []string) { + switch z := in.(type) { + case map[string]int: + case map[string]int32: + case map[string]int64: + case map[string]float32: + case map[string]float64: + case map[string]string: + case map[string]bool: + for k := range z { + keys = append(keys, k) + } + case []int: + for _, k := range z { + keys = append(keys, strconv.Itoa(k)) + } + default: + return []string{} + } + return keys +} + +func MergeMaps[K comparable, V any](m1 map[K]V, m2 map[K]V) map[K]V { + merged := make(map[K]V) + if len(m1) > 0 { + for key, value := range m1 { + merged[key] = value + } + } + if len(m2) > 0 { + for key, value := range m2 { + merged[key] = value + } + } + return merged +} + +// Contains check slice contains value or not +func Contains[T comparable](s []T, e T) bool { + for _, v := range s { + if v == e { + return true + } + } + return false +} + +// ForkDictionaryFromLink +// Link must be provided to file formatted as json +// Return maps[string]string +func ForkDictionaryFromLink(link string, debug bool) (*map[string]string, error) { + client := resty.New() + result := &map[string]string{} + // Set retry count to non zero to enable retries + client.SetRetryCount(3). + // You can override initial retry wait time. + // Default is 100 milliseconds. + SetRetryWaitTime(10 * time.Second). + // MaxWaitTime can be overridden as well. + // Default is 2 seconds. + SetRetryMaxWaitTime(20 * time.Second). + AddRetryCondition( + // RetryConditionFunc type is for retry condition function + // input: non-nil Response OR request execution error + func(r *resty.Response, err error) bool { + return r.StatusCode() >= http.StatusBadRequest && r.StatusCode() <= http.StatusNetworkAuthenticationRequired + }, + ). + // Enable debug mode + SetDebug(debug). + // Add headers + SetHeaders(map[string]string{ + "Content-Type": "application/json", + }) + + _, err := client.R().SetResult(&result).ForceContentType("application/json").Get(link) + + if err != nil { + log.Printf("fork dictionary from link %v has error occurred %v", link, err.Error()) + return result, err + } + + return result, nil +} + +func MarshalToString(v interface{}) (string, error) { + return _json.MarshalToString(v) +} + +func Marshal(v interface{}) ([]byte, error) { + return _json.Marshal(v) +} + +func MarshalNative(v interface{}) ([]byte, error) { + var buf bytes.Buffer + if err := Encode(&buf, "", reflect.ValueOf(v)); err != nil { + return nil, err + } + buf.WriteString(config.AmiSignalLetter) + return buf.Bytes(), nil +} + +func Unmarshal(data []byte, v interface{}) error { + return _json.Unmarshal(data, v) +} + +func UnmarshalFromString(str string, v interface{}) error { + return _json.UnmarshalFromString(str, v) +} + +func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { + return _json.MarshalIndent(v, prefix, indent) +} + +func Base64Encode(v interface{}) string { + d := ToJson(v) + return base64.StdEncoding.EncodeToString([]byte(d)) +} + +func Base64Decode(encoded string) string { + if encoded == "" { + return encoded + } + d, err := base64.StdEncoding.DecodeString(encoded) + if err != nil { + return "" + } + return string(d) +} + +func TrimAllSpace(s string) string { + return strings.Join(strings.Fields(s), " ") +} + +func IsSpace(str string) bool { + for _, c := range str { + if !unicode.IsSpace(c) { + return false + } + } + return true +} + +func IsEmptyAbsolute(str string) bool { + return len(str) == 0 || str == "" || strings.TrimSpace(str) == "" +} + +func IsLetter(s string) bool { + for _, r := range s { + if !unicode.IsLetter(r) { + return false + } + } + return true +} + +// AddTimezone +func AddTimezone(at time.Time, timezone string) (time.Time, error) { + loc, err := time.LoadLocation(timezone) + now := at.In(loc) + return now, err +} + +// SetTimezone +func SetTimezone(at time.Time, timezone string) time.Time { + t, err := AddTimezone(at, timezone) + if err != nil { + return at + } + return t +} + +func RemovePrefix(str string, prefix ...string) string { + if IsEmptyAbsolute(str) { + return str + } + if len(prefix) == 0 { + return str + } + for _, v := range prefix { + str = strings.TrimPrefix(str, v) + } + return str +} + // OpenContext func OpenContext(conn net.Conn) (*AMI, context.Context) { ctx, cancel := context.WithCancel(context.Background()) @@ -65,7 +385,7 @@ func OpenDialWith(network, ip string, port int) (net.Conn, error) { return nil, fatal.AMIErrorNew("AMI: Port must be positive number") } - host, _port, _ := utils.IPDecode(ip) + host, _port, _ := IPDecode(ip) if len(host) > 0 && len(_port) > 0 { form := net.JoinHostPort(host, _port) @@ -250,15 +570,6 @@ func EncodeMap(buf *bytes.Buffer, v reflect.Value) error { return nil } -func Marshal(v interface{}) ([]byte, error) { - var buf bytes.Buffer - if err := Encode(&buf, "", reflect.ValueOf(v)); err != nil { - return nil, err - } - buf.WriteString(config.AmiSignalLetter) - return buf.Bytes(), nil -} - // GenUUID returns a new UUID based on /dev/urandom (unix). func GenUUID() (string, error) { file, err := os.Open("/dev/urandom") @@ -425,7 +736,7 @@ func TransformKeyLevel(response AMIResultRawLevel, d *AMIDictionary) AMIResultRa } func IsPhoneNumber(phone string) bool { - if utils.IsEmptyAbsolute(phone) { + if IsEmptyAbsolute(phone) { return false } matcher := regexp.MustCompile(`^(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d?)\)?)?[\-\.\ \\\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\\/]?){0,})(?:[\-\.\ \\\/]?(?:#|ext\.?|extension|x)[\-\.\ \\\/]?(\d+))?$`) @@ -433,7 +744,7 @@ func IsPhoneNumber(phone string) bool { } func IsPhoneNumberAbsolute(phone string, region string) bool { - if utils.IsEmptyAbsolute(phone) { + if IsEmptyAbsolute(phone) { return false } diff --git a/pkg/ami/ami_manager.go b/pkg/ami/ami_manager.go index 22c40c2..c2c06a3 100644 --- a/pkg/ami/ami_manager.go +++ b/pkg/ami/ami_manager.go @@ -7,7 +7,6 @@ import ( "strings" "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) func NewAuth() *AMIAuth { @@ -116,7 +115,7 @@ func Logoff(ctx context.Context, s AMISocket) error { if err != nil { return err } - log.Printf("Logoff, response = %v", utils.ToJson(response)) + log.Printf("Logoff, response = %v", ToJson(response)) return err } @@ -141,7 +140,7 @@ func Ping(ctx context.Context, s AMISocket) error { return err } - log.Printf("Ping, response = %v", utils.ToJson(response)) + log.Printf("Ping, response = %v", ToJson(response)) return err } diff --git a/pkg/ami/ami_map.go b/pkg/ami/ami_map.go index de5cd6c..3b1649f 100644 --- a/pkg/ami/ami_map.go +++ b/pkg/ami/ami_map.go @@ -6,7 +6,6 @@ import ( "time" "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) func (c *AMICore) ExtensionStatesMap(ctx context.Context, guard *AMIExtensionGuard) (response []AMIExtensionStatus, err error) { @@ -28,13 +27,13 @@ func (c *AMICore) ExtensionStatesMap(ctx context.Context, guard *AMIExtensionGua } if len(guard.Context) > 0 { - if !utils.Contains(guard.Context, v.GetVal(config.AmiJsonFieldContext)) { + if !Contains(guard.Context, v.GetVal(config.AmiJsonFieldContext)) { continue } } if len(guard.StatusesText) > 0 { - if !utils.Contains(guard.StatusesText, v.GetVal(config.AmiJsonFieldStatusText)) { + if !Contains(guard.StatusesText, v.GetVal(config.AmiJsonFieldStatusText)) { continue } } @@ -109,13 +108,13 @@ func (c *AMICore) convRaw2PeerStatus(v AMIResultRaw, g *AMIPeerStatusGuard) *AMI SetPeerStatus(v.GetVal(config.AmiJsonFieldPeerStatus)). SetPrivilege(v.GetVal(config.AmiJsonFieldPrivilege)). SetTimeInMs(v.GetVal(config.AmiJsonFieldTime)). - SetPublishedAt(utils.SetTimezone(time.Now(), g.Timezone)) + SetPublishedAt(SetTimezone(time.Now(), g.Timezone)) if e.TimeInMs > 0 { e.SetPublishedAt(e.PublishedAt.Add(-time.Millisecond * time.Duration(e.TimeInMs))) } - if utils.IsEmptyAbsolute(g.DateTimeLayout) { + if IsEmptyAbsolute(g.DateTimeLayout) { e.SetPrePublishedAt(e.PublishedAt.Format(config.DateTimeFormatYYYYMMDDHHMMSS)) } else { e.SetPrePublishedAt(e.PublishedAt.Format(g.DateTimeLayout)) diff --git a/pkg/ami/ami_message.go b/pkg/ami/ami_message.go index 0ce9e15..e7d7687 100644 --- a/pkg/ami/ami_message.go +++ b/pkg/ami/ami_message.go @@ -13,7 +13,6 @@ import ( "time" "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) func NewActionWith(name string) *AMIMessage { @@ -43,7 +42,7 @@ func (m *AMIMessage) AppendPhonePrefix(values ...string) *AMIMessage { } func (m *AMIMessage) SetRegion(value string) *AMIMessage { - m.Region = utils.TrimAllSpace(value) + m.Region = TrimAllSpace(value) return m } @@ -60,7 +59,7 @@ func ofMessageWithDictionary(d *AMIDictionary, header textproto.MIMEHeader) *AMI p := make(textproto.MIMEHeader) for k, v := range header { p.Add(d.TranslateField(k), header.Get(k)) - log.Printf("(AMI). header renew with key = %v and value = %v", k, utils.ToJson(v)) + log.Printf("(AMI). header renew with key = %v and value = %v", k, ToJson(v)) } m.Header = p } else { @@ -101,7 +100,7 @@ func (k *AMIMessage) FieldByDictionary(d *AMIDictionary, key string) string { func (k *AMIMessage) FieldDictionaryOrRefer(d *AMIDictionary, key, ref string) string { value := k.FieldByDictionary(d, key) - if value != "" && len(value) > 0 && !utils.IsEmptyAbsolute(value) { + if value != "" && len(value) > 0 && !IsEmptyAbsolute(value) { return value } @@ -324,7 +323,7 @@ func (k *AMIMessage) VarWith(key string, vars []string) (string, bool) { } for _, value := range vars { - e, v := utils.VarsSplit(value) + e, v := VarsSplit(value) if e == key || strings.EqualFold(e, key) { return v, true } @@ -368,7 +367,7 @@ func (k *AMIMessage) ProduceMessageWithDictionaries(lowercaseField bool, transla if len(value) == 1 { data[field] = value[0] } else { - data[field] = utils.VarsMap(value) + data[field] = VarsMap(value) } } @@ -388,7 +387,7 @@ func (k *AMIMessage) ProduceMessagePure() map[string]interface{} { if len(value) == 1 { data[field] = value[0] } else { - data[field] = utils.VarsMap(value) + data[field] = VarsMap(value) } } @@ -397,17 +396,17 @@ func (k *AMIMessage) ProduceMessagePure() map[string]interface{} { // Return AMI message as Json string func (k *AMIMessage) Json() string { - return utils.ToJson(k.ProduceMessage()) + return ToJson(k.ProduceMessage()) } // Return AMI message as Json string func (k *AMIMessage) JsonTranslator(d *AMIDictionary) string { - return utils.ToJson(k.ProduceMessageTranslator(d)) + return ToJson(k.ProduceMessageTranslator(d)) } // Return AMI message as Json pure string func (k *AMIMessage) JsonPure() string { - return utils.ToJson(k.ProduceMessagePure()) + return ToJson(k.ProduceMessagePure()) } // Create AMI message from json string @@ -467,7 +466,7 @@ func (a *AMIPayloadMessage) SetBody(value string) *AMIPayloadMessage { } func (a *AMIPayloadMessage) SetBase64Body(value interface{}) *AMIPayloadMessage { - a.Base64Body = utils.Base64Encode(value) + a.Base64Body = Base64Encode(value) return a } diff --git a/pkg/ami/ami_originate.go b/pkg/ami/ami_originate.go index 683c793..def43bb 100644 --- a/pkg/ami/ami_originate.go +++ b/pkg/ami/ami_originate.go @@ -7,7 +7,6 @@ import ( "strings" "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) func NewAMIPayloadOriginate() *AMIPayloadOriginate { @@ -60,7 +59,7 @@ func (o *AMIPayloadOriginate) SetData(value string) *AMIPayloadOriginate { } func (o *AMIPayloadOriginate) SetDataWith(value interface{}) *AMIPayloadOriginate { - o.SetData(utils.ToJson(value)) + o.SetData(ToJson(value)) return o } @@ -131,7 +130,7 @@ func (o *AMIPayloadOriginate) SetOtherChannelId(value string) *AMIPayloadOrigina } func (o *AMIPayloadOriginate) Json() string { - return utils.ToJson(o) + return ToJson(o) } func (o *AMIOriginateDirection) SetTelephone(value string) *AMIOriginateDirection { @@ -169,7 +168,7 @@ func (o *AMIOriginateDirection) SetAllowSysValidator(value bool) *AMIOriginateDi } func (o *AMIOriginateDirection) Json() string { - return utils.ToJson(o) + return ToJson(o) } // MakeCall diff --git a/pkg/ami/ami_socket.go b/pkg/ami/ami_socket.go index 7eaa437..b610698 100644 --- a/pkg/ami/ami_socket.go +++ b/pkg/ami/ami_socket.go @@ -11,7 +11,6 @@ import ( "strings" "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) func NewAMISocket() *AMISocket { @@ -55,7 +54,7 @@ func (s *AMISocket) SetMaxConcurrencyMillis(value int64) *AMISocket { } func (s *AMISocket) Json() string { - return utils.ToJson(s) + return ToJson(s) } // NewSocket provides a new socket client, connecting to a tcp server. @@ -217,7 +216,7 @@ func (s AMIResultRaw) Values() []string { continue } v := s.GetVal(k) - if !utils.Contains(result, v) { + if !Contains(result, v) { result = append(result, v) } } @@ -267,7 +266,7 @@ func (s AMIResultRawLevel) GetVal(key string) string { if len(v) == 1 { return v[0] } - return utils.ToJson(v) + return ToJson(v) } func (s AMIResultRawLevel) Values() []string { @@ -280,7 +279,7 @@ func (s AMIResultRawLevel) Values() []string { continue } v := s.GetVal(k) - if !utils.Contains(result, v) { + if !Contains(result, v) { result = append(result, v) } } diff --git a/pkg/ami/ami_update_config.go b/pkg/ami/ami_update_config.go index 4a428b1..60e9ae7 100644 --- a/pkg/ami/ami_update_config.go +++ b/pkg/ami/ami_update_config.go @@ -3,8 +3,6 @@ package ami import ( "fmt" "strings" - - "github.com/pnguyen215/gobase-voip-core/pkg/ami/utils" ) func NewAMIUpdateConfigAction() *AMIUpdateConfigAction { @@ -47,7 +45,7 @@ func (a *AMIUpdateConfigAction) SetVarsMap(delimiter string, variables map[strin } _vars := make([]string, len(variables)) for k, v := range variables { - str := fmt.Sprintf("%s=%v", k, utils.ToJson(v)) + str := fmt.Sprintf("%s=%v", k, ToJson(v)) _vars = append(_vars, str) } a.SetVars(delimiter, _vars...) diff --git a/pkg/ami/utils/ami_utils.go b/pkg/ami/utils/ami_utils.go deleted file mode 100644 index b4b2b50..0000000 --- a/pkg/ami/utils/ami_utils.go +++ /dev/null @@ -1,322 +0,0 @@ -package utils - -import ( - "encoding/base64" - "log" - "net" - "net/http" - "net/url" - "strconv" - "strings" - "time" - "unicode" - - "github.com/go-resty/resty/v2" - "github.com/pnguyen215/gobase-voip-core/pkg/ami/config" - - jsonI "github.com/json-iterator/go" -) - -var _json = jsonI.ConfigCompatibleWithStandardLibrary - -func VarsMap(values []string) map[string]string { - r := make(map[string]string) - - for _, value := range values { - k, v := VarsSplit(value) - r[k] = v - } - - return r -} - -func VarsSplit(value string) (string, string) { - s := strings.SplitN(value, "=", 2) - k := s[0] - - if len(s) == 1 { - return k, "" - } - - return k, s[1] -} - -func HasRawConnection(ip string, port int) (bool, error) { - timeout := time.Second - conn, err := net.DialTimeout(config.AmiNetworkTcpKey, net.JoinHostPort(ip, strconv.Itoa(port)), timeout) - - if err != nil { - log.Printf("Connecting error: %v", err) - return false, err - } - - if conn != nil { - defer conn.Close() - log.Printf("Opened on: %s", net.JoinHostPort(ip, strconv.Itoa(port))) - return true, nil - } - - return false, nil -} - -func HasRawConnectionWith(ip string, ports []int) (bool, error) { - for _, port := range ports { - - if ok, err := HasRawConnection(ip, port); err != nil { - return ok, err - } - } - - return true, nil -} - -func IPDecode(ip string) (string, string, error) { - u, err := url.Parse(ip) - - if err != nil { - log.Printf("IP parse has error occurred = %v", err) - return "", "", err - } - - host, port, err := net.SplitHostPort(u.Host) - return host, port, err -} - -func ToJson(data interface{}) string { - s, ok := data.(string) - - if ok { - return s - } - - // result, err := json.Marshal(data) - result, err := MarshalToString(data) - - if err != nil { - log.Printf(err.Error()) - return "" - } - - return string(result) -} - -func ToJsonPretty(data interface{}) string { - s, ok := data.(string) - - if ok { - return s - } - - result, err := MarshalIndent(data, "", " ") - - if err != nil { - log.Printf(err.Error()) - return "" - } - - return string(result) -} - -func TakeKeyFromValue(collection map[string]string, value string) string { - if len(collection) <= 0 { - return value - } - - for k, v := range collection { - if strings.EqualFold(v, value) { - return k - } - } - - return value -} - -func TakeValueFromKey(collection map[string]string, key string) string { - if len(collection) <= 0 { - return key - } - - for k, v := range collection { - if strings.EqualFold(k, key) { - return v - } - } - - return "" -} - -func Keys(in interface{}) (keys []string) { - switch z := in.(type) { - case map[string]int: - case map[string]int32: - case map[string]int64: - case map[string]float32: - case map[string]float64: - case map[string]string: - case map[string]bool: - for k := range z { - keys = append(keys, k) - } - case []int: - for _, k := range z { - keys = append(keys, strconv.Itoa(k)) - } - default: - return []string{} - } - return keys -} - -func MergeMaps[K comparable, V any](m1 map[K]V, m2 map[K]V) map[K]V { - merged := make(map[K]V) - if len(m1) > 0 { - for key, value := range m1 { - merged[key] = value - } - } - if len(m2) > 0 { - for key, value := range m2 { - merged[key] = value - } - } - return merged -} - -// Contains check slice contains value or not -func Contains[T comparable](s []T, e T) bool { - for _, v := range s { - if v == e { - return true - } - } - return false -} - -// ForkDictionaryFromLink -// Link must be provided to file formatted as json -// Return maps[string]string -func ForkDictionaryFromLink(link string, debug bool) (*map[string]string, error) { - client := resty.New() - result := &map[string]string{} - // Set retry count to non zero to enable retries - client.SetRetryCount(3). - // You can override initial retry wait time. - // Default is 100 milliseconds. - SetRetryWaitTime(10 * time.Second). - // MaxWaitTime can be overridden as well. - // Default is 2 seconds. - SetRetryMaxWaitTime(20 * time.Second). - AddRetryCondition( - // RetryConditionFunc type is for retry condition function - // input: non-nil Response OR request execution error - func(r *resty.Response, err error) bool { - return r.StatusCode() >= http.StatusBadRequest && r.StatusCode() <= http.StatusNetworkAuthenticationRequired - }, - ). - // Enable debug mode - SetDebug(debug). - // Add headers - SetHeaders(map[string]string{ - "Content-Type": "application/json", - }) - - _, err := client.R().SetResult(&result).ForceContentType("application/json").Get(link) - - if err != nil { - log.Printf("fork dictionary from link %v has error occurred %v", link, err.Error()) - return result, err - } - - return result, nil -} - -func MarshalToString(v interface{}) (string, error) { - return _json.MarshalToString(v) -} - -func Marshal(v interface{}) ([]byte, error) { - return _json.Marshal(v) -} - -func Unmarshal(data []byte, v interface{}) error { - return _json.Unmarshal(data, v) -} - -func UnmarshalFromString(str string, v interface{}) error { - return _json.UnmarshalFromString(str, v) -} - -func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { - return _json.MarshalIndent(v, prefix, indent) -} - -func Base64Encode(v interface{}) string { - d := ToJson(v) - return base64.StdEncoding.EncodeToString([]byte(d)) -} - -func Base64Decode(encoded string) string { - if encoded == "" { - return encoded - } - d, err := base64.StdEncoding.DecodeString(encoded) - if err != nil { - return "" - } - return string(d) -} - -func TrimAllSpace(s string) string { - return strings.Join(strings.Fields(s), " ") -} - -func IsSpace(str string) bool { - for _, c := range str { - if !unicode.IsSpace(c) { - return false - } - } - return true -} - -func IsEmptyAbsolute(str string) bool { - return len(str) == 0 || str == "" || strings.TrimSpace(str) == "" -} - -func IsLetter(s string) bool { - for _, r := range s { - if !unicode.IsLetter(r) { - return false - } - } - return true -} - -// AddTimezone -func AddTimezone(at time.Time, timezone string) (time.Time, error) { - loc, err := time.LoadLocation(timezone) - now := at.In(loc) - return now, err -} - -// SetTimezone -func SetTimezone(at time.Time, timezone string) time.Time { - t, err := AddTimezone(at, timezone) - if err != nil { - return at - } - return t -} - -func RemovePrefix(str string, prefix ...string) string { - if IsEmptyAbsolute(str) { - return str - } - if len(prefix) == 0 { - return str - } - for _, v := range prefix { - str = strings.TrimPrefix(str, v) - } - return str -} diff --git a/pkg/bot/telegram/telegram_bot.go b/pkg/bot/telegram/telegram_bot.go deleted file mode 100644 index a0918a3..0000000 --- a/pkg/bot/telegram/telegram_bot.go +++ /dev/null @@ -1,135 +0,0 @@ -package telegram - -import ( - "encoding/json" - "errors" - "log" - "strings" - - telegramBot "github.com/go-telegram-bot-api/telegram-bot-api/v5" -) - -var preTelegram *telegramBot.BotAPI - -func NewBotWith(token string, chatId int64) (*telegramBot.BotAPI, error) { - t := &TelegramBot{ - Token: token, - ChatId: chatId, - DebugMode: true, - Enabled: true, - } - return t.NewBot() -} - -func NewBotWithMultiChatId(token string, chatId []int64) (*telegramBot.BotAPI, error) { - t := &TelegramBot{ - Token: token, - MultiChatId: chatId, - DebugMode: true, - Enabled: true, - } - return t.NewBot() -} - -func (t *TelegramBot) NewBot() (*telegramBot.BotAPI, error) { - - if !t.Enabled { - return &telegramBot.BotAPI{}, errors.New("Telegram Bot unavailable") - } - - if strings.EqualFold(t.Token, "") { - return &telegramBot.BotAPI{}, errors.New("Token telegram bot must be provided") - } - - if preTelegram != nil { - return preTelegram, nil - } - - bot, err := telegramBot.NewBotAPI(t.Token) - bot.Debug = t.DebugMode - preTelegram = bot - return bot, err -} - -func (t *TelegramBot) ResetBot() { - preTelegram = nil -} - -func (t *TelegramBot) ToJson(data interface{}) string { - s, ok := data.(string) - - if ok { - return s - } - - result, err := json.Marshal(data) - - if err != nil { - log.Printf(err.Error()) - return "" - } - - return string(result) -} - -// Send message as simple -// message will be sent to only one channel or group via chat id -func (t *TelegramBot) SendMessage(message interface{}) (telegramBot.Message, error) { - if t.ChatId == 0 { - return telegramBot.Message{}, errors.New("Chat Id must be provided") - } - - bot, err := t.NewBot() - if err != nil { - return telegramBot.Message{}, err - } - - content := t.ToJson(message) - _message := telegramBot.NewMessage(t.ChatId, content) - _message.ParseMode = telegramBot.ModeHTML - response, err := bot.Send(_message) - return response, err -} - -// Send message to multi chat id (group or channel) -// refer `mode` from telegram_config.go -func (t *TelegramBot) SendMessages(mode string, message interface{}) ([]telegramBot.Message, error) { - var response []telegramBot.Message - - if len(t.MultiChatId) == 0 { - return response, errors.New("Multi chat Id must be provided") - } - - bot, err := t.NewBot() - if err != nil { - log.Fatal(err) - return response, err - } - - key, ok := TelegramMessageMode[mode] - - if !ok { - key = telegramBot.ModeHTML - } - - content := t.ToJson(message) - for _, v := range t.MultiChatId { - _message := telegramBot.NewMessage(v, content) - _message.ParseMode = key - _response, err := bot.Send(_message) - - if err != nil { - log.Fatal(err) - return response, err - } - response = append(response, _response) - } - - return response, nil -} - -// Send message to multi chat id (group or channel) -// refer `mode` from telegram_config.go -func (t *TelegramBot) SendMessagesWith(message interface{}) ([]telegramBot.Message, error) { - return t.SendMessages("html", message) -} diff --git a/pkg/bot/telegram/telegram_config.go b/pkg/bot/telegram/telegram_config.go deleted file mode 100644 index 66bf333..0000000 --- a/pkg/bot/telegram/telegram_config.go +++ /dev/null @@ -1,11 +0,0 @@ -package telegram - -import telegramBot "github.com/go-telegram-bot-api/telegram-bot-api/v5" - -var ( - TelegramMessageMode map[string]string = map[string]string{ - "markdown_v1": telegramBot.ModeMarkdown, - "markdown_v2": telegramBot.ModeMarkdownV2, - "html": telegramBot.ModeHTML, - } -) diff --git a/pkg/bot/telegram/telegram_model.go b/pkg/bot/telegram/telegram_model.go deleted file mode 100644 index 5f7ff27..0000000 --- a/pkg/bot/telegram/telegram_model.go +++ /dev/null @@ -1,9 +0,0 @@ -package telegram - -type TelegramBot struct { - Enabled bool `json:"enabled"` - Token string `json:"telegram_bot_token"` - ChatId int64 `json:"telegram_chat_id"` - DebugMode bool `json:"debug_mode"` - MultiChatId []int64 `json:"multi_chat_id"` -}