Getting videos from Youtube official Channels - java

There are some Youtube official channels like Music, Games, News, etc. I'm trying to get the information of this channels like if it's a normal channel but it's sending me null responses. It might be because the channel videos are not owned by the channel even if it shows you them as "uploaded videos". This is my code which works with "normal" channels: (String ids means the id of each video comma separated)
This method gives the videos of the channel videos and it's working with "normal" channels.
public static ArrayList<VideoYoutube> getVideos (String ids) throws IOException
{
try
{
YouTube.Videos.List videos = youtube.videos().list("id,snippet,statistics");
videos.setKey(API_KEY);
//Setting all the video ids we want to get back
videos.setId(ids);
videos.setMaxResults(RETURN_NUMBER);
//Setting all the fields we want to be called from the api. Its such an
videos.setFields("items(id,snippet/publishedAt,snippet/title,snippet/description," +
"snippet/thumbnails/default/url,snippet/thumbnails/medium/url,snippet/thumbnails/high/url," +
"snippet/channelId,snippet/channelTitle,statistics/viewCount,statistics/likeCount,statistics/dislikeCount," +
"statistics/favoriteCount,statistics/commentCount)");
VideoListResponse videoResponse = videos.execute();
List<Video> videoResultList = videoResponse.getItems();
}
And this is the method that is supposed to retrieve the video ids from the channel I want. It's giving null for this exact channel but it's working with "normal" channels.
public static String getChannelVideosIds(String channelId) throws IOException
{
YouTube.Search.List search = youtube.search().list("id");
//Define the search key
search.setKey(API_KEY);
search.setChannelId(channelId);
//Give the type (video, playlist or channel)
search.setType("video");
//Giving the params we want to be returned comma separated (for example if we had chosen the snipped before, we could choose snipped fields like snipped/publishedAt)
search.setFields("items(id)");
//Set the max return number
search.setMaxResults(RETURN_NUMBER);
//Execute the search query
SearchListResponse searchResponse = search.execute();
List<SearchResult> searchResultList = searchResponse.getItems();
//Check if the result is null
return retrieveIds(searchResultList);
}

Related

How do you get the comments of a video using the YouTube Java Client API when given the video ID?

I am looking to write code that takes a video ID as input and retrieves the comments made on the corresponding video. Here's a link to the API docs. I tried this code
String videoId = "id";
YouTube.Comments.List list2 = youtube.comments().list(Arrays.asList("snippet"));
list2.setId(Arrays.asList(videoId));
list2.setKey(apiKey);
Comment c = list2.execute().getItems().get(0);
but I get an IndexOutOfBoundsException on the last line because getItems is returning an empty List. I set videoId as a valid YouTube video ID (one which I have already successfully been able to get video data like views, title, etc from), thinking that would work but clearly I was wrong. Unless I missed something I can't find anything in the docs for the Video class about getting comment data, so that's why I'm turning to SO for help again.
EDIT: Per stvar's comment I tried changing the second line of the above code to
YouTube.CommentThreads.List list2 = youtube.commentThreads().list(Arrays.asList("snippet"));
and of course changed the type of c to CommentThread.
It is the CommentThreads API I'm supposed to use, right? Either way, this is also returning an empty list...
Here is the complete Java code that retrieves all comments (top-level and replies) of any given video:
List<Comment> get_comment_replies(
YouTube youtube, String apiKey, String commentId)
{
YouTube.Comments.List request = youtube.comments()
.list(Arrays.asList("id", "snippet"))
.setParentId(commentId)
.setMaxResults(100)
.setKey(apiKey);
List<Comment> replies = new ArrayList<Comment>();
String pageToken = "";
do {
CommentListResponse response = request
.setPageToken(pageToken)
.execute();
replies.addAll(response.getItems());
pageToken = response.getNextPageToken();
} while (pageToken != null);
return replies;
}
List<CommentThread> get_video_comments(
YouTube youtube, String apiKey, String videoId)
{
YouTube.CommentThreads.List request = youtube.commentThreads()
.list(Arrays.asList("id", "snippet", "replies"))
.setVideoId(videoId)
.setMaxResults(100)
.setKey(apiKey);
List<CommentThread> comments = new ArrayList<CommentThread>();
String pageToken = "";
do {
CommentThreadListResponse response = request
.setPageToken(pageToken)
.execute();
for (CommentThread comment : respose.getItems()) {
CommentThreadReplies replies = comment.getReplies();
if (replies != null &&
replies.getComments().size() !=
comment.getSnippet().getTotalReplyCount())
replies.setComments(get_comment_replies(
youtube, apiKey, comment.getId()));
}
comments.addAll(response.getItems());
pageToken = response.getNextPageToken();
} while (pageToken != null);
return comments;
}
You'll have to invoke get_video_comments, passing to it the ID of the video of your interest. The returned list contains all top-level comments of that video; each top-level comment has its replies property containing all the associated comment replies.

Downloading attachments from unseen messages

I work on university project in java. I have to download attachments from new emails using GMAIL API.
I successfully connected to gmail account using OAuth 2.0 authorization.
private static final List<String> SCOPES = Collections.singletonList(GmailScopes.GMAIL_READONLY);
I tried to get unseen mails using
ListMessagesResponse listMessageResponse = service.users().messages().list(user).setQ("is:unseen").execute();
listMessageResponse is not null but when I call method .getResultSizeEstimate() it returns 0
also I tried to convert listMessageResponse to List < Message > (I guess this is more usable) using
List<Message> list = listMessageResponse.getMessages();
But list launches NullPointerException
Then tried to get each attachment with
for(Message m : list) {
List<MessagePart> part = m.getPayload().getParts();
for(MessagePart p: part) {
if(p.getFilename()!=null && p.getFilename().length()>0) {
System.out.println(p.getFilename()); // Just to check attachment filename
}
}
}
Is my approach correct (if not how to fix it) and how should I download those attachments.
EDIT 1:
Fixed q parameter, I mistakenly wrote is:unseen instead of is:unread.
Now app reaches unread mails successfully.
(For example there was two unread mails and both successfully reached, I can get theirs IDs easy).
Now this part trows NullPointerException
List<MessagePart> part = m.getPayload().getParts();
Both messages have attachments and m is not null (I get ID with .getID())
Any ideas how to overcome this and download attachment?
EDIT 2:
Attachments Downloading part
for(MessagePart p : parts) {
if ((p.getFilename() != null && p.getFilename().length() > 0)) {
String filename = p.getFilename();
String attId = p.getBody().getAttachmentId();
MessagePartBody attachPart;
FileOutputStream fileOutFile = null;
try {
attachPart = service.users().messages().attachments().get("me", p.getPartId(), attId).execute();
byte[] fileByteArray = Base64.decodeBase64(attachPart.getData());
fileOutFile = new FileOutputStream(filename); // Or any other dir
fileOutFile.write(fileByteArray);
fileOutFile.close();
}catch (IOException e) {
System.out.println("IO Exception processing attachment: " + filename);
} finally {
if (fileOutFile != null) {
try {
fileOutFile.close();
} catch (IOException e) {
// probably doesn't matter
}
}
}
}
}
Downloading working like charm, tested app with different type of emails.
Only thing left is to change label of unread message (that was reached by app) to read. Any tips how to do it?
And one tiny question:
I want this app to fetch mails on every 10 minutes using TimerTask abstract class. Is there need for manual "closing" of connection with gmail or that's done automatically after run() method iteration ends?
#Override
public void run(){
// Some fancy code
service.close(); // Something like that if even exists
}
I don't think ListMessagesResponse ever becomes null. Even if there are no messages that match your query, at least resultSizeEstimate will get populated in the resulting response: see Users.messages: list > Response.
I think you are using the correct approach, just that there is no message that matches your query. Actually, I never saw is:unseen before. Did you mean is:unread instead?
Update:
When using Users.messages: list only the id and the threadId of each message is populated, so you cannot access the message payload. In order to get the full message resource, you have to use Users.messages: get instead, as you can see in the referenced link:
Note that each message resource contains only an id and a threadId. Additional message details can be fetched using the messages.get method.
So in this case, after getting the list of messages, you have to iterate through the list, and do the following for each message in the list:
Get the message id via m.getId().
Once you have retrieved the message id, use it to call Gmail.Users.Messages.Get and get the full message resource. The retrieved message should have all fields populated, including payload, and you should be able to access the corresponding attachments.
Code sample:
List<Message> list = listMessageResponse.getMessages();
for(Message m : list) {
Message message = service.users().messages().get(user, m.getId()).execute();
List<MessagePart> part = message.getPayload().getParts();
// Rest of code
}
Reference:
Class ListMessagesResponse
Users.messages: list > Response

Size of RSS feed

I'm using ROME to generate a feed from data in my database.
In all the samples I found, the Servlet extracts all the data from the database, and sends it as a feed.
Now, if the database contains thousands of entries, how many entries should I send?
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
SyndFeed feed = getFeed(request);
String feedType = request.getParameter("type");
feedType = feedType != null ? feedType : defaultType;
feed.setFeedType(feedType);
response.setContentType("application/xml; charset=UTF-8");
SyndFeedOutput output = new SyndFeedOutput();
output.output(feed, response.getWriter());
} catch (FeedException ex) {
String msg = "Could not generate feed";
log(msg, ex);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg);
}
}
protected SyndFeed getFeed(HttpServletRequest request) {
// **** Here I query the database for posts, but I don't know how many
// I should fetch or where should I stop? ***
List<Post> posts = getPosts();
SyndFeed feed = new SyndFeedImpl();
feed.setTitle("My feed");
feed.setLink("http://myurl");
feed.setDescription("my desc");
// create the feeds.Each tutorial will be a feed entry
List<SyndEntry> entries = new ArrayList<SyndEntry>();
for (Post post : posts) {
SyndEntry entry = new SyndEntryImpl();
SyndContent description;
String title = post.getTitle();
String link = post.getLink();
entry.setTitle(title);
entry.setLink(link);
// Create the description of the feed entry
description = new SyndContentImpl();
description.setType("text/plain");
description.setValue(post.getDesc());
entry.setDescription(description);
entries.add(entry);
}
feed.setEntries(entries);
return feed;
}
There really isn't a single way to do this that all rss clients will support, but i would recommend checking out rfc 5005 appendix B, you'll at least have a referenxe to give to clients. https://www.rfc-editor.org/rfc/rfc5005#appendix-B
so long as your default query always shows the latest (page length you define) items, sorted descending, all clients will appear correct. Clients that need to be able to page can implement this standard.
I suggest a paging system. the user makes a request for page 0 to take 30 items. then the user makes a request for page 1 to take the next 30 items. first request: items 0->29, second request: items 30->59. to model this have a integer variable called skip keep track of what position to start at, for instance:
int skip = page * numItems; // first request: 0 * 30 (starts at 0), sec request: 1 * 30 (starts at 30)
So you will skip so many items and take only the value of numItems. Then the client requests for however many feed items the client wants at once.

Smack - How to read a MultiUserChat's configuration?

I tried to create a multiuserchat with Java. I'm using smack library.
Here is my code to create multiuserchat:
MultiUserChat muc = new MultiUserChat(connection, "roomname#somehost");
muc.create("mynickname");
Form form = muc.getConfigurationForm();
Form submitForm = form.createAnswerForm();
submitForm.setAnswer("muc#roomconfig_roomname", "A nice formatted Room Name");
submitForm.setAnswer("muc#roomconfig_roomdesc", "The description. It should be longer.");
muc.sendConfigurationForm(submitForm);
muc.addMessageListener(mucMessageListener); // mucMessageListener is a PacketListener
Then, I tried to capture the message sent by this room created above using mucMessageListener:
private PacketListener mucMessageListener = new PacketListener() {
public void processPacket(Packet packet) {
if (packet instanceof Message) {
Message message = (Message) packet;
// this is where I got the problem
}
}
}
As the message received by other part (the user who is not the owner of this multiuserchat), can he somehow get the value set in this line above:
submitForm.setAnswer("muc#roomconfig_roomname", "A nice formatted Room Name");
You see, getting just the JID of the room is not really good for the view. I expect I could have a String which value is "A nice formatted Room Name".
How can we get that?
You can easily get its configurations like name and etc from this code:
MultiUserChatManager mucManager = MultiUserChatManager.getInstanceFor(connection);
RoomInfo info = mucManager.getRoomInfo(room.getRoom());
now you can get its informations like this:
String mucName = info.getName();
Boolean isPersistence = info.isPersistent();
and etc.
Retrieving the value of muc#roomconfig_romname is described in XEP-45 6.4. Smack provides the MultiUserChat.getRoomInfo() method to perform the query.
RoomInfo roomInfo = MultiUserChat.getRoomInfo(connection, "roomname#somehost.com")
String roomDescription = roomInfo.getDescription()
If you want to read a value of var for example title name of room in config
Form form = chat.getConfigurationForm();
String value = form.getField("muc#roomconfig_roomname").getValues().next();
then do what ever you want with value..

Get an array of user photos using FQL

I'm to get a list of the users photos (one's they've been tagged in) using FQL.
Basically I've go an array object like so: _imageAddressArray.
I can retrieve the users' photos using graphApi so I know it works, problem with graphAPi is that it's too slow (+15 seconds min for 100 photos).
So far I've got:
//New Stuff
FQL fql = new FQL(facebook);
String FQLResult = null;
try
{
_userGallery = graphApi.getPhotosMy(_noOfPhotos);
FQLResult = fql.fqlQuery("SELECT object_id, src_small FROM photo");
}
catch (EasyFacebookError e)
{
e.printStackTrace();
}
System.out.println("FQL Result" + FQLResult);
This returns the error: 601, any ideas anyone?
Of course ideally FQLResult will be a string[] (string array)
You're getting an error because you don't have a WHERE clause in your FQL statement that references one of the indexed columns -- shown with a "*" here
To get the photos using FQL that your user has been tagged in, try this:
SELECT object_id, src_small FROM photo WHERE object_id IN
(SELECT object_id FROM photo_tag WHERE subject = me())

Categories