<?php
namespace App\Repositories\Eloquent;
use App\Jobs\ImportCampaign;
use App\Jobs\ScheduleBatchJob;
use App\Jobs\StoreCampaignJob;
use App\Library\SMSCounter;
use App\Library\Tool;
use App\Models\Blacklists;
use App\Models\Campaigns;
use App\Models\CampaignsList;
use App\Models\CampaignsRecipients;
use App\Models\CampaignsSenderid;
use App\Models\CampaignsSendingServer;
use App\Models\ContactGroups;
use App\Models\Country;
use App\Models\CsvData;
use App\Models\ImportJobHistory;
use App\Models\PhoneNumbers;
use App\Models\PlansCoverageCountries;
use App\Models\Senderid;
use App\Models\SendingServer;
use App\Models\SpamWord;
use App\Models\Templates;
use App\Models\User;
use App\Notifications\SendCampaignCopy;
use App\Repositories\Contracts\CampaignRepository;
use Carbon\Carbon;
use Illuminate\Bus\Batch;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\DB;
use Throwable;
class EloquentCampaignRepository extends EloquentBaseRepository implements CampaignRepository
{
public static array $serverPools = [];
/**
* EloquentCampaignRepository constructor.
*
* @param Campaigns $campaigns
*/
public function __construct(Campaigns $campaigns)
{
parent::__construct($campaigns);
}
/**
* send quick message
*
* @param Campaigns $campaign
* @param array $input
*
* @return JsonResponse
* @throws Throwable
*/
public function quickSend(Campaigns $campaign, array $input): JsonResponse
{
if (isset($input['user_id'])) {
$user = User::find($input['user_id']);
} else {
$user = Auth::user();
}
$sms_type = $input['sms_type'];
$blacklist = Blacklists::where('user_id', $user->id)->where('number', $input['recipient'])->first();
if ($blacklist) {
return response()->json([
'status' => 'error',
'message' => 'Number contain in blacklist',
]);
}
if ($user->customer->getOption('send_spam_message') == 'no') {
$spamWords = SpamWord::all()->filter(function ($spamWord) use ($input) {
if ( true === str_contains(strtolower($input['message']), strtolower($spamWord->word))) {
return true;
}
return false;
});
if ($spamWords->count()) {
return response()->json([
'status' => 'error',
'message' => 'Your message contains spam words.',
]);
}
}
if ($user->sms_unit == 0) {
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.sending_limit_exceed'),
]);
}
if ($user->customer->activeSubscription()) {
if ($sms_type == 'unicode') {
$db_sms_type = 'plain';
} else {
$db_sms_type = $sms_type;
}
if ($sms_type == 'plain' || $sms_type == 'unicode') {
$capabilities_type = 'sms';
} else {
$capabilities_type = $sms_type;
}
// Check the customer has permissions using sending servers and has his own sending servers
$sending_server = SendingServer::find($input['sending_server']);
if ( ! $sending_server) {
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.sending_server_not_available'),
]);
}
if ($sending_server->{$db_sms_type} != 1) {
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.sending_server_not_available'),
]);
}
$sender_id = null;
if ($user->customer->getOption('sender_id_verification') == 'yes') {
if (isset($input['originator'])) {
if ($input['originator'] == 'sender_id' && isset($input['sender_id'])) {
$sender_id = $input['sender_id'];
} elseif ($input['originator'] == 'phone_number' && isset($input['phone_number'])) {
$sender_id = $input['phone_number'];
}
} elseif (isset($input['sender_id'])) {
$sender_id = $input['sender_id'];
}
$check_sender_id = Senderid::where('user_id', $user->id)->where('sender_id', $sender_id)->where('status', 'active')->first();
if ( ! $check_sender_id) {
$number = PhoneNumbers::where('user_id', $user->id)->where('number', $sender_id)->where('status', 'assigned')->first();
if ( ! $number) {
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_invalid', ['sender_id' => $sender_id]),
]);
}
$capabilities = str_contains($number->capabilities, $capabilities_type);
if ( ! $capabilities) {
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_sms_capabilities', ['sender_id' => $sender_id, 'type' => $db_sms_type]),
]);
}
}
} elseif ($user->can('view_numbers') && $input['originator'] == 'phone_number' && isset($input['phone_number'])) {
$sender_id = $input['phone_number'];
$number = PhoneNumbers::where('user_id', $user->id)->where('number', $sender_id)->where('status', 'assigned')->first();
if ( ! $number) {
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_invalid', ['sender_id' => $sender_id]),
]);
}
$capabilities = str_contains($number->capabilities, $capabilities_type);
if ( ! $capabilities) {
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_sms_capabilities', ['sender_id' => $sender_id, 'type' => $db_sms_type]),
]);
}
} elseif (isset($input['sender_id'])) {
$sender_id = $input['sender_id'];
}
$message = null;
if (isset($input['message'])) {
$message = $input['message'];
}
$coverage = PlansCoverageCountries::where('plan_id', $user->customer->activeSubscription()->plan_id)->first();
if ( ! $coverage) {
return response()->json([
'status' => 'error',
'message' => "Permission to send an SMS has not been enabled for the region indicated by the 'To' number: ".$input['recipient'],
]);
}
if (isset($input['api_key']) || isset($input['exist_c_code'])) {
$country_list = Country::where('country_code', $input['country_code'])->where('status', 1)->get();
if ($country_list->count() > 1) {
$coverage_list = PlansCoverageCountries::where('plan_id', $user->customer->activeSubscription()->plan_id)->select('country_id')->get()->pluck('country_id')->toArray();
$filtered = $country_list->pluck('id')->filter(function ($value, $key) use ($coverage_list) {
return in_array($value, $coverage_list);
});
$country = Country::find($filtered->first());
} else {
$country = $country_list->first();
}
if ($country->country_code != $input['country_code']) {
return response()->json([
'status' => 'error',
'message' => "Permission to send an SMS has not been enabled for the region indicated by the 'To' number: ".$input['recipient'],
]);
}
} else {
$country = Country::find($input['country_code']);
}
if ( ! $country) {
return response()->json([
'status' => 'error',
'message' => "Permission to send an SMS has not been enabled for the region indicated by the 'To' number: ".$input['recipient'],
]);
}
$country_code = $country->country_code;
$coverage = PlansCoverageCountries::where('country_id', $country->id)->where('plan_id', $user->customer->activeSubscription()->plan_id)->first();
if ( ! $coverage) {
return response()->json([
'status' => 'error',
'message' => "Permission to send an SMS has not been enabled for the region indicated by the 'To' number: ".$input['recipient'],
]);
}
$priceOption = json_decode($coverage->options, true);
$price = 0;
$sms_counter = new SMSCounter();
$message_data = $sms_counter->count($message);
$sms_count = $message_data->messages;
if ($sms_type == 'plain' || $sms_type == 'unicode') {
$unit_price = $priceOption['plain_sms'];
$price = $sms_count * $unit_price;
}
if ($sms_type == 'voice') {
$unit_price = $priceOption['voice_sms'];
$price = $sms_count * $unit_price;
}
if ($sms_type == 'mms') {
if ($message_data->messages == 0) {
$sms_count = 1;
}
$unit_price = $priceOption['mms_sms'];
$price = $sms_count * $unit_price;
}
if ($sms_type == 'whatsapp') {
$unit_price = $priceOption['whatsapp_sms'];
$price = $sms_count * $unit_price;
}
$price = (int) $price;
if ($user->sms_unit != '-1') {
if ($price > $user->sms_unit) {
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.not_enough_balance', [
'current_balance' => $user->sms_unit,
'campaign_price' => $price,
]),
]);
}
}
//prepared message data
// $phone = Tool::strReplaceFirst($country_code, '', ltrim($input['recipient'], '0'));
//
$preparedData = [
'user_id' => $user->id,
'phone' => $country_code.$input['recipient'],
'sender_id' => $sender_id,
'message' => $message,
'cost' => $price,
'sending_server' => $sending_server,
'status' => null,
'sms_type' => $sms_type,
];
if (isset($input['api_key'])) {
$preparedData['api_key'] = $input['api_key'];
}
$data = null;
if ($sms_type == 'plain' || $sms_type == 'unicode') {
$data = $campaign->sendPlainSMS($preparedData);
}
if ($sms_type == 'voice') {
$preparedData['language'] = $input['language'];
$preparedData['gender'] = $input['gender'];
$data = $campaign->sendVoiceSMS($preparedData);
}
if ($sms_type == 'mms') {
if (isset($input['api_key'])) {
$preparedData['media_url'] = $input['media_url'];
} else {
$preparedData['media_url'] = Tool::uploadImage($input['mms_file']);
}
$data = $campaign->sendMMS($preparedData);
}
if ($sms_type == 'whatsapp') {
if (isset($input['mms_file'])) {
$preparedData['media_url'] = Tool::uploadImage($input['mms_file']);
}
$data = $campaign->sendWhatsApp($preparedData);
}
if (is_object($data)) {
if ( ! empty($data->status)) {
if (substr_count($data->status, 'Delivered') == 1) {
if ($user->sms_unit != '-1') {
DB::transaction(function () use ($user, $price) {
$remaining_balance = $user->sms_unit - $price;
$user->lockForUpdate();
$user->update(['sms_unit' => $remaining_balance]);
});
}
return response()->json([
'status' => 'success',
'data' => $data,
'message' => __('locale.campaigns.message_successfully_delivered'),
]);
} else {
return response()->json([
'status' => 'info',
'message' => $data->status,
'data' => $data,
]);
}
}
}
return response()->json([
'status' => 'info',
'message' => __('locale.exceptions.something_went_wrong'),
'data' => $data,
]);
}
return response()->json([
'status' => 'error',
'message' => __('locale.subscription.no_active_subscription'),
]);
}
/**
* @param Campaigns $campaign
* @param array $input
*
* @return JsonResponse
*/
public function campaignBuilder(Campaigns $campaign, array $input): JsonResponse
{
if (Auth::user()->sms_unit != '-1' && Auth::user()->sms_unit == 0) {
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.sending_limit_exceed'),
]);
}
$sms_type = $input['sms_type'];
if (Auth::user()->customer->getOption('send_spam_message') == 'no') {
$spamWords = SpamWord::all()->filter(function ($spamWord) use ($input) {
if ( true === str_contains(strtolower($input['message']), strtolower($spamWord->word))) {
return true;
}
return false;
});
if ($spamWords->count()) {
return response()->json([
'status' => 'error',
'message' => 'Your message contains spam words.',
]);
}
}
//create campaign
$new_campaign = Campaigns::create([
'user_id' => Auth::user()->id,
'campaign_name' => $input['name'],
'message' => $input['message'],
'sms_type' => $sms_type,
'status' => Campaigns::STATUS_NEW,
]);
if ( ! $new_campaign) {
return response()->json([
'status' => 'error',
'message' => __('locale.exceptions.something_went_wrong'),
]);
}
if ($sms_type == 'unicode') {
$db_sms_type = 'plain';
} else {
$db_sms_type = $sms_type;
}
if ($sms_type == 'plain' || $sms_type == 'unicode') {
$capabilities_type = 'sms';
} else {
$capabilities_type = $sms_type;
}
$sending_servers = SendingServer::where($db_sms_type, 1)->where('status', 1)->find($input['sending_server']);
if (empty($sending_servers)) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.sending_server_not_available'),
]);
}
$sender_id = null;
if (Auth::user()->customer->getOption('sender_id_verification') == 'yes') {
if (isset($input['originator'])) {
if ($input['originator'] == 'sender_id') {
if ( ! isset($input['sender_id'])) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
$sender_id = $input['sender_id'];
if (is_array($sender_id) && count($sender_id) > 0) {
$invalid = [];
$senderids = Senderid::where('user_id', Auth::user()->id)
->where('status', 'active')
->select('sender_id')
->cursor()
->pluck('sender_id')
->all();
foreach ($sender_id as $sender) {
if ( ! in_array($sender, $senderids)) {
$invalid[] = $sender;
}
}
if (count($invalid)) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_invalid', ['sender_id' => $invalid[0]]),
]);
}
} else {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
} else {
if ( ! isset($input['phone_number'])) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.phone_numbers_required'),
]);
}
$sender_id = $input['phone_number'];
if (is_array($sender_id) && count($sender_id) > 0) {
$type_supported = [];
PhoneNumbers::where('user_id', Auth::user()->id)
->where('status', 'assigned')
->cursor()
->reject(function ($number) use ($sender_id, &$type_supported, &$invalid, $capabilities_type) {
if (in_array($number->number, $sender_id) && ! str_contains($number->capabilities, $capabilities_type)) {
return $type_supported[] = $number->number;
}
return $sender_id;
})->all();
if (count($type_supported)) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_sms_capabilities', ['sender_id' => $type_supported[0], 'type' => $db_sms_type]),
]);
}
} else {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
}
} else {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
} elseif (Auth::user()->can('view_numbers') && isset($input['originator']) && $input['originator'] == 'phone_number') {
$sender_id = $input['phone_number'];
if (is_array($sender_id) && count($sender_id) > 0) {
$type_supported = [];
PhoneNumbers::where('user_id', Auth::user()->id)
->where('status', 'assigned')
->cursor()
->reject(function ($number) use ($sender_id, &$type_supported, &$invalid, $capabilities_type) {
if (in_array($number->number, $sender_id) && ! str_contains($number->capabilities, $capabilities_type)) {
return $type_supported[] = $number->number;
}
return $sender_id;
})->all();
if (count($type_supported)) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_sms_capabilities', ['sender_id' => $type_supported[0], 'type' => $db_sms_type]),
]);
}
} else {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
} else {
if (isset($input['originator'])) {
if ($input['originator'] == 'sender_id') {
if ( ! isset($input['sender_id'])) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
$sender_id = $input['sender_id'];
} else {
if ( ! isset($input['phone_number'])) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.phone_numbers_required'),
]);
}
$sender_id = $input['phone_number'];
}
if ( ! is_array($sender_id) || count($sender_id) <= 0) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
}
if (isset($input['sender_id'])) {
$sender_id = $input['sender_id'];
$input['originator'] = 'sender_id';
}
}
$sender_id = array_filter($sender_id);
if (count($sender_id)) {
foreach ($sender_id as $id) {
$data = [
'campaign_id' => $new_campaign->id,
'sender_id' => $id,
];
if (isset($input['originator'])) {
$data['originator'] = $input['originator'];
}
CampaignsSenderid::create($data);
}
}
$total = 0;
// update contact groups details
if (isset($input['contact_groups']) && is_array($input['contact_groups']) && count($input['contact_groups']) > 0) {
$contact_groups = ContactGroups::whereIn('id', $input['contact_groups'])->where('status', true)->where('customer_id', Auth::user()->id)->cursor();
foreach ($contact_groups as $group) {
$total += $group->subscribersCount($group->cache);
CampaignsList::create([
'campaign_id' => $new_campaign->id,
'contact_list_id' => $group->id,
]);
}
}
// update manual input numbers
if (isset($input['recipients'])) {
$recipients = match ($input['delimiter']) {
',' => explode(',', $input['recipients']),
';' => explode(';', $input['recipients']),
'|' => explode('|', $input['recipients']),
'tab' => explode(' ', $input['recipients']),
'new_line' => explode("\n", $input['recipients']),
default => [],
};
$recipients = collect($recipients)->unique();
$total += $recipients->count();
$numbers = [];
if ($input['country_code'] == 0) {
$country_code = null;
} else {
$country_code = Country::find($input['country_code'])->country_code;
}
foreach ($recipients->chunk(500) as $chunk) {
foreach ($chunk as $number) {
$number = $country_code.$number;
$numbers[] = [
'campaign_id' => $new_campaign->id,
'recipient' => preg_replace("/\r/", "", $number),
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
];
}
}
CampaignsRecipients::insert($numbers);
}
if ($total == 0) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.contact_not_found'),
]);
}
if (Auth::user()->sms_unit != '-1') {
$coverage = PlansCoverageCountries::where('plan_id', $input['plan_id'])->first();
if ( ! $coverage) {
return response()->json([
'status' => 'error',
'message' => "Please add coverage on your plan.",
]);
}
$priceOption = json_decode($coverage->options, true);
$sms_count = 1;
$price = 0;
if (isset($input['message'])) {
$sms_counter = new SMSCounter();
$message_data = $sms_counter->count($input['message']);
$sms_count = $message_data->messages;
}
if ($sms_type == 'plain' || $sms_type == 'unicode') {
$unit_price = $priceOption['plain_sms'];
$price = $total * $unit_price;
}
if ($sms_type == 'voice') {
$unit_price = $priceOption['voice_sms'];
$price = $total * $unit_price;
}
if ($sms_type == 'mms') {
$unit_price = $priceOption['mms_sms'];
$price = $total * $unit_price;
}
if ($sms_type == 'whatsapp') {
$unit_price = $priceOption['whatsapp_sms'];
$price = $total * $unit_price;
}
$price *= $sms_count;
$balance = Auth::user()->sms_unit;
if ($price > $balance) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.not_enough_balance', [
'current_balance' => $balance,
'campaign_price' => $price,
]),
]);
}
}
CampaignsSendingServer::create([
'campaign_id' => $new_campaign->id,
'sending_server_id' => $sending_servers->id,
'fitness' => 100,
]);
if (isset($input['advanced']) && $input['advanced'] == "true") {
if (isset($input['send_copy']) && $input['send_copy'] == "true") {
Auth::user()->notify(new SendCampaignCopy($input['message'], route('customer.reports.campaign.edit', $new_campaign->uid)));
}
// if advanced set true then work with send copy to email and create template
if (isset($input['create_template']) && $input['create_template'] == "true") {
// create sms template
Templates::create([
'user_id' => Auth::user()->id,
'name' => $input['name'],
'message' => $input['message'],
'status' => true,
]);
}
}
// if schedule is available then check date, time and timezone
if (isset($input['schedule']) && $input['schedule'] == "true") {
$schedule_date = $input['schedule_date'].' '.$input['schedule_time'];
$schedule_time = Tool::systemTimeFromString($schedule_date, $input['timezone']);
$new_campaign->timezone = $input['timezone'];
$new_campaign->status = Campaigns::STATUS_SCHEDULED;
$new_campaign->schedule_time = $schedule_time;
if ($input['frequency_cycle'] == 'onetime') {
// working with onetime schedule
$new_campaign->schedule_type = Campaigns::TYPE_ONETIME;
} else {
// working with recurring schedule
//if schedule time frequency is not one time then check frequency details
$recurring_date = $input['recurring_date'].' '.$input['recurring_time'];
$recurring_end = Tool::systemTimeFromString($recurring_date, $input['timezone']);
$new_campaign->schedule_type = Campaigns::TYPE_RECURRING;
$new_campaign->recurring_end = $recurring_end;
if (isset($input['frequency_cycle'])) {
if ($input['frequency_cycle'] != 'custom') {
$schedule_cycle = $campaign::scheduleCycleValues();
$limits = $schedule_cycle[$input['frequency_cycle']];
$new_campaign->frequency_cycle = $input['frequency_cycle'];
$new_campaign->frequency_amount = $limits['frequency_amount'];
$new_campaign->frequency_unit = $limits['frequency_unit'];
} else {
$new_campaign->frequency_cycle = $input['frequency_cycle'];
$new_campaign->frequency_amount = $input['frequency_amount'];
$new_campaign->frequency_unit = $input['frequency_unit'];
}
}
}
} else {
$new_campaign->status = Campaigns::STATUS_QUEUED;
}
//update cache
$new_campaign->cache = json_encode([
'ContactCount' => $total,
'DeliveredCount' => 0,
'FailedDeliveredCount' => 0,
'NotDeliveredCount' => 0,
]);
if ($sms_type == 'voice') {
$new_campaign->language = $input['language'];
$new_campaign->gender = $input['gender'];
}
if ($sms_type == 'mms') {
$new_campaign->media_url = Tool::uploadImage($input['mms_file']);
}
if ($sms_type == 'whatsapp' && isset($input['mms_file'])) {
$new_campaign->media_url = Tool::uploadImage($input['mms_file']);
}
//finally, store data and return response
$camp = $new_campaign->save();
if ($camp) {
try {
if (isset($schedule_time)) {
if ($input['frequency_cycle'] == 'onetime') {
$delay_minutes = Carbon::now()->diffInMinutes($schedule_time);
dispatch(new StoreCampaignJob($new_campaign->id))->delay(now()->addMinutes($delay_minutes));
}
} else {
dispatch(new StoreCampaignJob($new_campaign->id));
}
return response()->json([
'status' => 'success',
'message' => __('locale.campaigns.campaign_send_successfully'),
]);
} catch (Throwable $exception) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => $exception->getMessage(),
]);
}
}
$new_campaign->delete();
return response()->json([
'status' => 'success',
'message' => __('locale.exceptions.something_went_wrong'),
]);
}
/**
* @param Campaigns $campaign
* @param array $input
*
* @return JsonResponse
*/
public function sendApi(Campaigns $campaign, array $input): JsonResponse
{
$user = User::where('status', true)->where('api_token', $input['api_key'])->first();
if ( ! $user) {
return response()->json([
'status' => 'error',
'message' => __('locale.auth.user_not_exist'),
]);
}
if ($user->sms_unit != '-1' && $user->sms_unit == 0) {
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.sending_limit_exceed'),
]);
}
if ($user->customer->getOption('send_spam_message') == 'no') {
$spamWords = SpamWord::all()->filter(function ($spamWord) use ($input) {
if ( true === str_contains($input['message'], $spamWord->word)) {
return true;
}
return false;
});
if ($spamWords->count()) {
return response()->json([
'status' => 'error',
'message' => 'Your message contains spam words.',
]);
}
}
$sms_type = $input['sms_type'];
//create campaign
$new_campaign = Campaigns::create([
'user_id' => $user->id,
'campaign_name' => $input['name'],
'message' => $input['message'],
'sms_type' => $sms_type,
'status' => Campaigns::STATUS_NEW,
]);
if ( ! $new_campaign) {
return response()->json([
'status' => 'error',
'message' => __('locale.exceptions.something_went_wrong'),
]);
}
if ($sms_type == 'unicode') {
$db_sms_type = 'plain';
} else {
$db_sms_type = $sms_type;
}
$sending_servers = SendingServer::where($db_sms_type, 1)->where('status', 1)->first();
if (empty($sending_servers)) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.sending_server_not_available'),
]);
}
$sender_id = null;
if ($user->customer->getOption('sender_id_verification') == 'yes') {
if (isset($input['originator'])) {
if ($input['originator'] == 'sender_id') {
if ( ! isset($input['sender_id'])) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
$sender_id = $input['sender_id'];
if (is_array($sender_id) && count($sender_id) > 0) {
$invalid = [];
$senderids = Senderid::where('user_id', $user->id)
->where('status', 'active')
->select('sender_id')
->cursor()
->pluck('sender_id')
->all();
foreach ($sender_id as $sender) {
if ( ! in_array($sender, $senderids)) {
$invalid[] = $sender;
}
}
if (count($invalid)) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_invalid', ['sender_id' => $invalid[0]]),
]);
}
} else {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
} else {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
} else {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
} else {
if (isset($input['originator'])) {
if ($input['originator'] == 'sender_id') {
if ( ! isset($input['sender_id'])) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
$sender_id = $input['sender_id'];
} else {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
if ( ! is_array($sender_id) || count($sender_id) <= 0) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
}
if (isset($input['sender_id'])) {
$sender_id = $input['sender_id'];
}
}
$sender_id = array_filter($sender_id);
if (count($sender_id)) {
foreach ($sender_id as $id) {
$data = [
'campaign_id' => $new_campaign->id,
'sender_id' => $id,
];
if (isset($input['originator'])) {
$data['originator'] = $input['originator'];
}
CampaignsSenderid::create($data);
}
}
// update manual input numbers
$recipients = explode(',', $input['recipients']);
if (is_array($recipients) && count($recipients) == 0) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.contact_not_found'),
]);
}
$numbers = [];
foreach ($recipients as $number) {
$numbers[] = [
'campaign_id' => $new_campaign->id,
'recipient' => preg_replace("/\r/", "", $number),
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
];
}
CampaignsRecipients::insert($numbers);
$total = count($recipients);
if ($user->sms_unit != '-1') {
$sms_count = 1;
$price = 0;
if (isset($input['message'])) {
$sms_counter = new SMSCounter();
$message_data = $sms_counter->count($input['message']);
$sms_count = $message_data->messages;
}
if ($sms_type == 'plain' || $sms_type == 'unicode') {
$unit_price = $user->customer->getOption('plain_sms');
$price = $total * $unit_price;
}
if ($sms_type == 'voice') {
$unit_price = $user->customer->getOption('voice_sms');
$price = $total * $unit_price;
}
if ($sms_type == 'mms') {
$unit_price = $user->customer->getOption('mms_sms');
$price = $total * $unit_price;
}
if ($sms_type == 'whatsapp') {
$unit_price = $user->customer->getOption('whatsapp_sms');
$price = $total * $unit_price;
}
$price *= $sms_count;
$balance = $user->sms_unit;
if ($price > $balance) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.not_enough_balance', [
'current_balance' => $balance,
'campaign_price' => $price,
]),
]);
}
}
CampaignsSendingServer::create([
'campaign_id' => $new_campaign->id,
'sending_server_id' => $sending_servers->id,
'fitness' => 100,
]);
// if schedule is available then check date, time and timezone
if (isset($input['schedule']) && $input['schedule']) {
$schedule_date = $input['schedule_date'].' '.$input['schedule_time'];
$schedule_time = Tool::systemTimeFromString($schedule_date, $input['timezone']);
$new_campaign->timezone = $input['timezone'];
$new_campaign->status = Campaigns::STATUS_SCHEDULED;
$new_campaign->schedule_time = $schedule_time;
$new_campaign->schedule_type = Campaigns::TYPE_ONETIME;
} else {
$new_campaign->status = Campaigns::STATUS_QUEUED;
}
//update cache
$new_campaign->cache = json_encode([
'ContactCount' => $total,
'DeliveredCount' => 0,
'FailedDeliveredCount' => 0,
'NotDeliveredCount' => 0,
]);
if ($sms_type == 'voice') {
$new_campaign->language = $input['language'];
$new_campaign->gender = $input['gender'];
}
if ($sms_type == 'mms') {
$new_campaign->media_url = $input['media_url'];
}
//finally, store data and return response
$camp = $new_campaign->save();
if ($camp) {
try {
if (isset($schedule_time)) {
$delay_minutes = Carbon::now()->diffInMinutes($schedule_time);
dispatch(new StoreCampaignJob($new_campaign->id))->delay(now()->addMinutes($delay_minutes));
} else {
dispatch(new StoreCampaignJob($new_campaign->id));
}
return response()->json([
'status' => 'success',
'message' => __('locale.campaigns.campaign_send_successfully'),
]);
} catch (Throwable $exception) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => $exception->getMessage(),
]);
}
}
$new_campaign->delete();
return response()->json([
'status' => 'success',
'message' => __('locale.exceptions.something_went_wrong'),
]);
}
/**
* send message using file
*
* @param Campaigns $campaign
* @param array $input
*
* @return JsonResponse
*/
public function sendUsingFile(Campaigns $campaign, array $input): JsonResponse
{
if (Auth::user()->sms_unit != '-1' && Auth::user()->sms_unit == 0) {
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.sending_limit_exceed'),
]);
}
$data = CsvData::find($input['csv_data_file_id']);
$csv_data = json_decode($data->csv_data, true);
$db_fields = $input['fields'];
$form_data = json_decode($input['form_data'], true);
if (is_array($db_fields) && ! in_array('phone', $db_fields)) {
return response()->json([
'status' => 'error',
'message' => __('locale.filezone.phone_number_column_require'),
]);
}
$collection = collect($csv_data)->skip($data->csv_header);
$total = $collection->count();
if ($total == 0) {
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.contact_not_found'),
]);
}
if (Auth::user()->customer->getOption('send_spam_message') == 'no') {
$spamWords = SpamWord::all()->filter(function ($spamWord) use ($input) {
if ( true === str_contains(strtolower($input['message']), strtolower($spamWord->word))) {
return true;
}
return false;
});
if ($spamWords->count()) {
return response()->json([
'status' => 'error',
'message' => 'Your message contains spam words.',
]);
}
}
//create campaign
$new_campaign = Campaigns::create([
'user_id' => Auth::user()->id,
'campaign_name' => $form_data['name'],
'sms_type' => $form_data['sms_type'],
'message' => $input['message'],
'upload_type' => 'file',
'status' => Campaigns::STATUS_NEW,
]);
if ( ! $new_campaign) {
return response()->json([
'status' => 'error',
'message' => __('locale.exceptions.something_went_wrong'),
]);
}
if ($form_data['sms_type'] == 'unicode') {
$db_sms_type = 'plain';
} else {
$db_sms_type = $form_data['sms_type'];
}
if ($form_data['sms_type'] == 'plain' || $form_data['sms_type'] == 'unicode') {
$capabilities_type = 'sms';
} else {
$capabilities_type = $form_data['sms_type'];
}
$sending_servers = SendingServer::where('status', 1)->where($db_sms_type, 1)->find($form_data['sending_server']);
if (empty($sending_servers)) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.sending_server_not_available'),
]);
}
$sender_id = null;
if (Auth::user()->customer->getOption('sender_id_verification') == 'yes') {
if (isset($form_data['originator'])) {
if ($form_data['originator'] == 'sender_id') {
if ( ! isset($form_data['sender_id'])) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
$sender_id = $form_data['sender_id'];
if (is_array($sender_id) && count($sender_id) > 0) {
$invalid = [];
$senderids = Senderid::where('user_id', Auth::user()->id)
->where('status', 'active')
->select('sender_id')
->cursor()
->pluck('sender_id')
->all();
foreach ($sender_id as $sender) {
if ( ! in_array($sender, $senderids)) {
$invalid[] = $sender;
}
}
if (count($invalid)) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_invalid', ['sender_id' => $invalid[0]]),
]);
}
} else {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
} else {
if ( ! isset($form_data['phone_number'])) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.phone_numbers_required'),
]);
}
$sender_id = $form_data['phone_number'];
if (is_array($sender_id) && count($sender_id) > 0) {
$type_supported = [];
PhoneNumbers::where('user_id', Auth::user()->id)
->where('status', 'assigned')
->cursor()
->reject(function ($number) use ($sender_id, &$type_supported, &$invalid, $capabilities_type) {
if (in_array($number->number, $sender_id) && ! str_contains($number->capabilities, $capabilities_type)) {
return $type_supported[] = $number->number;
}
return $sender_id;
})->all();
if (count($type_supported)) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_sms_capabilities', ['sender_id' => $type_supported[0], 'type' => $db_sms_type]),
]);
}
} else {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
}
} else {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
} elseif (Auth::user()->can('view_numbers') && isset($form_data['originator']) && $form_data['originator'] == 'phone_number') {
$sender_id = $form_data['phone_number'];
if (is_array($sender_id) && count($sender_id) > 0) {
$type_supported = [];
PhoneNumbers::where('user_id', Auth::user()->id)
->where('status', 'assigned')
->cursor()
->reject(function ($number) use ($sender_id, &$type_supported, &$invalid, $capabilities_type) {
if (in_array($number->number, $sender_id) && ! str_contains($number->capabilities, $capabilities_type)) {
return $type_supported[] = $number->number;
}
return $sender_id;
})->all();
if (count($type_supported)) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_sms_capabilities', ['sender_id' => $type_supported[0], 'type' => $db_sms_type]),
]);
}
} else {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
} else {
if (isset($form_data['originator'])) {
if ($form_data['originator'] == 'sender_id') {
if ( ! isset($form_data['sender_id'])) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
$sender_id = $form_data['sender_id'];
} else {
if ( ! isset($form_data['phone_number'])) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.phone_numbers_required'),
]);
}
$sender_id = $form_data['phone_number'];
}
if ( ! is_array($sender_id) || count($sender_id) <= 0) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.sender_id.sender_id_required'),
]);
}
}
if (isset($form_data['sender_id'])) {
$sender_id = $form_data['sender_id'];
$form_data['originator'] = 'sender_id';
}
}
$sender_id = array_filter($sender_id);
if (count($sender_id)) {
foreach ($sender_id as $id) {
$sender_id_data = [
'campaign_id' => $new_campaign->id,
'sender_id' => $id,
];
if (isset($form_data['originator'])) {
$sender_id_data['originator'] = $form_data['originator'];
}
CampaignsSenderid::create($sender_id_data);
}
}
if (Auth::user()->sms_unit != '-1') {
$coverage = PlansCoverageCountries::where('plan_id', $form_data['plan_id'])->first();
if ( ! $coverage) {
return response()->json([
'status' => 'error',
'message' => "Please add coverage on your plan.",
]);
}
$priceOption = json_decode($coverage->options, true);
$price = 0;
if ($form_data['sms_type'] == 'plain' || $form_data['sms_type'] == 'unicode') {
$unit_price = $priceOption['plain_sms'];
$price = $total * $unit_price;
}
if ($form_data['sms_type'] == 'voice') {
$unit_price = $priceOption['voice_sms'];
$price = $total * $unit_price;
}
if ($form_data['sms_type'] == 'mms') {
$unit_price = $priceOption['mms_sms'];
$price = $total * $unit_price;
}
if ($form_data['sms_type'] == 'whatsapp') {
$unit_price = $priceOption['whatsapp_sms'];
$price = $total * $unit_price;
}
$balance = Auth::user()->sms_unit;
if ($price > $balance) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.campaigns.not_enough_balance', [
'current_balance' => $balance,
'campaign_price' => $price,
]),
]);
}
}
CampaignsSendingServer::create([
'campaign_id' => $new_campaign->id,
'sending_server_id' => $sending_servers->id,
'fitness' => 100,
]);
// if schedule is available then check date, time and timezone
if (isset($form_data['schedule']) && $form_data['schedule'] == "true") {
$schedule_date = $form_data['schedule_date'].' '.$form_data['schedule_time'];
$schedule_time = Tool::systemTimeFromString($schedule_date, $form_data['timezone']);
$new_campaign->timezone = $form_data['timezone'];
$new_campaign->status = Campaigns::STATUS_SCHEDULED;
$new_campaign->schedule_type = Campaigns::TYPE_ONETIME;
$new_campaign->schedule_time = $schedule_time;
} else {
$new_campaign->status = Campaigns::STATUS_QUEUED;
}
//update cache
$new_campaign->cache = json_encode([
'ContactCount' => $total,
'DeliveredCount' => 0,
'FailedDeliveredCount' => 0,
'NotDeliveredCount' => 0,
]);
if ($form_data['sms_type'] == 'voice') {
$new_campaign->language = $form_data['language'];
$new_campaign->gender = $form_data['gender'];
}
if ($form_data['sms_type'] == 'mms') {
$new_campaign->media_url = $form_data['media_url'];
}
//finally, store data and return response
$camp = $new_campaign->save();
if ($camp) {
try {
if (isset($schedule_time)) {
$delay_minutes = Carbon::now()->diffInMinutes($schedule_time);
dispatch(new ScheduleBatchJob(Auth::user()->id, $new_campaign->id, $collection, $db_fields, $csv_data[0]))->delay(now()->addMinutes($delay_minutes));
return response()->json([
'status' => 'success',
'message' => __('locale.campaigns.campaign_successfully_imported_in_background'),
]);
}
$batch_list = [];
Tool::resetMaxExecutionTime();
$collection->chunk(5000)
->each(function ($lines) use ($new_campaign, &$batch_list, $db_fields, $csv_data) {
$batch_list[] = new ImportCampaign(Auth::user()->id, $new_campaign->id, $lines, $db_fields, $csv_data[0]);
});
$import_name = 'ImportCampaigns_'.date('Ymdhms');
$import_job = ImportJobHistory::create([
'name' => $import_name,
'import_id' => $new_campaign->uid,
'type' => 'import_campaign',
'status' => 'processing',
'options' => json_encode(['status' => 'processing', 'message' => 'Import campaign are running']),
'batch_id' => null,
]);
$batch = Bus::batch($batch_list)
->then(function (Batch $batch) use ($new_campaign, $import_name, $import_job) {
$new_campaign->processing();
$new_campaign->update(['batch_id' => $batch->id]);
$import_job->update(['batch_id' => $batch->id]);
})
->catch(function (Batch $batch, Throwable $e) {
$import_history = ImportJobHistory::where('batch_id', $batch->id)->first();
if ($import_history) {
$import_history->status = 'failed';
$import_history->options = json_encode(['status' => 'failed', 'message' => $e->getMessage()]);
$import_history->save();
}
})
->finally(function (Batch $batch) use ($new_campaign, $data) {
$import_history = ImportJobHistory::where('batch_id', $batch->id)->first();
if ($import_history) {
$import_history->status = 'finished';
$import_history->options = json_encode(['status' => 'finished', 'message' => 'Import campaign was successfully imported.']);
$import_history->save();
Campaigns::find($new_campaign->id)->delivered();
}
$data->delete();
//send event notification remaining
})
->name($import_name)
->allowFailures(false)
->dispatch();
$new_campaign->update(['batch_id' => $batch->id]);
return response()->json([
'status' => 'success',
'message' => __('locale.campaigns.campaign_successfully_imported_in_background'),
]);
} catch (Throwable $exception) {
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => $exception->getMessage(),
]);
}
}
$new_campaign->delete();
return response()->json([
'status' => 'error',
'message' => __('locale.exceptions.something_went_wrong'),
]);
}
/**
* @inheritDoc
*/
public function cancel(Campaigns $campaign)
{
// TODO: Implement cancel() method.
}
/**
* @inheritDoc
*/
public function pause(Campaigns $campaign)
{
// TODO: Implement pause() method.
}
/**
* @inheritDoc
*/
public function destroy(Campaigns $campaign)
{
// TODO: Implement destroy() method.
}
/**
* @inheritDoc
*/
public function update(Campaigns $campaign, array $input)
{
// TODO: Implement update() method.
}
/**
* @inheritDoc
*/
public function resend(Campaigns $campaign)
{
// TODO: Implement resend() method.
}
}