Example #1
0
	def is_request_needed(self):
		global _request_interval
		global _request_sequence
		if not self.sid in _request_interval:
			_request_interval[self.sid] = cache.get_station(self.sid, "request_interval")
			if not _request_interval[self.sid]:
				_request_interval[self.sid] = 0
		if not self.sid in _request_sequence:
			_request_sequence[self.sid] = cache.get_station(self.sid, "request_sequence")
			if not _request_sequence[self.sid]:
				_request_sequence[self.sid] = 0
				
		# If we're ready for a request sequence, start one
		return_value = None
		if _request_interval[self.sid] <= 0 and _request_sequence[self.sid] <= 0:
			line_length = db.c.fetch_var("SELECT COUNT(*) FROM r4_request_line WHERE sid = %s", (self.sid,))
			_request_sequence[self.sid] = 1 + math.floor(line_length / config.get_station(self.sid, "request_interval_scale"))
			_request_interval[self.sid] = config.get_station(self.sid, "request_interval_gap")
			return_value = True
		# If we are in a request sequence, do one
		elif _request_sequence[self.sid] > 0:
			return_value = True
		else:
			_request_interval[self.sid] -= 1
			return_value = False

		cache.set_station(self.sid, "request_interval", _request_interval[self.sid])
		cache.set_station(self.sid, "request_sequence", _request_sequence[self.sid])
		return return_value
Example #2
0
def get_updated_albums_dict(sid):
    global updated_album_ids
    if not sid in updated_album_ids:
        return []

    previous_newest_album = cache.get_station(sid, "newest_album")
    if not previous_newest_album:
        cache.set_station(sid, "newest_album", timestamp())
    else:
        newest_albums = db.c.fetch_list(
            "SELECT album_id FROM r4_albums JOIN r4_album_sid USING (album_id) WHERE sid = %s AND album_added_on > %s",
            (sid, previous_newest_album))
        for album_id in newest_albums:
            updated_album_ids[sid][album_id] = True
        cache.set_station(sid, "newest_album", timestamp())
    album_diff = []
    for album_id in updated_album_ids[sid]:
        album = Album.load_from_id_sid(album_id, sid)
        album.solve_cool_lowest(sid)
        tmp = album.to_dict_full()
        # Remove user-related stuff since this gets stuffed straight down the pipe
        tmp.pop('rating_user', None)
        tmp.pop('fave', None)
        album_diff.append(tmp)
    return album_diff
Example #3
0
def get_updated_albums_dict(sid):
    global updated_album_ids
    if not sid in updated_album_ids:
        return []

    previous_newest_album = cache.get_station(sid, "newest_album")
    if not previous_newest_album:
        cache.set_station(sid, "newest_album", timestamp())
    else:
        newest_albums = db.c.fetch_list(
            "SELECT album_id FROM r4_albums JOIN r4_album_sid USING (album_id) WHERE sid = %s AND album_added_on > %s",
            (sid, previous_newest_album),
        )
        for album_id in newest_albums:
            updated_album_ids[sid][album_id] = True
        cache.set_station(sid, "newest_album", timestamp())
    album_diff = []
    for album_id in updated_album_ids[sid]:
        album = Album.load_from_id_sid(album_id, sid)
        album.solve_cool_lowest(sid)
        tmp = album.to_dict_full()
        # Remove user-related stuff since this gets stuffed straight down the pipe
        tmp.pop("rating_user", None)
        tmp.pop("fave", None)
        album_diff.append(tmp)
    return album_diff
Example #4
0
	def is_request_needed(self):
		global _request_interval
		global _request_sequence
		if not self.sid in _request_interval:
			_request_interval[self.sid] = cache.get_station(self.sid, "request_interval")
			if not _request_interval[self.sid]:
				_request_interval[self.sid] = 0
		if not self.sid in _request_sequence:
			_request_sequence[self.sid] = cache.get_station(self.sid, "request_sequence")
			if not _request_sequence[self.sid]:
				_request_sequence[self.sid] = 0
		log.debug("requests", "Interval %s // Sequence %s" % (_request_interval, _request_sequence))

		# If we're ready for a request sequence, start one
		return_value = None
		if _request_interval[self.sid] <= 0 and _request_sequence[self.sid] <= 0:
			return_value = True
		# If we are in a request sequence, do one
		elif _request_sequence[self.sid] > 0:
			_request_sequence[self.sid] -= 1
			log.debug("requests", "Still in sequence.  Remainder: %s" % _request_sequence[self.sid])
			return_value = True
		else:
			_request_interval[self.sid] -= 1
			log.debug("requests", "Waiting on interval.  Remainder: %s" % _request_interval[self.sid])
			return_value = False

		cache.set_station(self.sid, "request_interval", _request_interval[self.sid])
		cache.set_station(self.sid, "request_sequence", _request_sequence[self.sid])
		return return_value
Example #5
0
def get_next(sid):
	line = cache.get_station(sid, "request_line")
	if not line:
		return None
	song = None
	for pos in range(0, len(line)):
		if not line[pos] or not line[pos]['song_id']:
			pass
		else:
			entry = line.pop(pos)
			song = playlist.Song.load_from_id(entry['song_id'], sid)
			song.data['elec_request_user_id'] = entry['user_id']
			song.data['elec_request_username'] = entry['username']

			u = User(entry['user_id'])
			db.c.update("DELETE FROM r4_request_store WHERE user_id = %s AND song_id = %s", (u.id, entry['song_id']))
			u.remove_from_request_line()
			user_sid = u.get_tuned_in_sid()
			if u.has_requests():
				u.put_in_request_line(user_sid)
			request_count = db.c.fetch_var("SELECT COUNT(*) FROM r4_request_history WHERE user_id = %s", (u.id,)) + 1
			db.c.update("DELETE FROM r4_request_store WHERE song_id = %s AND user_id = %s", (song.id, u.id))
			db.c.update("INSERT INTO r4_request_history (user_id, song_id, request_wait_time, request_line_size, request_at_count) "
						"VALUES (%s, %s, %s, %s, %s)",
						(u.id, song.id, time.time() - entry['line_wait_start'], len(line), request_count))
			# Update the user's request cache
			u.get_requests(refresh=True)
			cache.set_station(sid, "request_line", line, True)
			break

	return song
Example #6
0
def _process_line(line, sid):
	new_line = []
	# user_positions has user_id as a key and position as the value, this is cached for quick lookups by API requests
	# so users know where they are in line
	user_positions = {}
	t = int(timestamp())
	albums_with_requests = []
	position = 1
	# For each person
	for row in line:
		add_to_line = False
		u = User(row['user_id'])
		row['song_id'] = None
		# If their time is up, remove them and don't add them to the new line
		if row['line_expiry_tune_in'] and row['line_expiry_tune_in'] <= t:
			log.debug("request_line", "%s: Removed user ID %s from line for tune in timeout, expiry time %s current time %s" % (sid, u.id, row['line_expiry_tune_in'], t))
			u.remove_from_request_line()
		else:
			tuned_in_sid = db.c.fetch_var("SELECT sid FROM r4_listeners WHERE user_id = %s AND sid = %s AND listener_purge = FALSE", (u.id, sid))
			tuned_in = True if tuned_in_sid == sid else False
			if tuned_in:
				# Get their top song ID
				song_id = u.get_top_request_song_id(sid)
				# If they have no song and their line expiry has arrived, boot 'em
				if not song_id and row['line_expiry_election'] and (row['line_expiry_election'] <= t):
					log.debug("request_line", "%s: Removed user ID %s from line for election timeout, expiry time %s current time %s" % (sid, u.id, row['line_expiry_election'], t))
					u.remove_from_request_line()
					# Give them more chances if they still have requests
					# They'll get added to the line of whatever station they're tuned in to (if any!)
					if u.has_requests():
						u.put_in_request_line(u.get_tuned_in_sid())
				# If they have no song, start the expiry countdown
				elif not song_id and not row['line_expiry_election']:
					row['line_expiry_election'] = t + 900
					db.c.update("UPDATE r4_request_line SET line_expiry_election = %s WHERE user_id = %s", ((t + 900), row['user_id']))
					add_to_line = True
				# Keep 'em in line
				else:
					if song_id:
						albums_with_requests.append(db.c.fetch_var("SELECT album_id FROM r4_songs WHERE song_id = %s", (song_id,)))
					row['song_id'] = song_id
					add_to_line = True
			elif not row['line_expiry_tune_in'] or row['line_expiry_tune_in'] == 0:
				db.c.update("UPDATE r4_request_line SET line_expiry_tune_in = %s WHERE user_id = %s", ((t + 600), row['user_id']))
				add_to_line = True
			else:
				add_to_line = True
		if add_to_line:
			new_line.append(row)
			user_positions[u.id] = position
			position = position + 1

	cache.set_station(sid, "request_line", new_line, True)
	cache.set_station(sid, "request_user_positions", user_positions, True)

	db.c.update("UPDATE r4_album_sid SET album_requests_pending = NULL WHERE album_requests_pending = TRUE AND sid = %s", (sid,))
	for album_id in albums_with_requests:
		db.c.update("UPDATE r4_album_sid SET album_requests_pending = TRUE WHERE album_id = %s AND sid = %s", (album_id, sid))

	return new_line
Example #7
0
def get_next(sid):
	line = cache.get_station(sid, "request_line")
	if not line:
		return None
	song = None
	for pos in range(0, len(line)):
		if not line[pos]:
			pass  # ?!?!
		elif not line[pos]['song_id']:
			log.debug("request", "Passing on user %s since they have no valid first song." % line[pos]['username'])
		else:
			entry = line.pop(pos)
			song = playlist.Song.load_from_id(entry['song_id'], sid)
			log.debug("request", "Fulfilling %s's request for %s." % (entry['username'], song.filename))
			song.data['elec_request_user_id'] = entry['user_id']
			song.data['elec_request_username'] = entry['username']

			u = User(entry['user_id'])
			db.c.update("DELETE FROM r4_request_store WHERE user_id = %s AND song_id = %s", (u.id, entry['song_id']))
			u.remove_from_request_line()
			if u.has_requests():
				u.put_in_request_line(u.get_tuned_in_sid())
			request_count = db.c.fetch_var("SELECT COUNT(*) FROM r4_request_history WHERE user_id = %s", (u.id,)) + 1
			db.c.update("DELETE FROM r4_request_store WHERE song_id = %s AND user_id = %s", (song.id, u.id))
			db.c.update("INSERT INTO r4_request_history (user_id, song_id, request_wait_time, request_line_size, request_at_count, sid) "
						"VALUES (%s, %s, %s, %s, %s, %s)",
						(u.id, song.id, time.time() - entry['line_wait_start'], len(line), request_count, sid))
			db.c.update("UPDATE phpbb_users SET radio_totalrequests = %s WHERE user_id = %s", (request_count, u.id))
			song.update_request_count(sid)
			# If we fully update the line, the user may sneak in and get 2 requests in the same election.
			# This is not a good idea, so we leave it to the scheduler to issue the full cache update.
			cache.set_station(sid, "request_line", line, True)
			break

	return song
Example #8
0
 def post(self):
     cache.set_station(self.sid, "pause_title", self.get_argument("title"))
     attach_dj_info_to_request(self)
     self.append(
         self.return_name,
         {"success": True, "pause_title": self.get_argument("title")},
     )
Example #9
0
File: dj.py Project: nv043/rainwave
	def post(self):
		new_pw = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for x in range(10))
		result = liquidsoap.set_password(self.sid, new_pw)
		if result.startswith("Variable harbor_pw set (was"):
			cache.set_station(self.sid, "dj_password", new_pw, save_local=True)
			attach_dj_info_to_request(self)
		else:
			raise APIException("internal_error", "Internal error changing DJ key.")
Example #10
0
def update_memcache(sid):
	_update_schedule_memcache(sid)
	cache.prime_rating_cache_for_events(sid, [ current[sid] ] + upnext[sid] + history[sid])
	cache.set_station(sid, "current_listeners", listeners.get_listeners_dict(sid), True)
	cache.set_station(sid, "album_diff", playlist.get_updated_albums_dict(sid), True)
	rainwave.playlist_objects.album.clear_updated_albums(sid)
	cache.set_station(sid, "all_albums", playlist.get_all_albums_list(sid), True)
	cache.set_station(sid, "all_artists", playlist.get_all_artists_list(sid), True)
	cache.set_station(sid, "all_groups", playlist.get_all_groups_list(sid), True)
Example #11
0
 def post(self):
     cache.set_station(self.sid, "backend_paused", True)
     attach_dj_info_to_request(self)
     self.append(
         self.return_name,
         {
             "success": True,
             "message": "At 0:00 the station will go silent and wait for you.",
         },
     )
Example #12
0
def update_live_voting(sid):
	live_voting = {}
	upnext_sid = cache.get_station(sid, "sched_next")
	if not upnext_sid:
		return live_voting
	for event in upnext_sid:
		if event.is_election:
			live_voting[event.id] = db.c.fetch_all("SELECT entry_id, entry_votes, song_id FROM r4_election_entries WHERE elec_id = %s", (event.id,))
	cache.set_station(sid, "live_voting", live_voting)
	return live_voting
Example #13
0
def update_line(sid):
    # Get everyone in the line
    line = db.c.fetch_all(
        "SELECT username, user_id, line_expiry_tune_in, line_expiry_election, line_wait_start FROM r4_request_line JOIN phpbb_users USING (user_id) WHERE sid = %s ORDER BY line_wait_start",
        (sid, ))
    new_line = []
    # user_positions has user_id as a key and position as the value, this is cached for quick lookups by API requests
    # so users know where they are in line
    user_positions = {}
    t = int(time.time())
    position = 1
    # For each person
    for row in line:
        add_to_line = False
        u = User(row['user_id'])
        u.refresh_sid = sid
        row['song_id'] = None
        # If their time is up, remove them and don't add them to the new line
        if row['line_expiry_tune_in'] and row['line_expiry_tune_in'] <= t:
            u.remove_from_request_line()
        else:
            u.refresh()
            # do nothing if they're not tuned in
            if not u.data['radio_tuned_in']:
                pass
            else:
                # Get their top song ID
                song_id = u.get_top_request_song_id(sid)
                # If they have no song and their line expiry has arrived, boot 'em
                if not song_id and row['line_expiry_election'] and (
                        row['line_expiry_election'] <= t):
                    u.remove_from_request_line()
                    # Give them a second chance if they still have requests
                    # They'll get added to the line of whatever station they're tuned in to (if any!)
                    if u.has_requests():
                        u.put_in_request_line(u.get_tuned_in_sid())
                # If they have no song, start the expiry countdown
                elif not song_id:
                    row['line_expiry_election'] = t + 600
                    db.c.update(
                        "UPDATE r4_request_line SET line_expiry_election = %s WHERE user_id = %s",
                        (row['line_expiry_election'], row['user_id']))
                    add_to_line = True
                # Keep 'em in line
                else:
                    row['song_id'] = song_id
                    add_to_line = True
        if add_to_line:
            new_line.append(row)
            user_positions[u.id] = position
            position = position + 1

    cache.set_station(sid, "request_line", new_line, True)
    cache.set_station(sid, "request_user_positions", user_positions, True)
Example #14
0
def update_live_voting(sid):
    live_voting = {}
    upnext_sid = cache.get_station(sid, "sched_next")
    if not upnext_sid:
        return live_voting
    for event in upnext_sid:
        if event.is_election:
            live_voting[event.id] = db.c.fetch_all(
                "SELECT entry_id, entry_votes, song_id FROM r4_election_entries WHERE elec_id = %s",
                (event.id, ))
    cache.set_station(sid, "live_voting", live_voting)
    return live_voting
Example #15
0
def update_line(sid):
	# TODO: This needs code review
	# Get everyone in the line
	line = db.c.fetch_all("SELECT username, user_id, line_expiry_tune_in, line_expiry_election FROM r4_request_line JOIN phpbb_users USING (user_id) WHERE sid = %s ORDER BY line_wait_start", (sid,))
	new_line = []
	user_positions = {}
	t = time.time()
	position = 1
	# For each person
	for row in line:
		add_to_line = False
		u = User(row['user_id'])
		row['song_id'] = None
		# If their time is up, remove them and don't add them to the new line
		if row['line_expiry_tune_in'] <= t:
			u.remove_from_request_line()
		else:
			# refresh the user to get their data, using local cache only - speed things up here
			u.refresh(True)
			# If they're not tuned in and haven't been marked as expiring yet, mark them, add to line, move on
			if not u.data['radio_tuned_in'] and not u.data['radio_tuned_in']:
				row['line_expiry_tune_in'] = t + 600
				add_to_line = True
			# do nothing if they're not tuned in
			elif not u.data['radio_tuned_in']:
				pass
			else:
				# Get their top song ID
				song_id = u.get_top_request_song_id(sid)
				# If they have no song and their line expiry has arrived, boot 'em
				if not song_id and (row['line_expiry_election'] <= t):
					u.remove_from_request_line()
					# Give them a second chance if they still have requests, this is SID-indiscriminate
					# they'll get added to whatever line is their top request
					if u.has_requests():
						u.put_in_request_line(u.get_top_request_sid())
				# If they have no song, start the expiry countdown
				elif not song_id:
					row['line_expiry_election'] = t + 600
					add_to_line = True
				# Keep 'em in line
				else:
					row['song_id'] = song_id
					add_to_line = True
		if add_to_line:
			new_line.append(row)
			user_positions[u.id] = position
			position = position + 1
	
	cache.set_station(sid, "request_line", new_line)
	cache.set_station(sid, "request_user_positions", user_positions)
Example #16
0
def update_line(sid):
	# Get everyone in the line
	line = db.c.fetch_all("SELECT username, user_id, line_expiry_tune_in, line_expiry_election, line_wait_start FROM r4_request_line JOIN phpbb_users USING (user_id) WHERE sid = %s ORDER BY line_wait_start", (sid,))
	new_line = []
	# user_positions has user_id as a key and position as the value, this is cached for quick lookups by API requests
	# so users know where they are in line
	user_positions = {}
	t = int(time.time())
	position = 1
	# For each person
	for row in line:
		add_to_line = False
		u = User(row['user_id'])
		u.refresh_sid = sid
		row['song_id'] = None
		# If their time is up, remove them and don't add them to the new line
		if row['line_expiry_tune_in'] and row['line_expiry_tune_in'] <= t:
			u.remove_from_request_line()
		else:
			u.refresh()
			# do nothing if they're not tuned in
			if not u.data['radio_tuned_in']:
				pass
			else:
				# Get their top song ID
				song_id = u.get_top_request_song_id(sid)
				# If they have no song and their line expiry has arrived, boot 'em
				if not song_id and row['line_expiry_election'] and (row['line_expiry_election'] <= t):
					u.remove_from_request_line()
					# Give them a second chance if they still have requests
					# They'll get added to the line of whatever station they're tuned in to (if any!)
					if u.has_requests():
						u.put_in_request_line(u.get_tuned_in_sid())
				# If they have no song, start the expiry countdown
				elif not song_id:
					row['line_expiry_election'] = t + 600
					db.c.update("UPDATE r4_request_line SET line_expiry_election = %s WHERE user_id = %s", (row['line_expiry_election'], row['user_id']))
					add_to_line = True
				# Keep 'em in line
				else:
					row['song_id'] = song_id
					add_to_line = True
		if add_to_line:
			new_line.append(row)
			user_positions[u.id] = position
			position = position + 1

	cache.set_station(sid, "request_line", new_line, True)
	cache.set_station(sid, "request_user_positions", user_positions, True)
Example #17
0
	def get(self, sid):	#pylint: disable=W0221
		self.success = False
		self.sid = None
		if int(sid) in config.station_ids:
			self.sid = int(sid)
		else:
			return

		if cache.get_station(self.sid, "backend_paused") and cache.get_station(self.sid, "backend_pause_extend"):
			self.write(self._get_pause_file())
			cache.set_station(self.sid, "backend_pause_extend", False)
			cache.set_station(self.sid, "backend_paused_playing", True)
			return
		else:
			cache.set_station(self.sid, "backend_pause_extend", False)
			cache.set_station(self.sid, "backend_paused", False)
			cache.set_station(self.sid, "backend_paused_playing", False)

		# This program must be run on 1 station for 1 instance, which would allow this operation to be safe.
		# Also works if 1 process is serving all stations.  Pinging any instance for any station
		# would break the program here, though.
		if cache.get_station(self.sid, "get_next_socket_timeout") and sid_output[self.sid]:
			log.warn("backend", "Using previous output to prevent flooding.")
			self.write(sid_output[self.sid])
			sid_output[self.sid] = None
			self.success = True
		else:
			try:
				schedule.advance_station(self.sid)
			except (psycopg2.OperationalError, psycopg2.InterfaceError) as e:
				log.warn("backend", e.diag.message_primary)
				db.close()
				db.connect()
				raise
			except psycopg2.extensions.TransactionRollbackError as e:
				log.warn("backend", "Database transaction deadlock.  Re-opening database and setting retry timeout.")
				db.close()
				db.connect()
				raise

			to_send = None
			if not config.get("liquidsoap_annotations"):
				to_send = schedule.get_advancing_file(self.sid)
			else:
				to_send = self._get_annotated(schedule.get_advancing_event(self.sid))
			sid_output[self.sid] = to_send
			self.success = True
			if not cache.get_station(self.sid, "get_next_socket_timeout"):
				self.write(to_send)
Example #18
0
def dj_heartbeat_check():
	# Don't do this in testing environments
	if config.get("developer_mode"):
		return
	for sid in config.station_ids:
		if cache.get_station(sid, "backend_paused_playing"):
			hb = cache.get_station(sid, "dj_heartbeat")
			hbs = cache.get_station(sid, "dj_heartbeat_start")
			if not hbs or ((timestamp() - hbs) <= 10):
				pass
			elif not hb or ((timestamp() - hb) >= 15):
				log.warn("dj_heartbeat", "DJ heart attack - resetting station to normal.")
				cache.set_station(sid, "backend_paused", False)
				cache.set_station(sid, "backend_paused_playing", False)
				liquidsoap.kick_dj(sid)
				liquidsoap.skip(sid)
Example #19
0
    def get(self, sid):
        self.success = False
        self.sid = None
        if int(sid) in config.station_ids:
            self.sid = int(sid)
        else:
            return

        if cache.get_station(self.sid, "backend_paused"):
            if not cache.get_station(self.sid, "dj_heartbeat_start"):
                log.debug("dj", "Setting server start heatbeat.")
                cache.set_station(self.sid, "dj_heartbeat_start", timestamp())
            self.write(self._get_pause_file())
            schedule.set_upnext_crossfade(self.sid, False)
            cache.set_station(self.sid, "backend_paused_playing", True)
            sync_to_front.sync_frontend_dj(self.sid)
            return
        else:
            cache.set_station(self.sid, "dj_heartbeat_start", False)
            cache.set_station(self.sid, "backend_paused", False)
            cache.set_station(self.sid, "backend_paused_playing", False)

        try:
            schedule.advance_station(self.sid)
        except (psycopg2.OperationalError, psycopg2.InterfaceError) as e:
            log.warn("backend", e.diag.message_primary)
            db.close()
            db.connect()
            raise
        except psycopg2.extensions.TransactionRollbackError as e:
            log.warn(
                "backend",
                "Database transaction deadlock.  Re-opening database and setting retry timeout.",
            )
            db.close()
            db.connect()
            raise

        to_send = None
        if not config.get("liquidsoap_annotations"):
            to_send = schedule.get_advancing_file(self.sid)
        else:
            to_send = self._get_annotated(
                schedule.get_advancing_event(self.sid))
        self.success = True
        if not cache.get_station(self.sid, "get_next_socket_timeout"):
            self.write(to_send)
Example #20
0
    def is_request_needed(self):
        global _request_interval
        global _request_sequence
        if not self.sid in _request_interval:
            _request_interval[self.sid] = cache.get_station(
                self.sid, "request_interval")
            if not _request_interval[self.sid]:
                _request_interval[self.sid] = 0
        if not self.sid in _request_sequence:
            _request_sequence[self.sid] = cache.get_station(
                self.sid, "request_sequence")
            if not _request_sequence[self.sid]:
                _request_sequence[self.sid] = 0
        log.debug(
            "requests",
            "Interval %s // Sequence %s" %
            (_request_interval, _request_sequence),
        )

        # If we're ready for a request sequence, start one
        return_value = None
        if _request_interval[self.sid] <= 0 and _request_sequence[
                self.sid] <= 0:
            return_value = True
        # If we are in a request sequence, do one
        elif _request_sequence[self.sid] > 0:
            _request_sequence[self.sid] -= 1
            log.debug(
                "requests",
                "Still in sequence.  Remainder: %s" %
                _request_sequence[self.sid],
            )
            return_value = True
        else:
            _request_interval[self.sid] -= 1
            log.debug(
                "requests",
                "Waiting on interval.  Remainder: %s" %
                _request_interval[self.sid],
            )
            return_value = False

        cache.set_station(self.sid, "request_interval",
                          _request_interval[self.sid])
        cache.set_station(self.sid, "request_sequence",
                          _request_sequence[self.sid])
        return return_value
Example #21
0
def dj_heartbeat_check():
    # Don't do this in testing environments
    if config.get("developer_mode"):
        return
    for sid in config.station_ids:
        if cache.get_station(sid, "backend_paused_playing"):
            hb = cache.get_station(sid, "dj_heartbeat")
            hbs = cache.get_station(sid, "dj_heartbeat_start")
            if not hbs or ((timestamp() - hbs) <= 10):
                pass
            elif not hb or ((timestamp() - hb) >= 15):
                log.warn("dj_heartbeat",
                         "DJ heart attack - resetting station to normal.")
                cache.set_station(sid, "backend_paused", False)
                cache.set_station(sid, "backend_paused_playing", False)
                liquidsoap.kick_dj(sid)
                liquidsoap.skip(sid)
Example #22
0
	def post(self):
		if not cache.get_station(self.sid, "backend_paused"):
			result = "Station seems unpaused already.  "
		else:
			result = "Unpausing station.  "
		cache.set_station(self.sid, "backend_paused", False)
		cache.set_station(self.sid, "backend_pause_extend", False)
		if (cache.get_station(self.sid, "backend_paused_playing")):
			result += "Automatically starting music.  "
			result += "\n"
			result += liquidsoap.skip(self.sid)
		else:
			result += "If station remains silent, music will start playing within 5 minutes unless you hit skip."
		if (self.get_argument("kick_dj", default=False)):
				result += "Kicking DJ.  "
				result += "\n"
				result += liquidsoap.kick_dj(self.sid)
		self.append(self.return_name, { "success": True, "message": result })
Example #23
0
File: dj.py Project: nv043/rainwave
	def post(self):
		if not cache.get_station(self.sid, "backend_paused"):
			result = "Station seems unpaused already.  "
		else:
			result = "Unpausing station.  "
		cache.set_station(self.sid, "backend_paused", False)
		if (cache.get_station(self.sid, "backend_paused_playing")):
			result += "Automatically starting music.  "
			result += "\n"
			result += liquidsoap.skip(self.sid)
		else:
			result += "If station remains silent, music will start playing within 5 minutes unless you hit skip."
		if (self.get_argument("kick_dj", default=False)):
				result += "Kicking DJ.  "
				result += "\n"
				result += liquidsoap.kick_dj(self.sid)
		attach_dj_info_to_request(self)
		self.append(self.return_name, { "success": True, "message": result })
Example #24
0
	def get(self, sid):	#pylint: disable=W0221
		self.success = False
		self.sid = None
		if int(sid) in config.station_ids:
			self.sid = int(sid)
		else:
			return

		if cache.get_station(self.sid, "backend_paused"):
			if not cache.get_station(self.sid, "dj_heartbeat_start"):
				log.debug("dj", "Setting server start heatbeat.")
				cache.set_station(self.sid, "dj_heartbeat_start", timestamp())
			self.write(self._get_pause_file())
			schedule.set_upnext_crossfade(self.sid, False)
			cache.set_station(self.sid, "backend_paused_playing", True)
			sync_to_front.sync_frontend_dj(self.sid)
			return
		else:
			cache.set_station(self.sid, "dj_heartbeat_start", False)
			cache.set_station(self.sid, "backend_paused", False)
			cache.set_station(self.sid, "backend_paused_playing", False)

		try:
			schedule.advance_station(self.sid)
		except (psycopg2.OperationalError, psycopg2.InterfaceError) as e:
			log.warn("backend", e.diag.message_primary)
			db.close()
			db.connect()
			raise
		except psycopg2.extensions.TransactionRollbackError as e:
			log.warn("backend", "Database transaction deadlock.  Re-opening database and setting retry timeout.")
			db.close()
			db.connect()
			raise

		to_send = None
		if not config.get("liquidsoap_annotations"):
			to_send = schedule.get_advancing_file(self.sid)
		else:
			to_send = self._get_annotated(schedule.get_advancing_event(self.sid))
		self.success = True
		if not cache.get_station(self.sid, "get_next_socket_timeout"):
			self.write(to_send)
Example #25
0
def get_next(sid):
    line = cache.get_station(sid, "request_line")
    if not line:
        return None
    song = None
    for pos in range(0, len(line)):
        if not line[pos] or not line[pos]['song_id']:
            pass
        else:
            entry = line.pop(pos)
            song = playlist.Song.load_from_id(entry['song_id'], sid)
            song.data['elec_request_user_id'] = entry['user_id']
            song.data['elec_request_username'] = entry['username']

            u = User(entry['user_id'])
            db.c.update(
                "DELETE FROM r4_request_store WHERE user_id = %s AND song_id = %s",
                (u.id, entry['song_id']))
            u.remove_from_request_line()
            user_sid = u.get_tuned_in_sid()
            if u.has_requests():
                u.put_in_request_line(user_sid)
            request_count = db.c.fetch_var(
                "SELECT COUNT(*) FROM r4_request_history WHERE user_id = %s",
                (u.id, )) + 1
            db.c.update(
                "DELETE FROM r4_request_store WHERE song_id = %s AND user_id = %s",
                (song.id, u.id))
            db.c.update(
                "INSERT INTO r4_request_history (user_id, song_id, request_wait_time, request_line_size, request_at_count) "
                "VALUES (%s, %s, %s, %s, %s)",
                (u.id, song.id, time.time() - entry['line_wait_start'],
                 len(line), request_count))
            # Update the user's request cache
            u.get_requests(refresh=True)
            cache.set_station(sid, "request_line", line, True)
            break

    return song
Example #26
0
def get_next(sid):
	# TODO: Code review
	line = cache.get_station(sid, "request_line")
	song = None
	for pos in range(0, len(line)):
		if not line['song_id']:
			pass
		else:
			entry = line.pop(pos)
			song = playlist.Song.load_from_id(entry['song_id'], sid)
			song.data['elec_request_user_id'] = entry['user_id']
			song.data['elec_request_username'] = entry['username']
			
			db.c.update("DELETE FROM r4_request_store WHERE user_id = %s AND song_id = %s", (u.id, request['song_id']))
			u = User(entry['user_id'])
			u.remove_from_request_line()
			if u.has_requests():
				u.put_in_request_line(u.get_top_request_sid())
			cache.set_station(sid, "request_line", line)
			break

	return song
Example #27
0
def get_updated_albums_dict(sid):
    global updated_album_ids
    if not sid in updated_album_ids:
        return []

    previous_newest_album = cache.get_station(sid, "newest_album")
    if not previous_newest_album:
        cache.set_station(sid, "newest_album", timestamp())
    else:
        newest_albums = db.c.fetch_list(
            "SELECT album_id FROM r4_albums JOIN r4_album_sid USING (album_id) WHERE sid = %s AND album_added_on > %s",
            (sid, previous_newest_album),
        )
        for album_id in newest_albums:
            updated_album_ids[sid][album_id] = True
        cache.set_station(sid, "newest_album", timestamp())
    album_diff = []
    for album_id in updated_album_ids[sid]:
        album = Album.load_from_id_sid(album_id, sid)
        album.solve_cool_lowest(sid)
        album_diff.append(album.to_album_diff())
    return album_diff
Example #28
0
def reset_schedule(sid):
    # Reset the schedule
    schedule.current = {}
    schedule.upnext = {}
    schedule.history = {}
    cache.set_station(sid, "sched_current", None, True)
    cache.set_station(sid, "sched_next", None, True)
    cache.set_station(sid, "sched_history", None, True)
    playlist.remove_all_locks(1)
Example #29
0
def reset_schedule(sid):
	# Reset the schedule
	schedule.current = {}
	schedule.upnext = {}
	schedule.history = {}
	cache.set_station(sid, "sched_current", None, True)
	cache.set_station(sid, "sched_next", None, True)
	cache.set_station(sid, "sched_history", None, True)
	playlist.remove_all_locks(1)
Example #30
0
parser = argparse.ArgumentParser(
    description="Fetches the next song from a Rainwave backend daemon.")
parser.add_argument("--dest", "-d", required=False, default="127.0.0.1")
parser.add_argument("--sid", "-s", required=False, default=1)
parser.add_argument("--config", "-c", required=False, default=None)
args = parser.parse_args()

config.load(args.config)
cache.open()

params = urllib.urlencode({"sid": args.sid})
try:
    conn = httplib.HTTPConnection(args.dest,
                                  config.get("backend_port"),
                                  timeout=10)
    conn.request("GET", "/advance/%s" % args.sid)
    result = conn.getresponse()
    if result.status == 200:
        print result.read()
    else:
        raise Exception("Backend HTTP Error %s" % result.status)
    cache.set_station(args.sid, "backend_ok", True)
    cache.set_station(args.sid, "backend_message", "OK")
    conn.close()
except Exception as e:
    cache.set_station(args.sid, "backend_ok", False)
    cache.set_station(args.sid, "backend_status", repr(e))
    if conn:
        conn.close()
    raise
Example #31
0
def _update_memcache(sid):
	cache.set_station(sid, "sched_current", current[sid])
Example #32
0
def _update_schedule_memcache(sid):
	cache.set_station(sid, "sched_current", current[sid], True)
	cache.set_station(sid, "sched_next", upnext[sid], True)
	cache.set_station(sid, "sched_history", history[sid], True)

	sched_current_dict = current[sid].to_dict()
	cache.set_station(sid, "sched_current_dict", sched_current_dict, True)
	
	next_dict_list = []
	for event in upnext[sid]:
		next_dict_list.append(event.to_dict())
	cache.set_station(sid, "sched_next_dict", next_dict_list, True)
	
	history_dict_list = []
	for event in history[sid]:
		history_dict_list.append(event.to_dict())
	cache.set_station(sid, "sched_history_dict", history_dict_list, True)

	all_station = {}
	if 'songs' in sched_current_dict:
		all_station['title'] = sched_current_dict['songs'][0]['title']
		all_station['album'] = sched_current_dict['songs'][0]['albums'][0]['name']
		all_station['art'] = sched_current_dict['songs'][0]['albums'][0]['art']
	else:
		all_station['title'] = sched_current_dict['name']
		all_station['album'] = ""
		all_station['art'] = None
	cache.set_station(sid, "all_station_info", all_station, True)
Example #33
0
def _process_line(line, sid):
    new_line = []
    # user_positions has user_id as a key and position as the value, this is cached for quick lookups by API requests
    # so users know where they are in line
    user_positions = {}
    t = int(timestamp())
    albums_with_requests = []
    position = 1
    user_viewable_position = 1
    valid_positions = 0
    # For each person
    for row in line:
        add_to_line = False
        u = User(row["user_id"])
        row["song_id"] = None
        # If their time is up, remove them and don't add them to the new line
        if row["line_expiry_tune_in"] and row["line_expiry_tune_in"] <= t:
            log.debug(
                "request_line",
                "%s: Removed user ID %s from line for tune in timeout, expiry time %s current time %s"
                % (sid, u.id, row["line_expiry_tune_in"], t),
            )
            u.remove_from_request_line()
        else:
            tuned_in_sid = db.c.fetch_var(
                "SELECT sid FROM r4_listeners WHERE user_id = %s AND sid = %s AND listener_purge = FALSE",
                (u.id, sid),
            )
            tuned_in = True if tuned_in_sid == sid else False
            if tuned_in:
                # Get their top song ID
                song_id = u.get_top_request_song_id(sid)
                if song_id and not row["line_has_had_valid"]:
                    row["line_has_had_valid"] = True
                    db.c.update(
                        "UPDATE r4_request_line SET line_has_had_valid = TRUE WHERE user_id = %s",
                        (u.id, ),
                    )
                if row["line_has_had_valid"]:
                    valid_positions += 1
                # If they have no song and their line expiry has arrived, boot 'em
                if (not song_id and row["line_expiry_election"]
                        and (row["line_expiry_election"] <= t)):
                    log.debug(
                        "request_line",
                        "%s: Removed user ID %s from line for election timeout, expiry time %s current time %s"
                        % (sid, u.id, row["line_expiry_election"], t),
                    )
                    u.remove_from_request_line()
                    # Give them more chances if they still have requests
                    # They'll get added to the line of whatever station they're tuned in to (if any!)
                    if u.has_requests():
                        u.put_in_request_line(u.get_tuned_in_sid())
                # If they have no song and they're in 2nd or 1st, start the expiry countdown
                elif not song_id and not row[
                        "line_expiry_election"] and position <= 2:
                    log.debug(
                        "request_line",
                        "%s: User ID %s has no valid requests, beginning boot countdown."
                        % (sid, u.id),
                    )
                    row["line_expiry_election"] = t + 900
                    db.c.update(
                        "UPDATE r4_request_line SET line_expiry_election = %s WHERE user_id = %s",
                        ((t + 900), row["user_id"]),
                    )
                    add_to_line = True
                # Keep 'em in line
                else:
                    log.debug("request_line",
                              "%s: User ID %s is in line." % (sid, u.id))
                    if song_id:
                        albums_with_requests.append(
                            db.c.fetch_var(
                                "SELECT album_id FROM r4_songs WHERE song_id = %s",
                                (song_id, ),
                            ))
                        row["song"] = db.c.fetch_row(
                            "SELECT song_id AS id, song_title AS title, album_name FROM r4_songs JOIN r4_albums USING (album_id) WHERE song_id = %s",
                            (song_id, ),
                        )
                    else:
                        row["song"] = None
                    row["song_id"] = song_id
                    add_to_line = True
            elif not row["line_expiry_tune_in"] or row[
                    "line_expiry_tune_in"] == 0:
                log.debug(
                    "request_line",
                    "%s: User ID %s being marked as tuned out." % (sid, u.id),
                )
                db.c.update(
                    "UPDATE r4_request_line SET line_expiry_tune_in = %s WHERE user_id = %s",
                    ((t + 600), row["user_id"]),
                )
                add_to_line = True
            else:
                log.debug(
                    "request_line",
                    "%s: User ID %s not tuned in, waiting on expiry for action."
                    % (sid, u.id),
                )
                add_to_line = True
        row["skip"] = not add_to_line
        row["position"] = user_viewable_position
        new_line.append(row)
        user_positions[u.id] = user_viewable_position
        user_viewable_position = user_viewable_position + 1
        if add_to_line:
            position = position + 1

    log.debug("request_line",
              "Request line valid positions: %s" % valid_positions)
    cache.set_station(sid, "request_valid_positions", valid_positions)
    cache.set_station(sid, "request_line", new_line, True)
    cache.set_station(sid, "request_user_positions", user_positions, True)

    db.c.update(
        "UPDATE r4_album_sid SET album_requests_pending = NULL WHERE album_requests_pending = TRUE AND sid = %s",
        (sid, ),
    )
    for album_id in albums_with_requests:
        db.c.update(
            "UPDATE r4_album_sid SET album_requests_pending = TRUE WHERE album_id = %s AND sid = %s",
            (album_id, sid),
        )

    return new_line
Example #34
0
File: dj.py Project: nv043/rainwave
	def post(self):
		cache.set_station(self.sid, "dj_heartbeat", timestamp())
		self.append(self.return_name, { "success": True })
Example #35
0
def _update_memcache(sid):
    cache.set_station(sid, "sched_current", current[sid], True)
    cache.set_station(sid, "sched_next", next[sid], True)
    cache.set_station(sid, "sched_history", history[sid], True)
    cache.set_station(sid, "sched_current_dict", current[sid].to_dict(), True)
    next_dict_list = []
    for event in next[sid]:
        next_dict_list.append(event.to_dict())
    cache.set_station(sid, "sched_next_dict", next_dict_list, True)
    history_dict_list = []
    for event in history[sid]:
        history_dict_list.append(event.to_dict())
    cache.set_station(sid, "sched_history_dict", history_dict_list, True)
    cache.prime_rating_cache_for_events([current[sid]] + next[sid] +
                                        history[sid])
    cache.set_station(sid, "listeners_current",
                      listeners.get_listeners_dict(sid), True)
    cache.set_station(sid, "album_diff", playlist.get_updated_albums_dict(sid),
                      True)
    playlist.clear_updated_albums(sid)
    cache.set_station(sid, "all_albums", playlist.get_all_albums_list(sid),
                      True)
    cache.set_station(sid, "all_artists", playlist.get_all_artists_list(sid),
                      True)
Example #36
0
def _process_line(line, sid):
	new_line = []
	# user_positions has user_id as a key and position as the value, this is cached for quick lookups by API requests
	# so users know where they are in line
	user_positions = {}
	t = int(timestamp())
	albums_with_requests = []
	position = 1
	user_viewable_position = 1
	valid_positions = 0
	# For each person
	for row in line:
		add_to_line = False
		u = User(row['user_id'])
		row['song_id'] = None
		# If their time is up, remove them and don't add them to the new line
		if row['line_expiry_tune_in'] and row['line_expiry_tune_in'] <= t:
			log.debug("request_line", "%s: Removed user ID %s from line for tune in timeout, expiry time %s current time %s" % (sid, u.id, row['line_expiry_tune_in'], t))
			u.remove_from_request_line()
		else:
			tuned_in_sid = db.c.fetch_var("SELECT sid FROM r4_listeners WHERE user_id = %s AND sid = %s AND listener_purge = FALSE", (u.id, sid))
			tuned_in = True if tuned_in_sid == sid else False
			if tuned_in:
				# Get their top song ID
				song_id = u.get_top_request_song_id(sid)
				if song_id and not row['line_has_had_valid']:
					row['line_has_had_valid'] = True
					db.c.update("UPDATE r4_request_line SET line_has_had_valid = TRUE WHERE user_id = %s", (u.id, ))
				if row['line_has_had_valid']:
					valid_positions += 1
				# If they have no song and their line expiry has arrived, boot 'em
				if not song_id and row['line_expiry_election'] and (row['line_expiry_election'] <= t):
					log.debug("request_line", "%s: Removed user ID %s from line for election timeout, expiry time %s current time %s" % (sid, u.id, row['line_expiry_election'], t))
					u.remove_from_request_line()
					# Give them more chances if they still have requests
					# They'll get added to the line of whatever station they're tuned in to (if any!)
					if u.has_requests():
						u.put_in_request_line(u.get_tuned_in_sid())
				# If they have no song and they're in 2nd or 1st, start the expiry countdown
				elif not song_id and not row['line_expiry_election'] and position <= 2:
					log.debug("request_line", "%s: User ID %s has no valid requests, beginning boot countdown." % (sid, u.id))
					row['line_expiry_election'] = t + 900
					db.c.update("UPDATE r4_request_line SET line_expiry_election = %s WHERE user_id = %s", ((t + 900), row['user_id']))
					add_to_line = True
				# Keep 'em in line
				else:
					log.debug("request_line", "%s: User ID %s is in line." % (sid, u.id))
					if song_id:
						albums_with_requests.append(db.c.fetch_var("SELECT album_id FROM r4_songs WHERE song_id = %s", (song_id,)))
						row['song'] = db.c.fetch_row("SELECT song_id AS id, song_title AS title, album_name FROM r4_songs JOIN r4_albums USING (album_id) WHERE song_id = %s", (song_id,))
					else:
						row['song'] = None
					row['song_id'] = song_id
					add_to_line = True
			elif not row['line_expiry_tune_in'] or row['line_expiry_tune_in'] == 0:
				log.debug("request_line", "%s: User ID %s being marked as tuned out." % (sid, u.id))
				db.c.update("UPDATE r4_request_line SET line_expiry_tune_in = %s WHERE user_id = %s", ((t + 600), row['user_id']))
				add_to_line = True
			else:
				log.debug("request_line", "%s: User ID %s not tuned in, waiting on expiry for action." % (sid, u.id))
				add_to_line = True
		row['skip'] = not add_to_line
		row['position'] = user_viewable_position
		new_line.append(row)
		user_positions[u.id] = user_viewable_position
		user_viewable_position = user_viewable_position + 1
		if add_to_line:
			position = position + 1

	log.debug("request_line", "Request line valid positions: %s" % valid_positions)
	cache.set_station(sid, 'request_valid_positions', valid_positions)
	cache.set_station(sid, "request_line", new_line, True)
	cache.set_station(sid, "request_user_positions", user_positions, True)

	db.c.update("UPDATE r4_album_sid SET album_requests_pending = NULL WHERE album_requests_pending = TRUE AND sid = %s", (sid,))
	for album_id in albums_with_requests:
		db.c.update("UPDATE r4_album_sid SET album_requests_pending = TRUE WHERE album_id = %s AND sid = %s", (album_id, sid))

	return new_line
Example #37
0
	def post(self):
		cache.set_station(self.sid, "backend_paused", True)
		cache.set_station(self.sid, "backend_pause_extend", True)
		self.append(self.return_name, { "success": True, "message": "At 0:00 the station will go silent and wait for you." })
Example #38
0
	else:
		dest_port += int(list(config.station_ids)[0])
	timeout = 5 if cache.get_station(args.sid, "backend_ok") else 120
	conn = httplib.HTTPConnection(args.dest, config.get("backend_port") + int(args.sid), timeout=timeout)
	conn.request("GET", "/advance/%s" % args.sid)
	result = conn.getresponse()
	if result.status == 200:
		next_song_filename = result.read()
		if not next_song_filename or len(next_song_filename) == 0:
			raise Exception("Got zero-length filename from backend!")
		if os.name == "nt":
			next_song_filename = next_song_filename.replace("\\", "/")
		print next_song_filename
	else:
		raise Exception("HTTP Error %s trying to reach backend!" % result.status)
	cache.set_station(args.sid, "backend_ok", True)
	cache.set_station(args.sid, "backend_message", "OK")
	conn.close()
except socket.timeout as e:
	cache.set_station(args.sid, "backend_ok", False)
	cache.set_station(args.sid, "backend_status", repr(e))
	time.sleep(2)
	raise
except Exception as e:
	cache.set_station(args.sid, "backend_ok", False)
	cache.set_station(args.sid, "backend_status", repr(e))
	if conn:
		conn.close()
	time.sleep(2)
	raise
Example #39
0
def _update_schedule_memcache(sid):
    cache.set_station(sid, "sched_current", current[sid], True)
    cache.set_station(sid, "sched_next", upnext[sid], True)
    cache.set_station(sid, "sched_history", history[sid], True)

    sched_current_dict = current[sid].to_dict()
    cache.set_station(sid, "sched_current_dict", sched_current_dict, True)

    next_dict_list = []
    for event in upnext[sid]:
        next_dict_list.append(event.to_dict())
    cache.set_station(sid, "sched_next_dict", next_dict_list, True)

    history_dict_list = []
    for event in history[sid]:
        history_dict_list.append(event.to_dict())
    cache.set_station(sid, "sched_history_dict", history_dict_list, True)

    all_station = {}
    if "songs" in sched_current_dict:
        all_station["title"] = sched_current_dict["songs"][0]["title"]
        all_station["album"] = sched_current_dict["songs"][0]["albums"][0]["name"]
        all_station["art"] = sched_current_dict["songs"][0]["albums"][0]["art"]
        all_station["artists"] = ", ".join(artist['name'] for artist in sched_current_dict["songs"][0]["artists"])
    else:
        all_station["title"] = None
        all_station["album"] = None
        all_station["art"] = None
        all_station["artists"] = None
    all_station["event_name"] = sched_current_dict["name"]
    all_station["event_type"] = sched_current_dict["type"]
    cache.set_station(sid, "all_station_info", all_station, True)
Example #40
0
def update_memcache(sid):
    _update_schedule_memcache(sid)
    update_live_voting(sid)
    cache.prime_rating_cache_for_events(sid, [current[sid]] + upnext[sid] + history[sid])
    cache.set_station(sid, "current_listeners", listeners.get_listeners_dict(sid), True)
    cache.set_station(sid, "album_diff", playlist.get_updated_albums_dict(sid), True)
    rainwave.playlist_objects.album.clear_updated_albums(sid)
    cache.set_station(sid, "all_albums", playlist.get_all_albums_list(sid), True)
    cache.set_station(sid, "all_artists", playlist.get_all_artists_list(sid), True)
    cache.set_station(sid, "all_groups", playlist.get_all_groups_list(sid), True)
    cache.set_station(sid, "all_groups_power", playlist.get_all_groups_for_power(sid), True)

    potential_dj_ids = []
    if getattr(current[sid], "dj_user_id", None):
        potential_dj_ids.append(current[sid].dj_user_id)
    for evt in upnext[sid]:
        if getattr(evt, "dj_user_id", None):
            potential_dj_ids.append(evt.dj_user_id)
    if len(history[sid]) and history[sid][-1] and getattr(history[sid][-1], "dj_user_id", None):
        potential_dj_ids.append(history[sid][-1].dj_user_id)
    cache.set_station(sid, "dj_user_ids", potential_dj_ids)
Example #41
0
def _update_schedule_memcache(sid):
    cache.set_station(sid, "sched_current", current[sid], True)
    cache.set_station(sid, "sched_next", upnext[sid], True)
    cache.set_station(sid, "sched_history", history[sid], True)

    sched_current_dict = current[sid].to_dict()
    cache.set_station(sid, "sched_current_dict", sched_current_dict, True)

    next_dict_list = []
    for event in upnext[sid]:
        next_dict_list.append(event.to_dict())
    cache.set_station(sid, "sched_next_dict", next_dict_list, True)

    history_dict_list = []
    for event in history[sid]:
        history_dict_list.append(event.to_dict())
    cache.set_station(sid, "sched_history_dict", history_dict_list, True)

    all_station = {}
    if "songs" in sched_current_dict:
        all_station["title"] = sched_current_dict["songs"][0]["title"]
        all_station["album"] = sched_current_dict["songs"][0]["albums"][0]["name"]
        all_station["art"] = sched_current_dict["songs"][0]["albums"][0]["art"]
    else:
        all_station["title"] = None
        all_station["album"] = None
        all_station["art"] = None
    all_station["event_name"] = sched_current_dict["name"]
    all_station["event_type"] = sched_current_dict["type"]
    cache.set_station(sid, "all_station_info", all_station, True)
Example #42
0
	def _listen(self, task_id):
		zeromq.init_pub()
		zeromq.init_sub()

		import api_requests.sync
		api_requests.sync.init()

		# task_ids start at zero, so we gobble up ports starting at the base port and work up
		port_no = int(config.get("api_base_port")) + task_id

		pid = os.getpid()
		pid_file = open("%s/api_%s.pid" % (config.get_directory("pid_dir"), port_no), 'w')
		pid_file.write(str(pid))
		pid_file.close()

		# Log according to configured directory and port # we're operating on
		log_file = "%s/rw_api_%s.log" % (config.get_directory("log_dir"), port_no)
		if config.test_mode and os.path.exists(log_file):
			os.remove(log_file)
		log.init(log_file, config.get("log_level"))
		log.debug("start", "Server booting, port %s." % port_no)
		db.connect()
		cache.connect()
		memory_trace.setup(port_no)

		api.locale.load_translations()
		api.locale.compile_static_language_files()

		if config.get("web_developer_mode"):
			for station_id in config.station_ids:
				playlist.prepare_cooldown_algorithm(station_id)
			# automatically loads every station ID and fills things in if there's no data
			schedule.load()
			for station_id in config.station_ids:
				schedule.update_memcache(station_id)
				rainwave.request.update_line(station_id)
				rainwave.request.update_expire_times()
				cache.set_station(station_id, "backend_ok", True)
				cache.set_station(station_id, "backend_message", "OK")
				cache.set_station(station_id, "get_next_socket_timeout", False)

		for sid in config.station_ids:
			cache.update_local_cache_for_sid(sid)
			playlist.prepare_cooldown_algorithm(sid)
			playlist.update_num_songs()

		# If we're not in developer, remove development-related URLs
		if not config.get("developer_mode"):
			i = 0
			while (i < len(request_classes)):
				if request_classes[i][0].find("/test/") != -1:
					request_classes.pop(i)
					i = i - 1
				i = i + 1

		# Make sure all other errors get handled in an API-friendly way
		request_classes.append((r"/api/.*", api.web.Error404Handler))
		request_classes.append((r"/api4/.*", api.web.Error404Handler))
		request_classes.append((r".*", api.web.HTMLError404Handler))

		# Initialize the help (rather than it scan all URL handlers every time someone hits it)
		api.help.sectionize_requests()

		# Fire ze missiles!
		global app
		app = tornado.web.Application(request_classes,
			debug=(config.test_mode or config.get("developer_mode")),
			template_path=os.path.join(os.path.dirname(__file__), "../templates"),
			static_path=os.path.join(os.path.dirname(__file__), "../static"),
			autoescape=None)
		http_server = tornado.httpserver.HTTPServer(app, xheaders = True)
		http_server.listen(port_no)

		if config.get("api_user") and config.get("api_group"):
			chuser.change_user(config.get("api_user"), config.get("api_group"))

		for request in request_classes:
			log.debug("start", "   Handler: %s" % str(request))
		log.info("start", "API server on port %s ready to go." % port_no)
		self.ioloop = tornado.ioloop.IOLoop.instance()

		try:
			self.ioloop.start()
		finally:
			self.ioloop.stop()
			http_server.stop()
			db.close()
			log.info("stop", "Server has been shutdown.")
			log.close()
Example #43
0
	def post(self):
		cache.set_station(self.sid, "backend_paused", False)
		result = liquidsoap.unpause(self.sid)
		self.append(self.return_name, { "success": True, "message": result })
Example #44
0
    # Windows, no multiprocessing
    else:
        dest_port += int(list(config.station_ids)[0])
    conn = httplib.HTTPConnection(args.dest,
                                  config.get("backend_port") + int(args.sid),
                                  timeout=3)
    conn.request("GET", "/advance/%s" % args.sid)
    result = conn.getresponse()
    if result.status == 200:
        next_song_filename = result.read()
        if not next_song_filename or len(next_song_filename) == 0:
            raise Exception("Got zero-length filename from backend!")
        print next_song_filename
    else:
        raise Exception("Backend HTTP Error %s" % result.status)
    cache.set_station(args.sid, "backend_ok", True)
    cache.set_station(args.sid, "backend_message", "OK")
    cache.set_station(args.sid, "get_next_socket_timeout", False)
    conn.close()
except socket.timeout as e:
    cache.set_station(args.sid, "backend_ok", False)
    cache.set_station(args.sid, "backend_status", repr(e))
    cache.set_station(args.sid, "get_next_socket_timeout", True)
    time.sleep(2)
    raise
except Exception as e:
    cache.set_station(args.sid, "backend_ok", False)
    cache.set_station(args.sid, "backend_status", repr(e))
    if conn:
        conn.close()
    time.sleep(2)
Example #45
0
    def _listen(self, task_id):
        zeromq.init_pub()
        zeromq.init_sub()

        import api_requests.sync

        api_requests.sync.init()

        # task_ids start at zero, so we gobble up ports starting at the base port and work up
        port_no = int(config.get("api_base_port")) + task_id

        # Log according to configured directory and port # we're operating on
        log_file = "%s/rw_api_%s.log" % (config.get_directory("log_dir"),
                                         port_no)
        log.init(log_file, config.get("log_level"))
        log.debug("start", "Server booting, port %s." % port_no)
        db.connect(auto_retry=False, retry_only_this_time=True)
        cache.connect()
        memory_trace.setup(port_no)

        api.locale.load_translations()
        api.locale.compile_static_language_files()

        if config.get("developer_mode"):
            for station_id in config.station_ids:
                playlist.prepare_cooldown_algorithm(station_id)
            # automatically loads every station ID and fills things in if there's no data
            schedule.load()
            for station_id in config.station_ids:
                schedule.update_memcache(station_id)
                rainwave.request.update_line(station_id)
                rainwave.request.update_expire_times()
                cache.set_station(station_id, "backend_ok", True)
                cache.set_station(station_id, "backend_message", "OK")
                cache.set_station(station_id, "get_next_socket_timeout", False)

        for sid in config.station_ids:
            cache.update_local_cache_for_sid(sid)
            playlist.prepare_cooldown_algorithm(sid)
            playlist.update_num_songs()

        # If we're not in developer, remove development-related URLs
        if not config.get("developer_mode"):
            i = 0
            while i < len(request_classes):
                if request_classes[i][0].find("/test/") != -1:
                    request_classes.pop(i)
                    i = i - 1
                i = i + 1

        # Make sure all other errors get handled in an API-friendly way
        request_classes.append((r"/api/.*", api.web.Error404Handler))
        request_classes.append((r"/api4/.*", api.web.Error404Handler))
        request_classes.append((r".*", api.web.HTMLError404Handler))

        # Initialize the help (rather than it scan all URL handlers every time someone hits it)
        api.help.sectionize_requests()

        # Fire ze missiles!
        global app
        debug = config.get("developer_mode")
        app = tornado.web.Application(
            request_classes,
            debug=debug,
            template_path=os.path.join(os.path.dirname(__file__),
                                       "../templates"),
            static_path=os.path.join(os.path.dirname(__file__), "../static"),
            autoescape=None,
            autoreload=debug,
            serve_traceback=debug,
        )
        http_server = tornado.httpserver.HTTPServer(app, xheaders=True)
        http_server.listen(port_no)

        for request in request_classes:
            log.debug("start", "   Handler: %s" % str(request))
        log.info("start", "API server on port %s ready to go." % port_no)
        self.ioloop = tornado.ioloop.IOLoop.instance()

        db_keepalive = tornado.ioloop.PeriodicCallback(db.connection_keepalive,
                                                       10000)
        db_keepalive.start()

        try:
            self.ioloop.start()
        finally:
            self.ioloop.stop()
            http_server.stop()
            db.close()
            log.info("stop", "Server has been shutdown.")
            log.close()
Example #46
0
def update_memcache(sid):
    _update_schedule_memcache(sid)
    update_live_voting(sid)
    cache.prime_rating_cache_for_events(
        sid, [current[sid]] + upnext[sid] + history[sid]
    )
    cache.set_station(sid, "current_listeners", listeners.get_listeners_dict(sid), True)
    cache.set_station(sid, "album_diff", playlist.get_updated_albums_dict(sid), True)
    rainwave.playlist_objects.album.clear_updated_albums(sid)
    cache.set_station(sid, "all_albums", playlist.get_all_albums_list(sid), True)
    cache.set_station(sid, "all_artists", playlist.get_all_artists_list(sid), True)
    cache.set_station(sid, "all_groups", playlist.get_all_groups_list(sid), True)
    cache.set_station(sid, "all_groups_power", playlist.get_all_groups_for_power(sid), True)

    potential_dj_ids = []
    if getattr(current[sid], "dj_user_id", None):
        potential_dj_ids.append(current[sid].dj_user_id)
    for evt in upnext[sid]:
        if getattr(evt, "dj_user_id", None):
            potential_dj_ids.append(evt.dj_user_id)
    if (
        history[sid]
        and history[sid][-1]
        and getattr(history[sid][-1], "dj_user_id", None)
    ):
        potential_dj_ids.append(history[sid][-1].dj_user_id)
    cache.set_station(sid, "dj_user_ids", potential_dj_ids)
Example #47
0
    def _listen(self, task_id):
        import api_requests.sync
        api_requests.sync.init()

        # task_ids start at zero, so we gobble up ports starting at the base port and work up
        port_no = int(config.get("api_base_port")) + task_id

        pid = os.getpid()
        pid_file = open(
            "%s/api_%s.pid" % (config.get_directory("pid_dir"), port_no), 'w')
        pid_file.write(str(pid))
        pid_file.close()

        # Log according to configured directory and port # we're operating on
        log_file = "%s/rw_api_%s.log" % (config.get_directory("log_dir"),
                                         port_no)
        if config.test_mode and os.path.exists(log_file):
            os.remove(log_file)
        log.init(log_file, config.get("log_level"))
        log.debug("start", "Server booting, port %s." % port_no)
        db.connect()
        cache.connect()
        memory_trace.setup(port_no)

        if config.get("web_developer_mode"):
            for station_id in config.station_ids:
                playlist.prepare_cooldown_algorithm(station_id)
            # automatically loads every station ID and fills things in if there's no data
            schedule.load()
            for station_id in config.station_ids:
                schedule.update_memcache(station_id)
                rainwave.request.update_line(station_id)
                rainwave.request.update_expire_times()
                cache.set_station(station_id, "backend_ok", True)
                cache.set_station(station_id, "backend_message", "OK")
                cache.set_station(station_id, "get_next_socket_timeout", False)

        for sid in config.station_ids:
            cache.update_local_cache_for_sid(sid)
            playlist.prepare_cooldown_algorithm(sid)
            playlist.update_num_songs()

        # If we're not in developer, remove development-related URLs
        if not config.get("developer_mode"):
            i = 0
            while (i < len(request_classes)):
                if request_classes[i][0].find("/test/") != -1:
                    request_classes.pop(i)
                    i = i - 1
                i = i + 1

        # Make sure all other errors get handled in an API-friendly way
        request_classes.append((r"/api/.*", api.web.Error404Handler))
        request_classes.append((r"/api4/.*", api.web.Error404Handler))
        request_classes.append((r".*", api.web.HTMLError404Handler))

        # Initialize the help (rather than it scan all URL handlers every time someone hits it)
        api.help.sectionize_requests()

        # Fire ze missiles!
        app = tornado.web.Application(
            request_classes,
            debug=(config.test_mode or config.get("developer_mode")),
            template_path=os.path.join(os.path.dirname(__file__),
                                       "../templates"),
            static_path=os.path.join(os.path.dirname(__file__), "../static"),
            autoescape=None)
        http_server = tornado.httpserver.HTTPServer(app, xheaders=True)
        http_server.listen(port_no)

        if config.get("api_user") and config.get("api_group"):
            chuser.change_user(config.get("api_user"), config.get("api_group"))

        if task_id == 0:
            buildtools.bake_css()
            buildtools.bake_js()
            buildtools.bake_beta_js()

        for request in request_classes:
            log.debug("start", "   Handler: %s" % str(request))
        log.info("start", "API server on port %s ready to go." % port_no)
        self.ioloop = tornado.ioloop.IOLoop.instance()

        try:
            self.ioloop.start()
        finally:
            self.ioloop.stop()
            http_server.stop()
            db.close()
            log.info("stop", "Server has been shutdown.")
            log.close()
Example #48
0
def _update_memcache(sid):
	cache.set_station(sid, "sched_current", current[sid], True)
	cache.set_station(sid, "sched_next", next[sid], True)
	cache.set_station(sid, "sched_history", history[sid], True)
	cache.set_station(sid, "sched_current_dict", current[sid].to_dict(), True)
	next_dict_list = []
	for event in next[sid]:
		next_dict_list.append(event.to_dict())
	cache.set_station(sid, "sched_next_dict", next_dict_list, True)
	history_dict_list = []
	for event in history[sid]:
		history_dict_list.append(event.to_dict())
	cache.set_station(sid, "sched_history_dict", history_dict_list, True)
	cache.prime_rating_cache_for_events([ current[sid] ] + next[sid] + history[sid])
	cache.set_station(sid, "listeners_current", listeners.get_listeners_dict(sid), True)
	cache.set_station(sid, "album_diff", playlist.get_updated_albums_dict(sid), True)
	playlist.clear_updated_albums(sid)
	cache.set_station(sid, "all_albums", playlist.get_all_albums_list(sid), True)
	cache.set_station(sid, "all_artists", playlist.get_all_artists_list(sid), True)
Example #49
0
	if hasattr(os, "fork"):
		dest_port += int(args.sid)
	# Windows, no multiprocessing
	else:
		dest_port += int(list(config.station_ids)[0])
	conn = httplib.HTTPConnection(args.dest, config.get("backend_port") + int(args.sid), timeout=3)
	conn.request("GET", "/advance/%s" % args.sid)
	result = conn.getresponse()
	if result.status == 200:
		next_song_filename = result.read()
		if not next_song_filename or len(next_song_filename) == 0:
			raise Exception("Got zero-length filename from backend!")
		print next_song_filename
	else:
		raise Exception("Backend HTTP Error %s" % result.status)
	cache.set_station(args.sid, "backend_ok", True)
	cache.set_station(args.sid, "backend_message", "OK")
	cache.set_station(args.sid, "get_next_socket_timeout", False)
	conn.close()
except socket.timeout as e:
	cache.set_station(args.sid, "backend_ok", False)
	cache.set_station(args.sid, "backend_status", repr(e))
	cache.set_station(args.sid, "get_next_socket_timeout", True)
	time.sleep(2)
	raise
except Exception as e:
	cache.set_station(args.sid, "backend_ok", False)
	cache.set_station(args.sid, "backend_status", repr(e))
	if conn:
		conn.close()
	time.sleep(2)
Example #50
0
def update_line(sid):
    # Get everyone in the line
    line = db.c.fetch_all(
        "SELECT username, user_id, line_expiry_tune_in, line_expiry_election, line_wait_start FROM r4_request_line JOIN phpbb_users USING (user_id) WHERE r4_request_line.sid = %s AND radio_requests_paused = FALSE ORDER BY line_wait_start",
        (sid, ))
    new_line = []
    # user_positions has user_id as a key and position as the value, this is cached for quick lookups by API requests
    # so users know where they are in line
    user_positions = {}
    t = int(time.time())
    albums_with_requests = []
    position = 1
    # For each person
    for row in line:
        add_to_line = False
        u = User(row['user_id'])
        row['song_id'] = None
        # If their time is up, remove them and don't add them to the new line
        if row['line_expiry_tune_in'] and row['line_expiry_tune_in'] <= t:
            log.debug(
                "request_line",
                "%s: Removed user ID %s from line for tune in timeout, expiry time %s current time %s"
                % (sid, u.id, row['line_expiry_tune_in'], t))
            u.remove_from_request_line()
        else:
            tuned_in_sid = db.c.fetch_var(
                "SELECT sid FROM r4_listeners WHERE user_id = %s AND sid = %s AND listener_purge = FALSE",
                (u.id, sid))
            tuned_in = True if tuned_in_sid == sid else False
            if tuned_in:
                # Get their top song ID
                song_id = u.get_top_request_song_id(sid)
                # If they have no song and their line expiry has arrived, boot 'em
                if not song_id and row['line_expiry_election'] and (
                        row['line_expiry_election'] <= t):
                    log.debug(
                        "request_line",
                        "%s: Removed user ID %s from line for election timeout, expiry time %s current time %s"
                        % (sid, u.id, row['line_expiry_election'], t))
                    u.remove_from_request_line()
                    # Give them more chances if they still have requests
                    # They'll get added to the line of whatever station they're tuned in to (if any!)
                    if u.has_requests():
                        u.put_in_request_line(u.get_tuned_in_sid())
                # If they have no song, start the expiry countdown
                elif not song_id and not row['line_expiry_election']:
                    row['line_expiry_election'] = t + 900
                    db.c.update(
                        "UPDATE r4_request_line SET line_expiry_election = %s WHERE user_id = %s",
                        ((t + 900), row['user_id']))
                    add_to_line = True
                # Keep 'em in line
                else:
                    if song_id:
                        albums_with_requests.append(
                            db.c.fetch_var(
                                "SELECT album_id FROM r4_songs WHERE song_id = %s",
                                (song_id, )))
                    row['song_id'] = song_id
                    add_to_line = True
            elif not row['line_expiry_tune_in'] or row[
                    'line_expiry_tune_in'] == 0:
                db.c.update(
                    "UPDATE r4_request_line SET line_expiry_tune_in = %s WHERE user_id = %s",
                    ((t + 900), row['user_id']))
                add_to_line = True
            else:
                add_to_line = True
        if add_to_line:
            new_line.append(row)
            user_positions[u.id] = position
            position = position + 1

    cache.set_station(sid, "request_line", new_line, True)
    cache.set_station(sid, "request_user_positions", user_positions, True)

    db.c.update(
        "UPDATE r4_album_sid SET album_requests_pending = NULL WHERE album_requests_pending = TRUE AND sid = %s",
        (sid, ))
    for album_id in albums_with_requests:
        db.c.update(
            "UPDATE r4_album_sid SET album_requests_pending = TRUE WHERE album_id = %s AND sid = %s",
            (album_id, sid))

    return new_line
Example #51
0
	def post(self):
		cache.set_station(self.sid, "pause_title", self.get_argument("title"))
		self.append(self.return_name, { "success": True, "pause_title": self.get_argument("title") })