def acquire_lock(lock_key, time=None): ''' Acquire lock. 若lock不存在即当前状态为unlock,则获取到,将状态改为locked,返回True 若lock存在即当前状态为locked,则未获取到,返回False ''' v = redis.get(lock_key) if v is None: if time is None: time = app.config['REDIS_EXPIRE_TIME_SHORT'] redis.setex(lock_key, 1, time) return True else: return False
async def run(self, uuid): redis.incr("exec_sum") redis.incr(uuid + "&&exec_sum") workflow_info = Workflow.select('uuid', 'name', 'remarks', 'start_app', 'end_app', 'input_app', 'webhook_app', 'timer_app', 'flow_json', 'flow_data', 'controller_data', 'local_var_data', 'status').where("uuid", uuid).first() if workflow_info: if str(workflow_info.status) == "1": return False self.workflow_name = workflow_info.name self.workflow_remarks = workflow_info.remarks self.start_app = workflow_info.start_app self.end_app = workflow_info.end_app self.input_app = workflow_info.input_app self.webhook_app = workflow_info.webhook_app self.timer_app = workflow_info.timer_app self.flow_json = json.loads(workflow_info.flow_json) self.flow_data = json.loads(workflow_info.flow_data) await self.make_var(workflow_info.local_var_data, workflow_info.controller_data) target_app = await self.find_start_app( edges=self.flow_json["edges"], start_app=self.start_app) await self.add_execute_logs(uuid=uuid, app_uuid=self.start_app, app_name="开始", result="剧本开始执行", status=0, html="<span>剧本开始执行</span>") is_while = True while is_while: try: edge_name, source_app, next_app, is_switch, edge_action, edge_if_else = await self.find_next_app( edges=self.flow_json["edges"], next_app=target_app) except Exception as e: await self.add_execute_logs( uuid=uuid, app_uuid="", app_name="", result="当前剧本不具有可执行条件", status=1, html="<span>当前剧本不具有可执行条件</span>") await self.decr_sum(uuid=uuid) is_while = False break key = target_app + "&&" + self.only_id + "&&sum" if redis.exists(key) == 1: sum = redis.get(key) redis.set(key, int(sum) + 1, ex=60 * 1) else: redis.set(key, 1, ex=60 * 1) if self.input_app == source_app or self.webhook_app == source_app or self.timer_app == source_app: is_status, if_else_result = await self.get_app_data( uuid=uuid, app_uuid=source_app) else: source_info = self.flow_data[source_app] is_status, if_else_result = await self.get_app_data( uuid=uuid, app_uuid=source_app, app_info=source_info) if is_status == 0: if is_switch: if str(edge_action) == "1": is_arr = re.findall(r'\[\w*.+\]', edge_if_else) if len(is_arr) > 0: edge_if_else_arr = str(is_arr[0]).replace( "[", "").replace("]", "").split(",") if if_else_result in edge_if_else_arr: target_app = next_app else: pass else: if edge_if_else == if_else_result: target_app = next_app else: pass elif str(edge_action) == "2": is_arr = re.findall(r'\[\w*.+\]', edge_if_else) if len(is_arr) > 0: edge_if_else_arr = str(is_arr[0]).replace( "[", "").replace("]", "").split(",") if if_else_result not in edge_if_else_arr: target_app = next_app else: pass else: if edge_if_else != if_else_result: target_app = next_app else: pass elif str(edge_action) == "3": is_arr = re.findall(r'{0}'.format(edge_if_else), if_else_result) if len(is_arr) > 0: target_app = next_app else: pass else: target_app = next_app else: is_while = False if next_app == self.end_app: await self.add_execute_logs(uuid=uuid, app_uuid=self.end_app, app_name="结束", result="剧本执行结束", status=0, html="<span>剧本执行结束</span>") await self.add_report() await self.decr_sum(uuid=uuid) is_while = False break
def check(): active = redis.get("active_requests") if active > 0: leds.enable_act_led() else: leds.disable_act_led()
async def get_app_data(self, uuid, app_uuid, app_info=None): key_result = app_uuid + "&&" + self.only_id + "&&result" key_status = app_uuid + "&&" + self.only_id + "&&status" if self.input_app == app_uuid or self.webhook_app == app_uuid or self.timer_app == app_uuid: if redis.exists(key_result) == 0: result_data = await self.execute(app_uuid=app_uuid) result = str(result_data["result"]) redis.set(key_result, result, ex=60 * 1) redis.set(key_status, result_data["status"], ex=60 * 1) if self.input_app == app_uuid: await self.add_execute_logs(uuid=uuid, app_uuid=app_uuid, app_name="用户输入", result=result, status=result_data["status"], html=result) elif self.webhook_app == app_uuid: await self.add_execute_logs(uuid=uuid, app_uuid=app_uuid, app_name="WebHook", result=result, status=result_data["status"], html=result) elif self.timer_app == app_uuid: await self.add_execute_logs(uuid=uuid, app_uuid=app_uuid, app_name="定时器", result=result, status=result_data["status"], html=result) return result_data["status"], result else: return int(redis.get(key_status).decode()), redis.get( key_result).decode() else: if redis.exists(key_result) == 0: result_data = await self.execute(app_uuid=app_uuid, app_dir=app_info["app_dir"], data=app_info["data"]) result = str(result_data["result"]) redis.set(key_result, result, ex=60 * 1) redis.set(key_status, result_data["status"], ex=60 * 1) if str(result_data["html"]) == "": html_data = result else: html_data = result_data["html"] await self.add_execute_logs( uuid=uuid, app_uuid=app_uuid, app_name=app_info["data"]["node_name"], result=result, status=result_data["status"], html=html_data, args=result_data["args"]) return result_data["status"], result else: return int(redis.get(key_status).decode()), redis.get( key_result).decode()
async def execute(self, app_uuid, app_dir=None, data=None): args_data = copy.deepcopy(data) if app_dir: args_data["app_dir"] = app_dir args_data_json_x = json.dumps(args_data) if self.input_app == app_uuid or self.webhook_app == app_uuid: key = app_uuid + "&&" + self.only_id + "&&text" return { "status": 0, "result": redis.get(key).decode(), "args": args_data_json_x, "html": "" } if self.timer_app == app_uuid: return { "status": 0, "result": "定时器正在执行", "args": args_data_json_x, "html": "" } is_identification = await self.is_identification(app_dir=app_dir) if is_identification == False: return { "status": 1, "result": "请勿使用非法应用", "args": args_data_json_x, "html": "" } is_public_status, is_public = await self.is_public(app_dir=app_dir) if is_public_status == 0: return { "status": 1, "result": "请配置 is_public", "args": args_data_json_x, "html": "" } import_path = "" if platform.system() == 'Windows': import_path = 'apps.' + str(app_dir) + '.windows.run' elif platform.system() == 'Linux': import_path = 'apps.' + str(app_dir) + '.linux.run' elif platform.system() == "Darwin": import_path = 'apps.' + str(app_dir) + '.mac.run' try: data["app"] = __import__(import_path, fromlist=['*']) except Exception as e: return { "status": 1, "result": "请使用正确的应用", "args": args_data_json_x, "html": "" } args = "" for key in data: if key != "node_name" and key != "action" and key != "app" and key != "action_name" and key != "description" and key != "app_dir": args = args + "," + key var_status, text = await self.analysis_var(text=str(data[key])) redis_key = app_uuid + "&&" + self.only_id + "&&" + key redis.set(redis_key, text, ex=60 * 1) if var_status == 0: data[key] = text args_data[key] = text else: return { "status": var_status, "result": text, "args": args_data_json_x, "html": "" } args_data_json = json.dumps(args_data) eval_action = "app.{action}({args})".format(action=data["action"], args=args[1:]) try: result_data = await eval(eval_action, data) except TypeError as e: return { "status": 1, "result": "请勿使用非法应用", "args": args_data_json, "html": "" } if "status" not in result_data: return { "status": 2, "result": "APP 错误,请检测 status 返回字段", "args": args_data_json, "html": "" } if "result" not in result_data: return { "status": 2, "result": "APP 错误,请检测 result 返回字段", "args": args_data_json, "html": "" } if "html" not in result_data: html_data = "" else: html_data = result_data["html"] return { "status": result_data["status"], "result": str(result_data["result"]), "args": args_data_json, "html": html_data }
def state_dict() -> Dict[str, Any]: """Extends the base state with musiq-specific information and returns it.""" state = base.state_dict() musiq_state: Dict[str, Any] = {} musiq_state["paused"] = storage.get("paused") musiq_state["shuffle"] = storage.get("shuffle") musiq_state["repeat"] = storage.get("repeat") musiq_state["autoplay"] = storage.get("autoplay") musiq_state["volume"] = storage.get("volume") try: current_song = CurrentSong.objects.get() current_song_dict = model_to_dict(current_song) current_song_dict = util.camelize(current_song_dict) current_song_dict["durationFormatted"] = song_utils.format_seconds( current_song_dict["duration"]) musiq_state["currentSong"] = current_song_dict paused = storage.get("paused") if paused: progress = (current_song.last_paused - current_song.created).total_seconds() else: progress = (timezone.now() - current_song.created).total_seconds() progress /= current_song.duration musiq_state["progress"] = progress * 100 except CurrentSong.DoesNotExist: musiq_state["currentSong"] = None musiq_state["paused"] = True musiq_state["progress"] = 0 song_queue = [] total_time = 0 all_songs = queue.all() if storage.get("interactivity") in [ storage.Interactivity.upvotes_only, storage.Interactivity.full_voting, ]: all_songs = all_songs.order_by("-votes", "index") for song in all_songs: song_dict = model_to_dict(song) song_dict = util.camelize(song_dict) song_dict["durationFormatted"] = song_utils.format_seconds( song_dict["duration"]) song_queue.append(song_dict) if song_dict["duration"] < 0: # skip duration of placeholders continue total_time += song_dict["duration"] musiq_state["totalTimeFormatted"] = song_utils.format_seconds(total_time) musiq_state["songQueue"] = song_queue if state["alarm"]: musiq_state["currentSong"] = { "queueKey": -1, "manuallyRequested": False, "votes": 0, "created": "", # https://github.com/python/mypy/issues/4976 **util.camelize(cast(Dict[Any, Any], get_alarm_metadata())), } musiq_state["progress"] = 0 musiq_state["paused"] = False elif redis.get("backup_playing"): musiq_state["currentSong"] = { "queueKey": -1, "manuallyRequested": False, "votes": 0, "internalUrl": "backup_stream", "externalUrl": storage.get("backup_stream"), "artist": "", "title": "Backup Stream", "duration": 60 * 60 * 24, "created": "", } musiq_state["paused"] = False state["musiq"] = musiq_state return state
def online_suggestions(request: WSGIRequest) -> JsonResponse: """Returns online suggestions for a given query.""" query = request.GET["term"] suggest_playlist = request.GET["playlist"] == "true" if storage.get("new_music_only"): return JsonResponse([], safe=False) results: List[SuggestionResult] = [] if storage.get("online_suggestions") and redis.get("has_internet"): threads = [] results_lock = threading.Lock() def fetch_youtube() -> None: from core.musiq.youtube import Youtube youtube_suggestions = Youtube().get_search_suggestions(query) youtube_suggestions = youtube_suggestions[:storage.get( "youtube_suggestions")] with results_lock: for suggestion in youtube_suggestions: results.append({ "key": -1, "value": suggestion, "type": "youtube-online" }) def fetch_spotify() -> None: from core.musiq.spotify import Spotify spotify_suggestions = Spotify().get_search_suggestions( query, suggest_playlist) spotify_suggestions = spotify_suggestions[:storage.get( "spotify_suggestions")] with results_lock: for suggestion, external_url in spotify_suggestions: results.append({ "key": external_url, "value": suggestion, "type": "spotify-online", }) def fetch_soundcloud() -> None: from core.musiq.soundcloud import Soundcloud soundcloud_suggestions = Soundcloud().get_search_suggestions(query) soundcloud_suggestions = soundcloud_suggestions[:storage.get( "soundcloud_suggestions")] with results_lock: for suggestion in soundcloud_suggestions: results.append({ "key": -1, "value": suggestion, "type": "soundcloud-online" }) def fetch_jamendo() -> None: from core.musiq.jamendo import Jamendo jamendo_suggestions = Jamendo().get_search_suggestions(query) jamendo_suggestions = jamendo_suggestions[:storage.get( "jamendo_suggestions")] with results_lock: for suggestion in jamendo_suggestions: results.append({ "key": -1, "value": suggestion, "type": "jamendo-online" }) suggestion_fetchers = { "youtube": fetch_youtube, "spotify": fetch_spotify, "soundcloud": fetch_soundcloud, "jamendo": fetch_jamendo, } for platform in ["youtube", "spotify", "soundcloud", "jamendo"]: if (storage.get(cast(PlatformEnabled, f"{platform}_enabled")) and storage.get( cast(PlatformSuggestions, f"{platform}_suggestions")) > 0): thread = threading.Thread(target=suggestion_fetchers[platform]) threads.append(thread) thread.start() for thread in threads: thread.join() return JsonResponse(results, safe=False)
def _offline_song_suggestions(query: str) -> List[SuggestionResult]: results: List[SuggestionResult] = [] terms = query.split() song_results: Iterable[Mapping[str, Any]] if settings.DEBUG: # Testing the whole table whether it contains any term is quite costly. # Used for sqlite3 which does not have a similarity function. matching_songs = ArchivedSong.objects.prefetch_related("queries") for term in terms: matching_songs = matching_songs.filter( Q(title__icontains=term) | Q(artist__icontains=term) | Q(queries__query__icontains=term)) song_results = ( matching_songs.order_by("-counter") # annotate with same values as in the postgres case to have a consistent interface .annotate( u_id=F("id"), u_url=F("url"), u_artist=F("artist"), u_title=F("title"), u_duration=F("duration"), u_counter=F("counter"), u_cached=F("cached"), ).values(*u_values_list).distinct() [:storage.get("number_of_suggestions")]) # Perhaps this could be combined with the similarity search # to improve usability with the right weighting. # matching_songs = matching_songs.annotate( # artist_similarity=Coalesce(TrigramWordSimilarity(query, "artist"), 0), # title_similarity=Coalesce(TrigramWordSimilarity(query, "title"), 0), # query_similarity=Coalesce(TrigramWordSimilarity(query, "queries__query"), 0), # max_similarity=Greatest( # "artist_similarity", "title_similarity", "query_similarity" # ), # ) # To combine, use union instead of | (or) in order to access the annotated values # similar_songs = union(matching_songs) else: song_results = _postgres_song_results(query) has_internet = redis.get("has_internet") for song in song_results: if song_utils.is_forbidden( song["u_artist"]) or song_utils.is_forbidden(song["u_title"]): continue platform = song_utils.determine_url_type(song["u_url"]) # don't suggest online songs when we don't have internet if not has_internet and not song["u_cached"]: continue if platform == "local": # don't suggest local songs if they are not cached (=not at expected location) if not song["u_cached"]: continue else: # don't suggest songs if the respective platform is disabled assert platform in ["youtube", "spotify", "soundcloud", "jamendo"] if not storage.get(cast(PlatformEnabled, f"{platform}_enabled")): continue result_dict: SuggestionResult = { "key": song["u_id"], "value": song_utils.displayname(song["u_artist"], song["u_title"]), "counter": song["u_counter"], "type": platform, "durationFormatted": song_utils.format_seconds(song["u_duration"]), } results.append(result_dict) # mark suggestions whose displayname is identical seen_values: Dict[str, int] = {} for index, result in enumerate(results): if result["value"] in seen_values: result["confusable"] = True results[seen_values[result["value"]]]["confusable"] = True seen_values[result["value"]] = index return results