WIP: tempoaray DB implementation.
This commit is contained in:
parent
87202437a8
commit
8788015c4f
@ -1,4 +1,4 @@
|
|||||||
import std/json, std/jsonutils, std/os, std/strtabs, std/tables, std/times
|
import std/[logging, json, jsonutils, options, os, tables, times]
|
||||||
import timeutils, uuids, zero_functional
|
import timeutils, uuids, zero_functional
|
||||||
|
|
||||||
import ./models
|
import ./models
|
||||||
@ -10,7 +10,7 @@ type
|
|||||||
bookmarks: TableRef[UUID, Bookmark]
|
bookmarks: TableRef[UUID, Bookmark]
|
||||||
mediaFiles: TableRef[UUID, MediaFile]
|
mediaFiles: TableRef[UUID, MediaFile]
|
||||||
playlists: TableRef[UUID, Playlist]
|
playlists: TableRef[UUID, Playlist]
|
||||||
tags: StringTableRef
|
tags: TableRef[string, Option[string]]
|
||||||
|
|
||||||
albumsToMediaFiles: TableRef[UUID, seq[UUID]]
|
albumsToMediaFiles: TableRef[UUID, seq[UUID]]
|
||||||
artistsToMediaFiles: TableRef[UUID, seq[UUID]]
|
artistsToMediaFiles: TableRef[UUID, seq[UUID]]
|
||||||
@ -18,128 +18,390 @@ type
|
|||||||
playlistsToMediaFiles: TableRef[UUID, seq[UUID]]
|
playlistsToMediaFiles: TableRef[UUID, seq[UUID]]
|
||||||
tagsAndMediaFiles: seq[tuple[tagName: string, mediaFileId: UUID]]
|
tagsAndMediaFiles: seq[tuple[tagName: string, mediaFileId: UUID]]
|
||||||
|
|
||||||
|
mediaFileHashToId: TableRef[string, UUID]
|
||||||
|
|
||||||
WdiwtltDb* = ref object
|
WdiwtltDb* = ref object
|
||||||
jsonFilePath: string
|
jsonFilePath: string
|
||||||
root: DbRoot
|
root: DbRoot
|
||||||
|
|
||||||
## API Contract
|
proc debug*(db: WdiwtltDb): string =
|
||||||
|
"\p\talbums: " & $db.root.albums &
|
||||||
|
"\p\tartists: " & $db.root.artists &
|
||||||
|
"\p\tbookmarks: " & $db.root.bookmarks &
|
||||||
|
"\p\tmediaFiles: " & $db.root.mediaFiles &
|
||||||
|
"\p\tplaylists: " & $db.root.playlists &
|
||||||
|
"\p\ttags: " & $db.root.tags &
|
||||||
|
"\p\talbumsToMediaFiles: " & $db.root.albumsToMediaFiles &
|
||||||
|
"\p\tartistsToMediaFiles: " & $db.root.artistsToMediaFiles &
|
||||||
|
"\p\tartistsAndAlbums: " & $db.root.artistsAndAlbums &
|
||||||
|
"\p\tplaylistsToMediaFiles: " & $db.root.playlistsToMediaFiles &
|
||||||
|
"\p\ttagsAndMediaFiles: " & $db.root.tagsAndMediaFiles &
|
||||||
|
"\p\tmediaFileHashToId: " & $db.root.mediaFileHashToId & "\p"
|
||||||
|
|
||||||
|
## ========================================================================= ##
|
||||||
|
## API Contract ##
|
||||||
|
## ========================================================================= ##
|
||||||
proc initDb*(path: string): WdiwtltDb;
|
proc initDb*(path: string): WdiwtltDb;
|
||||||
proc loadDb*(path: string): WdiwtltDb;
|
proc loadDb*(path: string): WdiwtltDb;
|
||||||
proc persist*(db: WdiwtltDb): void;
|
proc persist*(db: WdiwtltDb): void;
|
||||||
|
|
||||||
proc delete*(db: WdiwtltDb, a: Album);
|
## Albums
|
||||||
proc delete*(db: WdiwtltDb, a: Artist);
|
## --------------------
|
||||||
proc delete*(db: WdiwtltDb, b: Bookmark);
|
proc add*(db: WdiwtltDb, a: Album);
|
||||||
proc delete*(db: WdiwtltDb, mf: MediaFile);
|
proc remove*(db: WdiwtltDb, a: Album);
|
||||||
proc delete*(db: WdiwtltDb, p: Playlist);
|
proc update*(db: WdiwtltDb, a: Album);
|
||||||
proc delete*(db: WdiwtltDb, t: Tag);
|
|
||||||
|
|
||||||
|
proc findAlbumsByArtist*(db: WdiwtltDb, a: Artist): seq[Album];
|
||||||
|
proc findAlbumsByName*(db: WdiwtltDb, name: string): seq[Album];
|
||||||
|
|
||||||
|
proc add*(db: WdiwtltDb, a: Album, mf: MediaFile);
|
||||||
proc remove*(db: WdiwtltDb, a: Album, mf: MediaFile);
|
proc remove*(db: WdiwtltDb, a: Album, mf: MediaFile);
|
||||||
proc remove*(db: WdiwtltDb, a: Artist, mf: MediaFile);
|
|
||||||
proc remove*(db: WdiwtltDb, artist: Artist, album: Album);
|
|
||||||
|
|
||||||
|
## Artists
|
||||||
|
## --------------------
|
||||||
|
proc add*(db: WdiwtltDb, a: Artist);
|
||||||
|
proc remove*(db: WdiwtltDb, a: Artist);
|
||||||
|
proc update*(db: WdiwtltDb, a: Artist);
|
||||||
|
|
||||||
|
proc findArtistsByAlbum*(db: WdiwtltDb, a: Album): seq[Artist];
|
||||||
|
proc findArtistsByName*(db: WdiwtltDb, name: string): seq[Artist];
|
||||||
|
|
||||||
|
proc add*(db: WdiwtltDb, a: Artist, mf: MediaFile);
|
||||||
|
proc remove*(db: WdiwtltDb, a: Artist, mf: MediaFile);
|
||||||
|
|
||||||
|
proc isAssociated*(db: WdiwtltDb, artist: Artist, album: Album): bool;
|
||||||
|
proc associate*(db: WdiwtltDb, artist: Artist, album: Album);
|
||||||
|
proc disassociate*(db: WdiwtltDb, artist: Artist, album: Album);
|
||||||
|
|
||||||
|
## Bookmarks
|
||||||
|
## --------------------
|
||||||
|
proc add*(db: WdiwtltDb, b: Bookmark);
|
||||||
|
proc update*(db: WdiwtltDb, b: Bookmark);
|
||||||
|
proc remove*(db: WdiwtltDb, b: Bookmark);
|
||||||
|
|
||||||
|
## Media Files
|
||||||
|
## --------------------
|
||||||
|
proc add*(db: WdiwtltDb, mf: MediaFile);
|
||||||
|
proc remove*(db: WdiwtltDb, mf: MediaFile);
|
||||||
|
proc update*(db: WdiwtltDb, mf: MediaFile);
|
||||||
|
proc findMediaFilesByAlbum*(db: WdiwtltDb, a: Album): seq[MediaFile];
|
||||||
|
proc findMediaFilesByArtist*(db: WdiwtltDb, a: Artist): seq[MediaFile];
|
||||||
|
proc findMediaFileByHash*(db: WdiwtltDb, hash: string): Option[MediaFile];
|
||||||
|
|
||||||
|
## Playlists
|
||||||
|
## --------------------
|
||||||
|
proc add*(db: WdiwtltDb, p: Playlist);
|
||||||
|
proc remove*(db: WdiwtltDb, p: Playlist);
|
||||||
|
proc update*(db: WdiwtltDb, p: Playlist);
|
||||||
|
|
||||||
|
## Tags
|
||||||
|
## --------------------
|
||||||
|
proc add*(db: WdiwtltDb, t: Tag);
|
||||||
|
proc remove*(db: WdiwtltDb, t: Tag);
|
||||||
|
proc update*(db: WdiwtltDb, t: Tag);
|
||||||
|
|
||||||
|
## Housekeeping
|
||||||
|
## --------------------
|
||||||
proc pruneStalePlaylists*(db: WdiwtltDb, ts: DateTime);
|
proc pruneStalePlaylists*(db: WdiwtltDb, ts: DateTime);
|
||||||
proc pruneStaleBookmarks*(db: WdiwtltDb, ts: DateTime);
|
proc pruneStaleBookmarks*(db: WdiwtltDb, ts: DateTime);
|
||||||
proc removeEmptyAlbums*(db: WdiwtltDb): void;
|
proc removeEmptyAlbums*(db: WdiwtltDb): void;
|
||||||
proc removeEmptyArtists*(db: WdiwtltDb): void;
|
proc removeEmptyArtists*(db: WdiwtltDb): void;
|
||||||
proc removeEmptyPlaylists*(db: WdiwtltDb): void;
|
proc removeEmptyPlaylists*(db: WdiwtltDb): void;
|
||||||
|
|
||||||
|
proc toJsonHook(t: TableRef[UUID, Album]): JsonNode;
|
||||||
|
proc fromJsonHook(t: var TableRef[UUID, Album], n: JsonNode);
|
||||||
|
proc toJsonHook(t: TableRef[UUID, Artist]): JsonNode;
|
||||||
|
proc fromJsonHook(t: var TableRef[UUID, Artist], n: JsonNode);
|
||||||
|
proc toJsonHook(t: TableRef[UUID, Bookmark]): JsonNode;
|
||||||
|
proc fromJsonHook(t: var TableRef[UUID, Bookmark], n: JsonNode);
|
||||||
|
proc toJsonHook(t: TableRef[UUID, MediaFile]): JsonNode;
|
||||||
|
proc fromJsonHook(t: var TableRef[UUID, MediaFile], n: JsonNode);
|
||||||
|
proc toJsonHook(t: TableRef[UUID, Playlist]): JsonNode;
|
||||||
|
proc fromJsonHook(t: var TableRef[UUID, Playlist], n: JsonNode);
|
||||||
|
proc toJsonHook(t: TableRef[UUID, seq[UUID]]): JsonNode;
|
||||||
|
proc fromJsonHook(t: var TableRef[UUID, seq[UUID]], n: JsonNode);
|
||||||
|
proc toJsonHook(uuid: UUID): JsonNode;
|
||||||
|
proc fromJsonHook(u: var UUID, node: JsonNode);
|
||||||
|
proc toJsonHook(dt: DateTime): JsonNode;
|
||||||
|
proc fromJsonHook(dt: var DateTime, node: JsonNode);
|
||||||
|
|
||||||
|
|
||||||
|
## ========================================================================= ##
|
||||||
|
## API Implementation ##
|
||||||
|
## ========================================================================= ##
|
||||||
## Internals
|
## Internals
|
||||||
|
## --------------------
|
||||||
|
proc toJsonHook(t: TableRef[UUID, Album]): JsonNode =
|
||||||
|
result = newJObject()
|
||||||
|
for k, v in t.pairs: result[$k] = toJson(v)
|
||||||
|
|
||||||
|
proc fromJsonHook(t: var TableRef[UUID, Album], n: JsonNode) =
|
||||||
|
for k in n.keys:
|
||||||
|
var a: Album
|
||||||
|
fromJson(a, n[k])
|
||||||
|
t[parseUUID(k)] = a
|
||||||
|
|
||||||
|
proc toJsonHook(t: TableRef[UUID, Artist]): JsonNode =
|
||||||
|
result = newJObject()
|
||||||
|
for k, v in t.pairs: result[$k] = toJson(v)
|
||||||
|
|
||||||
|
proc fromJsonHook(t: var TableRef[UUID, Artist], n: JsonNode) =
|
||||||
|
for k in n.keys:
|
||||||
|
var a: Artist
|
||||||
|
fromJson(a, n[k])
|
||||||
|
t[parseUUID(k)] = a
|
||||||
|
|
||||||
|
proc toJsonHook(t: TableRef[UUID, Bookmark]): JsonNode =
|
||||||
|
result = newJObject()
|
||||||
|
for k, v in t.pairs: result[$k] = toJson(v)
|
||||||
|
|
||||||
|
proc fromJsonHook(t: var TableRef[UUID, Bookmark], n: JsonNode) =
|
||||||
|
for k in n.keys:
|
||||||
|
var b: Bookmark
|
||||||
|
fromJson(b, n[k])
|
||||||
|
t[parseUUID(k)] = b
|
||||||
|
|
||||||
|
proc toJsonHook(t: TableRef[UUID, MediaFile]): JsonNode =
|
||||||
|
result = newJObject()
|
||||||
|
for k, v in t.pairs: result[$k] = toJson(v)
|
||||||
|
|
||||||
|
proc fromJsonHook(t: var TableRef[UUID, MediaFile], n: JsonNode) =
|
||||||
|
for k in n.keys:
|
||||||
|
var mf: MediaFile
|
||||||
|
fromJson(mf, n[k])
|
||||||
|
t[parseUUID(k)] = mf
|
||||||
|
|
||||||
|
proc toJsonHook(t: TableRef[UUID, Playlist]): JsonNode =
|
||||||
|
result = newJObject()
|
||||||
|
for k, v in t.pairs: result[$k] = toJson(v)
|
||||||
|
|
||||||
|
proc fromJsonHook(t: var TableRef[UUID, Playlist], n: JsonNode) =
|
||||||
|
for k in n.keys:
|
||||||
|
var p: Playlist
|
||||||
|
fromJson(p, n[k])
|
||||||
|
t[parseUUID(k)] = p
|
||||||
|
|
||||||
|
proc toJsonHook(t: TableRef[UUID, seq[UUID]]): JsonNode =
|
||||||
|
result = newJObject()
|
||||||
|
for k, v in t.pairs: result[$k] = toJson(v)
|
||||||
|
|
||||||
|
proc fromJsonHook(t: var TableRef[UUID, seq[UUID]], n: JsonNode) =
|
||||||
|
for k in n.keys:
|
||||||
|
var s: seq[UUID]
|
||||||
|
fromJson(s, n[k])
|
||||||
|
t[parseUUID(k)] = s
|
||||||
|
|
||||||
proc toJsonHook(uuid: UUID): JsonNode = %($uuid)
|
proc toJsonHook(uuid: UUID): JsonNode = %($uuid)
|
||||||
proc fromJsonHook(u: var UUID,node: JsonNode) =
|
proc fromJsonHook(u: var UUID, node: JsonNode) =
|
||||||
u = parseUUID(node.getStr)
|
u = parseUUID(node.getStr)
|
||||||
|
|
||||||
proc toJsonHook(dt: DateTime): JsonNode = %(dt.formatIso8601)
|
proc toJsonHook(dt: DateTime): JsonNode = %(dt.formatIso8601)
|
||||||
proc fromJsonHook(dt: var DateTime, node: JsonNode) =
|
proc fromJsonHook(dt: var DateTime, node: JsonNode) =
|
||||||
dt = parseIso8601(node.getStr)
|
dt = parseIso8601(node.getStr)
|
||||||
|
|
||||||
## API Implementation
|
|
||||||
proc initDb*(path: string): WdiwtltDb =
|
proc initDbRoot(): DbRoot =
|
||||||
WdiwtltDb(
|
DbRoot(
|
||||||
jsonFilePath: path,
|
|
||||||
root: DbRoot(
|
|
||||||
albums: newTable[UUID, Album](),
|
albums: newTable[UUID, Album](),
|
||||||
artists: newTable[UUID, Artist](),
|
artists: newTable[UUID, Artist](),
|
||||||
bookmarks: newTable[UUID, Bookmark](),
|
bookmarks: newTable[UUID, Bookmark](),
|
||||||
mediaFiles: newTable[UUID, MediaFile](),
|
mediaFiles: newTable[UUID, MediaFile](),
|
||||||
playlists: newTable[UUID, Playlist](),
|
playlists: newTable[UUID, Playlist](),
|
||||||
tags: newStringTable(),
|
tags: newTable[string, Option[string]](),
|
||||||
albumsToMediaFiles: newTable[UUID, seq[UUID]](),
|
albumsToMediaFiles: newTable[UUID, seq[UUID]](),
|
||||||
artistsToMediaFiles: newTable[UUID, seq[UUID]](),
|
artistsToMediaFiles: newTable[UUID, seq[UUID]](),
|
||||||
artistsAndAlbums: @[],
|
artistsAndAlbums: @[],
|
||||||
playlistsToMediaFiles: newTable[UUID, seq[UUID]](),
|
playlistsToMediaFiles: newTable[UUID, seq[UUID]](),
|
||||||
tagsAndMediaFiles: @[]
|
tagsAndMediaFiles: @[],
|
||||||
))
|
mediaFileHashToId: newTable[string, UUID]())
|
||||||
|
|
||||||
|
proc initDb*(path: string): WdiwtltDb =
|
||||||
|
WdiwtltDb(
|
||||||
|
jsonFilePath: path,
|
||||||
|
root: initDbRoot())
|
||||||
|
|
||||||
proc loadDb*(path: string): WdiwtltDb =
|
proc loadDb*(path: string): WdiwtltDb =
|
||||||
if not fileExists(path):
|
if not fileExists(path):
|
||||||
raise newException(Exception, "Unable to open database file '" & path & "'")
|
raise newException(Exception, "Unable to open database file '" & path & "'")
|
||||||
|
|
||||||
let jsonRoot = parseJson(path)
|
let jsonRoot = parseJson(path.readFile)
|
||||||
var root: DbRoot
|
var root: DbRoot = initDbRoot()
|
||||||
root.fromJson(jsonRoot)
|
root.fromJson(jsonRoot)
|
||||||
|
|
||||||
|
debug "loaded DB"
|
||||||
result = WdiwtltDb(
|
result = WdiwtltDb(
|
||||||
jsonFilePath: path,
|
jsonFilePath: path,
|
||||||
root: root)
|
root: root)
|
||||||
|
debug result.debug
|
||||||
|
|
||||||
proc persist*(db: WdiwtltDb): void =
|
proc persist*(db: WdiwtltDb): void =
|
||||||
let jsonRoot = db.root.toJson
|
let jsonRoot = db.root.toJson
|
||||||
db.jsonFilePath.writeFile($jsonRoot)
|
db.jsonFilePath.writeFile($jsonRoot)
|
||||||
|
|
||||||
proc delete*(db: WdiwtltDb, a: Album) =
|
## Albums
|
||||||
|
## --------------------
|
||||||
|
proc add*(db: WdiwtltDb, a: Album) = db.root.albums[a.id] = a
|
||||||
|
|
||||||
|
proc remove*(db: WdiwtltDb, a: Album) =
|
||||||
db.root.albums.del(a.id)
|
db.root.albums.del(a.id)
|
||||||
db.root.albumsToMediaFiles.del(a.id)
|
db.root.albumsToMediaFiles.del(a.id)
|
||||||
db.root.artistsAndAlbums =
|
db.root.artistsAndAlbums =
|
||||||
db.root.artistsAndAlbums --> filter(it.albumId != a.id)
|
db.root.artistsAndAlbums --> filter(it.albumId != a.id)
|
||||||
|
|
||||||
proc delete*(db: WdiwtltDb, a: Artist) =
|
proc update*(db: WdiwtltDb, a: Album) = db.add(a)
|
||||||
|
|
||||||
|
proc findAlbumsByArtist*(db: WdiwtltDb, a: Artist): seq[Album] =
|
||||||
|
db.root.artistsAndAlbums -->
|
||||||
|
filter(it.artistId == a.id and db.root.artists.contains(a.id)).
|
||||||
|
map(db.root.albums[it.albumId])
|
||||||
|
|
||||||
|
proc findAlbumsByName*(db: WdiwtltDb, name: string): seq[Album] =
|
||||||
|
result = @[]
|
||||||
|
for a in db.root.albums.values:
|
||||||
|
if a.name == name: result.add(a)
|
||||||
|
|
||||||
|
proc add*(db: WdiwtltDb, a: Album, mf: MediaFile) =
|
||||||
|
if not db.root.albumsToMediaFiles.contains(a.id):
|
||||||
|
db.root.albumsToMediaFiles[a.id] = @[mf.id]
|
||||||
|
else:
|
||||||
|
let idsInAlbum = db.root.albumsToMediaFiles[a.id]
|
||||||
|
if not idsInAlbum.contains(mf.id):
|
||||||
|
db.root.albumsToMediaFiles[a.id].add(mf.id)
|
||||||
|
|
||||||
|
proc remove*(db: WdiwtltDb, a: Album, mf: MediaFile) =
|
||||||
|
if db.root.albumsToMediaFiles.contains(a.id):
|
||||||
|
db.root.albumsToMediaFiles[a.id] =
|
||||||
|
db.root.albumsToMediaFiles[a.id] --> filter(it != mf.id)
|
||||||
|
|
||||||
|
## Artists
|
||||||
|
## --------------------
|
||||||
|
proc add*(db: WdiwtltDb, a: Artist) = db.root.artists[a.id] = a
|
||||||
|
|
||||||
|
proc remove*(db: WdiwtltDb, a: Artist) =
|
||||||
db.root.artists.del(a.id)
|
db.root.artists.del(a.id)
|
||||||
db.root.artistsToMediaFiles.del(a.id)
|
db.root.artistsToMediaFiles.del(a.id)
|
||||||
db.root.artistsAndAlbums =
|
db.root.artistsAndAlbums =
|
||||||
db.root.artistsAndAlbums --> filter(it.artistId != a.id)
|
db.root.artistsAndAlbums --> filter(it.artistId != a.id)
|
||||||
|
|
||||||
proc delete*(db: WdiwtltDb, b: Bookmark) = db.root.bookmarks.del(b.id)
|
proc update*(db: WdiwtltDb, a: Artist) = db.add(a)
|
||||||
|
|
||||||
proc delete*(db: WdiwtltDb, mf: MediaFile) =
|
proc findArtistsByAlbum*(db: WdiwtltDb, a: Album): seq[Artist] =
|
||||||
|
db.root.artistsAndAlbums -->
|
||||||
|
filter(it.albumId == a.id and db.root.albums.contains(a.id)).
|
||||||
|
map(db.root.artists[it.artistId])
|
||||||
|
|
||||||
|
proc findArtistsByName*(db: WdiwtltDb, name: string): seq[Artist] =
|
||||||
|
result = @[]
|
||||||
|
for a in db.root.artists.values:
|
||||||
|
if a.name == name: result.add(a)
|
||||||
|
|
||||||
|
proc add*(db: WdiwtltDb, a: Artist, mf: MediaFile) =
|
||||||
|
if not db.root.artistsToMediaFiles.contains(a.id):
|
||||||
|
db.root.artistsToMediaFiles[a.id] = @[mf.id]
|
||||||
|
else:
|
||||||
|
let idsInArtist = db.root.artistsToMediaFiles[a.id]
|
||||||
|
if not idsInArtist.contains(mf.id):
|
||||||
|
db.root.artistsToMediaFiles[a.id].add(mf.id)
|
||||||
|
|
||||||
|
proc remove*(db: WdiwtltDb, a: Artist, mf: MediaFile) =
|
||||||
|
if db.root.artistsToMediaFiles.contains(a.id):
|
||||||
|
db.root.artistsToMediaFiles[a.id] =
|
||||||
|
db.root.artistsToMediaFiles[a.id] --> filter(it != mf.id)
|
||||||
|
|
||||||
|
proc isAssociated*(
|
||||||
|
db: WdiwtltDb,
|
||||||
|
artist: Artist,
|
||||||
|
album: Album
|
||||||
|
): bool =
|
||||||
|
let matching = db.root.artistsAndAlbums -->
|
||||||
|
filter(it.artistId == artist.id and it.albumId == album.id)
|
||||||
|
return matching.len > 0
|
||||||
|
|
||||||
|
proc associate*(db: WdiwtltDb, artist: Artist, album: Album) =
|
||||||
|
if not db.isAssociated(artist, album):
|
||||||
|
db.root.artistsAndAlbums.add((artist.id, album.id))
|
||||||
|
|
||||||
|
proc disassociate*(db: WdiwtltDb, artist: Artist, album: Album) =
|
||||||
|
db.root.artistsAndAlbums = db.root.artistsAndAlbums -->
|
||||||
|
filter(it.albumId != album.id or it.artistId != artist.id)
|
||||||
|
|
||||||
|
## Bookmarks
|
||||||
|
## --------------------
|
||||||
|
proc add*(db: WdiwtltDb, b: Bookmark) = db.root.bookmarks[b.id] = b
|
||||||
|
proc remove*(db: WdiwtltDb, b: Bookmark) = db.root.bookmarks.del(b.id)
|
||||||
|
proc update*(db: WdiwtltDb, b: Bookmark) = db.add(b)
|
||||||
|
|
||||||
|
## Media Files
|
||||||
|
## --------------------
|
||||||
|
proc add*(db: WdiwtltDb, mf: MediaFile) =
|
||||||
|
db.root.mediaFiles[mf.id] = mf
|
||||||
|
db.root.mediaFileHashToId[mf.fileHash] = mf.id
|
||||||
|
|
||||||
|
proc remove*(db: WdiwtltDb, mf: MediaFile) =
|
||||||
db.root.mediaFiles.del(mf.id)
|
db.root.mediaFiles.del(mf.id)
|
||||||
|
|
||||||
for albumId, mfIds in db.root.albumsToMediaFiles.pairs:
|
for albumId, mfIds in db.root.albumsToMediaFiles.pairs:
|
||||||
if mfIds.contains(mf.id):
|
if mfIds.contains(mf.id):
|
||||||
db.remove(db.root.albums[albumId], mf)
|
db.remove(db.root.albums[albumId], mf)
|
||||||
|
|
||||||
proc delete*(db: WdiwtltDb, p: Playlist) =
|
db.root.mediaFileHashToId.del(mf.fileHash)
|
||||||
|
|
||||||
|
proc update*(db: WdiwtltDb, mf: MediaFile) = db.add(mf)
|
||||||
|
|
||||||
|
proc findMediaFilesByAlbum*(db: WdiwtltDb, a: Album): seq[MediaFile] =
|
||||||
|
result = @[]
|
||||||
|
if db.root.albumsToMediaFiles.contains(a.id):
|
||||||
|
return db.root.albumsToMediaFiles[a.id] -->
|
||||||
|
filter(db.root.mediaFiles.contains(it)).
|
||||||
|
map(db.root.mediaFiles[it])
|
||||||
|
|
||||||
|
proc findMediaFilesByArtist*(db: WdiwtltDb, a: Artist): seq[MediaFile] =
|
||||||
|
result = @[]
|
||||||
|
if db.root.artistsToMediaFiles.contains(a.id):
|
||||||
|
return db.root.artistsToMediaFiles[a.id] -->
|
||||||
|
filter(db.root.mediaFiles.contains(it)).
|
||||||
|
map(db.root.mediaFiles[it])
|
||||||
|
|
||||||
|
proc findMediaFileByHash*(db: WdiwtltDb, hash: string): Option[MediaFile] =
|
||||||
|
if db.root.mediaFileHashToId.contains(hash):
|
||||||
|
let mfId = db.root.mediaFileHashToId[hash]
|
||||||
|
if db.root.mediaFiles.contains(mfId):
|
||||||
|
return some(db.root.mediaFiles[mfId])
|
||||||
|
|
||||||
|
return none[MediaFile]()
|
||||||
|
|
||||||
|
## Playlists
|
||||||
|
## --------------------
|
||||||
|
proc add*(db: WdiwtltDb, p: Playlist) = db.root.playlists[p.id] = p
|
||||||
|
|
||||||
|
proc remove*(db: WdiwtltDb, p: Playlist) =
|
||||||
db.root.playlists.del(p.id)
|
db.root.playlists.del(p.id)
|
||||||
db.root.playlistsToMediaFiles.del(p.id)
|
db.root.playlistsToMediaFiles.del(p.id)
|
||||||
for b in db.root.bookmarks.values:
|
for b in db.root.bookmarks.values:
|
||||||
if b.playlistId == p.id: db.delete(b)
|
if b.playlistId == p.id: db.remove(b)
|
||||||
|
|
||||||
proc delete*(db: WdiwtltDb, t: Tag) =
|
proc update*(db: WdiwtltDb, p: Playlist) = db.add(p)
|
||||||
|
|
||||||
|
## Tags
|
||||||
|
## --------------------
|
||||||
|
proc add*(db: WdiwtltDb, t: Tag) = db.root.tags[t.name] = t.description
|
||||||
|
|
||||||
|
proc remove*(db: WdiwtltDb, t: Tag) =
|
||||||
db.root.tags.del(t.name)
|
db.root.tags.del(t.name)
|
||||||
db.root.tagsAndMediaFiles = db.root.tagsAndMediaFiles -->
|
db.root.tagsAndMediaFiles = db.root.tagsAndMediaFiles -->
|
||||||
filter(it.tagName != t.name)
|
filter(it.tagName != t.name)
|
||||||
|
|
||||||
proc remove*(db: WdiwtltDb, a: Album, mf: MediaFile) =
|
proc update*(db: WdiwtltDb, t: Tag) = db.add(t)
|
||||||
db.root.albumsToMediaFiles[a.id] =
|
|
||||||
db.root.albumsToMediaFiles[a.id] -->
|
|
||||||
filter(it != mf.id)
|
|
||||||
|
|
||||||
proc remove*(db: WdiwtltDb, a: Artist, mf: MediaFile) =
|
|
||||||
db.root.artistsToMediaFiles[a.id] =
|
|
||||||
db.root.artistsToMediaFiles[a.id] -->
|
|
||||||
filter(it != mf.id)
|
|
||||||
|
|
||||||
proc remove*(db: WdiwtltDb, artist: Artist, album: Album) =
|
|
||||||
db.root.artistsAndAlbums = db.root.artistsAndAlbums -->
|
|
||||||
filter(it.albumId != album.id or it.artistId != artist.id)
|
|
||||||
|
|
||||||
|
## Housekeeping
|
||||||
|
## --------------------
|
||||||
proc pruneStalePlaylists*(db: WdiwtltDb, ts: DateTime) =
|
proc pruneStalePlaylists*(db: WdiwtltDb, ts: DateTime) =
|
||||||
db.root.playlists.values -->
|
db.root.playlists.values -->
|
||||||
filter(it.lastUsed > ts).foreach(db.delete(it))
|
filter(it.lastUsed > ts).foreach(db.remove(it))
|
||||||
|
|
||||||
proc pruneStaleBookmarks*(db: WdiwtltDb, ts: DateTime) =
|
proc pruneStaleBookmarks*(db: WdiwtltDb, ts: DateTime) =
|
||||||
db.root.bookmarks.values -->
|
db.root.bookmarks.values -->
|
||||||
filter(it.lastUsed > ts).foreach(db.delete(it))
|
filter(it.lastUsed > ts).foreach(db.remove(it))
|
||||||
|
|
||||||
proc removeEmptyAlbums*(db: WdiwtltDb): void =
|
proc removeEmptyAlbums*(db: WdiwtltDb): void =
|
||||||
let emptyAlbumIds = db.root.albumsToMediaFiles.pairs -->
|
let emptyAlbumIds = db.root.albumsToMediaFiles.pairs -->
|
||||||
|
Loading…
Reference in New Issue
Block a user