Exemple #1
0
def bilibiliStartLive(subscribe_obj, room_title, area_id=None):
    curSub = subscribe_obj

    tmp_area_id = area_id
    if tmp_area_id == None:
        tmp_area_id = curSub.get('bilibili_areaid', '199')

    b = getBilibiliProxy(curSub)

    t_room_id = b.getLiveRoomId()
    t_cur_blive_url = 'https://live.bilibili.com/' + t_room_id
    curSub['cur_blive_url'] = t_cur_blive_url
    # b.stopLive(t_room_id)   #Just don't care the Live status, JUST STARTLIVE
    t_b_title = curSub.get('change_b_title')
    if t_b_title:
        b.updateRoomTitle(t_room_id, t_b_title)
    rtmp_link = b.startLive(t_room_id, tmp_area_id)

    if curSub.get(
            'auto_send_dynamic'
    ) and rtmp_link and questInfo._getObjWithRTMPLink(rtmp_link) is None:
        if curSub.get('dynamic_template'):
            b.send_dynamic(
                (curSub['dynamic_template']).replace('${roomUrl}',
                                                     t_cur_blive_url))
        else:
            b.send_dynamic('转播开始了哦~')
    return b, t_room_id, rtmp_link
Exemple #2
0
def _forwardToBilibili_Sync(channelId,
                            link,
                            room_title,
                            area_id=None,
                            isSubscribeQuest=True):
    resloveURLOK = False
    tmp_retryTime = 10
    while tmp_retryTime > 0:
        if 'youtube.com/' in link or 'youtu.be/' in link:
            m3u8Link, err, errcode = _getYotube_m3u8_sync(link)
            if errcode == 0:
                link = m3u8Link
                resloveURLOK = True
                break
            else:
                tmp_retryTime -= 1
                time.sleep(60)
        else:
            utitls.myLogger(
                '_forwardToBilibili_Sync LOG: Unsupport ForwardLink:' + link)
            return

    if resloveURLOK:
        b, t_room_id, rtmp_link = bilibiliStartLive(channelId, room_title,
                                                    area_id)
        if rtmp_link:
            tmp_quest = questInfo._getObjWithRTMPLink(rtmp_link)
            if tmp_quest != None:
                try:
                    os.kill(tmp_quest.get('pid', None), signal.SIGKILL)
                except Exception:
                    utitls.myLogger(traceback.format_exc())
                questInfo.removeQuest(rtmp_link)
            # force stream
            _forwardStream_sync(link, rtmp_link, isSubscribeQuest)
Exemple #3
0
def bilibiliStartLive(channelId, room_title, area_id=None):
    curSub = utitls.getSubInfoWithSubChannelId(channelId)
    curBiliAccCookie = curSub['bilibili_cookiesStr']

    tmp_area_id = area_id
    if tmp_area_id == None:
        tmp_area_id = curSub['bilibili_areaid']

    b = BilibiliProxy(curBiliAccCookie)
    t_room_id = b.getLiveRoomId()
    # b.stopLive(t_room_id)   #Just don't care the Live status, JUST STARTLIVE

    b.updateRoomTitle(t_room_id, room_title)
    rtmp_link = b.startLive(t_room_id, tmp_area_id)
    if curSub[
            'auto_send_dynamic'] and rtmp_link and questInfo._getObjWithRTMPLink(
                rtmp_link) is None:
        if curSub['dynamic_template']:
            b.send_dynamic(curSub['dynamic_template']).replace(
                '${roomUrl}', 'https://live.bilibili.com/' + t_room_id)
        else:
            b.send_dynamic('转播开始了哦~')
    return b, t_room_id, rtmp_link
Exemple #4
0
    def do_GET(self):
        request_path = self.path
        rc = 404
        rb = None
        params = parse_qs(urlsplit(request_path).query)

        try:
            if request_path.startswith('/web/'):
                fname, ext = os.path.splitext(request_path)
                if ext in (".html", ".css", ".js"):
                    tmp_filePath = os.path.join(os.getcwd())
                    for v in request_path.split('/'):
                        tmp_filePath = os.path.join(tmp_filePath, v)
                    print(tmp_filePath)
                    with open(tmp_filePath, 'r', encoding='utf-8') as f:
                        self.send_response(200)
                        self.send_header('Content-type', types_map[ext])
                        self.end_headers()
                        self.wfile.write(f.read().encode('utf-8'))
                return
        except Exception:
            utitls.myLogger(traceback.format_exc())
            self.send_error(404)
            self.end_headers()
            return

        if request_path.startswith('/subscribe?'):
            hub_challenge_list = params.get('hub.challenge', None)
            if None != hub_challenge_list:
                rc = 202
                rb = hub_challenge_list[0]
        elif request_path.startswith('/questlist'):
            rc = 200
            rb = json.dumps(getQuestList_AddStarts())
        elif request_path.startswith('/get_manual_json'):
            rc = 200
            rb = json.dumps(utitls.manualJson())
        elif request_path.startswith('/addRestreamSrc'):
            rc = 200
            srcNote_list = params.get('srcNote', None)
            srcLink_list = params.get('srcLink', None)
            if srcNote_list and srcLink_list:
                tmp_srcNote = srcNote_list[0].strip()
                tmp_srcLink = srcLink_list[0].strip()
                utitls.addManualSrc(tmp_srcNote, tmp_srcLink)
            rb = json.dumps({"code": 0, "msg": "添加成功"})
        elif request_path.startswith('/addRtmpDes'):
            rc = 200
            rtmpNote_list = params.get('rtmpNote', None)
            rtmpLink_list = params.get('rtmpLink', None)
            if rtmpNote_list and rtmpLink_list:
                tmp_rtmpNote = rtmpNote_list[0].strip()
                tmp_rtmpLink = rtmpLink_list[0].strip()
                utitls.addManualDes(tmp_rtmpNote, tmp_rtmpLink)
            rb = json.dumps({"code": 0, "msg": "添加成功"})
        elif request_path.startswith('/kill_quest?'):
            rc = 200
            tmp_rtmpLink_list = params.get('rtmpLink', None)
            if tmp_rtmpLink_list:
                tmp_rtmpLink = tmp_rtmpLink_list[0].strip()
                tmp_quest = _getObjWithRTMPLink(tmp_rtmpLink)
                if tmp_quest != None:
                    try:
                        os.kill(tmp_quest.get('pid', None), signal.SIGKILL)
                        rb = json.dumps({"code": 0, "msg": "操作成功"})
                    except Exception:
                        utitls.myLogger(traceback.format_exc())
                        rb = json.dumps({"code": -2, "msg": "错误PID,操作失败!!"})
                else:
                    rb = json.dumps({
                        "code":
                        -1,
                        "msg":
                        "查找不到对应的任务:{},操作失败!!".format(tmp_rtmpLink)
                    })
        elif request_path.startswith('/live_restream?'):
            forwardLink_list = params.get('forwardLink', None)
            restreamRtmpLink_list = params.get('restreamRtmpLink', None)
            if forwardLink_list and restreamRtmpLink_list:
                tmp_forwardLink = forwardLink_list[0].strip()
                tmp_rtmpLink = restreamRtmpLink_list[0].strip()
                isForwardLinkFormateOK = True

                if 'rtmp://' in tmp_rtmpLink:
                    if 'twitcasting.tv/' in tmp_forwardLink:
                        #('https://www.', 'twitcasting.tv/', 're2_takatsuki/fwer/aeqwet')
                        tmp_twitcasID = tmp_forwardLink.partition(
                            'twitcasting.tv/')[2]
                        tmp_twitcasID = tmp_twitcasID.split('/')[0]
                        tmp_forwardLink = 'http://twitcasting.tv/{}/metastream.m3u8/?video=1'.format(
                            tmp_twitcasID)
                    elif '.m3u8' in tmp_forwardLink \
                        or 'youtube.com/' in tmp_forwardLink or 'youtu.be/' in tmp_forwardLink:
                        tmp_forwardLink = tmp_forwardLink
                    else:
                        isForwardLinkFormateOK = False

                    rc = 200
                    if isForwardLinkFormateOK:
                        if checkIfInQuest(tmp_rtmpLink) == False:
                            #try to restream
                            async_forwardStream(tmp_forwardLink, tmp_rtmpLink,
                                                False)
                            rb = json.dumps({
                                "code":
                                0,
                                "msg":
                                "请求成功。请等待大概30秒,网络不好时程序会自动重试30次。也可以查看任务状态看是否添加成功。\
                            \nRequesting ForwardLink: {},\nRequesting RestreamRtmpLink: {}\n\n当前任务:\n{}"
                                .format(tmp_forwardLink, tmp_rtmpLink,
                                        getQuestListStr())
                            })
                        else:
                            rb = json.dumps({
                                "code":
                                1,
                                "msg":
                                "当前推流已经在任务中. \nRequesting ForwardLink: {},\nRequesting RestreamRtmpLink: {}\n\n\n-----------------CurrentQuests:\n{}"
                                .format(tmp_forwardLink, tmp_rtmpLink,
                                        getQuestListStr())
                            })
                    else:
                        rb = json.dumps({
                            "code": -3,
                            "msg": "来源地址格式错误, 请查看上面支持的格式"
                        })
                else:
                    rc = 200
                    rb = json.dumps({
                        "code":
                        -4,
                        "msg":
                        "RTMPLink格式错误!!! bilibili的RTMPLink格式是两串合起来。\nEXAMPLE:rtmp://XXXXXX.acg.tv/live-js/?streamname=live_XXXXXXX&key=XXXXXXXXXX"
                    })

        self.send_response(rc)
        self.send_header('Content-type', 'text/html; charset=utf-8')
        self.end_headers()
        if None != rb:
            try:
                self.wfile.write(rb.encode('utf-8'))
            except Exception:
                print(traceback.format_exc())
Exemple #5
0
    def do_GET(self):
        request_path = self.path
        rc = 404
        rb = None
        sh = {'Content-Encoding': 'gzip'}
        params = parse_qs(urlsplit(request_path).query)

        try:
            if request_path.startswith('/web/'):
                request_path = request_path.split('?')[0]
                fname, ext = os.path.splitext(request_path)
                if ext in (".html", ".css", ".js"):
                    tmp_filePath = os.path.join(os.getcwd())
                    for v in request_path.split('/'):
                        tmp_filePath = os.path.join(tmp_filePath, v)
                    with open(tmp_filePath, 'r', encoding='utf-8') as f:
                        lastMtime = self.date_time_string(
                            os.fstat(f.fileno()).st_mtime)
                        if self.headers.get('If-Modified-Since') == lastMtime:
                            self.send_response(304)
                            self.end_headers()
                            return

                        self.send_response(200)
                        sh['Content-type'] = types_map[ext]
                        sh['Cache-Control'] = 'max-age=72000'
                        fb = f.read()
                        rb = self.gzip_encode(fb.encode('utf-8'))
                        sh['Content-length'] = len(rb)
                        sh['Last-Modified'] = lastMtime
                        for key in sh:
                            self.send_header(key, sh[key])
                        self.end_headers()
                        self.wfile.write(rb)
                return
        except Exception:
            utitls.myLogger(traceback.format_exc())
            self.send_error(404)
            self.end_headers()
            return

        if request_path.startswith('/get_manual_json'):
            rc = 200
            ret_dic = utitls.manualJson()
            ret_dic['des_dict'] = []  #clear the des

            tmp_acc_mark_list = []
            for sub in utitls.configJson().get('subscribeList', []):
                tmp_mark = sub.get('mark')
                if tmp_mark:
                    tmp_acc_mark_list.append(tmp_mark)
            ret_dic['acc_mark_list'] = tmp_acc_mark_list
            rb = json.dumps(ret_dic)
        elif request_path.startswith('/questlist'):
            rc = 200
            rb = json.dumps(getQuestList_AddStarts())
        elif request_path.startswith('/live_restream?'):
            forwardLink_list = params.get('forwardLink', None)
            restreamRtmpLink_list = params.get('restreamRtmpLink', None)
            if forwardLink_list and restreamRtmpLink_list:
                tmp_forwardLink = forwardLink_list[0].strip()
                tmp_rtmpLink = restreamRtmpLink_list[0].strip()

                if 'rtmp://' in tmp_rtmpLink:
                    if utitls.checkIsSupportForwardLink(tmp_forwardLink):
                        isForwardLinkFormateOK = True
                    else:
                        isForwardLinkFormateOK = False

                    rc = 200
                    if isForwardLinkFormateOK:
                        if checkIfInQuest(tmp_rtmpLink) == False:
                            #try to restream
                            async_forwardStream(tmp_forwardLink, tmp_rtmpLink,
                                                False)
                            rb = json.dumps({
                                "code":
                                0,
                                "msg":
                                "请求成功。请等待大概30秒,网络不好时程序会自动重试30次。也可以查看任务状态看是否添加成功。\
                                            \nRequesting ForwardLink: {},\nRequesting RestreamRtmpLink: {}\n\n"
                                .format(tmp_forwardLink, tmp_rtmpLink)
                            })
                        else:
                            rb = json.dumps({
                                "code":
                                1,
                                "msg":
                                "当前推流已经在任务中. \nRequesting ForwardLink: {},\nRequesting RestreamRtmpLink: {}\n\n\n-----------------CurrentQuests:\n{}"
                                .format(tmp_forwardLink, tmp_rtmpLink,
                                        getQuestListStr())
                            })
                    else:
                        rb = json.dumps({
                            "code": -3,
                            "msg": "来源地址格式错误, 请查看上面支持的格式"
                        })
                elif tmp_rtmpLink.startswith('ACCMARK='):
                    params = parse_qs(tmp_rtmpLink)
                    acc_list = params.get('ACCMARK', None)
                    opt_code_list = params.get('OPTC', None)
                    is_send_dynamic_list = params.get('SEND_DYNAMIC', None)
                    dynamic_words_list = params.get('DYNAMIC_WORDS', None)
                    is_should_record_list = params.get('IS_SHOULD_RECORD',
                                                       None)
                    b_title_list = params.get('B_TITLE', None)

                    rc = 200
                    if acc_list and opt_code_list and is_send_dynamic_list and dynamic_words_list:
                        acc_mark = acc_list[0].strip()
                        opt_code = opt_code_list[0].strip()
                        is_send_dynamic = is_send_dynamic_list[0].strip()
                        dynamic_words = dynamic_words_list[0].strip()
                        is_should_record = is_should_record_list[0].strip()
                        b_title = None
                        if b_title_list:
                            b_title = b_title_list[0].strip()

                        tmp_is_acc_exist = False
                        for sub in utitls.configJson().get(
                                'subscribeList', []):
                            tmp_mark = sub.get('mark', "")
                            if tmp_mark == acc_mark:
                                if opt_code == sub.get('opt_code', ""):
                                    tmp_is_acc_exist = True
                                    sub['auto_send_dynamic'] = True if is_send_dynamic == '1' else False
                                    sub['dynamic_template'] = dynamic_words + "${roomUrl}"
                                    sub['is_should_record'] = True if is_should_record == '1' else False
                                    if b_title:
                                        sub['change_b_title'] = b_title
                                    Async_forwardToBilibili(
                                        sub,
                                        tmp_forwardLink,
                                        isSubscribeQuest=False)
                                break

                        if tmp_is_acc_exist:
                            rb = json.dumps({
                                "code":
                                0,
                                "msg":
                                "请求成功。请等待大概30秒,网络不好时程序会自动重试30次。也可以查看任务状态看是否添加成功。\
                                            \nRequesting ForwardLink: {},\nRequesting RestreamRtmpLink: {}\n\n"
                                .format(tmp_forwardLink, tmp_rtmpLink)
                            })
                        else:
                            rb = json.dumps({
                                "code":
                                -5,
                                "msg":
                                "当前账号不存在或者账号操作码错误:{}".format(acc_mark)
                            })

                else:
                    rc = 200
                    rb = json.dumps({
                        "code":
                        -4,
                        "msg":
                        "RTMPLink格式错误!!! bilibili的RTMPLink格式是两串合起来。\nEXAMPLE:rtmp://XXXXXX.acg.tv/live-js/?streamname=live_XXXXXXX&key=XXXXXXXXXX"
                    })
        elif request_path.startswith('/bilibili_opt?'):
            rc = 200
            acc_list = params.get('acc', None)
            opt_code_list = params.get('opt_code', None)
            dynamic_words_list = params.get('sendDynamic', None)
            b_title_list = params.get('changeTitle', None)
            refreshRTMP_list = params.get('refreshRTMP', None)
            killRTMP_list = params.get('killRTMP', None)
            if acc_list and opt_code_list:
                acc = acc_list[0]
                opt_code = opt_code_list[0]

                curSub = utitls.getSubWithKey('mark', acc)
                if curSub.get('opt_code') == opt_code:
                    if dynamic_words_list:
                        dynamic_words = dynamic_words_list[0]
                        b = getBilibiliProxy(curSub)
                        t_room_id = b.getLiveRoomId()
                        t_cur_blive_url = 'https://live.bilibili.com/' + t_room_id
                        b.send_dynamic("{}\n{}".format(dynamic_words,
                                                       t_cur_blive_url))
                    elif b_title_list:
                        b_title = b_title_list[0]
                        b = getBilibiliProxy(curSub)
                        t_room_id = b.getLiveRoomId()
                        b.updateRoomTitle(t_room_id, b_title)
                    elif refreshRTMP_list:
                        refreshRTMP = refreshRTMP_list[0]
                        if refreshRTMP == '1':
                            b = getBilibiliProxy(curSub)
                            t_room_id = b.getLiveRoomId()
                            b.startLive(t_room_id, '33')
                    elif killRTMP_list:
                        killRTMP = killRTMP_list[0]
                        if killRTMP == '1':
                            cur_quest = _getObjWithAccMark(acc)
                            if cur_quest:
                                updateQuestInfo('isDead', True,
                                                cur_quest.get('rtmpLink'))
                                utitls.kill_child_processes(
                                    cur_quest.get('pid', None))
                    rb = json.dumps({"code": 0, "msg": "操作成功"})
                else:
                    rb = json.dumps({
                        "code": -5,
                        "msg": "当前账号不存在或者账号操作码错误:{}".format(acc)
                    })
        elif request_path.startswith('/kill_quest?'):
            rc = 200
            tmp_rtmpLink_list = params.get('rtmpLink', None)
            if tmp_rtmpLink_list:
                tmp_rtmpLink = tmp_rtmpLink_list[0].strip()
                tmp_quest = _getObjWithRTMPLink(tmp_rtmpLink)
                if tmp_quest != None:
                    updateQuestInfo('isDead', True, tmp_rtmpLink)
                    utitls.kill_child_processes(tmp_quest.get('pid', None))
                    rb = json.dumps({"code": 0, "msg": "操作成功"})
                else:
                    rb = json.dumps({
                        "code":
                        -1,
                        "msg":
                        "查找不到对应的任务:{},操作失败!!".format(tmp_rtmpLink)
                    })
        elif request_path.startswith('/addRestreamSrc?'):
            rc = 200
            srcNote_list = params.get('srcNote', None)
            srcLink_list = params.get('srcLink', None)
            if srcNote_list and srcLink_list:
                tmp_srcNote = srcNote_list[0].strip()
                tmp_srcLink = srcLink_list[0].strip()
                utitls.addManualSrc(tmp_srcNote, tmp_srcLink)
            rb = json.dumps({"code": 0, "msg": "添加成功"})
        elif request_path.startswith('/addRtmpDes?'):
            rc = 200
            rtmpNote_list = params.get('rtmpNote', None)
            rtmpLink_list = params.get('rtmpLink', None)
            if rtmpNote_list and rtmpLink_list:
                tmp_rtmpNote = rtmpNote_list[0].strip()
                tmp_rtmpLink = rtmpLink_list[0].strip()
                utitls.addManualDes(tmp_rtmpNote, tmp_rtmpLink)
            rb = json.dumps({"code": 0, "msg": "添加成功"})
        elif request_path.startswith('/subscribe?'):
            hub_challenge_list = params.get('hub.challenge', None)
            if None != hub_challenge_list:
                rc = 202
                rb = hub_challenge_list[0]

#######
        if rb:
            rb = self.gzip_encode(rb.encode('utf-8'))
            sh['Content-length'] = len(rb)

        self.send_response(rc)
        for key in sh:
            self.send_header(key, sh[key])
        self.end_headers()

        if None != rb:
            try:
                self.wfile.write(rb)
            except Exception:
                print(traceback.format_exc())
Exemple #6
0
def _forwardStream_sync(forwardLink,
                        outputRTMP,
                        isSubscribeQuest,
                        subscribe_obj=None):
    tmp_quest = questInfo._getObjWithRTMPLink(outputRTMP)
    if tmp_quest:
        if tmp_quest.get('isRestart') == None:
            utitls.myLogger(
                "_forwardStream_sync ERROR: rtmp already in quest!!!!\n forwardLink:%s, \n rtmpLink:%s"
                % (forwardLink, outputRTMP))
            return
    else:
        questInfo.addQuest(forwardLink, outputRTMP, isSubscribeQuest)

    if outputRTMP.startswith('rtmp://'):
        is_stream_playable = False

        tmp_title = forwardLink  # default title is the forwardLink
        tmp_forwardLink = forwardLink
        if 'twitcasting.tv/' in tmp_forwardLink:
            #('https://www.', 'twitcasting.tv/', 're2_takatsuki/fwer/aeqwet')
            tmp_twitcasID = tmp_forwardLink.partition('twitcasting.tv/')[2]
            tmp_twitcasID = tmp_twitcasID.split('/')[0]
            # if using the streamlink, it should be start with hlsvariant://
            tmp_forwardLink = 'hlsvariant://twitcasting.tv/{}/metastream.m3u8/?video=1'.format(
                tmp_twitcasID)
            is_stream_playable = True
        else:
            m3u8Link, tmp_title, err, errcode = resolveStreamToM3u8(
                tmp_forwardLink)
            tmp_forwardLink = forwardLink  # use the orgin streamlink
            if errcode == 0:
                is_stream_playable = True
            else:
                utitls.myLogger(
                    "_forwardStream_sync ERROR: Unsupport forwardLink:%s" %
                    tmp_forwardLink)
                is_stream_playable = False

        if is_stream_playable == True:
            questInfo.updateQuestInfo('title', tmp_title, outputRTMP)
            if subscribe_obj:
                questInfo.updateQuestInfo('AccountMARK',
                                          subscribe_obj.get("mark", ""),
                                          outputRTMP)
                questInfo.updateQuestInfo(
                    'Live_URL', subscribe_obj.get("cur_blive_url", ""),
                    outputRTMP)
            tmp_retryTime = 0
            tmp_cmdStartTime = time.time()
            while tmp_retryTime <= 6:  # must be <=
                # try to restream
                out, err, errcode = _forwardStreamCMD_sync(
                    tmp_title, subscribe_obj, tmp_forwardLink, outputRTMP)

                out = out.decode('utf-8') if isinstance(
                    out, (bytes, bytearray)) else out
                if ('[cli][info] Stream ended' in out) and (
                        time.time() - tmp_cmdStartTime > 180
                ):  # this will cause the retry out, it good as so far.
                    utitls.myLogger(
                        "_forwardStreamCMD_sync LOG: Stream ended=======<")
                    break

                isQuestDead = questInfo._getObjWithRTMPLink(outputRTMP).get(
                    'isDead', False)
                if errcode == -9 or isQuestDead or isQuestDead == 'True':
                    utitls.myLogger(
                        "_forwardStreamCMD_sync LOG: Kill Current procces by rtmp:%s"
                        % outputRTMP)
                    break
                # maybe can ignore the error if ran after 2min?
                if time.time() - tmp_cmdStartTime < 120:
                    tmp_retryTime += 1  # make it can exit
                else:
                    tmp_retryTime = 0  # let every Connect success reset the retrytime
                time.sleep(10)  # one m3u8 can hold 20 secounds or less
                tmp_cmdStartTime = time.time()  #import should not miss it.
                utitls.myLogger(
                    '_forwardStream_sync LOG: CURRENT RETRY TIME:%s' %
                    tmp_retryTime)
                utitls.myLogger(
                    "_forwardStream_sync LOG RETRYING___________THIS:\ninputM3U8:%s, \noutputRTMP:%s"
                    % (forwardLink, outputRTMP))
    else:
        utitls.myLogger("_forwardStream_sync ERROR: Invalid outputRTMP:%s" %
                        outputRTMP)

    questInfo.removeQuest(outputRTMP)