def create_for_video_moved(self, video, user, from_team=None, to_team=None): with transaction.atomic(): if from_team is not None: if to_team is not None: to_team_id = to_team.id else: to_team_id = None self.create_for_video('video-moved-from-team', video, user=user, created=dates.now(), related_obj_id=to_team_id, team=from_team, private_to_team=True) if to_team is not None: if from_team is not None: from_team_id = from_team.id else: from_team_id = None self.create_for_video('video-moved-to-team', video, user=user, created=dates.now(), related_obj_id=from_team_id, team=to_team, private_to_team=True)
def build_notifications(self): time_keep = dates.now() time_remove = dates.now() - timedelta(days=30) for team in self.teams: for i in range(1, 151): time = time_remove if i < 80 else time_keep n = TeamNotification.objects.create( number=i, data={'text': 'Notification {}'.format(i)}, url='https://example.com/{}'.format(team.slug), timestamp=time, team=team) self.notifications.append(n)
def create_for_video_url_made_primary(self, video_url, old_url, user): with transaction.commit_on_success(): url_edit = URLEdit.objects.create(old_url=old_url.url, new_url=video_url.url) return self.create_for_video('video-url-edited', video_url.video, user=user, created=dates.now(), related_obj_id=url_edit.id)
def setUp(self): self.remove_after = dates.now() - timedelta(days=15) self.keep_up_to = 50 self.teams = [TeamFactory() for i in range(0, 3)] self.notifications = [] self.build_notifications()
def create_for_video_url_deleted(self, video_url, user): with transaction.atomic(): url_edit = URLEdit.objects.create(old_url=video_url.url) return self.create_for_video('video-url-deleted', video_url.video, user=user, created=dates.now(), related_obj_id=url_edit.id)
def create_for_subtitle_language_changed(self, user, subtitle_language, old_language_code): with transaction.atomic(): change = SubtitleLanguageChange.objects.create( old_language=translation.get_language_label(old_language_code)) return self.create_for_video('language-changed', subtitle_language.video, user=user, created=dates.now(), language_code=subtitle_language.language_code, related_obj_id=change.id)
def datetime(when): if isinstance(when, timedelta): dt = now() - timedelta else: dt = when if dt is None: return '' return dt.strftime("%b %-d, %Y, %-I:%M %p")
def create_for_video_deleted(self, video, user): with transaction.commit_on_success(): url = video.get_video_url() video_deletion = VideoDeletion.objects.create( title=video.title_display(), url=url if url is not None else '') return self.create('video-deleted', user=user, created=dates.now(), related_obj_id=video_deletion.id)
def check_too_many_messages(self, user): now = dates.now() self.get_queryset().filter( created__lt=now - timedelta(minutes=settings.MESSAGES_SENT_WINDOW_MINUTES)).delete() return self.get_queryset().filter( user=user, created__gt=now - timedelta(minutes=settings.MESSAGES_SENT_WINDOW_MINUTES)).count( ) > settings.MESSAGES_SENT_LIMIT
def create_new(cls, team, url, data): data = data.copy() if isinstance(team, Team): obj = cls(team=team, url=url, timestamp=dates.now()) else: obj = cls(team_id=team, url=url, timestamp=dates.now()) obj.set_number() # There is a potential race condition here where another thread also # creates a TeamNotification and takes our number. If that happens, # then try with the next number. for i in range(10): try: data['number'] = obj.number obj.data = json.dumps(data) obj.save() return obj except IntegrityError: obj.number = obj.number + 1 raise IntegrityError("Couldn't find unused number")
def create_for_video_deleted(self, video, user): with transaction.atomic(): team_video = video.get_team_video() team_id = team_video.team_id if team_video else None url = video.get_video_url() video_deletion = VideoDeletion.objects.create( title=video.title_display(), url=url if url is not None else '') return self.create('video-deleted', user=user, created=dates.now(), team_id=team_id, related_obj_id=video_deletion.id)
def increment(team, name): """ Increment a team stat. """ r = get_redis_connection('storage') hash_name = calc_hash_name(team) hash_key = calc_hash_key(name, dates.now()) pipe = r.pipeline() pipe.hincrby(hash_name, hash_key, 1) pipe.sadd(TRACKING_SET_KEY, hash_name) pipe.execute()
def elapsed_time(when): """ Format the amount of time that has passed Args: when (datetime/timedelta): time to display. If this is a datetime, then we will display the time between now and it. If it's a timedelta, then we use that directly """ if isinstance(when, timedelta): delta = when dt = now() - timedelta else: delta = now() - when dt = when if delta.days < 0: return _('now') elif delta.days < 1: if delta.seconds < 60: return _('now') elif delta.seconds < 60 * 60: minutes = int(round(delta.seconds / 60.0)) return fmt(ungettext(u'%(count)s minute ago', u'%(count)s minutes ago', minutes), count=minutes) else: hours = int(round(delta.seconds / 60.0 / 60.0)) return fmt(ungettext(u'%(count)s hours ago', u'%(count)s hours ago', hours), count=hours) elif delta.days < 7: days = int(round(delta.days + delta.seconds / SECONDS_IN_A_DAY)) return fmt(ungettext('%(count)s day ago', '%(count)s days ago', days), count=days) else: return date(dt)
def timesince_short(datetime): delta = dates.now() - datetime if delta.days != 0: return fmt(ungettext('%(count)s day ago', '%(count)s days ago', delta.days), count=delta.days) elif delta.seconds > 3600: hours = int(round(delta.seconds / 3600.0)) return fmt(ungettext('%(count)shour ago', '%(count)s hours ago', hours), count=hours) elif delta.seconds > 60: minutes = int(round(delta.seconds / 60.0)) return fmt(ungettext('%(count)s minute ago', '%(count)s minutes ago', minutes), count=minutes) else: return ugettext('Just now')
def get_stats(team): """ Get all current stats for a team Returns: dict mapping stat names to Counts objects """ cached = cache.get(cache_key(team)) if cached: return cache_deserialize(cached) now = dates.now() stats = defaultdict(StatSums) r = get_redis_connection('storage') all_counts = r.hgetall(calc_hash_name(team)) for key, count in all_counts.items(): count = int(count) name, dt = parse_hash_key(key) date_delta = now - dt # note that we're still in the process of recording stats for today, # so stats get offset by 1. "last_week" means "between 1 and 8 days # ago" if date_delta.days == 0: stats[name].today += count elif date_delta.days == 1: stats[name].yesterday += count stats[name].last_week += count stats[name].last_month += count elif date_delta.days < 8: stats[name].last_week += count stats[name].last_month += count elif date_delta.days < 31: stats[name].last_month += count stats = dict(stats) # convert defaultdict to a normal dict cache.set(cache_key(team), cache_seralize(stats), cache_timeout(now)) return stats
def sent_message(self, user): self.create(user=user, created=dates.now())
def cleanup_counters(): now = dates.now() r = get_redis_connection('storage') for hash_name in r.sscan_iter(TRACKING_SET_KEY): cleanup_counter(r, hash_name, now)
def create_for_video_title_edited(self, video, user): return self.create_for_video('video-title-changed', video, user=user, created=dates.now())
def create_for_member_deleted(self, member): return self.create('member-left', team=member.team, user=member.user, created=dates.now())
def create_for_version_declined(self, version, user): return self.create_for_video('version-declined', version.video, user=user, language_code=version.language_code, created=dates.now())
def due_date(deadline, when, hypothetical=False): """Get text to display a due date Args: deadline (unicode): name of the thing that's due ("request", "assignment", etc) when (datetime/timedelta): time to display. If this is a datetime, then we will display the time between now and it. If it's a timedelta, then we use that directly hypothetical: Use for a hypothetical due date. We will display "would be due" instead of "due" """ if isinstance(when, timedelta): delta = when dt = now() + when else: delta = when - now() dt = when delta_total_seconds = delta.total_seconds() if delta_total_seconds < 0 and delta.days < -7: count = None if hypothetical: msg = _(u'%(deadline)s could have been due %(date)s') else: msg = _(u'%(deadline)s was due %(date)s') elif delta_total_seconds <= 60 * 60 * 24 * -1: ''' Time differences of n days + "a fraction of a day" ago get ceiling'd up--ending up with 'deadline due n+1 days ago' The round up happens because of the way negative timedeltas work (the negative day deltas always overshoot and get compensated by positive hour and second deltas) I think this makes sense rather than falling short a day when looking back when something was due ''' count = delta.days * -1 if hypothetical: msg = ungettext( '%(deadline)s was possibly due %(count)s day ago', '%(deadline)s was possibly due %(count)s days ago', count) else: msg = ungettext('%(deadline)s was due %(count)s day ago', '%(deadline)s was due %(count)s days ago', count) # Time difference 1 hour ago and further back elif delta_total_seconds <= 60 * 60 * -1: count = int(round(delta.total_seconds() * -1 / (60.0 * 60.0))) if hypothetical: msg = ungettext( '%(deadline)s was possibly due %(count)s hour ago', '%(deadline)s was possibly due %(count)s hours ago', count) else: msg = ungettext('%(deadline)s was due %(count)s hour ago', '%(deadline)s was due %(count)s hours ago', count) # Time difference 1 minute ago and further back elif delta.days < 0: if delta_total_seconds <= 60 * -1: count = int(round(delta.total_seconds() * -1 / 60.0)) if hypothetical: msg = ungettext( '%(deadline)s was possibly due %(count)s minute ago', '%(deadline)s was possibly due %(count)s minutes ago', count) else: msg = ungettext('%(deadline)s was due %(count)s minute ago', '%(deadline)s was due %(count)s minutes ago', count) else: count = int(delta.total_seconds() * -1) if hypothetical: msg = ungettext( '%(deadline)s was possibly due %(count)s second ago', '%(deadline)s was possibly due %(count)s seconds ago', count) else: msg = ungettext('%(deadline)s was due %(count)s second ago', '%(deadline)s was due %(count)s seconds ago', count) elif delta.days < 3: if delta_total_seconds < 60: count = None if hypothetical: msg = _('%(deadline)s would be due now') else: msg = _('%(deadline)s due now') elif delta_total_seconds < 60 * 60 * 2: count = int(round(delta_total_seconds / 60.0)) if hypothetical: msg = ungettext( u'%(deadline)s would be due in %(count)s minute', u'%(deadline)s would be due in %(count)s minutes', count) else: msg = ungettext(u'%(deadline)s due in %(count)s minute', u'%(deadline)s due in %(count)s minutes', count) else: count = int(round(delta_total_seconds / 60.0 / 60.0)) if hypothetical: msg = ungettext( u'%(deadline)s would be due in %(count)s hour', u'%(deadline)s would be due in %(count)s hours', count) else: msg = ungettext(u'%(deadline)s due in %(count)s hour', u'%(deadline)s due in %(count)s hours', count) elif delta.days < 7: count = int(round(delta.days + delta.seconds / SECONDS_IN_A_DAY)) if hypothetical: msg = ungettext('%(deadline)s would be due in %(count)s day', '%(deadline)s would be due in %(count)s days', count) else: msg = ungettext('%(deadline)s due in %(count)s day', '%(deadline)s due in %(count)s days', count) else: count = None if hypothetical: msg = _(u'%(deadline)s would be due %(date)s') else: msg = _(u'%(deadline)s due %(date)s') # Note: We're not sure where the deadline label will end up in the final # string, so we lowercase it, interplate the string, then capitalize the # whole thing. msg = fmt(msg, deadline=deadline.lower(), count=count, date=date(dt)).capitalize() # we make the text red when its deadline has passed if delta_total_seconds <= 59: msg = format_html(u'<span class="text-amaranth-dark">{}</span>', msg.capitalize()) return msg
def create_for_team_settings_changed(self, team, user, changes): change_info = TeamSettingsChangeInfo.create_from_dict(changes) return self.create('team-settings-changed', team=team, user=user, related_obj_id=change_info.id, created=dates.now())
def due_date(deadline, when, hypothetical=False): """Get text to display a due date Args: deadline (unicode): name of the thing that's due ("request", "assignment", etc) when (datetime/timedelta): time to display. If this is a datetime, then we will display the time between now and it. If it's a timedelta, then we use that directly hypothetical: Use for a hypothetical due date. We will display "would be due" instead of "due" """ if isinstance(when, timedelta): delta = when dt = now() + when else: delta = when - now() dt = when if delta.days < 0: count = None if hypothetical: msg = _('%(deadline)s would be due now') else: msg = _('%(deadline)s due now') elif delta.days < 1: if delta.seconds < 60: count = None if hypothetical: msg = _('%(deadline)s would be due now') else: msg = _('%(deadline)s due now') elif delta.seconds < 60 * 60: count = int(round(delta.seconds / 60.0)) if hypothetical: msg = ungettext(u'%(deadline)s would be due in %(count)s minute', u'%(deadline)s would be due in %(count)s minutes', count) else: msg = ungettext(u'%(deadline)s due in %(count)s minute', u'%(deadline)s due in %(count)s minutes', count) else: count = int(round(delta.seconds / 60.0 / 60.0)) if hypothetical: msg = ungettext(u'%(deadline)s would be due in %(count)s hours', u'%(deadline)s would be due in %(count)s hours', count) else: msg = ungettext(u'%(deadline)s due in %(count)s hours', u'%(deadline)s due in %(count)s hours', count) elif delta.days < 7: count = int(round(delta.days + delta.seconds / SECONDS_IN_A_DAY)) if hypothetical: msg = ungettext('%(deadline)s would be due in %(count)s day', '%(deadline)s would be due in %(count)s days', count) else: msg = ungettext('%(deadline)s due in %(count)s day', '%(deadline)s due in %(count)s days', count) else: count = None if hypothetical: msg = _(u'%(deadline)s would be due %(date)s') else: msg = _(u'%(deadline)s due %(date)s') # Note: We're not sure where the deadline label will end up in the final # string, so we lowercase it, interplate the string, then capitalize the # whole thing. msg = fmt(msg, deadline=deadline.lower(), count=count, date=date(dt)) return msg.capitalize()