File size: 3,020 Bytes
b50804a
4061cfd
 
b50804a
 
146f069
b50804a
 
4a3e3b3
b50804a
 
09b0629
b50804a
050996b
 
 
 
 
 
 
4061cfd
0861f14
6486919
0861f14
6486919
4061cfd
b50804a
4061cfd
b50804a
 
4061cfd
0861f14
 
 
 
 
 
6486919
 
 
0861f14
 
6486919
4061cfd
6486919
 
 
 
8fb2fb5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6486919
 
 
 
4061cfd
 
6486919
b50804a
 
 
09b0629
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
const express = require('express');
const mm = require('music-metadata');
const util = require('util');
const fs = require('fs');
const path = require('path');
const sharp = require('sharp');

const app = express();
const PORT = process.env.PORT || 7860;

app.use(express.static('public'));
app.use('/music', express.static('music'));

const SUPPORTED_FORMATS = ['.mp3', '.mp4', '.wav', '.flac', '.ogg', '.opus']; // Add or remove formats as needed

function isSupportedFormat(filename) {
  const ext = path.extname(filename).toLowerCase();
  return SUPPORTED_FORMATS.includes(ext);
}

app.get('/tracks', async (req, res) => {
    const searchQuery = (req.query.search || '').toLowerCase();
    const pageNumber = parseInt(req.query.page) || 1;
    const pageSize = 5;

    fs.readdir('music', async (err, files) => {
        if (err) {
            console.error('Error reading music directory', err);
            return res.sendStatus(500);
        }

        // If there's a search query, filter files by it
        let filteredFiles = files.filter(file => isSupportedFormat(file));
        if (searchQuery) {
          filteredFiles = filteredFiles.filter(file => file.toLowerCase().includes(searchQuery));
        }

        const pageStart = (pageNumber - 1) * pageSize;
        const pageEnd = pageStart + pageSize;
        
        // Slice files for pagination after filtering, ONLY if not searching. If searching, ignore pagination and send first 5 results.
        const pagedFiles = filteredFiles.slice(searchQuery ? 0 : pageStart, searchQuery ? pageSize : pageEnd);

        const trackDetails = [];
        for (const file of pagedFiles) {
            const filePath = path.join(__dirname, 'music', file);
            try {
                const metadata = await mm.parseFile(filePath, { native: true });
              let artwork = '';
// Fallback path for default icon
const fallbackIconPath = path.join(__dirname, 'music', 'icon.png');

try {
  let imageBuffer;
  if (metadata.common.picture && metadata.common.picture[0]) {
    imageBuffer = await sharp(metadata.common.picture[0].data)
      .resize(256, 256, { fit: 'inside' })
      .toBuffer();
  } else {
    // Use the default icon if no album art is present
    imageBuffer = await sharp(fallbackIconPath)
      .resize(256, 256, { fit: 'inside' })
      .toBuffer();
  }

  // Determine the image format
  const imageFormat = metadata.common.picture && metadata.common.picture[0] ? metadata.common.picture[0].format : 'image/png';
  
  artwork = `data:${imageFormat};base64,${imageBuffer.toString('base64')}`;
} catch (e) {
  console.error(`Error processing artwork for file: ${file}`, e);
}
                trackDetails.push({filename: file, artwork});
            } catch (error) {
                console.error(`Error reading metadata for file: ${file}`, error);
            }
        }

        res.json({tracks: trackDetails, total: filteredFiles.length});
    });
});

app.listen(PORT, () => console.log(`Server running on port ${PORT}`));