Detect videos with Youtube playback restriction - python

I am developing a web service using python and i want to filter out the videos which can not be played outside of the youtube page .
Like on this link [https://www.youtube.com/v/SC3pupLn-_8?version=3&f=videos&app=youtube_gdata]
you have to watch video on the youtube page is there is any way of filter which videos belong to the same category. So that i choose only those videos which can be played without any restriction.
import gdata.youtube.service
#------------------------------------------------------------------------------
yt_service = gdata.youtube.service.YouTubeService()
yt_service.developer_key = 'YOUR API DEVELOPER KEY'
count=0
def PrintEntryDetails(entry):
if entry.media.category[0].text == "Movies" :
global count
count = count + 1
if entry.noembed != None:
print 'Video embedding not enable: %s' % entry.noembed.text
else :
print "entry embedable"
print 'Video title: %s' % entry.media.title.text
print 'Video category: %s' % entry.media.category[0].text
print 'Video published on: %s ' % entry.published.text
print 'Video description: %s' % entry.media.description.text
if entry.media.private != None :
print entry.media.private.text
else :
print "Right not found"
if entry.media.keywords :
print 'Video tags: %s' % entry.media.keywords.text
print 'Video watch page: %s' % entry.media.player.url
print 'Video flash player URL: %s' % entry.GetSwfUrl()
print 'Video duration: %s' % entry.media.duration.seconds
# For video statistics
if entry.statistics :
print 'Video view count: %s' % entry.statistics.view_count
# For video rating
if entry.rating :
print 'Video rating: %s' % entry.rating.average
# show alternate formats
for alternate_format in entry.media.content:
if 'isDefault' not in alternate_format.extension_attributes:
print 'Alternate format: %s | url: %s ' % (alternate_format.type,
alternate_format.url)
# show thumbnails
for thumbnail in entry.media.thumbnail:
print 'Thumbnail url: %s' % thumbnail.url
print "#########################################"
else :
pass
def PrintVideoFeed(feed):
counter = 0
for entry in feed.entry:
PrintEntryDetails(entry)
counter = counter+1
#print counter
def SearchAndPrint():
max = 20
yt_service = gdata.youtube.service.YouTubeService()
query = gdata.youtube.service.YouTubeVideoQuery()
# OrderBy must be one of: published viewCount rating relevance
query.orderby = "relevance"
query.racy = 'include'
query.author = "tseries"
query.max_results = 50
index = 01
for i in (range(max)):
query.start_index = index
index = index + 50
query.format = "5"
feed = yt_service.YouTubeQuery(query)
PrintVideoFeed(feed)
SearchAndPrint()
print "**********************************************************"
print "Total Movies"
print count

The general answer is to use the format=5 parameter when performing your search: https://developers.google.com/youtube/2.0/reference#formatsp
That will filter out videos from the search results that have embedding disabled completely.
That being said, there are videos that have embedding enabled but only are playable in certain regions or when embedded on certain domains.
To handle the regional restrictions, you should set the restriction= parameter to something appropriate for your use case, as described at https://developers.google.com/youtube/2.0/reference#restrictionsp
There is no way to exclude videos from search results that have domain-level embed restrictions, though.
This blog post has more general information about embedded playback restrictions: http://apiblog.youtube.com/2011/12/understanding-playback-restrictions.html

If I understand your question, you're looking for the app:control/yt:state tag. For example, if a video is restricted to playing on the YouTube site, but you're trying to access it through an embedded URL or through a non-browser, you'll get back something like this:
<app:control>
<yt:state name="restricted" reasonCode="limitedSyndication">Syndication of this video was restricted.</yt:state>
</app:control>
You can see this in your entry object as:
entry.control.FindExtensions('state')[0].attributes
Which will be:
{'name': 'restricted', 'reasonCode': 'limitedSyndication'}
Of course you need to make this more robust—control may be None, it may have no state tags, etc. But you get the idea.
I don't think you can directly search on the presence or absence or particular value of state, but you can use the fields parameter to post-filter the results before retrieving them. The docs actually give the example of returning only "entries that do not restrict playback in any way, which is indicated by the presence of the <yt:state> element":
entry[not(app:control/yt:state)]
I've left off the (title,media:group) part because you want the default tags, not a limited set.
For some reason, the fields parameter doesn't always get sent. This may be because, as the docs say, "The fields parameter is currently used for experimental features only." But anyway, you can just retrieve everything and filter on control yourself.

Related

Call a range of dates from an API using Python

Currently writing a program using an API from MarketStack.com. This is for school, so I am still learning.
I am writing a stock prediction program using Python on PyCharm and I have written the connection between the program and the API without issues. So, I can certainly get the High, Name, Symbols, etc. What I am trying to do now is call a range of dates. The API says I can call up to 30 years of historical data, so I want to call all 30 years for a date that is entered by the user. Then the program will average the high on that date in order to give a trend prediction.
So, the problem I am having is calling more than one date. As I said, I want to call all 30 dates, and then I will do the math, etc.
Can someone help me call a range of dates? I tried installing Pandas and that wasn't being accepted by PyCharm for some reason.. Any help is greatly appreciated.
import tkinter as tk
import requests
# callouts for window size
HEIGHT = 650
WIDTH = 600
# function for response
def format_response(selected_stock):
try:
name1 = selected_stock['data']['name']
symbol1 = selected_stock['data']['symbol']
high1 = selected_stock['data']['eod'][1]['high']
final_str = 'Name: %s \nSymbol: %s \nEnd of Day ($ USD): %s' % (name1, symbol1, high1)
except:
final_str = 'There was a problem retrieving that information'
return final_str
# function linking to API
def stock_data(entry):
params = {'access_key': 'xxx'}
response = requests.get('http://api.marketstack.com/v1/tickers/' + entry + '/' + 'eod', params=params)
selected_stock = response.json()
label2['text'] = format_response(selected_stock)
# function for response
def format_response2(stock_hist_data):
try:
name = stock_hist_data['data']['name']
symbol = stock_hist_data['data']['symbol']
high = stock_hist_data['data']['eod'][1]['high']
name3 = stock_hist_data['data']['name']
symbol3 = stock_hist_data['data']['symbol']
high3 = stock_hist_data['data']['eod'][1]['high']
final_str2 = 'Name: %s \nSymbol: %s \nEnd of Day ($ USD): %s' % (name, symbol, high)
final_str3 = '\nName: %s \nSymbol: %s \nEnd of Day ($ USD): %s' % (name3, symbol3, high3)
except:
final_str2 = 'There was a problem retrieving that information'
final_str3 = 'There was a problem retrieving that information'
return final_str2 + final_str3
# function for response in lower window
def stock_hist_data(entry2):
params2 = {'access_key': 'xxx'}
response2 = requests.get('http://api.marketstack.com/v1/tickers/' + entry2 + '/' + 'eod', params=params2)
hist_data = response2.json()
label4['text'] = format_response2(hist_data)

How to get user story points using pyral?

I am trying to modify the statecounts.py from pyral examples to pull all the defined/accepted/in progress/completed stories point for each release. I am keep getting query exception error. Is there anything that I have missed?
state = 'ScheduleState'
state_values = rally.getAllowedValues('HierarchicalRequirement', state)
output = []
for rel in sorted(release_names):
for state_value in sorted(state_values):
response = rally.get(artifact_type, fetch="FormattedID", query='(Release.Name= %s ) AND %s = %s' % (rel, state, state_value),
projectScopeUp=False, projectScopeDown=False)
output.append("%20s : %16s : %5d" % (rel, state, state_value, response.resultCount))
Thanks!!!
If you are ANDing multiple terms it's easiest to create a list of terms like so:
query=['Release.Name = %s' % (rel), '%s = %s' % (state, state_value)]
Also, whitespace matters. You were missing a space before the first =.

Python Logging: Evaluate Time before adding a new entry

I am editing a python-script to control home appliances (sonos, hue etc.) with the log of a plex mediaserver.
So far things went well, now i am struggeling with a question i could not find an answer to. These are my first steps, please bear with me.
I have a log file, which collects session information in this format:
...
2014-09-13 14:40:02 johnedoe is watching 30c3 Keynote
2014-09-13 14:48:06 thomas is watching Band of Brothers
2014-09-13 15:28:03 johnedoe is watching The Zero Theorem
...
if a new session is detected, the script evaluates if the part "johnedoe is watching 30c3 Keynote" is already present. i would like to include a timestamp-check, which would not only examine if the session is present, but also if a already logged session is older than two hours.
In pseudocode: if (alert not in log) or (if alert in log and older than two hours):
Can i access the corresponding timestamp directly, or to i have to regex the line? Any help is greatly appreciated. Many thanks in advance.
This is the tail of code:
logLocation = '/storage/downloads/plexMon.log'
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S', filename=logLocation, level=logging.INFO)
log = open(logLocation).read()
server = urllib2.urlopen('http://127.0.0.1:32400/status/sessions')
data = server.read()
server.close()
tree = ET.fromstring(data)
for video in tree.iter('Video'):
show = video.get('grandparentTitle')
episode = video.get('title')
if show == "None":
title = episode
else:
title = '%s - %s' % (show, episode)
user = video.find('User').get('title').split('#')[0]
alert = '%s is watching %s' % (user, title)
if alert not in log:
logging.info(alert)
if all(i not in alert for i in ignoreAlertList):
sendAlert(alert)
if user == "johnedoe":
b = Bridge('192.168.1.109')
b.set_light(1, 'bri', 50)
my_zone = SoCo('192.168.1.105')
my_zone.unjoin()
my_zone.pause()
Without regexes, this may be easier to achieve, if you use:
log_lines = open(logLocation).readlines() # read log files as a list[] of lines
instead of:
log = open(logLocation).read()
and then use something like:
for line in log_lines:
if(line.__contains__(alert)):
partsOfLine = str(line).split()
dateParts = str(partsOfLine[0]).split("-")
timeParts = str(partsOfLine[1]).split(":")
alerttime = datetime.datetime(int(dateParts[0]),int(dateParts[1]),int(dateParts[2]),int(timeParts[0]),int(timeParts[1]),int(timeParts[2]))
timediff_in_min = (alerttime - datetime.now()).total_seconds()/60
if(timediff_in_min >= 120):
print "ignoring older than 2 hours"
else:
print "new alert in the last 2 hours"

How can I unit test django messages?

In my django application, I'm trying to write a unit test that performs an action and then checks the messages in the response.
As far as I can tell, there is no nice way of doing this.
I'm using the CookieStorage storage method, and I'd like to do something similar to the following:
response = self.client.post('/do-something/', follow=True)
self.assertEquals(response.context['messages'][0], "fail.")
The problem is, all I get back is a
print response.context['messages']
<django.contrib.messages.storage.cookie.CookieStorage object at 0x3c55250>
How can I turn this into something useful, or am I doing it all wrong?
Thanks,
Daniel
I found a really easy approach:
response = self.client.post('/foo/')
messages = list(response.context['messages'])
self.assertEqual(len(messages), 1)
self.assertEqual(str(messages[0]), 'my message')
If you need to check for messages on a response that has no context you can use the following:
from django.contrib.messages import get_messages
messages = list(get_messages(response.wsgi_request))
self.assertEqual(len(messages), 1)
self.assertEqual(str(messages[0]), 'my message')
The fallback storage doesn't support indexing, however it is an iterable.
From django documentation:
Outside of templates, you can use get_messages()
So, you could write something like:
from django.contrib.messages import get_messages
[...]
messages = [m.message for m in get_messages(response.wsgi_request)]
self.assertIn('My message', messages)
This works for me (displays all messages):
print [m.message for m in list(response.context['messages'])]
Also here are a couple of utility methods I have in a test class inherited from Django's TestCase. If you'd prefer to have them as functions, remove the self arguments and replace self.fail()'s with a raise.
def assert_message_count(self, response, expect_num):
"""
Asserts that exactly the given number of messages have been sent.
"""
actual_num = len(response.context['messages'])
if actual_num != expect_num:
self.fail('Message count was %d, expected %d' %
(actual_num, expect_num))
def assert_message_contains(self, response, text, level=None):
"""
Asserts that there is exactly one message containing the given text.
"""
messages = response.context['messages']
matches = [m for m in messages if text in m.message]
if len(matches) == 1:
msg = matches[0]
if level is not None and msg.level != level:
self.fail('There was one matching message but with different'
'level: %s != %s' % (msg.level, level))
return
elif len(matches) == 0:
messages_str = ", ".join('"%s"' % m for m in messages)
self.fail('No message contained text "%s", messages were: %s' %
(text, messages_str))
else:
self.fail('Multiple messages contained text "%s": %s' %
(text, ", ".join(('"%s"' % m) for m in matches)))
def assert_message_not_contains(self, response, text):
""" Assert that no message contains the given text. """
messages = response.context['messages']
matches = [m for m in messages if text in m.message]
if len(matches) > 0:
self.fail('Message(s) contained text "%s": %s' %
(text, ", ".join(('"%s"' % m) for m in matches)))
Update
My original answer was written when django was still 1.1 or so. This answer is no longer relevant. See #daveoncode's answer for a better solution.
Original Answer
I did an experiment to test this. I changed the MESSAGE_STORAGE setting in one of my projects to 'django.contrib.messages.storage.cookie.CookieStorage' and executed a test that I had written to check for messages. It worked.
The key difference from what you were doing is the way I retrieved messages. See below:
def test_message_sending(self):
data = dict(...)
response = self.client.post(reverse('my_view'), data)
messages = self.user.get_and_delete_messages()
self.assertTrue(messages)
self.assertEqual('Hey there!', messages[0])
This may be worth a try.
I created a python class to simplify messages testing :
class TestMessageCase(TestCase):
""" class inherited from TestCase to add a function to test messages response """
def assertMessageContains(self, response, messages_list, debug=False):
"""
Function to test messages returned by the response view
:param response: The response of the view
:param messages_list: An ordered list of messages to test
:type messages_list: list of string
:param debug: Show all response messages
:type debug: bool
"""
response_messages = list(response.context['messages'])
if debug:
print(
" ---------------------------------------------------------------------\n",
"| DEBUG MESSAGES RETURNED BY THE RESPONSE |\n",
"---------------------------------------------------------------------"
)
for i in range(len(response_messages)):
print(f"Message n°{i + 1} :\n{response_messages[i]}\n\n")
print(
" ---------------------------------------------------------------------\n",
"| END DEBUG |\n",
"---------------------------------------------------------------------"
)
self.assertEqual(len(response_messages), len(messages_list))
for i in range(len(response_messages)):
self.assertEqual(str(response_messages[i]), messages_list[i])
And in test function :
response = self.client.post('/foo/')
self.assertMessageContains(response, ["Foo"])
Simpler version of the stalemate one:
class TestCaseMessagesMixture(object):
def assertMessageCount(self, response, expect_num):
"""
Asserts that exactly the given number of messages have been sent.
"""
actual_num = len(response.context['messages'])
if actual_num != expect_num:
self.fail('Message count was %d, expected %d' %
(actual_num, expect_num)
)
def assertMessageEqual(self, response, text):
"""
Asserts that the response includes the message text.
"""
messages = [m.message for m in response.context['messages']]
if text not in messages:
self.fail(
'No message with text "%s", messages were: %s' %
(text, messages)
)
def assertMessageNotEqual(self, response, text):
"""
Asserts that the response does not include the message text.
"""
messages = [m.message for m in response.context['messages']]
if text in messages:
self.fail(
'Message with text "%s" found, messages were: %s' %
(text, messages)
)
Test helpers for validation of response messages count and content
def get_response_messages(self, response):
from django.contrib.messages import get_messages
return list(get_messages(response.wsgi_request))
def check_response_messages(self, response, message_index=None, message_value=None, exp_count=None):
messages = self.get_response_messages(response)
if exp_count is not None:
self.assertEqual(len(messages), exp_count)
if message_index is not None:
message = messages[message_index]
self.assertIn(message_value, str(message))
Can be used like this
message_value = "You can not switch to another type of account"
self.check_response_messages(response, exp_count=1, message_index=0, message_value=message_value)

youtube data api comment paging

I'm struggling a little bit with the syntax for iterating through all comments on a youtube video. I'm using the python and have found little documentation on the GetYouTubeVideoCommentFeed() function.
What I'm really trying to do is search all comments of a video for an instance of a word and increase a counter (eventually the comment will be printed out). It functions for the 25 results returned, but I need to access the rest of the comments.
import gdata.youtube
import gdata.youtube.service
video_id = 'hMnk7lh9M3o'
yt_service = gdata.youtube.service.YouTubeService()
comment_feed = yt_service.GetYouTubeVideoCommentFeed(video_id=video_id)
for comment_entry in comment_feed.entry:
comment = comment_entry.content.text
if comment.find('hi') != -1:
counter = counter + 1
print "hi: "
print counter
I tried to set the start_index of GetYouTubeVideoCommentFeed() in addition to the video_id but it didn't like that.
Is there something I'm missing?
Thanks!
Steve
Here's the code snippet for the same:
# Comment feed URL
comment_feed_url = "http://gdata.youtube.com/feeds/api/videos/%s/comments"
''' Get the comment feed of a video given a video_id'''
def WriteCommentFeed(video_id, data_file):
url = comment_feed_url % video_id
comment_feed = yt_service.GetYouTubeVideoCommentFeed(uri=url)
try:
while comment_feed:
for comment_entry in comment_feed.entry:
print comment_entry.id.text
print comment_entry.author[0].name.text
print comment_entry.title.text
print comment_entry.published.text
print comment_entry.updated.text
print comment_entry.content.text
comment_feed = yt_service.Query(comment_feed.GetNextLink().href)
except:
pass
Found out how to do it. Instead of passing a video_id to the GetYouTubeVideoCommentFeed function, you can pass it a URL. You can iterate through the comments by changing the URL parameters.
There must be an API limitation though; I can only access the last 1000 comments on the video.

Categories

Resources