summary refs log tree commit diff stats
path: root/imagestore.cpp
blob: 509456933f133f2d13e500d0909a259959c8eb0e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include "imagestore.h"

#include <curlcpp/curl_easy.h>

#include <chrono>
#include <fstream>
#include <sstream>
#include <thread>

Magick::Image imagestore::get(std::string key, std::string url) const {
  std::lock_guard lock(mutex_);

  std::string filename = path_ + "/" + key;

  Magick::Image pic;

  if (std::ifstream(filename)) {
    pic.read(filename);
  } else {
    // This is to avoid getting rate limited.
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    std::ostringstream imgbuf;
    curl::curl_ios<std::ostringstream> imgios(imgbuf);
    curl::curl_easy imghandle(imgios);

    imghandle.add<CURLOPT_URL>(url.c_str());
    imghandle.add<CURLOPT_CONNECTTIMEOUT>(30);
    imghandle.add<CURLOPT_TIMEOUT>(300);

    imghandle.perform();

    if (imghandle.get_info<CURLINFO_RESPONSE_CODE>().get() != 200) {
      throw std::runtime_error("Could not download image");
    }

    std::string content_type =
        imghandle.get_info<CURLINFO_CONTENT_TYPE>().get();
    if (content_type.substr(0, 6) != "image/") {
      throw std::runtime_error("Could not download image");
    }

    std::string imgstr = imgbuf.str();
    Magick::Blob img(imgstr.c_str(), imgstr.length());

    try {
      pic.read(img);
    } catch (const Magick::ErrorOption& e) {
      // Occurs when the the data downloaded from the server is malformed
      std::cout << "Magick: " << e.what() << std::endl;

      throw std::runtime_error("Could not download image");
    }

    pic.write(filename);
  }

  return pic;
}

void imagestore::cleanup() const {
  std::lock_guard lock(mutex_);

  for (const auto& entry : std::filesystem::directory_iterator(path_)) {
    std::filesystem::remove_all(entry);
  }
}