5

Since Youtube shut down its RSS feeds for searches with it's newest version of the API, I've been trying to recreate them using Google App Script. Here's what I have so far (based off of this tutorial for converting a twitter widget to RSS):

function getSearches(a){
  try{
    var rss,title,link;

    title="Youtube RSS Feed";
    link="http://www.youtube.com";

    var d=ScriptApp.getService().getUrl()+"?"+a;
    rss='<?xml version="1.0"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">';
    rss+='<channel><title>'+title+'</title>';
    rss+='<link>'+link+'</link>';
    rss+='<atom:link href="'+d+'" rel="self" type="application/rss+xml" />';
    rss+='<description>Youtube RSS feed updated on '+new Date()+'.</description>';

    var results = YouTube.Search.list('id, snippet', {
      q: a,
      maxResults: 50,
      order: 'date'
    });

    for(var i = 0; i < results.items.length; i++){
      var item = results.items[i];
      rss += "<item>";
      rss += "<title>" + item.snippet.title + "</title>";
      rss += "<link>http://www.youtube.com/watch?v=" + item.id.videoId + "</link>";
      rss += "<description>" + item.snippet.description + "</description>";
      rss += "<pubDate>" + Utilities.formatDate(new Date(item.snippet.publishedAt), "EDT", "EEE, dd MMM yyyy HH:mm:ss Z") + "</pubDate>";
      rss += "<guid>http://www.youtube.com/watch?v=" + item.id.videoId + "</guid>";
      rss += "</item>";
    }
    rss+="</channel></rss>";
    Logger.log(rss)
    return rss
  }
  catch(e){
    return"Something went wrong. Please retry after few minutes"
  }
}

function doGet(e){
  //var a = e.queryString();
  var a = getSearches("search term");

  return ContentService.createTextOutput(a).setMimeType(ContentService.MimeType.RSS);
}

When I publish this as a web app and test it, the resulting page looks good. I can click the links and they take me to the correct videos. However when I try to subscribe to the feed (using Inoreader in my case), it says that there is no feed found. If I subscribe to the web app url directly in my reader (again, Inoreader), it appears to work; but all of the entries link to the web app, not youtube, and return an error from Google App Script when clicked.

Ideally I want the web app to be able to take an any search term and return the feeds to subscribe to via https://script.google.com/macros/s/LONG_KEY/exec?SEARCH_TERM similar to how the twitter RSS linked above functions. Has anyone had any success with something like this or can give me pointers?

user1535152
  • 256
  • 4
  • 17
  • 1
    Have you set the access to the app? When you click `Deploy as Webapp` down the bottom there is a section saying `Who has access to the app` I often will have another browser running which I have not logged into google to do my testing, so that I know that the access levels are correct. Apart from that if your feed is identical it should just work. – FuzzyJulz May 27 '15 at 23:59
  • I believe I have everything set up correctly. I have authorized the app. Under the permissions, I am executing the app as myself and "Anyone, even anonymous" has access to the app. – user1535152 May 28 '15 at 13:16

2 Answers2

2

How can I make an RSS feed from Youtube search using Google App Script:

Get the latest version of my script at GitHub

function getSearchRSS(query){
  let results = YouTube.Search.list('id, snippet', {
    q: query,
    maxResults: 50,
    order: 'date'
  });

  let encoded_query = encodeURIComponent(query)
  let rss_url = ScriptApp.getService().getUrl() + "?" + encoded_query;

  let channel = XmlService.createElement("channel")
    .addContent(XmlService.createElement("title").addContent(XmlService.createText("Youtube Search RSS Feed: " + query)))
    .addContent(XmlService.createElement("link").addContent(XmlService.createText("https://www.youtube.com/results?search_query=" + encoded_query)))
    .addContent(XmlService.createElement("description").addContent(XmlService.createText("Youtube Search RSS feed for search query '" + query + "' updated on " + (new Date()))))
    .addContent(XmlService.createElement("link", XmlService.getNamespace("atom", "http://www.w3.org/2005/Atom")).setAttribute("rel", "self").setAttribute("href", rss_url));

  for(let i = 0; i < results.items.length; ++i){
    let video = results.items[i];
    let yt_url = "https://www.youtube.com/watch?v=" + video.id.videoId;
    channel.addContent(XmlService.createElement("item")
      .addContent(
        XmlService.createElement("title").addContent(XmlService.createText(video.snippet.title))
      ).addContent(
        XmlService.createElement("link").addContent(XmlService.createText(yt_url))
      ).addContent(
        XmlService.createElement("description").addContent(XmlService.createText(video.snippet.description))
      ).addContent(
        XmlService.createElement("pubDate").addContent(XmlService.createText(Utilities.formatDate(new Date(video.snippet.publishedAt), "EDT", "EEE, dd MMM yyyy HH:mm:ss Z")))
      ).addContent(
        XmlService.createElement("guid").addContent(XmlService.createText(yt_url))
      ))
  }


  return XmlService.getPrettyFormat().format(XmlService.createDocument(
        XmlService.createElement("rss").setAttribute("version", "2.0").addContent(channel)
      ));
}

function doGet(req) {
  let query = decodeURIComponent(req.queryString);
  return ContentService.createTextOutput(getSearchRSS(query))
    .setMimeType(ContentService.MimeType.RSS)
}

How to use this script:

To deploy:

  1. Create script on https://script.google.com/
  2. Paste code to new script
  3. Resources -> Advanced Google Services -> enable YouTube Data API
  4. Publish -> As an web app
  5. Grab generated URL, add search query on the end of URL, prepending it with "?" mark.
  6. Done.

Every change in code requires you to add new project version in deploy window:

For example:

URL from deploy tab: https://script.google.com/macros/s/BLABLABLA/exec

Search query I want this to generate: #hot16challenge2

URL-encoded version of this query: %23hot16challenge2

Final URL responding with RSS based on this query:

https://script.google.com/macros/s/BLABLABLA/exec?%23hot16challenge2

somebadhat
  • 744
  • 1
  • 5
  • 17
JuniorJPDJ
  • 21
  • 3
0

So it would appear that my problem was the version of the published web app. I was not aware that not incrementing the version would cache the app as it was when it was first published under that revision. I noticed that code changes were showing up when I was testing the app; but when looking at the published url output, they were not present.

File > Manage Versions allowed me to increment the version number and then the changes started showing up and I was able to subscribe to the feed.

user1535152
  • 256
  • 4
  • 17