Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 49 additions & 34 deletions main/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
createPlaylist,
getAlbumWithSongs,
getAlbums,
getLibraryItems,
getLibraryStats,
getPlaylistWithSongs,
getPlaylists,
Expand Down Expand Up @@ -51,7 +52,7 @@ const initializeLibrary = async () => {
await initializeData(settings.musicFolder);
}
} catch (error) {
console.error('Error initializing library:', error);
console.error("Error initializing library:", error);
}
};

Expand Down Expand Up @@ -113,43 +114,46 @@ const initializeLibrary = async () => {

// @hiaaryan: Initialize Discord RPC
const client = new Client({
clientId: "1243707416588320800"
clientId: "1243707416588320800",
});

ipcMain.on("set-rpc-state", async (_, { details, state, seek, duration, cover }) => {
let startTimestamp, endTimestamp;
ipcMain.on(
"set-rpc-state",
async (_, { details, state, seek, duration, cover }) => {
let startTimestamp, endTimestamp;

if (duration && seek) {
const now = Math.ceil(Date.now());
startTimestamp = now - (seek * 1000);
endTimestamp = now + ((duration - seek) * 1000);
}
if (duration && seek) {
const now = Math.ceil(Date.now());
startTimestamp = now - seek * 1000;
endTimestamp = now + (duration - seek) * 1000;
}

const setActivity = {
details,
state,
largeImageKey: cover,
instance: false,
type: 2,
startTimestamp: startTimestamp,
endTimestamp: endTimestamp,
buttons: [
{ label: "Support Project", url: "https://github.com/hiaaryan/wora" },
]
};

if (!client.isConnected) {
try {
await client.login();
} catch (error) {
console.error('Error logging into Discord:', error);
const setActivity = {
details,
state,
largeImageKey: cover,
instance: false,
type: 2,
startTimestamp: startTimestamp,
endTimestamp: endTimestamp,
buttons: [
{ label: "Support Project", url: "https://github.com/hiaaryan/wora" },
],
};

if (!client.isConnected) {
try {
await client.login();
} catch (error) {
console.error("Error logging into Discord:", error);
}
}
}

if (client.isConnected) {
client.user.setActivity(setActivity);
}
});
if (client.isConnected) {
client.user.setActivity(setActivity);
}
},
);

// @hiaaryan: Called to Rescan Library
ipcMain.handle("rescanLibrary", async () => {
Expand Down Expand Up @@ -267,6 +271,11 @@ ipcMain.handle("getRandomLibraryItems", async () => {
return libraryItems;
});

ipcMain.handle("getLibraryItems", async () => {
const libraryItems = await getLibraryItems();
return libraryItems;
});

ipcMain.handle("updatePlaylist", async (_, data: any) => {
const playlist = await updatePlaylist(data);
return playlist;
Expand Down Expand Up @@ -294,7 +303,10 @@ ipcMain.handle("updateSettings", async (_, data: any) => {
});

ipcMain.handle("uploadProfilePicture", async (_, file) => {
const uploadsDir = path.join(app.getPath("userData"), "utilities/uploads/profile");
const uploadsDir = path.join(
app.getPath("userData"),
"utilities/uploads/profile",
);
if (!fs.existsSync(uploadsDir)) {
fs.mkdirSync(uploadsDir, { recursive: true });
}
Expand All @@ -308,7 +320,10 @@ ipcMain.handle("uploadProfilePicture", async (_, file) => {
});

ipcMain.handle("uploadPlaylistCover", async (_, file) => {
const uploadsDir = path.join(app.getPath("userData"), "utilities/uploads/playlists");
const uploadsDir = path.join(
app.getPath("userData"),
"utilities/uploads/playlists",
);
if (!fs.existsSync(uploadsDir)) {
fs.mkdirSync(uploadsDir, { recursive: true });
}
Expand Down
122 changes: 95 additions & 27 deletions main/helpers/db/connectDB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,29 @@ import path from "path";
import { BetterSQLite3Database, drizzle } from "drizzle-orm/better-sqlite3";
import * as schema from "./schema";
import { sqlite } from "./createDB";
import { app } from 'electron';
import { app } from "electron";

const db: BetterSQLite3Database<typeof schema> = drizzle(sqlite, { schema });

const APP_DATA = app.getPath('userData');
const ART_DIR = path.join(APP_DATA, 'utilities/uploads/covers');
const APP_DATA = app.getPath("userData");
const ART_DIR = path.join(APP_DATA, "utilities/uploads/covers");

const audioExtensions = [
".mp3", ".mpeg", ".opus", ".ogg", ".oga", ".wav", ".aac",
".caf", ".m4a", ".m4b", ".mp4", ".weba", ".webm", ".dolby", ".flac"
".mp3",
".mpeg",
".opus",
".ogg",
".oga",
".wav",
".aac",
".caf",
".m4a",
".m4b",
".mp4",
".weba",
".webm",
".dolby",
".flac",
];

const imageExtensions = [".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp"];
Expand All @@ -25,7 +38,11 @@ function findFirstImageInDirectory(dir: string): string | null {
for (const file of files) {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isFile() && imageExtensions.includes(path.extname(file).toLowerCase())) {
if (
stat.isFile() &&
imageExtensions.includes(path.extname(file).toLowerCase()) &&
path.basename(filePath)[0] !== "."
) {
return filePath;
}
}
Expand All @@ -38,9 +55,13 @@ function readFilesRecursively(dir: string): string[] {
list.forEach((file) => {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
console.log(path.basename(filePath));
if (stat && stat.isDirectory()) {
results = results.concat(readFilesRecursively(filePath));
} else if (audioExtensions.includes(path.extname(filePath).toLowerCase())) {
} else if (
audioExtensions.includes(path.extname(filePath).toLowerCase()) &&
path.basename(filePath)[0] !== "."
) {
results.push(filePath);
}
});
Expand All @@ -50,7 +71,9 @@ function readFilesRecursively(dir: string): string[] {
export const getLibraryStats = async () => {
const songCount = await db.select({ count: sql`count(*)` }).from(songs);
const albumCount = await db.select({ count: sql`count(*)` }).from(albums);
const playlistCount = await db.select({ count: sql`count(*)` }).from(playlists);
const playlistCount = await db
.select({ count: sql`count(*)` })
.from(playlists);

return {
songs: songCount[0].count,
Expand Down Expand Up @@ -197,7 +220,10 @@ export const isSongFavorite = async (file: string) => {
if (!song) return false;

const isFavourite = await db.query.playlistSongs.findFirst({
where: and(eq(playlistSongs.playlistId, 1), eq(playlistSongs.songId, song.id)),
where: and(
eq(playlistSongs.playlistId, 1),
eq(playlistSongs.songId, song.id),
),
});

return !!isFavourite;
Expand All @@ -207,7 +233,9 @@ export const addToFavourites = async (songId: number) => {
const existingEntry = await db
.select()
.from(playlistSongs)
.where(and(eq(playlistSongs.playlistId, 1), eq(playlistSongs.songId, songId)));
.where(
and(eq(playlistSongs.playlistId, 1), eq(playlistSongs.songId, songId)),
);

if (!existingEntry[0]) {
await db.insert(playlistSongs).values({
Expand All @@ -217,7 +245,9 @@ export const addToFavourites = async (songId: number) => {
} else {
await db
.delete(playlistSongs)
.where(and(eq(playlistSongs.playlistId, 1), eq(playlistSongs.songId, songId)));
.where(
and(eq(playlistSongs.playlistId, 1), eq(playlistSongs.songId, songId)),
);
}
};

Expand Down Expand Up @@ -252,7 +282,10 @@ export const searchDB = async (query: string) => {

export const addSongToPlaylist = async (playlistId: number, songId: number) => {
const checkIfExists = await db.query.playlistSongs.findFirst({
where: and(eq(playlistSongs.playlistId, playlistId), eq(playlistSongs.songId, songId)),
where: and(
eq(playlistSongs.playlistId, playlistId),
eq(playlistSongs.songId, songId),
),
});

if (checkIfExists) return false;
Expand All @@ -265,10 +298,18 @@ export const addSongToPlaylist = async (playlistId: number, songId: number) => {
return true;
};

export const removeSongFromPlaylist = async (playlistId: number, songId: number) => {
export const removeSongFromPlaylist = async (
playlistId: number,
songId: number,
) => {
await db
.delete(playlistSongs)
.where(and(eq(playlistSongs.playlistId, playlistId), eq(playlistSongs.songId, songId)));
.where(
and(
eq(playlistSongs.playlistId, playlistId),
eq(playlistSongs.songId, songId),
),
);

return true;
};
Expand All @@ -292,12 +333,29 @@ export const getRandomLibraryItems = async () => {
};
};

export const getLibraryItems = async () => {
const albumsList = await db
.select()
.from(albums)
.orderBy(sql`RANDOM()`);

const songsList = await db.query.songs.findMany({
with: { album: true },
//orderBy: sql`RANDOM()`,
});

return {
albums: albumsList,
songs: songsList,
};
};

export const initializeData = async (musicFolder: string) => {
const currentFiles = readFilesRecursively(musicFolder);
const dbFiles = await db.select().from(songs);

const deletedFiles = dbFiles.filter(
(dbFile) => !currentFiles.includes(dbFile.filePath)
(dbFile) => !currentFiles.includes(dbFile.filePath),
);

if (deletedFiles.length > 0) {
Expand All @@ -311,9 +369,16 @@ export const initializeData = async (musicFolder: string) => {

for (const file of currentFiles) {
const dbFile = dbFiles.find((dbFile) => dbFile.filePath === file);
const metadata = await parseFile(file, {
skipPostHeaders: true,
});

let metadata;

try {
metadata = await parseFile(file, {
skipPostHeaders: true,
});
} catch (error) {
continue;
}

let artPath;

Expand All @@ -323,7 +388,10 @@ export const initializeData = async (musicFolder: string) => {
if (albumImage) {
const imageData = fs.readFileSync(albumImage);
const imageExt = path.extname(albumImage).slice(1);
const hash = require('crypto').createHash('md5').update(imageData).digest('hex');
const hash = require("crypto")
.createHash("md5")
.update(imageData)
.digest("hex");
artPath = path.join(ART_DIR, `${hash}.${imageExt}`);

if (!fs.existsSync(artPath)) {
Expand All @@ -334,8 +402,11 @@ export const initializeData = async (musicFolder: string) => {
const cover = selectCover(metadata.common.picture);

if (cover) {
const hash = require('crypto').createHash('md5').update(cover.data).digest('hex');
artPath = path.join(ART_DIR, `${hash}.${cover.format.split('/')[1]}`);
const hash = require("crypto")
.createHash("md5")
.update(cover.data)
.digest("hex");
artPath = path.join(ART_DIR, `${hash}.${cover.format.split("/")[1]}`);

if (!fs.existsSync(artPath)) {
await fs.promises.mkdir(ART_DIR, { recursive: true });
Expand Down Expand Up @@ -370,7 +441,7 @@ export const initializeData = async (musicFolder: string) => {
// @hiaaryan: Update Album if Artist or Cover is different
if (
album.artist !==
(metadata.common.albumartist || metadata.common.artist) ||
(metadata.common.albumartist || metadata.common.artist) ||
album.year !== metadata.common.year ||
album.cover !== artPath
) {
Expand Down Expand Up @@ -451,11 +522,8 @@ export const initializeData = async (musicFolder: string) => {
.where(eq(settings.id, 1));

if (existingSettings[0]) {
await db
.update(settings)
.set({ musicFolder })
.where(eq(settings.id, 1));
await db.update(settings).set({ musicFolder }).where(eq(settings.id, 1));
} else {
await db.insert(settings).values({ musicFolder });
}
};
};
Loading