Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import (
- "database/sql"
- "encoding/json"
- "fmt"
- curl "github.com/andelf/go-curl"
- _ "github.com/go-sql-driver/mysql"
- "github.com/ivahaev/amigo"
- "os"
- "strconv"
- "strings"
- "time"
- )
- type AccountCode struct {
- o string
- e int
- t string
- }
- type Config struct {
- Manager struct {
- User string `json:"user"`
- Pass string `json:"pass"`
- Host string `json:"host"`
- } `json:"manager"`
- Database struct {
- User string `json:"user"`
- Pass string `json:"pass"`
- Host string `json:"host"`
- Name string `json:"name"`
- } `json:"database"`
- API struct {
- URLCrm string `json:"url_crm"`
- URLPeerUse string `json:"url_peer_use"`
- URLGetOperator string `json:"url_get_operator"`
- Key string `json:"key"`
- } `json:"api"`
- }
- //var db *sql.DB
- var a *amigo.Amigo
- var config Config
- func return_curl(url string, data string) {
- easy := curl.EasyInit()
- defer easy.Cleanup()
- if easy != nil {
- easy.Setopt(curl.OPT_URL, url)
- easy.Setopt(curl.OPT_CUSTOMREQUEST, "POST")
- easy.Setopt(curl.OPT_FRESH_CONNECT, 1)
- easy.Setopt(curl.OPT_TIMEOUT_MS, 150)
- easy.Setopt(curl.OPT_HTTPHEADER, []string{
- "Content-Type: application/json",
- `charset="UTF-8"`,
- })
- easy.Setopt(curl.OPT_TIMEOUT_MS, 150)
- easy.Setopt(curl.OPT_SSL_VERIFYHOST, 0)
- easy.Setopt(curl.OPT_SSL_VERIFYPEER, 0) // 0 is ok
- easy.Setopt(curl.OPT_POSTFIELDS, data)
- easy.Perform()
- }
- }
- func return_curl_key(url string, data string, key string) {
- easy := curl.EasyInit()
- defer easy.Cleanup()
- if easy != nil {
- easy.Setopt(curl.OPT_URL, url)
- easy.Setopt(curl.OPT_CUSTOMREQUEST, "POST")
- easy.Setopt(curl.OPT_FRESH_CONNECT, 1)
- easy.Setopt(curl.OPT_TIMEOUT_MS, 150)
- easy.Setopt(curl.OPT_HTTPHEADER, []string{
- "Content-Type: application/json",
- `charset="UTF-8"`,
- "keyaccess: " + config.API.Key,
- })
- easy.Setopt(curl.OPT_TIMEOUT_MS, 150)
- easy.Setopt(curl.OPT_SSL_VERIFYHOST, 0)
- easy.Setopt(curl.OPT_SSL_VERIFYPEER, 0) // 0 is ok
- easy.Setopt(curl.OPT_POSTFIELDS, data)
- easy.Perform()
- }
- }
- func events_bus_vid(event string) {
- if event == "" {
- fmt.Println("Event_bus: Ошибка - нет данных\n")
- } else {
- return_curl(config.API.URLCrm, event)
- }
- }
- //функция изменения состояния пира, разговаривает или нет
- func peer_use(peer_use string, use_status string) {
- if config.API.URLPeerUse == "" {
- return
- }
- mapS := map[string]string{"operator": peer_use, "queue": "", "status": use_status}
- event, _ := json.Marshal(mapS)
- event_use := string(event)
- return_curl_key(config.API.URLPeerUse, event_use, config.API.Key)
- }
- func dial_events(data map[string]string) {
- db, _ := sql.Open("mysql", config.Database.User+":"+config.Database.Pass+"@tcp("+config.Database.Host+")/"+config.Database.Name)
- defer db.Close()
- var chann, type_call, log_EXTEN_db, log_CAllerID_db, log_Uniqueid_caller_db, log_Uniqueid_answer_db string
- var autocall int
- if len(data["Context"]) == 0 {
- return
- }
- if data["Context"] == "autocall-normal" {
- return
- }
- //срез
- arr := (data["DialString"])
- fmc_dialstring := arr[0:3]
- //срез
- if (data["Context"] == "macro-dialout-trunk") || (data["Context"] == "fenix-local") || (data["Context"] == "fenix") || len(data["AccountCode"]) != 0 { //костыль
- if fmc_dialstring == "fmc" && len(data["AccountCode"]) == 0 {
- type_call = "in"
- } else {
- type_call = "out"
- } //костыли для FMC!!!!!!!!!!!!!!!
- } else {
- type_call = "in"
- }
- if data["Context"] == "ext-queues" {
- fmt.Println("ЭТО Звонок в очереди, не конечный звонок - ВЫХОД")
- fmt.Println(data)
- return
- }
- if (data["Context"] == "macro-dial-one") && (data["CallerIDNum"] == "<unknown>") {
- out_channel := data["Channel"] //запрашиваем название канала
- find_str_1 := "/"
- find_str_2 := "@"
- pos1 := strings.Index(out_channel, find_str_1) //возращение вхождения strbos
- cid := out_channel[pos1+1:] // срез substr
- pos2 := strings.Index(cid, find_str_2) //возращение вхождения
- out_cid := cid[:pos2] //узнаем логин пира который совершает звонок
- fmt.Println("OUT CID ==>> ", out_cid, "\n")
- //$setcid = $manager->SetVar($data['Channel'], 'CALLERID(ALL)', "{$out_cid} <{$out_cid}>");
- log_CAllerID_db = out_cid
- } else {
- if (data["Context"] == "macro-dialout-trunk") && (data["CallerIDNum"] == "<unknown>") { //нужно при звонке через FMC
- out_channel := data["Channel"] //запраиваем название канала
- find_str_1 := "/"
- find_str_2 := "@"
- pos1 := strings.Index(out_channel, find_str_1)
- cid := out_channel[pos1+1:]
- pos2 := strings.Index(cid, find_str_2)
- out_cid := cid[:pos2] //узнаем номер абонента
- fmt.Println("OUT CID ==>> ", out_cid, "\n")
- log_CAllerID_db = out_cid
- } else {
- log_CAllerID_db = data["CallerIDNum"]
- }
- }
- if _, err := strconv.ParseInt(data["DialString"], 0, 64); err == nil { //определяем число или нет
- log_EXTEN_db = data["DialString"]
- } else {
- log_EXTEN_db = data["DestCallerIDNum"]
- //$log_EXTEN_db = $data['DestExten']; Проверяем ощибку S для FMC
- }
- chan_caller := data["Channel"]
- chan_answer := data["DestChannel"]
- log_Uniqueid_caller_db = data["Uniqueid"]
- log_Uniqueid_answer_db = data["DestUniqueid"]
- //делаем правильный callerid для предиктивных звонков
- //Проверяем вспомогательный канал
- find_str_1 := ";2"
- pos1_des := strings.Index(log_Uniqueid_caller_db, find_str_1)
- fmt.Println(log_Uniqueid_caller_db)
- if pos1_des != -1 {
- chann = "2"
- log_Uniqueid_caller_db = log_Uniqueid_caller_db[:pos1_des]
- } else {
- chann = ""
- }
- fmt.Println(data)
- var vid_arr map[string]string
- json.Unmarshal([]byte(data["AccountCode"]), &vid_arr)
- fmt.Println(vid_arr["o"])
- //Забираем все данные из accountcode
- if (len(vid_arr["o"]) != 0) && (chann == "2") {
- log_CAllerID_db = vid_arr["o"]
- }
- //делаем правильный callerid для предиктивных звонков
- //узнаем этот звонок с автообзвона или нет
- if vid_arr["o"] == "autocall" {
- autocall = 1
- } else {
- autocall = 0
- }
- //время
- t := time.Now()
- times := t.Format("2006-01-02 15:04:05")
- //узнаем этот звонок с автообзвона или нет
- //запись в базу
- var sqlInsert = "INSERT INTO calls (type_call,exten,callerid,unigueid_caller,status_call,chan_caller,chan_answer,unigueid_answer,date_start,autocall) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
- _, err := db.Exec(sqlInsert, type_call, log_EXTEN_db, log_CAllerID_db, log_Uniqueid_caller_db, "1", chan_caller, chan_answer, log_Uniqueid_answer_db, times, autocall)
- if err != nil {
- fmt.Println("Error insert :( --> %s", err)
- }
- //событие по виджету (event_bus)
- //костыль
- fmt.Println("AccountCode ================>>>>>>>", data["AccountCode"], type_call, chann)
- //
- if len(data["AccountCode"]) != 0 {
- //fmt.Println("AccountCode nil================>>>>>>>",data["AccountCode"],chann, type_call)
- if (chann == "2") && (vid_arr["t"] != "pred") {
- return
- }
- if (chann != "2") && (vid_arr["t"] == "pred") {
- return
- }
- if (chann == "2") && (vid_arr["t"] == "norm") {
- return
- }
- if (vid_arr["o"] != data["CallerIDNum"]) && (vid_arr["t"] == "norm") {
- return
- }
- vid := map[string]string{
- "operator": vid_arr["o"],
- "type_call": type_call,
- "status": "ring",
- "num": vid_arr["e"],
- "uniqueid": log_Uniqueid_caller_db}
- vid1, _ := json.Marshal(vid)
- vid_event := string(vid1)
- fmt.Println(vid_event)
- events_bus_vid(vid_event)
- } else {
- //если это звонок не из АПИ то параметры подставляем в зависимости от типа звонка
- if type_call == "in" {
- vid := map[string]string{
- "operator": log_EXTEN_db,
- "type_call": type_call,
- "status": "ring",
- "num": log_CAllerID_db,
- "uniqueid": log_Uniqueid_caller_db}
- vid1, _ := json.Marshal(vid)
- vid_event := string(vid1)
- fmt.Println(vid_event)
- events_bus_vid(vid_event)
- } else {
- vid := map[string]string{
- "operator": log_CAllerID_db,
- "type_call": type_call,
- "status": "ring",
- "num": log_EXTEN_db,
- "uniqueid": log_Uniqueid_caller_db}
- vid1, _ := json.Marshal(vid)
- vid_event := string(vid1)
- fmt.Println(vid_event)
- events_bus_vid(vid_event)
- }
- }
- //событие по виджету (event_bus)
- //обновляем статус пира
- peer_use(log_EXTEN_db, "IN_USE")
- peer_use(log_CAllerID_db, "IN_USE")
- }
- func dialend_events(data map[string]string) {
- var chann, type_call, cid, log_EXTEN_db, log_CAllerID_db, date_start, date_answer, ringing, callerid, log_Uniqueid_caller_db string
- var autocall int
- db, _ := sql.Open("mysql", config.Database.User+":"+config.Database.Pass+"@tcp("+config.Database.Host+")/"+config.Database.Name)
- defer db.Close()
- fmt.Println(data)
- if len(data["Context"]) == 0 {
- return
- }
- if data["Context"] == "autocall-normal" {
- return
- }
- if data["Context"] == "ext-queues" {
- fmt.Println("ЭТО Звонок в очереди, не конечный звонок - ВЫХОД")
- return
- }
- if data["DialStatus"] == "ANSWER" {
- log_CAllerID_db = data["CallerIDNum"]
- log_EXTEN_db = data["DestCallerIDNum"]
- log_Uniqueid_caller_db = data["Uniqueid"]
- //
- //Проверяем вспомогательный канал
- find_str_1 := ";2"
- pos1_des := strings.Index(log_Uniqueid_caller_db, find_str_1)
- if pos1_des != -1 {
- chann = "2"
- log_Uniqueid_caller_db = log_Uniqueid_caller_db[:pos1_des]
- } else {
- chann = ""
- }
- //Проверяем вспомогательный канал
- //Забираем все данные из AccountCode
- var vid_arr map[string]string
- json.Unmarshal([]byte(data["AccountCode"]), &vid_arr)
- fmt.Println(vid_arr["o"])
- operator := vid_arr["o"]
- //
- if (len(operator) != 0) && (chann == "2") {
- log_CAllerID_db = operator
- } else {
- if (data["Context"] == "macro-dialout-trunk") && (data["CallerIDNum"] == "<unknown>") {
- out_channel := data["Channel"]
- find_str_1 := "/"
- find_str_2 := "@"
- pos1 := strings.Index(out_channel, find_str_1)
- cid = out_channel[pos1+1:]
- pos2 := strings.Index(cid, find_str_2)
- out_cid := cid[:pos2] //узнаем номер абонента
- log_CAllerID_db = out_cid
- } else {
- fmt.Println("Проверить на рабочем событии\n\n")
- cid = ""
- }
- }
- if vid_arr["o"] == "autocall" {
- autocall = 1
- } else {
- autocall = 0
- }
- //время
- t := time.Now()
- times := t.Format("2006-01-02 15:04:05")
- //узнаем этот звонок с автообзвона или нет
- //запись в базу
- sqlInsert := "Update calls set status_call=2, shower=0, date_answer='" + times + "' where `chan_caller`='" + data["Channel"] + "' OR `chan_answer`='" + data["Channel"] + "';"
- _, err := db.Exec(sqlInsert)
- if err != nil {
- fmt.Println("Error insert :( --> %s", err)
- }
- rows, _ := db.Query("select date_start, date_answer, (UNIX_TIMESTAMP(date_answer) - UNIX_TIMESTAMP(date_start)) AS ringing, autocall, callerid,type_call from calls where chan_caller=?", data["Channel"])
- for rows.Next() {
- rows.Scan(&date_start, &date_answer, &ringing, &autocall, &callerid, &type_call)
- fmt.Println("date_start", date_start)
- fmt.Println("date_answer", date_answer)
- fmt.Println("ringing", ringing)
- fmt.Println("autocall", autocall)
- fmt.Println("callerid", callerid)
- fmt.Println("type_call", type_call,"\n")
- }
- if (cid == "") || (log_CAllerID_db == log_EXTEN_db) {
- log_CAllerID_db = callerid
- }
- //событие по виджету (event_bus)
- if len(data["AccountCode"]) != 0 {
- fmt.Println("chan ===>>> ", chann, "\n")
- fmt.Println("type_call ===>>> ", vid_arr["t"], "\n")
- fmt.Println("Operator ===>>> ", vid_arr["o"], "\n")
- fmt.Println("CallerIDNum ===>>> ", data["CallerIDNum"], "\n\n")
- if (chann == "2") && (vid_arr["t"] == "pred") {
- return
- }
- if (log_Uniqueid_caller_db != data["Uniqueid"]) && (vid_arr["t"] == "norm") {
- return
- }
- if vid_arr["o"] != data["CallerIDNum"] && vid_arr["t"] == "norm" {
- return
- }
- vid := map[string]string{
- "operator": vid_arr["o"],
- "type_call": type_call,
- "status": "answer",
- "num": vid_arr["e"],
- "uniqueid": log_Uniqueid_caller_db}
- vid1, _ := json.Marshal(vid)
- vid_event := string(vid1)
- fmt.Println(vid_event)
- if vid_arr["t"] == "pred" {
- //запись в канал
- setcid, _ := a.Action(map[string]string{"Action": "Setvar", "Channel": data["Channel"], "Variable": "CALLERID(ALL)", "Value": vid_arr["e"] + ` <` + vid_arr["e"] + `>`})
- fmt.Println("SETVAR ===>>> ", setcid, "\n")
- }
- events_bus_vid(vid_event)
- } else {
- //если это звонок не из АПИ то параметры подставляем в зависимости от типа звонка
- if type_call == "in" {
- vid := map[string]string{
- "operator": log_EXTEN_db,
- "type_call": type_call,
- "status": "answer",
- "num": log_CAllerID_db,
- "uniqueid": log_Uniqueid_caller_db}
- vid1, _ := json.Marshal(vid)
- vid_event := string(vid1)
- fmt.Println(vid_event)
- events_bus_vid(vid_event)
- } else {
- vid := map[string]string{
- "operator": log_CAllerID_db,
- "type_call": type_call,
- "status": "answer",
- "num": log_EXTEN_db,
- "uniqueid": log_Uniqueid_caller_db}
- vid1, _ := json.Marshal(vid)
- vid_event := string(vid1)
- fmt.Println(vid_event)
- events_bus_vid(vid_event)
- }
- }
- //запись в канал
- setvar, _ := a.Action(map[string]string{"Action": "Setvar", "Channel": data["Channel"], "Variable": "CDR(ringing)", "Value": ringing})
- fmt.Println("!!!!!!!!!!!!!!!!!!SETVAR!!!!!!!!!!!!!!!!!!!", setvar, "!!!!!!!!!!!!!!!!!!!!!!!SETVAR!!!!!!")
- } else {
- return
- }
- }
- func hangup_events(data map[string]string) {
- var log_CAllerID_db, chann, chan_caller, log_EXTEN_db, autocall, type_call, log_Uniqueid_caller_db, sqlInsert string
- //config, _ := LoadConfiguration("config.json")
- db, _ := sql.Open("mysql", config.Database.User+":"+config.Database.Pass+"@tcp("+config.Database.Host+")/"+config.Database.Name)
- defer db.Close()
- if data["Cause-txt"] == "Unknown" {
- return
- }
- fmt.Println(data)
- var vid_arr map[string]string
- json.Unmarshal([]byte(data["AccountCode"]), &vid_arr)
- fmt.Println(vid_arr["o"])
- if data["Context"] == "autocall-normal" {
- return
- }
- //запрашиваем CID и Exten
- rows, _ := db.Query("select `exten`, `callerid`, `unigueid_caller`, `chan_caller`, `autocall`, `type_call` from calls where (`chan_caller`='" + data["Channel"] + "' OR `chan_answer`='" + data["Channel"] + "') AND `chan_caller`!=''")
- for rows.Next() {
- rows.Scan(&log_EXTEN_db, &log_CAllerID_db, &log_Uniqueid_caller_db, &chan_caller, &autocall, &type_call)
- fmt.Println("exten", log_EXTEN_db)
- fmt.Println("calleridr", log_CAllerID_db)
- fmt.Println("unigueid_caller", log_Uniqueid_caller_db)
- fmt.Println("chan_caller", chan_caller)
- fmt.Println("autocall", autocall)
- fmt.Println("type_call", type_call, "\n")
- }
- //Проверяем вспомогательный канал
- find_str_1 := ";2"
- pos1_des := strings.Index(data["Uniqueid"], find_str_1)
- if pos1_des != -1 {
- chann = "2"
- log_Uniqueid_caller_db = data["Uniqueid"][:pos1_des]
- } else {
- chann = ""
- }
- //Проверяем вспомогательный канал
- if type_call != "" {
- if len(data["AccountCode"]) != 0 {
- fmt.Println("chan ===>>> ", chann, "\n")
- fmt.Println("type_call ===>>> ", vid_arr["t"], "\n")
- fmt.Println("Operator ===>>> ", vid_arr["o"], "\n")
- fmt.Println("CallerIDNum ===>>> ", data["CallerIDNum"], "\n\n")
- if (chann == "2") && (vid_arr["t"] == "norm") {
- return
- }
- if (log_Uniqueid_caller_db != data["Uniqueid"]) && (vid_arr["t"] == "norm") {
- return
- }
- if (vid_arr["o"] != data["CallerIDNum"]) && (vid_arr["t"] == "norm") {
- return
- }
- vid := map[string]string{
- "operator": vid_arr["o"],
- "type_call": type_call,
- "status": "hangup",
- "num": vid_arr["e"],
- "uniqueid": log_Uniqueid_caller_db}
- vid1, _ := json.Marshal(vid)
- vid_event := string(vid1)
- fmt.Println(vid_event)
- events_bus_vid(vid_event)
- sqlInsert = "delete from calls where `exten`='" + vid_arr["o"] + "' OR `callerid`='" + vid_arr["o"] + "' OR `exten`='" + vid_arr["e"] + "' OR `callerid`='" + vid_arr["e"] + "'"
- _, err := db.Exec(sqlInsert)
- fmt.Println("Error insert :( --> %s", err)
- } else {
- if type_call == "in" {
- vid := map[string]string{
- "operator": log_EXTEN_db,
- "type_call": type_call,
- "status": "hangup",
- "num": log_CAllerID_db,
- "uniqueid": log_Uniqueid_caller_db}
- vid1, _ := json.Marshal(vid)
- vid_event := string(vid1)
- fmt.Println(vid_event)
- events_bus_vid(vid_event)
- sqlInsert = "delete from calls where `exten`='" + log_EXTEN_db + "' OR `callerid`='" + log_EXTEN_db + "' OR `exten`='" + log_CAllerID_db + "' OR `callerid`='" + log_CAllerID_db + "'"
- _, err := db.Exec(sqlInsert)
- fmt.Println("Error insert :( --> %s", err)
- } else {
- vid := map[string]string{
- "operator": log_CAllerID_db,
- "type_call": type_call,
- "status": "hangup",
- "num": log_EXTEN_db,
- "uniqueid": log_Uniqueid_caller_db}
- vid1, _ := json.Marshal(vid)
- vid_event := string(vid1)
- fmt.Println(vid_event)
- events_bus_vid(vid_event)
- sqlInsert = "delete from calls where `exten`='" + log_EXTEN_db + "' OR `callerid`='" + log_EXTEN_db + "' OR `exten`='" + log_CAllerID_db + "' OR `callerid`='" + log_CAllerID_db + "'"
- _, err := db.Exec(sqlInsert)
- fmt.Println("Error insert :( --> %s", err)
- }
- }
- } else {
- fmt.Println("Пусто")
- return
- }
- peer_use(log_CAllerID_db, "NOT_IN_USE")
- peer_use(log_EXTEN_db, "NOT_IN_USE")
- }
- func main() {
- //загружаем конфиг-файл в формате json и распарсим
- filename := "config.json"
- configFile, err := os.Open(filename)
- if err != nil {
- fmt.Println("Конфиг не найден")
- return
- }
- jsonParser := json.NewDecoder(configFile)
- err = jsonParser.Decode(&config)
- defer configFile.Close()
- //Подключаемя к AMI
- settings := &amigo.Settings{Username: config.Manager.User, Password: config.Manager.Pass, Host: config.Manager.Host}
- a = amigo.New(settings)
- a.Connect()
- // Listen for connection events
- a.On("connect", func(message string) {
- fmt.Println("Connected", message)
- })
- a.On("error", func(message string) {
- fmt.Println("Connection error:", message)
- })
- a.RegisterHandler("Hangup", hangup_events)
- a.RegisterHandler("Dialbegin", dial_events)
- a.RegisterHandler("Dialend", dialend_events)
- ch := make(chan bool)
- <-ch
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement