useYoutubeDirect.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import { ref } from "vue";
  2. import Toast from "toasters";
  3. import { AddSongToPlaylistResponse } from "@musare_types/actions/PlaylistsActions";
  4. import { useWebsocketsStore } from "@/stores/websockets";
  5. const youtubeVideoUrlRegex =
  6. /^(?:https?:\/\/)?(?:www\.)?(m\.)?(?:music\.)?(?:youtube\.com|youtu\.be)\/(?:watch\/?\?v=)?(?:.*&v=)?(?<youtubeId>[\w-]{11}).*$/;
  7. const youtubeVideoIdRegex = /^(?<youtubeId>[\w-]{11})$/;
  8. export const useYoutubeDirect = () => {
  9. const youtubeDirect = ref("");
  10. const { socket } = useWebsocketsStore();
  11. const getYoutubeVideoId = () => {
  12. const inputValue = youtubeDirect.value.trim();
  13. // Check if the user simply used a YouTube ID in the input directly
  14. const youtubeVideoIdMatch = youtubeVideoIdRegex.exec(inputValue);
  15. if (youtubeVideoIdMatch && youtubeVideoIdMatch.groups.youtubeId) {
  16. // eslint-disable-next-line prefer-destructuring
  17. return youtubeVideoIdMatch.groups.youtubeId;
  18. }
  19. // Check if we can get the video ID from passing in the input value into the URL regex
  20. const youtubeVideoUrlMatch = youtubeVideoUrlRegex.exec(inputValue);
  21. if (youtubeVideoUrlMatch && youtubeVideoUrlMatch.groups.youtubeId) {
  22. // eslint-disable-next-line prefer-destructuring
  23. return youtubeVideoUrlMatch.groups.youtubeId;
  24. }
  25. // Check if the user provided a URL of some kind that has the query parameter v, which also passes the YouTube video ID regex
  26. try {
  27. const { searchParams } = new URL(inputValue);
  28. if (searchParams.has("v")) {
  29. const vValue = searchParams.get("v");
  30. const vValueMatch = youtubeVideoIdRegex.exec(vValue);
  31. if (vValueMatch && vValueMatch.groups.youtubeId) {
  32. // eslint-disable-next-line prefer-destructuring
  33. return youtubeVideoIdMatch.groups.youtubeId;
  34. }
  35. }
  36. } catch (error) {
  37. return null;
  38. }
  39. return null;
  40. };
  41. const addToPlaylist = (playlistId: string) => {
  42. const youtubeVideoId = getYoutubeVideoId();
  43. if (!youtubeVideoId)
  44. new Toast(
  45. `Could not determine the YouTube video id from the provided URL.`
  46. );
  47. else {
  48. socket.dispatch(
  49. "playlists.addSongToPlaylist",
  50. false,
  51. `youtube:${youtubeVideoId}`,
  52. playlistId,
  53. (res: AddSongToPlaylistResponse) => {
  54. if (res.status !== "success")
  55. new Toast(`Error: ${res.message}`);
  56. else {
  57. new Toast(res.message);
  58. youtubeDirect.value = "";
  59. }
  60. }
  61. );
  62. }
  63. };
  64. const addToQueue = (stationId: string) => {
  65. const youtubeVideoId = getYoutubeVideoId();
  66. if (!youtubeVideoId)
  67. new Toast(
  68. `Could not determine the YouTube video id from the provided URL.`
  69. );
  70. else {
  71. socket.dispatch(
  72. "stations.addToQueue",
  73. stationId,
  74. `youtube:${youtubeVideoId}`,
  75. "manual",
  76. res => {
  77. if (res.status !== "success")
  78. new Toast(`Error: ${res.message}`);
  79. else {
  80. new Toast(res.message);
  81. youtubeDirect.value = "";
  82. }
  83. }
  84. );
  85. }
  86. };
  87. return {
  88. youtubeDirect,
  89. addToPlaylist,
  90. addToQueue,
  91. getYoutubeVideoId
  92. };
  93. };