« get me outta code hell

playlist-utils.js « src - http-music - Command-line music player + utils (not a server!)
about summary refs log tree commit diff
path: root/src/playlist-utils.js
blob: 5266f1ae7b70859b7dc7d76825b98135304599a7 (plain)
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
'use strict'

function flattenPlaylist(playlist) {
  // Flattens a playlist, taking all of the non-group items (tracks) at all
  // levels in the playlist tree and returns them as a single-level array of
  // tracks.

  const groups = playlist.filter(x => Array.isArray(x[1]))
  const nonGroups = playlist.filter(x => x[1] && !(Array.isArray(x[1])))
  return groups.map(g => flattenPlaylist(g[1]))
    .reduce((a, b) => a.concat(b), nonGroups)
}

function filterPlaylistByPathString(playlist, pathString) {
  // Calls filterPlaylistByPath, taking a path string, rather than a parsed
  // path.

  return filterPlaylistByPath(playlist, parsePathString(pathString))
}

function filterPlaylistByPath(playlist, pathParts) {
  // Finds a group by following the given group path and returns it. If the
  // function encounters an item in the group path that is not found, it logs
  // a warning message and returns the group found up to that point.

  let cur = pathParts[0]

  const match = playlist.find(g => g[0] === cur || g[0] === cur + '/')

  if (match) {
    const groupContents = match[1]
    if (pathParts.length > 1) {
      const rest = pathParts.slice(1)
      return filterPlaylistByPath(groupContents, rest)
    } else {
      return match
    }
  } else {
    console.warn(`Not found: "${cur}"`)
    return playlist
  }
}

function removeGroupByPathString(playlist, pathString) {
  // Calls removeGroupByPath, taking a path string, rather than a parsed path.

  return removeGroupByPath(playlist, parsePathString(pathString))
}

function removeGroupByPath(playlist, pathParts) {
  // Removes the group at the given path from the given playlist.

  const groupToRemove = filterPlaylistByPath(playlist, pathParts)

  const parentPath = pathParts.slice(0, pathParts.length - 1)
  let parent

  if (parentPath.length === 0) {
    parent = playlist
  } else {
    parent = filterPlaylistByPath(playlist, pathParts.slice(0, -1))
  }

  const index = parent.indexOf(groupToRemove)

  if (index >= 0) {
    parent.splice(index, 1)
  } else {
    console.error(
      'Group ' + pathParts.join('/') + ' doesn\'t exist, so we can\'t ' +
      'explicitly ignore it.'
    )
  }
}

function getPlaylistTreeString(playlist, showTracks = false) {
  function recursive(group) {
    const groups = group.filter(x => Array.isArray(x[1]))
    const nonGroups = group.filter(x => x[1] && !(Array.isArray(x[1])))

    const childrenString = groups.map(g => {
      const groupString = recursive(g[1])

      if (groupString) {
        const indented = groupString.split('\n').map(l => '| ' + l).join('\n')
        return '\n' + g[0] + '\n' + indented
      } else {
        return g[0]
      }
    }).join('\n')

    let trackString = ''
    if (showTracks) {
      trackString = nonGroups.map(g => g[0]).join('\n')
    }

    if (tracksString && childrenString) {
      return tracksString + '\n' + childrenString
    } else if (childrenString) {
      return childrenString
    } else if (tracksString) {
      return tracksString
    } else {
      return ''
    }
  }

  return recursive(playlist)
}

function parsePathString(pathString) {
  const pathParts = pathString.split('/')
  return pathParts
}

module.exports = {
  flattenPlaylist,
  filterPlaylistByPathString, filterPlaylistByPath,
  ignoreGroupByPathString, ignoreGroupByPath,
  parsePathString
}