Exemplo n.º 1
0
	def load_from_id(klass, song_id, sid = None, all_categories = False):
		if sid is not None:
			d = db.c.fetch_row("SELECT * FROM r4_songs JOIN r4_song_sid USING (song_id) WHERE r4_songs.song_id = %s AND r4_song_sid.sid = %s", (song_id, sid))
		else:
			d = db.c.fetch_row("SELECT * FROM r4_songs WHERE song_id = %s", (song_id,))
			sid = d['song_origin_sid']
		if not d:
			raise SongNonExistent

		try:
			s = klass()
			s.id = song_id
			s.sid = sid
			s.filename = d['song_filename']
			s.verified = d['song_verified']
			s.replay_gain = d['song_replay_gain']
			s.data['sids'] = db.c.fetch_list("SELECT sid FROM r4_song_sid WHERE song_id = %s", (song_id,))
			s.data['sid'] = sid
			s.data['rank'] = None
			s._assign_from_dict(d)

			if 'album_id' in d and d['album_id']:
				s.albums = [ Album.load_from_id_sid(d['album_id'], sid) ]
			s.artists = Artist.load_list_from_song_id(song_id)
			s.groups = SongGroup.load_list_from_song_id(song_id, sid, all_categories = all_categories)
		except Exception as e:
			log.exception("song", "Song ID %s failed to load, sid %s." % (song_id, sid), e)
			s.disable()
			raise

		return s
Exemplo n.º 2
0
	def load_from_id(klass, song_id, sid = None):
		if sid is not None:
			d = db.c.fetch_row("SELECT * FROM r4_songs JOIN r4_song_sid USING (song_id) WHERE r4_songs.song_id = %s AND r4_song_sid.sid = %s", (song_id, sid))
		else:
			d = db.c.fetch_row("SELECT * FROM r4_songs WHERE song_id = %s", (song_id,))
		if not d:
			raise SongNonExistent

		try:
			s = klass()
			s.id = song_id
			s.sid = sid
			s.filename = d['song_filename']
			s.verified = d['song_verified']
			s.replay_gain = d['song_replay_gain']
			s.data['sids'] = db.c.fetch_list("SELECT sid FROM r4_song_sid WHERE song_id = %s", (song_id,))
			s.data['sid'] = sid
			s.data['rank'] = None
			s._assign_from_dict(d)

			if 'album_id' in d and d['album_id']:
				if sid is not None:
					s.albums = [ Album.load_from_id_sid(d['album_id'], s.sid) ]
				else:
					s.albums = [ Album.load_from_id(d['album_id']) ]
			s.artists = Artist.load_list_from_song_id(song_id)
			s.groups = SongGroup.load_list_from_song_id(song_id)
		except Exception as e:
			log.exception("song", "Song ID %s failed to load, sid %s." % (song_id, sid), e)
			s.disable()
			raise

		return s
Exemplo n.º 3
0
def _add_scan_error(filename, xception):
	global _scan_errors
	
	_scan_errors.insert(0, { "time": time.time(), "file": filename, "type": xception.__class__.__name__, "error": str(xception) })
	log.exception("scan", "Error scanning %s" % filename, xception)
	if config.test_mode:
		raise Exception(_scan_errors[0])
Exemplo n.º 4
0
    async def post(self):
        if not config.has("sentry_dsn"):
            return

        try:
            sentry_host = config.get("sentry_host")
            envelope = self.request.body.decode("utf-8")
            piece = envelope.split("\n")[0]
            header = json.loads(piece)
            dsn = urllib.parse.urlparse(header.get("dsn"))

            if dsn.hostname != sentry_host:
                raise Exception(f"Invalid Sentry host: {dsn.hostname}")

            project_id = dsn.path.strip("/")
            if project_id != config.get("sentry_frontend_project_id"):
                raise Exception(f"Invalid Project ID: {project_id}")

            tunneled = HTTPRequest(
                url=f"https://{sentry_host}/api/{project_id}/envelope/",
                method="POST",
                body=envelope,
            )
            http_client = AsyncHTTPClient()
            await http_client.fetch(tunneled)
        except Exception as e:
            log.exception("sentry", "Error tunneling Sentry", e)

        return {}
Exemplo n.º 5
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()
Exemplo n.º 6
0
def _count():
	global in_process

	log.debug("icecast_sync", "All responses came back for counting.")

	try:
		stations = {}
		for sid in config.station_ids:
			stations[sid] = 0

		for handler, data in in_process.iteritems():
			if isinstance(data, list):
				stations[handler.sid] += len(data)

		for sid, listener_count in stations.iteritems():
			log.debug("icecast_sync", "%s has %s listeners." % (config.station_id_friendly[sid], listener_count))
			db.c.update("INSERT INTO r4_listener_counts (sid, lc_guests) VALUES (%s, %s)", (sid, listener_count))

		_cache_relay_status()

		# db.c.update("DELETE FROM r4_listener_counts WHERE lc_time <= %s", (current_time - config.get("trim_history_length"),))

		in_process = {}
	except Exception as e:
		log.exception("icecast_sync", "Could not finish counting listeners.", e)
Exemplo n.º 7
0
def _count():
    global in_process

    log.debug("icecast_sync", "All responses came back for counting.")

    try:
        stations = {}
        for sid in config.station_ids:
            stations[sid] = 0

        for handler, data in in_process.iteritems():
            if isinstance(data, list):
                stations[handler.sid] += len(data)

        for sid, listener_count in stations.iteritems():
            log.debug(
                "icecast_sync", "%s has %s listeners." %
                (config.station_id_friendly[sid], listener_count))
            db.c.update(
                "INSERT INTO r4_listener_counts (sid, lc_guests) VALUES (%s, %s)",
                (sid, listener_count))

        _cache_relay_status()

        # db.c.update("DELETE FROM r4_listener_counts WHERE lc_time <= %s", (current_time - config.get("trim_history_length"),))

        in_process = {}
    except Exception as e:
        log.exception("icecast_sync", "Could not finish counting listeners.",
                      e)
Exemplo n.º 8
0
def _start(callback):
	global in_process
	if in_process:
		log.warn("icecast_sync", "Previous operation did not finish!")

	stream_names = {}
	for sid in config.station_ids:
		stream_names[sid] = config.get_station(sid, 'stream_filename')

	for relay, relay_info in config.get("relays").iteritems():
		relay_base_url = "%s%s:%s/admin/listclients?mount=/" % (relay_info['protocol'], relay_info['ip_address'], relay_info['port'])
		for sid in relay_info['sids']:
			for ftype in ('.mp3', '.ogg'):
				try:
					handler = IcecastSyncCallback(relay, relay_info, ftype, sid, callback)
					in_process[handler] = False
					http_client = tornado.httpclient.HTTPClient()
					http_client.fetch(relay_base_url + stream_names[sid] + ftype,
										auth_username=relay_info['admin_username'],
										auth_password=relay_info['admin_password'],
										callback=handler.process)
				except Exception as e:
					log.exception("icecast_sync", "Could not sync %s %s.%s" % (relay, stream_names[sid], ftype), e)

	callback()
Exemplo n.º 9
0
def _start(callback):
    global in_process
    if in_process:
        log.warn("icecast_sync", "Previous operation did not finish!")

    stream_names = {}
    for sid in config.station_ids:
        stream_names[sid] = config.get_station(sid, 'stream_filename')

    for relay, relay_info in config.get("relays").iteritems():
        relay_base_url = "%s%s:%s/admin/listclients?mount=/" % (
            relay_info['protocol'], relay_info['ip_address'],
            relay_info['port'])
        for sid in relay_info['sids']:
            for ftype in ('.mp3', '.ogg'):
                try:
                    handler = IcecastSyncCallback(relay, relay_info, ftype,
                                                  sid, callback)
                    in_process[handler] = False
                    http_client = tornado.httpclient.HTTPClient()
                    http_client.fetch(
                        relay_base_url + stream_names[sid] + ftype,
                        auth_username=relay_info['admin_username'],
                        auth_password=relay_info['admin_password'],
                        callback=handler.process)
                except Exception as e:
                    log.exception(
                        "icecast_sync", "Could not sync %s %s.%s" %
                        (relay, stream_names[sid], ftype), e)

    callback()
Exemplo n.º 10
0
	def keep_alive(self):
		for session in self.sessions + self.websockets:
			try:
				session.keep_alive()
			except Exception as e:
				session.rw_finish()
				log.exception("sync", "Session failed keepalive.", e)
Exemplo n.º 11
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):
         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)
             pass
     if len(self.songs) == 0:
         raise ElectionEmptyException
Exemplo n.º 12
0
def get_producer_at_time(sid, at_time):
    to_ret = None
    local_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(at_time))
    time_ahead = int((at_time - timestamp()) / 60)
    sched_id = db.c.fetch_var(
        "SELECT sched_id "
        "FROM r4_schedule "
        "WHERE sid = %s AND sched_start <= %s AND sched_end > %s "
        "ORDER BY sched_id DESC "
        "LIMIT 1",
        (sid, at_time + 20, at_time),
    )
    try:
        to_ret = events.event.BaseProducer.load_producer_by_id(sched_id)
        if to_ret:
            to_ret.start_producer()
    except Exception as e:
        log.warn("get_producer", "Failed to obtain producer at time %s (%sm ahead)." % (local_time, time_ahead))
        log.exception(
            "get_producer",
            "Failed to get an appropriate producer at time %s  (%sm ahead)." % (local_time, time_ahead),
            e,
        )
    if not to_ret:
        log.debug(
            "get_producer", "No producer at time %s  (%sm ahead), defaulting to election." % (local_time, time_ahead)
        )
        return election.ElectionProducer(sid)
    if not to_ret.has_next_event():
        log.warn("get_producer", "Producer ID %s (type %s, %s) has no events." % (to_ret.id, to_ret.type, to_ret.name))
        return election.ElectionProducer(sid)
    return to_ret
Exemplo n.º 13
0
def get_producer_at_time(sid, at_time):
    to_ret = None
    local_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(at_time))
    time_ahead = int((at_time - timestamp()) / 60)
    sched_id = db.c.fetch_var(
        "SELECT sched_id "
        "FROM r4_schedule "
        "WHERE sid = %s AND sched_start <= %s AND sched_end > %s "
        "ORDER BY sched_id DESC "
        "LIMIT 1", (sid, at_time + 20, at_time))
    try:
        to_ret = events.event.BaseProducer.load_producer_by_id(sched_id)
        if to_ret:
            to_ret.start_producer()
    except Exception as e:
        log.warn(
            "get_producer",
            "Failed to obtain producer at time %s (%sm ahead)." %
            (local_time, time_ahead))
        log.exception(
            "get_producer",
            "Failed to get an appropriate producer at time %s  (%sm ahead)." %
            (local_time, time_ahead), e)
    if not to_ret:
        log.debug(
            "get_producer",
            "No producer at time %s  (%sm ahead), defaulting to election." %
            (local_time, time_ahead))
        return election.ElectionProducer(sid)
    if not to_ret.has_next_event():
        log.warn(
            "get_producer", "Producer ID %s (type %s, %s) has no events." %
            (to_ret.id, to_ret.type, to_ret.name))
        return election.ElectionProducer(sid)
    return to_ret
Exemplo n.º 14
0
	def update(self):
		handler = APIHandler(websocket=True)
		handler.locale = self.locale
		handler.request = FakeRequestObject({}, self.request.cookies)
		handler.sid = self.sid
		handler.user = self.user
		handler.return_name = "sync_result"
		try:
			startclock = timestamp()
			handler.prepare_standalone()

			if not cache.get_station(self.sid, "backend_ok"):
				raise APIException("station_offline")

			self.refresh_user()
			api_requests.info.attach_info_to_request(handler, live_voting=True)
			if self.user.is_dj():
				api_requests.info.attach_dj_info_to_request(handler)
			handler.append("user", self.user.to_private_dict())
			handler.append("api_info", { "exectime": timestamp() - startclock, "time": round(timestamp()) })
		except Exception as e:
			if handler:
				handler.write_error(500, exc_info=sys.exc_info(), no_finish=True)
			log.exception("websocket", "Exception during update.", e)
		finally:
			if handler:
				self.write_message(handler._output) 	#pylint: disable=W0212
Exemplo n.º 15
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)
Exemplo n.º 16
0
def load_translations():
	global master
	global translations
	global locale_names_json

	master_file = open(os.path.join(os.path.dirname(__file__), "../lang/en_MASTER.json"))
	master = json.load(master_file)
	master_file.close()

	locale_names = {}
	for root, subdir, files in os.walk(os.path.join(os.path.dirname(__file__), "../lang")):		#pylint: disable=W0612
		for filename in files:
			if filename == "en_MASTER.json":
				continue
			if not filename.endswith(".json"):
				continue
			try:
				f = codecs.open(os.path.join(os.path.dirname(__file__), "../lang/", filename), "r", encoding="utf-8")
				translations[filename[:-5]] = RainwaveLocale(filename[:-5], master, json.load(f))
				f.close()
				locale_names[filename[:-5]] = translations[filename[:-5]].dict['language_name']
			except Exception as e:
				log.exception("locale", "%s translation did not load." % filename[:-5], e)

	locale_names_json = tornado.escape.json_encode(locale_names)
Exemplo n.º 17
0
def _add_scan_error(filename, xception, full_exc=None):
    scan_errors = []
    try:
        scan_errors = cache.get("backend_scan_errors")
    except:
        pass
    if not scan_errors:
        scan_errors = []

    eo = {
        "time": int(timestamp()),
        "file": filename,
        "type": xception.__class__.__name__,
        "error": str(xception),
        "traceback": ""
    }
    if not isinstance(xception, PassableScanError) and not isinstance(
            xception, IOError) and not isinstance(xception, OSError):
        if full_exc:
            eo['traceback'] = traceback.format_exception(*full_exc)  #pylint: disable=W0142
            log.exception("scan", "Error scanning %s" % filename, full_exc)
        else:
            eo['traceback'] = traceback.format_exception(*sys.exc_info())
            log.exception("scan", "Error scanning %s" % filename,
                          sys.exc_info())
    else:
        log.warn("scan",
                 "Warning scanning %s: %s" % (filename, xception.message))
    scan_errors.insert(0, eo)
    if len(scan_errors) > 100:
        scan_errors = scan_errors[0:100]
    cache.set("backend_scan_errors", scan_errors)
Exemplo n.º 18
0
Arquivo: db.py Projeto: nv043/rainwave
 def execute(self, query, params=None):
     if self.print_next:
         self.print_next = False
         if params:
             print self._convert_pg_query(query, True) % params
         else:
             print self._convert_pg_query(query, True)
     query = self._convert_pg_query(query)
     # If the query can't be done or properly to SQLite,
     # silently drop it.  This is mostly for table creation, things like foreign keys.
     if not query:
         log.critical("sqlite",
                      "Query has not been made SQLite friendly: %s" % query)
         raise Exception("Query has not been made SQLite friendly: %s" %
                         query)
     try:
         if params:
             self.cur.execute(query, params)
         else:
             self.cur.execute(query)
     except Exception as e:
         log.critical("sqlite", query)
         log.critical("sqlite", repr(params))
         log.exception("sqlite", "Failed query.", e)
         raise
     self.rowcount = self.cur.rowcount
     self.con.commit()
Exemplo n.º 19
0
    def _do_user_update(self, session, updated_by_ip):
        # clear() might wipe out the timeouts for a bigger update (that includes user update anyway!)
        # don't bother updating again if that's already happened
        if not session in self.throttled:
            return
        del (self.throttled[session])

        try:
            potential_mixup_warn = updated_by_ip and not session.user.is_anonymous(
            ) and not session.user.is_tunedin()
            session.refresh_user()
            if potential_mixup_warn and not session.user.is_tunedin():
                log.debug(
                    "sync_update_ip",
                    "Warning logged in user of potential M3U mixup at IP %s" %
                    session.request.remote_ip)
                session.login_mixup_warn()
            else:
                session.update_user()
        except Exception as e:
            log.exception("sync",
                          "Session failed to be updated during update_user.",
                          e)
            try:
                session.rw_finish()
            except Exception:
                log.exception("sync",
                              "Session failed finish() during update_user.", e)
Exemplo n.º 20
0
def monitor():
    _common_init()

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

    observers = []
    for directory, sids in config.get("song_dirs").iteritems():
        observer = watchdog.observers.Observer()
        observer.schedule(FileEventHandler(directory, sids),
                          directory,
                          recursive=True)
        observer.start()
        log.info("scan", "Observing %s with sids %s" % (directory, repr(sids)))
        observers.append(observer)

    try:
        while True:
            time.sleep(60)
            _process_album_art_queue()
    except Exception as e:
        log.exception("scan", "Exception leaked to top monitoring function.",
                      e)
        for observer in observers:
            observer.stop()
    for observer in observers:
        observer.join()
Exemplo n.º 21
0
 def keep_alive(self):
     for session in self.sessions:
         try:
             session.keep_alive()
         except Exception as e:
             self.remove(session)
             log.exception("sync", "Session failed keepalive.", e)
Exemplo n.º 22
0
    def _do_ip_update(self, ip_address):
        if not ip_address in self.ip_update_timers or not self.ip_update_timers[
                ip_address]:
            return

        del self.ip_update_timers[ip_address]
        for session in self.find_ip(ip_address):
            try:
                if session.user.is_anonymous():
                    session.update_user()
                    log.debug("sync_update_ip",
                              "Updated IP %s" % session.request.remote_ip)
                else:
                    log.debug(
                        "sync_update_ip",
                        "Warning logged in user of potential mixup at IP %s" %
                        session.request.remote_ip)
                    session.anon_registered_mixup_warn()
            except Exception as e:
                try:
                    session.finish()
                except:
                    pass
                self.remove(session)
                log.exception(
                    "sync", "Session failed to be updated during update_user.",
                    e)
        self.clean()
Exemplo n.º 23
0
def load_translations():
	global master
	global translations
	global locale_names
	global locale_names_json

	master_file = open(os.path.join(os.path.dirname(__file__), "../lang/en_MASTER.json"))
	master = json.load(master_file)
	master_file.close()

	locale_names = {}
	for root, subdir, files in os.walk(os.path.join(os.path.dirname(__file__), "../lang")):		#pylint: disable=W0612
		for filename in files:
			if filename == "en_MASTER.json":
				continue
			if not filename.endswith(".json"):
				continue
			try:
				f = codecs.open(os.path.join(os.path.dirname(__file__), "../lang/", filename), "r", encoding="utf-8")
				translations[filename[:-5]] = RainwaveLocale(filename[:-5], master, json.load(f))
				f.close()
				locale_names[filename[:-5]] = translations[filename[:-5]].dict['language_name_short']
			except Exception as e:
				log.exception("locale", "%s translation did not load." % filename[:-5], e)

	locale_names_json = tornado.escape.json_encode(locale_names)
Exemplo n.º 24
0
def monitor():
	_common_init()

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

	observers = []
	for directory, sids in config.get("song_dirs").iteritems():
		observer = watchdog.observers.Observer()
		observer.schedule(FileEventHandler(directory, sids), directory, recursive=True)
		observer.start()
		log.info("scan", "Observing %s with sids %s" % (directory, repr(sids)))
		observers.append(observer)

	try:
		while True:
			time.sleep(60)
			_process_album_art_queue()
	except Exception as e:
		log.exception("scan", "Exception leaked to top monitoring function.", e)
		for observer in observers:
			observer.stop()
	for observer in observers:
		observer.join()
Exemplo n.º 25
0
	def load_from_id(klass, song_id, sid = None):
		if sid:
			d = db.c.fetch_row("SELECT * FROM r4_songs JOIN r4_song_sid USING (song_id) WHERE r4_songs.song_id = %s AND r4_song_sid.sid = %s", (song_id, sid))
		else:
			d = db.c.fetch_row("SELECT * FROM r4_songs WHERE song_id = %s", (song_id,))
		if not d:
			raise SongNonExistent

		try:
			s = klass()
			s.id = song_id
			s.sid = sid
			s.filename = d['song_filename']
			s.verified = d['song_verified']
			s.replay_gain = d['song_replay_gain']
			s.data['sids'] = db.c.fetch_list("SELECT sid FROM r4_song_sid WHERE song_id = %s", (song_id,))
			s.data['sid'] = sid
			s.data['rank'] = None
			s._assign_from_dict(d)

			if 'album_id' in d and d['album_id']:
				if sid:
					s.albums = [ Album.load_from_id_sid(d['album_id'], s.sid) ]
				else:
					s.albums = [ Album.load_from_id(d['album_id']) ]
			s.artists = Artist.load_list_from_song_id(song_id)
			s.groups = SongGroup.load_list_from_song_id(song_id)
		except Exception as e:
			log.exception("song", "Song failed to load.", e)
			db.c.update("UPDATE r4_songs SET song_verified = FALSE WHERE song_id = song_id")
			raise

		return s
Exemplo n.º 26
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()
Exemplo n.º 27
0
	def keep_alive(self):
		for session in self.sessions:
			try:
				session.keep_alive()
			except Exception as e:
				self.remove(session)
				log.exception("sync", "Session failed keepalive.", e)
Exemplo n.º 28
0
	def keep_alive(self):
		for session in self.sessions + self.websockets:
			try:
				session.keep_alive()
			except Exception as e:
				session.rw_finish()
				log.exception("sync", "Session failed keepalive.", e)
Exemplo n.º 29
0
	def execute(self, query, params = None):
		if self.print_next:
			self.print_next = False
			if params:
				print self._convert_pg_query(query, True) % params
			else:
				print self._convert_pg_query(query, True)
		query = self._convert_pg_query(query)
		# If the query can't be done or properly to SQLite,
		# silently drop it.  This is mostly for table creation, things like foreign keys.
		if not query:
			log.critical("sqlite", "Query has not been made SQLite friendly: %s" % query)
			raise Exception("Query has not been made SQLite friendly: %s" % query)
		try:
			if params:
				self.cur.execute(query, params)
			else:
				self.cur.execute(query)
		except Exception as e:
			log.critical("sqlite", query)
			log.critical("sqlite", repr(params))
			log.exception("sqlite", "Failed query.", e)
			raise
		self.rowcount = self.cur.rowcount
		self.con.commit()
Exemplo n.º 30
0
	def update(self):
		handler = APIHandler(websocket=True)
		handler.locale = self.locale
		handler.request = FakeRequestObject({}, self.request.cookies)
		handler.sid = self.sid
		handler.user = self.user
		handler.return_name = "sync_result"
		try:
			startclock = timestamp()
			handler.prepare_standalone()

			if not cache.get_station(self.sid, "backend_ok"):
				raise APIException("station_offline")

			self.refresh_user()
			api_requests.info.attach_info_to_request(handler, live_voting=True)
			if self.user.is_dj():
				api_requests.info.attach_dj_info_to_request(handler)
			handler.append("user", self.user.to_private_dict())
			handler.append("api_info", { "exectime": timestamp() - startclock, "time": round(timestamp()) })
		except Exception as e:
			if handler:
				handler.write_error(500, exc_info=sys.exc_info(), no_finish=True)
			log.exception("websocket", "Exception during update.", e)
		finally:
			if handler:
				self.write_message(handler._output) 	#pylint: disable=W0212
Exemplo n.º 31
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)
Exemplo n.º 32
0
def _on_zmq(messages):
    global votes_by
    global last_vote_by

    for message in messages:
        try:
            message = json.loads(message)
        except Exception as e:
            log.exception("zeromq", "Error decoding ZeroMQ message.", e)
            return

        if not "action" in message or not message["action"]:
            log.critical("zeromq", "No action received from ZeroMQ.")

        try:
            if message["action"] == "result_sync":
                sessions[message["sid"]].send_to_user(
                    message["user_id"], message["uuid_exclusion"], message["data"]
                )
            elif message["action"] == "live_voting":
                sessions[message["sid"]].send_to_all(
                    message["uuid_exclusion"], message["data"]
                )
                delay_live_vote_removal(message["sid"])
            elif message["action"] == "delayed_live_voting":
                if not delayed_live_vote_timers[message["sid"]]:
                    delay_live_vote(message)
                delayed_live_vote[message["sid"]] = message
            elif message["action"] == "update_all":
                delay_live_vote_removal(message["sid"])
                rainwave.playlist.update_num_songs()
                rainwave.playlist.prepare_cooldown_algorithm(message["sid"])
                cache.update_local_cache_for_sid(message["sid"])
                sessions[message["sid"]].update_all(message["sid"])
                votes_by = {}
                last_vote_by = {}
            elif message["action"] == "update_ip":
                for sid in sessions:
                    sessions[sid].update_ip_address(message["ip"])
            elif message["action"] == "update_listen_key":
                for sid in sessions:
                    sessions[sid].update_listen_key(message["listen_key"])
            elif message["action"] == "update_user":
                for sid in sessions:
                    sessions[sid].update_user(message["user_id"])
            elif message["action"] == "update_dj":
                sessions[message["sid"]].update_dj()
            elif message["action"] == "ping":
                log.debug("zeromq", "Pong")
            elif message["action"] == "vote_by":
                votes_by[message["by"]] = (
                    votes_by[message["by"]] + 1 if message["by"] in votes_by else 1
                )
                last_vote_by[message["by"]] = timestamp()
        except Exception as e:
            log.exception(
                "zeromq", "Error handling Zero MQ action '%s'" % message["action"], e
            )
            return
Exemplo n.º 33
0
def _add_scan_error(filename, xception):
	global _scan_errors, _raise_scan_errors

	_scan_errors.insert(0, { "time": int(time.time()), "file": filename, "type": xception.__class__.__name__, "error": str(xception) })
	_save_scan_errors()
	log.exception("scan", "Error scanning %s" % filename, xception)

	if config.test_mode or _raise_scan_errors:
		raise
Exemplo n.º 34
0
	def write_error(self, status_code, **kwargs):
		self.failed = True
		if kwargs.has_key("exc_info"):
			exc = kwargs['exc_info'][1]
			if isinstance(exc, APIException):
				exc.localize(self.locale)
				self.set_header("icecast-auth-message", exc.reason)
			log.debug("ldetect", "Relay command failed: %s" % exc.reason)
			log.exception("ldetect", "Exception encountered handling relay command.", exc)
		super(IcecastHandler, self).finish()
Exemplo n.º 35
0
	def write_error(self, status_code, **kwargs):
		self.failed = True
		if kwargs.has_key("exc_info"):
			exc = kwargs['exc_info'][1]
			if isinstance(exc, APIException):
				exc.localize(self.locale)
				self.set_header("icecast-auth-message", exc.reason)
			log.debug("ldetect", "Relay command failed: %s" % exc.reason)
			log.exception("ldetect", "Exception encountered handling relay command.", exc)
		super(IcecastHandler, self).finish()
Exemplo n.º 36
0
def _add_scan_error(filename, xception):
	scan_errors = cache.get("backend_scan_errors")
	if not scan_errors:
		scan_errors = []

	scan_errors.insert(0, { "time": int(timestamp()), "file": filename, "type": xception.__class__.__name__, "error": str(xception) })
	if len(scan_errors) > 100:
		scan_errors = scan_errors[0:100]
	cache.set("backend_scan_errors", scan_errors)
	log.exception("scan", "Error scanning %s" % filename, xception)
Exemplo n.º 37
0
	def update_dj(self):
		for session in self.websockets:
			if session.user.is_dj():
				try:
					session.update_dj_only()
					log.debug("sync_update_dj", "Updated user %s session." % session.user.id)
				except Exception as e:
					try:
						session.rw_finish()
					except:
						pass
					log.exception("sync_update_dj", "Session failed to be updated during update_dj.", e)
Exemplo n.º 38
0
	def write_message(self, obj, *args, **kwargs):
		message = json.dumps(obj)
		try:
			super(WSHandler, self).write_message(message, *args, **kwargs)
		except tornado.websocket.WebSocketClosedError:
			self.on_close()
		except tornado.websocket.WebSocketError as e:
			log.exception("websocket", "WebSocket Error", e)
			try:
				self.close()
			except Exception:
				self.on_close()
Exemplo n.º 39
0
def _add_scan_error(filename, xception):
    global _scan_errors

    _scan_errors.insert(
        0, {
            "time": int(time.time()),
            "file": filename,
            "type": xception.__class__.__name__,
            "error": str(xception)
        })
    _save_scan_errors()
    log.exception("scan", "Error scanning %s" % filename, xception)
Exemplo n.º 40
0
	def write_message(self, obj, *args, **kwargs):
		message = json.dumps(obj)
		try:
			super(WSHandler, self).write_message(message, *args, **kwargs)
		except tornado.websocket.WebSocketClosedError:
			self.on_close()
		except tornado.websocket.WebSocketError as e:
			log.exception("websocket", "WebSocket Error", e)
			try:
				self.close()
			except Exception:
				self.on_close()
Exemplo n.º 41
0
	def update_dj(self):
		for session in self.websockets:
			if session.user.is_dj():
				try:
					session.update_dj_only()
					log.debug("sync_update_dj", "Updated user %s session." % session.user.id)
				except Exception as e:
					try:
						session.rw_finish()
					except:
						pass
					log.exception("sync_update_dj", "Session failed to be updated during update_dj.", e)
Exemplo n.º 42
0
	def get(self):	#pylint: disable=E0202,W0221
		ph = self._output[self.return_name]
		self.write(self.render_string("bare_header.html", title="%s" % ph['name']))
		self.write("<script>\nwindow.top.refresh_all_screens = false;\n</script>")
		self.write("<h2>%s</h2>" % ph['name'])
		self.write("<span>Times from the server:</span><br>")
		self.write("<div style='font-family: monospace;'>%s</div>" % get_ph_formatted_time(ph['start'], ph['end'], 'US/Eastern'))
		self.write("<div style='font-family: monospace;'>%s</div>" % get_ph_formatted_time(ph['start'], ph['end'], 'US/Pacific'))
		self.write("<div style='font-family: monospace;'>%s</div>" % get_ph_formatted_time(ph['start'], ph['end'], 'Europe/London'))
		self.write("<div style='font-family: monospace;'>%s</div>" % get_ph_formatted_time(ph['start'], ph['end'], 'Asia/Tokyo'))

		total_len = 0
		for i, song in enumerate(ph['songs']):
			total_len += song['length']
		self.write("<br><div>Total length of songs: <b>%d:%02d</b></div>" % (int(total_len / 3600), (total_len / 60) % 60))

		self.write("<br><span>Change time.  Use YOUR timezone.</span><br>")
		index.write_html_time_form(self, "power_hour", ph['start'])
		self.write("<br><button onclick=\"window.top.call_api('admin/change_producer_start_time', ")
		self.write("{ 'utc_time': document.getElementById('power_hour_timestamp').value, 'sched_id': %s });\"" % ph['id'])
		self.write(">Change Time</button></div><hr>")

		self.write("<button onclick=\"window.top.call_api('admin/delete_producer', { 'sched_id': %s });\">Delete This Power Hour</button><hr>" % ph['id'])

		self.write("Name: <input type='text' id='new_ph_name' value='%s'><br>" % ph['name'])
		self.write("<button onclick=\"window.top.call_api('admin/change_producer_name', { 'sched_id': %s, 'name': document.getElementById('new_ph_name').value });\">Change Name</button><hr>" % ph['id'])

		self.write("URL: <input type='text' id='new_ph_url' value='%s'><br>" % (ph['url'] or ""))
		self.write("<button onclick=\"window.top.call_api('admin/change_producer_url', { 'sched_id': %s, 'url': document.getElementById('new_ph_url').value });\">Change URL</button><hr>" % ph['id'])

		self.write("<button onclick=\"window.top.call_api('admin/shuffle_power_hour', { 'sched_id': %s });\">Shuffle the Song Order</button><hr>\n\n" % ph['id'])

		try:
			self.write("<ol>")
			for song in ph['songs']:
				self.write("<li><div>%s" % song['title'])
				if song['one_up_used']:
					self.write(" <b>(PLAYED)</b>")
				elif song['one_up_queued']:
					self.write(" (queued)")
				self.write("</div><div>%s</div>\n" % song['albums'][0]['name'])
				self.write("<div>")
				self.write("<a onclick=\"window.top.call_api('admin/remove_from_power_hour', { 'one_up_id': %s });\">Delete</a> - " % song['one_up_id'])
				self.write("<a onclick=\"window.top.call_api('admin/move_up_in_power_hour', { 'one_up_id': %s });\">Move Up</a>" % song['one_up_id'])
				self.write("</div></li>\n")
			self.write("</ol>\n")
			self.write("<script>window.top.current_sched_id = %s;</script>\n\n" % ph['id'])
		except Exception as e:
			self.write("</ol>")
			self.write("<div>ERROR DISPLAYING SONG LIST.  Something is wrong.  Consult Rob.  Do not play this Power Hour.</div>")
			log.exception("admin", "Could not display song list.", e)
		self.write(self.render_string("basic_footer.html"))
Exemplo n.º 43
0
def _on_zmq(messages):
	global votes_by
	global last_vote_by

	for message in messages:
		try:
			message = json.loads(message)
		except Exception as e:
			log.exception("zeromq", "Error decoding ZeroMQ message.", e)
			return

		if not 'action' in message or not message['action']:
			log.critical("zeromq", "No action received from ZeroMQ.")

		try:
			if message['action'] == "result_sync":
				sessions[message['sid']].send_to_user(message['user_id'], message['uuid_exclusion'], message['data'])
			elif message['action'] == "live_voting":
				sessions[message['sid']].send_to_all(message['uuid_exclusion'], message['data'])
				delay_live_vote_removal(message['sid'])
			elif message['action'] == "delayed_live_voting":
				if not delayed_live_vote_timers[message['sid']]:
					delay_live_vote(message)
				delayed_live_vote[message['sid']] = message
			elif message['action'] == "update_all":
				delay_live_vote_removal(message['sid'])
				rainwave.playlist.update_num_songs()
				rainwave.playlist.prepare_cooldown_algorithm(message['sid'])
				cache.update_local_cache_for_sid(message['sid'])
				sessions[message['sid']].update_all(message['sid'])
				votes_by = {}
				last_vote_by = {}
			elif message['action'] == "update_ip":
				for sid in sessions:
					sessions[sid].update_ip_address(message['ip'])
			elif message['action'] == "update_listen_key":
				for sid in sessions:
					sessions[sid].update_listen_key(message['listen_key'])
			elif message['action'] == "update_user":
				for sid in sessions:
					sessions[sid].update_user(message['user_id'])
			elif message['action'] == "update_dj":
				sessions[message['sid']].update_dj()
			elif message['action'] == "ping":
				log.debug("zeromq", "Pong")
			elif message['action'] == "vote_by":
				votes_by[message['by']] = votes_by[message['by']] + 1 if message['by'] in votes_by else 1
				last_vote_by[message['by']] = timestamp()
		except Exception as e:
			log.exception("zeromq", "Error handling Zero MQ action '%s'" % message['action'], e)
			return
Exemplo n.º 44
0
    def save_preferences(self, ip_addr, prefs_json_string):
        if not config.get("store_prefs") or not prefs_json_string:
            return

        try:
            prefs_json_string = parse.unquote(prefs_json_string)
            if self.id > 1:
                if not db.c.fetch_var(
                        "SELECT COUNT(*) FROM r4_pref_storage WHERE user_id = %s",
                    (self.id, ),
                ):
                    db.c.update(
                        "INSERT INTO r4_pref_storage (user_id, prefs) VALUES (%s, %s::jsonb)",
                        (self.id, prefs_json_string),
                    )
                else:
                    db.c.update(
                        "UPDATE r4_pref_storage SET prefs = %s::jsonb WHERE user_id = %s",
                        (prefs_json_string, self.id),
                    )
            else:
                if not db.c.fetch_var(
                        "SELECT COUNT(*) FROM r4_pref_storage WHERE ip_address = %s AND user_id = %s",
                    (ip_addr, self.id),
                ):
                    db.c.update(
                        "INSERT INTO r4_pref_storage (user_id, ip_address, prefs) VALUES (%s, %s, %s::jsonb)",
                        (self.id, ip_addr, prefs_json_string),
                    )
                else:
                    db.c.update(
                        "UPDATE r4_pref_storage SET prefs = %s::jsonb WHERE ip_address = %s AND user_id = %s",
                        (prefs_json_string, ip_addr, self.id),
                    )
        except Exception as e:
            if "name" in self.data:
                log.exception(
                    "store_prefs",
                    "Could not store user preferences for %s (ID %s)" %
                    (self.data["name"], self.id),
                    e,
                )
            else:
                log.exception(
                    "store_prefs",
                    "Could not store user preferences for anonymous user from IP %s"
                    % ip_addr,
                    e,
                )
Exemplo n.º 45
0
def get_producer_at_time(sid, at_time):
	to_ret = None
	sched_id = db.c.fetch_var(	"SELECT sched_id "
								"FROM r4_schedule "
								"WHERE sid = %s AND sched_start <= %s AND sched_end > %s "
								"ORDER BY sched_id DESC "
								"LIMIT 1", (sid, at_time + 20, at_time))
	try:
		to_ret = events.event.BaseProducer.load_producer_by_id(sched_id)
	except Exception as e:
		log.warn("get_producer", "Failed to obtain producer.")
		log.exception("get_producer", "Failed to get an appropriate producer.", e)
	if not to_ret:
		return election.ElectionProducer(sid)
	return to_ret
Exemplo n.º 46
0
    def execute(self, *args, **kwargs):
        if self.disconnected:
            raise DatabaseDisconnectedError

        try:
            return super().execute(*args, **kwargs)
        except connection_errors as e:
            if self.auto_retry:
                log.exception("psycopg", "Psycopg exception", e)
                close()
                connect(auto_retry=self.auto_retry)
                global c
                return c.execute(*args, **kwargs)
            else:
                raise
Exemplo n.º 47
0
def _add_scan_error(filename, xception, full_exc=None):
	scan_errors = cache.get("backend_scan_errors")
	if not scan_errors:
		scan_errors = []

	eo = { "time": int(timestamp()), "file": filename, "type": xception.__class__.__name__, "error": str(xception), "traceback": "" }
	if not isinstance(xception, PassableScanError) and not isinstance(xception, IOError) and not isinstance(xception, OSError):
		if full_exc:
			eo['traceback'] = traceback.format_exception(*full_exc)			#pylint: disable=W0142
		else:
			eo['traceback'] = traceback.format_exception(*sys.exc_info())
	scan_errors.insert(0, eo)
	if len(scan_errors) > 100:
		scan_errors = scan_errors[0:100]
	cache.set("backend_scan_errors", scan_errors)
	log.exception("scan", "Error scanning %s" % filename, xception)
Exemplo n.º 48
0
	def update_all(self, sid):
		session_count = 0
		session_failed_count = 0
		for session in self.sessions + self.websockets:
			try:
				session.update()
				session_count += 1
			except Exception as e:
				try:
					session.rw_finish()
				except:
					pass
				session_failed_count += 1
				log.exception("sync_update_all", "Failed to update session.", e)
		log.debug("sync_update_all", "Updated %s sessions (%s failed) for sid %s." % (session_count, session_failed_count, sid))

		self.clear()
Exemplo n.º 49
0
	def update_all(self, sid):
		session_count = 0
		session_failed_count = 0
		for session in self.sessions + self.websockets:
			try:
				session.update()
				session_count += 1
			except Exception as e:
				try:
					session.rw_finish()
				except:
					pass
				session_failed_count += 1
				log.exception("sync_update_all", "Failed to update session.", e)
		log.debug("sync_update_all", "Updated %s sessions (%s failed) for sid %s." % (session_count, session_failed_count, sid))

		self.clear()
Exemplo n.º 50
0
	def _do_user_update(self, user_id):
		# clear() might wipe out the timeouts - let's make sure we don't waste resources
		# doing unnecessary updates
		if not user_id in self.user_update_timers or not self.user_update_timers[user_id]:
			return

		del self.user_update_timers[user_id]
		for session in self.find_user(user_id):
			try:
				session.update_user()
				log.debug("sync_update_user", "Updated user %s session." % session.user.id)
			except Exception as e:
				try:
					session.finish()
				except:
					pass
				log.exception("sync_update_user", "Session failed to be updated during update_user.", e)
		self.clean()
Exemplo n.º 51
0
	def _do_user_update(self, user_id):
		# clear() might wipe out the timeouts - let's make sure we don't waste resources
		# doing unnecessary updates
		if not user_id in self.user_update_timers or not self.user_update_timers[user_id]:
			return

		del self.user_update_timers[user_id]
		for session in self.find_user(user_id):
			try:
				session.update_user()
				log.debug("sync_update_user", "Updated user %s session." % session.user.id)
			except Exception as e:
				try:
					session.finish()
				except:
					pass
				log.exception("sync_update_user", "Session failed to be updated during update_user.", e)
		self.clean()
Exemplo n.º 52
0
def connect(auto_retry=True, retry_only_this_time=False):
    global connection
    global c

    if connection and c and not c.disconnected:
        return True

    name = config.get("db_name")
    host = config.get("db_host")
    port = config.get("db_port")
    user = config.get("db_user")
    password = config.get("db_password")

    psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
    psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
    base_connstr = "sslmode=disable "
    if host:
        base_connstr += "host=%s " % host
    if port:
        base_connstr += "port=%s " % port
    if user:
        base_connstr += "user=%s " % user
    if password:
        base_connstr += "password=%s " % password
    connected = False
    while not connected:
        try:
            connection = psycopg2.connect(base_connstr + ("dbname=%s" % name),
                                          connect_timeout=1)
            connection.set_isolation_level(
                psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
            connection.autocommit = True
            c = connection.cursor(cursor_factory=PostgresCursor)
            c.auto_retry = auto_retry
            connected = True
        except connection_errors as e:
            log.exception("psycopg", "Psycopg2 exception", e)
            if auto_retry or retry_only_this_time:
                time.sleep(1)
            else:
                raise
    return True
Exemplo n.º 53
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):
			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)
				pass
		if len(self.songs) == 0:
			raise ElectionEmptyException
Exemplo n.º 54
0
	def _do_ip_update(self, ip_address):
		if not ip_address in self.ip_update_timers or not self.ip_update_timers[ip_address]:
			return

		del self.ip_update_timers[ip_address]
		for session in self.find_ip(ip_address):
			try:
				if session.user.is_anonymous():
					session.update_user()
					log.debug("sync_update_ip", "Updated IP %s" % session.request.remote_ip)
				else:
					log.debug("sync_update_ip", "Warning logged in user of potential mixup at IP %s" % session.request.remote_ip)
					session.anon_registered_mixup_warn()
			except Exception as e:
				try:
					session.finish()
				except:
					pass
				self.remove(session)
				log.exception("sync", "Session failed to be updated during update_user.", e)
		self.clean()
Exemplo n.º 55
0
	def _do_user_update(self, session, updated_by_ip):
		# clear() might wipe out the timeouts for a bigger update (that includes user update anyway!)
		# don't bother updating again if that's already happened
		if not session in self.throttled:
			return
		del(self.throttled[session])

		try:
			potential_mixup_warn = updated_by_ip and not session.user.is_anonymous() and not session.user.is_tunedin()
			session.refresh_user()
			if potential_mixup_warn and not session.user.is_tunedin():
				log.debug("sync_update_ip", "Warning logged in user of potential M3U mixup at IP %s" % session.request.remote_ip)
				session.login_mixup_warn()
			else:
				session.update_user()
		except Exception as e:
			log.exception("sync", "Session failed to be updated during update_user.", e)
			try:
				session.rw_finish()
			except Exception:
				log.exception("sync", "Session failed finish() during update_user.", e)
Exemplo n.º 56
0
	def save_preferences(self, ip_addr, prefs_json_string):
		if not config.get("store_prefs") or not prefs_json_string:
			return
		if not db.c.is_postgres:
			return

		try:
			prefs_json_string = urllib2.unquote(prefs_json_string)
			if self.id > 1:
				if not db.c.fetch_var("SELECT COUNT(*) FROM r4_pref_storage WHERE user_id = %s", (self.id,)):
					db.c.update("INSERT INTO r4_pref_storage (user_id, prefs) VALUES (%s, %s::jsonb)", (self.id, prefs_json_string))
				else:
					db.c.update("UPDATE r4_pref_storage SET prefs = %s::jsonb WHERE user_id = %s", (prefs_json_string, self.id))
			else:
				if not db.c.fetch_var("SELECT COUNT(*) FROM r4_pref_storage WHERE ip_address = %s AND user_id = %s", (ip_addr, self.id)):
					db.c.update("INSERT INTO r4_pref_storage (user_id, ip_address, prefs) VALUES (%s, %s, %s::jsonb)", (self.id, ip_addr, prefs_json_string))
				else:
					db.c.update("UPDATE r4_pref_storage SET prefs = %s::jsonb WHERE ip_address = %s AND user_id = %s", (prefs_json_string, ip_addr, self.id))
		except Exception as e:
			if 'username' in self.data:
				log.exception("store_prefs", "Could not store user preferences for %s (ID %s)" % (self.data['username'], self.id), e)
			else:
				log.exception("store_prefs", "Could not store user preferences for anonymous user from IP %s" % ip_addr, e)
Exemplo n.º 57
0
def post_process(sid):
    try:
        db.c.start_transaction()
        start_time = timestamp()
        playlist.prepare_cooldown_algorithm(sid)
        rainwave.playlist_objects.album.clear_updated_albums(sid)
        log.debug("post", "Playlist prepare time: %.6f" % (timestamp() - start_time,))

        start_time = timestamp()
        current[sid].finish()
        for sched_id in db.c.fetch_list(
            "SELECT sched_id FROM r4_schedule WHERE sched_end < %s AND sched_used = FALSE", (timestamp(),)
        ):
            t_evt = events.event.BaseProducer.load_producer_by_id(sched_id)
            t_evt.finish()
        log.debug("post", "Current finish time: %.6f" % (timestamp() - start_time,))

        start_time = timestamp()
        last_song = current[sid].get_song()
        if last_song:
            db.c.update("INSERT INTO r4_song_history (sid, song_id) VALUES (%s, %s)", (sid, last_song.id))
        log.debug("post", "Last song insertion time: %s" % (timestamp() - start_time,))

        start_time = timestamp()
        history[sid].insert(0, current[sid])
        while len(history[sid]) > 5:
            history[sid].pop()
        log.debug("post", "History management: %.6f" % (timestamp() - start_time,))

        start_time = timestamp()
        current[sid] = upnext[sid].pop(0)
        current[sid].start_event()
        log.debug("advance", "Current management: %.6f" % (timestamp() - start_time,))

        start_time = timestamp()
        playlist.warm_cooled_songs(sid)
        playlist.warm_cooled_albums(sid)
        log.debug("advance", "Cooldown warming: %.6f" % (timestamp() - start_time,))

        start_time = timestamp()
        _add_listener_count_record(sid)
        _trim(sid)
        user.trim_listeners(sid)
        cache.update_user_rating_acl(sid, history[sid][0].get_song().id)
        user.unlock_listeners(sid)
        db.c.update("UPDATE r4_listeners SET listener_voted_entry = NULL WHERE sid = %s", (sid,))
        log.debug("advance", "User management and trimming: %.6f" % (timestamp() - start_time,))

        start_time = timestamp()
        # reduce song blocks has to come first, otherwise it wll reduce blocks generated by _create_elections
        playlist.reduce_song_blocks(sid)
        # update_cache updates both the line and expiry times
        # this is expensive and must be done before and after every request is filled
        # DO THIS AFTER EVERYTHING ELSE, RIGHT BEFORE NEXT MANAGEMENT, OR PEOPLE'S REQUESTS SLIP THROUGH THE CRACKS
        request.update_line(sid)
        # add to the event list / update start times for events
        manage_next(sid)
        # update expire times AFTER manage_next, so people who aren't in line anymore don't see expiry times
        request.update_expire_times()
        log.debug("advance", "Request and upnext management: %.6f" % (timestamp() - start_time,))

        update_memcache(sid)

        sync_to_front.sync_frontend_all(sid)
        db.c.commit()
    except:
        db.c.rollback()
        raise

    if current[sid] and config.has_station(sid, "tunein_partner_key") and config.get_station(sid, "tunein_partner_key"):
        ti_song = current[sid].get_song()
        if ti_song:
            ti_title = ti_song.data["title"]
            ti_album = ti_song.albums[0].data["name"]
            ti_artist = ", ".join([a.data["name"] for a in ti_song.artists])

            params = {
                "id": config.get_station(sid, "tunein_id"),
                "title": ti_title,
                "artist": ti_artist,
                "album": ti_album,
            }

            try:
                req = requests.Request("GET", "http://air.radiotime.com/Playing.ashx", params=params)
                p = req.prepare()
                # Must be done here rather than in params because of odd strings TuneIn creates
                p.url += "&partnerId=%s" % config.get_station(sid, "tunein_partner_id")
                p.url += "&partnerKey=%s" % config.get_station(sid, "tunein_partner_key")
                s = requests.Session()
                resp = s.send(p, timeout=3)
                log.debug("advance", "TuneIn updated (%s): %s" % (resp.status_code, resp.text))
            except Exception as e:
                log.exception("advance", "Could not update TuneIn.", e)
Exemplo n.º 58
0
	def _process_message(self, message, is_throttle_process=False):
		message_id = None
		if "message_id" in message:
			message_id = fieldtypes.zero_or_greater_integer(message['message_id'])

		throt_t = timestamp() - 3
		self.msg_times = [ t for t in self.msg_times if t > throt_t ]

		if not is_throttle_process:
			self.msg_times.append(timestamp())
			# log.debug("throttle", "%s - %s" % (len(self.msg_times), message['action']))
			if self.throttled:
				# log.debug("throttle", "Currently throttled, adding to queue.")
				self.throttled_msgs.append(message)
				return
			elif len(self.msg_times) >= 5:
				# log.debug("throttle", "Too many messages, throttling.")
				self.throttled = True
				self.throttled_msgs.append(message)
				tornado.ioloop.IOLoop.instance().add_timeout(datetime.timedelta(seconds=0.5), self.process_throttle)
				return

		if message['action'] == "ping":
			self.write_message({ "pong": { "timestamp": timestamp() } })
			return

		if message['action'] == "pong":
			self.write_message({ "pongConfirm": { "timestamp": timestamp() } })
			return

		if message['action'] == "vote":
			zeromq.publish({ "action": "vote_by", "by": self.votes_by_key })

		if message['action'] == "check_sched_current_id":
			self._do_sched_check(message)
			return

		message['action'] = "/api4/%s" % message['action']
		if not message['action'] in api_endpoints:
			self.write_message({ "wserror": { "tl_key": "websocket_404", "text": self.locale.translate("websocket_404") } })
			return

		endpoint = api_endpoints[message['action']](websocket=True)
		endpoint.locale = self.locale
		endpoint.request = FakeRequestObject(message, self.request.cookies)
		endpoint.sid = message['sid'] if ('sid' in message and message['sid']) else self.sid
		endpoint.user = self.user
		#pylint: disable=W0212
		try:
			startclock = timestamp()
			# TODO: this should be a part of prepare_standalone!
			# it's required to see if another person on the same IP address has overriden the vote
			# for the in-memory user here, so it requires a DB fetch.
			if message['action'] == "/api4/vote" and self.user.is_anonymous():
				self.user.refresh(self.sid)
			if "message_id" in message:
				if message_id == None:
					endpoint.prepare_standalone()
					raise APIException("invalid_argument", argument="message_id", reason=fieldtypes.zero_or_greater_integer_error, http_code=400)
				endpoint.prepare_standalone(message_id)
			else:
				endpoint.prepare_standalone()
			endpoint.post()
			endpoint.append("api_info", { "exectime": timestamp() - startclock, "time": round(timestamp()) })
			if endpoint.sync_across_sessions:
				if endpoint.return_name in endpoint._output and isinstance(endpoint._output[endpoint.return_name], dict) and not endpoint._output[endpoint.return_name]['success']:
					pass
				else:
					zeromq.publish({ "action": "result_sync", "sid": self.sid, "user_id": self.user.id, "data": endpoint._output, "uuid_exclusion": self.uuid })
			if message['action'] == "/api4/vote" and endpoint.return_name in endpoint._output and isinstance(endpoint._output[endpoint.return_name], dict) and endpoint._output[endpoint.return_name]['success']:
				live_voting = rainwave.schedule.update_live_voting(self.sid)
				endpoint.append("live_voting", live_voting)
				if self.should_vote_throttle():
					zeromq.publish({ "action": "delayed_live_voting", "sid": self.sid, "uuid_exclusion": self.uuid, "data": { "live_voting": live_voting } })
				else:
					zeromq.publish({ "action": "live_voting", "sid": self.sid, "uuid_exclusion": self.uuid, "data": { "live_voting": live_voting } })
		except Exception as e:
			endpoint.write_error(500, exc_info=sys.exc_info(), no_finish=True)
			log.exception("websocket", "API Exception during operation.", e)
		finally:
			self.write_message(endpoint._output)
Exemplo n.º 59
0
    def get(self):  # pylint: disable=E0202
        ph = self._output[self.return_name]
        self.write(self.render_string("bare_header.html", title="%s" % ph["name"]))
        self.write("<script>\nwindow.top.refresh_all_screens = false;\n</script>")
        self.write("<h2>%s</h2>" % ph["name"])
        self.write("<span>Times from the server:</span><br>")
        self.write(
            "<div style='font-family: monospace;'>%s</div>"
            % get_ph_formatted_time(ph["start"], ph["end"], "US/Eastern")
        )
        self.write(
            "<div style='font-family: monospace;'>%s</div>"
            % get_ph_formatted_time(ph["start"], ph["end"], "US/Pacific")
        )
        self.write(
            "<div style='font-family: monospace;'>%s</div>"
            % get_ph_formatted_time(ph["start"], ph["end"], "Europe/London")
        )
        self.write(
            "<div style='font-family: monospace;'>%s</div>"
            % get_ph_formatted_time(ph["start"], ph["end"], "Asia/Tokyo")
        )

        total_len = 0
        for song in ph["songs"]:
            total_len += song["length"]
        self.write(
            "<br><div>Total length of songs: <b>%d:%02d</b></div>"
            % (int(total_len / 3600), (total_len / 60) % 60)
        )

        self.write("<br><span>Change time.  Use YOUR timezone.</span><br>")
        index.write_html_time_form(self, "power_hour", ph["start"])
        self.write(
            "<br><button onclick=\"window.top.call_api('admin/change_producer_start_time', "
        )
        self.write(
            "{ 'utc_time': document.getElementById('power_hour_timestamp').value, 'sched_id': %s });\""
            % ph["id"]
        )
        self.write(">Change Time</button></div><hr>")

        self.write(
            "<button onclick=\"window.top.call_api('admin/delete_producer', { 'sched_id': %s });\">Delete This Power Hour</button><hr>"
            % ph["id"]
        )

        self.write(
            "Name: <input type='text' id='new_ph_name' value='%s'><br>" % ph["name"]
        )
        self.write(
            "<button onclick=\"window.top.call_api('admin/change_producer_name', { 'sched_id': %s, 'name': document.getElementById('new_ph_name').value });\">Change Name</button><hr>"
            % ph["id"]
        )

        self.write(
            "URL: <input type='text' id='new_ph_url' value='%s'><br>"
            % (ph["url"] or "")
        )
        self.write(
            "<button onclick=\"window.top.call_api('admin/change_producer_url', { 'sched_id': %s, 'url': document.getElementById('new_ph_url').value });\">Change URL</button><hr>"
            % ph["id"]
        )

        self.write(
            "<button onclick=\"window.top.call_api('admin/shuffle_power_hour', { 'sched_id': %s });\">Shuffle the Song Order</button><hr>\n\n"
            % ph["id"]
        )

        try:
            self.write("<ol>")
            for song in ph["songs"]:
                self.write("<li><div>%s" % song["title"])
                if song["one_up_used"]:
                    self.write(" <b>(PLAYED)</b>")
                elif song["one_up_queued"]:
                    self.write(" (queued)")
                self.write("</div><div>%s</div>\n" % song["albums"][0]["name"])
                self.write("<div>")
                self.write(
                    "<a onclick=\"window.top.call_api('admin/remove_from_power_hour', { 'one_up_id': %s });\">Delete</a> - "
                    % song["one_up_id"]
                )
                self.write(
                    "<a onclick=\"window.top.call_api('admin/move_up_in_power_hour', { 'one_up_id': %s });\">Move Up</a>"
                    % song["one_up_id"]
                )
                self.write("</div></li>\n")
            self.write("</ol>\n")
            self.write(
                "<script>window.top.current_sched_id = %s;</script>\n\n" % ph["id"]
            )
        except Exception as e:
            self.write("</ol>")
            self.write(
                "<div>ERROR DISPLAYING SONG LIST.  Something is wrong.  Consult Rob.  Do not play this Power Hour.</div>"
            )
            log.exception("admin", "Could not display song list.", e)
        self.write(self.render_string("basic_footer.html"))