• דף הבית
    • אינדקס קישורים
    • פוסטים אחרונים
    • משתמשים
    • חיפוש בהגדרות המתקדמות
    • חיפוש גוגל בפורום
    • ניהול המערכת
    • ניהול המערכת - שרת private
    • הרשמה
    • התחברות
    1. דף הבית
    2. שלוחה-404
    3. פוסטים
    ש מנותק
    • פרופיל
    • עוקב אחרי 0
    • עוקבים 5
    • נושאים 34
    • פוסטים 590
    • קבוצות 0

    פוסטים

    פוסטים אחרונים הגבוה ביותר שנוי במחלוקת
    • RE: בוט שעוקב אחרי הודעות

      @הדיבל-המעופף @מערכות-טלפוניות מצרף את הקוד הוא צריך התאמה למערכת שלכם כי הוא מובנה למערכת שלי
      פעולת הקוד בסיום הקלטה עוברים לשלוחת API ששולחת את הפרמטרים הבאים

      api_add_0=secret1=
      api_add_1=RECORD=/02/2
      api_add_2=NATIV=/02/1
      api_add_3=email1=@gmail.com
      

      נתיב שלוחת הקלטה נתיב שלוחה שנשמר הקובץ
      הקובץ נשלח לתמלול בגימיני ובשרת פייטון שלי אם גימני זמין הוא מתמלל מחליט לפי הפרומפט האם לאשר או לדחות הוא מוסיף את המילה שפסלה לקובץ גסון בשרת במקרה שגימיני לא זמין אנחנו בודקים את התמלול מפיטון מול הרשימת מילים שולחים צינתוק אם הקובץ אושר זה עובד ביחד אם צינתוק מותאם אישית של@איל-משולש אם עבר 30 שניות ואין תשובה עדיין זה שולח צינתוק וממשיך בבדיקה אפשר להכניס מספרים שאצלהם הבדיקה תהיה יותר יסודית

      <?php
      
      declare(strict_types=1);
      
      namespace App\Webhook;
      
      use RuntimeException;
      use Throwable;
      use CURLFile;
      use DateTimeImmutable;
      use CurlHandle;
      
      // ==========================================
      // ⚙️ טעינת הגדרות ראשיות
      // ==========================================
      if (file_exists($configPath)) {
          require_once $configPath;
      }
      
      date_default_timezone_set('Asia/Jerusalem');
      
      // ==========================================
      // 🛡️ Enums & DTOs
      // ==========================================
      
      enum Decision: string
      {
          case APPROVE = 'APPROVE';
          case REJECT  = 'REJECT';
          case UNKNOWN = 'UNKNOWN';
      }
      
      enum Engine: string
      {
          case GEMINI_AUDIO = 'Gemini (Audio)';
          case GEMINI_TEXT  = 'Gemini (Text Fallback)';
          case PYTHON_DICT  = 'Python + Dictionary';
          case ERROR        = 'System Error';
      }
      
      readonly class AnalysisResult
      {
          public function __construct(
              public Decision $decision,
              public string $transcription,
              public Engine $engine,
              public string $bannedWord = ''
          ) {}
      }
      
      // ==========================================
      // 🛠️ מחלקות תשתית ולוגיקה
      // ==========================================
      
      readonly class Logger
      {
          public function __construct(private string $logDir) {}
      
          public function log(string $type, string $message): void
          {
              $timeNow = date("Y-m-d H:i:s");
              $logEntry = sprintf("[%s] [%s] %s%s", $timeNow, $type, $message, PHP_EOL);
              
              $periodId = (int)floor(time() / (15 * 86400));
              $currentLogFile = rtrim($this->logDir, '/') . "/system_log_period_{$periodId}.txt";
              
              file_put_contents($currentLogFile, $logEntry, FILE_APPEND | LOCK_EX);
              
              $this->cleanupOldLogs($periodId);
          }
          
          private function cleanupOldLogs(int $currentPeriodId): void
          {
              $files = glob(rtrim($this->logDir, '/') . "/system_log_period_*.txt");
              if ($files === false) return;
      
              foreach ($files as $file) {
                  if (preg_match('/system_log_period_(\d+)\.txt$/', $file, $matches)) {
                      $filePeriod = (int)$matches[1];
                      if ($filePeriod < $currentPeriodId - 1) {
                          @unlink($file);
                      }
                  }
              }
          }
      }
      
      class SystemReleaser
      {
          public static function release(string $output = "OK"): void
          {
              if (function_exists('fastcgi_finish_request')) {
                  echo $output;
                  session_write_close();
                  fastcgi_finish_request();
              } else {
                  ignore_user_abort(true);
                  set_time_limit(300);
                  ob_start();
                  echo $output;
                  header("Content-Length: " . (string)ob_get_length());
                  header("Connection: close");
                  ob_end_flush();
                  flush();
              }
          }
      }
      
      readonly class YemotClient
      {
          public function __construct(
              private string $apiUrl,
              private string $token
          ) {}
      
          public function call(string $method, array $params = []): array
          {
              $params['token'] = $this->token;
              $ch = curl_init($this->apiUrl . $method);
              
              if (!$ch) {
                  throw new RuntimeException("Failed to init cURL for Yemot API.");
              }
      
              curl_setopt_array($ch, [
                  CURLOPT_POST           => true,
                  CURLOPT_POSTFIELDS     => http_build_query($params),
                  CURLOPT_RETURNTRANSFER => true,
                  CURLOPT_TIMEOUT        => 15
              ]);
      
              $response = curl_exec($ch);
              curl_close($ch);
      
              $decoded = json_decode((string)$response, true);
              return is_array($decoded) ? $decoded : [];
          }
      
          public function downloadAudio(string $path): string
          {
              $url = $this->apiUrl . "DownloadFile?token={$this->token}&path=ivr2:{$path}";
              $ch = curl_init($url);
              
              if (!$ch) {
                  throw new RuntimeException("Failed to init cURL for Audio Download.");
              }
      
              curl_setopt_array($ch, [
                  CURLOPT_RETURNTRANSFER => true,
                  CURLOPT_SSL_VERIFYPEER => false,
                  CURLOPT_TIMEOUT        => 30
              ]);
              
              $audio = curl_exec($ch);
              $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
              curl_close($ch);
      
              if ($audio === false || $httpCode !== 200) {
                  throw new RuntimeException("Failed to download audio from: {$path}");
              }
              return (string)$audio;
          }
      
          public function normalizePhone(string $phone): string
          {
              $clean = preg_replace('/[^0-9]/', '', $phone);
              if (str_starts_with($clean, '972')) {
                  $clean = substr($clean, 3);
              }
              return ltrim($clean, '0');
          }
      }
      
      class DictionaryManager
      {
          public function __construct(private readonly string $filePath)
          {
              if (!file_exists($this->filePath)) {
                  $initialWords = ];
                  file_put_contents($this->filePath, json_encode($initialWords, JSON_UNESCAPED_UNICODE));
              }
          }
      
          public function getWords(): array
          {
              $data = json_decode(file_get_contents($this->filePath) ?: '[]', true);
              return is_array($data) ? $data : [];
          }
      
          public function addWord(string $word): void
          {
              $word = trim($word);
              if ($word === '') return;
      
              $fp = fopen($this->filePath, 'c+');
              if ($fp && flock($fp, LOCK_EX)) {
                  $size = filesize($this->filePath);
                  $content = $size > 0 ? fread($fp, $size) : '[]';
                  $words = json_decode($content, true);
                  if (!is_array($words)) $words = [];
      
                  if (!in_array($word, $words, true)) {
                      $words[] = $word;
                      ftruncate($fp, 0);
                      rewind($fp);
                      fwrite($fp, json_encode($words, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
                  }
                  flock($fp, LOCK_UN);
                  fclose($fp);
              }
          }
      }
      
      class TzintukManager
      {
          public function __construct(
              private readonly string $numbersFile,
              private readonly Logger $logger
          ) {
              if (!file_exists($this->numbersFile)) {
                  file_put_contents($this->numbersFile, json_encode([]));
              }
          }
      
          public function updateHours(string $phone, string $m, string $h, string $adminPhone): void
          {
              $numbersData = json_decode(file_get_contents($this->numbersFile) ?: '[]', true) ?: [];
              $cleanPhone = str_starts_with(trim($phone), '0') ? trim($phone) : '0' . trim($phone);
      
              $numbersData[$cleanPhone] = [
                  'start' => str_replace("-", ":", $m),
                  'end'   => str_replace("-", ":", $h)
              ];
              
              file_put_contents($this->numbersFile, json_encode($numbersData, JSON_PRETTY_PRINT | LOCK_EX));
          }
      
          public function sendTzintuk(YemotClient $apiClient): void
          {
              $numbersData = json_decode(file_get_contents($this->numbersFile) ?: '[]', true) ?: [];
              $phonesToCall = [];
              $curTime = time();
      
              foreach ($numbersData as $num => $hours) {
                  $s = strtotime($hours['start']);
                  $e = strtotime($hours['end']);
                  if ($s && $e) {
                      $inRange = $s <= $e ? ($curTime >= $s && $curTime <= $e) : ($curTime >= $s || $curTime <= $e);
                      if ($inRange) $phonesToCall[] = $num;
                  }
              }
      
              $phonesParam = empty($phonesToCall) ? "" : "," . implode(",", $phonesToCall);
              try {
                  $apiClient->call("RunTzintuk", [
                      'callerId' => '',
                      'TzintukTimeOut' => 6,
                      'phones' => "tzl:women{$phonesParam}"
                  ]);
                  $this->logger->log("צינתוק", "נשלח צינתוק למנויים במערכת.");
              } catch (Throwable $e) {
                  // התעלמות
              }
          }
      }
      
      // ==========================================
      // 🧠 מנוע ניהול סינון מקבילי (Orchestrator)
      // ==========================================
      
      readonly class ModerationOrchestrator
      {
          private const GEMINI_API = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent';
      
          private const MODERATION_PROMPT = "You are a ZERO TOLERANCE content moderation AI for a community hotline. "
              . "Listen and transcribe perfectly in Hebrew. Pay close attention to the context of the words.\n"
              . "REJECT if the audio mentions ANY of the following:\n"
              . "1. Violence, threats, or physical conflicts.\n"
              . "2. Gossip, slander, speaking negatively about specific people, or talking 'behind someone's back' (e.g., 'מאחורי הגב').\n"
              . "3. Marital status changes, separation, divorce (e.g., 'נפרדתי מבעלי'), or airing personal family drama.\n"
              . "APPROVE:\n"
              . "1. Genuine requests for help, lost and found, technical info, benign greetings.\n"
              . "2. Updates or complaints about PUBLIC SERVICES or businesses (e.g., 'הספרייה לא נפתחת, אי אפשר לסמוך על זה' - This is ALLOWED because it's a consumer update, not personal gossip).\n"
              . "IMPORTANT: DO NOT REJECT merely because a sentence is cut off. DO NOT REJECT criticism of public institutions.\n"
              . "Return EXACT JSON: {\"decision\":\"APPROVE|REJECT\",\"transcription\":\"exact text\",\"reason_word\":\"worst phrase if rejected\"}";
      
          public function __construct(
              private string $geminiKey,
              private string $pythonUrl,
              private string $pythonKey,
              private DictionaryManager $dictionary,
              private TzintukManager $tzManager,
              private YemotClient $yemotClient
          ) {}
      
          // 🌟 הוספנו כאן את הפרמטר $skipTzintuk
          public function processParallelAndDecide(string $audioData, bool $isStrict, bool $skipTzintuk): AnalysisResult
          {
              $tmpFile = tempnam(sys_get_temp_dir(), 'py_') . '.wav';
              file_put_contents($tmpFile, $audioData);
              $base64Audio = base64_encode($audioData);
      
              $mh = curl_multi_init();
      
              $chGemini = $this->createGeminiAudioRequest($base64Audio);
              curl_multi_add_handle($mh, $chGemini);
      
              $chPython = $this->createPythonRequest($tmpFile);
              curl_multi_add_handle($mh, $chPython);
      
              $startTime = microtime(true);
              $tzintukSent = false;
              $active = null;
      
              do {
                  curl_multi_exec($mh, $active);
                  curl_multi_select($mh, 0.5);
      
                  $elapsed = microtime(true) - $startTime;
                  
                  // 🌟 הצינתוק יישלח רק אם המשתמש לא חסם אותו ($skipTzintuk == false)
                  if (!$skipTzintuk && !$isStrict && $elapsed > 35.0 && !$tzintukSent) {
                      $this->tzManager->sendTzintuk($this->yemotClient);
                      $tzintukSent = true;
                  }
      
              } while ($active > 0);
      
              $geminiResponse = curl_multi_getcontent($chGemini);
              $pythonResponse = curl_multi_getcontent($chPython);
      
              curl_multi_remove_handle($mh, $chGemini);
              curl_multi_remove_handle($mh, $chPython);
              curl_multi_close($mh);
              @unlink($tmpFile);
      
              $geminiParsed = $this->parseGeminiResponse((string)$geminiResponse);
              $finalResult = null;
      
              if ($geminiParsed['decision'] !== Decision::UNKNOWN) {
                  $finalResult = new AnalysisResult(
                      $geminiParsed['decision'], 
                      $geminiParsed['transcription'], 
                      Engine::GEMINI_AUDIO,
                      $geminiParsed['reason_word']
                  );
              } else {
                  $finalResult = $this->handlePythonFallback((string)$pythonResponse);
              }
      
              // 🌟 גם פה נוודא ששולחים צינתוק בסיום רק אם הוא לא בוטל
              if (!$skipTzintuk && !$tzintukSent && $finalResult->decision === Decision::APPROVE) {
                  $this->tzManager->sendTzintuk($this->yemotClient);
              } 
      
              if ($finalResult->bannedWord !== '') {
                  $this->dictionary->addWord($finalResult->bannedWord);
              }
      
              return $finalResult;
          }
      
          private function handlePythonFallback(string $pythonResponse): AnalysisResult
          {
              $data = json_decode($pythonResponse, true);
              $transcription = trim($data['recognized_text'] ?? '');
      
              if ($transcription === '') {
                  return new AnalysisResult(Decision::UNKNOWN, 'כשל בתמלול', Engine::ERROR);
              }
      
              $bannedWords = $this->dictionary->getWords();
              foreach ($bannedWords as $word) {
                  if (str_contains($transcription, $word)) {
                      return new AnalysisResult(Decision::REJECT, $transcription, Engine::PYTHON_DICT, $word);
                  }
              }
      
              return $this->analyzeTextWithGemini($transcription);
          }
      
          private function analyzeTextWithGemini(string $text): AnalysisResult
          {
              $ch = curl_init(self::GEMINI_API . '?key=' . $this->geminiKey);
              if (!$ch) throw new RuntimeException("Failed to init cURL for Gemini Text.");
      
              $payload = ['contents' => [['parts' => [['text' => self::MODERATION_PROMPT . "\nText: " . $text]]]], 'generationConfig' => ['temperature' => 0.0, 'responseMimeType' => 'application/json']];
              
              curl_setopt_array($ch, [
                  CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload),
                  CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
                  CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10
              ]);
              
              $res = curl_exec($ch);
              curl_close($ch);
              
              $parsed = $this->parseGeminiResponse((string)$res);
              return new AnalysisResult($parsed['decision'] !== Decision::UNKNOWN ? $parsed['decision'] : Decision::APPROVE, $text, Engine::GEMINI_TEXT, $parsed['reason_word']);
          }
      
          private function createGeminiAudioRequest(string $base64Audio): CurlHandle
          {
              $payload = [
                  'contents' => [['parts' => [['inlineData' => ['mimeType' => 'audio/wav', 'data' => $base64Audio]], ['text' => self::MODERATION_PROMPT]]]],
                  'generationConfig' => ['temperature' => 0.0, 'responseMimeType' => 'application/json']
              ];
      
              $ch = curl_init(self::GEMINI_API . '?key=' . $this->geminiKey);
              if (!$ch) throw new RuntimeException("Failed to init cURL for Gemini Audio.");
      
              curl_setopt_array($ch, [
                  CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload),
                  CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
                  CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 45
              ]);
              return $ch;
          }
      
          private function createPythonRequest(string $filePath): CurlHandle
          {
              $ch = curl_init($this->pythonUrl . '/process_by_file');
              if (!$ch) throw new RuntimeException("Failed to init cURL for Python Audio.");
      
              $headers = $this->pythonKey !== '' ? ['Authorization: Bearer ' . $this->pythonKey] : [];
              
              curl_setopt_array($ch, [
                  CURLOPT_POST => true, CURLOPT_POSTFIELDS => ['file' => new CURLFile($filePath, 'audio/wav', 'rec.wav')],
                  CURLOPT_HTTPHEADER => $headers, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 60,
                  CURLOPT_SSL_VERIFYPEER => false
              ]);
              return $ch;
          }
      
          private function parseGeminiResponse(string $json): array
          {
              $data = json_decode($json, true);
              $text = $data['candidates'][0]['content']['parts'][0]['text'] ?? '{}';
              $result = json_decode($text, true) ?: [];
      
              $decStr = strtoupper(trim($result['decision'] ?? 'UNKNOWN'));
              $decision = match ($decStr) {
                  'APPROVE' => Decision::APPROVE,
                  'REJECT'  => Decision::REJECT,
                  default   => Decision::UNKNOWN,
              };
      
              return [
                  'decision'      => $decision,
                  'transcription' => trim($result['transcription'] ?? ''),
                  'reason_word'   => trim($result['reason_word'] ?? '')
              ];
          }
      }
      
      // ==========================================
      // 🚀 Main Execution
      // ==========================================
      
      $getString = fn(string $key): string => isset($_REQUEST[$key]) && is_string($_REQUEST[$key]) ? trim($_REQUEST[$key]) : '';
      
      $secret1 = $getString('secret1');
      $phone   = $getString('ApiPhone');
      $record  = $getString('RECORD');
      $nativ   = $getString('NATIV');
      $email   = $getString('email1');
      $m       = $getString('M');
      $h       = $getString('H');
      $adminPh = $getString('ApiRealPhone') ?: $phone;
      
      // 🌟 בדיקה אם התקבל פרמטר לביטול הצינתוק
      $noTzintukParam = $getString('NoTzintuk');
      $skipTzintuk = ($noTzintukParam === '1' || strtolower($noTzintukParam) === 'yes');
      
      $logger = new Logger(__DIR__);
      $expectedSecret = defined('SECRET1') ? SECRET1 : '';
      
      if ($secret1 !== $expectedSecret) {
          $logger->log("שגיאת גישה", "הסיסמה שהתקבלה מול המערכת אינה תואמת.");
          exit("Access Denied");
      }
      
      $yemotToken = defined('YEMOT_TOKEN') ? YEMOT_TOKEN : '';
      $yemotApi   = defined('YEMOT_API') ? YEMOT_API : 'https://www.call2all.co.il/ym/api/';
      $yemotClient = new YemotClient($yemotApi, $yemotToken);
      $tzManager  = new TzintukManager(__DIR__ . '/numbers1.json', $logger);
      
      if ($phone !== '' && $m !== '' && $h !== '') {
          $tzManager->updateHours($phone, $m, $h, $adminPh);
          SystemReleaser::release("OK");
          exit;
      }
      
      SystemReleaser::release("OK");
      
      try {
          if ($phone !== '' && $record !== '' && $nativ !== '') {
              $tzintukStatusStr = $skipTzintuk ? "מבוטל" : "פעיל";
              $logger->log("התחלת תהליך", "התקבלה הודעה לסינון ממספר: {$phone} | צינתוק להודעה זו: {$tzintukStatusStr}");
              
              $recordFolder = rtrim($record, '/');
              $nativFolder  = rtrim($nativ, '/');
              
              $logData = $yemotClient->call("RenderYMGRFile", ['wath' => "ivr2:{$recordFolder}/record_log.ymgr", 'convertType' => 'json', 'notLoadLang' => 1]);
              
              $lastFile = null;
              $searchPhone = $yemotClient->normalizePhone($phone);
              
              if (isset($logData['data']) && is_array($logData['data'])) {
                  foreach (array_reverse($logData['data']) as $row) {
                      $rowPhone = $yemotClient->normalizePhone($row['Phone'] ?? '');
                      
                      if ($rowPhone === $searchPhone) {
                          $rowDate = $row['Date'] ?? date('d/m/Y'); 
                          $rowTime = $row['Time'] ?? date('H:i:s');
                          
                          $fileDateTime = DateTimeImmutable::createFromFormat('d/m/Y H:i:s', "$rowDate $rowTime");
                          $now = new DateTimeImmutable();
                          
                          if ($fileDateTime && ($now->getTimestamp() - $fileDateTime->getTimestamp()) < 600) {
                              $lastFile = $row['FileNumber'] ?? null;
                          } 
                          break; 
                      }
                  }
              }
      
              if ($lastFile) {
                  $logger->log("איתור קובץ", "קובץ מספר {$lastFile} נמשך בהצלחה ומועבר ל-AI.");
                  
                  $fileYmPath = "{$nativFolder}/{$lastFile}.wav";
                  $audioData = $yemotClient->downloadAudio($fileYmPath);
      
                  $geminiKey = defined('GEMINI_KEY') ? GEMINI_KEY : '';
                  $pythonUrl = defined('PYTHON_URL') ? PYTHON_URL : '';
                  $pythonKey = defined('PYTHON_API_KEY') ? PYTHON_API_KEY : '';
                  
                  $strictNumbersFile = __DIR__ . '/strict_numbers.json';
                  if (!file_exists($strictNumbersFile)) {
                      file_put_contents($strictNumbersFile, json_encode(['0501234567'], JSON_PRETTY_PRINT));
                  }
                  $strictNumbers = json_decode(file_get_contents($strictNumbersFile) ?: '[]', true) ?: [];
                  $isStrictPhone = in_array($searchPhone, $strictNumbers, true);
                  
                  $dictManager = new DictionaryManager(__DIR__ . '/banned_words.json');
                  $orchestrator = new ModerationOrchestrator($geminiKey, $pythonUrl, $pythonKey, $dictManager, $tzManager, $yemotClient);
                  
                  // 🌟 שולחים את פרמטר ביטול הצינתוק לפונקציה
                  $result = $orchestrator->processParallelAndDecide($audioData, $isStrictPhone, $skipTzintuk);
      
                  if ($result->decision === Decision::REJECT) {
                      $yemotClient->call("FileAction", ['action' => 'delete', 'what' => "ivr2:{$fileYmPath}"]);
                      $yemotClient->call("FileAction", ['action' => 'delete', 'what' => "ivr2:{$nativFolder}/{$lastFile}.txt"]);
                      
                      $addedWordStr = $result->bannedWord !== '' ? $result->bannedWord : 'נפסל ע"י AI ללא מילה ספציפית';
                      $logger->log("הקלטה נמחקה", "מספר מקליט: {$phone} | מילה פסולה: '{$addedWordStr}' | תמלול מלא: {$result->transcription}");
      
                      if ($email !== '' && defined('MAIL_ENGINE') && file_exists(MAIL_ENGINE)) {
                          require_once MAIL_ENGINE;
                          $subject = "⚠️ מערכת סינון: הקלטה נמחקה ({$result->engine->value})";
                          $body = "<div dir='rtl'><h3>הקלטה נפסלה</h3><p>טלפון: " . htmlspecialchars($phone, ENT_QUOTES, 'UTF-8') . "</p><p>מילה שגרמה לפסילה: <b>" . htmlspecialchars($result->bannedWord, ENT_QUOTES, 'UTF-8') . "</b></p><p>תמלול מלא:<br>" . htmlspecialchars($result->transcription, ENT_QUOTES, 'UTF-8') . "</p></div>";
                          
                          $tmpMailFile = tempnam(sys_get_temp_dir(), 'mail_') . '.wav';
                          file_put_contents($tmpMailFile, $audioData);
                          if (function_exists('sendCustomMail')) {
                              sendCustomMail([$email], $subject, $body, 'רובוט סינון', $tmpMailFile, "Deleted_{$phone}.wav");
                          }
                          @unlink($tmpMailFile);
                      }
                  } elseif ($result->decision === Decision::APPROVE) {
                      $logger->log("הקלטה אושרה", "קובץ מספר {$lastFile} תומלל ואושר | מספר מקליט: {$phone}");
                  }
              } else {
                  $logger->log("שגיאת איתור", "לא נמצא קובץ תואם למספר בקובץ הלוג.");
              }
          } else {
              $logger->log("נתונים חסרים", "לא התקבלו כל הנתונים הנדרשים מהשרת.");
          }
      } catch (Throwable $e) {
          $logger->log("שגיאה קריטית", $e->getMessage());
      }
      
      

      פורסם בעזרה הדדית למשתמשים מתקדמים
      ש
      שלוחה-404
    • RE: בוט שעוקב אחרי הודעות

      @מערכות-טלפוניות יש לך שרת ?
      אני כתבתי קוד כזה ההודעה נשמרת אבל לא נשלח צינתוק שהרובוט מסיים לתמלל ולבדוק הוא שולח צינתוק
      מה שאתה עושה שבסיום ההקלטה לחיצה על 2 מעביר לשלוחה API בקוד מוגדר שכל פעם שמגיעה קריאה לכתובת להכינס ללוג ההקלטות לקחת את המספר קובץ האחרון של המספר שחייג להכינס לשלוחה שבה נשמרים להוריד לתמלל לכתוב פרומפט הנחיה מה לסנן ואם אושר לשלוח צינתוק אם לא לשלוח מייל ולמחוק את הקובץ

      פורסם בעזרה הדדית למשתמשים מתקדמים
      ש
      שלוחה-404
    • RE: שגיאה במודול API בשעות האחרונות

      @אז-נדברו יש לי כמה שלוחות לכמה שרתים שונים שעבדו עד היום חלק השרתים תקינים

      פורסם בפורום מפתחים API
      ש
      שלוחה-404
    • RE: שגיאה במודול API בשעות האחרונות

      @אז-נדברו שלחתי פניה לשירות לקוחות כל המודל API לא עובד לי האם יש מצב שהתקלה תתוקן היום ?

      פורסם בפורום מפתחים API
      ש
      שלוחה-404
    • RE: שגיאה במודול API בשעות האחרונות

      @אז-נדברו נכון לעכשיו כל שלוחות API במערכת שלי מחזירות אין מענה משרת API

      פורסם בפורום מפתחים API
      ש
      שלוחה-404
    • RE: באג כעת - האם זה כללי? לא שומעים קבצים בשלוחות השמעת קבצים

      @אז-נדברו אתמול גם לי בשרת YMTA לקח מלא זמן לשיחות להתחבר
      היום זה הסתדר

      פורסם בשאלות ועזרה הדדית
      ש
      שלוחה-404
    • RE: במקרה שנשלח צינתוק לרשימה ריקה השיחה מתנתקת

      @יענקי-פולק במשך שנה וחצי + היה לי כמה שלוחות שהפעילו צינתוק לרשימה ריקה וזה עבד (זה לא שלח צינתוק) אבל המערכת המשיכה לתפקד היום בלחיצה על צינתוק שהרשימה ריקה השיחה מנתקת ללא שמירת הקובץ

      פורסם בשאלות ועזרה הדדית
      ש
      שלוחה-404
    • RE: שליחת הודעה לכשרים בשיחה והשמעת ההודעה

      @קו-הרהיטים כמדומה ני שלהחזיר נקודה במחרוזת טקסט שובר את השרת

      פורסם בעזרה הדדית למשתמשים מתקדמים
      ש
      שלוחה-404
    • RE: חזרה לנקודת העצירה במקש API

      @מסובך-מאוד בעיקרון יש משהו מובנה לי זה לא עבד
      מקש API
      תדפדף קצת למעלה

      פורסם בשאלות ועזרה הדדית
      ש
      שלוחה-404
    • RE: מוזיקה בהמתנה לתגובת השרת במודל תור עם טעינת מספרים לחיוג בAPI

      @שיבקשו-שלשתם הגיונית לא אמור להיות מוזיקה בהמתנה לטעינת הנציגים של התור לכאורה המוזיקה של ההמתנה למענה אמורה להתחיל גם אם התור עוד לא נטען

      @שיבקשו-שלשתם כתב:

      אבל גם מה שהבאת וגם מה שאני שמתי מלכתחילה- בשניהם זה לא עובד

      מניין לך שזה לא עובד אולי השרת פשוט מגיב מהר ואין צורך במוזיקה ?

      פורסם בפורום מפתחים API
      ש
      שלוחה-404
    • RE: השמעת הודעת קמפיין בתפריט

      @אA בסוף עשיתי כבר עם API

      פורסם בעזרה הדדית למשתמשים מתקדמים
      ש
      שלוחה-404
    • RE: השמעת הודעת קמפיין בתפריט

      למישהו יש פתרון אחר קל ללא API להשמעת הודעה פעם ביום שהאיפוס יהיה בשעה 13:30 אשמח לדעת

      פורסם בעזרה הדדית למשתמשים מתקדמים
      ש
      שלוחה-404
    • RE: השמעת הודעת קמפיין בתפריט

      @אז-נדברו האם יש חדש ?

      פורסם בעזרה הדדית למשתמשים מתקדמים
      ש
      שלוחה-404
    • RE: שליחת פרטי הקובץ

      @מסובך-מאוד תמשוך את הקובץ מטא זה אותו נתיב אם סיומת טקסט ושמה יש לך את כל המידע

      פורסם בפורום מפתחים API
      ש
      שלוחה-404
    • RE: שליחת פרטי הקובץ

      @מסובך-מאוד לא שולח ולא ידוע לי על דרך להגדיר שישלח פשוט אתה אומר לשרת להחליף סיומת wav לtxt

      פורסם בפורום מפתחים API
      ש
      שלוחה-404
    • RE: שרת ymx

      @מסובך-מאוד בפאנל הניהול האתר הרגיל למטה בתוך [ymta] ymx הוא הכי חדש אני לא יודע את שאר סדר הדורות

      פורסם בעזרה הדדית למשתמשים מתקדמים
      ש
      שלוחה-404
    • RE: במקרה שנשלח צינתוק לרשימה ריקה השיחה מתנתקת

      @מסובך-מאוד פחות משאבי שרת אולי לא יודע

      פורסם בשאלות ועזרה הדדית
      ש
      שלוחה-404
    • RE: במקרה שנשלח צינתוק לרשימה ריקה השיחה מתנתקת

      @המומחה ימות עדכנו הרבה דברים בשרתים אחד העדכונים זה במקרה שנשלח צינתוק לרשימה ריקה השיחה מתנתקת חדש מלני שבוע וחצי בערך

      פורסם בשאלות ועזרה הדדית
      ש
      שלוחה-404
    • RE: מעבר לשלוחה בהקשת מקש בהודעת קמפיין

      @יהודה-לוי לא הבנתי דרך האתר להעביר מאזין מחובר ?

      פורסם בעזרה הדדית למשתמשים מתקדמים
      ש
      שלוחה-404
    • RE: קמפיין שיגור שיחה וכניסה למערכת

      @מערכת-תוכן יש גם אם API אבל עלות יחידות על כל דקה בשירות לקוחות זה מוגבל ל2 יחידות ללקוח

      פורסם בשאלות ועזרה הדדית
      ש
      שלוחה-404