<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: fri3d</title>
    <description>The latest articles on DEV Community by fri3d (@fri3d).</description>
    <link>https://dev.to/fri3d</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F121600%2Fe1f8af60-b4ba-46ad-a51c-25bad42a6b3a.png</url>
      <title>DEV Community: fri3d</title>
      <link>https://dev.to/fri3d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fri3d"/>
    <language>en</language>
    <item>
      <title>Updating a Youtube Title, The Tom Scott way.</title>
      <dc:creator>fri3d</dc:creator>
      <pubDate>Wed, 29 Apr 2020 14:00:00 +0000</pubDate>
      <link>https://dev.to/fri3d/updating-a-youtube-title-the-tom-scott-way-5no</link>
      <guid>https://dev.to/fri3d/updating-a-youtube-title-the-tom-scott-way-5no</guid>
      <description>&lt;p&gt;Recently Tom Scott made a &lt;a href="https://www.youtube.com/watch?v=BxV14h0kFs0" rel="noopener noreferrer"&gt;Youtube video&lt;/a&gt; in which the title would keep up to date with the number of views that the video had. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu737xqu5lc2ugfiqd7wb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu737xqu5lc2ugfiqd7wb.png" alt="Tom Scott"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Its a really good video, but the video isnt about the actual code that does the update, the video is about things not always reamining the same, and that over time, things change. Anyone whose done things like web scraping or even just working with APIs will know that things change, and sometimes without any notice. One day a thing you've built which is being used by hundreds of users might be working fine and then the next day Twitter announces that its shutting off the firehose access to tweets. &lt;/p&gt;

&lt;p&gt;Whilst the video wasnt about the code, I was really interested in what it would take. Tom, by his own admission, is a fan of 'The Bodge' - getting something working just well enough to demonstrate that it is possible, even if it is just held together with string and a bit of glue. You just need to know its possible to do, then you can start figuring out how to make it better and more stable.&lt;/p&gt;




&lt;p&gt;Whenever thinking about doing something like this I always like to try and break it down into a few steps. So I know that I want to execute a single script to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Login to Youtube (with the account that contains the video I want to update )&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get the number of current views of the chosen video.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the title of the video with the new information&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run this script as often as I like ( Cron Job )&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;This might be very far from the most optimal way to do this. Im sure there are going to be plenty of people who choose to do this in a different language, or use 'Serverless' setup. There's also a lack of error handling, but feel free to take this as a starting point and making it your own.&lt;/p&gt;




&lt;h3&gt;
  
  
  Google credentials
&lt;/h3&gt;

&lt;p&gt;First thing that we are going to need are the credentials to access the Youtube API. Head on over to the &lt;a href="https://console.cloud.google.com/" rel="noopener noreferrer"&gt;Google Cloud Console&lt;/a&gt; and then in the menu go to APIs &amp;amp; Services -&amp;gt; Credentials.&lt;/p&gt;

&lt;p&gt;On the next screen Create a new Credential and select &lt;strong&gt;OAuth Client ID&lt;/strong&gt;. In the Create screen, select Other and give your credential a name.&lt;/p&gt;

&lt;p&gt;Back on the credentials screen you will now be able to download your credentials. This is a json file needed to generate a Oauth token that our application will be able to use. &lt;/p&gt;

&lt;h3&gt;
  
  
  Project start
&lt;/h3&gt;

&lt;p&gt;Lets create a new directory for our project and run &lt;code&gt;npm init&lt;/code&gt; to create a &lt;code&gt;package.json&lt;/code&gt;. Also create a file that will be our script that we will have our cron job execute. I've called mine &lt;code&gt;update.js&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Youtube API
&lt;/h3&gt;

&lt;p&gt;We are going to be using the Youtube Data API in order to both fetch the statistics of the video and then do the updating. The main documentation can be &lt;a href="https://developers.google.com/youtube/v3" rel="noopener noreferrer"&gt;found here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Head straight to the guides, give the overview a quick read, and then we're gonna grab the &lt;a href="https://developers.google.com/youtube/v3/quickstart/nodejs" rel="noopener noreferrer"&gt;Node.js sample&lt;/a&gt;. Copy and paste that into out &lt;code&gt;update.js&lt;/code&gt; file and also run &lt;code&gt;npm install googleapis --save&lt;/code&gt; to get the google library. The documentation also specifies to install &lt;code&gt;google-auth-library&lt;/code&gt;, but I didn't as it didn't seem to be used in the sample project. &lt;/p&gt;

&lt;p&gt;Once that is done, you should be able to execute the script from your terminal and be prompted to head to a link in your browser to authorize the application. Once you follow that URL you will be asked to log into your google account and connect it to a YouTube account that uses that same email address. &lt;/p&gt;

&lt;p&gt;There will be a warning when authorizing the application ( because the redirect URL is localhost ) this is fine for our use case as this isnt an application that we will be distributing. We can continue on to give us a code that we can copy and paste back in terminal where there is a prompt for it. &lt;/p&gt;

&lt;p&gt;Once the code is accepted - the script will run as is and give us some information about the Google Developers Youtube channel. &lt;/p&gt;

&lt;h2&gt;
  
  
  Whats happening here?
&lt;/h2&gt;

&lt;p&gt;We are creating an OAUTH token that our script is going to use and it gets stored in the home directory of our system in a directory called &lt;code&gt;.credentials&lt;/code&gt;. We can choose this directory in &lt;a href="https://github.com/DeepfriedDev/GreatScott/blob/d3528c90697f966244c3fe3779bdd5043bfcdd28/update.js#L8" rel="noopener noreferrer"&gt;this line of the code&lt;/a&gt;. Once that is created once, everytime the script runs it checks to see if that exists and is all correct - if it does, then the script will carry on executing, if it doesn't then we just have to go through the process of generating the token. &lt;/p&gt;

&lt;h2&gt;
  
  
  Script editing time
&lt;/h2&gt;

&lt;p&gt;Assuming that all went well, we now have a starting point for what we want to do.&lt;/p&gt;

&lt;p&gt;Now we have a way to authorize with the Youtube Data API and get some information about a given video, its time for the fun stuff. &lt;/p&gt;

&lt;p&gt;Im gonna start of with creating some variables that I want to use, one of them is for referencing the API and the other is to hold the Video ID of which I want to be able to change the title of. &lt;/p&gt;

&lt;p&gt;I uploaded a test video for this use case, but once the script is up and running, you can change it to anything you want ( which is likely what Tom did for his )&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const youtube = google.youtube("v3");
const VIDEO_ID = "NhcZteF-sDE";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next part is that we want to change the function that is called once we are authorized -- in my script, this can be found on &lt;a href="https://github.com/DeepfriedDev/GreatScott/blob/d3528c90697f966244c3fe3779bdd5043bfcdd28/update.js#L23" rel="noopener noreferrer"&gt;line 23&lt;/a&gt; I changed the function call to a new function that we are going to write called &lt;code&gt;makeAuthCall&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This function is going to go out to YouTube and grab the details we want. This is all based on the documentation and also from that bit in Toms video where he flashed the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const makeAuthCall = (auth) =&amp;gt; {
  youtube.videos.list(
    {
      auth: auth,
      id: VIDEO_ID,
      part: "id,snippet,statistics",
    },
    (err, response) =&amp;gt; {
      if (err) {
        console.log(`some shit went wrong ${err}`);
        return;
      }

      if (response.data.items[0]) {
        // We have found the video and the details
        console.log(`We found the video, now updating...`);
        updateVideoTitle(response.data.items[0], auth);
      }
    }
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, when we get a successful response, which is a response that contains some items in the data object, we will then call another function that runs our update to the title of the video and pass through the video object that has videos details and the auth object in the params of the function call.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const updateVideoTitle = (video, auth) =&amp;gt; {
  // get the number of views
  let views = video.statistics.viewCount;
  let likes = video.statistics.likeCount;
  let commentCount = video.statistics.commentCount;

  video.snippet.title = `This video has ${views} views, ${likes} likes and ${commentCount} comments`;

  console.log(`Updating title to ${video.snippet.title}`);

  youtube.videos.update(
    {
      auth: auth,
      part: "snippet,statistics",
      resource: video,
    },
    (err, response) =&amp;gt; {
      console.log(response);
      if (err) {
        console.log(`There was an error updating ${err}`);
        return;
      }
      if (response.data.items) {
        console.log("Done");
      }
    }
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function first assigns some variables to some of the bits we want ( views, likes and comments ) and then we update the video object we passed through to have the new title we want. &lt;/p&gt;

&lt;p&gt;We can then call the update function on the API, passing through the authentication object, the options we want to update in the &lt;code&gt;part&lt;/code&gt; key and then in the resource key we pass back through the updated &lt;code&gt;video&lt;/code&gt; object which contains the update to the title. Upon both error and success we dont do anything -- this is where you might want to handle these situations, I am just choosing not too. &lt;/p&gt;

&lt;h2&gt;
  
  
  Get this on a server ( Digital Ocean )
&lt;/h2&gt;

&lt;p&gt;OK, so now we can test our script locally and it runs just fine. We now want it in a place where it can run every minute or every second...every Tuesday, whenever you want. Im choosing to use Digital Ocean,you can choose any other service you might want to use such as AWS or Linode.&lt;/p&gt;

&lt;p&gt;If you are going to use Digital Ocean and want some free credits, feel free to use this &lt;a href="https://m.do.co/c/5922acee6229" rel="noopener noreferrer"&gt;referral link&lt;/a&gt; you should get $100 in credit.&lt;/p&gt;

&lt;p&gt;The instance we're going to use is a the cheapest $5 a month and under the marketplace tab we're going to use the NodeJS Quickstart.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnme53m4ybhimeibxsg25.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnme53m4ybhimeibxsg25.png" alt="Digital Ocean Droplet Overview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When this is up and running we can SSH into the droplet and get ready to get our script up and running. &lt;/p&gt;

&lt;p&gt;You can get the script onto the machine in a number of ways, I chose to just &lt;code&gt;git clone&lt;/code&gt; from github to the machine, but you might choose to use something like Jenkins, Buddy or any of the other numerous services that are able to take a git repository and drop it onto a Droplet.&lt;/p&gt;

&lt;p&gt;After cloning the repository down and running &lt;code&gt;npm install&lt;/code&gt;, we just need to create the OAUTH credential again by running the script once, but before we do that we need to make sure that our credentials file that we downloaded from Google is in the root. &lt;/p&gt;

&lt;p&gt;This isn't really going to be a file that you want to commit into git and as its not something thats going to change often, we can just recreate the file on the server. I just &lt;code&gt;touch&lt;/code&gt; a new &lt;code&gt;credentials.json&lt;/code&gt; and then copy the contents of the file locally, up to the one on the server. &lt;/p&gt;

&lt;p&gt;Now we can run the script once to go through the OAUTH process again and once thats done, we're ready to set this script up to run as a cron job. &lt;/p&gt;

&lt;h2&gt;
  
  
  Cron job
&lt;/h2&gt;

&lt;p&gt;Cron is just a utility in Linux that allows you to schedule a command to run. &lt;/p&gt;

&lt;p&gt;To add a job to the schedule we add it to a file called a cron tab. We can edit this file by running &lt;code&gt;crontab -e&lt;/code&gt;. The first time you run this you will be asked to select your preferred editor. Select one and you will presented with the crontab file. This contains some commented out details about cron jobs and a handy guide for writing our own. &lt;/p&gt;

&lt;p&gt;The first five integers of a cron job let it know when to schedule:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;min hour dayOfMonth month dayOfWeek&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and then add the command to be run after. You can use Integers or an asterix to represent EVERY minute/day/month etc. Theres a good overview of &lt;a href="https://www.adminschoice.com/crontab-quick-reference" rel="noopener noreferrer"&gt;cron here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have chosen to run the script every minute so mine looks like the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* * * * * node GreatScott/update.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, once its saved, how do we know it works?&lt;/p&gt;

&lt;p&gt;There's a few things you can do. You can have the cron job write to a logfile or have it send an email through setting up a mail service on the server. Me?&lt;/p&gt;

&lt;p&gt;I just head over to the video, click like, wait a minute and ...&lt;/p&gt;

&lt;p&gt;Yup, thats working.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I coded this live on (Twitch)[&lt;a href="https://twitch.tv/DeepfriedDev" rel="noopener noreferrer"&gt;https://twitch.tv/DeepfriedDev&lt;/a&gt;] and the video can be seen below ( warning, its long ).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/SoKwiwamFiU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The code is available on &lt;a href="https://github.com/DeepfriedDev/GreatScott" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>youtube</category>
      <category>node</category>
      <category>api</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
