Bugfix/list clickup issue (#5)

Reviewed-on: #5
Co-authored-by: ISMAIL MASSERAN <ismail@koppkb.com>
Co-committed-by: ISMAIL MASSERAN <ismail@koppkb.com>
This commit was merged in pull request #5.
This commit is contained in:
2026-10-19 13:30:36 +08:00
committed by ismailmasseran
parent b1d393b1a1
commit e29a5891c8
196 changed files with 18243 additions and 19520 deletions
+3 -3
View File
@@ -3,8 +3,8 @@
namespace App\Services;
use Billplz\Client as BillplzClient;
use Http\Client\Common\HttpMethodsClient;
use GuzzleHttp\Client as GuzzleHttpClient;
use Http\Client\Common\HttpMethodsClient;
use Http\Message\MessageFactory\GuzzleMessageFactory;
use Laravie\Codex\Exceptions\NotFoundException;
@@ -16,8 +16,8 @@ class BillplzService
{
// Buat HttpMethodsClient dengan GuzzleHttpClient dan GuzzleMessageFactory
$http = new HttpMethodsClient(
new GuzzleHttpClient(), // Guzzle HTTP client
new GuzzleMessageFactory() // Guzzle message factory untuk request dan response
new GuzzleHttpClient, // Guzzle HTTP client
new GuzzleMessageFactory // Guzzle message factory untuk request dan response
);
// Get API key dan base URL dari environment
+17 -21
View File
@@ -2,16 +2,14 @@
namespace App\Services;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use App\Models\FileMarhun;
use App\Models\LelongBid;
use Exception;
use Buglinjo\LaravelWebp\Facades\Webp;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class MarhunPhotoService
{
public function store(Request $request)
{
@@ -22,7 +20,7 @@ class MarhunPhotoService
logger($exception);
}
$addfile = new FileMarhun();
$addfile = new FileMarhun;
$addfile->lelongbid_id = $request->lelongbid_id;
$addfile->file_type = $file_type;
if ($request->photo_type == 1) {
@@ -40,10 +38,9 @@ class MarhunPhotoService
$directory = "/{$no_rujukan_sag}/{$photo_type_name}/";
$imageExtension = $file_type;
$marhunImageFileName = "overall";
$marhunImageFileName = 'overall';
if (!empty($request->lelongbidmarhun_id)) {
if (! empty($request->lelongbidmarhun_id)) {
$marhunImageFileName = "$request->lelongbidmarhun_id";
}
@@ -73,7 +70,7 @@ class MarhunPhotoService
$lelongbidmarhun_id = $deleteFile->lelongbidmarhun_id;
if (!empty($request->lelongbidmarhun_id)) {
if (! empty($request->lelongbidmarhun_id)) {
$marhunImageFileName = "$lelongbidmarhun_id.$imageExtension";
}
@@ -92,14 +89,14 @@ class MarhunPhotoService
$marhunImageFileName = "overall.{$imageExtension}";
if (!empty($lelongbidmarhun_id)) {
if (! empty($lelongbidmarhun_id)) {
$marhunImageFileName = "$lelongbidmarhun_id.$imageExtension";
}
$filePath = Storage::disk('marhun')->path("{$directory}${marhunImageFileName}");
header('Content-Type: ' . mime_content_type($filePath));
header('Content-Disposition: inline; filename="' . basename($filePath) . '"');
header('Content-Type: '.mime_content_type($filePath));
header('Content-Disposition: inline; filename="'.basename($filePath).'"');
readfile($filePath);
}
@@ -114,24 +111,23 @@ class MarhunPhotoService
$marhunImageFileName = "overall.{$imageExtension}";
if (!empty($lelongbidmarhun_id)) {
if (! empty($lelongbidmarhun_id)) {
$marhunImageFileName = "$lelongbidmarhun_id.$imageExtension";
}
return Storage::disk('marhun')->get("{$directory}${marhunImageFileName}");
}
private function getWebpCompilerByOS()
{
$DS = DIRECTORY_SEPARATOR;
$cwebp_compilers = [
'Windows' => 'binaries' . $DS . 'libwebp-1.2.4-windows-x64' . $DS . 'bin' . $DS . 'cwebp',
'Linux' => 'binaries' . $DS . 'libwebp-1.2.4-linux-x86-64' . $DS . 'bin' . $DS .'cwebp',
'Windows' => 'binaries'.$DS.'libwebp-1.2.4-windows-x64'.$DS.'bin'.$DS.'cwebp',
'Linux' => 'binaries'.$DS.'libwebp-1.2.4-linux-x86-64'.$DS.'bin'.$DS.'cwebp',
'Darwin' => [
'X86-64' => 'binaries' . $DS . 'libwebp-1.2.4-mac-X86-64' . $DS . 'bin' . $DS . 'cwebp',
'arm64' => 'binaries' . $DS . 'libwebp-1.2.4-mac-arm64' . $DS . 'bin' . $DS .'cwebp',
'X86-64' => 'binaries'.$DS.'libwebp-1.2.4-mac-X86-64'.$DS.'bin'.$DS.'cwebp',
'arm64' => 'binaries'.$DS.'libwebp-1.2.4-mac-arm64'.$DS.'bin'.$DS.'cwebp',
],
];
@@ -140,7 +136,7 @@ class MarhunPhotoService
if ($server_operating_system === 'Darwin') {
return resource_path($cwebp_compilers['Darwin'][$server_processor_architecture]);
}
}
if (in_array($server_operating_system, array_keys($cwebp_compilers))) {
return resource_path($cwebp_compilers[$server_operating_system]);
@@ -149,10 +145,10 @@ class MarhunPhotoService
private function optimizeImageToWebP($originalFilePath, $directory, $lelongbidmarhun_id)
{
$convertedFilePath = config('filesystems.disks.marhun.root') . '/' . "{$directory}{$lelongbidmarhun_id}.webp";
$convertedFilePath = config('filesystems.disks.marhun.root').'/'."{$directory}{$lelongbidmarhun_id}.webp";
$webpCompiler = $this->getWebpCompilerByOS();
exec($webpCompiler . ' -preset photo ' . ' -resize 1280 720 ' . ' -mt ' . $originalFilePath . ' -o ' . $convertedFilePath);
exec($webpCompiler.' -preset photo '.' -resize 1280 720 '.' -mt '.$originalFilePath.' -o '.$convertedFilePath);
}
}
+12 -16
View File
@@ -2,16 +2,13 @@
namespace App\Services;
use App\Models\FileResit;
use Buglinjo\LaravelWebp\Facades\Webp;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use App\Models\FileResit;
use App\Models\LelongBid;
use Exception;
use Buglinjo\LaravelWebp\Facades\Webp;
class ResitPhotoService
{
public function delete(Request $request)
{
$deleteFile = FileResit::where('id', '=', $request->fileresit_id)->first();
@@ -26,7 +23,7 @@ class ResitPhotoService
$lelongbidmarhun_id = $deleteFile->lelongbidmarhun_id;
if (!empty($request->lelongbidmarhun_id)) {
if (! empty($request->lelongbidmarhun_id)) {
$resitImageFileName = "$lelongbidmarhun_id.$imageExtension";
}
@@ -50,7 +47,7 @@ class ResitPhotoService
// $resitImageFileName = "{$fileresit_id}.{$imageExtension}";
if (!empty($fileresit_id)) {
if (! empty($fileresit_id)) {
$resitImageFileName = "$fileresit_id.$imageExtension";
// dd($resitImageFileName);
}
@@ -60,7 +57,7 @@ class ResitPhotoService
// dd($filePath);
// header('Content-Type: ' . mime_content_type($filePath));
header('Content-Disposition: inline; filename="' . basename($filePath) . '"');
header('Content-Disposition: inline; filename="'.basename($filePath).'"');
readfile($filePath);
// dd($filePath);
}
@@ -78,17 +75,16 @@ class ResitPhotoService
return Storage::disk('resit')->get("{$directory}${resitImageFileName}");
}
private function getWebpCompilerByOS()
{
$DS = DIRECTORY_SEPARATOR;
$cwebp_compilers = [
'Windows' => 'binaries' . $DS . 'libwebp-1.2.4-windows-x64' . $DS . 'bin' . $DS . 'cwebp',
'Linux' => 'binaries' . $DS . 'libwebp-1.2.4-linux-x86-64' . $DS . 'bin' . $DS .'cwebp',
'Windows' => 'binaries'.$DS.'libwebp-1.2.4-windows-x64'.$DS.'bin'.$DS.'cwebp',
'Linux' => 'binaries'.$DS.'libwebp-1.2.4-linux-x86-64'.$DS.'bin'.$DS.'cwebp',
'Darwin' => [
'X86-64' => 'binaries' . $DS . 'libwebp-1.2.4-mac-X86-64' . $DS . 'bin' . $DS . 'cwebp',
'arm64' => 'binaries' . $DS . 'libwebp-1.2.4-mac-arm64' . $DS . 'bin' . $DS .'cwebp',
'X86-64' => 'binaries'.$DS.'libwebp-1.2.4-mac-X86-64'.$DS.'bin'.$DS.'cwebp',
'arm64' => 'binaries'.$DS.'libwebp-1.2.4-mac-arm64'.$DS.'bin'.$DS.'cwebp',
],
];
@@ -97,7 +93,7 @@ class ResitPhotoService
if ($server_operating_system === 'Darwin') {
return resource_path($cwebp_compilers['Darwin'][$server_processor_architecture]);
}
}
if (in_array($server_operating_system, array_keys($cwebp_compilers))) {
return resource_path($cwebp_compilers[$server_operating_system]);
@@ -106,11 +102,11 @@ class ResitPhotoService
public function optimizeImageToWebP($originalFilePath, $directory, $resitImageFileName)
{
$convertedFilePath = config('filesystems.disks.resit.root') . "{$directory}{$resitImageFileName}.webp";
$convertedFilePath = config('filesystems.disks.resit.root')."{$directory}{$resitImageFileName}.webp";
$webpCompiler = $this->getWebpCompilerByOS();
exec($webpCompiler . ' -preset photo ' . '-q 10' . ' -mt ' . $originalFilePath . ' -o ' . $convertedFilePath);
exec($webpCompiler.' -preset photo '.'-q 10'.' -mt '.$originalFilePath.' -o '.$convertedFilePath);
}
}
+132
View File
@@ -0,0 +1,132 @@
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class WhatsAppCloudService
{
public function isEnabled()
{
return (bool) config('whatsapp.whatsapp_cloud_enabled')
&& ! empty(config('whatsapp.token'))
&& ! empty(config('whatsapp.phone_number_id'));
}
/**
* Normalize Malaysian phone numbers to digits with country code (e.g. 60123456789).
*/
public function normalizePhone($phone)
{
if ($phone === null || $phone === '') {
return null;
}
$digits = preg_replace('/\D+/', '', (string) $phone);
if ($digits === '') {
return null;
}
if (strpos($digits, '60') === 0) {
return $digits;
}
if (strpos($digits, '0') === 0) {
return '6'.$digits;
}
return '60'.ltrim($digits, '0');
}
/**
* In non-production, always send to ADMIN_PHONE_NUMBER.
*/
public function resolveRecipient($phone)
{
if (config('app.env') !== 'production') {
return $this->normalizePhone(config('app.admin_phone_number'));
}
return $this->normalizePhone($phone);
}
/**
* Send an approved WhatsApp Cloud API template message.
*
* @param string $to E.164-ish digits without +
* @param string $templateName
* @param array<int, string> $bodyParams Ordered body variables {{1}}, {{2}}, ...
* @return array{ok:bool,status:int,body:mixed}
*/
public function sendTemplate($to, $templateName, array $bodyParams = [], $languageCode = null)
{
if (! $this->isEnabled()) {
Log::warning('WhatsApp Cloud API skipped: not enabled or missing credentials.');
return ['ok' => false, 'status' => 0, 'body' => 'disabled'];
}
$to = $this->normalizePhone($to);
if (! $to) {
return ['ok' => false, 'status' => 0, 'body' => 'invalid_phone'];
}
$languageCode = $languageCode ?: config('whatsapp.template_lang', 'en_US');
$version = config('whatsapp.api_version', 'v25.0');
$phoneNumberId = config('whatsapp.phone_number_id');
$url = "https://graph.facebook.com/{$version}/{$phoneNumberId}/messages";
$template = [
'name' => $templateName,
'language' => ['code' => $languageCode],
];
if (! empty($bodyParams)) {
$template['components'] = [[
'type' => 'body',
'parameters' => array_map(function ($value) {
return [
'type' => 'text',
'text' => (string) $value,
];
}, array_values($bodyParams)),
]];
}
$payload = [
'messaging_product' => 'whatsapp',
'to' => $to,
'type' => 'template',
'template' => $template,
];
$response = Http::withToken(config('whatsapp.token'))
->acceptJson()
->asJson()
->post($url, $payload);
$result = [
'ok' => $response->successful(),
'status' => $response->status(),
'body' => $response->json() ?? $response->body(),
];
if (! $result['ok']) {
Log::error('WhatsApp Cloud API template send failed', [
'to' => $to,
'template' => $templateName,
'status' => $result['status'],
'body' => $result['body'],
]);
} else {
Log::info('WhatsApp Cloud API template sent', [
'to' => $to,
'template' => $templateName,
'message_id' => data_get($result['body'], 'messages.0.id'),
]);
}
return $result;
}
}