Outbound calls and play message

hello,
i would like to have a setup/call file

  1. check time of the day- if between specific time then proceed
  2. check a excel/csv/txt file for number to be dialed
  3. dial the number
  4. on connection , plays a specific message/audio file
  5. if person wants to connect further, then on pressing the key, connects to preassigned number (ext/trunk call) - optional
  6. if person does not want to connect further, call get disconnected
  7. if time of the day is in allowed range, check csv/txt file again and dial next number in the row
  8. if time of the day is in disallowed range, then start from the next number in row on next day.
  9. create call files initially in a temp directory and then transfer the files to the outgoing calls directory

i have 5 trunks and thus can use all the trunks to dial out.

Please suggest a solution…

so i used bash script to get all the conditions met
revised bash script

#!/bin/bash

# Function to check if it's working hours (Monday to Friday, 10 am to 6 pm)
function is_working_hours() {
    current_hour=$(date +%H)
    current_day=$(date +%u)  # 1 (Monday) to 7 (Sunday)

    if [ $current_day -ge 1 ] && [ $current_day -le 5 ] && [ $current_hour -ge 10 ] && [ $current_hour -lt 18 ]; then
        return 0  # True, it's working hours
    else
        return 1  # False, it's not working hours
    fi
}

# Function to create call files and move to the outbound folder
function create_call_files() {
    input_file="phone_numbers.txt"
    outbound_folder="/var/spool/asterisk/outgoing/"
    audio_file="/path/to/your/audio/file.wav"
#  audio_file="/path/to/your/audio/file.alaw"

    # Check if the outbound folder has more than 15 call files, and pause if necessary
    current_files=$(ls -l "$outbound_folder" | grep -c '^')

    if [ "$current_files" -gt 15 ]; then
        echo "More than 15 call files in the outbound folder. Pausing the script."
        exit 0
    fi

    # Read phone numbers from the input file and create call files
    while IFS= read -r phone_number; do
        call_file="${outbound_folder}callfile_$(date +%s).call"

        echo "Channel: SIP/your_sip_trunk/$phone_number" > "$call_file"
        echo "Application: Playback" >> "$call_file"
        echo "Data: $audio_file" >> "$call_file"
        echo "MaxRetries: 2" >> "$call_file"
        echo "RetryTime: 60" >> "$call_file"
        echo "WaitTime: 30" >> "$call_file"
        echo "" >> "$call_file"  # Add an empty line

        echo "Call file created: $call_file"
    done < "$input_file"
}

# Main script execution

# Check if it's working hours before generating call files
if is_working_hours; then
    create_call_files
else
    echo "Not within working hours. Script not executed."
fi

on running the script, and transferring the file to outgoing folder, i am getting the following error.

i imported the audio file using GUI of freepbx.
the file is visible in the folder and able to play it on the gui.

Connected to Asterisk 18.19.0 currently running on mnhpbx (pid = 2628)
    -- SIP/matrix_setu-0000112c answered
[2024-01-21 00:35:07] WARNING[30768]: file.c:824 ast_openstream_full: File /var/lib/asterisk/sounds/en/custom/GP_call.alaw does not exist in any format
[2024-01-21 00:35:07] WARNING[30768]: file.c:1303 ast_streamfile: Unable to open /var/lib/asterisk/sounds/en/custom/GP_call.alaw (format (alaw)): No such file or directory
[2024-01-21 00:35:07] WARNING[30768]: app_playback.c:512 playback_exec: Playback failed on SIP/matrix_setu-0000112c for /var/lib/asterisk/sounds/en/custom/GP_call.alaw
[2024-01-21 00:35:07] NOTICE[30768]: pbx_spool.c:463 attempt_thread: Call completed to SIP/matrix_setu/XXXXXXXXXX@from-internal

hello

so i figured out the issue.
the file name has to be without any ext specified eg wav/alaw etc

now i want to understand how to create a freepbx module with

  1. ability to specify the number text file and add the same filename and location to the bash script
  2. ability to specify the audio file uploaded in system recordings (from dropdown menu) and add the same filename and location to the bash script
  3. ability to specify the trunk name from the dropdown menu as per the trunks created in freepbx

if anyone can help me with this i would be very thankful.
i would like to release it as open source module for freepbx

FreePBX OpenSource Project: FreePBX Module Generator (sangoma.com)

FreePBX OpenSource Project : FreePBX Development (sangoma.com)

FreePBX OpenSource Project : FreePBX Internals (sangoma.com)

Hello

thanks for the reply…

the first link for the module generator, has a GIT repository link and there is not repo for the module generator. when trying to download… the webpage is getting downloaded.

wget https://git.freepbx.org/projects/FL/repos/freepbx-module-generator/raw/dist/freepbxgenerator.phar?at=refs%2Fheads%2Fmaster -O freepbxgenerator.phar
--2024-01-23 10:57:22--  https://git.freepbx.org/projects/FL/repos/freepbx-module-generator/raw/dist/freepbxgenerator.phar?at=refs%2Fheads%2Fmaster
Resolving git.freepbx.org (git.freepbx.org)... wget https://git.freepbx.org/projects/FL/repos/freepbx-module-generator/raw/dist/freepbxgenerator.phar?at=refs%2Fheads%2Fmaster -O freepbxgenerator.phar
199.102.239.68
Connecting to git.freepbx.org (git.freepbx.org)|199.102.239.68|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://github.com/freepbx [following]
--2024-01-23 10:57:23--  https://github.com/freepbx
Resolving github.com (github.com)... 20.207.73.82
Connecting to github.com (github.com)|20.207.73.82|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: ‘freepbxgenerator.phar’

also i found another link from developer corner section of sangoma but that is also not working showing a 403 forbidden error.

if you can point me to a working link i would like to give creating a module a try. i am not a coder by any means but still want to give it a try.

Till date this forum and members like you have supported me solved my complex and noob queries and because of that i have a working freepbx setup working for last 1.5 years.

hello

another issue which i am facing is that when the out-call is made, everything works fine but the first 2-3 seconds of audio clip is skipped when it is being played…

any idea how to make it work.

have updated the bash script i am currently using.

#!/bin/bash

# Function to check if it's working hours (Monday to Friday, 10 am to 6 pm)
function is_working_hours() {
    current_hour=$(date +%H)
    current_day=$(date +%u)  # 1 (Monday) to 7 (Sunday)

    if [ $current_day -ge 1 ] && [ $current_day -le 5 ] && [ $current_hour -ge 10 ] && [ $current_hour -lt 18 ]; then
        return 0  # True, it's working hours
    else
        return 1  # False, it's not working hours
    fi
}

# Function to create call files and move to the temp outbound folder and specify playback file
function create_call_files() {
    input_file="/root/gplist.txt"
    outbound_folder="/var/spool/asterisk/out/"
    dest_dir="/var/spool/asterisk/outgoing/"
    audio_file="full_path_to_your_audio_file"

    # Check if the outbound folder has more than 10 call files, and pause if necessary
    current_files=$(ls -l "$dest_dir" | grep -c '^')

    if [ "$current_files" -gt 10 ]; then
        echo "More than 10 call files in the outbound folder. Pausing the script."
        exit 0
    fi

    # Read phone numbers from the input file and create call files
    while IFS= read -r phone_number; do
        call_file="${outbound_folder}callfile_$phone_number.call"
        echo "Channel: SIP/your_sip_trunk_name/$phone_number@from-internal" > "$call_file"
        echo "Application: Playback" >> "$call_file"
        echo "Data: silence/3&$audio_file" >> "$call_file"
        echo "MaxRetries: 2" >> "$call_file"
        echo "RetryTime: 60" >> "$call_file"
        echo "WaitTime: 100" >> "$call_file"
        echo "Archive: yes" >> "$call_file"
        echo "" >> "$call_file"  # Add an empty line

        echo "Call file created: $call_file"

    done < "$input_file"
}


# Main script execution

# Check if it's working hours before generating call files
if is_working_hours; then
    create_call_files

else
    create_call_files

 #   echo "Not within working hours. Script not executed."
fi

# moving the call files from temp location to outgoing calls location(monitored by asterisk)
 
# Source and destination directories
source_dir="/var/spool/asterisk/out/"
destination_dir="/var/spool/asterisk/outgoing/"

# Check if source directory exists
if [ ! -d "$source_dir" ]; then
    echo "Source directory $source_dir does not exist."
    exit 1
fi

# Check if destination directory exists, create if not
if [ ! -d "$destination_dir" ]; then
    mkdir -p "$destination_dir"
    echo "Created destination directory: $destination_dir"
fi

# Move .call files from source to destination
for file in "$source_dir"*.call; do
    if [ -e "$file" ]; then
        mv "$file" "$destination_dir"
        echo "Moved $file to $destination_dir"
    fi
done

echo "File move completed."

Try editing the line

"Data: silence/3&$audio_file"

or use sox to pad 3 seconds of silence to $audio_file.

sox audiofile.wav audiofilewithsilence.wav pad 3 0

thanks man…
it works, but only if the receiving person picks up the call immediately…
if the recipient takes few rings to pick the call then that many seconds of recording is skipped…

it seems that the asterisk start playing the recording as soon as there is ringing and not after the call is actually connected.

any solution to this??

edited the same in the final code

Find a competent SIP provider, or fix the destination PABX not to answer prematurely. Asterisk is being told that the call has been answered when it has not been.

i am calling a mobile number… so can’t ask telecom operator to do that…
i have tried on multiple operators both at outbound(PSTN) and inbound(mobile)

another solution i can tried is to transfer the call to IVR-extension, but i am still getting the same issue… asterisk start playing the recorded message immediately.

        call_file="${outbound_folder}callfile_$phone_number.call"
        echo "Channel: SIP/matrix_setu/$phone_number@from-internal" > "$call_file"
#      echo "Application: Playback" >> "$call_file"
#      echo "Data: silence/5&$audio_file" >> "$call_file"
#	echo "Application: Extension"  >> "$call_file"
#	echo "Context: from-internal"  >> "$call_file"
	echo "Extension:988"  >> "$call_file"
	echo "Priority: 1"  >> "$call_file"
        echo "MaxRetries: 2" >> "$call_file"
        echo "RetryTime: 60" >> "$call_file"
        echo "WaitTime: 180" >> "$call_file"
	echo "Archive: yes" >> "$call_file"
        echo "" >> "$call_file"  # Add an empty line
        echo "Call file created: $call_file"
    done < "$input_file"

asterisk log

    -- Attempting call on SIP/matrix_setu/XXXXX@from-internal for 988@from-internal:1 (Retry 1)
  == Using SIP VIDEO TOS bits 136
  == Using SIP VIDEO CoS mark 6
  == Using SIP RTP TOS bits 184
  == Using SIP RTP CoS mark 5
    -- Called matrix_setu/XXXXX@from-internal
    -- SIP/matrix_setu-0000116c is making progress
    -- SIP/matrix_setu-0000116c answered
    -- Executing [988@from-internal:1] NoOp("SIP/matrix_setu-0000116c", "Running miscapp 2: diverting gp outgoing calls to IVR recorded messag") in new stack
    -- Executing [988@from-internal:2] Macro("SIP/matrix_setu-0000116c", "user-callerid,") in new stack
    -- Executing [s@macro-user-callerid:1] Set("SIP/matrix_setu-0000116c", "TOUCH_MONITOR=1706109721.8046") in new stack
    -- Executing [s@macro-user-callerid:2] Set("SIP/matrix_setu-0000116c", "CHANCONTEXT=") in new stack
    -- Executing [s@macro-user-callerid:3] Progress("SIP/matrix_setu-0000116c", "") in new stack
    -- Executing [s@macro-user-callerid:4] Set("SIP/matrix_setu-0000116c", "CHANCONTEXT=") in new stack
    -- Executing [s@macro-user-callerid:5] Set("SIP/matrix_setu-0000116c", "CHANEXTENCONTEXT=matrix_setu-0000116c") in new stack
    -- Executing [s@macro-user-callerid:6] Set("SIP/matrix_setu-0000116c", "CHANEXTEN=matrix_setu-0000116c") in new stack
    -- Executing [s@macro-user-callerid:7] Set("SIP/matrix_setu-0000116c", "CALLERID(number)=") in new stack
    -- Executing [s@macro-user-callerid:8] Set("SIP/matrix_setu-0000116c", "AMPUSER=") in new stack
    -- Executing [s@macro-user-callerid:9] Set("SIP/matrix_setu-0000116c", "HOTDESCKCHAN=matrix_setu-0000116c") in new stack
    -- Executing [s@macro-user-callerid:10] Set("SIP/matrix_setu-0000116c", "HOTDESKEXTEN=matrix_setu") in new stack
    -- Executing [s@macro-user-callerid:11] Set("SIP/matrix_setu-0000116c", "HOTDESKCALL=0") in new stack
    -- Executing [s@macro-user-callerid:12] ExecIf("SIP/matrix_setu-0000116c", "0?Set(HOTDESKCALL=1)") in new stack
    -- Executing [s@macro-user-callerid:13] ExecIf("SIP/matrix_setu-0000116c", "0?Set(CALLERID(name)=)") in new stack
    -- Executing [s@macro-user-callerid:14] GotoIf("SIP/matrix_setu-0000116c", "0?report") in new stack
    -- Executing [s@macro-user-callerid:15] ExecIf("SIP/matrix_setu-0000116c", "1?Set(REALCALLERIDNUM=)") in new stack
    -- Executing [s@macro-user-callerid:16] Set("SIP/matrix_setu-0000116c", "AMPUSER=") in new stack
    -- Executing [s@macro-user-callerid:17] GotoIf("SIP/matrix_setu-0000116c", "0?limit") in new stack
    -- Executing [s@macro-user-callerid:18] Set("SIP/matrix_setu-0000116c", "AMPUSERCIDNAME=") in new stack
    -- Executing [s@macro-user-callerid:19] ExecIf("SIP/matrix_setu-0000116c", "0?Set(__CIDMASQUERADING=TRUE)") in new stack
    -- Executing [s@macro-user-callerid:20] GotoIf("SIP/matrix_setu-0000116c", "1?report") in new stack
    -- Goto (macro-user-callerid,s,29)
    -- Executing [s@macro-user-callerid:29] NoOp("SIP/matrix_setu-0000116c", "Macro Depth is 1") in new stack
    -- Executing [s@macro-user-callerid:30] GotoIf("SIP/matrix_setu-0000116c", "1?report2:macroerror") in new stack
    -- Goto (macro-user-callerid,s,31)
    -- Executing [s@macro-user-callerid:31] GotoIf("SIP/matrix_setu-0000116c", "0?continue") in new stack
    -- Executing [s@macro-user-callerid:32] ExecIf("SIP/matrix_setu-0000116c", "1?Set(__CALLEE_ACCOUNCODE=)") in new stack
    -- Executing [s@macro-user-callerid:33] Set("SIP/matrix_setu-0000116c", "__TTL=64") in new stack
    -- Executing [s@macro-user-callerid:34] GotoIf("SIP/matrix_setu-0000116c", "1?continue") in new stack
    -- Goto (macro-user-callerid,s,50)
    -- Executing [s@macro-user-callerid:50] Set("SIP/matrix_setu-0000116c", "CALLERID(number)=") in new stack
    -- Executing [s@macro-user-callerid:51] Set("SIP/matrix_setu-0000116c", "CALLERID(name)=") in new stack
    -- Executing [s@macro-user-callerid:52] GotoIf("SIP/matrix_setu-0000116c", "1?cnum") in new stack
    -- Goto (macro-user-callerid,s,54)
    -- Executing [s@macro-user-callerid:54] Set("SIP/matrix_setu-0000116c", "CDR(cnum)=") in new stack
    -- Executing [s@macro-user-callerid:55] Set("SIP/matrix_setu-0000116c", "CHANNEL(language)=en") in new stack
    -- Executing [988@from-internal:3] Goto("SIP/matrix_setu-0000116c", "play-system-recording,4,1") in new stack
    -- Goto (play-system-recording,4,1)
    -- Executing [4@play-system-recording:1] Answer("SIP/matrix_setu-0000116c", "") in new stack
    -- Executing [4@play-system-recording:2] Playback("SIP/matrix_setu-0000116c", "custom/GP_call") in new stack
    -- <SIP/matrix_setu-0000116c> Playing 'custom/GP_call.alaw' (language 'en')
    -- Executing [4@play-system-recording:3] Hangup("SIP/matrix_setu-0000116c", "") in new stack
  == Spawn extension (play-system-recording, 4, 3) exited non-zero on 'SIP/matrix_setu-0000116c'
[2024-01-24 20:52:45] NOTICE[6725][C-00000a50]: pbx_spool.c:463 attempt_thread: Call completed to SIP/matrix_setu/XXXXX@from-internal

Hello @dicko @david55 @comtech and everyone

so i am able to make outbound calls and play the recording… target achieved i guess… thanks to all of you…

my next concern is that, when i try to check the CDR details in the freepbx, i am not getting the number which was dialed but, getting empty outbound caller ID and “<>” as the caller ID, even the destination is empty.
i thought the asterisk will pick the called number as the caller ID/destination and will be shown in the CDR, similarly outbound caller ID is mentioned in the trunk settings but still in the CDR is showing empty…

any workaround for this… specially the caller ID part…

so if i add following in the call file will it work??

CallerID: abc 9999999