diff --git a/src/App/Service/KoinService.php b/src/App/Service/KoinService.php index 4bb7eff..06c5b0d 100644 --- a/src/App/Service/KoinService.php +++ b/src/App/Service/KoinService.php @@ -12,263 +12,352 @@ use Zend\EventManager\Event; class KoinService { - const BASE_URI = 'https://www.koin.hu'; - const DEFAULT_EXPENSE = 'Egyéb kiadás'; + const BASE_URI = 'https://www.koin.hu'; + const DEFAULT_EXPENSE = 'Egyéb kiadás'; - /** - * 1 - date - * 2 - time - * 3 - amount contains dot as thousand separator - * 4 - currency - * 5 - pos info - */ - const OTP_SMS_PATTERN = '#([0-9]{6}) ([0-9]{1,2}:[0-9]{1,2}) K[áà]rty[áà]s v[áà]s[áà]rl[áà]s/z[áà]rol[áà]s: -([0-9.]+) ([A-Z]{2,3}); (.*?); K[áà]rtyasz[áà]m: ...[0-9]{4}; Egyenleg: \+[0-9.]+ HUF - OTPdirekt#msiu'; + /** + * 1 - date + * 2 - time + * 3 - amount contains dot as thousand separator + * 4 - currency + * 5 - pos info + */ + const OTP_SMS_PATTERN = '#([0-9]{6}) ([0-9]{1,2}:[0-9]{1,2}) K[áà]rty[áà]s v[áà]s[áà]rl[áà]s/z[áà]rol[áà]s: -([0-9.]+) ([A-Z]{2,3}); (.*?); K[áà]rtyasz[áà]m: ...[0-9]{4}; Egyenleg: \+[0-9.]+ HUF - OTPdirekt#msiu'; - /** - * @var array - */ - private $config; + /** + * @var array + */ + private $config; - /** - * @var Client - */ - private $httpClient; + /** + * @var Client + */ + private $httpClient; - /** - * @var string - */ - private $csrfParam; + /** + * @var string + */ + private $csrfParam; - /** - * @var string - */ - private $csrfToken; + /** + * @var string + */ + private $csrfToken; - /** - * @var array - */ - private $expenseCategories = []; + /** + * @var array + */ + private $expenseCategories = []; - /** - * @var array - */ - private $incomeCategories = []; + /** + * @var array + */ + private $incomeCategories = []; - public function __construct(Client $httpClient, array $config) - { - $this->config = $config; - $this->httpClient = $httpClient; - } - - public function onReceiveSmsListener(Event $event) - { - $this->onReceiveSms($event->getParam('sms')); - } - - /** - * @param Sms $sms - * @return int - */ - public function onReceiveSms(Sms $sms) - { - if (1 === ($matchStatus = preg_match(self::OTP_SMS_PATTERN, $sms->getText(), $otpMatches))) { - $datePart = implode("-", sscanf($otpMatches[1], '%2c%2c%2c')); - - $this->saveTransaction( - intval(str_replace(".","", $otpMatches[3])), - $otpMatches[4], - "20${datePart}", - $this->getExpenseCategory($otpMatches[5]), - $this->getExpenseTags($otpMatches[5]) - ); - } - return $matchStatus; - } - - /** - * @param string $posInfo - * @return string - */ - private function getExpenseCategory(string $posInfo): string - { - if(false !== strpos($posInfo, "TESCO")) { - return 'Bevásárlás'; + public function __construct(Client $httpClient, array $config) + { + $this->config = $config; + $this->httpClient = $httpClient; } - if(false !== strpos($posInfo, "MCDHU")) { - return 'Étel'; + public function onReceiveSmsListener(Event $event) + { + $this->onReceiveSms($event->getParam('sms')); } - if(false !== strpos($posInfo, "GYOGYSZER")) { - return 'Egészség'; + /** + * @param Sms $sms + * @return int + */ + public function onReceiveSms(Sms $sms) + { + if (1 === ($matchStatus = preg_match(self::OTP_SMS_PATTERN, $sms->getText(), $otpMatches))) { + $datePart = implode("-", sscanf($otpMatches[1], '%2c%2c%2c')); + + $this->saveTransaction( + intval(str_replace(".", "", $otpMatches[3])), + $otpMatches[4], + "20${datePart}", + $this->getExpenseCategory($otpMatches[5]), + $this->getExpenseTags($otpMatches[5]) + ); + } + return $matchStatus; } - return self::DEFAULT_EXPENSE; - } + /** + * @param string $posInfo + * @return string + */ + private function getExpenseCategory(string $posInfo): string + { + if (false !== strpos($posInfo, "STOCZEK ETTEREM")) { + return 'Étel'; + } - /** - * @param string $posInfo - * @return array - */ - private function getExpenseTags(string $posInfo): array - { - $tags = []; + if (false !== strpos($posInfo, "BKK AUTOMATA")) { + return 'Közlekedés'; + } - if(false !== strpos($posInfo, "TESCO")) { - $tags[] = 'Tesco'; - } - if(false !== strpos($posInfo, "MCDHU")) { - $tags[] = 'Junk food'; - } - if(false !== strpos($posInfo, "GYOGYSZER")) { - $tags[] = 'Gyógyszer'; + if (false !== strpos($posInfo, "TESCO")) { + return 'Bevásárlás'; + } + + if (false !== strpos($posInfo, "SPAR MAGYARORSZAG")) { + return 'Étel'; + } + + if (false !== strpos($posInfo, "SZLOVàK ABC")) { + return 'Bevásárlás'; + } + + if (false !== strpos($posInfo, "MCDHU")) { + return 'Étel'; + } + + if (false !== strpos($posInfo, "OSMANI DÖNER KEBAB")) { + return 'Étel'; + } + + if (false !== strpos($posInfo, "Princess Bakery")) { + return 'Étel'; + } + + if (false !== strpos($posInfo, "PIROG-DA")) { + return 'Étel'; + } + + if (false !== strpos($posInfo, "GYOGYSZER")) { + return 'Egészség'; + } + + if (false !== strpos($posInfo, "GOOGLE *Google Music")) { + return 'Szórakozás'; + } + + if (false !== strpos($posInfo, "Aqua Electromax")) { + return 'Szórakozás'; + } + + + return self::DEFAULT_EXPENSE; } - $tags[] = 'Auto'; - return $tags; - } + /** + * @param string $posInfo + * @return array + */ + private function getExpenseTags(string $posInfo): array + { + $tags = []; - /** - * @param int $amount - * @param string $currency - * @param string $date - * @param string $category - * @param array $tags - * @return int - */ - public function saveTransaction(int $amount, string $currency = 'HUF', string $date, string $category, array $tags): int - { - $pageData = $this->login($this->config['koin.user'], $this->config['koin.pass']); + if (false !== strpos($posInfo, "SCIENCE PARK ÉTTEREM")) { + $tags[] = 'Science Park'; + $tags[] = 'Menza'; + } - $this->loadFormData($pageData->getBody()); - return $this->postData( - $amount, - $currency, - $date, - $this->getCategoryId($category), - $this->getTagsString($tags) - ); - } + if (false !== strpos($posInfo, "STOCZEK ETTEREM")) { + $tags[] = "Stoczek"; + $tags[] = "Menza"; + } - /** - * @param string $user - * @param string $pass - * @return \Psr\Http\Message\ResponseInterface - */ - private function login(string $user, string $pass): ResponseInterface - { - $httpResponse = $this->httpClient->get(self::BASE_URI); + if (false !== strpos($posInfo, "BKK AUTOMATA")) { + $tags[] = "Bérlet"; + $tags[] = "BKV"; + } - $body = $httpResponse->getBody(); + if (false !== strpos($posInfo, "SPAR MAGYARORSZAG")) { + $tags[] = 'Spar'; + } - $this->getCsrfToken($body); + if (false !== strpos($posInfo, "TESCO")) { + $tags[] = 'Tesco'; + } - $httpResponse = $this->httpClient - ->post(self::BASE_URI . "/site/login", [ - 'form_params' => [ - $this->csrfParam => $this->csrfToken, - 'LoginForm[email]' => $user, - 'LoginForm[pass]' => $pass, - 'LoginForm[rememberMe]' => 0, - ], - ]); - return $httpResponse; - } + if (false !== strpos($posInfo, "SZLOVàK ABC")) { + $tags[] = 'Szlovák ABC'; + } - /** - * @param $htmlData - */ - private function loadFormData($htmlData) - { - $documentXpath = $this->getCsrfToken($htmlData); + if (false !== strpos($posInfo, "MCDHU")) { + $tags[] = 'Junk food'; + } - /** @var \DOMNodeList $expenseOptionElements */ - $expenseOptionElements = $documentXpath->query('//select[@id="transactioncreate-category_id"]/optgroup[@label="Kiadás"]/option'); - /** @var \DOMNodeList $incomeOptionElements */ - $incomeOptionElements = $documentXpath->query('//select[@id="transactioncreate-category_id"]/optgroup[@label="Bevétel"]/option'); + if (false !== strpos($posInfo, "OSMANI DÖNER KEBAB")) { + $tags[] = 'Kebab'; + $tags[] = 'Junk food'; + } - /** @var \DOMElement $element */ - foreach ($expenseOptionElements as $element) { - $this->expenseCategories[$element->nodeValue] = $element->getAttribute("value"); + if (false !== strpos($posInfo, "Princess Bakery")) { + $tags[] = 'Pricess Bakery'; + $tags[] = 'Junk food'; + } + + if (false !== strpos($posInfo, "PIROG-DA")) { + $tags[] = 'Pirog-da'; + $tags[] = 'Junk food'; + } + + if (false !== strpos($posInfo, "GYOGYSZER")) { + $tags[] = 'Gyógyszer'; + } + + if (false !== strpos($posInfo, "GOOGLE *Google Music")) { + $tags[] = 'Google play'; + } + + if (false !== strpos($posInfo, "Aqua Electromax")) { + $tags[] = 'Aqua'; + } + + $tags[] = 'Auto'; + return $tags; } - /** @var \DOMElement $element */ - foreach ($incomeOptionElements as $element) { - $this->incomeCategories[$element->nodeValue] = $element->getAttribute("value"); + /** + * @param int $amount + * @param string $currency + * @param string $date + * @param string $category + * @param array $tags + * @return int + */ + public function saveTransaction(int $amount, + string $currency = 'HUF', + string $date, + string $category, + array $tags): int + { + $pageData = $this->login($this->config['koin.user'], $this->config['koin.pass']); + + $this->loadFormData($pageData->getBody()); + return $this->postData( + $amount, + $currency, + $date, + $this->getCategoryId($category), + $this->getTagsString($tags) + ); } - } - /** - * Parse csrf from html - * - * @param $html - * @return \DOMXPath - */ - private function getCsrfToken($html): \DOMXPath - { - $xmlErrorHandling = libxml_use_internal_errors(TRUE); - $domDocument = new \DOMDocument(); - $domDocument->loadHTML($html); - libxml_clear_errors(); - libxml_use_internal_errors($xmlErrorHandling); + /** + * @param string $user + * @param string $pass + * @return \Psr\Http\Message\ResponseInterface + */ + private function login(string $user, string $pass): ResponseInterface + { + $httpResponse = $this->httpClient->get(self::BASE_URI); - $documentXpath = new \DOMXPath($domDocument); - /** @var \DOMElement $paramElement */ - $paramElement = $documentXpath->query('//meta[@name="csrf-param"]')->item(0); - /** @var \DOMElement $tokenElement */ - $tokenElement = $documentXpath->query('//meta[@name="csrf-token"]')->item(0); + $body = $httpResponse->getBody(); - $this->csrfParam = $paramElement->getAttribute("content"); - $this->csrfToken = $tokenElement->getAttribute("content"); + $this->getCsrfToken($body); - return $documentXpath; - } - - /** - * @param int $amount - * @param string $currency - * @param string $date - * @param string $category - * @param string $tags - * @return int - */ - private function postData(int $amount, string $currency = 'HUF', string $date, string $category, string $tags): int - { - $saveResponse = $this->httpClient - ->post(self::BASE_URI . "/main/save-transaction", [ - 'form_params' => [ - $this->csrfParam => $this->csrfToken, - 'TransactionCreate[category_id]' => $category, - 'TransactionCreate[value]' => $amount, - 'TransactionCreate[currency]' => $currency, - 'TransactionCreate[imgKey]' => "", - 'TransactionCreate[tagData]' => $tags, - 'TransactionCreate[date]' => $date, - ], - ]); - - return $saveResponse->getStatusCode(); - } - - /** - * @param array $tags - * @return string - */ - private function getTagsString(array $tags): string - { - return implode(';', $tags); - } - - /** - * @param string $category - * @return string - */ - private function getCategoryId(string $category): string - { - if(in_array($category, array_keys($this->expenseCategories))) { - return $this->expenseCategories[$category]; + $httpResponse = $this->httpClient + ->post(self::BASE_URI . "/site/login", [ + 'form_params' => [ + $this->csrfParam => $this->csrfToken, + 'LoginForm[email]' => $user, + 'LoginForm[pass]' => $pass, + 'LoginForm[rememberMe]' => 0, + ], + ]); + return $httpResponse; + } + + /** + * @param $htmlData + */ + private function loadFormData($htmlData) + { + $documentXpath = $this->getCsrfToken($htmlData); + + /** @var \DOMNodeList $expenseOptionElements */ + $expenseOptionElements = $documentXpath->query('//select[@id="transactioncreate-category_id"]/optgroup[@label="Kiadás"]/option'); + /** @var \DOMNodeList $incomeOptionElements */ + $incomeOptionElements = $documentXpath->query('//select[@id="transactioncreate-category_id"]/optgroup[@label="Bevétel"]/option'); + + /** @var \DOMElement $element */ + foreach ($expenseOptionElements as $element) { + $this->expenseCategories[$element->nodeValue] = $element->getAttribute("value"); + } + + /** @var \DOMElement $element */ + foreach ($incomeOptionElements as $element) { + $this->incomeCategories[$element->nodeValue] = $element->getAttribute("value"); + } + } + + /** + * Parse csrf from html + * + * @param $html + * @return \DOMXPath + */ + private function getCsrfToken($html): \DOMXPath + { + $xmlErrorHandling = libxml_use_internal_errors(TRUE); + $domDocument = new \DOMDocument(); + $domDocument->loadHTML($html); + libxml_clear_errors(); + libxml_use_internal_errors($xmlErrorHandling); + + $documentXpath = new \DOMXPath($domDocument); + /** @var \DOMElement $paramElement */ + $paramElement = $documentXpath->query('//meta[@name="csrf-param"]')->item(0); + /** @var \DOMElement $tokenElement */ + $tokenElement = $documentXpath->query('//meta[@name="csrf-token"]')->item(0); + + $this->csrfParam = $paramElement->getAttribute("content"); + $this->csrfToken = $tokenElement->getAttribute("content"); + + return $documentXpath; + } + + /** + * @param int $amount + * @param string $currency + * @param string $date + * @param string $category + * @param string $tags + * @return int + */ + private function postData(int $amount, string $currency = 'HUF', string $date, string $category, string $tags): int + { + $saveResponse = $this->httpClient + ->post(self::BASE_URI . "/main/save-transaction", [ + 'form_params' => [ + $this->csrfParam => $this->csrfToken, + 'TransactionCreate[category_id]' => $category, + 'TransactionCreate[value]' => $amount, + 'TransactionCreate[currency]' => $currency, + 'TransactionCreate[imgKey]' => "", + 'TransactionCreate[tagData]' => $tags, + 'TransactionCreate[date]' => $date, + ], + ]); + + return $saveResponse->getStatusCode(); + } + + /** + * @param array $tags + * @return string + */ + private function getTagsString(array $tags): string + { + return implode(';', $tags); + } + + /** + * @param string $category + * @return string + */ + private function getCategoryId(string $category): string + { + if (in_array($category, array_keys($this->expenseCategories))) { + return $this->expenseCategories[$category]; + } + return $this->expenseCategories[self::DEFAULT_EXPENSE]; } - return $this->expenseCategories[self::DEFAULT_EXPENSE]; - } }