diff --git a/actions/actions.go b/actions/actions.go
index 301a3fa23..0e121b3fc 100644
--- a/actions/actions.go
+++ b/actions/actions.go
@@ -66,3 +66,56 @@ func (aS *ActionS) Shutdown() (err error) {
func (aS *ActionS) Call(serviceMethod string, args interface{}, reply interface{}) error {
return utils.RPCCall(aS, serviceMethod, args, reply)
}
+
+// matchingActionProfilesForEvent returns the matched ActionProfiles for the given event
+func (aS *ActionS) matchingActionProfilesForEvent(tnt string, aPrflIDs []string,
+ cgrEv *utils.CGREventWithOpts) (actPrfls engine.ActionProfiles, err error) {
+ evNm := utils.MapStorage{
+ utils.MetaReq: cgrEv.CGREvent.Event,
+ utils.MetaOpts: cgrEv.Opts,
+ }
+ if len(aPrflIDs) == 0 {
+ var aPfIDMp utils.StringSet
+ if aPfIDMp, err = engine.MatchingItemIDsForEvent(
+ evNm,
+ aS.cfg.ActionSCfg().StringIndexedFields,
+ aS.cfg.ActionSCfg().PrefixIndexedFields,
+ aS.cfg.ActionSCfg().SuffixIndexedFields,
+ aS.dm,
+ utils.CacheActionProfilesFilterIndexes,
+ tnt,
+ aS.cfg.ActionSCfg().IndexedSelects,
+ aS.cfg.ActionSCfg().NestedFields,
+ ); err != nil {
+ return
+ }
+ aPrflIDs = aPfIDMp.AsSlice()
+ }
+ for _, aPfID := range aPrflIDs {
+ var aPf *engine.ActionProfile
+ if aPf, err = aS.dm.GetActionProfile(tnt, aPfID,
+ true, true, utils.NonTransactional); err != nil {
+ if err == utils.ErrNotFound {
+ err = nil
+ continue
+ }
+ return
+ }
+ if aPf.ActivationInterval != nil && cgrEv.Time != nil &&
+ !aPf.ActivationInterval.IsActiveAtTime(*cgrEv.Time) { // not active
+ continue
+ }
+ var pass bool
+ if pass, err = aS.fltrS.Pass(tnt, aPf.FilterIDs, evNm); err != nil {
+ return
+ } else if !pass {
+ continue
+ }
+ actPrfls = append(actPrfls, aPf)
+ }
+ if len(actPrfls) == 0 {
+ return nil, utils.ErrNotFound
+ }
+ actPrfls.Sort()
+ return
+}
diff --git a/config/actionscfg.go b/config/actionscfg.go
new file mode 100644
index 000000000..4c5117656
--- /dev/null
+++ b/config/actionscfg.go
@@ -0,0 +1,29 @@
+/*
+Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+
+package config
+
+// ActionSCfg is the configuration of ActionS
+type ActionSCfg struct {
+ Enabled bool
+ IndexedSelects bool
+ StringIndexedFields *[]string
+ PrefixIndexedFields *[]string
+ SuffixIndexedFields *[]string
+ NestedFields bool
+}
diff --git a/config/config.go b/config/config.go
index ad7928854..2e2460844 100644
--- a/config/config.go
+++ b/config/config.go
@@ -194,6 +194,7 @@ func newCGRConfig(config []byte) (cfg *CGRConfig, err error) {
cfg.eesCfg = new(EEsCfg)
cfg.eesCfg.Cache = make(map[string]*CacheParamCfg)
cfg.rateSCfg = new(RateSCfg)
+ //cfg.actionSCfg = new(ActionSCfg)
cfg.sipAgentCfg = new(SIPAgentCfg)
cfg.configSCfg = new(ConfigSCfg)
cfg.apiBanCfg = new(APIBanCfg)
@@ -326,6 +327,7 @@ type CGRConfig struct {
ersCfg *ERsCfg // EventReader config
eesCfg *EEsCfg // EventExporter config
rateSCfg *RateSCfg // RateS config
+ actionSCfg *ActionSCfg // ActionS config
sipAgentCfg *SIPAgentCfg // SIPAgent config
configSCfg *ConfigSCfg // ConfigS config
apiBanCfg *APIBanCfg // APIBan config
@@ -1088,6 +1090,13 @@ func (cfg *CGRConfig) RateSCfg() *RateSCfg {
return cfg.rateSCfg
}
+// ActionSCfg reads the ActionS configuration
+func (cfg *CGRConfig) ActionSCfg() *ActionSCfg {
+ cfg.lks[ActionSJson].RLock()
+ defer cfg.lks[ActionSJson].RUnlock()
+ return cfg.actionSCfg
+}
+
// SIPAgentCfg reads the Apier configuration
func (cfg *CGRConfig) SIPAgentCfg() *SIPAgentCfg {
cfg.lks[SIPAgentJson].Lock()
diff --git a/config/config_json.go b/config/config_json.go
index ab9d3a999..d75be742e 100644
--- a/config/config_json.go
+++ b/config/config_json.go
@@ -60,6 +60,7 @@ const (
ERsJson = "ers"
EEsJson = "ees"
RateSJson = "rates"
+ ActionSJson = "actions"
RPCConnsJsonName = "rpc_conns"
SIPAgentJson = "sip_agent"
TemplatesJson = "templates"
diff --git a/engine/actionprofile.go b/engine/actionprofile.go
index aa3c65c8b..85a3132bc 100644
--- a/engine/actionprofile.go
+++ b/engine/actionprofile.go
@@ -19,6 +19,7 @@ along with this program. If not, see
package engine
import (
+ "sort"
"time"
"github.com/cgrates/cgrates/config"
@@ -42,6 +43,14 @@ func (aP *ActionProfile) TenantID() string {
return utils.ConcatenatedKey(aP.Tenant, aP.ID)
}
+// ActionProfiles is a sortable list of ActionProfiles
+type ActionProfiles []*ActionProfile
+
+// Sort is part of sort interface, sort based on Weight
+func (aps ActionProfiles) Sort() {
+ sort.Slice(aps, func(i, j int) bool { return aps[i].Weight > aps[j].Weight })
+}
+
// APAction defines action related information used within a ActionProfile
type APAction struct {
ID string // Action ID
@@ -54,6 +63,7 @@ type APAction struct {
Value config.RSRParsers // Value to execute on path
}
+// ActionProfileWithOpts is used in API calls
type ActionProfileWithOpts struct {
*ActionProfile
Opts map[string]interface{}