Skip to content

Commit

Permalink
adding video.list:status
Browse files Browse the repository at this point in the history
-> adding struct and functions to fetch video.list:status
-> adding status information to example
-> altering doc to show which attributes are not implemented yet
  • Loading branch information
Colum31 committed Apr 22, 2022
1 parent 7443443 commit 154894e
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 4 deletions.
26 changes: 25 additions & 1 deletion examples/VideoFullInformation/VideoFullInformation.ino
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ void setup() {
// Required if you are using ESP8266 V2.5 or above
client.setInsecure();
#endif

// Uncomment for extra debugging info
// api._debug = true;

Expand Down Expand Up @@ -258,6 +258,30 @@ void loop() {
Serial.println("-------------------------------------------------");
}

delay(timeBetweenRequests);

if(api.getVideoStatus(videoId)){
Serial.println("\n\n status");

Serial.print("------ upload status: ");
Serial.println(api.vStatus.uploadStatus);

Serial.print("------ privacy status: ");
Serial.println(api.vStatus.privacyStatus);

Serial.print("------ license: ");
Serial.println(api.vStatus.license);

Serial.print("------ embeddable: ");
printYesNo(api.vStatus.embeddable);

Serial.print("------ public stats viewable: ");
printYesNo(api.vStatus.publicStatsViewable);

Serial.print("------ made for kids: ");
printYesNo(api.vStatus.madeForKids);
}

Serial.print("\nRefreshing in ");
Serial.print(timeBetweenRequestGroup / 1000.0);
Serial.println(" seconds...");
Expand Down
114 changes: 112 additions & 2 deletions src/YoutubeApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@

// TODO
//
// add video.list:status
// video.list:topicDetails
// add video.list:topicDetails

#include "YoutubeApi.h"

Expand Down Expand Up @@ -321,6 +320,75 @@ bool YoutubeApi::parseSnippet(){
}


bool YoutubeApi::parseVideoStatus(){

bool wasSuccessful = false;
const size_t bufferSize = 384;

// Creating a filter to filter out
// metadata, thumbnail links, tags, localized information

StaticJsonDocument<192> filter;

JsonObject filterItems = filter["items"][0].createNestedObject("status");
filterItems["uploadStatus"] = true;
filterItems["privacyStatus"] = true;
filterItems["license"] = true;
filterItems["embeddable"] = true;
filterItems["publicStatsViewable"] = true;
filterItems["madeForKids"] = true;

JsonObject filterPageInfo = filter.createNestedObject("pageInfo");
filterPageInfo["totalResults"] = true;
filterPageInfo["resultsPerPage"] = true;

// Allocate DynamicJsonDocument
DynamicJsonDocument doc(bufferSize);

// Parse JSON object
DeserializationError error = deserializeJson(doc, client, DeserializationOption::Filter(filter));

// check for errors and empty response
if(error){
Serial.print(F("deserializeJson() failed with code "));
Serial.println(error.c_str());
}
else if(doc["pageInfo"]["totalResults"].as<int>() == 0){
Serial.println("No results found for video id ");
}
else{
JsonObject itemsStatus = doc["items"][0]["status"];

if(vStatus.set){
freeStatus(&vStatus);
}

int checksum = 0;
checksum += allocAndCopy(&vStatus.uploadStatus, itemsStatus["uploadStatus"]);
checksum += allocAndCopy(&vStatus.privacyStatus, itemsStatus["privacyStatus"]);
checksum += allocAndCopy(&vStatus.license, itemsStatus["license"]);

vStatus.embeddable = itemsStatus["embeddable"]; // true
vStatus.publicStatsViewable = itemsStatus["publicStatsViewable"]; // true
vStatus.madeForKids = itemsStatus["madeForKids"];

if(checksum){
// don't set videoStatus.set flag in order to avoid false free
Serial.print("Error reading in response values. Checksum: ");
Serial.println(checksum);
vStatus.set = false;
wasSuccessful = false;
}else{
vStatus.set = true;
wasSuccessful = true;
}
}

closeClient();
return wasSuccessful;
}


/**
* @brief Makes an API request for a specific endpoint and type. Calls a parsing function
* to handle parsing.
Expand Down Expand Up @@ -349,11 +417,16 @@ bool YoutubeApi::getRequestedType(int op, const char *id) {
sprintf(command, YTAPI_REQUEST_FORMAT, YTAPI_VIDEO_ENDPOINT, "snippet", id, apiKey.c_str());
break;

case videoListStatus:
sprintf(command, YTAPI_REQUEST_FORMAT, YTAPI_VIDEO_ENDPOINT, "status", id, apiKey.c_str());
break;

case channelListStats:
sprintf(command, YTAPI_REQUEST_FORMAT, YTAPI_CHANNEL_ENDPOINT, "statistics", id, apiKey.c_str());
break;

default:
Serial.println("Unknown operation");
return false;
}

Expand Down Expand Up @@ -383,6 +456,10 @@ bool YoutubeApi::getRequestedType(int op, const char *id) {
wasSuccessful = parseSnippet();
break;

case videoListStatus:
wasSuccessful = parseVideoStatus();
break;

default:
wasSuccessful = false;
break;
Expand Down Expand Up @@ -459,6 +536,23 @@ bool YoutubeApi::getSnippet(const char *videoId){
}


/**
* @brief Gets the status of a specific video. Stores them in the calling object.
*
* @param videoId videoID of the video to get the information from
* @return wasSuccesssful true, if there were no errors and the video was found
*/
bool YoutubeApi::getVideoStatus(const String& videoId){
return getRequestedType(videoListStatus, videoId.c_str());
}


bool YoutubeApi::getVideoStatus(const char *videoId){
return getRequestedType(videoListStatus, videoId);
}



/**
* @brief Parses the ISO8601 duration string into a tm time struct.
*
Expand Down Expand Up @@ -617,6 +711,22 @@ void YoutubeApi::freeSnippet(snippet *s){
return;
}


void YoutubeApi::freeStatus(videoStatus *s){

if(!s->set){
return;
}

free(s->uploadStatus);
free(s->license);
free(s->privacyStatus);

memset(s, 0, sizeof(videoStatus));

return;
}

/**
* @brief Allocates memory and copies a string into it.
*
Expand Down
32 changes: 31 additions & 1 deletion src/YoutubeApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ enum operation{
videoListStats,
videoListContentDetails,
videoListSnippet,
videoListStatus,

channelListStats
};
Expand All @@ -65,28 +66,51 @@ struct contentDetails{
char defintion[3];
bool caption;
bool licensedContent;
// char **regionRestriction;
// char **contentRating;
char projection[12];
// bool hasCustomThumbnail;
};


struct videoStatistics {
long viewCount;
long commentCount;
long likeCount;
// long favourites;
// long dislikeCount;

// In Memory of the old dislike count.
};


struct videoStatus{
bool set;
char *uploadStatus;
// char *failureReason;
// char *rejectionReason;
char *privacyStatus;
// tm publishAt;
char *license;
bool embeddable;
bool publicStatsViewable;
bool madeForKids;
// bool selfDeclaredMadeForKids;
};

struct snippet{
bool set;
tm publishedAt;
char *channelId;
char *title;
char *description;
// char **thumbnails;
char *channelTitle;
// char **tags;
int categoryId;
char *liveBroadcastContent;
char *defaultLanguage;
// char **localized;
char *defaultAudioLanguage;
};

Expand All @@ -110,11 +134,15 @@ class YoutubeApi

bool getSnippet(const String& videoId);
bool getSnippet(const char *videoId);


bool getVideoStatus(const String& videoId);
bool getVideoStatus(const char *videoId);

snippet snip;
channelStatistics channelStats;
videoStatistics videoStats;
contentDetails contentDets;
videoStatus vStatus;
bool _debug = false;

private:
Expand All @@ -124,6 +152,7 @@ class YoutubeApi
tm parseUploadDate(const char *dateTime);

void freeSnippet(snippet *s);
void freeStatus(videoStatus *s);
int allocAndCopy(char **pos, const char *data);
bool getRequestedType(int op, const char *channelId);
int getHttpStatusCode();
Expand All @@ -132,6 +161,7 @@ class YoutubeApi
bool parseVideoStatistics();
bool parseContentDetails();
bool parseSnippet();
bool parseVideoStatus();

void skipHeaders();
void closeClient();
Expand Down

0 comments on commit 154894e

Please sign in to comment.