Динамическая маршрутизация входящих вызовов на основе Caller ID, DID и времени суток

Данный скрипт позволяет перенаправлять входящие вызовы на основе заданных критериев, таких как время суток, Caller ID или DID. Динамическая маршрутизация срабатывает при поступлении вызова на транк и направляет абонента на настроенное направление / сотруднику.

Настройка скрипта маршрутизации вызовов по времени

  1. Перейдите в Console > Integrations > Call Scripts.
  2. Нажмите Add from Store и выберите “Time Based Call Routing”.
  3. Для удобства, дайте скрипту название.
  4. Запустите скрипт при получении вызова на транке.
  5. Выберите транк, на котором будут перехватываться входящие вызовы.
  6. По умолчанию скрипт имеет предустановленное расписание, которое можно изменить, указав значения в переменной schedule. Например: { DayOfWeek.Monday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) }.
  7. Скрипт также принимает вызовы со всех DID/Caller ID, поскольку переменные DIDs/Callers содержат символ *, который можно заменить на конкретные DID и Caller ID.
  8. Измените 801 в строке const string DestinationDN = "801"; на выбранное вами направление.

Для чего используется динамическая маршрутизация

  • Маршрутизация вызовов с учетом времени: Автоматическое перенаправление вызовов на определенные направления / сотрудникам в зависимости от рабочего времени.
  • Обработка вызовов от определенных абонентов: Создание уникальных правил маршрутизации для важных Caller ID или DID.
  • Эффективное управление вызовами: Сокращение ручного вмешательства – автоматизация маршрутизации вызовов в нерабочее время или по определенным критериям.

Код скрипта

ВНИМАНИЕ! Код скрипта приведен только для справки. Актуальную версию можно скачать из Магазина 3CX.

Script: Intercept Inbound Calls

/*
* Time Base Call Routing - Use code with caution!
* Calls will be intercepted and redirected to the specified DestinationDN during the following times:
* Monday to Sunday: 5:30 PM to 7:00 AM
* The current destination DN is set to "801" modify destination to any system extension or extension you want.
*
* INSTRUCTIONS
* - Configure Date & Time (Line 31)
* - Change the destination DN, and modify the value of the constant DestinationDN to any destination you want to route call (Line 26).
*/


#nullable disable
using CallFlow;
using System;
using System.Threading;
using System.Threading.Tasks;
using TCX.Configuration;
using TCX.PBXAPI;
using System.Collections.Generic;
using System.Linq;
using CallFlow.CFD;


namespace interceptcall
{
public class InterceptInboundCall : ScriptBase
{
// The destination DN to which the call will be redirected
const string DestinationDN = "801";


// Define a schedule for when calls should be intercepted
static readonly Schedule schedule = new Schedule(RuleHoursType.SpecificHours)
{
{ DayOfWeek.Monday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
{ DayOfWeek.Monday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
{ DayOfWeek.Tuesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
{ DayOfWeek.Tuesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
{ DayOfWeek.Wednesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
{ DayOfWeek.Wednesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
{ DayOfWeek.Thursday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
{ DayOfWeek.Thursday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
{ DayOfWeek.Friday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
{ DayOfWeek.Friday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) }
};

public override async void Start()
{
// Handle calls as a detached task, catching all exceptions.
try
{
await Task.Run(async () =>
{
try
{
MyCall.Debug($"Script start delay: {DateTime.UtcNow - MyCall.LastChangeStatus}");
MyCall.Debug($"Incoming connection {MyCall} from {MyCall.Caller}");
bool intercepted = false;
var ps = MyCall.PS as PhoneSystem;

if (MyCall.Caller.DN is ExternalLine externalLine)
{
var DIDNumber = MyCall.Caller["inbound_did"];
var CallerID = MyCall.Caller.CallerID;
var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);


// Intercept calls during the specified schedule
if (schedule.IsActiveTime(currentTime))
{
string[] DIDs = { "*" }; // Allow all DIDs
string[] Callers = { "*" }; // Allow all Callers
var destination_struct = new DestinationStruct(ps.GetDNByNumber(DestinationDN));


// Check if the call's DID and CallerID match the interception criteria
if ((DIDs.Contains(DIDNumber) || DIDs.Contains("*")) &&
(Callers.Contains(CallerID) || Callers.Contains("*")))
{
try
{
var result = await MyCall.RouteToAsync(destination_struct);
MyCall.Info($"{CallerID} -> {DIDNumber} has been redirected to {DestinationDN} ({result})");
intercepted = true;
}
catch (Exception ex)
{
MyCall.Info($"{CallerID} -> {DIDNumber}: interception failed. '{DestinationDN}' is not reachable: {ex}");
}
}
else
{
MyCall.Info($"{CallerID} -> {DIDNumber}@{currentTime}: Default CallerID/DID based routing will be applied");
}
}
}


MyCall.Return(intercepted);
}
catch (Exception ex)
{
MyCall.Error($"Script execution failed: {ex}");
MyCall.Return(false);
}
});
}
catch (Exception ex)
{
MyCall.Error($"Task execution failed: {ex}");
MyCall.Return(false);
}
}
}
}