问题
I'm trying to make a simple chatbot which will send a message whenever a certain channel uploads a video, ideally with the video's name and a hyperlink to the video.
YouTube's API is very strange, I haven't the slightest idea how to approach this.
This is what I have so far:
using System;
using System.Linq;
using Google.Apis.Services;
using Google.Apis.YouTube.v3;
YouTubeService service = new YouTubeService(new BaseClientService.Initializer() {
ApiKey = apiKey,
ApplicationName = "GoodApp"
});
var getChannel = service.Channels.List("snippet");
getChannel.Id = channelId;
var response = getChannel.Execute();
var channel = response[0]; //now what?
回答1:
Using the YouTube PubSubHubbub service you can get push notifications when a channel uploads new videos, changes a video's title, or changes a video's description. Quote from that page about setting it up:
- Set up a callback server that can handle incoming Atom feed notifications.
- Use the Google hub to subscribe to receive push notifications:
- Set the mode to
subscribe
. (Or set the mode tounsubscribe
to cancel a subscription.)- Set the callback URL to the URL that you set up in step 1.
- Set the topic URL to
https://www.youtube.com/xml/feeds/videos.xml?channel_id=CHANNEL_ID
, whereCHANNEL_ID
is the YouTube channel ID for which you want to retrieve push notifications.- Process notifications sent to your callback server. [...]
Unfortunately a callback server is more than a few lines of code, and it depends on what kind of server you're running. If you know PHP, AppEngine, or Go, the subscriber repositories on PubSubHubbub may be helpful, otherwise search engines seem to have good results for me.
回答2:
I gave up on Google's .NET API because it seems too arcane for my simple mind.
Instead, I decided to access the API directly from the web using RestSharp, and parse the response using JSON.
I then set a System.Timers.Timer
to check every 5 minutes (the channel uploads every 30 minutes, but will vary timings) for videos that it has not already checked.
RestClient restClient = new RestClient("https://www.googleapis.com/youtube/v3/");
DateTime lastTimeChecked = DateTime.Now;
Timer timer = new Timer(60 * 5 * 1000);
refreshTimer.Elapsed += CheckVideos;
refreshTimer.Start();
public static void CheckVideos(object source = null, ElapsedEventArgs e = null) {
var request = new RestRequest(String.Format(
"search?part=snippet&channelId={0}&maxResults=4&order=date&type=video&key={1}",
channelId,
apiKey
), Method.GET);
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
var queryResult = restClient.Execute(request);
YouTubeResponse response = JsonConvert.DeserializeObject<YouTubeResponse>(queryResult.Content);
foreach (var video in response.items.Reverse<Item>()) {
if (video.snippet.publishedAt > lastCheckTime) { //actual code to compare is much longer...
SendMessage(String.Format("Video {0} was uploaded!", video.snippet.title));
}
}
LastCheckTime = DateTime.Now;
}
This is nowhere near perfect, it often will drop videos if the timing of the video's upload is unlucky. Obviously, an event-based solution would be optimal.
来源:https://stackoverflow.com/questions/37913009/how-to-call-a-function-when-a-youtube-user-uploads-a-video