def test_click_store_autofields(self): token = utils.counter_to_token(random.randrange(0, 100000)) url = "http://xlarrakoetxea.org" OS = "linux" ip = "111.222.333.444" incr_times = 4 # Store a link sl = ShortLink(token=token, url=url) sl.save() for i in range(incr_times): ShortLink.incr_clicks(token) c = Click(token=token, os=OS, ip=ip) c.save() # The save method has set the click_date click_date = c.click_date self.assertIsNotNone(click_date) # Check the stored object key = Click.REDIS_CLICK_KEY.format(token, c.click_id) r = get_redis_connection() values = r.hgetall(key) # Check the key is correctly set (this means that the counter has # increased correctly) correct_key = Click.REDIS_CLICK_KEY.format(token, incr_times + 1) self.assertEquals(correct_key, key) self.assertEquals(OS, values["os"]) self.assertEquals(ip, values["ip"])
def test_delete_link(self): counter = random.randrange(0, 100000) url = "xlarrakoetxea.org" sl = ShortLink(counter=counter, url=url) sl.save() r = get_redis_connection() times = random.randrange(10, 100) for i in range(times): c = Click(token=sl.token) c.save() self.assertTrue(r.exists(ShortLink.REDIS_TOKEN_KEY.format(sl.token))) self.assertTrue(r.sismember(ShortLink.REDIS_URL_KEY.format(sl.url), sl.token)) self.assertEquals(times, len(r.keys( Click.REDIS_CLICK_KEY.format(sl.token, "*")))) sl.delete() self.assertFalse(r.exists(ShortLink.REDIS_TOKEN_KEY.format(sl.token))) self.assertFalse(r.sismember(ShortLink.REDIS_URL_KEY.format(sl.url), sl.token)) self.assertEquals(0, len(r.keys( Click.REDIS_CLICK_KEY.format(sl.token, "*"))))
def index(request): if request.method == 'POST': form = URLForm(request.POST) if form.is_valid(): try: result = create_token.delay(form.cleaned_data['url']) token = result.get() messages.success(request, 'New token {0} created'.format(token)) except: raise Http404 form = URLForm() # Get links try: links = ShortLink.findall() total_links = ShortLink.get_counter() except ShortLinkNotFoundError: total_links = 0 links = () data = { 'my_form': form, 'total_links': total_links, 'links': links } return render_to_response('simple/index.html', data, context_instance=RequestContext(request))
def test_click_findall(self): url = "http://xlarrakoetxea.org" clicks = set() # Save sl = ShortLink(url=url) sl.save() # Clicks for i in range(random.randrange(0, 5)): c = Click(token=sl.token, os="linux") c.save() clicks.add(c) clicks2 = Click.findall(sl.token) self.assertEquals(len(clicks), len(clicks2)) for i in clicks: clicks2_aux = set(clicks2) for j in clicks2_aux: if i == j: clicks2.remove(j) self.assertEquals(0, len(clicks2))
def test_save_shortLink(self): counter = random.randrange(0, 100000) url = "xlarrakoetxea.org" creation_date = dateutils.unix_now_utc() clicks = 20 title = "This is a title" host = url disabled = True # Save the links sl = ShortLink(counter=counter, url=url, creation_date=creation_date, clicks=clicks, title=title, host=host) sl.disabled = disabled sl.save() r = redis.StrictRedis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=settings.REDIS_DB) # Construct the Keys rtk = ShortLink.REDIS_TOKEN_KEY.format(utils.counter_to_token(counter)) ruk = ShortLink.REDIS_URL_KEY.format(url) # Check token = utils.counter_to_token(counter) self.assertTrue(token in r.smembers(ruk)) keys = ('url', 'creation_date', 'clicks', 'title', 'host') data = [url, creation_date, clicks, title, host] aux = r.hmget(rtk, keys) data_result = [aux[0], int(aux[1]), int(aux[2]), aux[3], aux[4]] self.assertEquals(data, data_result)
def test_click_link(self): data = { "LANG": "en_US", "REMOTE_ADDR": "72.14.207.99", "HTTP_USER_AGENT": "Mozilla/5.0 (X11; Linux x86_64; rv:17.0)" + " Gecko/17.0 Firefox/17.0", } # Prepare the database counter = random.randrange(0, 100000) url = "http://xlarrakoetxea.org" sl = ShortLink(counter=counter, url=url) sl.save() # Call teh task result = tasks.click_link.delay(sl.token, data) # Wait (for testing only) result.get() # Check the stored information c = Click.find(sl.token, 1) self.assertEquals("en_US", c.language) self.assertEquals("linux x86_64", c.os) self.assertEquals("firefox", c.browser) self.assertEquals("72.14.207.99", c.ip) self.assertEquals("US", c.location)
def test_increment_stored_counter(self): counter = random.randrange(0, 100000) times = random.randrange(0, 100) ShortLink.set_counter(counter) for i in range(times): self.assertEquals(counter + i + 1, ShortLink.incr_counter()) self.assertEquals(counter + times, ShortLink.get_counter())
def test_save_shortLink_error(self): counter = random.randrange(0, 100000) sl = ShortLink() self.assertRaises(ShortLinkError, sl.save) sl.url = None sl.counter = counter self.assertRaises(ShortLinkError, sl.save)
def test_getall_shortlink(self): times = random.randrange(1, 20) for i in range(times): url = "xlarrakoetxea{0}.org".format(i) sl = ShortLink(url=url) sl.save() sls = ShortLink.findall() self.assertEquals(times, len(sls))
def test_get_shortLinks_by_url(self): times = 10 counters = [random.randrange(0, 100000) for i in range(times)] url = "xlarrakoetxea.org" for i in counters: sl = ShortLink(counter=i, url=url) sl.save() sls = ShortLink.find(url=sl.url) self.assertEquals(len(counters), len(sls))
def test_get_shortLink_by_counter(self): counter = random.randrange(0, 100000) url = "xlarrakoetxea.org" title = "My webpage" host = "xlarrakoetxea.org" sl = ShortLink(counter=counter, url=url, title=title, host=host) sl.save() sl2 = ShortLink.find(counter=counter) self.assertEquals(sl, sl2)
def test_get_shortLink_by_token(self): counter = random.randrange(0, 100000) url = "xlarrakoetxea.org" title = "My webpage" host = "xlarrakoetxea.org" sl = ShortLink(token=utils.counter_to_token(counter), url=url, title=title, host=host) sl.save() sl2 = ShortLink.find(token=sl.token) self.assertEquals(sl, sl2)
def save(self): """ Save a click in the database. If the instance doens't have the click_id the method will get the correct value, based on the Short link click counter""" r = get_redis_connection() if not self.token: raise ClickError("Not enought data to store click instance") #if there isn't an identification then get the apropiate id if not self.click_id: self.click_id = ShortLink.incr_clicks(self.token) #set the date if there isn't a date if not self.click_date: self.click_date = dateutils.unix_now_utc() key = Click.REDIS_CLICK_KEY.format(self.token, self.click_id) #Create the data to_store = {} for i in Click.FIELDS: value = getattr(self, i) if value: to_store[i] = value r.hmset(key, to_store)
def forward(request, token): # get the forwarding Forward sl = ShortLink.find(token=token) if sl.disabled: raise Http404 # Click :) click_link(token, request.META) if not re.search("^https?://.+", sl.url): forward_url = "http://{0}".format(sl.url) else: forward_url = sl.url # Add the points to the user user_link = UserLink.objects.get(token=token) # If returns something then level upload then notification new_level = utils.incr_points(user_link.user, settings.POINTS_PER_CLICK) if new_level: # Send notifications notif = LevelNotification(level=new_level, user_id=user_link.user.id) #notif.send_push() # Push realtime notification notif.save() # save the notification for the dashboard return redirect(forward_url)
def details(request, token): clicks = list(Click.findall(token=token)) # Sort clicks.sort(key=lambda click: click.click_id) short_link = ShortLink.find(token=token) # Get data for the charts browsers = get_data_for_charts(clicks, "browser") browsers.append("Browsers") os = get_data_for_charts(clicks, "os") os.append("OS") country = get_data_for_charts(clicks, "location") country.append("Country") not_json_data = (browsers, os, country) #Serialize json_data = json.dumps(not_json_data) data = { 'shortlink': short_link, 'clicks': clicks, 'json_data': json_data } return render_to_response('simple/details.html', data, context_instance=RequestContext(request))
def user_dashboard(request): # Notifications # Rest one beacause is the upper limit inclusive notifs = Notification.find(user=request.user, limit=NOTIFS_IN_DASHBOARD-1) # Stats total_links = UserLink.objects.filter(user=request.user).count() total_achieves = UserAchievement.objects.filter(user=request.user).count() # Latest links links_aux = UserLink.objects.filter( user=request.user).order_by('-id')[:LINKS_IN_DASHBOARD] links = [ShortLink.find(token=i.token) for i in links_aux] # Latest achievements achievements = UserAchievement.objects.filter( user=request.user).order_by('-id')[:ACHIEV_IN_DASHBOARD] context = { "notifications": notifs, "links": links, "stats": { "Total Links": total_links, "Achievements": total_achieves, "Level": request.user.profile.level.level_number, "Points": request.user.profile.points, }, "achievements": achievements } return render_to_response('userprofile/dashboard.html', context, context_instance=RequestContext(request))
def test_click_find(self): token = utils.counter_to_token(random.randrange(0, 100000)) OS = "linux" ip = "111.222.333.444" browser = "firefox" click_date = dateutils.unix_now_utc() language = "EN_us" location = "US" url = "http://xlarrakoetxea.org" sl = ShortLink(token=token, url=url) sl.save() c = Click( token=token, os=OS, ip=ip, browser=browser, click_date=click_date, language=language, location=location ) c.save() c2 = Click.find(token, c.click_id) self.assertEquals(c, c2)
def index(request): context = { 'total_users': User.objects.all().count(), 'total_links': ShortLink.get_counter(), 'total_clicks': TotalClickMetrics().count() } return render_to_response('homepage/index.html', context, context_instance=RequestContext(request))
def test_create_new_token(self): counter = random.randrange(100000) url = "http://xlarrakoetxea{0}.org".format(random.randrange(100)) # Set the counter ShortLink.set_counter(counter) # Call the async task with celery result = tasks.create_token.delay(url) new_token = result.get() #Check if the returned token is ok self.assertEquals(utils.counter_to_token(counter + 1), new_token) self.assertTrue(result.successful()) # Check if the link is stored in the database correctly sl = ShortLink.find(url=url)[0] # creation_date is trap!! :P sl2 = ShortLink(counter=counter + 1, url=url, creation_date=sl.creation_date) # The host and title are set after the instance was created so we add sl2.host = sl.host sl2.title = sl.title self.assertEquals(sl2, sl)
def create_token(url, user_id=None, notification=True): # Get the next counter to create the token counter = ShortLink.incr_counter() # Sanitize the url url = sanitize_url(url) # Get the title # Fix this!! test if the url exists or not!! try: title = extract_url_title(url) except: title = "No title" # Get the host host = extract_url_host(url) # Create the instance with the data sl = ShortLink() sl.counter = counter sl.url = url sl.title = title sl.host = host # Save sl.save() # If is a user link save it also if user_id: user_link = UserLink() user_link.user = User.objects.get(id=user_id) user_link.token = sl.token user_link.save() # Only need notification if we have a user if notification: # Send notifications notif = ShortLinkNotification(sl, user_id=user_id) #notif.send_push() # Push realtime notification notif.save() # save the notification for the dashboard # Fill the metrics SharedLinkMetrics().increment() logger.debug("{0} shorted url '{1}' to token '{2}'".format(user_id, url, sl.token)) # Return the new token return sl.token
def links_index(request): # get the page page = int(request.GET.get('page', 1)) # Get the total pages (rounding up, ex: 1.2 pages means 2 pages) total_pages = int(math.ceil( float(UserLink.objects.filter( user=request.user).count()) / LINK_PER_PAGE)) # If the page doesn't exists then 404 if page > total_pages and total_pages > 0: raise Http404 # Get the links offset = LINK_PER_PAGE * (page - 1) limit = offset + LINK_PER_PAGE links_aux = UserLink.objects.filter(user=request.user).order_by('-id')[offset:limit] links = [ShortLink.find(token=i.token) for i in links_aux] # Group by day grouped_links = [] temp = [] for i in links: creation_date = unix_to_datetime(i.creation_date) if len(temp) == 0: temp.append(i) else: previous_date = unix_to_datetime(temp[0].creation_date) if previous_date.year == creation_date.year and\ previous_date.month == creation_date.month and\ previous_date.day == creation_date.day: temp.append(i) else: grouped_links.append(temp) temp = [] # If no links don't add them if temp: grouped_links.append(temp) context = { "total_pages": total_pages, "actual_page": page, "links": grouped_links } return render_to_response('links/user_links.html', context, context_instance=RequestContext(request))
def test_shortlink_basic_object_str(self): url = "xlarrakoetxea.org" counter = random.randrange(0, 100000) token = utils.counter_to_token(counter) creation_date = None clicks = 0 title = "This is a title" host = url disabled = True format = ShortLink.OBJECT_STR_FORMAT.format(counter, token, url, creation_date, clicks, title, host, disabled) sl = ShortLink(counter=counter, url=url, title=title, host=host) sl.disabled = disabled self.assertEquals(format, str(sl))
def from_json(cls, json_dict): # Avoid circular dependency of the signals from linkshortener.models import ShortLink # Maybe the link has been deleted, so we catch the exception try: short_link = ShortLink.find(token=json_dict["token"]) sl = ShortLinkNotification(short_link, user_id=json_dict["user_id"]) sl.date = json_dict["date"] return sl except ShortLinkNotFoundError: pass
def test_save_shortLink_autofield(self): times = random.randrange(1, 100) url = "xlarrakoetxea.org" title = "My webpage" host = "xlarrakoetxea.org" # Set the shor link counter for i in range(times): ShortLink.incr_counter() # Save sl = ShortLink() sl.url = url sl.title = title sl.host = host sl.save() # Check the correct counter sl2 = ShortLink.find(counter=times + 1) self.assertEquals(sl, sl2)
def disable_link(request): if request.method == "POST": form = DisableLinkForm(data=request.POST) if form.is_valid(): data = form.cleaned_data link_token = data['token'] # Disable the token sl = ShortLink.find(token=link_token) if not sl.disabled: sl.disable() else: sl.enable() return redirect(reverse(links_info, args=[link_token]))
def delete_link(request): if request.method == "POST": form = DisableLinkForm(data=request.POST) if form.is_valid(): data = form.cleaned_data link_token = data['token'] # Delete the token ul = UserLink.objects.get(token=link_token) ul.delete() sl = ShortLink.find(token=link_token) sl.delete() return redirect(reverse(links_index)) else: return redirect(reverse(links_info, args=[link_token]))
def test_shortlink_basic_object(self): url = "xlarrakoetxea.org" counter = random.randrange(0, 100000) token = utils.counter_to_token(counter) creation_date = None clicks = 0 title = "This is a title" host = url disabled = True # Setters from counter sl = ShortLink(counter=counter, url=url, title=title, host=host) sl.disabled = disabled # Getters self.assertEquals(url, sl.url) self.assertEquals(counter, sl.counter) self.assertEquals(token, sl.token) self.assertEquals(creation_date, sl.creation_date) self.assertEquals(clicks, sl.clicks) self.assertEquals(title, sl.title) self.assertEquals(host, sl.host) self.assertEquals(disabled, sl.disabled) # Setters from token sl2 = ShortLink(token=token, url=url) creation_date = dateutils.unix_now_utc() sl2.creation_date = creation_date clicks = 5 sl2.clicks = clicks sl2.title = title sl2.host = host sl2.disabled = disabled # Getters self.assertEquals(url, sl2.url) self.assertEquals(counter, sl2.counter) self.assertEquals(token, sl2.token) self.assertEquals(creation_date, sl2.creation_date) self.assertEquals(clicks, sl2.clicks) self.assertEquals(title, sl2.title) self.assertEquals(host, sl2.host) self.assertEquals(disabled, sl2.disabled)
def test_enable_link(self): clicks = random.randrange(0, 100000) counter = random.randrange(0, 100000) url = "xlarrakoetxea.org" sl = ShortLink(counter=counter, url=url, clicks=clicks) sl.save() sl.disable() sl2 = ShortLink.find(token=sl.token) self.assertTrue(sl2.disabled) sl2.enable() sl2 = ShortLink.find(token=sl.token) self.assertFalse(sl2.disabled)
def findall(cls, token): """Finds all the click instances of a given token. Returns a set of Click instances :param token: the token that is associated to the clicks """ if not token: raise ClickError("Not enought data to find a Click instance") # Get the max counters counter = 0 try: short_link = ShortLink.find(token=token) counter = short_link.clicks except ShortLinkNotFoundError: raise ClickNotFoundError("Shortlink doesnt exists, clicks neither") clicks = set() for i in range(1, counter + 1): clicks.add(Click.find(token, i)) return clicks
def test_shortlink_notification_store(self): #with three we have enought to test sls = ShortLink.findall()[:3] user = User.objects.get(id=1) a_len = len(sls) for i in sls: notif = ShortLinkNotification(short_link=i, user=user) time.sleep(1) # We need notification order notif.save() r = get_redis_connection() res = r.zrange( Notification.STORE_KEY_UNREAD_FORMAT.format(user.id), 0, -1) self.assertEquals(a_len, len(res)) for i in range(len(res)): before = sls[i] after = json.loads(res[i]) self.assertEquals(before.token, after['token'])