Ver código fonte

refactor: Typescript continued..

Owen Diffey 2 anos atrás
pai
commit
1b975a5c75

+ 5 - 7
frontend/src/App.vue

@@ -3,10 +3,8 @@ import { useRouter } from "vue-router";
 import { defineAsyncComponent, ref, computed, watch, onMounted } from "vue";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
-import {
-	GetPreferencesResponse,
-	UpdatePreferencesResponse
-} from "@musare_types/actions/UsersActions";
+import { GenericResponse } from "@musare_types/actions/GenericActions";
+import { GetPreferencesResponse } from "@musare_types/actions/UsersActions";
 import { NewestResponse } from "@musare_types/actions/NewsActions";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useUserAuthStore } from "@/stores/userAuth";
@@ -61,7 +59,7 @@ const toggleNightMode = () => {
 		socket.dispatch(
 			"users.updatePreferences",
 			{ nightmode: !nightmode.value },
-			(res: UpdatePreferencesResponse) => {
+			(res: GenericResponse) => {
 				if (res.status !== "success") new Toast(res.message);
 			}
 		);
@@ -122,7 +120,7 @@ onMounted(async () => {
 	if (!loggedIn.value) {
 		lofig.get("cookie.SIDname").then(sid => {
 			broadcastChannel.value = new BroadcastChannel(`${sid}.user_login`);
-			broadcastChannel.value.onmessage = data => {
+			broadcastChannel.value.onmessage = (data: boolean) => {
 				if (data) {
 					broadcastChannel.value.close();
 					window.location.reload();
@@ -131,7 +129,7 @@ onMounted(async () => {
 		});
 	}
 
-	document.onkeydown = (ev: any) => {
+	document.onkeydown = (ev: KeyboardEvent) => {
 		const event = ev || window.event;
 		const { keyCode } = event;
 		const shift = event.shiftKey;

+ 0 - 47
frontend/src/auth.ts

@@ -1,47 +0,0 @@
-let callbacks = [];
-const bannedCallbacks = [];
-
-export default {
-	ready: false,
-	authenticated: false,
-	username: "",
-	userId: "",
-	role: "default",
-	banned: null,
-	ban: {},
-
-	getStatus(cb) {
-		if (this.ready)
-			cb(this.authenticated, this.role, this.username, this.userId);
-		else callbacks.push(cb);
-	},
-
-	setBanned(ban) {
-		this.banned = true;
-		this.ban = ban;
-		bannedCallbacks.forEach(callback => {
-			callback(true, this.ban);
-		});
-	},
-
-	isBanned(cb) {
-		if (this.ready) return cb(false);
-		if (!this.ready && this.banned === true) return cb(true, this.ban);
-		return bannedCallbacks.push(cb);
-	},
-
-	data(authenticated, role, username, userId) {
-		this.authenticated = authenticated;
-		this.role = role;
-		this.username = username;
-		this.userId = userId;
-		this.ready = true;
-		callbacks.forEach(callback => {
-			callback(authenticated, role, username, userId);
-		});
-		bannedCallbacks.forEach(callback => {
-			callback(false);
-		});
-		callbacks = [];
-	}
-};

+ 3 - 6
frontend/src/components/modals/EditNews.vue

@@ -5,11 +5,8 @@ import DOMPurify from "dompurify";
 import Toast from "toasters";
 import { formatDistance } from "date-fns";
 import { storeToRefs } from "pinia";
-import {
-	GetNewsResponse,
-	CreateNewsResponse,
-	UpdateNewsResponse
-} from "@musare_types/actions/NewsActions";
+import { GetNewsResponse } from "@musare_types/actions/NewsActions";
+import { GenericResponse } from "@musare_types/actions/GenericActions";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useEditNewsStore } from "@/stores/editNews";
 import { useModalsStore } from "@/stores/modals";
@@ -81,7 +78,7 @@ const { inputs, save, setOriginalValue } = useForm(
 				status: values.status,
 				showToNewUsers: values.showToNewUsers
 			};
-			const cb = (res: CreateNewsResponse | UpdateNewsResponse) => {
+			const cb = (res: GenericResponse) => {
 				new Toast(res.message);
 				if (res.status === "success") resolve();
 				else reject(new Error(res.message));

+ 2 - 2
frontend/src/components/modals/ViewYoutubeVideo.vue

@@ -329,7 +329,7 @@ onMounted(() => {
 												video.value.youtubeId
 											);
 
-										setPlaybackRate(null);
+										setPlaybackRate();
 
 										drawCanvas();
 									},
@@ -429,7 +429,7 @@ onMounted(() => {
 												);
 											}
 
-											setPlaybackRate(null);
+											setPlaybackRate();
 										} else if (event.data === 2) {
 											player.value.paused = true;
 											updateMediaModalPlayingAudio(false);

+ 6 - 4
frontend/src/main.ts

@@ -73,7 +73,7 @@ app.component("PageMetadata", {
 
 app.directive("scroll", {
 	mounted(el, binding) {
-		const f = evt => {
+		const f = (evt: Event) => {
 			clearTimeout(window.scrollDebounceId);
 			window.scrollDebounceId = setTimeout(() => {
 				if (binding.value(evt, el)) {
@@ -273,7 +273,7 @@ createSocket().then(async socket => {
 			const toast =
 				typeof to.query.toast === "string"
 					? { content: to.query.toast, timeout: 20000 }
-					: to.query.toast;
+					: { ...to.query.toast };
 			new Toast(toast);
 			const { query } = to;
 			delete query.toast;
@@ -288,7 +288,9 @@ createSocket().then(async socket => {
 					next({ path: "/login" });
 				else if (
 					to.meta.permissionRequired &&
-					!userAuthStore.hasPermission(to.meta.permissionRequired)
+					!userAuthStore.hasPermission(
+						`${to.meta.permissionRequired}`
+					)
 				)
 					next({ path: "/" });
 				else if (to.meta.guestsOnly && userAuthStore.loggedIn)
@@ -395,7 +397,7 @@ createSocket().then(async socket => {
 			if (
 				meta &&
 				meta.permissionRequired &&
-				!userAuthStore.hasPermission(meta.permissionRequired)
+				!userAuthStore.hasPermission(`${meta.permissionRequired}`)
 			)
 				router.push({
 					path: "/",

+ 2 - 2
frontend/src/pages/Admin/News.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
 import { defineAsyncComponent, ref } from "vue";
 import Toast from "toasters";
-import { RemoveNewsResponse } from "@musare_types/actions/NewsActions";
+import { GenericResponse } from "@musare_types/actions/GenericActions";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useModalsStore } from "@/stores/modals";
 import { useUserAuthStore } from "@/stores/userAuth";
@@ -131,7 +131,7 @@ const remove = (id: string) => {
 	socket.dispatch(
 		"news.remove",
 		id,
-		(res: RemoveNewsResponse) => new Toast(res.message)
+		(res: GenericResponse) => new Toast(res.message)
 	);
 };
 </script>

+ 1 - 1
frontend/src/pages/Banned.vue

@@ -14,7 +14,7 @@ const { ban } = storeToRefs(userAuthStore);
 		<h4>
 			You are banned for
 			<strong>{{
-				formatDistance(new Date(ban.expiresAt), Date.now())
+				formatDistance(new Date(Number(ban.expiresAt)), Date.now())
 			}}</strong>
 		</h4>
 		<h5 class="reason">

+ 2 - 1
frontend/src/pages/Station/index.vue

@@ -371,7 +371,8 @@ const calculateTimeElapsed = () => {
 	if (playerReady.value && songDuration <= duration)
 		player.value.pauseVideo();
 	if (duration <= songDuration)
-		timeElapsed.value = utils.formatTime(duration) || "0";
+		timeElapsed.value =
+			typeof duration === "number" ? utils.formatTime(duration) : "0";
 };
 const playVideo = () => {
 	if (playerReady.value) {

+ 23 - 9
frontend/src/stores/userAuth.ts

@@ -47,7 +47,12 @@ export const useUserAuthStore = defineStore("userAuth", {
 		permissions: {}
 	}),
 	actions: {
-		register(user) {
+		register(user: {
+			username: string;
+			email: string;
+			password: string;
+			recaptchaToken: string;
+		}) {
 			return new Promise((resolve, reject) => {
 				const { username, email, password, recaptchaToken } = user;
 
@@ -140,7 +145,7 @@ export const useUserAuthStore = defineStore("userAuth", {
 				}
 			});
 		},
-		login(user) {
+		login(user: { email: string; password: string }) {
 			return new Promise((resolve, reject) => {
 				const { email, password } = user;
 
@@ -244,11 +249,14 @@ export const useUserAuthStore = defineStore("userAuth", {
 				}
 			);
 		},
-		mapUserId(data) {
+		mapUserId(data: {
+			userId: string;
+			user: { name: string; username: string };
+		}) {
 			this.userIdMap[`Z${data.userId}`] = data.user;
 			this.userIdRequested[`Z${data.userId}`] = false;
 		},
-		requestingUserId(userId) {
+		requestingUserId(userId: string) {
 			this.userIdRequested[`Z${userId}`] = true;
 			if (!this.pendingUserIdCallbacks[`Z${userId}`])
 				this.pendingUserIdCallbacks[`Z${userId}`] = [];
@@ -262,7 +270,13 @@ export const useUserAuthStore = defineStore("userAuth", {
 		clearPendingCallbacks(userId: string) {
 			this.pendingUserIdCallbacks[`Z${userId}`] = [];
 		},
-		authData(data) {
+		authData(data: {
+			loggedIn: boolean;
+			role: string;
+			username: string;
+			email: string;
+			userId: string;
+		}) {
 			this.loggedIn = data.loggedIn;
 			this.role = data.role;
 			this.username = data.username;
@@ -270,17 +284,17 @@ export const useUserAuthStore = defineStore("userAuth", {
 			this.userId = data.userId;
 			this.gotData = true;
 		},
-		banUser(ban) {
+		banUser(ban: { reason: string; expiresAt: number }) {
 			this.banned = true;
 			this.ban = ban;
 		},
-		updateUsername(username) {
+		updateUsername(username: string) {
 			this.username = username;
 		},
-		updateRole(role) {
+		updateRole(role: string) {
 			this.role = role;
 		},
-		hasPermission(permission) {
+		hasPermission(permission: string) {
 			return !!(this.permissions && this.permissions[permission]);
 		},
 		updatePermissions() {

+ 4 - 4
frontend/src/stores/userPlaylists.ts

@@ -8,16 +8,16 @@ export const useUserPlaylistsStore = defineStore("userPlaylists", {
 		playlists: []
 	}),
 	actions: {
-		setPlaylists(playlists) {
+		setPlaylists(playlists: Playlist[]) {
 			this.playlists = playlists;
 		},
-		updatePlaylists(playlists) {
+		updatePlaylists(playlists: Playlist[]) {
 			this.playlists = playlists;
 		},
-		addPlaylist(playlist) {
+		addPlaylist(playlist: Playlist) {
 			this.playlists.push(playlist);
 		},
-		removePlaylist(playlistId) {
+		removePlaylist(playlistId: string) {
 			this.playlists.forEach((playlist, index) => {
 				if (playlist._id === playlistId)
 					this.playlists.splice(index, 1);

+ 1 - 1
frontend/src/stores/viewPunishment.ts

@@ -14,7 +14,7 @@ export const useViewPunishmentStore = ({ modalUuid }: { modalUuid: string }) =>
 			}
 		}),
 		actions: {
-			init({ punishmentId }) {
+			init({ punishmentId }: { punishmentId: string }) {
 				this.punishmentId = punishmentId;
 			},
 			viewPunishment(punishment) {

+ 1 - 1
frontend/src/stores/viewReport.ts

@@ -8,7 +8,7 @@ export const useViewReportStore = ({ modalUuid }: { modalUuid: string }) =>
 			reportId: null
 		}),
 		actions: {
-			init({ reportId }) {
+			init({ reportId }: { reportId: string }) {
 				this.reportId = reportId;
 			}
 		}

+ 10 - 4
frontend/src/stores/viewYoutubeVideo.ts

@@ -58,7 +58,13 @@ export const useViewYoutubeVideoStore = ({
 			}
 		}),
 		actions: {
-			init({ videoId, youtubeId }) {
+			init({
+				videoId,
+				youtubeId
+			}: {
+				videoId: string;
+				youtubeId: string;
+			}) {
 				this.videoId = videoId;
 				this.youtubeId = youtubeId;
 			},
@@ -79,7 +85,7 @@ export const useViewYoutubeVideoStore = ({
 			loadVideoById(id) {
 				this.player.player.loadVideoById(id);
 			},
-			pauseVideo(status) {
+			pauseVideo(status: boolean) {
 				if (
 					(this.player.player && this.player.player.pauseVideo) ||
 					this.player.playVideo
@@ -89,8 +95,8 @@ export const useViewYoutubeVideoStore = ({
 				}
 				this.player.paused = status;
 			},
-			setPlaybackRate(rate) {
-				if (rate) {
+			setPlaybackRate(rate?: number) {
+				if (typeof rate === "number") {
 					this.player.playbackRate = rate;
 					this.player.player.setPlaybackRate(rate);
 				} else if (

+ 22 - 24
frontend/src/stores/websockets.ts

@@ -11,37 +11,35 @@ export const useWebsocketsStore = defineStore("websockets", {
 	}),
 	actions: {
 		createSocket(): Promise<SocketHandler> {
-			return new Promise((resolve, reject) => {
-				lofig
-					.get("backend.websocketsDomain")
-					.then(websocketsDomain => {
-						const { listeners } = this.socket.dispatcher;
+			return new Promise(resolve => {
+				lofig.get("backend.websocketsDomain").then(websocketsDomain => {
+					const { listeners } = this.socket.dispatcher;
 
-						this.socket = new SocketHandler(websocketsDomain);
+					this.socket = new SocketHandler(websocketsDomain);
 
-						// only executes if the websocket object is being replaced
-						if (listeners) {
-							// for each listener type
-							Object.keys(listeners).forEach(listenerType =>
-								// for each callback previously present for the listener type
-								listeners[listenerType].forEach(element => {
-									// add the listener back after the websocket object is reset
-									this.socket.dispatcher.addEventListener(
-										listenerType,
-										element.cb
-									);
-								})
-							);
-						}
+					// only executes if the websocket object is being replaced
+					if (listeners) {
+						// for each listener type
+						Object.keys(listeners).forEach(listenerType =>
+							// for each callback previously present for the listener type
+							listeners[listenerType].forEach(element => {
+								// add the listener back after the websocket object is reset
+								this.socket.dispatcher.addEventListener(
+									listenerType,
+									element.cb,
+									element.options
+								);
+							})
+						);
+					}
 
-						resolve(this.socket);
-					})
-					.catch(err => reject(err));
+					resolve(this.socket);
+				});
 			});
 		}
 	},
 	getters: {
-		getSocket() {
+		getSocket(): SocketHandler {
 			return this.socket;
 		}
 	}

+ 1 - 1
frontend/src/stores/whatIsNew.ts

@@ -9,7 +9,7 @@ export const useWhatIsNewStore = ({ modalUuid }: { modalUuid: string }) =>
 			news: null
 		}),
 		actions: {
-			init({ news }) {
+			init({ news }: { news: NewsModel }) {
 				this.news = news;
 			}
 		}

+ 5 - 1
frontend/src/types/global.d.ts

@@ -2,7 +2,11 @@
 /* eslint vars-on-top: 0 */
 
 declare global {
-	var lofig: any;
+	var lofig: {
+		config: object;
+		fetchConfig: () => Promise<unknown>;
+		get: (setting: string) => unknown;
+	};
 	var stationInterval: number;
 	var YT: any;
 	var stationNextSongTimeout: any;

+ 19 - 22
frontend/src/utils.ts

@@ -12,34 +12,31 @@ export default {
 			window.crypto.getRandomValues(array);
 			return (array[0] % 16).toString(16);
 		}),
-	formatTime: originalDuration => {
-		if (typeof originalDuration === "number") {
-			if (originalDuration <= 0) return "0:00";
+	formatTime: (originalDuration: number) => {
+		if (originalDuration <= 0) return "0:00";
 
-			let duration = originalDuration;
-			let hours: number | string = Math.floor(duration / (60 * 60));
-			duration -= hours * 60 * 60;
-			let minutes: number | string = Math.floor(duration / 60);
-			duration -= minutes * 60;
-			let seconds: number | string = Math.floor(duration);
+		let duration = originalDuration;
+		let hours: number | string = Math.floor(duration / (60 * 60));
+		duration -= hours * 60 * 60;
+		let minutes: number | string = Math.floor(duration / 60);
+		duration -= minutes * 60;
+		let seconds: number | string = Math.floor(duration);
 
-			if (hours === 0) {
-				hours = "";
-			}
-
-			if (hours > 0) {
-				if (minutes < 10) minutes = `0${minutes}`;
-			}
+		if (hours === 0) {
+			hours = "";
+		}
 
-			if (seconds < 10) {
-				seconds = `0${seconds}`;
-			}
+		if (hours > 0) {
+			if (minutes < 10) minutes = `0${minutes}`;
+		}
 
-			return `${hours}${hours ? ":" : ""}${minutes}:${seconds}`;
+		if (seconds < 10) {
+			seconds = `0${seconds}`;
 		}
-		return false;
+
+		return `${hours}${hours ? ":" : ""}${minutes}:${seconds}`;
 	},
-	formatTimeLong: duration => {
+	formatTimeLong: (duration: number) => {
 		if (duration <= 0) return "0 seconds";
 
 		const hours = Math.floor(duration / (60 * 60));

+ 2 - 2
frontend/src/validation.ts

@@ -7,9 +7,9 @@ export default {
 		name: /^[\p{L}0-9 .'_-]+$/u,
 		password:
 			/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~])[A-Za-z\d!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/,
-		custom: regex => new RegExp(`^[${regex}]+$`)
+		custom: (regex: string) => new RegExp(`^[${regex}]+$`)
 	},
-	isLength: (string, min, max) =>
+	isLength: (string: string, min: number, max: number) =>
 		!(
 			typeof string !== "string" ||
 			string.length < min ||

+ 6 - 2
musare.sh

@@ -411,8 +411,12 @@ case $1 in
         bcChange=$(echo "${updated}" | grep "backend/config/template.json")
         if [[ ( $2 == "auto" && -z $dbChange && -z $fcChange && -z $bcChange && -z $musareshChange ) || -z $2 ]]; then
             if [[ -n $musareshChange ]]; then
-                git checkout @\{u\} -- musare.sh
-                echo -e "${YELLOW}musare.sh has been updated, please run the update command again to continue${NC}"
+                if [[ $(git diff HEAD -- musare.sh) != "" ]]; then
+                    echo -e "${RED}musare.sh has been modified, please reset or commit these changes and run the update command again to continue.${NC}"
+                else
+                    git checkout @\{u\} -- musare.sh
+                    echo -e "${YELLOW}musare.sh has been updated, please run the update command again to continue.${NC}"
+                fi
                 exit 1
             else
                 git pull

+ 1 - 1
types/actions/BaseActions.ts → types/actions/GenericActions.ts

@@ -1,4 +1,4 @@
-export type BaseResponse = {
+export type GenericResponse = {
 	status: "success" | "error";
 	message: string;
 };

+ 3 - 6
types/actions/NewsActions.ts

@@ -1,7 +1,7 @@
-import { BaseResponse } from "./BaseActions";
+import { GenericResponse } from "./GenericActions";
 import { NewsModel } from "../models/News";
 
-type BaseNewsResponse = BaseResponse & {
+type BaseNewsResponse = GenericResponse & {
 	data: {
 		news: NewsModel;
 	};
@@ -9,11 +9,8 @@ type BaseNewsResponse = BaseResponse & {
 
 export type NewestResponse = BaseNewsResponse;
 export type GetNewsResponse = BaseNewsResponse;
-export type GetPublishedNewsResponse = BaseResponse & {
+export type GetPublishedNewsResponse = GenericResponse & {
 	data: {
 		news: NewsModel[]
 	}
 };
-export type CreateNewsResponse = BaseResponse;
-export type UpdateNewsResponse = BaseResponse;
-export type RemoveNewsResponse = BaseResponse;

+ 4 - 4
types/actions/PlaylistsActions.ts

@@ -1,17 +1,17 @@
 import { PlaylistModel, PlaylistSong } from "../models/Playlist";
-import { BaseResponse } from "./BaseActions";
+import { GenericResponse } from "./GenericActions";
 
-export type IndexMyPlaylistsResponse = BaseResponse & {
+export type IndexMyPlaylistsResponse = GenericResponse & {
 	data: {
 		playlists: (PlaylistModel & { weight: number })[];
 	};
 };
-export type AddSongToPlaylistResponse = BaseResponse & {
+export type AddSongToPlaylistResponse = GenericResponse & {
 	data: {
 		songs: PlaylistSong[];
 	};
 };
-export type RemoveSongFromPlaylistResponse = BaseResponse & {
+export type RemoveSongFromPlaylistResponse = GenericResponse & {
 	data: {
 		songs: PlaylistSong[];
 	};

+ 2 - 3
types/actions/UsersActions.ts

@@ -1,7 +1,6 @@
 import { UserPreferences } from "../models/User";
-import { BaseResponse } from "./BaseActions";
+import { GenericResponse } from "./GenericActions";
 
-export type UpdatePreferencesResponse = BaseResponse;
-export type GetPreferencesResponse = BaseResponse & {
+export type GetPreferencesResponse = GenericResponse & {
 	data: { preferences: UserPreferences };
 };