pornsieve  0.0.0
Search porn sites and filter the results using regular expressions
Functions
pornsieve::redtube Namespace Reference

Namespace for the RedTube API. More...

Functions

vector< string > get_categories ()
 Get a list of categories from RedTube. More...
 
vector< string > get_tags ()
 Get a list of tags from RedTube. More...
 
search_result search (media_type type, string_view query, const vector< string_view > &tags={}, string_view category={}, result_order order_by=result_order::none, std::uint32_t page=1)
 Search RedTube. More...
 

Detailed Description

Namespace for the RedTube API.

Since
0.1.0

Function Documentation

◆ get_categories()

vector< string > pornsieve::redtube::get_categories ( )

Get a list of categories from RedTube.

Note
According to the API documentation, a search can specify 1 category as string. However, some category names are used 2 times (for example: categories→Amateur and categories_gay→Amateur). 🤷
Exceptions
pornsieve::CURLExceptionThrown on libcurl errors.
std::runtime_exceptionThrown if libcurl failed to initialize.
nlohmann::detail::type_errorThrown if the format of the JSON is different than expected.
Returns
Category names without ID. Names are not unique.
Since
0.1.0
50 {
51  try
52  {
53  cw::CURLWrapper curl;
54  configure_curl(curl.get_curl_easy_handle());
55 
56  const string url{
57  format("{:s}&data=redtube.Categories.getCategoriesList", base_url)};
58  const auto answer{curl.make_http_request(cw::http_method::GET, url)};
59  if (answer)
60  {
61  vector<string> categories;
62  // Supercategories are "categories" and "categories_gay" ATM.
63  for (const auto &supercategory : nlohmann::json::parse(answer.body))
64  {
65  for (const auto &category : supercategory)
66  {
67  categories.emplace_back(category["category"]);
68  }
69  }
70  return categories;
71  }
72  throw HTTPException{answer.status};
73  }
74  catch (const cw::CURLException &e)
75  {
76  throw pornsieve::CURLException(e.error_code, e.error_message);
77  }
78 }

◆ get_tags()

vector< string > pornsieve::redtube::get_tags ( )

Get a list of tags from RedTube.

Exceptions
pornsieve::CURLExceptionThrown on libcurl errors.
std::runtime_exceptionThrown if libcurl failed to initialize.
nlohmann::detail::type_errorThrown if the format of the JSON is different than expected.
Returns
Tag names.
Since
0.1.0
81 {
82  try
83  {
84  cw::CURLWrapper curl;
85  configure_curl(curl.get_curl_easy_handle());
86 
87  const auto answer{
88  curl.make_http_request(cw::http_method::GET,
89  format("{:s}&data=redtube.Tags.getTagList",
90  base_url))};
91  if (answer)
92  {
93  vector<string> tags;
94  const auto json{nlohmann::json::parse(answer.body)};
95  for (const auto &tag : json.front()["tags"])
96  {
97  tags.emplace_back(tag["tag"]["tag_name"]);
98  }
99  return tags;
100  }
101  throw HTTPException{answer.status};
102  }
103  catch (const cw::CURLException &e)
104  {
105  throw pornsieve::CURLException(e.error_code, e.error_message);
106  }
107 }

◆ search()

search_result pornsieve::redtube::search ( media_type  type,
string_view  query,
const vector< string_view > &  tags = {},
string_view  category = {},
result_order  order_by = result_order::none,
std::uint32_t  page = 1 
)

Search RedTube.

Note
The search seems to be completely broken. The results are highly inaccurate.
Parameters
typeAccepted values: video.
queryMatching seems to be very fuzzy, to the point where it is unusable.
tagsDoes not really change the result count. Does not seem to influence the result ordering. 😕
categoryOnly some categories work, some return always 0 results. If the specified category does not exist, it returns 0 results.
order_byAccepted values: none, newest, mostviewed, rating, popular_week, popular_month.
pageReturn this page of results.
Exceptions
pornsieve::CURLExceptionThrown on libcurl errors.
std::runtime_exceptionThrown if libcurl failed to initialize.
nlohmann::detail::type_errorThrown if the format of the JSON is different than expected.
std::logic_errorThrown if the ordering algorithm or media type is not supported.
Since
0.1.0
113 {
114  if (type != media_type::video)
115  {
116  throw std::logic_error{"Media type not supported"};
117  }
118 
119  try
120  {
121  cw::CURLWrapper curl;
122  configure_curl(curl.get_curl_easy_handle());
123 
124  string tags_maybe;
125  for (const auto &tag : tags)
126  {
127  tags_maybe += format("&tags[]={:s}", curl.escape_url(tag));
128  }
129 
130  const string category_maybe{
131  [&category, &curl]
132  {
133  if (!category.empty())
134  {
135  return format("&category={:s}", curl.escape_url(category));
136  }
137  return string{};
138  }()};
139 
140  const string order_by_maybe{
141  [order_by]
142  {
143  switch (order_by)
144  {
145  case result_order::none:
146  {
147  return "";
148  break;
149  }
150  case result_order::newest:
151  {
152  return "&ordering=newest";
153  break;
154  }
155  case result_order::mostviewed:
156  {
157  return "&ordering=mostviewed";
158  break;
159  }
160  case result_order::rating:
161  {
162  return "&ordering=rating";
163  break;
164  }
165  case result_order::popular_week:
166  {
167  return "&ordering=rating&period=weekly";
168  break;
169  }
170  case result_order::popular_month:
171  {
172  return "&ordering=rating&period=monthly";
173  break;
174  }
175  default:
176  {
177  throw std::logic_error{"Ordering algorithm not supported"};
178  break;
179  }
180  }
181  }()};
182 
183  const string url{format("{:s}&data=redtube.Videos.searchVideos"
184  "&search={:s}{:s}{:s}{:s}&page={:d}",
185  base_url, curl.escape_url(query), tags_maybe,
186  category_maybe, order_by_maybe, page)};
187  const auto answer{curl.make_http_request(cw::http_method::GET, url)};
188  if (answer)
189  {
190  search_result result;
191  result.original_data = answer.body;
192  const auto json{nlohmann::json::parse(answer.body)};
193  result.count = json.front()["count"];
194 
195  for (const auto &item_json : json.front()["videos"])
196  {
197  search_result::item item;
198  const auto &video{item_json["video"]};
199 
200  item.title = video["title"];
201  item.url = video["url"];
202  item.duration = string_to_duration(
203  video["duration"].get<string>());
204  item.tags = json_to_vector(video["tags"].dump(), "tag_name");
205  item.thumbnails = json_to_vector(video["thumbs"].dump(), "src");
206  if (video["rating"].is_string())
207  { // If it is not a string, it is 0.
208  item.rating = std::stof(video["rating"].get<string>());
209  }
210  item.views = video["views"];
211  item.date = string_to_timepoint(
212  video["publish_date"].get<string>());
213 
214  result.items.emplace_back(item);
215  }
216  return result;
217  }
218  throw HTTPException{answer.status};
219  }
220  catch (const cw::CURLException &e)
221  {
222  throw pornsieve::CURLException(e.error_code, e.error_message);
223  }
224 }
pornsieve::string_to_duration
std::chrono::seconds string_to_duration(string_view duration_string)
Converts a duration from string to chrono seconds.
Definition: helpers.cpp:47
pornsieve::json_to_vector
vector< string > json_to_vector(string_view json, string_view key)
Converts a JSON array into a vector.
Definition: helpers.cpp:37
pornsieve::CURLException
Exception for libcurl errors.
Definition: exceptions.hpp:45
pornsieve::string_to_timepoint
time_point string_to_timepoint(string_view time_string)
Converts a time from string to time_point.
Definition: helpers.cpp:72
pornsieve::configure_curl
void configure_curl(CURL *curl_easy_handle)
Set some options for curl connections.
Definition: config.cpp:31