Add basic chatroom

This commit is contained in:
batteredbunny 2024-02-24 19:40:46 +02:00
parent b01ee46748
commit 6d59ddaa1a
4 changed files with 106 additions and 4 deletions

View file

@ -12,8 +12,9 @@
</head>
<body>
<div class="container">
<div class="center-video">
<h1 class="text-center">Best livestream website ever</h1>
<div class="first-ui-row">
<div>
<video id="livestream" class="video-js" controls preload="auto" data-setup="{}">
<source src="/media/stream.mpd" type="application/dash+xml" />
<p class="vjs-no-js">
@ -23,7 +24,16 @@
</p>
</video>
</div>
<div class="chatbox">
<div id="messages"></div>
<div>
<input id="message-input" type="text" placeholder="Enter a message" autocomplete="off">
<button id="message-submit" type="submit">Send</button>
</div>
</div>
</div>
<div class="container">
<h2 class="text-center">Currently playing: <span id="currently_playing">Nothing</span></h2>
<h2 class="text-center">Viewers: <span id="viewers">1</span></h2>
</div>

View file

@ -1,4 +1,26 @@
.center-video {
.first-ui-row {
display: flex;
justify-content: center;
}
.chatbox {
align-self: end;
margin-left: 10px;
display: flex;
flex-direction: column;
}
#messages .message {
padding: 5px;
margin: 10px;
align-self: end;
width: 100%;
}
#messages .message .message-username {
text-align: start;
}
#messages .message .message-content {
text-align: end;
}

View file

@ -1,5 +1,10 @@
const WebsocketMessageTypeViewers = 0;
const WebsocketMessageTypeCurrentlyPlaying = 1;
const WebsocketMessageTypeChatMessage = 2;
const messages = document.getElementById("messages");
const messageInput = document.getElementById("message-input");
const messageSubmit = document.getElementById("message-submit");
let stream = videojs('livestream');
@ -12,6 +17,24 @@ if (location.protocol === 'https:') {
let websocket = new WebSocket(wsurl)
function sendInput() {
let message = {
type: WebsocketMessageTypeChatMessage,
message: messageInput.value,
};
messageInput.value = "";
websocket.send(JSON.stringify(message));
}
messageInput.addEventListener("keyup", function(e) {
if (e.key === "Enter") {
sendInput()
}
});
messageSubmit.addEventListener("click", (e) => sendInput())
websocket.onmessage = (event) => {
let data = JSON.parse(event.data)
@ -28,6 +51,22 @@ websocket.onmessage = (event) => {
console.log("trying again")
})
break
case WebsocketMessageTypeChatMessage:
let message = document.createElement("div");
message.className = "message";
let username = document.createElement("div");
username.className = "message-username";
username.innerText = data.message.username;
message.appendChild(username);
let content = document.createElement("div");
content.className = "message-content";
content.innerText = data.message.content;
message.appendChild(content);
messages.appendChild(message);
break
}
};

View file

@ -13,11 +13,12 @@ type WebsocketMessageType = int
const (
WebsocketMessageTypeViewers WebsocketMessageType = iota
WebsocketMessageTypeCurrentlyPlaying
WebsocketMessageTypeChatMessage
)
type WebsocketMessage struct {
Type WebsocketMessageType `json:"type"`
Message string `json:"message"`
Message any `json:"message"`
}
func (w WebsocketMessage) Encode() []byte {
@ -29,6 +30,11 @@ func (w WebsocketMessage) Encode() []byte {
return m
}
type WebsocketSendMessage struct {
Username string `json:"username"`
Content string `json:"content"`
}
func (state *State) setupWebsocket() {
state.Websocket = melody.New()
@ -49,6 +55,31 @@ func (state *State) setupWebsocket() {
}.Encode())
})
state.Websocket.HandleMessage(func(s *melody.Session, b []byte) {
var genericMessage WebsocketMessage
if err := json.Unmarshal(b, &genericMessage); err != nil {
log.Println(err)
return
}
switch genericMessage.Type {
case WebsocketMessageTypeChatMessage:
content, valid := genericMessage.Message.(string)
if !valid {
return
}
// TODO: turn IP into hash hex and get color from name
state.Websocket.Broadcast(WebsocketMessage{
Type: WebsocketMessageTypeChatMessage,
Message: WebsocketSendMessage{
Username: s.RemoteAddr().String(),
Content: content,
},
}.Encode())
}
})
state.Websocket.HandleDisconnect(func(s *melody.Session) {
viewers, err := state.ViewersAmount()
if err != nil {