Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding video statistics functionality #50

Open
wants to merge 63 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
94d51f6
Adding video statistics functionality
Colum31 Apr 12, 2022
ed6a161
adding new datatype to hold video info
Colum31 Apr 12, 2022
c417329
Implement video.list:contentDetails
Colum31 Apr 15, 2022
d17aba0
Implement video.list:snippet
Colum31 Apr 18, 2022
c81fb75
fixed bug
Colum31 Apr 18, 2022
4c1e1cb
refactoring code
Colum31 Apr 19, 2022
4a3e942
adding new example and changing config files
Colum31 Apr 21, 2022
7443443
Fixing example and adjusting buffer sizes
Colum31 Apr 22, 2022
154894e
adding video.list:status
Colum31 Apr 22, 2022
9368462
refactoring varibale names and library metadata
Colum31 Apr 22, 2022
504b687
Merge pull request #1 from Colum31/video_info
Colum31 Apr 22, 2022
0229afe
making videos a seperate class
Colum31 Aug 11, 2022
ad064a5
moving library to lib and creating some unittests
Colum31 Aug 12, 2022
c225dac
adding doc and new testcases
Colum31 Aug 12, 2022
d82ba8b
adding new testcases
Colum31 Aug 13, 2022
040c6f8
moving functions from api to video class and new tests
Colum31 Aug 13, 2022
3ac50a7
fixing size reserved for api key
Colum31 Aug 13, 2022
b49551b
removing duplicate functions from YoutubeApi
Colum31 Aug 13, 2022
a156114
adding new testcases
Colum31 Aug 14, 2022
83f2e75
-moving videoSnippet functionality to YoutubeVideo
Colum31 Aug 14, 2022
7f470fa
changing variable type to address popular videos
Colum31 Aug 14, 2022
ad7d843
changing long variable types to inttypes
Colum31 Aug 14, 2022
de8d7b0
fixing memory leaks
Colum31 Aug 14, 2022
dee25db
moving video status functionality to Video Class
Colum31 Aug 14, 2022
c7196bd
moving contentDetails functionality to video class
Colum31 Aug 16, 2022
d58a66e
adding test for videoContentDetails
Colum31 Aug 16, 2022
46d6c40
Merge pull request #2 from Colum31:video_split
Colum31 Aug 16, 2022
9ee517d
internet connection is now established in severaly tries when testing
Colum31 Aug 19, 2022
529436c
spliting channel functions into seperate class
Colum31 Aug 19, 2022
829490f
adding tests
Colum31 Aug 20, 2022
069025b
moving channelStatisitcs functionality into channel class
Colum31 Aug 20, 2022
df9f8b5
adding documentation to functions
Colum31 Aug 20, 2022
2fd9408
it is now possible to fetch channel snippet
Colum31 Sep 16, 2022
993e448
implementing channelContentDetails struct
Colum31 Sep 30, 2022
4482dfb
adding content details functionality
Colum31 Sep 30, 2022
d05de13
rewrting video information example
Colum31 Oct 3, 2022
4a6b2f8
rewriting example and adding extra error checking
Colum31 Oct 5, 2022
19643d7
Renaming examples
Colum31 Oct 5, 2022
1bc3326
Merge pull request #3 from Colum31/channel_split
Colum31 Oct 5, 2022
d32b83d
changing readme
Colum31 Oct 6, 2022
f7c683a
fixing imgur links in readme
Colum31 Oct 6, 2022
1cf6f1d
initial commit on playlist branch
Colum31 Oct 8, 2022
ffe8985
implementing constructor/destructor and new types
Colum31 Oct 8, 2022
7571572
adding cleanup functions
Colum31 Oct 8, 2022
8f06009
adding helper functions and flags
Colum31 Oct 8, 2022
4b2734a
refactoring YoutubeChannel test and error checking
Colum31 Oct 8, 2022
d64e860
adding url generation for playlist:status
Colum31 Oct 8, 2022
48948cf
adding fetching of playlist status and tests
Colum31 Oct 9, 2022
5cf8528
adding fetching of playlists:contentDetails
Colum31 Oct 9, 2022
f75d34c
adding fetching of playlists:snippet
Colum31 Oct 10, 2022
8b53c66
creating structs for playlist items
Colum31 Oct 10, 2022
c2394d5
adding fetching of playlistItems:contentDetails
Colum31 Oct 11, 2022
79da586
implementing and testing fetching of playlistItems
Colum31 Oct 13, 2022
eb6804f
adding helper function getYoutubeApiObj()
Colum31 Oct 13, 2022
023b86f
implementing fetching of following pages
Colum31 Oct 13, 2022
e794867
implementing fetching previous page and a simple test
Colum31 Oct 20, 2022
a2ea175
Implemented fetching previous playlist pages
Colum31 May 26, 2023
c930626
Merge branch 'playlist' of github.com:Colum31/arduino-youtube-api int…
Colum31 May 27, 2023
405597e
adding example for YoutubePlaylist
Colum31 May 29, 2023
05e7d67
Using YoutubePlaylist in YoutubeChannel example
Colum31 Jun 1, 2023
035ae79
Merge pull request #4 from Colum31/playlist
Colum31 Jun 1, 2023
2d1f28d
putting internet connection check into setup
Colum31 Jun 5, 2023
0409256
Making client a global var
Colum31 Jun 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -367,3 +367,7 @@ vs-readme.txt
.gcc-flags.json
.pio/
.vscode/

# custom ignores
src/*
lib/secrets/*
27 changes: 0 additions & 27 deletions .travis.yml

This file was deleted.

20 changes: 15 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
# Arduino YouTube API Library
[![arduino-library-badge](https://www.ardu-badge.com/badge/YoutubeApi.svg?)](https://www.ardu-badge.com/YoutubeApi) [![Build Status](https://travis-ci.org/witnessmenow/arduino-youtube-api.svg?branch=master)](https://travis-ci.org/witnessmenow/arduino-youtube-api)

A wrapper for the [YouTube API](https://developers.google.com/youtube/v3/docs/) for Arduino. Works on both ESP8266 and ESP32.

![Imgur](http://i.imgur.com/FmXyW4E.png)
### Example fetching channel information:

![Imgur](https://i.imgur.com/JaZR9m9.png)

### Example fetching video information:

![Imgur](https://i.imgur.com/hTbtVvg.png)

### Support what I do!

Expand Down Expand Up @@ -42,16 +47,21 @@ then once you're connected to WiFi you can start requesting data from the API:

#define CHANNEL_ID "UCezJOfu7OtqGzd5xrP3q6WA"

if(api.getChannelStatistics(CHANNEL_ID)) {
YoutubeChannel channel(CHANNEL_ID, &api);

if(channel.getChannelStatistics()) {
Serial.print("Subscriber Count: ");
Serial.println(api.channelStats.subscriberCount);
Serial.println(channel.channelStats->subscriberCount);
}

If you don't know it, you can find your own YouTube channel ID [here](https://www.youtube.com/account_advanced). See [the examples](examples) for more details on how to use the library.

## Supported Data Methods

Currently the only implemented method is getting channel statistics, but the library can be easily extended. Please raise an issue if there is a method you are looking for.
The library is currently able to fetch:

- video list: snippet, status, statistics and contentDetails
- channel list: snippet, statistics and content details

## License

Expand Down
279 changes: 279 additions & 0 deletions examples/ChannelInformation/ChannelInformation.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
/*******************************************************************
Read YouTube Channel information from the YouTube API
and print them to the serial monitor

Compatible Boards:
* Any ESP8266 board
* Any ESP32 board

Recommended Board: D1 Mini ESP8266
http://s.click.aliexpress.com/e/uzFUnIe (affiliate)

If you find what I do useful and would like to support me,
please consider becoming a sponsor on Github
https://github.com/sponsors/witnessmenow/

Written by Brian Lough
YouTube: https://www.youtube.com/brianlough
Tindie: https://www.tindie.com/stores/brianlough/
Twitter: https://twitter.com/witnessmenow
*******************************************************************/

// ----------------------------
// Standard Libraries
// ----------------------------

#if defined(ESP8266)
#include <ESP8266WiFi.h>
#elif defined(ESP32)
#include <WiFi.h>
#endif

#include <WiFiClientSecure.h>

// ----------------------------
// Additional Libraries - each of these will need to be installed
// ----------------------------

// Library for connecting to the YouTube API
// https://github.com/witnessmenow/arduino-youtube-api
// (search for "youtube" in the Arduino Library Manager)
#include "YoutubeApi.h"
#include "YoutubeChannel.h"
#include "YoutubePlaylist.h"
#include "YoutubeVideo.h"

// Library used for parsing Json from the API responses
// https://github.com/bblanchon/ArduinoJson
// (search for "Arduino Json" in the Arduino Library Manager)
#include <ArduinoJson.h>

//------- Replace the following! ------
const char ssid[] = "xxx"; // your network SSID (name)
const char password[] = "yyyy"; // your network key
#define API_KEY "zzzz" // your Google API key
#define CHANNEL_ID "UCezJOfu7OtqGzd5xrP3q6WA" // part of the channel url
//------- ---------------------- ------

#define channelIdLen 24

#define timeBetweenRequestGroup 120 * 1000 // 120 seconds, in milliseconds | time between all requests
#define timeBetweenRequests 2 * 1000 // 2 seconds, in milliseconds | time between single requests

WiFiClientSecure client;
YoutubeApi api(API_KEY, client);

char videoId[channelIdLen + 1];
unsigned long startTime;

/**
* @brief Tries to read the videoId from Serial.
*
* @return 1 on success, 0 if no data available
*/
int readVideoId(){

if(Serial.available() > channelIdLen - 1){

for(int i = 0; i < channelIdLen; i++){

videoId[i] = Serial.read();
}

videoId[channelIdLen] = '\0';
return 1;
}
return 0;
}

/**
* @brief Flushes the Serial input buffer.
*
*/
void flushSerialBuffer(){
while(Serial.available()){
Serial.read();
}
}

/**
* @brief Prints "Yes\n" if x or "No\n" if not x
*
* @param x parameter
*/
void printYesNo(bool x){
if(x){
Serial.println("Yes");
}else{
Serial.println("No");
}
}


void setup() {
Serial.begin(115200);

// Set WiFi to 'station' mode and disconnect
// from the AP if it was previously connected
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);

// Connect to the WiFi network
Serial.print("\nConnecting to WiFi: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println("\nWiFi connected!");
Serial.print("IP address: ");
IPAddress ip = WiFi.localIP();
Serial.println(ip);

#ifdef ESP8266
// Required if you are using ESP8266 V2.5 or above
client.setInsecure();
#endif

client.setInsecure();

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

flushSerialBuffer();
Serial.print("Enter channelId: ");

while(1){
if(readVideoId()){
flushSerialBuffer();
break;
}
}

Serial.println(videoId);
}

void loop() {

Serial.setTimeout(timeBetweenRequestGroup);

YoutubeChannel channel(videoId, &api);

// fetch and print information in channel.list:snippet
if(channel.getChannelSnippet()){
Serial.println("\n\nsnippet");

channelSnippet *fetchedSnip = channel.channelSnip;


Serial.print("|----- Channel title: ");
Serial.println(fetchedSnip->title);

Serial.print("|----- Channel description: ");
Serial.println(fetchedSnip->description);

Serial.print("|----- Channel country: ");
Serial.println(fetchedSnip->country);

tm channelCreation = fetchedSnip->publishedAt;

Serial.print("|----- Channel creation (d.m.y h:m:s): ");
Serial.print(channelCreation.tm_mday);
Serial.print(".");
Serial.print(channelCreation.tm_mon);
Serial.print(".");
Serial.print(channelCreation.tm_year + 1900);
Serial.print(" ");
Serial.print(channelCreation.tm_hour);
Serial.print(":");
Serial.print(channelCreation.tm_min);
Serial.print(":");
Serial.println(channelCreation.tm_sec);

Serial.println("-------------------------------------------------");
}

if(channel.getChannelStatistics()){
Serial.println("\n\nstatistics");

channelStatistics *fetchedStats = channel.channelStats;

Serial.print("|----- Channel views: ");
Serial.println(fetchedStats->viewCount);

Serial.print("|----- Channel subscriber count hidden? ");
printYesNo(fetchedStats->hiddenSubscriberCount);

Serial.print("|----- Channel subscribers: ");
Serial.println(fetchedStats->subscriberCount);

Serial.print("|----- Channel video count: ");
Serial.println(fetchedStats->videoCount);

Serial.println("-------------------------------------------------");
}

delay(timeBetweenRequests);

// fetch and print information in channel.list:contentDetails
if(channel.getChannelContentDetails()){
Serial.println("\n\ncontent details");

channelContentDetails *fetchedDetails = channel.channelContentDets;

Serial.print("|----- Liked videos playlist id: ");
Serial.println(fetchedDetails->relatedPlaylistsLikes);

Serial.print("|----- Uploaded videos playlist id: ");
Serial.println(fetchedDetails->relatedPlaylistsUploads);

Serial.println("-------------------------------------------------");
}

if(channel.checkChannelContentDetailsSet() && channel.checkChannelSnipSet()){
Serial.print("\n\nFetching last five videos of ");
Serial.println(channel.channelSnip->title);

YoutubePlaylist recentVideos = YoutubePlaylist(&api, channel.channelContentDets->relatedPlaylistsUploads);
recentVideos.getPlaylistItemsPage(0);

playlistItemsContentDetails *page = recentVideos.itemsContentDets;

for(int i = 0; i < YT_PLAYLIST_ITEM_RESULTS_PER_PAGE; i++){
char *videoId = page[i].videoId;

if(!strcmp("", videoId)){
break;
}

YoutubeVideo vid = YoutubeVideo(videoId, &api);
if(vid.getVideoSnippet() && vid.getVideoStatistics()){
Serial.print("videoId: ");
Serial.print(videoId);
Serial.print(" | \"");
Serial.print(vid.videoSnip->title);
Serial.print("\" | Views: ");
Serial.println(vid.videoStats->viewCount);
}
}
}


Serial.print("\nRefreshing in ");
Serial.print(timeBetweenRequestGroup / 1000.0);
Serial.println(" seconds...");
Serial.print("Or set a new channelId: ");

startTime = millis();
flushSerialBuffer();

while(millis() - startTime < timeBetweenRequestGroup){

if(readVideoId()){;
Serial.println(videoId);
break;
}
}
}
Loading