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
Esempio n. 2
0
File: core.py Progetto: yinlj/w5
    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
Esempio n. 3
0
 def check():
     active = redis.get("active_requests")
     if active > 0:
         leds.enable_act_led()
     else:
         leds.disable_act_led()
Esempio n. 4
0
File: core.py Progetto: yinlj/w5
    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()
Esempio n. 5
0
File: core.py Progetto: yinlj/w5
    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
        }
Esempio n. 6
0
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
Esempio n. 7
0
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)
Esempio n. 8
0
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