示例#1
0
    def do_phpbb_auth(self):
        phpbb_cookie_name = config.get("phpbb_cookie_name") + "_"
        user_id = fieldtypes.integer(
            self.get_cookie(phpbb_cookie_name + "u", ""))
        if not user_id:
            pass
        else:
            if self._verify_phpbb_session(user_id):
                # update_phpbb_session is done by verify_phpbb_session if successful
                self.user = User(user_id)
                self.user.ip_address = self.request.remote_ip
                self.user.authorize(self.sid, None, bypass=True)
                return True

            if not self.user and self.get_cookie(phpbb_cookie_name + "k"):
                can_login = db.c.fetch_var(
                    "SELECT 1 FROM phpbb_sessions_keys WHERE key_id = %s AND user_id = %s",
                    (hashlib.md5(self.get_cookie(phpbb_cookie_name +
                                                 "k")).hexdigest(), user_id))
                if can_login == 1:
                    self._update_phpbb_session(
                        self._get_phpbb_session(user_id))
                    self.user = User(user_id)
                    self.user.ip_address = self.request.remote_ip
                    self.user.authorize(self.sid, None, bypass=True)
                    return True
        return False
示例#2
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 'skip' in line[pos] and line[pos]['skip']:
			log.debug("request", "Passing on user %s since they're marked as skippable." % line[pos]['username'])
		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()
			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, timestamp() - 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)
			break

	return song
示例#3
0
    def prepare(self):
        super(MainIndex, self).prepare()

        if not cache.get_station(self.sid, "sched_current"):
            raise APIException(
                "server_just_started",
                "Rainwave is Rebooting, Please Try Again in a Few Minutes",
                http_code=500)

        # self.json_payload = {}
        self.jsfiles = None

        if not self.user:
            self.user = User(1)
        self.user.ensure_api_key()

        if self.beta or config.get("web_developer_mode") or config.get(
                "developer_mode") or config.get("test_mode"):
            buildtools.bake_beta_css()
            buildtools.bake_beta_templates()
            self.jsfiles = []
            for root, subdirs, files in os.walk(
                    os.path.join(os.path.dirname(__file__),
                                 "../static/%s" % self.js_dir)):  #pylint: disable=W0612
                for f in files:
                    if f.endswith(".js"):
                        self.jsfiles.append(
                            os.path.join(
                                root[root.find("static/%s" % self.js_dir):],
                                f))
示例#4
0
    def test_check_song_for_conflict(self):
        db.c.update("DELETE FROM r4_listeners")
        db.c.update("DELETE FROM r4_request_store")

        e = Election.create(1)
        self.assertEqual(False, e._check_song_for_conflict(self.song1))

        u = User(2)
        u.authorize(sid=1, ip_address=None, api_key=None, bypass=True)
        self.assertEqual(1, u.put_in_request_line(1))
        # TODO: Use proper request/user methods here instead of DB call
        db.c.update(
            "UPDATE r4_request_line SET line_top_song_id = %s, line_expiry_tune_in = %s WHERE user_id = %s",
            (self.song1.id, int(time.time()) + 9999, u.id))
        db.c.update(
            "INSERT INTO r4_listeners (sid, user_id, listener_icecast_id) VALUES (1, %s, 1)",
            (u.id, ))
        db.c.update(
            "INSERT INTO r4_request_store (user_id, song_id, sid) VALUES (%s, %s, 1)",
            (u.id, self.song1.id))
        request.update_cache(1)
        request.update_expire_times()
        cache.update_local_cache_for_sid(1)
        self.assertEqual(True, e._check_song_for_conflict(self.song1))
        self.assertEqual(True, e._check_song_for_conflict(self.song5))
        self.assertEqual(event.ElecSongTypes.conflict,
                         self.song5.data['entry_type'])
        self.assertEqual(event.ElecSongTypes.request,
                         self.song1.data['entry_type'])
示例#5
0
    def rainwave_auth(self):
        user_id_present = "user_id" in self.request.arguments

        if self.auth_required and not user_id_present:
            raise APIException("missing_argument",
                               argument="user_id",
                               http_code=400)
        if user_id_present and not fieldtypes.numeric(
                self.get_argument("user_id")):
            # do not spit out the user ID back at them, that would create a potential XSS hack
            raise APIException("invalid_argument",
                               argument="user_id",
                               reason="not numeric.",
                               http_code=400)
        if (self.auth_required
                or user_id_present) and not "key" in self.request.arguments:
            raise APIException("missing_argument",
                               argument="key",
                               http_code=400)

        if user_id_present:
            self.user = User(long(self.get_argument("user_id")))
            self.user.ip_address = self.request.remote_ip
            self.user.authorize(self.sid, self.get_argument("key"))
            if not self.user.authorized:
                raise APIException("auth_failed", http_code=403)
            else:
                self._update_phpbb_session(
                    self._get_phpbb_session(self.user.id))
示例#6
0
    def prepare(self):
        if self.path_kwargs.get("station"):
            self.sid = config.stream_filename_to_sid.get(
                self.path_kwargs["station"])
            if not self.sid:
                self.redirect(config.get("base_site_url"))
                return

        super(MainIndex, self).prepare()

        if self.path_kwargs.get("station") is None:
            self.redirect("{}{}/".format(
                config.get("base_site_url"),
                config.station_mount_filenames[self.sid],
            ))
            return

        if config.get("enforce_ssl") and self.request.protocol != "https":
            self.redirect("{}{}/".format(
                config.get("base_site_url"),
                config.station_mount_filenames[self.sid],
            ))
            return

        if not config.get("developer_mode"
                          ) and self.request.host != config.get("hostname"):
            self.redirect("{}{}/".format(
                config.get("base_site_url"),
                config.station_mount_filenames[self.sid],
            ))
            return

        if not cache.get_station(self.sid, "sched_current"):
            raise APIException(
                "server_just_started",
                "Rainwave is Rebooting, Please Try Again in a Few Minutes",
                http_code=500,
            )

        self.jsfiles = None

        if not self.user:
            self.user = User(1)
        self.user.ip_address = self.request.remote_ip
        self.user.ensure_api_key()

        if (self.beta or config.get("web_developer_mode")
                or config.get("developer_mode") or config.get("test_mode")):
            buildtools.bake_beta_css()
            buildtools.bake_beta_templates()
            self.jsfiles = []
            for root, _subdirs, files in os.walk(
                    os.path.join(os.path.dirname(__file__),
                                 "../static/%s" % self.js_dir)):
                for f in files:
                    if f.endswith(".js"):
                        self.jsfiles.append(
                            os.path.join(
                                root[root.find("static/%s" % self.js_dir):],
                                f))
示例#7
0
 def fill(self, target_song_length=None, skip_requests=False):
     # ONLY RUN _ADD_REQUESTS ONCE PER FILL
     if not skip_requests:
         self._add_requests()
     for i in range(len(self.songs), self._num_songs):  #pylint: disable=W0612
         try:
             if not target_song_length and len(
                     self.songs) > 0 and 'length' in self.songs[0].data:
                 target_song_length = self.songs[0].data['length']
                 log.debug(
                     "elec_fill",
                     "Second song in election, aligning to length %s" %
                     target_song_length)
             song = self._fill_get_song(target_song_length)
             song.data['entry_votes'] = 0
             song.data['entry_type'] = ElecSongTypes.normal
             song.data['elec_request_user_id'] = 0
             song.data['elec_request_username'] = None
             self._check_song_for_conflict(song)
             self.add_song(song)
         except Exception as e:
             log.exception("elec_fill",
                           "Song failed to fill in an election.", e)
     if len(self.songs) == 0:
         raise ElectionEmptyException
     for song in self.songs:
         if 'elec_request_user_id' in song.data and song.data[
                 'elec_request_user_id']:
             log.debug(
                 "elec_fill",
                 "Putting user %s back in line after request fulfillment." %
                 song.data['elec_request_username'])
             u = User(song.data['elec_request_user_id'])
             u.put_in_request_line(u.get_tuned_in_sid())
     request.update_line(self.sid)
示例#8
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
示例#9
0
	def _do_auth(self, message):
		try:
			if not "user_id" in message or not message['user_id']:
				self.write_message({ "wserror": { "tl_key": "missing_argument", "text": self.locale.translate("missing_argument", argument="user_id") } })
			if not isinstance(message['user_id'], numbers.Number):
				self.write_message({ "wserror": { "tl_key": "invalid_argument", "text": self.locale.translate("invalid_argument", argument="user_id") } })
			if not "key" in message or not message['key']:
				self.write_message({ "wserror": { "tl_key": "missing_argument", "text": self.locale.translate("missing_argument", argument="key") } })

			self.user = User(message['user_id'])
			self.user.ip_address = self.request.remote_ip
			self.user.authorize(None, message['key'])
			if not self.user.authorized:
				self.write_message({ "wserror": { "tl_key": "auth_failed", "text": self.locale.translate("auth_failed") } })
				self.close()
				return
			self.authorized = True
			self.uuid = str(uuid.uuid4())

			global sessions
			sessions[self.sid].append(self)

			self.votes_by_key = self.request.remote_ip if self.user.is_anonymous() else self.user.id

			self.refresh_user()
			# no need to send the user's data to the user as that would have come with bootstrap
			# and will come with each synchronization of the schedule anyway
			self.write_message({ "wsok": True })
			# since this will be the first action in any websocket interaction though,
			# it'd be a good time to send a station offline message.
			self._station_offline_check()
		except Exception as e:
			log.exception("websocket", "Exception during authentication.", e)
			self.close()
示例#10
0
    def prepare(self):
        super(MainIndex, self).prepare()

        self.json_payload = []
        if not self.user:
            self.user = User(1)
        self.user.ensure_api_key(self.request.remote_ip)
        self.user.data['sid'] = self.sid
示例#11
0
文件: index.py 项目: nullun/rainwave
 def prepare(self):
     super(Bootstrap, self).prepare()
     if not self.user:
         self.user = User(1)
     self.user.ensure_api_key()
     self.is_mobile = self.request.headers.get("User-Agent").lower().find(
         "mobile") != -1 or self.request.headers.get(
             "User-Agent").lower().find("android") != -1
示例#12
0
  def setup_rainwave_session_and_redirect(self, user_id, destination):
    session_id = str(uuid.uuid4())
    db.c.update(
      "INSERT INTO r4_sessions (session_id, user_id) VALUES (%s, %s)",
      (session_id, user_id,)
    )
    self.set_cookie("r4_session_id", session_id)

    if destination == "app" or destination == "rw":
      user = User(user_id)
      user.authorize(1, None, bypass=True)
      self.redirect("rw://%s:%[email protected]" % (user.id, user.ensure_api_key()),)
    elif destination == "rwpath":
      user = User(user_id)
      user.authorize(1, None, bypass=True)
      self.redirect("rwpath://rainwave.cc/%s/%s" % (user.id, user.ensure_api_key()),)
    else:
      self.redirect("/")
示例#13
0
	def prepare(self):
		if self.local_only and not self.request.remote_ip in config.get("api_trusted_ip_addresses"):
			log.info("api", "Rejected %s request from %s, untrusted address." % (self.url, self.request.remote_ip))
			raise APIException("rejected", text="You are not coming from a trusted address.")

		if self.allow_cors:
			self.set_header("Access-Control-Allow-Origin", "*")
			self.set_header("Access-Control-Max-Age", "600")
			self.set_header("Access-Control-Allow-Credentials", "false")

		if not isinstance(self.locale, locale.RainwaveLocale):
			self.locale = self.get_browser_locale()

		self.setup_output()

		if 'in_order' in self.request.arguments:
			self._output = []
			self._output_array = True
		else:
			self._output = {}

		self.sid = fieldtypes.integer(self.get_cookie("r4_sid", None))
		hostname = self.request.headers.get('Host', None)
		if hostname:
			hostname = unicode(hostname).split(":")[0]
			if hostname in config.station_hostnames:
				self.sid = config.station_hostnames[hostname]
		sid_arg = fieldtypes.integer(self.get_argument("sid", None))
		if sid_arg is not None:
			self.sid = sid_arg
		if self.sid is None and self.sid_required:
			raise APIException("missing_station_id", http_code=400)

		self.arg_parse()

		self.sid_check()

		if self.sid:
			self.set_cookie("r4_sid", str(self.sid), expires_days=365, domain=config.get("cookie_domain"))

		if self.phpbb_auth:
			self.do_phpbb_auth()
		else:
			self.rainwave_auth()

		if not self.user and self.auth_required:
			raise APIException("auth_required", http_code=403)
		elif not self.user and not self.auth_required:
			self.user = User(1)
			self.user.ip_address = self.request.remote_ip

		self.user.refresh(self.sid)

		if self.user and config.get("store_prefs"):
			self.user.save_preferences(self.request.remote_ip, self.get_cookie("r4_prefs", None))

		self.permission_checks()
示例#14
0
 def do_rw_session_auth(self):
     rw_session_id = self.get_cookie("r4_session_id")
     if rw_session_id:
         user_id = db.c.fetch_var("SELECT user_id FROM r4_sessions WHERE session_id = %s", (rw_session_id,))
         if user_id:
             self.user = User(user_id)
             self.user.ip_address = self.request.remote_ip
             self.user.authorize(self.sid, None, bypass=True)
             return True
     return False
示例#15
0
文件: request.py 项目: Reani/rainwave
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)
示例#16
0
def get_next(sid):
    entry, line = get_next_entry(sid)
    if not entry:
        return None

    user = User(entry["user_id"])
    user.data["name"] = entry["username"]
    song = playlist.Song.load_from_id(entry["song_id"], sid)
    mark_request_filled(sid, user, song, entry, line)

    return song
示例#17
0
	def do_phpbb_auth(self):
		phpbb_cookie_name = config.get("phpbb_cookie_name")
		self.user = None
		if not fieldtypes.integer(self.get_cookie(phpbb_cookie_name + "u", "")):
			self.user = User(1)
		else:
			user_id = int(self.get_cookie(phpbb_cookie_name + "u"))
			if self._verify_phpbb_session(user_id):
				# update_phpbb_session is done by verify_phpbb_session if successful
				self.user = User(user_id)
				self.user.authorize(self.sid, None, None, True)
				return True

			if not self.user and self.get_cookie(phpbb_cookie_name + "k"):
				can_login = db.c_old.fetch_var("SELECT 1 FROM phpbb_sessions_keys WHERE key_id = %s AND user_id = %s", (hashlib.md5(self.get_cookie(phpbb_cookie_name + "k")).hexdigest(), user_id))
				if can_login == 1:
					self._update_phpbb_session(self._get_phpbb_session(user_id))
					self.user = User(user_id)
					self.user.authorize(self.sid, None, None, True)
					return True
		return False
示例#18
0
	def test_get_request(self):
		db.c.update("DELETE FROM r4_listeners")
		db.c.update("DELETE FROM r4_request_store")
		u = User(2)
		u.authorize(1, None, None, True)
		u.put_in_request_line(1)
		# TODO: Use proper request class here instead of DB call
		db.c.update("INSERT INTO r4_listeners (sid, user_id, listener_icecast_id) VALUES (1, %s, 1)", (u.id,))
		db.c.update("INSERT INTO r4_request_store (user_id, song_id, sid) VALUES (%s, %s, 1)", (u.id, self.song1.id,))
		
		e = Election.create(1)
		req = e.get_request()
		self.assertNotEqual(None, req)
		self.assertEqual(self.song1.id, req.id)
示例#19
0
def get_next_ignoring_cooldowns(sid):
    line = db.c.fetch_all(LINE_SQL, (sid, ))

    if not line or len(line) == 0:
        return None

    entry = line[0]
    user = User(entry["user_id"])
    user.data["name"] = entry["username"]
    song = playlist.Song.load_from_id(user.get_top_request_song_id_any(sid),
                                      sid)
    mark_request_filled(sid, user, song, entry, line)

    return song
示例#20
0
文件: index.py 项目: Dinir/rainwave
    def prepare(self):
        super(MainIndex, self).prepare()
        self.json_payload = {}
        self.jsfiles = None

        if not self.user:
            self.user = User(1)
        self.user.ensure_api_key()

        if self.beta or config.get("web_developer_mode") or config.get(
                "developer_mode") or config.get("test_mode"):
            buildtools.bake_beta_css()
            self.jsfiles = []
            for root, subdirs, files in os.walk(
                    os.path.join(os.path.dirname(__file__), "../static/js4")):
                for f in files:
                    self.jsfiles.append(
                        os.path.join(root[root.find("static/js4"):], f))
示例#21
0
文件: request.py 项目: Reani/rainwave
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
示例#22
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
示例#23
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
示例#24
0
 def prepare(self):
     super(Bootstrap, self).prepare()
     if not self.user:
         self.user = User(1)
     self.user.ensure_api_key()
示例#25
0
文件: web.py 项目: Dinir/rainwave
    def prepare(self):
        if self.local_only and not self.request.remote_ip in config.get(
                "api_trusted_ip_addresses"):
            log.info(
                "api", "Rejected %s request from %s, untrusted address." %
                (self.url, self.request.remote_ip))
            raise APIException(
                "rejected", text="You are not coming from a trusted address.")

        if not isinstance(self.locale, locale.RainwaveLocale):
            self.locale = self.get_browser_locale()

        if not self.return_name:
            self.return_name = self.url[self.url.rfind("/") + 1:] + "_result"
        else:
            self.return_name = self.return_name

        if self.admin_required or self.dj_required:
            self.login_required = True

        if 'in_order' in self.request.arguments:
            self._output = []
            self._output_array = True
        else:
            self._output = {}

        self.sid = fieldtypes.integer(self.get_cookie("r4_sid", None))
        hostname = self.request.headers.get('Host', None)
        if hostname:
            hostname = unicode(hostname).split(":")[0]
            if hostname in config.station_hostnames:
                self.sid = config.station_hostnames[hostname]
        self.sid = fieldtypes.integer(self.get_argument("sid",
                                                        None)) or self.sid
        if self.sid and not self.sid in config.station_ids:
            self.sid = None
        if not self.sid and self.sid_required:
            raise APIException("missing_station_id", http_code=400)

        for field, field_attribs in self.__class__.fields.iteritems():
            type_cast, required = field_attribs
            if required and field not in self.request.arguments:
                raise APIException("missing_argument",
                                   argument=field,
                                   http_code=400)
            elif not required and field not in self.request.arguments:
                self.cleaned_args[field] = None
            else:
                parsed = type_cast(self.get_argument(field), self)
                if parsed == None and required != None:
                    raise APIException(
                        "invalid_argument",
                        argument=field,
                        reason="%s %s" %
                        (field,
                         getattr(fieldtypes, "%s_error" % type_cast.__name__)),
                        http_code=400)
                else:
                    self.cleaned_args[field] = parsed

        if not self.sid and not self.sid_required:
            self.sid = 5
        if not self.sid in config.station_ids:
            raise APIException("invalid_station_id", http_code=400)
        self.set_cookie("r4_sid",
                        str(self.sid),
                        expires_days=365,
                        domain=config.get("cookie_domain"))

        if self.phpbb_auth:
            self.do_phpbb_auth()
        else:
            self.rainwave_auth()

        if not self.user and self.auth_required:
            raise APIException("auth_required", http_code=403)
        elif not self.user and not self.auth_required:
            self.user = User(1)
            self.user.ip_address = self.request.remote_ip

        self.user.refresh(self.sid)

        if self.login_required and (not self.user or self.user.is_anonymous()):
            raise APIException("login_required", http_code=403)
        if self.tunein_required and (not self.user
                                     or not self.user.is_tunedin()):
            raise APIException("tunein_required", http_code=403)
        if self.admin_required and (not self.user or not self.user.is_admin()):
            raise APIException("admin_required", http_code=403)
        if self.dj_required and (not self.user or not self.user.is_dj()):
            raise APIException("dj_required", http_code=403)
        if self.perks_required and (not self.user
                                    or not self.user.has_perks()):
            raise APIException("perks_required", http_code=403)

        if self.unlocked_listener_only and not self.user:
            raise APIException("auth_required", http_code=403)
        elif self.unlocked_listener_only and self.user.data[
                'lock'] and self.user.data['lock_sid'] != self.sid:
            raise APIException(
                "unlocked_only",
                station=config.station_id_friendly[self.user.data['lock_sid']],
                lock_counter=self.user.data['lock_counter'],
                http_code=403)