So what I want to do now is I want to go back to our follow service and to our recommended service. So in here if you remember we have a property called is live and this is supposed to change every time the user successfully connects their OBS with our ingress right But if you remember what we do currently, let's go ahead and revisit that. So inside of our app, which I think it's browse components sidebar. So in here we have following and recommended, right? So let's check out recommended first.
And in here we have the property isLive and we manually set it to false. I wanna change this now to use the stream model and the property we have in our Prisma schema. Here we have model stream and we have a property called isLive and right now this live cannot be triggered in any way, right? But so this is what we're going to do. First we're going to revisit our follow service and our recommended service so that inside of this user object we also include the relation with the stream for that user and then we're gonna go ahead and change this isLive to use user.stream.isLive right?
And then what we have to do is create a webhook with LiveKit so that every time we connect to our ingress this boolean changes from false to true and also when the ingress ends we want to change it back to false. So this is what I'm going to do first. Let's do the recommended service. So go inside of your lib folder and go inside of the recommended service here and in here go ahead and find the function get recommended and in here what I want to do first is go inside of this function where we we are logged in right where we have the user id So in here we have a chain of some queries here to ensure that we are not blocking the user, that we are not following the user and that we are not the user themselves. And now what I want to add is just above the order by I want to add include stream to be true like this.
And I also want to do that right here in the else function where we load the users for logged out users so also add include stream true here like this And now what I want to do is I want to go back inside of the recommended component. So inside of the app browse components sidebar. And if you take a look at my index here. So now we are loading the recommended here. And what you're going to see is that we now have the stream model inside which means we have to modify our data prop for the recommended component.
So go inside of the RecommendedComponent.vsx where we have hardcoded isLiveToFalse and let's modify this to not just load the user but also load the populated stream model. So I'm going to change this to use parentheses and then I'm going to write user and and then I'm going to open an object stream and stream is going to be the stream from Prisma Client so don't accidentally import it from the stream package, import it from Prisma Client like this or it's going to be null like that. Great! And now if you take a look in the sidebar index you should be having no errors here so that type should be supported and then in the recommended in here let's go ahead and change this to not use is live false instead let's use user.stream which we now have ?.isLive like this Great! And now I want to go ahead and do the same thing for the following service so let's go ahead and close everything, let's go inside the lib folder and let's go inside of the follow service here so find get followed users inside and we only have to do that inside of the try block because inside of the catch we just return an empty array for logged out users So in here we already include the following.
So now let's go ahead and do this. Let's extend the following include and let's also add another include inside a stream to be true like this. Great! So very simple modification for getFollowedUsers. We extended our following from just being true to an object which also includes the stream of that following.
And now we have to go back inside of our app folder, browse components, sidebar, following right here and we have to modify this prop as well. So it's no longer going to be just the user. Instead, it's going to be the following. So it's going to be the user and and go ahead and open an object and write stream to be stream from Prisma Client. So make sure you add stream from Prisma Client or null like that.
And if you want to, you can even collapse this. Let me go ahead and do that. Just so it's a bit more readable. Let me try it like this. There we go.
I think this is a bit more readable. So we are wrapping all of this inside of parentheses because that's gonna be an array, right? So we get the follow model, we include the following and I think I should have indented this as well. There we go. And then the following is a type of user which has the stream included inside.
Great. So make sure you add this and now we can modify our user item here as well to use is live. And let's give it a property of follow dot following dot stream question mark dot is live. Like that. Great.
And nothing should change in the code now, right? Because both of these are not working. But what you can already do manually is go ahead and open your Prisma Studio if you want to. So npx prisma studio, right? And that should open it on localhost 5555.
And now you have to find the stream of the user you can see in the recommended so my user is code with Antonio's in my Prisma studio I'm looking at code with Antonio's stream and I'm going to manually change this value of is live to be true like this and I'm going to click save one change and now what should happen is when I refresh here this should stay live like this right because now we're no longer hard coding that prop instead we are using the is live property and if you log out you will also see it as live as well. Great. So what I want you to do now is go back inside of your Prisma Studio and just change this property back to false and click save one change like this. So we have the proper data inside of our database. What we have to do now is we have to spin up our ngrok local tunnel and we have to create a webhook with LiveKit.
So just a quick reminder where you can find that. So go inside of ngrok, click on your cloud edge sidebar, domains right here and in here you should have your domain. Click on the little terminal icon which says start a tunnel and there we go you have the URL from here. So you can do it this way or you can simply run ngrok HTTP 3000 and then use that new URL But remember you have to change it everywhere we are using it. So I'm going to shut down this for now, just so I can show you everything I have running.
So I have running npm run dev, so we can do that together. So make sure you do npm run dev on localhost 3000, open a new terminal and then paste this command which you just copied from ngrok like this and make sure you change the port from 80 to 3000 like this. So this is one option you can do you know just press ENTER and then you have your stable URL and you don't have to change that from clerk because remember this doesn't change right or you can do ngrok HTTP 3000 if for any reason your domains are not working and then you're going to get a randomly assigned URL. So just remember, you have to go ahead into clerk webhooks and then change that to the new URL. So what I'm gonna do is I'm gonna be using this command which we just copied from the ngrok.
So I have my stable webhook URL, Make sure you're doing it on port 3000 and not 80. So make sure you change that part of the command. Great. And now what I want to do is just confirm in my URL that this will render my localhost 3000 and it seems to be working great. So what I want to do now is go inside of my LiveKit here and let's go inside of the settings and let's click on webhooks right here and let's go ahead and click add new endpoint like that and I'm going to call this development as well and let's go ahead and paste this and then what we have to do is go add to this URL to go to slash API slash webhooks slash livekit so this is very important that you add this part because that's where we are going to create our webhook, right?
And then in designing API key it is important that you select the one you created when we were setting up LiveKit. So don't choose the default one we created together a new one if you remember and we called it development so make sure that one is selected and then just click create and that's it nothing else you have to do here and now we are ready to create our webhook so Let's go ahead and create the appropriate URL for that. So I want to go inside of my app folder inside of API and in here we have webhooks. So inside of this folder create a new folder called livekit like this and inside simply create route.ts file. Great and now let's go ahead and let's import headers from next slash headers.
Let's go ahead and import webhook receiver from LiveKit server SDK. Let's go ahead and import our database from add slash lib database and now let's set up our receiver So const receiver is new webhook receiver which accepts process dot environment dot livekit underscore API key and process dot environment dot livekit underscore API secret and make sure to add exclamation points at the end and double check that you actually have those in your environment file so you should copy the livekit API key paste it here to ensure you don't have any typos and do the same thing with the secret. So LiveKit API secret and add it here and they should match. Great. Now let's do export asynchronous function post, which accepts the request, which is a type of request.
Let's get the body using a wait request in a form of text. So our webhook can process this. Let's get our header payload. So const header payload is headers. And now let's get the authorization from the headers so header payload.get authorization with capital I like this if there is no authorization header if there is no authorization header we're gonna go ahead and throw actually return new response which is going to say no authorization header, and let's pass in a status of 400, meaning that we cannot proceed with this webhook.
And now let's get the event which was passed. So event is receiver dot receive passing the body in form of text here and authorization so we can confirm that the live kid has access to this web hook right And then we can simply check which event was fired. So if event.event is equal to ingress underscore ended like that, let's do await DB stream update where, and we're going to find the stream using our ingress ID so that's why we added that in our schema prisma our stream model has the ingress ID and inside of our ingress action when we create an ingress you can see right here that we make sure to assign the ingress.id right so make sure you do this now so we are going to find the stream using the ingress so go back inside of your livekit webhook right and in here we're going to write ingress ID is event.ingressInfo?.ingressID like that and then let's add data is live to be false right so when the ingress ends we turn it back to false like this and now let's go ahead and let's add a new one here so this is for ended you can easily copy and paste this and change this one to be if event dot event is ingress started like this the where query is exactly the same but the data changes from is live false to is live true like this.
Great! And one more thing that I want you to confirm is that inside of your middleware you have this route in your public routes so the webhook can be received without authentication from Clark. Great! And now what should happen is that you should be able to go inside of your OBS studio so let me just go ahead back to localhost 3000 here and ensure that you have both your terminal running using the npm run dev and also the ngrok with the URL which you just passed to livekit. Go inside of your creator page here and go inside of the keys and in here go ahead and make sure that you have those in OBS and click start streaming.
So I'm gonna go ahead and attempt to do that. I am recording currently with my OBS but I'm still going to try and stream as well. So I will just confirm that I have the correct stream key inside of my OBS settings here. So inside of my stream looks like I have the correct key and I'm going to click start streaming like this and let's see if that's going to successfully connect. There we go I have a successful connection and now what I'm going to do is I'm going to log out right because we cannot see ourselves in this sidebar so let's go ahead and log out and there we go you can see that it says that I am live right I can refresh and it still says that I am live.
So our webhook is working and now what I'm gonna try is click stop streaming in the OBS and now when I refresh here maybe not instantly but after a couple of seconds it should go back to offline. Great! So make sure you just refresh a couple of times. It could be cache, it could be a bit of a late webhook, but this is fine. Other streaming services also have a bit of a delay.
Sometimes it says that the stream is active and then you click on it and then it says it's offline, right? So this is perfectly fine. Great! So our webhook is officially working and you can also double check this by opening up MPX Prisma Studio here and just ensure inside of your stream right now both of my streams is live is false but if I go and click start streaming in my OBS studio in a couple of seconds one of them should be true and there we go you can see that the first one is live is true and if I go ahead and click stop streaming then after a couple of refreshes I believe it should change to false, so it's still true let's try again let me scroll here one more time let's hope this is the one and there we go, now isLive is false great, so you successfully connected the webhook with your live kit and you can see how almost in real time it works and it's a great experience for your users so they can see what's going on in the page here. Perfect, so we now have control over the is live property and what we're gonna go ahead and do now is finally create the interface where other users will be able to look at the live stream and chat in real time.
Great, great job!