Add custom playlists
This commit is contained in:
parent
2fb5af4171
commit
aa10b5b2cc
@ -15,14 +15,17 @@ export const WaitingRoom = () => {
|
|||||||
const [isHost, setIsHost] = useState(false);
|
const [isHost, setIsHost] = useState(false);
|
||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
|
const [playlists, setPlaylists] = useState({});
|
||||||
|
const [votes, setVotes] = useState({});
|
||||||
|
const [selectedPlaylist, setSelectedPlaylist] = useState(null);
|
||||||
const messageEndRef = useRef(null);
|
const messageEndRef = useRef(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Check if the user is a host and get other initial data
|
|
||||||
send("check-host-status");
|
send("check-host-status");
|
||||||
send("get-user-info");
|
send("get-user-info");
|
||||||
send("get-room-users");
|
send("get-room-users");
|
||||||
send("get-room-code");
|
send("get-room-code");
|
||||||
|
send("get-playlist-options");
|
||||||
|
|
||||||
const handleHostStatus = (status) => {
|
const handleHostStatus = (status) => {
|
||||||
setIsHost(status.isHost);
|
setIsHost(status.isHost);
|
||||||
@ -72,6 +75,14 @@ export const WaitingRoom = () => {
|
|||||||
setCurrentState("Game");
|
setCurrentState("Game");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handlePlaylistOptions = (options) => {
|
||||||
|
setPlaylists(options);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleVotesUpdated = (newVotes) => {
|
||||||
|
setVotes(newVotes);
|
||||||
|
};
|
||||||
|
|
||||||
// Register event listeners
|
// Register event listeners
|
||||||
const cleanupHostStatus = on("host-status", handleHostStatus);
|
const cleanupHostStatus = on("host-status", handleHostStatus);
|
||||||
const cleanupUserInfo = on("user-info", handleUserInfo);
|
const cleanupUserInfo = on("user-info", handleUserInfo);
|
||||||
@ -82,8 +93,9 @@ export const WaitingRoom = () => {
|
|||||||
const cleanupUserDisconnected = on("user-disconnected", handleUserDisconnected);
|
const cleanupUserDisconnected = on("user-disconnected", handleUserDisconnected);
|
||||||
const cleanupChatMessage = on("chat-message", handleChatMessage);
|
const cleanupChatMessage = on("chat-message", handleChatMessage);
|
||||||
const cleanupGameStarted = on("game-started", handleGameStarted);
|
const cleanupGameStarted = on("game-started", handleGameStarted);
|
||||||
|
const cleanupPlaylistOptions = on("playlist-options", handlePlaylistOptions);
|
||||||
|
const cleanupVotesUpdated = on("playlist-votes-updated", handleVotesUpdated);
|
||||||
|
|
||||||
// Add welcome message
|
|
||||||
setMessages([{
|
setMessages([{
|
||||||
system: true,
|
system: true,
|
||||||
text: "Welcome to the waiting room! Waiting for others to join..."
|
text: "Welcome to the waiting room! Waiting for others to join..."
|
||||||
@ -99,6 +111,8 @@ export const WaitingRoom = () => {
|
|||||||
cleanupUserDisconnected();
|
cleanupUserDisconnected();
|
||||||
cleanupChatMessage();
|
cleanupChatMessage();
|
||||||
cleanupGameStarted();
|
cleanupGameStarted();
|
||||||
|
cleanupPlaylistOptions();
|
||||||
|
cleanupVotesUpdated();
|
||||||
};
|
};
|
||||||
}, [on, send, socket, setCurrentState]);
|
}, [on, send, socket, setCurrentState]);
|
||||||
|
|
||||||
@ -125,7 +139,6 @@ export const WaitingRoom = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleLeaveRoom = () => {
|
const handleLeaveRoom = () => {
|
||||||
// Disconnect from the current room
|
|
||||||
if (socket) {
|
if (socket) {
|
||||||
socket.disconnect();
|
socket.disconnect();
|
||||||
}
|
}
|
||||||
@ -138,7 +151,40 @@ export const WaitingRoom = () => {
|
|||||||
setTimeout(() => setCopied(false), 2000);
|
setTimeout(() => setCopied(false), 2000);
|
||||||
};
|
};
|
||||||
|
|
||||||
const minPlayersToStart = 1; // Set your minimum players requirement here
|
const handleVote = (playlistId) => {
|
||||||
|
setSelectedPlaylist(playlistId);
|
||||||
|
send("vote-playlist", { playlistId });
|
||||||
|
};
|
||||||
|
|
||||||
|
const getVoteCount = (playlistId) => {
|
||||||
|
return votes[playlistId]?.length || 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderPlaylists = () => (
|
||||||
|
<div className="playlists-grid">
|
||||||
|
{Object.entries(playlists).map(([genre, playlist]) => (
|
||||||
|
<div
|
||||||
|
key={playlist.id}
|
||||||
|
className={`playlist-card ${selectedPlaylist === playlist.id ? 'selected' : ''}`}
|
||||||
|
onClick={() => handleVote(playlist.id)}
|
||||||
|
>
|
||||||
|
<div className="playlist-thumbnail">
|
||||||
|
<img src={playlist.thumbnail.url} alt={playlist.title} />
|
||||||
|
<div className="vote-count">
|
||||||
|
<span>{getVoteCount(playlist.id)}</span>
|
||||||
|
<span className="vote-label">votes</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="playlist-info">
|
||||||
|
<h3>{genre.toUpperCase()}</h3>
|
||||||
|
<p>{playlist.songCount} songs</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const minPlayersToStart = 1;
|
||||||
const canStartGame = isHost && users.length >= minPlayersToStart;
|
const canStartGame = isHost && users.length >= minPlayersToStart;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -227,6 +273,11 @@ export const WaitingRoom = () => {
|
|||||||
<button onClick={handleSendMessage}>Senden</button>
|
<button onClick={handleSendMessage}>Senden</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="playlist-section">
|
||||||
|
<h2>Vote for Playlist</h2>
|
||||||
|
{renderPlaylists()}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -330,6 +330,86 @@
|
|||||||
font-size: 1.4rem
|
font-size: 1.4rem
|
||||||
margin: 0
|
margin: 0
|
||||||
|
|
||||||
|
.playlist-section
|
||||||
|
margin-bottom: 30px
|
||||||
|
|
||||||
|
h2
|
||||||
|
color: $white
|
||||||
|
text-align: center
|
||||||
|
margin-bottom: 20px
|
||||||
|
font-size: 24px
|
||||||
|
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5)
|
||||||
|
|
||||||
|
.playlists-grid
|
||||||
|
display: grid
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))
|
||||||
|
gap: 20px
|
||||||
|
padding: 20px
|
||||||
|
|
||||||
|
.playlist-card
|
||||||
|
background: rgba(255, 255, 255, 0.1)
|
||||||
|
border-radius: 15px
|
||||||
|
overflow: hidden
|
||||||
|
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)
|
||||||
|
cursor: pointer
|
||||||
|
border: 2px solid transparent
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
transform: translateY(-5px)
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3)
|
||||||
|
background: rgba(255, 255, 255, 0.15)
|
||||||
|
|
||||||
|
&.selected
|
||||||
|
border-color: $yellow
|
||||||
|
box-shadow: 0 0 30px rgba($yellow, 0.3)
|
||||||
|
|
||||||
|
.playlist-thumbnail
|
||||||
|
position: relative
|
||||||
|
width: 100%
|
||||||
|
padding-top: 56.25%
|
||||||
|
|
||||||
|
img
|
||||||
|
position: absolute
|
||||||
|
top: 0
|
||||||
|
left: 0
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
object-fit: cover
|
||||||
|
|
||||||
|
.vote-count
|
||||||
|
position: absolute
|
||||||
|
top: 10px
|
||||||
|
right: 10px
|
||||||
|
background: rgba(0, 0, 0, 0.8)
|
||||||
|
padding: 8px 12px
|
||||||
|
border-radius: 20px
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
align-items: center
|
||||||
|
|
||||||
|
span
|
||||||
|
color: $white
|
||||||
|
|
||||||
|
&:first-child
|
||||||
|
font-size: 24px
|
||||||
|
font-weight: bold
|
||||||
|
|
||||||
|
&.vote-label
|
||||||
|
font-size: 12px
|
||||||
|
opacity: 0.8
|
||||||
|
|
||||||
|
.playlist-info
|
||||||
|
padding: 15px
|
||||||
|
|
||||||
|
h3
|
||||||
|
color: $white
|
||||||
|
margin-bottom: 5px
|
||||||
|
font-size: 18px
|
||||||
|
|
||||||
|
p
|
||||||
|
color: rgba(255, 255, 255, 0.7)
|
||||||
|
font-size: 14px
|
||||||
|
|
||||||
@keyframes pop
|
@keyframes pop
|
||||||
0%
|
0%
|
||||||
transform: scale(1)
|
transform: scale(1)
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
|
"googleapis": "^146.0.0",
|
||||||
"socket.io": "^4.8.1"
|
"socket.io": "^4.8.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
209
pnpm-lock.yaml
generated
209
pnpm-lock.yaml
generated
@ -11,6 +11,9 @@ importers:
|
|||||||
express:
|
express:
|
||||||
specifier: ^4.21.2
|
specifier: ^4.21.2
|
||||||
version: 4.21.2
|
version: 4.21.2
|
||||||
|
googleapis:
|
||||||
|
specifier: ^146.0.0
|
||||||
|
version: 146.0.0
|
||||||
socket.io:
|
socket.io:
|
||||||
specifier: ^4.8.1
|
specifier: ^4.8.1
|
||||||
version: 4.8.1
|
version: 4.8.1
|
||||||
@ -37,6 +40,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
|
agent-base@7.1.3:
|
||||||
|
resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==}
|
||||||
|
engines: {node: '>= 14'}
|
||||||
|
|
||||||
ansi-regex@5.0.1:
|
ansi-regex@5.0.1:
|
||||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@ -55,10 +62,16 @@ packages:
|
|||||||
balanced-match@1.0.2:
|
balanced-match@1.0.2:
|
||||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||||
|
|
||||||
|
base64-js@1.5.1:
|
||||||
|
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||||
|
|
||||||
base64id@2.0.0:
|
base64id@2.0.0:
|
||||||
resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==}
|
resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==}
|
||||||
engines: {node: ^4.5.0 || >= 5.9}
|
engines: {node: ^4.5.0 || >= 5.9}
|
||||||
|
|
||||||
|
bignumber.js@9.1.2:
|
||||||
|
resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==}
|
||||||
|
|
||||||
binary-extensions@2.3.0:
|
binary-extensions@2.3.0:
|
||||||
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
|
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@ -74,6 +87,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
|
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
buffer-equal-constant-time@1.0.1:
|
||||||
|
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
|
||||||
|
|
||||||
bytes@3.1.2:
|
bytes@3.1.2:
|
||||||
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
|
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
@ -165,6 +181,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
ecdsa-sig-formatter@1.0.11:
|
||||||
|
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
|
||||||
|
|
||||||
ee-first@1.1.1:
|
ee-first@1.1.1:
|
||||||
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
||||||
|
|
||||||
@ -214,6 +233,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==}
|
resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==}
|
||||||
engines: {node: '>= 0.10.0'}
|
engines: {node: '>= 0.10.0'}
|
||||||
|
|
||||||
|
extend@3.0.2:
|
||||||
|
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
|
||||||
|
|
||||||
fill-range@7.1.1:
|
fill-range@7.1.1:
|
||||||
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
|
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@ -238,6 +260,14 @@ packages:
|
|||||||
function-bind@1.1.2:
|
function-bind@1.1.2:
|
||||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||||
|
|
||||||
|
gaxios@6.7.1:
|
||||||
|
resolution: {integrity: sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==}
|
||||||
|
engines: {node: '>=14'}
|
||||||
|
|
||||||
|
gcp-metadata@6.1.1:
|
||||||
|
resolution: {integrity: sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==}
|
||||||
|
engines: {node: '>=14'}
|
||||||
|
|
||||||
get-caller-file@2.0.5:
|
get-caller-file@2.0.5:
|
||||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||||
engines: {node: 6.* || 8.* || >= 10.*}
|
engines: {node: 6.* || 8.* || >= 10.*}
|
||||||
@ -254,10 +284,30 @@ packages:
|
|||||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
|
|
||||||
|
google-auth-library@9.15.1:
|
||||||
|
resolution: {integrity: sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==}
|
||||||
|
engines: {node: '>=14'}
|
||||||
|
|
||||||
|
google-logging-utils@0.0.2:
|
||||||
|
resolution: {integrity: sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==}
|
||||||
|
engines: {node: '>=14'}
|
||||||
|
|
||||||
|
googleapis-common@7.2.0:
|
||||||
|
resolution: {integrity: sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
|
||||||
|
googleapis@146.0.0:
|
||||||
|
resolution: {integrity: sha512-NewqvhnBZOJsugCAOo636O0BGE/xY7Cg/v8Rjm1+5LkJCjcqAzLleJ6igd5vrRExJLSKrY9uHy9iKE7r0PrfhQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
|
||||||
gopd@1.2.0:
|
gopd@1.2.0:
|
||||||
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
|
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
gtoken@7.1.0:
|
||||||
|
resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
|
||||||
has-flag@3.0.0:
|
has-flag@3.0.0:
|
||||||
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
|
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@ -278,6 +328,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
|
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
|
https-proxy-agent@7.0.6:
|
||||||
|
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
|
||||||
|
engines: {node: '>= 14'}
|
||||||
|
|
||||||
iconv-lite@0.4.24:
|
iconv-lite@0.4.24:
|
||||||
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@ -312,6 +366,19 @@ packages:
|
|||||||
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
|
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
|
||||||
engines: {node: '>=0.12.0'}
|
engines: {node: '>=0.12.0'}
|
||||||
|
|
||||||
|
is-stream@2.0.1:
|
||||||
|
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
json-bigint@1.0.0:
|
||||||
|
resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==}
|
||||||
|
|
||||||
|
jwa@2.0.0:
|
||||||
|
resolution: {integrity: sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==}
|
||||||
|
|
||||||
|
jws@4.0.0:
|
||||||
|
resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==}
|
||||||
|
|
||||||
lodash@4.17.21:
|
lodash@4.17.21:
|
||||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
||||||
|
|
||||||
@ -356,6 +423,15 @@ packages:
|
|||||||
resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
|
resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
|
node-fetch@2.7.0:
|
||||||
|
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
||||||
|
engines: {node: 4.x || >=6.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
encoding: ^0.1.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
encoding:
|
||||||
|
optional: true
|
||||||
|
|
||||||
nodemon@3.1.9:
|
nodemon@3.1.9:
|
||||||
resolution: {integrity: sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==}
|
resolution: {integrity: sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@ -511,6 +587,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==}
|
resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
tr46@0.0.3:
|
||||||
|
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
||||||
|
|
||||||
tree-kill@1.2.2:
|
tree-kill@1.2.2:
|
||||||
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
|
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@ -532,14 +611,27 @@ packages:
|
|||||||
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
|
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
|
url-template@2.0.8:
|
||||||
|
resolution: {integrity: sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==}
|
||||||
|
|
||||||
utils-merge@1.0.1:
|
utils-merge@1.0.1:
|
||||||
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
|
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
|
||||||
engines: {node: '>= 0.4.0'}
|
engines: {node: '>= 0.4.0'}
|
||||||
|
|
||||||
|
uuid@9.0.1:
|
||||||
|
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
vary@1.1.2:
|
vary@1.1.2:
|
||||||
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
|
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
|
webidl-conversions@3.0.1:
|
||||||
|
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||||
|
|
||||||
|
whatwg-url@5.0.0:
|
||||||
|
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
||||||
|
|
||||||
wrap-ansi@7.0.0:
|
wrap-ansi@7.0.0:
|
||||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@ -585,6 +677,8 @@ snapshots:
|
|||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
negotiator: 0.6.3
|
negotiator: 0.6.3
|
||||||
|
|
||||||
|
agent-base@7.1.3: {}
|
||||||
|
|
||||||
ansi-regex@5.0.1: {}
|
ansi-regex@5.0.1: {}
|
||||||
|
|
||||||
ansi-styles@4.3.0:
|
ansi-styles@4.3.0:
|
||||||
@ -600,8 +694,12 @@ snapshots:
|
|||||||
|
|
||||||
balanced-match@1.0.2: {}
|
balanced-match@1.0.2: {}
|
||||||
|
|
||||||
|
base64-js@1.5.1: {}
|
||||||
|
|
||||||
base64id@2.0.0: {}
|
base64id@2.0.0: {}
|
||||||
|
|
||||||
|
bignumber.js@9.1.2: {}
|
||||||
|
|
||||||
binary-extensions@2.3.0: {}
|
binary-extensions@2.3.0: {}
|
||||||
|
|
||||||
body-parser@1.20.3:
|
body-parser@1.20.3:
|
||||||
@ -630,6 +728,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fill-range: 7.1.1
|
fill-range: 7.1.1
|
||||||
|
|
||||||
|
buffer-equal-constant-time@1.0.1: {}
|
||||||
|
|
||||||
bytes@3.1.2: {}
|
bytes@3.1.2: {}
|
||||||
|
|
||||||
call-bind-apply-helpers@1.0.2:
|
call-bind-apply-helpers@1.0.2:
|
||||||
@ -720,6 +820,10 @@ snapshots:
|
|||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
gopd: 1.2.0
|
gopd: 1.2.0
|
||||||
|
|
||||||
|
ecdsa-sig-formatter@1.0.11:
|
||||||
|
dependencies:
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
ee-first@1.1.1: {}
|
ee-first@1.1.1: {}
|
||||||
|
|
||||||
emoji-regex@8.0.0: {}
|
emoji-regex@8.0.0: {}
|
||||||
@ -796,6 +900,8 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
extend@3.0.2: {}
|
||||||
|
|
||||||
fill-range@7.1.1:
|
fill-range@7.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
to-regex-range: 5.0.1
|
to-regex-range: 5.0.1
|
||||||
@ -821,6 +927,26 @@ snapshots:
|
|||||||
|
|
||||||
function-bind@1.1.2: {}
|
function-bind@1.1.2: {}
|
||||||
|
|
||||||
|
gaxios@6.7.1:
|
||||||
|
dependencies:
|
||||||
|
extend: 3.0.2
|
||||||
|
https-proxy-agent: 7.0.6
|
||||||
|
is-stream: 2.0.1
|
||||||
|
node-fetch: 2.7.0
|
||||||
|
uuid: 9.0.1
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
- supports-color
|
||||||
|
|
||||||
|
gcp-metadata@6.1.1:
|
||||||
|
dependencies:
|
||||||
|
gaxios: 6.7.1
|
||||||
|
google-logging-utils: 0.0.2
|
||||||
|
json-bigint: 1.0.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
- supports-color
|
||||||
|
|
||||||
get-caller-file@2.0.5: {}
|
get-caller-file@2.0.5: {}
|
||||||
|
|
||||||
get-intrinsic@1.3.0:
|
get-intrinsic@1.3.0:
|
||||||
@ -845,8 +971,50 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
|
|
||||||
|
google-auth-library@9.15.1:
|
||||||
|
dependencies:
|
||||||
|
base64-js: 1.5.1
|
||||||
|
ecdsa-sig-formatter: 1.0.11
|
||||||
|
gaxios: 6.7.1
|
||||||
|
gcp-metadata: 6.1.1
|
||||||
|
gtoken: 7.1.0
|
||||||
|
jws: 4.0.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
- supports-color
|
||||||
|
|
||||||
|
google-logging-utils@0.0.2: {}
|
||||||
|
|
||||||
|
googleapis-common@7.2.0:
|
||||||
|
dependencies:
|
||||||
|
extend: 3.0.2
|
||||||
|
gaxios: 6.7.1
|
||||||
|
google-auth-library: 9.15.1
|
||||||
|
qs: 6.13.0
|
||||||
|
url-template: 2.0.8
|
||||||
|
uuid: 9.0.1
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
- supports-color
|
||||||
|
|
||||||
|
googleapis@146.0.0:
|
||||||
|
dependencies:
|
||||||
|
google-auth-library: 9.15.1
|
||||||
|
googleapis-common: 7.2.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
- supports-color
|
||||||
|
|
||||||
gopd@1.2.0: {}
|
gopd@1.2.0: {}
|
||||||
|
|
||||||
|
gtoken@7.1.0:
|
||||||
|
dependencies:
|
||||||
|
gaxios: 6.7.1
|
||||||
|
jws: 4.0.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
- supports-color
|
||||||
|
|
||||||
has-flag@3.0.0: {}
|
has-flag@3.0.0: {}
|
||||||
|
|
||||||
has-flag@4.0.0: {}
|
has-flag@4.0.0: {}
|
||||||
@ -865,6 +1033,13 @@ snapshots:
|
|||||||
statuses: 2.0.1
|
statuses: 2.0.1
|
||||||
toidentifier: 1.0.1
|
toidentifier: 1.0.1
|
||||||
|
|
||||||
|
https-proxy-agent@7.0.6:
|
||||||
|
dependencies:
|
||||||
|
agent-base: 7.1.3
|
||||||
|
debug: 4.3.7(supports-color@5.5.0)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
iconv-lite@0.4.24:
|
iconv-lite@0.4.24:
|
||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer: 2.1.2
|
safer-buffer: 2.1.2
|
||||||
@ -889,6 +1064,23 @@ snapshots:
|
|||||||
|
|
||||||
is-number@7.0.0: {}
|
is-number@7.0.0: {}
|
||||||
|
|
||||||
|
is-stream@2.0.1: {}
|
||||||
|
|
||||||
|
json-bigint@1.0.0:
|
||||||
|
dependencies:
|
||||||
|
bignumber.js: 9.1.2
|
||||||
|
|
||||||
|
jwa@2.0.0:
|
||||||
|
dependencies:
|
||||||
|
buffer-equal-constant-time: 1.0.1
|
||||||
|
ecdsa-sig-formatter: 1.0.11
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
|
jws@4.0.0:
|
||||||
|
dependencies:
|
||||||
|
jwa: 2.0.0
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
lodash@4.17.21: {}
|
lodash@4.17.21: {}
|
||||||
|
|
||||||
math-intrinsics@1.1.0: {}
|
math-intrinsics@1.1.0: {}
|
||||||
@ -917,6 +1109,10 @@ snapshots:
|
|||||||
|
|
||||||
negotiator@0.6.3: {}
|
negotiator@0.6.3: {}
|
||||||
|
|
||||||
|
node-fetch@2.7.0:
|
||||||
|
dependencies:
|
||||||
|
whatwg-url: 5.0.0
|
||||||
|
|
||||||
nodemon@3.1.9:
|
nodemon@3.1.9:
|
||||||
dependencies:
|
dependencies:
|
||||||
chokidar: 3.6.0
|
chokidar: 3.6.0
|
||||||
@ -1107,6 +1303,8 @@ snapshots:
|
|||||||
|
|
||||||
touch@3.1.1: {}
|
touch@3.1.1: {}
|
||||||
|
|
||||||
|
tr46@0.0.3: {}
|
||||||
|
|
||||||
tree-kill@1.2.2: {}
|
tree-kill@1.2.2: {}
|
||||||
|
|
||||||
tslib@2.8.1: {}
|
tslib@2.8.1: {}
|
||||||
@ -1122,10 +1320,21 @@ snapshots:
|
|||||||
|
|
||||||
unpipe@1.0.0: {}
|
unpipe@1.0.0: {}
|
||||||
|
|
||||||
|
url-template@2.0.8: {}
|
||||||
|
|
||||||
utils-merge@1.0.1: {}
|
utils-merge@1.0.1: {}
|
||||||
|
|
||||||
|
uuid@9.0.1: {}
|
||||||
|
|
||||||
vary@1.1.2: {}
|
vary@1.1.2: {}
|
||||||
|
|
||||||
|
webidl-conversions@3.0.1: {}
|
||||||
|
|
||||||
|
whatwg-url@5.0.0:
|
||||||
|
dependencies:
|
||||||
|
tr46: 0.0.3
|
||||||
|
webidl-conversions: 3.0.1
|
||||||
|
|
||||||
wrap-ansi@7.0.0:
|
wrap-ansi@7.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-styles: 4.3.0
|
ansi-styles: 4.3.0
|
||||||
|
@ -10,16 +10,22 @@ module.exports.roomExists = (roomId) => rooms[roomId] !== undefined;
|
|||||||
|
|
||||||
module.exports.isRoomOpen = (roomId) => rooms[roomId] && rooms[roomId].state === 'waiting';
|
module.exports.isRoomOpen = (roomId) => rooms[roomId] && rooms[roomId].state === 'waiting';
|
||||||
|
|
||||||
|
const initializeRoom = (roomId, user) => {
|
||||||
|
rooms[roomId] = {
|
||||||
|
members: [{...user, creator: true}],
|
||||||
|
settings: {},
|
||||||
|
state: 'waiting',
|
||||||
|
playlistVotes: {},
|
||||||
|
selectedPlaylist: null
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
module.exports.connectUserToRoom = (roomId, user) => {
|
module.exports.connectUserToRoom = (roomId, user) => {
|
||||||
roomId = roomId.toUpperCase();
|
roomId = roomId.toUpperCase();
|
||||||
if (rooms[roomId]) {
|
if (rooms[roomId]) {
|
||||||
rooms[roomId].members.push({...user, creator: false});
|
rooms[roomId].members.push({...user, creator: false});
|
||||||
} else {
|
} else {
|
||||||
rooms[roomId] = {
|
initializeRoom(roomId, user);
|
||||||
members: [{...user, creator: true}],
|
|
||||||
settings: {},
|
|
||||||
state: 'waiting'
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
console.log(`User ${user.name} connected to room ${roomId}`);
|
console.log(`User ${user.name} connected to room ${roomId}`);
|
||||||
}
|
}
|
||||||
@ -132,4 +138,32 @@ module.exports.getUserName = (userId) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.voteForPlaylist = (roomId, userId, playlistId) => {
|
||||||
|
if (!rooms[roomId]) return false;
|
||||||
|
|
||||||
|
const room = rooms[roomId];
|
||||||
|
if (room.state !== 'waiting') return false;
|
||||||
|
|
||||||
|
// Remove previous vote if exists
|
||||||
|
const previousVote = Object.entries(room.playlistVotes)
|
||||||
|
.find(([_, voters]) => voters.includes(userId));
|
||||||
|
|
||||||
|
if (previousVote) {
|
||||||
|
room.playlistVotes[previousVote[0]] =
|
||||||
|
room.playlistVotes[previousVote[0]].filter(id => id !== userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new vote
|
||||||
|
if (!room.playlistVotes[playlistId]) {
|
||||||
|
room.playlistVotes[playlistId] = [];
|
||||||
|
}
|
||||||
|
room.playlistVotes[playlistId].push(userId);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.getPlaylistVotes = (roomId) => {
|
||||||
|
return rooms[roomId]?.playlistVotes || {};
|
||||||
};
|
};
|
@ -308,4 +308,24 @@ module.exports = (io) => (socket) => {
|
|||||||
socket.emit("playlist-songs", { songs: youtubeService.getDefaultSongs() });
|
socket.emit("playlist-songs", { songs: youtubeService.getDefaultSongs() });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on("get-playlist-options", async () => {
|
||||||
|
try {
|
||||||
|
const playlists = await youtubeService.getPlaylistDetails();
|
||||||
|
socket.emit("playlist-options", playlists);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching playlist options:", error);
|
||||||
|
socket.emit("error", { message: "Failed to load playlists" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("vote-playlist", ({ playlistId }) => {
|
||||||
|
const roomId = roomController.getUserRoom(socket.id);
|
||||||
|
if (!roomId) return;
|
||||||
|
|
||||||
|
if (roomController.voteForPlaylist(roomId, socket.id, playlistId)) {
|
||||||
|
const votes = roomController.getPlaylistVotes(roomId);
|
||||||
|
io.to(roomId).emit("playlist-votes-updated", votes);
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
@ -1,6 +1,17 @@
|
|||||||
|
const { google } = require('googleapis');
|
||||||
|
const youtube = google.youtube('v3');
|
||||||
|
|
||||||
const YOUTUBE_API_KEY = process.env.YOUTUBE_API_KEY;
|
const YOUTUBE_API_KEY = process.env.YOUTUBE_API_KEY;
|
||||||
const PLAYLIST_ID = "PLmXxqSJJq-yXrCPGIT2gn8b34JjOrl4Xf";
|
const PLAYLIST_ID = "PLmXxqSJJq-yXrCPGIT2gn8b34JjOrl4Xf";
|
||||||
|
|
||||||
|
const PLAYLISTS = {
|
||||||
|
seventies: 'PLmXxqSJJq-yXrCPGIT2gn8b34JjOrl4Xf',
|
||||||
|
eighties: 'PLmXxqSJJq-yUvMWKuZQAB_8yxnjZaOZUp',
|
||||||
|
nineties: 'PLmXxqSJJq-yUF3jbzjF_pa--kuBuMlyQQ'
|
||||||
|
};
|
||||||
|
|
||||||
|
const API_KEY = process.env.YOUTUBE_API_KEY;
|
||||||
|
|
||||||
let cachedSongs = null;
|
let cachedSongs = null;
|
||||||
let lastFetchTime = 0;
|
let lastFetchTime = 0;
|
||||||
const CACHE_TTL = 3600000; // 1 hour
|
const CACHE_TTL = 3600000; // 1 hour
|
||||||
@ -68,4 +79,38 @@ const getAvailableSongIds = async () => {
|
|||||||
return songs.map(song => song.id);
|
return songs.map(song => song.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {fetchPlaylistSongs, getAvailableSongIds};
|
async function getPlaylistDetails() {
|
||||||
|
try {
|
||||||
|
const details = {};
|
||||||
|
|
||||||
|
for (const [genre, playlistId] of Object.entries(PLAYLISTS)) {
|
||||||
|
const response = await youtube.playlists.list({
|
||||||
|
key: API_KEY,
|
||||||
|
part: 'snippet,contentDetails',
|
||||||
|
id: playlistId
|
||||||
|
});
|
||||||
|
|
||||||
|
const playlist = response.data.items[0];
|
||||||
|
details[genre] = {
|
||||||
|
id: playlistId,
|
||||||
|
title: playlist.snippet.title,
|
||||||
|
description: playlist.snippet.description,
|
||||||
|
thumbnail: playlist.snippet.thumbnails.maxres || playlist.snippet.thumbnails.high,
|
||||||
|
songCount: playlist.contentDetails.itemCount,
|
||||||
|
votes: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return details;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching playlist details:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
fetchPlaylistSongs,
|
||||||
|
getAvailableSongIds,
|
||||||
|
PLAYLISTS,
|
||||||
|
getPlaylistDetails
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user