feat: Integrate OpenAI API for email task parsing and update configuration

This commit is contained in:
2026-02-08 22:48:57 +01:00
parent 0c5a133aa7
commit 63268e35dc
3 changed files with 204 additions and 15 deletions

View File

@@ -3,34 +3,42 @@
"public_html": {
"ajax.php": {
"type": "-",
"size": 1208,
"size": 1340,
"lmtime": 0,
"modified": false
"modified": true
},
"api.php": {
"type": "-",
"size": 2446,
"size": 3758,
"lmtime": 0,
"modified": false
"modified": true
},
"autoload": {},
"ceidg.php": {
"type": "-",
"size": 3862,
"size": 3950,
"lmtime": 0,
"modified": false
"modified": true
},
".claude": {
"settings.local.json": {
"type": "-",
"size": 72,
"lmtime": 1770583517578,
"modified": false
}
},
"config.php": {
"type": "-",
"size": 355,
"lmtime": 0,
"size": 729,
"lmtime": 1770583610342,
"modified": false
},
"cron.php": {
"type": "-",
"size": 1777,
"size": 2093,
"lmtime": 0,
"modified": false
"modified": true
},
".htaccess": {
"type": "-",
@@ -40,12 +48,18 @@
},
"index.php": {
"type": "-",
"size": 2372,
"size": 2464,
"lmtime": 0,
"modified": false
"modified": true
},
"layout": {},
"libraries": {},
"REFACTORING_PLAN.md": {
"type": "-",
"size": 3576,
"lmtime": 0,
"modified": false
},
"robots.txt": {
"type": "-",
"size": 25,
@@ -53,7 +67,59 @@
"modified": false
},
"temp": {},
"templates": {},
"templates": {
"tasks": {
"filtr_save_form.php": {
"type": "-",
"size": 775,
"lmtime": 0,
"modified": false
},
"main_view_by_ajax.php": {
"type": "-",
"size": 284,
"lmtime": 0,
"modified": false
},
"main_view.php": {
"type": "-",
"size": 42341,
"lmtime": 1770583657535,
"modified": false
},
"task_edit.php": {
"type": "-",
"size": 10202,
"lmtime": 0,
"modified": false
},
"task_popup.php": {
"type": "-",
"size": 11071,
"lmtime": 0,
"modified": false
},
"task_single.php": {
"type": "-",
"size": 2893,
"lmtime": 0,
"modified": false
},
"work-time.php": {
"type": "-",
"size": 12396,
"lmtime": 0,
"modified": false
}
}
},
"tests": {},
"tmp_debug_mail_import.php": {
"type": "-",
"size": 1238,
"lmtime": 0,
"modified": false
},
"upload": {}
}
},

View File

@@ -88,8 +88,34 @@ class MailToTaskImporter
try
{
$content = $this -> extractMessageContent( $imap, $message_no );
$task_name = trim( $subject ) !== '' ? trim( $subject ) : '(bez tematu)';
$task_text = $this -> prepareImportedTaskText( $content['text'] );
// Sprawdź czy użyć AI do parsowania
global $settings;
$use_ai = isset( $settings['openai_parse_emails'] ) && $settings['openai_parse_emails'] === true;
$api_key = isset( $settings['openai_api_key'] ) ? trim( (string)$settings['openai_api_key'] ) : '';
if ( $use_ai && $api_key !== '' )
{
$model = isset( $settings['openai_model'] ) ? trim( (string)$settings['openai_model'] ) : 'gpt-3.5-turbo';
$ai_result = $this -> parseWithAI( $api_key, $model, $subject, $content['text'] );
if ( $ai_result !== null )
{
$task_name = $ai_result['task_name'];
$task_text = $ai_result['task_text'];
}
else
{
// Fallback do normalnego parsowania jeśli AI nie zadziała
$task_name = trim( $subject ) !== '' ? trim( $subject ) : '(bez tematu)';
$task_text = $this -> prepareImportedTaskText( $content['text'] );
}
}
else
{
// Normalne parsowanie
$task_name = trim( $subject ) !== '' ? trim( $subject ) : '(bez tematu)';
$task_text = $this -> prepareImportedTaskText( $content['text'] );
}
$client_id = $this -> resolveClientIdBySenderDomain( $sender );
$task_id = \factory\Tasks::task_save(
@@ -648,4 +674,96 @@ class MailToTaskImporter
$value = trim( $value, '<>' );
return strtolower( $value );
}
private function parseWithAI( $api_key, $model, $subject, $raw_content )
{
$subject = trim( (string)$subject );
$raw_content = trim( (string)$raw_content );
$model = trim( (string)$model );
if ( $model === '' )
$model = 'gpt-3.5-turbo';
// Przygotuj treść do analizy (usuń HTML jesli jest)
if ( preg_match( '/<\s*[a-z][^>]*>/i', $raw_content ) )
{
$raw_content = $this -> htmlToText( $raw_content );
$raw_content = $this -> cleanBodyText( $raw_content );
}
$prompt = "Jesteś asystentem do przetwarzania emaili na zadania w systemie CRM. " .
"Na podstawie poniższego tematu i treści emaila, wygeneruj:\n" .
"1. Zwięzły, konkretny temat zadania (max 100 znaków)\n" .
"2. Czytelny opis zadania zawierający najważniejsze informacje\n\n" .
"Temat emaila: " . $subject . "\n\n" .
"Treść emaila:\n" . mb_substr( $raw_content, 0, 2000 ) . "\n\n" .
"Odpowiedz TYLKO w formacie JSON bez żadnych dodatkowych wyjaśnień:\n" .
'{"task_name": "temat zadania", "task_text": "opis zadania"}';
$payload = [
'model' => $model,
'messages' => [
[
'role' => 'system',
'content' => 'Jesteś asystentem do przetwarzania emaili. Odpowiadasz TYLKO w formacie JSON.'
],
[
'role' => 'user',
'content' => $prompt
]
],
'temperature' => 0.3,
'max_tokens' => 500
];
$ch = curl_init( 'https://api.openai.com/v1/chat/completions' );
curl_setopt_array( $ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode( $payload ),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $api_key
],
CURLOPT_TIMEOUT => 30
] );
$response = curl_exec( $ch );
$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
curl_close( $ch );
if ( $http_code !== 200 || !$response )
return null;
$data = json_decode( $response, true );
if ( !isset( $data['choices'][0]['message']['content'] ) )
return null;
$content = trim( $data['choices'][0]['message']['content'] );
// Usuń markdown code block jeśli jest
$content = preg_replace( '/```json\s*|\s*```/', '', $content );
$content = trim( $content );
$parsed = json_decode( $content, true );
if ( !is_array( $parsed ) || !isset( $parsed['task_name'] ) || !isset( $parsed['task_text'] ) )
return null;
$task_name = trim( (string)$parsed['task_name'] );
$task_text = trim( (string)$parsed['task_text'] );
if ( $task_name === '' )
$task_name = '(bez tematu)';
if ( $task_text === '' )
$task_text = '(brak treści)';
// Formatuj treść zadania z nl2br
$task_text = nl2br( $task_text );
return [
'task_name' => $task_name,
'task_text' => $task_text
];
}
}

View File

@@ -18,3 +18,8 @@ $imap_tasks['password'] = 'ProjectPro2025!';
// Auto-start timer when opening task popup (true/false)
$settings['tasks_auto_start_timer'] = false;
// OpenAI ChatGPT API configuration for email task parsing
$settings['openai_api_key'] = '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'; // Wklej tutaj swój klucz API OpenAI
$settings['openai_parse_emails'] = true; // true = użyj AI do parsowania emaili, false = normalne parsowanie
$settings['openai_model'] = 'gpt-3.5-turbo'; // Model: gpt-3.5-turbo (najtańszy), gpt-4o-mini, gpt-4o, itp.