Exemplo n.º 1
0
def checkRTMPAuthIP(requestData):
    authorized = False
    requestIP = "0.0.0.0"
    if requestData.environ.get('HTTP_X_FORWARDED_FOR') is None:
        requestIP = requestData.environ['REMOTE_ADDR']
    else:
        requestIP = requestData.environ['HTTP_X_FORWARDED_FOR']

    authorizedRTMPServers = settings.rtmpServer.query.all()

    receivedIP = requestIP
    ipList = requestIP.split(',')
    confirmedIP = ""
    for ip in ipList:
        parsedip = ip.strip()
        for server in authorizedRTMPServers:
            if authorized is False:
                if server.active is True:
                    resolveResults = socket.getaddrinfo(server.address, 0)
                    for resolved in resolveResults:
                        if parsedip == resolved[4][0]:
                            authorized = True
                            confirmedIP = resolved[4][0]

    if authorized is False:
        confirmedIP = receivedIP
        system.newLog(1, "Unauthorized RTMP Server - " + confirmedIP)

    return (authorized, confirmedIP)
Exemplo n.º 2
0
def deleteClip(clipID):
    clipQuery = RecordedVideo.Clips.query.filter_by(id=int(clipID)).first()
    videos_root = globalvars.videoRoot + 'videos/'

    if current_user.id == clipQuery.recordedVideo.owningUser and clipQuery is not None:
        videoPath = videos_root + clipQuery.videoLocation
        thumbnailPath = videos_root + clipQuery.thumbnailLocation
        gifPath = videos_root + clipQuery.gifLocation

        if thumbnailPath != videos_root:
            if os.path.exists(thumbnailPath) and (thumbnailPath is not None
                                                  or thumbnailPath != ""):
                os.remove(thumbnailPath)
        if gifPath != videos_root:
            if os.path.exists(gifPath) and (clipQuery.gifLocation is not None
                                            or gifPath != ""):
                os.remove(gifPath)
        if videoPath != videos_root:
            if os.path.exists(videoPath) and (clipQuery.videoLocation
                                              is not None or videoPath != ""):
                os.remove(videoPath)

        db.session.delete(clipQuery)

        db.session.commit()
        system.newLog(6, "Clip Deleted - ID #" + str(clipID))
        return True
    else:
        return False
def page_not_found(e):
    sysSettings = settings.settings.query.first()
    system.newLog(0, "500 Error - " + str(request.url))
    return render_template(themes.checkOverride('500.html'),
                           sysSetting=sysSettings,
                           previous=request.referrer,
                           error=e), 500
def testWebhook(webhookType, webhookID, **kwargs):
    system.newLog(
        8,
        "Testing Webhook for ID #" + str(webhookID) + ", Type: " + webhookType)
    webhookQuery = None
    if webhookType == "channel":
        webhookQuery = webhook.webhook.query.filter_by(id=webhookID).first()
    elif webhookType == "global":
        webhookQuery = webhook.globalWebhook.query.filter_by(
            id=webhookID).first()
    if webhookQuery is not None:
        url = webhookQuery.endpointURL
        payload = processWebhookVariables(webhookQuery.requestPayload,
                                          **kwargs)
        header = json.loads(webhookQuery.requestHeader)
        requestType = webhookQuery.requestType
        try:
            if requestType == 0:
                r = requests.post(url, headers=header, data=payload)
            elif requestType == 1:
                r = requests.get(url, headers=header, data=payload)
            elif requestType == 2:
                r = requests.put(url, headers=header, data=payload)
            elif requestType == 3:
                r = requests.delete(url, headers=header, data=payload)
        except Exception as e:
            print("Webhook Error-" + str(e))
        system.newLog(
            8, "Completed Webhook Test for ID #" + str(webhookQuery.id) +
            " - Destination:" + str(url))
Exemplo n.º 5
0
def deleteVideo(videoID):
    recordedVid = RecordedVideo.RecordedVideo.query.filter_by(
        id=videoID).first()

    if current_user.id == recordedVid.owningUser and recordedVid.videoLocation is not None:
        videos_root = globalvars.videoRoot + 'videos/'
        filePath = videos_root + recordedVid.videoLocation
        thumbnailPath = videos_root + recordedVid.videoLocation[:-4] + ".png"
        gifPath = videos_root + recordedVid.videoLocation[:-4] + ".gif"

        if filePath != videos_root:
            if os.path.exists(filePath) and (
                    recordedVid.videoLocation is not None
                    or recordedVid.videoLocation != ""):
                os.remove(filePath)
                if os.path.exists(thumbnailPath):
                    os.remove(thumbnailPath)
                if os.path.exists(gifPath):
                    os.remove(gifPath)

        # Delete Clips Attached to Video
        for clip in recordedVid.clips:
            thumbnailPath = videos_root + clip.thumbnailLocation

            if thumbnailPath != videos_root:
                if os.path.exists(thumbnailPath) and (
                        clip.thumbnailLocation is not None
                        or clip.thumbnailLocation != ""):
                    os.remove(thumbnailPath)
            db.session.delete(clip)

        # Delete Upvotes Attached to Video
        upvoteQuery = upvotes.videoUpvotes.query.filter_by(
            videoID=recordedVid.id).all()

        for vote in upvoteQuery:
            db.session.delete(vote)

        # Delete Comments Attached to Video
        commentQuery = comments.videoComments.query.filter_by(
            videoID=recordedVid.id).all()

        for comment in commentQuery:
            db.session.delete(comment)

        # Delete Views Attached to Video
        viewQuery = views.views.query.filter_by(viewType=1,
                                                itemID=recordedVid.id).all()

        for view in viewQuery:
            db.session.delete(view)

        db.session.delete(recordedVid)

        db.session.commit()
        system.newLog(4, "Video Deleted - ID #" + str(videoID))
        return True
    return False
Exemplo n.º 6
0
def upload():
    videos_root = globalvars.videoRoot + 'videos/'

    sysSettings = settings.settings.query.first()
    if not sysSettings.allowUploads:
        db.session.close()
        return "Video Uploads Disabled", 501
    if request.files['file']:

        if not os.path.exists(videos_root + 'temp'):
            os.makedirs(videos_root + 'temp')

        file = request.files['file']

        if request.form['ospfilename'] != "":
            ospfilename = request.form['ospfilename']
        else:
            return "Ooops.", 500

        if system.videoupload_allowedExt(
                file.filename, current_app.config['VIDEO_UPLOAD_EXTENSIONS']):
            save_path = os.path.join(
                current_app.config['VIDEO_UPLOAD_TEMPFOLDER'],
                secure_filename(ospfilename))
            current_chunk = int(request.form['dzchunkindex'])
        else:
            system.newLog(
                4, "File Upload Failed - File Type not Allowed - Username:"******"Filetype not allowed", 403

        if current_chunk > 4500:
            open(save_path, 'w').close()
            return "File is getting too large.", 403

        if os.path.exists(save_path) and current_chunk == 0:
            open(save_path, 'w').close()

        try:
            with open(save_path, 'ab') as f:
                f.seek(int(request.form['dzchunkbyteoffset']))
                f.write(file.stream.read())
        except OSError:
            system.newLog(
                4, "File Upload Failed - OSError - Username:"******"Ooops.", 500

        total_chunks = int(request.form['dztotalchunkcount'])

        if current_chunk + 1 == total_chunks:
            if os.path.getsize(save_path) != int(
                    request.form['dztotalfilesize']):
                return "Size mismatch", 500

        return "success", 200
    else:
        return "I don't understand", 501
Exemplo n.º 7
0
def rtmp_stage2_user_auth_check(channelLoc, ipaddress):
    sysSettings = settings.settings.query.first()

    currentTime = datetime.datetime.utcnow()

    requestedChannel = Channel.Channel.query.filter_by(channelLoc=channelLoc).first()

    if requestedChannel is not None:
        authedStream = Stream.Stream.query.filter_by(streamKey=requestedChannel.streamKey).first()

        if authedStream is not None:

            authedStream.currentViewers = int(xmpp.getChannelCounts(requestedChannel.channelLoc))
            authedStream.totalViewers = int(xmpp.getChannelCounts(requestedChannel.channelLoc))
            db.session.commit()

            if requestedChannel.imageLocation is None:
                channelImage = (sysSettings.siteProtocol + sysSettings.siteAddress + "/static/img/video-placeholder.jpg")
            else:
                channelImage = (sysSettings.siteProtocol + sysSettings.siteAddress + "/images/" + requestedChannel.imageLocation)

            webhookFunc.runWebhook(requestedChannel.id, 0, channelname=requestedChannel.channelName, channelurl=(sysSettings.siteProtocol + sysSettings.siteAddress + "/channel/" + str(requestedChannel.id)), channeltopic=requestedChannel.topic,
                       channelimage=channelImage, streamer=templateFilters.get_userName(requestedChannel.owningUser), channeldescription=str(requestedChannel.description),
                       streamname=authedStream.streamName, streamurl=(sysSettings.siteProtocol + sysSettings.siteAddress + "/view/" + requestedChannel.channelLoc), streamtopic=templateFilters.get_topicName(authedStream.topic),
                       streamimage=(sysSettings.siteProtocol + sysSettings.siteAddress + "/stream-thumb/" + requestedChannel.channelLoc + ".png"))

            subscriptionQuery = subscriptions.channelSubs.query.filter_by(channelID=requestedChannel.id).all()
            for sub in subscriptionQuery:
                # Create Notification for Channel Subs
                newNotification = notifications.userNotification(templateFilters.get_userName(requestedChannel.owningUser) + " has started a live stream in " + requestedChannel.channelName, "/view/" + str(requestedChannel.channelLoc),
                                                                 "/images/" + str(requestedChannel.owner.pictureLocation), sub.userID)
                db.session.add(newNotification)
            db.session.commit()

            try:
                subsFunc.processSubscriptions(requestedChannel.id,
                                 sysSettings.siteName + " - " + requestedChannel.channelName + " has started a stream",
                                 "<html><body><img src='" + sysSettings.siteProtocol + sysSettings.siteAddress + sysSettings.systemLogo + "'><p>Channel " + requestedChannel.channelName +
                                 " has started a new video stream.</p><p>Click this link to watch<br><a href='" + sysSettings.siteProtocol + sysSettings.siteAddress + "/view/" + str(requestedChannel.channelLoc)
                                 + "'>" + requestedChannel.channelName + "</a></p>")
            except:
                system.newLog(0, "Subscriptions Failed due to possible misconfiguration")

            returnMessage = {'time': str(currentTime), 'request': 'Stage2', 'success': True, 'channelLoc': requestedChannel.channelLoc, 'ipAddress': str(ipaddress), 'message': 'Success - Stream Authenticated & Initialized'}
            db.session.close()
            return returnMessage
        else:
            returnMessage = {'time': str(currentTime), 'request': 'Stage2', 'success': False, 'channelLoc': requestedChannel.channelLoc, 'ipAddress': str(ipaddress), 'message': 'Failed - No Matching Stage 1 Connection'}
            db.session.close()
            return returnMessage
    else:
        returnMessage = {'time': str(currentTime), 'request': 'Stage2', 'success': False, 'channelLoc': channelLoc, 'ipAddress': str(ipaddress), 'message': 'Failed - Passed Stage 1 Channel ID Does Not Match Any Known Channels'}
        db.session.close()
        return returnMessage
Exemplo n.º 8
0
def deleteChannelAdmin(message):
    channelID = int(message['channelID'])
    channelQuery = Channel.Channel.query.filter_by(id=channelID).first()
    if channelQuery is not None:
        if current_user.has_role(
                'Admin') or channelQuery.owningUser == current_user.id:
            for vid in channelQuery.recordedVideo:
                for upvote in vid.upvotes:
                    db.session.delete(upvote)
                vidComments = vid.comments
                for comment in vidComments:
                    db.session.delete(comment)
                vidViews = views.views.query.filter_by(viewType=1,
                                                       itemID=vid.id)
                for view in vidViews:
                    db.session.delete(view)
                for clip in vid.clips:
                    db.session.delete(clip)

                db.session.delete(vid)

            for upvote in channelQuery.upvotes:
                db.session.delete(upvote)
            for inviteCode in channelQuery.inviteCodes:
                db.session.delete(inviteCode)
            for viewer in channelQuery.invitedViewers:
                db.session.delete(viewer)
            for sub in channelQuery.subscriptions:
                db.session.delete(sub)
            for hook in channelQuery.webhooks:
                db.session.delete(hook)
            for sticker in channelQuery.chatStickers:
                db.session.delete(sticker)

            stickerFolder = '/var/www/images/stickers/' + channelQuery.channelLoc + '/'
            shutil.rmtree(stickerFolder, ignore_errors=True)

            filePath = globalvars.videoRoot + channelQuery.channelLoc

            if filePath != globalvars.videoRoot:
                shutil.rmtree(filePath, ignore_errors=True)

            from app import ejabberd
            sysSettings = settings.settings.query.first()
            ejabberd.destroy_room(channelQuery.channelLoc,
                                  'conference.' + sysSettings.siteAddress)

            system.newLog(
                1, "User " + current_user.username + " deleted Channel " +
                str(channelQuery.id))
            db.session.delete(channelQuery)
            db.session.commit()
    db.session.close()
    return 'OK'
Exemplo n.º 9
0
def disable_2fa(msg):
    if current_user.has_role('Admin'):
        userID = int(msg['userID'])
        userQuery = Sec.User.query.filter_by(id=userID).first()
        if userQuery is not None:
            userQuery.tf_primary_method = None
            userQuery.tf_totp_secret = None
            db.session.commit()
            system.newLog(
                1, "User " + current_user.username + " disabled 2FA for " +
                str(userQuery.username))
    db.session.close()
    return 'OK'
Exemplo n.º 10
0
def processSubscriptions(channelID, subject, message):
    subscriptionQuery = subscriptions.channelSubs.query.filter_by(channelID=channelID).all()
    if subscriptionQuery:
        system.newLog(2, "Sending Subscription Emails for Channel ID: " + str(channelID))

        subCount = 0
        for sub in subscriptionQuery:
            userQuery = Sec.User.query.filter_by(id=int(sub.userID)).first()
            if userQuery is not None:
                result = runSubscription(subject, userQuery.email, message)
                subCount = subCount + 1
        system.newLog(2, "Processed " + str(subCount) + " out of " + str(len(subscriptionQuery)) + " Email Subscriptions for Channel ID: " + str(channelID) )
    return True
Exemplo n.º 11
0
def changeVideoMetadata(videoID, newVideoName, newVideoTopic, description,
                        allowComments):

    recordedVidQuery = RecordedVideo.RecordedVideo.query.filter_by(
        id=videoID, owningUser=current_user.id).first()
    sysSettings = settings.settings.query.first()

    if recordedVidQuery is not None:

        recordedVidQuery.channelName = system.strip_html(newVideoName)
        recordedVidQuery.topic = newVideoTopic
        recordedVidQuery.description = system.strip_html(description)
        recordedVidQuery.allowComments = allowComments

        if recordedVidQuery.channel.imageLocation is None:
            channelImage = (sysSettings.siteProtocol +
                            sysSettings.siteAddress +
                            "/static/img/video-placeholder.jpg")
        else:
            channelImage = (sysSettings.siteProtocol +
                            sysSettings.siteAddress + "/images/" +
                            recordedVidQuery.channel.imageLocation)

        webhookFunc.runWebhook(
            recordedVidQuery.channel.id,
            9,
            channelname=recordedVidQuery.channel.channelName,
            channelurl=(sysSettings.siteProtocol + sysSettings.siteAddress +
                        "/channel/" + str(recordedVidQuery.channel.id)),
            channeltopic=templateFilters.get_topicName(
                recordedVidQuery.channel.topic),
            channelimage=channelImage,
            streamer=templateFilters.get_userName(
                recordedVidQuery.channel.owningUser),
            channeldescription=str(recordedVidQuery.channel.description),
            videoname=recordedVidQuery.channelName,
            videodate=recordedVidQuery.videoDate,
            videodescription=recordedVidQuery.description,
            videotopic=templateFilters.get_topicName(recordedVidQuery.topic),
            videourl=(sysSettings.siteProtocol + sysSettings.siteAddress +
                      '/videos/' + recordedVidQuery.videoLocation),
            videothumbnail=(sysSettings.siteProtocol +
                            sysSettings.siteAddress + '/videos/' +
                            recordedVidQuery.thumbnailLocation))
        db.session.commit()
        system.newLog(
            4, "Video Metadata Changed - ID # " + str(recordedVidQuery.id))
        return True
    return False
Exemplo n.º 12
0
def changeClipMetadata(clipID, name, description):
    # TODO Add Webhook for Clip Metadata Change

    clipQuery = RecordedVideo.Clips.query.filter_by(id=int(clipID)).first()

    if clipQuery is not None:
        if clipQuery.recordedVideo.owningUser == current_user.id:

            clipQuery.clipName = system.strip_html(name)
            clipQuery.description = system.strip_html(description)

            db.session.commit()
            system.newLog(6, "Clip Metadata Changed - ID #" + str(clipID))
            return True
    return False
Exemplo n.º 13
0
def user_registered_sighandler(app, user, confirm_token):
    defaultRoleQuery = Sec.Role.query.filter_by(default=True)
    for role in defaultRoleQuery:
        user_datastore.add_role_to_user(user, role.name)
    user.authType = 0
    user.xmppToken = str(os.urandom(32).hex())
    user.uuid = str(uuid.uuid4())
    webhookFunc.runWebhook("ZZZ", 20, user=user.username)
    system.newLog(1,
                  "A New User has Registered - Username:"******"An email has been sent to the email provided. Please check your email and verify your account to activate."
        )
    db.session.commit()
Exemplo n.º 14
0
def runWebhook(channelID, triggerType, **kwargs):
    webhookQueue = []
    if channelID != "ZZZ":

        webhookQuery = webhook.webhook.query.filter_by(
            channelID=channelID, requestTrigger=triggerType).all()
        webhookQueue.append(webhookQuery)

    globalWebhookQuery = webhook.globalWebhook.query.filter_by(
        requestTrigger=triggerType).all()
    webhookQueue.append(globalWebhookQuery)

    for queue in webhookQueue:
        if queue:
            for hook in queue:
                url = hook.endpointURL
                payload = processWebhookVariables(hook.requestPayload,
                                                  **kwargs)
                header = json.loads(hook.requestHeader)
                requestType = hook.requestType
                try:
                    if requestType == 0:
                        r = requests.post(url, headers=header, data=payload)
                    elif requestType == 1:
                        r = requests.get(url, headers=header, data=payload)
                    elif requestType == 2:
                        r = requests.put(url, headers=header, data=payload)
                    elif requestType == 3:
                        r = requests.delete(url, headers=header, data=payload)
                except:
                    pass
                system.newLog(
                    8, "Processing Webhook for ID #" + str(hook.id) +
                    " - Destination:" + str(url))
    db.session.commit()
    db.session.close()
    return True
Exemplo n.º 15
0
def upload_vid():
    sysSettings = settings.settings.query.first()
    if not sysSettings.allowUploads:
        db.session.close()
        flash("Video Upload Disabled", "error")
        return redirect(url_for('root.main_page'))

    currentTime = datetime.datetime.now()

    channel = int(request.form['uploadToChannelID'])
    topic = int(request.form['uploadTopic'])
    thumbnailFilename = request.form['thumbnailFilename']
    videoFilename= request.form['videoFilename']

    ChannelQuery = Channel.Channel.query.filter_by(id=channel).first()

    if ChannelQuery.owningUser != current_user.id:
        flash('You are not allowed to upload to this channel!')
        db.session.close()
        return redirect(url_for('root.main_page'))

    videoPublishState = ChannelQuery.autoPublish

    newVideo = RecordedVideo.RecordedVideo(current_user.id, channel, ChannelQuery.channelName, ChannelQuery.topic, 0, "", currentTime, ChannelQuery.allowComments, videoPublishState)

    videoLoc = ChannelQuery.channelLoc + "/" + videoFilename.rsplit(".", 1)[0] + '_' + datetime.datetime.strftime(currentTime, '%Y%m%d_%H%M%S') + ".mp4"
    videos_root = current_app.config['WEB_ROOT'] + 'videos/'
    videoPath = videos_root + videoLoc

    if videoFilename != "":
        if not os.path.isdir(videos_root + ChannelQuery.channelLoc):
            try:
                os.mkdir(videos_root + ChannelQuery.channelLoc)
            except OSError:
                system.newLog(4, "File Upload Failed - OSError - Unable to Create Directory - Username:"******"Error uploading video - Unable to create directory","error")
                db.session.close()
                return redirect(url_for("root.main_page"))
        shutil.move(current_app.config['VIDEO_UPLOAD_TEMPFOLDER'] + '/' + videoFilename, videoPath)
    else:
        db.session.close()
        flash("Error uploading video - Couldn't move video file")
        return redirect(url_for('root.main_page'))

    newVideo.videoLocation = videoLoc

    if thumbnailFilename != "":
        thumbnailLoc = ChannelQuery.channelLoc + '/' + thumbnailFilename.rsplit(".", 1)[0] + '_' +  datetime.datetime.strftime(currentTime, '%Y%m%d_%H%M%S') + videoFilename.rsplit(".", 1)[-1]

        thumbnailPath = videos_root + thumbnailLoc
        try:
            shutil.move(current_app.config['VIDEO_UPLOAD_TEMPFOLDER'] + '/' + thumbnailFilename, thumbnailPath)
        except:
            flash("Thumbnail Upload Failed Due to Missing File","error")
        newVideo.thumbnailLocation = thumbnailLoc
    else:
        thumbnailLoc = ChannelQuery.channelLoc + '/' + videoFilename.rsplit(".", 1)[0] + '_' +  datetime.datetime.strftime(currentTime, '%Y%m%d_%H%M%S') + ".png"

        subprocess.call(['ffmpeg', '-ss', '00:00:01', '-i', videos_root + videoLoc, '-s', '384x216', '-vframes', '1', videos_root + thumbnailLoc])
        newVideo.thumbnailLocation = thumbnailLoc

    newGifFullThumbnailLocation = ChannelQuery.channelLoc + '/' + videoFilename.rsplit(".", 1)[0] + '_' + datetime.datetime.strftime(currentTime, '%Y%m%d_%H%M%S') + ".gif"
    gifresult = subprocess.call(['ffmpeg', '-ss', '00:00:01', '-t', '3', '-i', videos_root + videoLoc, '-filter_complex', '[0:v] fps=30,scale=w=384:h=-1,split [a][b];[a] palettegen=stats_mode=single [p];[b][p] paletteuse=new=1', '-y', videos_root + newGifFullThumbnailLocation])
    newVideo.gifLocation = newGifFullThumbnailLocation

    if request.form['videoTitle'] != "":
        newVideo.channelName = system.strip_html(request.form['videoTitle'])
    else:
        newVideo.channelName = currentTime

    newVideo.topic = topic

    newVideo.description = system.strip_html(request.form['videoDescription'])

    if os.path.isfile(videoPath):
        newVideo.pending = False
        db.session.add(newVideo)
        db.session.commit()

        if ChannelQuery.autoPublish is True:
            newVideo.published = True
        else:
            newVideo.published = False
        db.session.commit()

        if ChannelQuery.imageLocation is None:
            channelImage = (sysSettings.siteProtocol + sysSettings.siteAddress + "/static/img/video-placeholder.jpg")
        else:
            channelImage = (sysSettings.siteProtocol + sysSettings.siteAddress + "/images/" + ChannelQuery.imageLocation)
        system.newLog(4, "File Upload Successful - Username:"******"/channel/" + str(ChannelQuery.id)),
                       channeltopic=templateFilters.get_topicName(ChannelQuery.topic),
                       channelimage=channelImage, streamer=templateFilters.get_userName(ChannelQuery.owningUser),
                       channeldescription=str(ChannelQuery.description), videoname=newVideo.channelName,
                       videodate=newVideo.videoDate, videodescription=newVideo.description,
                       videotopic=templateFilters.get_topicName(newVideo.topic),
                       videourl=(sysSettings.siteProtocol + sysSettings.siteAddress + '/play/' + str(newVideo.id)),
                       videothumbnail=(sysSettings.siteProtocol + sysSettings.siteAddress + '/videos/' + newVideo.thumbnailLocation))

            subscriptionQuery = subscriptions.channelSubs.query.filter_by(channelID=ChannelQuery.id).all()
            for sub in subscriptionQuery:
                # Create Notification for Channel Subs
                newNotification = notifications.userNotification(templateFilters.get_userName(ChannelQuery.owningUser) + " has posted a new video to " + ChannelQuery.channelName + " titled " + newVideo.channelName, '/play/' + str(newVideo.id),
                                                                 "/images/" + ChannelQuery.owner.pictureLocation, sub.userID)
                db.session.add(newNotification)
            db.session.commit()

            try:
                subsFunc.processSubscriptions(ChannelQuery.id,
                                 sysSettings.siteName + " - " + ChannelQuery.channelName + " has posted a new video",
                                 "<html><body><img src='" + sysSettings.siteProtocol + sysSettings.siteAddress + sysSettings.systemLogo + "'><p>Channel " + ChannelQuery.channelName + " has posted a new video titled <u>" + newVideo.channelName +
                                 "</u> to the channel.</p><p>Click this link to watch<br><a href='" + sysSettings.siteProtocol + sysSettings.siteAddress + "/play/" + str(newVideo.id) + "'>" + newVideo.channelName + "</a></p>")
            except:
                system.newLog(0, "Subscriptions Failed due to possible misconfiguration")

    videoID = newVideo.id
    db.session.commit()
    db.session.close()
    flash("Video upload complete")
    return redirect(url_for('play.view_vid_page', videoID=videoID))
Exemplo n.º 16
0
def user_auth_check():
    sysSettings = settings.settings.query.first()

    key = request.form['name']
    ipaddress = request.form['addr']

    requestedChannel = Channel.Channel.query.filter_by(channelLoc=key).first()

    if requestedChannel is not None:
        authedStream = Stream.Stream.query.filter_by(
            streamKey=requestedChannel.streamKey).first()

        if authedStream is not None:
            returnMessage = {
                'time': str(datetime.datetime.now()),
                'status': 'Successful Channel Auth',
                'key': str(requestedChannel.streamKey),
                'channelName': str(requestedChannel.channelName),
                'ipAddress': str(ipaddress)
            }
            print(returnMessage)

            if requestedChannel.imageLocation is None:
                channelImage = (sysSettings.siteProtocol +
                                sysSettings.siteAddress +
                                "/static/img/video-placeholder.jpg")
            else:
                channelImage = (sysSettings.siteProtocol +
                                sysSettings.siteAddress + "/images/" +
                                requestedChannel.imageLocation)

            webhookFunc.runWebhook(
                requestedChannel.id,
                0,
                channelname=requestedChannel.channelName,
                channelurl=(sysSettings.siteProtocol +
                            sysSettings.siteAddress + "/channel/" +
                            str(requestedChannel.id)),
                channeltopic=requestedChannel.topic,
                channelimage=channelImage,
                streamer=templateFilters.get_userName(
                    requestedChannel.owningUser),
                channeldescription=str(requestedChannel.description),
                streamname=authedStream.streamName,
                streamurl=(sysSettings.siteProtocol + sysSettings.siteAddress +
                           "/view/" + requestedChannel.channelLoc),
                streamtopic=templateFilters.get_topicName(authedStream.topic),
                streamimage=(sysSettings.siteProtocol +
                             sysSettings.siteAddress + "/stream-thumb/" +
                             requestedChannel.channelLoc + ".png"))

            subscriptionQuery = subscriptions.channelSubs.query.filter_by(
                channelID=requestedChannel.id).all()
            for sub in subscriptionQuery:
                # Create Notification for Channel Subs
                newNotification = notifications.userNotification(
                    templateFilters.get_userName(requestedChannel.owningUser) +
                    " has started a live stream in " +
                    requestedChannel.channelName,
                    "/view/" + str(requestedChannel.channelLoc),
                    "/images/" + str(requestedChannel.owner.pictureLocation),
                    sub.userID)
                db.session.add(newNotification)
            db.session.commit()

            try:
                subsFunc.processSubscriptions(
                    requestedChannel.id, sysSettings.siteName + " - " +
                    requestedChannel.channelName + " has started a stream",
                    "<html><body><img src='" + sysSettings.siteProtocol +
                    sysSettings.siteAddress + sysSettings.systemLogo +
                    "'><p>Channel " + requestedChannel.channelName +
                    " has started a new video stream.</p><p>Click this link to watch<br><a href='"
                    + sysSettings.siteProtocol + sysSettings.siteAddress +
                    "/view/" + str(requestedChannel.channelLoc) + "'>" +
                    requestedChannel.channelName + "</a></p>")
            except:
                system.newLog(
                    0, "Subscriptions Failed due to possible misconfiguration")

            inputLocation = "rtmp://" + coreNginxRTMPAddress + ":1935/live/" + requestedChannel.channelLoc

            # Begin RTMP Restream Function
            if requestedChannel.restreamDestinations != []:
                globalvars.restreamSubprocesses[
                    requestedChannel.channelLoc] = []
                for rtmpRestream in requestedChannel.restreamDestinations:
                    if rtmpRestream.enabled == True:
                        p = subprocess.Popen([
                            "ffmpeg", "-i", inputLocation, "-c", "copy", "-f",
                            "flv", rtmpRestream.url, "-c:v", "libx264",
                            "-maxrate",
                            str(sysSettings.restreamMaxBitrate) + "k",
                            "-bufsize", "6000k", "-c:a", "aac", "-b:a", "160k",
                            "-ac", "2"
                        ],
                                             stdout=subprocess.DEVNULL,
                                             stderr=subprocess.DEVNULL)
                        globalvars.restreamSubprocesses[
                            requestedChannel.channelLoc].append(p)

            # Start OSP Edge Nodes
            ospEdgeNodeQuery = settings.edgeStreamer.query.filter_by(
                active=True).all()
            if ospEdgeNodeQuery is not []:
                globalvars.edgeRestreamSubprocesses[
                    requestedChannel.channelLoc] = []

                for node in ospEdgeNodeQuery:
                    if node.address != sysSettings.siteAddress:
                        subprocessConstructor = [
                            "ffmpeg", "-i", inputLocation, "-c", "copy"
                        ]
                        subprocessConstructor.append("-f")
                        subprocessConstructor.append("flv")
                        if sysSettings.adaptiveStreaming:
                            subprocessConstructor.append(
                                "rtmp://" + node.address +
                                "/stream-data-adapt/" +
                                requestedChannel.channelLoc)
                        else:
                            subprocessConstructor.append(
                                "rtmp://" + node.address + "/stream-data/" +
                                requestedChannel.channelLoc)

                        p = subprocess.Popen(subprocessConstructor,
                                             stdout=subprocess.DEVNULL,
                                             stderr=subprocess.DEVNULL)
                        globalvars.edgeRestreamSubprocesses[
                            requestedChannel.channelLoc].append(p)

            db.session.close()
            return 'OK'
        else:
            returnMessage = {
                'time': str(datetime.datetime.now()),
                'status': 'Failed Channel Auth. No Authorized Stream Key',
                'channelName': str(key),
                'ipAddress': str(ipaddress)
            }
            print(returnMessage)
            db.session.close()
            return abort(400)
    else:
        returnMessage = {
            'time': str(datetime.datetime.now()),
            'status':
            'Failed Channel Auth. Channel Loc does not match Channel',
            'channelName': str(key),
            'ipAddress': str(ipaddress)
        }
        print(returnMessage)
        db.session.close()
        return abort(400)
Exemplo n.º 17
0
def createClip(videoID, clipStart, clipStop, clipName, clipDescription):
    settingsQuery = settings.settings.query.first()

    # TODO Add Webhook for Clip Creation
    recordedVidQuery = RecordedVideo.RecordedVideo.query.filter_by(
        id=int(videoID), owningUser=current_user.id).first()

    if recordedVidQuery is not None:

        clipLength = clipStop - clipStart
        if settingsQuery.maxClipLength < 301:
            if clipLength > settingsQuery.maxClipLength:
                return False, None

        if clipStop > clipStart:
            videos_root = globalvars.videoRoot + 'videos/'

            # Generate Clip Object
            newClip = RecordedVideo.Clips(recordedVidQuery.id, None, clipStart,
                                          clipStop, clipName, clipDescription)
            newClip.published = False
            db.session.add(newClip)
            db.session.commit()

            newClipQuery = RecordedVideo.Clips.query.filter_by(
                id=newClip.id).first()

            videoLocation = videos_root + recordedVidQuery.videoLocation

            # Establish Locations for Clips and Thumbnails
            clipVideoLocation = recordedVidQuery.channel.channelLoc + '/clips/' + 'clip-' + str(
                newClipQuery.id) + ".mp4"
            clipThumbNailLocation = recordedVidQuery.channel.channelLoc + '/clips/' + 'clip-' + str(
                newClipQuery.id) + ".png"
            clipGifLocation = recordedVidQuery.channel.channelLoc + '/clips/' + 'clip-' + str(
                newClipQuery.id) + ".gif"

            # Set Clip Object Values for Locations
            newClipQuery.videoLocation = clipVideoLocation
            newClipQuery.thumbnailLocation = clipThumbNailLocation
            newClipQuery.gifLocation = clipGifLocation

            # Set Full Path for Locations to be handled by FFMPEG
            fullvideoLocation = videos_root + clipVideoLocation
            fullthumbnailLocation = videos_root + clipThumbNailLocation
            fullgifLocation = videos_root + clipGifLocation

            # Create Clip Directory if doesn't exist
            if not os.path.isdir(videos_root +
                                 recordedVidQuery.channel.channelLoc +
                                 '/clips'):
                os.mkdir(videos_root + recordedVidQuery.channel.channelLoc +
                         '/clips')

            # FFMPEG Subprocess to Clip Video and generate Thumbnails
            clipVideo = subprocess.call([
                'ffmpeg', '-ss',
                str(clipStart), '-i', videoLocation, '-t',
                str(newClipQuery.length), fullvideoLocation
            ])
            processResult = subprocess.call([
                'ffmpeg', '-ss',
                str(clipStart), '-i', videoLocation, '-s', '384x216',
                '-vframes', '1', fullthumbnailLocation
            ])
            gifprocessResult = subprocess.call([
                'ffmpeg', '-ss',
                str(clipStart), '-t', '3', '-i', videoLocation,
                '-filter_complex',
                '[0:v] fps=30,scale=w=384:h=-1,split [a][b];[a] palettegen=stats_mode=single [p];[b][p] paletteuse=new=1',
                '-y', fullgifLocation
            ])

            redirectID = newClipQuery.id
            newClipQuery.published = True
            system.newLog(6, "New Clip Created - ID #" + str(redirectID))

            subscriptionQuery = subscriptions.channelSubs.query.filter_by(
                channelID=recordedVidQuery.channel.id).all()
            for sub in subscriptionQuery:
                # Create Notification for Channel Subs
                newNotification = notifications.userNotification(
                    templateFilters.get_userName(recordedVidQuery.owningUser) +
                    " has posted a new clip to " +
                    recordedVidQuery.channel.channelName + " titled " +
                    clipName, '/clip/' + str(newClipQuery.id), "/images/" +
                    str(recordedVidQuery.channel.owner.pictureLocation),
                    sub.userID)
                db.session.add(newNotification)

            db.session.commit()
            db.session.close()
            return True, redirectID
    return False, None
Exemplo n.º 18
0
def moveVideo(videoID, newChannel):

    recordedVidQuery = RecordedVideo.RecordedVideo.query.filter_by(
        id=int(videoID), owningUser=current_user.id).first()

    if recordedVidQuery is not None:
        newChannelQuery = Channel.Channel.query.filter_by(
            id=newChannel, owningUser=current_user.id).first()
        if newChannelQuery is not None:
            videos_root = globalvars.videoRoot + 'videos/'

            recordedVidQuery.channelID = newChannelQuery.id
            coreVideo = (recordedVidQuery.videoLocation.split("/")[1]).split(
                "_", 1)[1]
            if not os.path.isdir(videos_root + newChannelQuery.channelLoc):
                try:
                    os.mkdir(videos_root + newChannelQuery.channelLoc)
                except OSError:
                    system.newLog(
                        4,
                        "Error Moving Video ID #" + str(recordedVidQuery.id) +
                        "to Channel ID" + str(newChannelQuery.id) + "/" +
                        newChannelQuery.channelLoc)
                    flash("Error Moving Video - Unable to Create Directory",
                          "error")
                    return False
            shutil.move(
                videos_root + recordedVidQuery.videoLocation,
                videos_root + newChannelQuery.channelLoc + "/" +
                newChannelQuery.channelLoc + "_" + coreVideo)
            recordedVidQuery.videoLocation = newChannelQuery.channelLoc + "/" + newChannelQuery.channelLoc + "_" + coreVideo
            if (recordedVidQuery.thumbnailLocation is not None) and (
                    os.path.exists(videos_root +
                                   recordedVidQuery.thumbnailLocation)):
                coreThumbnail = (
                    recordedVidQuery.thumbnailLocation.split("/")[1]).split(
                        "_", 1)[1]
                coreThumbnailGif = (
                    recordedVidQuery.gifLocation.split("/")[1]).split("_",
                                                                      1)[1]
                shutil.move(
                    videos_root + recordedVidQuery.thumbnailLocation,
                    videos_root + newChannelQuery.channelLoc + "/" +
                    newChannelQuery.channelLoc + "_" + coreThumbnail)
                if (recordedVidQuery.gifLocation is not None) and (
                        os.path.exists(videos_root +
                                       recordedVidQuery.gifLocation)):
                    shutil.move(
                        videos_root + recordedVidQuery.gifLocation,
                        videos_root + newChannelQuery.channelLoc + "/" +
                        newChannelQuery.channelLoc + "_" + coreThumbnailGif)
                recordedVidQuery.thumbnailLocation = newChannelQuery.channelLoc + "/" + newChannelQuery.channelLoc + "_" + coreThumbnail
                recordedVidQuery.gifLocation = newChannelQuery.channelLoc + "/" + newChannelQuery.channelLoc + "_" + coreThumbnailGif
            for clip in recordedVidQuery.clips:
                coreThumbnail = (clip.thumbnailLocation.split("/")[2])
                if not os.path.isdir(videos_root + newChannelQuery.channelLoc +
                                     '/clips'):
                    try:
                        os.mkdir(videos_root + newChannelQuery.channelLoc +
                                 '/clips')
                    except OSError:
                        system.newLog(
                            4, "Error Moving Video ID #" +
                            str(recordedVidQuery.id) + "to Channel ID" +
                            str(newChannelQuery.id) + "/" +
                            newChannelQuery.channelLoc)
                        flash(
                            "Error Moving Video - Unable to Create Clips Directory",
                            "error")
                        return False
                newClipLocation = videos_root + newChannelQuery.channelLoc + "/clips/" + coreThumbnail
                shutil.move(videos_root + clip.thumbnailLocation,
                            newClipLocation)
                clip.thumbnailLocation = newChannelQuery.channelLoc + "/clips/" + coreThumbnail

            db.session.commit()
            system.newLog(
                4, "Video ID #" + str(recordedVidQuery.id) +
                "Moved to Channel ID" + str(newChannelQuery.id) + "/" +
                newChannelQuery.channelLoc)
            return True
    return False
Exemplo n.º 19
0
    user.xmppToken = str(os.urandom(32).hex())
    user.uuid = str(uuid.uuid4())
    webhookFunc.runWebhook("ZZZ", 20, user=user.username)
    system.newLog(1,
                  "A New User has Registered - Username:"******"An email has been sent to the email provided. Please check your email and verify your account to activate."
        )
    db.session.commit()


#----------------------------------------------------------------------------#
# Additional Handlers.
#----------------------------------------------------------------------------#
@app.teardown_appcontext
def shutdown_session(exception=None):
    db.session.remove()


#----------------------------------------------------------------------------#
# Finalize App Init
#----------------------------------------------------------------------------#
system.newLog(
    "0", "OSP Started Up Successfully - version: " + str(globalvars.version))

if __name__ == '__main__':
    app.jinja_env.auto_reload = False
    app.config['TEMPLATES_AUTO_RELOAD'] = False
    socketio.run(app, Debug=config.debugMode)
Exemplo n.º 20
0
def oAuthAuthorize(provider):
    oAuthClient = oauth.create_client(provider)
    oAuthProviderQuery = settings.oAuthProvider.query.filter_by(
        name=provider).first()
    if oAuthProviderQuery is not None:

        try:
            token = oAuthClient.authorize_access_token()
        except:
            return redirect('/login')

        userData = oAuthClient.get(oAuthProviderQuery.profile_endpoint)
        userDataDict = userData.json()

        userQuery = Sec.User.query.filter_by(
            oAuthID=userDataDict[oAuthProviderQuery.id_value],
            oAuthProvider=provider,
            authType=1).first()

        # Default expiration time to 365 days into the future
        if 'expires_at' not in token:
            if 'expires_in' in token:
                token['expires_at'] = datetime.timedelta(seconds=int(
                    token['exipires_in'])) + datetime.datetime.utcnow()
            else:
                token['expires_at'] = time() + (365 * 24 * 3600)

        # If oAuth ID, Provider, and Auth Type Match - Initiate Login
        if userQuery is not None:
            existingTokenQuery = Sec.OAuth2Token.query.filter_by(
                user=userQuery.id).all()
            for existingToken in existingTokenQuery:
                db.session.delete(existingToken)
            db.session.commit()
            newToken = None
            if 'refresh_token' in token:
                newToken = Sec.OAuth2Token(provider, token['token_type'],
                                           token['access_token'],
                                           token['refresh_token'],
                                           token['expires_at'], userQuery.id)
            else:
                newToken = Sec.OAuth2Token(provider, token['token_type'],
                                           token['access_token'], None,
                                           token['expires_at'], userQuery.id)
            db.session.add(newToken)
            db.session.commit()

            if userQuery.active is False:
                flash(
                    "User has been Disabled.  Please contact your administrator",
                    "error")
                return redirect('/login')
            else:
                login_user(userQuery)

                if oAuthProviderQuery.preset_auth_type == "Discord":
                    discord_processLogin(userDataDict, userQuery)
                elif oAuthProviderQuery.preset_auth_type == "Reddit":
                    reddit_processLogin(userDataDict, userQuery)
                elif oAuthProviderQuery.preset_auth_type == "Facebook":
                    facebook_processLogin(oAuthProviderQuery.api_base_url,
                                          userDataDict, userQuery)

                if userQuery.email is None or userQuery.email == 'None':
                    flash("Please Add an Email Address to your User Profile",
                          "error")
                    return redirect(url_for('settings.user_page'))
                else:
                    return redirect(url_for('root.main_page'))

        # If No Match, Determine if a User Needs to be created
        else:
            existingEmailQuery = None
            hasEmail = False

            if oAuthProviderQuery.email_value in userDataDict:
                existingEmailQuery = Sec.User.query.filter_by(
                    email=userDataDict[
                        oAuthProviderQuery.email_value]).first()
                hasEmail = True
            else:
                flash("Please Add an Email Address to your User Profile",
                      "error")

            # No Username Match - Create New User
            if existingEmailQuery is None:
                convertedUsername = userDataDict[
                    oAuthProviderQuery.username_value].replace(" ", "_")
                userDataDict[
                    oAuthProviderQuery.username_value] = convertedUsername
                existingUsernameQuery = Sec.User.query.filter_by(
                    username=convertedUsername).first()
                requestedUsername = convertedUsername
                if existingUsernameQuery is not None:
                    requestedUsername = requestedUsername + str(
                        random.randint(1, 9999))
                if hasEmail is True:
                    user_datastore.create_user(
                        email=userDataDict[oAuthProviderQuery.email_value],
                        username=requestedUsername,
                        active=True,
                        confirmed_at=datetime.datetime.utcnow(),
                        authType=1,
                        oAuthID=userDataDict[oAuthProviderQuery.id_value],
                        oAuthProvider=provider)
                else:
                    user_datastore.create_user(
                        email=None,
                        username=requestedUsername,
                        active=True,
                        confirmed_at=datetime.datetime.utcnow(),
                        authType=1,
                        oAuthID=userDataDict[oAuthProviderQuery.id_value],
                        oAuthProvider=provider)
                db.session.commit()
                user = Sec.User.query.filter_by(
                    username=requestedUsername).first()
                defaultRoleQuery = Sec.Role.query.filter_by(default=True)
                for role in defaultRoleQuery:
                    user_datastore.add_role_to_user(user, role.name)
                user.uuid = str(uuid.uuid4())
                user.xmppToken = str(os.urandom(32).hex())

                if oAuthProviderQuery.preset_auth_type == "Discord":
                    discord_processLogin(userDataDict, user)
                elif oAuthProviderQuery.preset_auth_type == "Reddit":
                    reddit_processLogin(userDataDict, user)
                elif oAuthProviderQuery.preset_auth_type == "Facebook":
                    facebook_processLogin(oAuthProviderQuery.api_base_url,
                                          userDataDict, user)

                newToken = None
                if 'refresh_token' in token:
                    newToken = Sec.OAuth2Token(provider, token['token_type'],
                                               token['access_token'],
                                               token['refresh_token'],
                                               token['expires_at'], user.id)
                else:
                    newToken = Sec.OAuth2Token(provider, token['token_type'],
                                               token['access_token'], None,
                                               token['expires_at'], user.id)
                db.session.add(newToken)
                db.session.commit()
                login_user(user)

                runWebhook("ZZZ", 20, user=user.username)
                newLog(
                    1, "A New User has Registered - Username:"******"An existing OAuth User exists under this email address with another provider",
                        "error")
                    return redirect('/')
Exemplo n.º 21
0
def comments_vid_page(videoID):
    sysSettings = settings.settings.query.first()

    recordedVid = RecordedVideo.RecordedVideo.query.filter_by(
        id=videoID).first()

    if recordedVid is not None:

        if request.method == 'POST':

            comment = system.strip_html(request.form['commentText'])
            currentUser = current_user.id

            newComment = comments.videoComments(currentUser, comment,
                                                recordedVid.id)
            db.session.add(newComment)
            db.session.commit()

            if recordedVid.channel.imageLocation is None:
                channelImage = (sysSettings.siteProtocol +
                                sysSettings.siteAddress +
                                "/static/img/video-placeholder.jpg")
            else:
                channelImage = (sysSettings.siteProtocol +
                                sysSettings.siteAddress + "/images/" +
                                recordedVid.channel.imageLocation)

            pictureLocation = ""
            if current_user.pictureLocation is None:
                pictureLocation = '/static/img/user2.png'
            else:
                pictureLocation = '/images/' + pictureLocation

            newNotification = notifications.userNotification(
                templateFilters.get_userName(current_user.id) +
                " commented on your video - " + recordedVid.channelName,
                '/play/' + str(recordedVid.id),
                "/images/" + str(current_user.pictureLocation),
                recordedVid.owningUser)
            db.session.add(newNotification)
            db.session.commit()

            webhookFunc.runWebhook(
                recordedVid.channel.id,
                7,
                channelname=recordedVid.channel.channelName,
                channelurl=(sysSettings.siteProtocol +
                            sysSettings.siteAddress + "/channel/" +
                            str(recordedVid.channel.id)),
                channeltopic=templateFilters.get_topicName(
                    recordedVid.channel.topic),
                channelimage=channelImage,
                streamer=templateFilters.get_userName(
                    recordedVid.channel.owningUser),
                channeldescription=str(recordedVid.channel.description),
                videoname=recordedVid.channelName,
                videodate=recordedVid.videoDate,
                videodescription=recordedVid.description,
                videotopic=templateFilters.get_topicName(recordedVid.topic),
                videourl=(sysSettings.siteProtocol + sysSettings.siteAddress +
                          '/videos/' + recordedVid.videoLocation),
                videothumbnail=(sysSettings.siteProtocol +
                                sysSettings.siteAddress + '/videos/' +
                                recordedVid.thumbnailLocation),
                user=current_user.username,
                userpicture=(sysSettings.siteProtocol +
                             sysSettings.siteAddress + str(pictureLocation)),
                comment=comment)
            flash('Comment Added', "success")
            system.newLog(
                4, "Video Comment Added by " + current_user.username +
                "to Video ID #" + str(recordedVid.id))

        elif request.method == 'GET':
            if request.args.get('action') == "delete":
                commentID = int(request.args.get('commentID'))
                commentQuery = comments.videoComments.query.filter_by(
                    id=commentID).first()
                if commentQuery is not None:
                    if current_user.has_role(
                            'Admin'
                    ) or recordedVid.owningUser == current_user.id or commentQuery.userID == current_user.id:
                        upvoteQuery = upvotes.commentUpvotes.query.filter_by(
                            commentID=commentQuery.id).all()
                        for vote in upvoteQuery:
                            db.session.delete(vote)
                        db.session.delete(commentQuery)
                        db.session.commit()
                        system.newLog(
                            4, "Video Comment Deleted by " +
                            current_user.username + "to Video ID #" +
                            str(recordedVid.id))
                        flash('Comment Deleted', "success")
                    else:
                        flash("Not Authorized to Remove Comment", "error")

    else:
        flash('Invalid Video ID', 'error')
        return redirect(url_for('root.main_page'))

    return redirect(url_for('.view_vid_page', videoID=videoID))