def clear_programs(cls, cid=None, all=False): if cid: channel = Channel.get_by_key_name(cid) Programming.clear_channel(channel) elif all: Programming.clear() else: Programming.clear_channels()
def remove_program(cls, channel_id, media): from model import Channel cached_programming = memcache.get('programming') or {} new_schedule = [] sched = 0 if cached_programming.get(channel_id): for program in cached_programming[channel_id]: time = iso8601.parse_date(program['time']).replace(tzinfo=None) if program['media']['id'] == media.id: sched += 1 continue if sched: new_time = time - datetime.timedelta(seconds=(sched * media.duration)) program['time'] = new_time.isoformat() new_schedule.append(program) channel = Channel.get_by_key_name(channel_id) channel.next_time = channel.next_time - datetime.timedelta(seconds=(sched * media.duration)) channel.put() cached_programming[channel_id] = new_schedule memcache.set('programming', cached_programming) return new_schedule
def set_programming(cls, channel_id, duration=3600, schedule_next=False, fetch_twitter=True, queue='programming', target=None, kickoff=False): import broadcast import constants from model import Channel from model import Program # Stored programming programming = memcache.get('programming') or {} onlineUsers = memcache.get('web_channels') or {} logging.info('programming: ' + channel_id) next_programs = Programming.next_programs(programming.get(channel_id, []), duration, prelude=300) gap = Programming.gap(programming.get(channel_id, []), duration) logging.info('GAP: ' + str(gap)) if programming.get(channel_id) and len(programming[channel_id]) and \ programming[channel_id][0]['media'].get('live') == True: logging.info('live tweets') # Update tweets for live events media = Media.get_by_key_name(programming[channel_id][0]['media']['id']) deferred.defer(Programming.fetch_related_tweets, [], _name='twitter-' + channel_id + '-' + str(uuid.uuid1()), _queue='twitter') programs = [] if not programming.get(channel_id) or gap > 60: logging.info('PROGRAOMMING') channel = Channel.get_by_key_name(channel_id) #channel.update_next_time() viewers = (memcache.get('channel_viewers') or {}).get(str(channel_id), []) cols = channel.get_collections() all_medias = [] backup_medias = [] limit = 100 for col in cols: medias = [] filtered_medias = [] offset = 0 while offset <= 400: medias = col.get_medias(limit=limit, offset=offset) logging.info('fetched medias: ' + str(len(medias))) if not len(medias): break backup_medias += medias # Dont reprogram anytihng already scheduled filtered_medias = Programming.no_reprogram(programming.get(channel_id, []), medias) # Don't repeat the same program within two hour cutoff = 7200 if col.lifespan else 43200 filtered_medias = [c for c in filtered_medias if not c.last_programmed or (datetime.datetime.now() - c.last_programmed).seconds > cutoff] # At most, 30% of the audience has already "witnessed" this program # filtered_medias = [m for m in filtered_medias if not len(viewers) or # float(len(Programming.have_seen(m, viewers)))/len(viewers) < .3] all_medias += filtered_medias logging.info('all medias: ' + str(len(all_medias))) offset += limit all_medias = backup_medias if not len(all_medias) else all_medias # Don't repeat already programmed # all_medias = Programming.no_reprogram(next_programs, all_medias) # StorySort algorithm # all_medias = Programming.story_sort(all_medias) # Only one publisher per story all_medias = Programming.unique_publishers(all_medias) # Grab "duration" seconds of programming all_medias = Programming.timed_subset(all_medias, duration) if fetch_twitter: # Find related twitter posts deferred.defer(Programming.fetch_related_tweets, all_medias, _name='twitter-' + channel.name.replace(' ', '') + '-' + str(uuid.uuid1()), _queue='twitter', _countdown=30) # Truncate old programs programming[channel_id] = Programming.cutoff_programs(programming.get(channel_id), 300) for media in all_medias: program = Program.add_program(channel, media, min_time=datetime.datetime.now(), max_time=(datetime.datetime.now() + datetime.timedelta(seconds=duration))) logging.info(program) if program: if not programming.get(channel_id, None): programming[channel_id] = [] programming.get(channel_id).append(program.toJson(fetch_channel=False, fetch_media=True, media_desc=False, pub_desc=False)) programs.append(program) logging.info('ADDING: ' + media.name + ' at: ' + program.time.isoformat()) if len(pickle.dumps(programming)) > 1000000: # We can only fit 1mb into memcache break if len(programs): broadcast.broadcastNewPrograms(channel, programs) memcache.set('programming', programming) channels = memcache.get('channels') or [] updated = False for i,c in enumerate(channels): if c['id'] == channel_id: channels[i] = channel.toJson(get_programming=False) updated = True if not updated: channels.append(channel.toJson(get_programming=False)) memcache.set('channels', channels) # Schedule our next programming selection if schedule_next and (not constants.SLEEP_PROGRAMMING or (constants.SLEEP_PROGRAMMING and (kickoff or len(onlineUsers.keys())))): logging.info('NUMBER OF PROGRAMS: ' + str(len(programs))) if len(programs) > 1: next_gen = (programs[-2].time - datetime.datetime.now()).seconds / 2 elif len(programs) == 1: next_gen = programs[0].media.duration / 2 else: next_gen = 60 next_gen = min(next_gen, reduce(lambda x, y: x + y, [p.media.duration for p in programs], 0) \ if len(programs) else 10) next_gen = min(next_gen, duration / 2) logging.info('COUNTDOWN FOR ' + channel_id + ': ' + str(next_gen)) deferred.defer(Programming.set_programming, channel_id, fetch_twitter=fetch_twitter, _name=channel_id + '-' + str(uuid.uuid1()), _countdown=next_gen, _queue=queue) return programs