def setUp(self):
		self.source = Source.objects.create(name='CNN-IBN Top Stories', link='http://www.ibnlive.com/xml/top.xml')
		self.user = NTUser.objects.create_user(name='Karthik', email='*****@*****.**', password='******')
		#A default tab will automatically be created with CNN-IBN Top Stories as the source
		self.tab = get_object_or_none(Tab, user=self.user, name='Headlines')
		if self.tab:
			self.tabsource = get_object_or_none(TabSource, tab=self.tab, source=self.source)
Example #2
0
def remove_source(request, tab_id, source_name):
    logger.info("remove_source ajax request received(tab_id=%s, source_name=%s)" % (str(tab_id), str(source_name)))

    success = False
    tab = get_object_or_none(Tab, user=request.user, id=tab_id)
    if tab:
        source = get_object_or_none(Source, name=source_name)
        if source:
            if tab.delete_source(source):
                logger.debug("Removed %s from tab(%s)" % (str(source), str(tab)))
                success = True

    logger.info("Sending response(remove_source)")
    return simplejson.dumps({"success": success})
Example #3
0
def get_tab_tags(request, tab_id):
	tab = get_object_or_none(Tab, id=tab_id, user=request.user)
	tags = []
	if tab:
		tags = [tag.name for tag in tab.tags.all()]
	
	return simplejson.dumps({ "tags": tags })
	def add_tag(self, tag_name):
		'''
		Adds a tag to this article. If the tag already exists, it adds the tag to this article 
		'''
		tag = tag_name.strip().lower()
		db_tag = get_object_or_none(Tag, name=tag_name)
		if db_tag is not None:
			tag = db_tag
		self.tags.add(tag)
	def change_source_priority(self, source, priority):
		'''
		Changes the priority of the source to the specified priority. Returns the new priority is successful, None if unsuccessful
		'''
		tabsource = get_object_or_none(TabSource, tab=self, source=source)
		if tabsource:
			tabsource = tabsource.change_priority(priority)
			self.clear_cache()
		return tabsource
Example #6
0
def change_source_position(request, tab_id, source_name, position):
    logger.info(
        "change_source_position ajax request received(tab_id=%s, source_name=%s, position=%s)"
        % (str(tab_id), str(source_name), str(position))
    )

    success = False
    tab = get_object_or_none(Tab, user=request.user, id=tab_id)
    if tab:
        source = get_object_or_none(Source, name=source_name)
        if source:
            new_position = tab.change_source_priority(source, position)
            if new_position == position:
                logger.debug("%s position changed to %s" % (str(source), str(position)))
                success = True

    logger.info("Sending response(change_source_position")
    return simplejson.dumps({"success": success})
Example #7
0
def delete_tag(request, tab_id, tag):
	success = False
	
	tab = get_object_or_none(Tab, id=tab_id, user=request.user)
	if tab:
		tab.delete_tag(tag)
		tab.save()
		success = True

	return simplejson.dumps({ "success": success })
Example #8
0
def get_sources(request, tab_id):
    logger.info("get_sources ajax request received(tab_id=%s)" % str(tab_id))

    source_names = []
    tab = get_object_or_none(Tab, user=request.user, id=tab_id)
    if tab:
        source_names = [source.name for source in tab.get_sources()]
        logger.debug("Sources found: %s" % str(source_names))

    logger.info("Sending response(get_sources)")
    return simplejson.dumps({"sources": source_names})
Example #9
0
def change_tab_position(request, tab_id, position):
    logger.info("change_tab_position ajax request received(tab_id=%s, position=%s)" % (str(tab_id), str(position)))

    success = False
    tab = get_object_or_none(Tab, user=request.user, id=tab_id)
    if tab:
        if tab.change_order(position) == position:
            logger.debug("%s position changed to %s" % (str(tab), str(position)))
            success = True

    logger.info("Sending response(change_tab_position)")
    return simplejson.dumps({"success": success})
	def test_multiple_tabs_integrity(self):
		'''
		A user must have unique names for each tab. Name can not be left empty
		'''
		#A user must have different names for each tab
		self.assertRaises(IntegrityError, Tab.objects.create_tab, user=self.user, name='Headlines')

		#Different users can have tabs with same names
		user = NTUser.objects.create_user(name='Divyansh', email='*****@*****.**', password='******')
		tab = get_object_or_none(Tab, user=user, name='Headlines')
		self.assertIsInstance(tab, Tab)

		#ValueError must be raised when trying to create a tab with no name
		self.assertRaises(ValueError, Tab.objects.create_tab, user=self.user, name='')
Example #11
0
def delete_tab(request, tab_id):
    logger.info("delete_tab ajax request received(tab_id=%s)" % str(tab_id))

    success = False
    tab = get_object_or_none(Tab, user=request.user, id=tab_id)
    if tab:
        tabsources = TabSource.objects.filter(tab=tab)
        tabsources.delete()
        tab.delete()
        logger.debug("%s tab deleted" % str(tab))
        success = True

    logger.info("Sending response(delete_tab)")
    return simplejson.dumps({"success": success})
Example #12
0
def reset_password(request):
	context = {
		'form': True, #Shows the password-reset form
		'verify_token': False, #If true, the operation is verify token, else send mail
		'success': False, #If operation is successful, then True
	}

	if request.method == "POST":
		#POST request is done to send the password reset mail
		context['form'] = False
		email = request.POST.get('email', None)

		if email:
			user = get_object_or_none(NTUser, email=email)
			context['email'] = email
			
			#Send the email only if the user exists and is verified
			if user and user.verified:
				token = user.generate_password_reset_token()
				mail.send_reset_password_mail(str(user.name), str(user.email), str(token))
				context['success'] = True
	elif request.method == "GET":
		#GET request is done to verify the token and reset user's password
		email = request.GET.get('email', None)
		token = request.GET.get('token', None)

		if email and token:
			context['form'] = False
			context['verify_token'] = True
			context['email'] = email
			
			user = get_object_or_none(NTUser, email=email)
			if user and user.get_password_reset_token() == token:
				context['token'] = token
				context['success'] = True #Token exists and valid. Let the user change the password

	return render(request, 'newsreader/reset-password.html', context)
	def test_add_source(self):
		'''
		add_source must associate the source with the tab. If the tab is none, no error must be displayed.
		The new source must automatically be assigned the last priority
		'''
		#Adding an existing source returns None
		self.assertIsNone(self.tab.add_source(source=self.source))

		#A new source should automatically have the lowest priority (highest number)
		source = Source.objects.create(name='Hindu', link='http://hindu.com')
		self.tab.add_source(source)
		tabsource = get_object_or_none(TabSource, tab=self.tab, source=source)
		self.assertEqual(tabsource.source_priority, self.tabsource.source_priority + 1)
		
		#Adding an empty source should not raise an exception
		self.assertIsNone(self.tab.add_source(None))
	def test_order_number(self):
		'''
		Tab order number must automatically increment when new tab is created. Changing the tab order must automatically reorder the rest
		'''
		#Check auto-increment
		tab = Tab.objects.create_tab(user=self.user, name='Hello')
		self.assertEqual(tab.order, 2)

		#Check tab re-order
		self.assertEqual(tab.change_order(1), 1)
		c_tab = get_object_or_none(Tab, pk=self.tab.id) #Retreive the newly changed tab
		self.assertEqual(c_tab.order, 2)

		#Invalid order conditions must result in no change
		self.assertEqual(self.tab.change_order(100), self.tab.order)
		self.assertEqual(self.tab.change_order(0), self.tab.order)
Example #15
0
def article(request, article_no=None, article_url=None):
	if not article_url or not article_no:
		raise Http404
	
	article = get_object_or_none(Article, id=article_no)
	if not article:
		raise Http404
	
	if not article_url == generate_seo_link(article.get_heading()):
		raise Http404
	
	context = {}
	context['heading'] = article.get_heading()
	context['link'] = article.link
	
	article_viewed(request, article_no)
	
	return render(request, 'newsreader/article.html', context)
def default_tabs(sender, **kwargs):
	user = kwargs.get('instance', None)
	created = kwargs.get('created', None)

	#If it was a newly created record
	if created and user:
		#Create default tab
		logger.debug("Creating default tabs for user %s" % str(user))
		tab = Tab.objects.create_tab(user=user, name='Headlines')
		source = get_object_or_none(Source, name='CNN-IBN Top Stories')
		if source:
			tab.add_source(source)
			logger.debug("Default tab created successfuly")

		logger.debug("Sending confirmation email to user %s" % str(user))
		token = user.get_email_confirmation_token()
		mail.send_confirmation_mail(str(user.name), str(user.email), str(token))
		logger.debug("Mail sent to %s" % str(user.email))
Example #17
0
def change_password(request):
	token = request.POST.get('token', None)
	email = request.POST.get('email', None)
	password = request.POST.get('password', None)

	context = {
		'password_changed': False
	}
	print "%s" % str(request)
	if token and email and password:
		user = get_object_or_none(NTUser, email=email)
		if user and user.get_password_reset_token() == token:
			user.set_password(password)
			user.save()
			user.delete_password_reset_token()
			context['password_changed'] = True

	return render(request, 'newsreader/change-password.html', context)
def update_feed(source):
	'''
	Updates the feeds from source if it has not been updated for UPDATE_INTERVAL hours
	'''
	logger.info("Checking if %s needs to be updated" % str(source))
	#Get the last update time
	if source:
		last_update = source.last_update
	updated_articles = []
	logger.debug("%s was last updated: %s" % (str(source), format_datetime(last_update)))

	#Update only if UPDATE_INTERVAL time has elapse since the last update
	if not last_update or timedelta(datetime.now(tzlocal()), last_update) >= timedelta(hours=UPDATE_INTERVAL):
		logger.info("Updating source %s" % str(source))
		feed = fp.parse(source.link)
		
		for entry in feed.get('entries'):
			#Try parsing the date and if it thows an exception, default to the current date
			try:
				pub_date = date.parse(entry.get('published'), default=datetime.now(tzlocal()))
			except:
				pub_date = datetime.now(tzlocal())

			link = entry.get('link')
			heading = entry.get('title')
			summary = entry.get('summary_detail').get('value')
			logger.debug("Parsed article: %s" % u''.join(heading).encode('utf-8').strip())

			#Check if article has already been added.
			article = get_object_or_none(Article, link=link)
			if not article:
				try:
					logger.debug("Article not found in database. Adding to database")
					article = Article.objects.create(pub_date=pub_date, link=link, source=source, heading=heading, summary=summary)
					article.tag_self()
					updated_articles.append(article)
				except Exception, e:
					logger.exception(e)

		#Update the last update time of this source
		source.last_update = datetime.now(tzlocal())
		source.save()
		logger.info("No of articles updated: %d" % len(updated_articles))
Example #19
0
	def test_change_tab_position(self):
		'''
		change_tab_position changes the order of the tabs. Invalid requests must be ignored
		'''
		#Anonymous user test
		response = dajaxice_post(self.client, 'newsreader', 'change_tab_position', {'tab_id': self.tabs[0].id, 'position': 2})
		self.assertFalse(json.loads(response.content)['success'])

		#Logged in user
		self.client.login(email=self.user_email, password=self.user_pass)
		response = dajaxice_post(self.client, 'newsreader', 'change_tab_position', {'tab_id': self.tabs[0].id, 'position': 2})
		self.assertTrue(json.loads(response.content)['success'])
		self.assertTrue(get_object_or_none(Tab, pk=self.tabs[0].id).order, 2)

		#Invalid tab id
		response = dajaxice_post(self.client, 'newsreader', 'change_tab_position', {'tab_id': 100, 'position': 2})
		self.assertFalse(json.loads(response.content)['success'])

		#Invalid position
		response = dajaxice_post(self.client, 'newsreader', 'change_tab_position', {'tab_id': self.tabs[0].id, 'position': 0})
		self.assertFalse(json.loads(response.content)['success'])
		response = dajaxice_post(self.client, 'newsreader', 'change_tab_position', {'tab_id': self.tabs[0].id, 'position': 100})
		self.assertFalse(json.loads(response.content)['success'])
def get_content(user, tab_id):
	'''
	Returns a list of articles. Loads from cache if available.
	'''
	logger.info("Retrieving content for tab_id %s" % int(tab_id))
	
	#Try finding articles in cache
	cache_key = "tab_cache" + str(user.id) + str(tab_id)
	articles = cache.get(cache_key, [])
	logger.debug("No of articles found in cache: %d (cache_key=%s)" % (len(articles), cache_key))
	
	#If the articles are not found in the cache, then retreive the articles
	if not articles:
		logger.info("Trying to retrieve articles from database")
		tab = get_object_or_none(Tab, id=tab_id, user=user)
		
		articles = []
		tagged_articles = []
		
		if tab is not None:
			logger.debug("Tab found: %s. Getting sources and tags" % str(tab))
			#Get all the sources and tags in the tab
			sources = tab.get_sources() #This makes sure that the articles are arranged in order of source priority
			tags = tab.tags.all()
			logger.debug("Sources: %s, Tags: %s" % (str(sources), str(tags)))

			#For each source, retrieve the articles
			for source in sources:
				logger.debug("Retrieving articles for source: %s" % str(source))
				
				#Make sure the source has the latest feeds
				update_feed(source)
				source_articles = Article.objects.filter(source=source, pub_date__gt=datetime.now(tzlocal())-delta(days=1)).order_by('-pub_date')
				logger.debug("No of source articles found: %d" % len(source_articles))

				#If tags are specified, filter articles with tags
				if tags:
					logger.debug("Filtering articles based on the tags")
					tagged_articles_in_source = source_articles.filter(tags__in=tags).distinct()
					
					tagged_articles += tagged_articles_in_source
					# source_articles -= tagged_articles_in_source
					temp_articles = []
					temp_articles += source_articles
					for t_article in tagged_articles_in_source:
						temp_articles.remove(t_article)
					
					logger.debug("No of tagged articles: %s" % len(tagged_articles))

					articles += temp_articles
				else:
					articles += source_articles
			
			articles = tagged_articles+articles
			
			logger.info("No of articles retrieved: %d" % len(articles))
			logger.info("Adding articles to cache")
			
			#add the articles to cache
			cache.add(cache_key, articles, CACHE_EXPIRES)

	return articles