FS-8799 [mod_callcenter] Add JSON API interface for mod_callcenter

Adding a JSON API interface to fetch data in the JSON format. It abides with the JSON command and its implementations by other modules like mod_verto.
It outputs the exactly same column names as the data in CLI.
Various listing of mod_callcenter data such as agents, queues, members, tiers are as follows below.

- Listing of agents
Command: `json {"command": "callcenter_config", "format": "pretty", "data": {"arguments":"agent list"}}`

- Listing of queues
Command: `json {"command": "callcenter_config", "format": "pretty", "data": {"arguments":"queue list"}}`

- Listing of agents for a queue
Command: `json {"command": "callcenter_config", "data": {"arguments":"queue list agents", "queue_name":"support@default"}}`
(`queue_name` is a required)

- Listing of members(callers) for a queue
Command: `json {"command": "callcenter_config", "data": {"arguments":"queue list members", "queue_name":"support@default"}}`

- Listing of tiers for a queue
Command: `json {"command": "callcenter_config","data": {"arguments":"queue list tiers", "queue_name":"support@default"}}`

- Listing of members(callers)
Command: `json {"command": "callcenter_config","data": {"arguments":"member list"}}`

- Listing of tiers
Command: `json {"command": "callcenter_config","data": {"arguments":"tier list"}}`

It handles various errors and also returns back response in JSON as follow
E.g. Send a command without a required field (`queue_name`)
Command: `json {"command": "callcenter_config", "data": {"arguments":"queue list agents"}}`
Output: `{"command":"callcenter_config","data":{"arguments":"queue list agents"},"status":"error","message":"The command returned an error","response":{"error":"Missing data attribute: queue_name"}}`
This commit is contained in:
rajeshvaya 2016-01-28 12:38:00 +04:00
parent 8daa71eb14
commit 23e53df721
1 changed files with 186 additions and 1 deletions

View File

@ -2925,6 +2925,29 @@ static int list_result_callback(void *pArg, int argc, char **argv, char **column
return 0;
}
struct list_result_json {
const char *name;
const char *format;
int row_process;
switch_stream_handle_t *stream;
cJSON *json_reply;
};
static int list_result_json_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct list_result_json *cbt = (struct list_result_json *) pArg;
cJSON *o = cJSON_CreateObject();
int i = 0;
cbt->row_process++;
for ( i = 0; i < argc; i++) {
cJSON_AddItemToObject(o, columnNames[i], cJSON_CreateString(argv[i]));
}
cJSON_AddItemToArray(cbt->json_reply, o);
return 0;
}
#define CC_CONFIG_API_SYNTAX "callcenter_config <target> <args>,\n"\
"\tcallcenter_config agent add [name] [type] | \n" \
"\tcallcenter_config agent del [name] | \n" \
@ -3124,7 +3147,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
switch_safe_free(sql);
stream->write_function(stream, "%s", "+OK\n");
}
} else if (section && !strcasecmp(section, "tier")) {
if (action && !strcasecmp(action, "add")) {
if (argc-initial_argc < 2) {
@ -3414,11 +3437,171 @@ done:
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_JSON_API(json_callcenter_config_function)
{
cJSON *data = cJSON_GetObjectItem(json, "data");
const char *error = NULL;
const char *arguments = cJSON_GetObjectCstr(data, "arguments");
/* Validate the arguments - try to keep it similar to the CLI api */
if(zstr(arguments)){
return SWITCH_STATUS_FALSE;
}
/* Prepare the JSON for list of agents */
if(!strcasecmp(arguments, "agent list")){
struct list_result_json cbt;
char *sql;
cbt.row_process = 0;
cbt.json_reply = cJSON_CreateArray();
sql = switch_mprintf("SELECT * FROM agents");
cc_execute_sql_callback(NULL /* queue */, NULL /* mutex */, sql, list_result_json_callback, &cbt /* Call back variables */);
switch_safe_free(sql);
*json_reply = cbt.json_reply;
return SWITCH_STATUS_SUCCESS;
}
/* Prepare the JSON for list of queues */
if(!strcasecmp(arguments, "queue list")){
cJSON *reply = cJSON_CreateArray();
switch_hash_index_t *hi;
switch_mutex_lock(globals.mutex);
for (hi = switch_core_hash_first(globals.queue_hash); hi; hi = switch_core_hash_next(&hi)) {
cJSON *o = cJSON_CreateObject();
void *val = NULL;
const void *key;
switch_ssize_t keylen;
cc_queue_t *queue;
switch_core_hash_this(hi, &key, &keylen, &val);
queue = (cc_queue_t *) val;
cJSON_AddItemToObject(o, "name", cJSON_CreateString(queue->name));
cJSON_AddItemToObject(o, "strategy", cJSON_CreateString(queue->strategy));
cJSON_AddItemToObject(o, "moh_sound", cJSON_CreateString(queue->moh));
cJSON_AddItemToObject(o, "time_base_score", cJSON_CreateString(queue->time_base_score));
cJSON_AddItemToObject(o, "tier_rules_apply", cJSON_CreateString(queue->tier_rules_apply ? "true" : "false"));
cJSON_AddItemToObject(o, "tier_rule_wait_second", cJSON_CreateNumber(queue->tier_rule_wait_second));
cJSON_AddItemToObject(o, "tier_rule_wait_multiply_level", cJSON_CreateString(queue->tier_rule_wait_multiply_level ? "true": "false"));
cJSON_AddItemToObject(o, "tier_rule_no_agent_no_wait", cJSON_CreateString(queue->tier_rule_no_agent_no_wait ? "true": "false"));
cJSON_AddItemToObject(o, "discard_abandoned_after", cJSON_CreateNumber(queue->discard_abandoned_after));
cJSON_AddItemToObject(o, "abandoned_resume_allowed", cJSON_CreateString(queue->abandoned_resume_allowed ? "true": "false"));
cJSON_AddItemToObject(o, "max_wait_time", cJSON_CreateNumber(queue->max_wait_time));
cJSON_AddItemToObject(o, "max_wait_time_with_no_agent", cJSON_CreateNumber(queue->max_wait_time_with_no_agent));
cJSON_AddItemToObject(o, "max_wait_time_with_no_agent_time_reached", cJSON_CreateNumber(queue->max_wait_time_with_no_agent_time_reached));
cJSON_AddItemToObject(o, "record_template", cJSON_CreateString(queue->record_template));
cJSON_AddItemToArray(reply, o);
queue = NULL;
}
switch_mutex_unlock(globals.mutex);
*json_reply = reply;
return SWITCH_STATUS_SUCCESS;
}
/* Prepare the JSON for list of agents for a queue */
if(!strcasecmp(arguments, "queue list agents")){
struct list_result_json cbt;
const char *queue_name = cJSON_GetObjectCstr(data, "queue_name");
char *sql;
cJSON *error_reply = cJSON_CreateObject();
if (zstr(queue_name)) {
error = "Missing data attribute: queue_name";
cJSON_AddItemToObject(error_reply, "error", cJSON_CreateString(error));
*json_reply = error_reply;
return SWITCH_STATUS_FALSE;
}
cbt.row_process = 0;
cbt.json_reply = cJSON_CreateArray();
sql = switch_mprintf("SELECT agents.* FROM agents,tiers WHERE tiers.agent = agents.name AND tiers.queue = '%q'", queue_name);
cc_execute_sql_callback(NULL /* queue */, NULL /* mutex */, sql, list_result_json_callback, &cbt /* Call back variables */);
switch_safe_free(sql);
*json_reply = cbt.json_reply;
return SWITCH_STATUS_SUCCESS;
}
/* Prepare the JSON for list of callers for a queue */
if(!strcasecmp(arguments, "queue list members")){
struct list_result_json cbt;
const char *queue_name = cJSON_GetObjectCstr(data, "queue_name");
char *sql;
cJSON *error_reply = cJSON_CreateObject();
if (zstr(queue_name)) {
error = "Missing data attribute: queue_name";
cJSON_AddItemToObject(error_reply, "error", cJSON_CreateString(error));
*json_reply = error_reply;
return SWITCH_STATUS_FALSE;
}
cbt.row_process = 0;
cbt.json_reply = cJSON_CreateArray();
sql = switch_mprintf("SELECT *,(%" SWITCH_TIME_T_FMT "-joined_epoch)+base_score+skill_score AS score FROM members WHERE queue = '%q' ORDER BY score DESC;", local_epoch_time_now(NULL), queue_name);
cc_execute_sql_callback(NULL /* queue */, NULL /* mutex */, sql, list_result_json_callback, &cbt /* Call back variables */);
switch_safe_free(sql);
*json_reply = cbt.json_reply;
return SWITCH_STATUS_SUCCESS;
}
/* Prepare the JSON for list of tiers for a queue */
if(!strcasecmp(arguments, "queue list tiers")){
struct list_result_json cbt;
const char *queue_name = cJSON_GetObjectCstr(data, "queue_name");
char *sql;
cJSON *error_reply = cJSON_CreateObject();
if (zstr(queue_name)) {
error = "Missing data attribute: queue_name";
cJSON_AddItemToObject(error_reply, "error", cJSON_CreateString(error));
*json_reply = error_reply;
return SWITCH_STATUS_FALSE;
}
cbt.row_process = 0;
cbt.json_reply = cJSON_CreateArray();
sql = switch_mprintf("SELECT * FROM tiers WHERE queue = '%q';", queue_name);
cc_execute_sql_callback(NULL /* queue */, NULL /* mutex */, sql, list_result_json_callback, &cbt /* Call back variables */);
switch_safe_free(sql);
*json_reply = cbt.json_reply;
return SWITCH_STATUS_SUCCESS;
}
/* Prepare the JSON for list of all callers */
if(!strcasecmp(arguments, "member list")){
struct list_result_json cbt;
char *sql;
cbt.row_process = 0;
cbt.json_reply = cJSON_CreateArray();
sql = switch_mprintf("SELECT *,(%" SWITCH_TIME_T_FMT "-joined_epoch)+base_score+skill_score AS score FROM members ORDER BY score DESC;", local_epoch_time_now(NULL));
cc_execute_sql_callback(NULL /* queue */, NULL /* mutex */, sql, list_result_json_callback, &cbt /* Call back variables */);
switch_safe_free(sql);
*json_reply = cbt.json_reply;
return SWITCH_STATUS_SUCCESS;
}
/* Prepare the JSON for list of all tiers */
if(!strcasecmp(arguments, "tier list")){
struct list_result_json cbt;
char *sql;
cbt.row_process = 0;
cbt.json_reply = cJSON_CreateArray();
sql = switch_mprintf("SELECT * FROM tiers ORDER BY level, position");
cc_execute_sql_callback(NULL /* queue */, NULL /* mutex */, sql, list_result_json_callback, &cbt /* Call back variables */);
switch_safe_free(sql);
*json_reply = cbt.json_reply;
return SWITCH_STATUS_SUCCESS;
}
/* if nothing was executed from above, it should return error */
return SWITCH_STATUS_FALSE;
}
/* Macro expands to: switch_status_t mod_callcenter_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
SWITCH_MODULE_LOAD_FUNCTION(mod_callcenter_load)
{
switch_application_interface_t *app_interface;
switch_api_interface_t *api_interface;
switch_json_api_interface_t *json_api_interface;
switch_status_t status;
@ -3451,6 +3634,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_callcenter_load)
SWITCH_ADD_APP(app_interface, "callcenter", "CallCenter", CC_DESC, callcenter_function, CC_USAGE, SAF_NONE);
SWITCH_ADD_API(api_interface, "callcenter_config", "Config of callcenter", cc_config_api_function, CC_CONFIG_API_SYNTAX);
SWITCH_ADD_JSON_API(json_api_interface, "callcenter_config", "JSON Callcenter API", json_callcenter_config_function, "");
switch_console_set_complete("add callcenter_config agent add");
switch_console_set_complete("add callcenter_config agent del");
switch_console_set_complete("add callcenter_config agent reload");