public function create() { $filter = []; if ($this->current_user->is_mod_or_higher() and $this->params()->user_id == "all") { } elseif ($this->current_user->is_mod_or_higher() and $this->params()->user_id) { $filter['user_id'] = $this->params()->user_id; } else { $filter['user_id'] = $this->current_user->id; } if ($this->params()->url) { $this->source = $this->params()->url; // $text = ""; $text = Danbooru::http_get_streaming($this->source); $this->urls = ExtractUrls::extract_image_urls($this->source, $text); } }
public function download_source() { if (!preg_match('/^https?:\\/\\//', $this->source) || $this->file_ext || $this->received_file) { return; } try { $file = Danbooru::http_get_streaming($this->source); file_put_contents($this->tempfile_image_path(), $file); unset($file); $this->got_file(); } catch (Exception $e) { $this->delete_tempfile(); $this->errors()->add('source', "couldn't be opened: " . $e->getMessage()); return false; } }
public function download_source() { if (!preg_match('/^https?:\\/\\//', $this->source) || $this->file_ext || $this->tempfile_path) { return; } try { $file = Danbooru::http_get_streaming($this->source); if ($file) { file_put_contents($this->tempfile_path(), $file); # This flag will cause Post\ImageStore\Base\move_file() to rename() the file # instead of move_uploaded_file(). $this->is_import = true; } if (preg_match('/^http/', $this->source) && !preg_match('/pixiv\\.net/', $this->source)) { # $this->source = "Image board"; $this->source = ""; } return true; } catch (Danbooru\Exception\RuntimeException $e) { $this->delete_tempfile(); $this->errors()->add('source', "couldn't be opened: " . $e->getMessage()); return false; } }
function reduce_and_crop($image_width, $image_height, $params) { $cropped_image_width = $image_width * ($params['right'] - $params['left']); $cropped_image_height = $image_height * ($params['bottom'] - $params['top']); $size = Danbooru::reduce_to(array('width' => $cropped_image_width, 'height' => $cropped_image_height), array('width' => CONFIG::avatar_max_width, 'height' => CONFIG::avatar_max_height), 1, true); $size['crop_top'] = $image_height * $params['top']; $size['crop_bottom'] = $image_height * $params['bottom']; $size['crop_left'] = $image_width * $params['left']; $size['crop_right'] = $image_width * $params['right']; return $size; }
public function similar() { $params = array_merge(['file' => null, 'url' => null, 'id' => $this->params()->id, 'search_id' => null, 'services' => null, 'threshold' => null, 'forcegray' => null, 'initial' => null, 'width' => null, 'height' => null], $this->params()->toArray()); if (!empty($params['data_search']) && !current_user()->is_mod_or_higher()) { unset($params['data_search']); } if (!SimilarImages::valid_saved_search($params['search_id'])) { $params['search_id'] = null; } if (!empty($params['width'])) { $params['width'] = (int) $params['width']; } if (!empty($params['height'])) { $params['height'] = (int) $params['height']; } $this->initial = $params['initial']; if ($this->initial && !$params['services']) { $params['services'] = "local"; } $this->services = SimilarImages::get_services($params['services']); if ($this->params()->id) { $this->compared_post = Post::find($this->params()->id); } else { $this->compared_post = new Post(); } $this->errors = null; $this->posts = Post::emptyCollection(); $this->similar = []; $similarity = []; if ($this->compared_post && $this->compared_post->is_deleted()) { $this->respond_to_error("Post deleted", ['post#show', 'id' => $this->params()->id, 'tag_title' => $this->compared_post->tag_title()]); return; } # We can do these kinds of searches: # # File: Search from a specified file. The image is saved locally with an ID, and sent # as a file to the search servers. # # URL: search from a remote URL. The URL is downloaded, and then treated as a :file # search. This way, changing options doesn't repeatedly download the remote image, # and it removes a layer of abstraction when an error happens during download # compared to having the search server download it. # # Post ID: Search from a post ID. The preview image is sent as a URL. # # Search ID: Search using an image uploaded with a previous File search, using # the search MD5 created. We're not allowed to repopulate filename fields in the # user's browser, so we can't re-submit the form as a file search when changing search # parameters. Instead, we hide the search ID in the form, and use it to recall the # file from before. These files are expired after a while; we check for expired files # when doing later searches, so we don't need a cron job. $search = function (array $params) { $options = array_merge($params, ['services' => $this->services]); # Check search_id first, so options links that include it will use it. If the # user searches with the actual form, search_id will be cleared on submission. if (!empty($params['search_id'])) { $file_path = SimilarImages::find_saved_search($params['search_id']); if (!$file_path) { # The file was probably purged. Delete :search_id before redirecting, so the # error doesn't loop. // unset($params.delete(:search_id) return ['errors' => ['error' => "Search expired"]]; } } elseif (!empty($params['url']) || !empty($_FILES['file']['tmp_name'])) { # Save the file locally. try { if (!empty($params['url'])) { $file = Danbooru::http_get_streaming($params['url']); $search = SimilarImages::save_search($file); } else { # file $file = file_get_contents($_FILES['file']['tmp_name']); $search = SimilarImages::save_search($file); $options['type'] = 'file'; } } catch (Moebooru\Exception\ResizeErrorException $e) { return ['errors' => ['error' => $e->getMessage()]]; } catch (Danbooru\Exception\ExceptionInterface $e) { return ['errors' => ['error' => $e->getMessage()]]; } // } rescue Timeout::Error => e // return { :errors => { :error => "Download timed out" } } // end $file_path = $search['file_path']; # Set :search_id in params for generated URLs that point back here. $params['search_id'] = $search['search_id']; # The :width and :height params specify the size of the original image, for display # in the results. The user can specify them; if not specified, fill it in. empty($params['width']) && ($params['width'] = $search['original_width']); empty($params['height']) && ($params['height'] = $search['original_height']); } elseif (!empty($params['id'])) { $options['source'] = $this->compared_post; $options['type'] = 'post'; } if (!empty($params['search_id'])) { $options['source'] = $file_path; $options['source_filename'] = $params['search_id']; $options['source_thumb'] = "/data/search/" . $params['search_id']; $options['type'] = 'file'; } $options['width'] = $params['width']; $options['height'] = $params['height']; if ($options['type'] == 'file') { SimilarImages::cull_old_searches(); } return SimilarImages::similar_images($options); }; $this->searched = false; if ($this->params()->url || $this->params()->id || !empty($_FILES['file']) && empty($_FILES['file']['error']) || !empty($this->params()->search_id)) { $res = $search($params); # Error when no service was selected and/or local search isn't supported if (is_string($res['errors'])) { $this->notice($res['errors']); } else { $this->errors = !empty($res['errors']) ? $res['errors'] : []; $this->searched = true; $this->search_id = $this->params()->search_id; # Never pass :file on through generated URLs. $params['file'] = null; } } else { $res = []; $this->errors = []; } if ($res && $this->searched) { !empty($res['posts']) && ($this->posts = $res['posts']); $this->similar = $res; !empty($res['similarity']) && ($similarity = $res['similarity']); } if ($this->request()->format() == "json" || $this->request()->format() == "xml") { if (!empty($this->errors['error'])) { $this->respond_to_error($this->errors['error'], ['#index'], ['status' => 503]); return; } if (!$this->searched) { $this->respond_to_error("no search supplied", ['#index'], ['status' => 503]); return; } } $this->respondTo(['html' => function () use($similarity, $res) { if ($this->initial && !$this->posts->any()) { // flash.keep $this->redirectTo(['post#show', 'id' => $this->params()->id, 'tag_title' => $this->compared_post->tag_title()]); return; } if (!empty($this->errors['error'])) { $this->notice($this->errors['error']); } if ($this->searched) { !empty($res['posts_external']) && $this->posts->merge($res['posts_external']); $this->posts->sort(function ($a, $b) use($similarity) { $aid = spl_object_hash($a); $bid = spl_object_hash($b); if ($similarity[$aid] == $similarity[$bid]) { return 0; } elseif ($similarity[$aid] > $similarity[$bid]) { return 1; } return -1; }); # Add the original post to the start of the list. if (!empty($res['source'])) { $this->posts[] = $res['source']; } elseif (!empty($res['external_source'])) { $this->posts[] = $res['external_source']; } } }, 'json' => function () use($res) { foreach ($this->posts as $post) { $post->similarity = $res['similarity'][spl_object_hash($post)]; } if (!empty($res['posts_external'])) { foreach ($res['posts_external'] as $post) { $post->similarity = $res['similarity'][spl_object_hash($post)]; } $this->posts->merge($res['posts_external']); } $api_data = ['posts' => $this->posts, 'search_id' => $this->params()->search_id]; if (!empty($res['source'])) { $api_data['source'] = $res['source']; } elseif (!empty($res['external_source'])) { $api_data['source'] = $res['external_source']; } else { $api_data['source'] = ''; } if (!empty($res['errors'])) { $api_data['error'] = []; foreach ($res['errors'] as $server => $error) { $services = !empty($error['services']) ? implode(', ', $error['services']) : array(); $api_data['error'][] = ['server' => $server, 'message' => $error['message'], 'services' => $services]; } } $this->respond_to_success('', [], ['api' => $api_data]); }]); $this->params = $params; }
function generate_preview() { if (!$this->is_image() && !$this->width && !$this->height) { return true; } $size = Danbooru::reduce_to(array('width' => $this->width, 'height' => $this->height), array('width' => 300, 'height' => 300)); # Generate the preview from the new sample if we have one to save CPU, otherwise from the image. if (file_exists($this->tempfile_sample_path())) { list($path, $ext) = array($this->tempfile_sample_path(), "jpg"); } elseif (file_exists($this->sample_path())) { list($path, $ext) = array($this->sample_path(), "jpg"); } elseif (file_exists($this->tempfile_path)) { list($path, $ext) = array($this->tempfile_path, $this->file_ext); } elseif (file_exists($this->file_path())) { list($path, $ext) = array($this->file_path(), $this->file_ext); } else { return false; } try { Danbooru::resize($ext, $path, $this->tempfile_preview_path(), $size, 85); } catch (Exception $e) { $this->record_errors->add("preview", "couldn't be generated ({$e->getMessage()})"); return false; } $this->actual_preview_width = $this->raw_preview_dimensions('w'); $this->actual_preview_height = $this->raw_preview_dimensions('h'); $this->preview_width = $this->preview_dimensions('w'); $this->preview_height = $this->preview_dimensions('h'); return true; }