diff --git a/.gitignore b/.gitignore index 6310a3e..fd28551 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ index.php vendor/ log-* +logs +config.php \ No newline at end of file diff --git a/.nova/Configuration.json b/.nova/Configuration.json index bc4376e..cbf8704 100644 --- a/.nova/Configuration.json +++ b/.nova/Configuration.json @@ -1,6 +1,6 @@ { "com.thorlaksson.phpcs.runOnChange" : "onSave", - "com.thorlaksson.phpcs.standard" : "\/Volumes\/Alyx\/System\/Volumes\/Update\/mnt1\/Users\/max\/Dev\/Pnut\/APnutI\/phpcs.xml", + "com.thorlaksson.phpcs.standard" : "phpcs.xml", "editor.default_syntax" : "php", "php.validate" : "onSave", "workspace.color" : 1, diff --git a/src/APnutI.php b/src/APnutI.php index 9372223..c36b7c8 100644 --- a/src/APnutI.php +++ b/src/APnutI.php @@ -12,6 +12,7 @@ use APnutI\Exceptions\HttpPnutException; use APnutI\Exceptions\HttpPnutRedirectException; use APnutI\Exceptions\NotSupportedPollException; use APnutI\Exceptions\HttpPnutForbiddenException; +use APnutI\Exceptions\PollAccessRestrictedException; use APnutI\Meta; use Monolog\Logger; use Monolog\Handler\RotatingFileHandler; @@ -471,17 +472,52 @@ class APnutI return $polls; } - public function getPoll(int $poll_id): Poll + private function getPollFromResponse(array $res): Poll { try { - $res = $this->get('/polls/' . $poll_id); return new Poll($res, $this); } catch (NotSupportedPollException $e) { $this->logger->error('Poll not supported: '.json_encode($res)); throw $e; } catch (HttpPnutForbiddenException $fe) { $this->logger->error('Poll token required and not provided!'); - throw $fe; + throw new PollAccessRestrictedException(); + } catch (NotAuthorizedException $nauth) { + $this->logger->error('Not authorized when fetching poll'); + throw new PollAccessRestrictedException(); + } + } + + public function getPollFromToken(int $poll_id, ?string $poll_token = null): Poll + { + $poll_token_query = empty($poll_token) ? '' : '?poll_token=' . $poll_token; + $res = $this->get('/polls/' . $poll_id . $poll_token_query); + return $this->getPollFromResponse($res); + } + + public function getPoll(int $poll_id, ?string $poll_token = null): Poll + { + if (empty($poll_token)) { + return $this->getPollFromToken($poll_id, $poll_token); + } + + $this->logger->debug('Poll token provided'); + $re = '/((http(s)?:\/\/)?((posts)|(beta))\.pnut\.io\/(@.*\/)?)?(?(1)|^)(?\d+)/'; + preg_match($re, $poll_token, $matches); + if (!empty($matches['postid'])) { + $this->logger->debug('Poll token is post ' . $matches['postid']); + $post_id = (int)$matches['postid']; + $args = [ + 'include_raw' => true, + 'include_counts' => false, + 'include_html' => false, + 'include_post_raw' => true + ]; + $res = $this->get('/posts/' . $post_id, $args); + return $this->getPollFromResponse($res); + } else { + $this->logger->debug('Poll token seems to be an actual poll token'); + return $this->getPollFromToken($poll_id, $poll_token); } } diff --git a/src/Entities/Poll.php b/src/Entities/Poll.php index 64712ca..d23b19d 100644 --- a/src/Entities/Poll.php +++ b/src/Entities/Poll.php @@ -36,8 +36,8 @@ class Poll { $this->api = $api; $this->options = []; - $this->type = $data['type']; - if ($data['type'] === Poll::$notice_type) { + $type = ''; + if (array_key_exists('type', $data) && $data['type'] === Poll::$notice_type) { $val = $data['value']; $this->closed_at = new \DateTime($val['closed_at']); foreach ($val['options'] as $option) { @@ -46,18 +46,29 @@ class Poll $this->id = (int)$val['poll_id']; $this->token = $val['poll_token']; $this->prompt = $val['prompt']; - } elseif (in_array($data['type'], Poll::$poll_types)) { + } elseif (array_key_exists('type', $data) &&in_array($data['type'], Poll::$poll_types)) { $this->parsePoll($data); - } elseif (strpos($data['type'], '.poll') !== false) { + } elseif (array_key_exists('type', $data) &&strpos($data['type'], '.poll') !== false) { // Try parsing unknown types if they *might* be a poll try { $this->parsePoll($data); } catch (\Exception $e) { throw new NotSupportedPollException($data['type']); } + } elseif (array_key_exists('raw', $data) && #Polls included in posts + array_key_exists(Poll::$notice_type, $data['raw']) && + count($data['raw'][Poll::$notice_type]) > 0 + ) { + $poll_data = $data['raw'][Poll::$notice_type][0]; + if (!empty($data['source'])) { #Source is attached to post, not to poll raw + $poll_data['source'] = $data['source']; + } + $type = Poll::$notice_type; + $this->parsePoll($poll_data); } else { throw new NotSupportedPollException($data['type']); } + $this->type = empty($type) ? $data['type'] : $type; } private function parsePoll(array $data) @@ -65,8 +76,8 @@ class Poll $this->created_at = new \DateTime($data['created_at']); $this->closed_at = new \DateTime($data['closed_at']); $this->id = (int)$data['id']; - $this->is_anonymous = (bool)$data['is_anonymous']; - $this->is_public = (bool)$data['is_public']; + $this->is_anonymous = array_key_exists('is_anonymous', $data) ? (bool)$data['is_anonymous'] : false; + $this->is_public = array_key_exists('is_public', $data) ? (bool)$data['is_public'] : false; foreach ($data['options'] as $option) { $this->options[] = new PollOption($option); } diff --git a/src/Exceptions/PollAccessRestrictedException.php b/src/Exceptions/PollAccessRestrictedException.php new file mode 100644 index 0000000..9aebac5 --- /dev/null +++ b/src/Exceptions/PollAccessRestrictedException.php @@ -0,0 +1,7 @@ +