예제 #1
0
 public static ReleaseList FromDataRelease(Data.Release release, Data.Artist artist, string baseUrl,
                                           Image artistThumbnail, Image thumbnail)
 {
     return(new ReleaseList
     {
         DatabaseId = release.Id,
         Id = release.RoadieId,
         Artist = new DataToken
         {
             Value = artist.RoadieId.ToString(),
             Text = artist.Name
         },
         Release = new DataToken
         {
             Text = release.Title,
             Value = release.RoadieId.ToString()
         },
         ArtistThumbnail = artistThumbnail,
         CreatedDate = release.CreatedDate,
         Duration = release.Duration,
         LastPlayed = release.LastPlayed,
         LastUpdated = release.LastUpdated,
         LibraryStatus = release.LibraryStatus,
         MediaCount = release.MediaCount,
         Rating = release.Rating,
         Rank = SafeParser.ToNumber <double?>(release.Rank),
         ReleaseDateDateTime = release.ReleaseDate,
         ReleasePlayUrl = $"{baseUrl}/play/release/{release.RoadieId}",
         Status = release.Status,
         Thumbnail = thumbnail,
         TrackCount = release.TrackCount,
         TrackPlayedCount = release.PlayedCount
     });
 }
예제 #2
0
        public static int?ParseDiscNumber(string input)
        {
            var discNumber = SafeParser.ToNumber <int?>(input);

            if (!discNumber.HasValue && !string.IsNullOrEmpty(input))
            {
                input      = input.ToUpper().Replace("A", "1");
                input      = input.ToUpper().Replace("B", "2");
                input      = input.ToUpper().Replace("C", "3");
                input      = input.ToUpper().Replace("D", "4");
                input      = input.ToUpper().Replace("E", "5");
                discNumber = SafeParser.ToNumber <int?>(input);
                if (!discNumber.HasValue && input.Contains("/"))
                {
                    discNumber = SafeParser.ToNumber <int?>(input.Split("/")[0]);
                }
                if (!discNumber.HasValue && input.Contains("\\"))
                {
                    discNumber = SafeParser.ToNumber <int?>(input.Split("\\")[0]);
                }
                if (!discNumber.HasValue && input.Contains(":"))
                {
                    discNumber = SafeParser.ToNumber <int?>(input.Split(":")[0]);
                }
                if (!discNumber.HasValue && input.Contains(","))
                {
                    discNumber = SafeParser.ToNumber <int?>(input.Split(",")[0]);
                }
                if (!discNumber.HasValue && input.Contains("|"))
                {
                    discNumber = SafeParser.ToNumber <int?>(input.Split("|")[0]);
                }
            }
            return(discNumber);
        }
예제 #3
0
        public async Task <OperationResult <IEnumerable <ReleaseSearchResult> > > PerformReleaseSearch(string artistName, string query, int resultsCount)
        {
            var cacheKey = $"uri:lastfm:releasesearch:{ artistName.ToAlphanumericName() }:{ query.ToAlphanumericName() }";
            var data     = await CacheManager.GetAsync <ReleaseSearchResult>(cacheKey, async() =>
            {
                var request      = new RestRequest(Method.GET);
                var client       = new RestClient(string.Format("http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key={0}&artist={1}&album={2}&format=xml", ApiKey.Key, artistName, query));
                var responseData = await client.ExecuteAsync <lfm>(request);

                ReleaseSearchResult result = null;

                var response = responseData != null && responseData.Data != null ? responseData.Data : null;
                if (response != null && response.album != null)
                {
                    var lastFmAlbum = response.album;
                    result          = new ReleaseSearchResult
                    {
                        ReleaseTitle  = lastFmAlbum.name,
                        MusicBrainzId = lastFmAlbum.mbid
                    };

                    // No longer fetching/consuming images LastFm says is violation of ToS ; https://getsatisfaction.com/lastfm/topics/api-announcement-dac8oefw5vrxq

                    if (lastFmAlbum.tags != null)
                    {
                        result.Tags = lastFmAlbum.tags.Select(x => x.name).ToList();
                    }
                    if (lastFmAlbum.tracks != null)
                    {
                        var tracks = new List <TrackSearchResult>();
                        foreach (var lastFmTrack in lastFmAlbum.tracks)
                        {
                            tracks.Add(new TrackSearchResult
                            {
                                TrackNumber = SafeParser.ToNumber <short?>(lastFmTrack.rank),
                                Title       = lastFmTrack.name,
                                Duration    = SafeParser.ToNumber <int?>(lastFmTrack.duration),
                                Urls        = string.IsNullOrEmpty(lastFmTrack.url) ? new[] { lastFmTrack.url } : null
                            });
                        }
                        result.ReleaseMedia = new List <ReleaseMediaSearchResult>
                        {
                            new ReleaseMediaSearchResult
                            {
                                ReleaseMediaNumber = 1,
                                Tracks             = tracks
                            }
                        };
                    }
                }
                return(result);
            }, "uri:metadata");

            return(new OperationResult <IEnumerable <ReleaseSearchResult> >
            {
                IsSuccess = data != null,
                Data = new[] { data }
            });
        }
예제 #4
0
        public void Parse_Larger_Int()
        {
            var n      = "12345";
            int n1     = 12345;
            var parsed = SafeParser.ToNumber <int>(n);

            Assert.Equal(parsed, n1);
        }
예제 #5
0
        public void Parse_Short()
        {
            var   n      = "23";
            short n1     = 23;
            var   parsed = SafeParser.ToNumber <short>(n);

            Assert.Equal(parsed, n1);
        }
예제 #6
0
        public async Task <OperationResult <IEnumerable <ReleaseSearchResult> > > PerformReleaseSearch(string artistName, string query, int resultsCount)
        {
            var request      = new RestRequest(Method.GET);
            var client       = new RestClient(string.Format("http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key={0}&artist={1}&album={2}&format=xml", this.ApiKey.Key, artistName, query));
            var responseData = await client.ExecuteTaskAsync <lfm>(request);

            ReleaseSearchResult result = null;

            var response = responseData != null && responseData.Data != null ? responseData.Data : null;

            if (response != null && response.album != null)
            {
                var lastFmAlbum = response.album;
                result = new ReleaseSearchResult
                {
                    ReleaseTitle  = lastFmAlbum.name,
                    MusicBrainzId = lastFmAlbum.mbid
                };

                if (lastFmAlbum.image != null)
                {
                    result.ImageUrls = lastFmAlbum.image.Where(x => x.size == "extralarge").Select(x => x.Value).ToList();
                }
                if (lastFmAlbum.tags != null)
                {
                    result.Tags = lastFmAlbum.tags.Select(x => x.name).ToList();
                }
                if (lastFmAlbum.tracks != null)
                {
                    var tracks = new List <TrackSearchResult>();
                    foreach (var lastFmTrack in lastFmAlbum.tracks)
                    {
                        tracks.Add(new TrackSearchResult
                        {
                            TrackNumber = SafeParser.ToNumber <short?>(lastFmTrack.rank),
                            Title       = lastFmTrack.name,
                            Duration    = SafeParser.ToNumber <int?>(lastFmTrack.duration),
                            Urls        = string.IsNullOrEmpty(lastFmTrack.url) ? new string[] { lastFmTrack.url } : null,
                        });
                    }
                    result.ReleaseMedia = new List <ReleaseMediaSearchResult>
                    {
                        new ReleaseMediaSearchResult
                        {
                            ReleaseMediaNumber = 1,
                            Tracks             = tracks
                        }
                    };
                }
            }
            return(new OperationResult <IEnumerable <ReleaseSearchResult> >
            {
                IsSuccess = result != null,
                Data = new List <ReleaseSearchResult> {
                    result
                }
            });
        }
예제 #7
0
        private async Task <OperationResult <bool> > ScanFolder(DirectoryInfo d, DirectoryInfo dest, ApplicationUser user, bool isReadOnly)
        {
            var sw = new Stopwatch();

            sw.Start();

            long processedFiles = 0;

            await this.LogAndPublish($"** Processing Folder: [{d.FullName}]");

            long processedFolders = 0;
            var  folderProcessor  = new FolderProcessor(this.Configuration, this.HttpEncoder, this.Configuration.LibraryFolder, this.DbContext, this.CacheManager, this.MessageLogger, this.ArtistLookupEngine, this.ArtistFactory, this.ReleaseFactory, this.ImageFactory, this.ReleaseLookupEngine, this.AudioMetaDataHelper);

            var newArtists  = 0;
            var newReleases = 0;
            var newTracks   = 0;
            OperationResult <bool> result = null;

            foreach (var folder in Directory.EnumerateDirectories(d.FullName).ToArray())
            {
                result = await folderProcessor.Process(new DirectoryInfo(folder), isReadOnly);

                // Between folders flush cache, the caching for folder processing was intended for caching artist metadata lookups. Most of the time artists are in the same folder.
                this.CacheManager.Clear();
                processedFolders++;
            }
            if (result.AdditionalData != null)
            {
                newArtists  = SafeParser.ToNumber <int>(result.AdditionalData["newArtists"]);
                newReleases = SafeParser.ToNumber <int>(result.AdditionalData["newReleases"]);
                newTracks   = SafeParser.ToNumber <int>(result.AdditionalData["newTracks"]);
            }
            if (!isReadOnly)
            {
                FolderProcessor.DeleteEmptyFolders(d, this.Logger);
            }
            sw.Stop();
            this.DbContext.ScanHistories.Add(new data.ScanHistory
            {
                UserId            = user.Id,
                NewArtists        = newArtists,
                NewReleases       = newReleases,
                NewTracks         = newTracks,
                TimeSpanInSeconds = (int)sw.Elapsed.TotalSeconds
            });
            await this.DbContext.SaveChangesAsync();

            this.CacheManager.Clear();
            await this.LogAndPublish($"**Completed!Processed Folders[{ processedFolders }], Processed Files[{ processedFiles}] : Elapsed Time[{ sw.Elapsed}]");

            return(new OperationResult <bool>
            {
                Data = true,
                IsSuccess = true,
                OperationTime = sw.ElapsedMilliseconds
            });
        }
예제 #8
0
        public static bool DoesStartWithNumber(this string input)
        {
            if (string.IsNullOrEmpty(input))
            {
                return(false);
            }
            var firstPart = input.Split(' ').First().SafeReplace("[").SafeReplace("]");

            return(SafeParser.ToNumber <long>(firstPart) > 0);
        }
예제 #9
0
        public static short?ParseYear(string input)
        {
            if (string.IsNullOrEmpty(input))
            {
                return(null);
            }
            var   date = SafeParser.ToDateTime(input);
            short?year = (short?)date?.Year ?? SafeParser.ToNumber <short?>(input);

            return(year > 2200 || year < 1900 ? null : year);
        }
예제 #10
0
        public static string TrackPlayToken(User user, Guid trackId)
        {
            var trackIdPart = BitConverter.ToInt32(trackId.ToByteArray(), 6);

            if (trackIdPart < 0)
            {
                trackIdPart *= -1;
            }
            var token = hashIds.Value.Encode(user.Id, SafeParser.ToNumber <int>(user.CreatedDate.Value.ToString("DDHHmmss")), trackIdPart);

            return(token);
        }
예제 #11
0
        /// <summary>
        ///     Update Relase Rank
        ///     Release Rank Calculation = Average of Track User Ratings + (User Rating of Release / Release Track Count) +
        ///     Collection Rank Value
        /// </summary>
        protected async Task UpdateReleaseRank(int releaseId, bool updateArtistRank = true)
        {
            try
            {
                var release = DbContext.Releases.FirstOrDefault(x => x.Id == releaseId);
                if (release != null)
                {
                    var releaseTrackAverage = (from ut in DbContext.UserTracks
                                               join t in DbContext.Tracks on ut.TrackId equals t.Id
                                               join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
                                               where rm.ReleaseId == releaseId
                                               select ut.Rating).Select(x => (decimal?)x).Average();

                    var releaseUserRatingRank = release.Rating > 0 ? release.Rating / (decimal?)release.TrackCount : 0;

                    var collectionsWithRelease = from c in DbContext.Collections
                                                 join cr in DbContext.CollectionReleases on c.Id equals cr.CollectionId
                                                 where c.CollectionType != CollectionType.Chart
                                                 where cr.ReleaseId == release.Id
                                                 select new
                    {
                        c.CollectionCount,
                        cr.ListNumber
                    };

                    decimal releaseCollectionRank = 0;
                    foreach (var collectionWithRelease in collectionsWithRelease)
                    {
                        var rank = (decimal)(collectionWithRelease.CollectionCount * .01 -
                                             (collectionWithRelease.ListNumber - 1) * .01);
                        releaseCollectionRank += rank;
                    }

                    release.Rank = SafeParser.ToNumber <decimal>(releaseTrackAverage) + releaseUserRatingRank +
                                   releaseCollectionRank;

                    await DbContext.SaveChangesAsync();

                    CacheManager.ClearRegion(release.CacheRegion);
                    Logger.LogInformation("UpdateReleaseRank For Release `{0}`", release);
                    if (updateArtistRank)
                    {
                        await UpdateArtistsRankForRelease(release);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "Error UpdateReleaseRank RelaseId [{0}], UpdateArtistRank [{1}]", releaseId,
                                updateArtistRank);
            }
        }
예제 #12
0
        public Task <OperationResult <IEnumerable <DateAndCount> > > ReleasesByDate()
        {
            var sw = new Stopwatch();

            sw.Start();

            var result = new List <DateAndCount>();

            using (var conn = new MySqlConnection(this.Configuration.ConnectionString))
            {
                conn.Open();
                var sql = @"SELECT DATE_FORMAT(createdDate, '%Y-%m-%d') as date, count(1) as count
                            FROM `release`
                            group by DATE_FORMAT(createdDate, '%Y-%m-%d')
                            order by createdDate;";
                using (var cmd = new MySqlCommand(sql, conn))
                {
                    try
                    {
                        using (var rdr = cmd.ExecuteReader())
                        {
                            if (rdr.HasRows)
                            {
                                while (rdr.Read())
                                {
                                    result.Add(new DateAndCount
                                    {
                                        Date  = SafeParser.ToString(rdr["date"]),
                                        Count = SafeParser.ToNumber <int?>(rdr["count"])
                                    });
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Logger.LogError(ex);
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }

            sw.Stop();
            return(Task.FromResult(new OperationResult <IEnumerable <DateAndCount> >
            {
                OperationTime = sw.ElapsedMilliseconds,
                Data = result
            }));
        }
예제 #13
0
        public static string TrackPlayToken(ApplicationUser user, Guid trackId)
        {
            var hashids     = new Hashids(ServiceBase.TrackTokenSalt);
            var trackIdPart = BitConverter.ToInt32(trackId.ToByteArray(), 6);

            if (trackIdPart < 0)
            {
                trackIdPart = trackIdPart * -1;
            }
            var token = hashids.Encode(user.Id, SafeParser.ToNumber <int>(user.CreatedDate.Value.ToString("DDHHmmss")), trackIdPart);

            return(token);
        }
예제 #14
0
        private async Task <byte[]> TrackBytesAndMarkPlayed(int releaseId, data.Track track, string trackToken)
        {
            var results = await TrackService.TrackStreamInfo(track.RoadieId, 0, SafeParser.ToNumber <long>(track.FileSize), null).ConfigureAwait(false);

            // Some DLNA clients call for the track file several times for each play
            if (ShouldMakeScrobble(trackToken))
            {
                await PlayActivityService.Scrobble(null, new Library.Scrobble.ScrobbleInfo
                {
                    TrackId    = track.RoadieId,
                    TimePlayed = DateTime.UtcNow
                }).ConfigureAwait(false);
            }
            return(results.Data.Bytes);
        }
예제 #15
0
        public static short?ParseTrackNumber(string input)
        {
            if (string.IsNullOrEmpty(input))
            {
                return(null);
            }
            var trackparts = input.Split('/');
            var r          = trackparts[0];

            r = r.ToUpper().Replace("A", "");
            r = r.ToUpper().Replace("B", "");
            r = r.ToUpper().Replace("C", "");
            r = r.ToUpper().Replace("D", "");
            r = r.ToUpper().Replace("E", "");
            return(SafeParser.ToNumber <short?>(r));
        }
예제 #16
0
        public void Parse_NullablleInt()
        {
            var one    = "1";
            var parsed = SafeParser.ToNumber <int?>(one);

            Assert.True(parsed.HasValue);

            int?oneNullable = 1;

            Assert.Equal(parsed.Value, oneNullable);

            var nothing = "";

            parsed = SafeParser.ToNumber <int?>(nothing);
            Assert.Null(parsed);
        }
예제 #17
0
        /// <summary>
        ///     Update Artist Rank
        ///     Artist Rank is a sum of the artists release ranks + artist tracks rating + artist user rating
        /// </summary>
        protected async Task UpdateArtistRank(int artistId, bool updateReleaseRanks = false)
        {
            try
            {
                var artist = DbContext.Artists.FirstOrDefault(x => x.Id == artistId);
                if (artist != null)
                {
                    if (updateReleaseRanks)
                    {
                        var artistReleaseIds = DbContext.Releases.Where(x => x.ArtistId == artistId).Select(x => x.Id)
                                               .ToArray();
                        foreach (var artistReleaseId in artistReleaseIds)
                        {
                            await UpdateReleaseRank(artistReleaseId, false);
                        }
                    }

                    var artistTrackAverage = (from t in DbContext.Tracks
                                              join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
                                              join ut in DbContext.UserTracks on t.Id equals ut.TrackId
                                              where t.ArtistId == artist.Id
                                              select ut.Rating).Select(x => (decimal?)x).Average();

                    var artistReleaseRatingRating = (from r in DbContext.Releases
                                                     join ur in DbContext.UserReleases on r.Id equals ur.ReleaseId
                                                     where r.ArtistId == artist.Id
                                                     select ur.Rating).Select(x => (decimal?)x).Average();

                    var artistReleaseRankSum = (from r in DbContext.Releases
                                                where r.ArtistId == artist.Id
                                                select r.Rank).ToArray().Sum(x => x) ?? 0;

                    artist.Rank = SafeParser.ToNumber <decimal>(artistTrackAverage + artistReleaseRatingRating) +
                                  artistReleaseRankSum + artist.Rating;

                    await DbContext.SaveChangesAsync();

                    CacheManager.ClearRegion(artist.CacheRegion);
                    Logger.LogInformation("UpdatedArtistRank For Artist `{0}`", artist);
                }
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "Error in UpdateArtistRank ArtistId [{0}], UpdateReleaseRanks [{1}]", artistId,
                                updateReleaseRanks);
            }
        }
예제 #18
0
        private IMediaFolder RandomOrRatedTracks(bool isRated)
        {
            var result = new VirtualFolder()
            {
                Name = isRated ? "Random Rated Tracks" : "Random Tracks",
                Id   = isRated ? "vf:randomratedtracks" : "vf:randomtracks"
            };

            foreach (var randomTrack in RandomTracks(RandomTrackLimit, (short)(isRated ? 1 : 0)))
            {
                var t = new Track($"r:t:tk:{randomTrack.ReleaseMedia.Release.Id}:{randomTrack.Id}:{ Guid.NewGuid() }", randomTrack.ReleaseMedia.Release.Artist.Name, randomTrack.ReleaseMedia.Release.Title, randomTrack.ReleaseMedia.MediaNumber,
                                  randomTrack.Title, randomTrack.ReleaseMedia.Release.Genres.Select(x => x.Genre.Name).ToCSV(), randomTrack.TrackArtist?.Name, randomTrack.TrackNumber, randomTrack.ReleaseMedia.Release.ReleaseYear,
                                  TimeSpan.FromMilliseconds(SafeParser.ToNumber <double>(randomTrack.Duration)), isRated ? $"Rating: { randomTrack.Rating }" : randomTrack.PartTitles, randomTrack.LastUpdated ?? randomTrack.CreatedDate, ReleaseCoverArt(randomTrack.ReleaseMedia.Release.RoadieId));
                result.AddResource(t);
            }
            return(result);
        }
예제 #19
0
        public AudioMetaData MetaDataFromFileInfo(FileInfo fileInfo)
        {
            var justFilename = CleanString(fileInfo.Name.Replace(fileInfo.Extension, ""));

            if (IsTrckTit2(justFilename))
            {
                var Release     = fileInfo.Directory.Name;
                var ReleaseYear = SafeParser.ToYear(Release.Substring(0, 4));
                if (ReleaseYear.HasValue)
                {
                    Release = Release.Substring(5, Release.Length - 5);
                }
                var artist = fileInfo.Directory.Parent.Name;

                var title             = justFilename.Substring(2, justFilename.Length - 2);
                var artistYearRelease = CleanString(string.Format("{0} {1} {2}", artist, ReleaseYear, Release));
                if (justFilename.StartsWith(artistYearRelease) || CleanString(justFilename.Replace("The ", ""))
                    .StartsWith(CleanString(artistYearRelease.Replace("The ", ""))))
                {
                    title = CleanString(CleanString(justFilename.Replace("The ", ""))
                                        .Replace(CleanString(artistYearRelease.Replace("The ", "")), ""));
                }
                else
                {
                    var regex = new Regex(@"[0-9]{2}-[\w\s,$/.'-`#&()!]+");
                    if (regex.IsMatch(title))
                    {
                        title = fileInfo.Name.Replace(fileInfo.Extension, "");
                        title = title.Substring(6, title.Length - 6);
                        title = Regex.Replace(title, @"(\B[A-Z]+?(?=[A-Z][^A-Z])|\B[A-Z]+?(?=[^A-Z]))", " $1");
                    }
                }

                var trackNumber = SafeParser.ToNumber <short>(title.Substring(0, 2));
                return(new AudioMetaData
                {
                    Artist = artist,
                    Release = Release,
                    Year = ReleaseYear,
                    TrackNumber = trackNumber,
                    Title = CleanString(title.Replace(trackNumber.ToString("D2") + " ", ""))
                });
            }

            return(new AudioMetaData());
        }
예제 #20
0
        public Task <OperationResult <IEnumerable <DateAndCount> > > ReleasesByDecade()
        {
            var sw = new Stopwatch();

            sw.Start();
            var result      = new List <DateAndCount>();
            var decadeInfos = (from r in DbContext.Releases
                               orderby r.ReleaseDate
                               select r.ReleaseDate ?? r.CreatedDate)
                              .ToArray()
                              .GroupBy(x => x.ToString("yyyy"))
                              .Select(x => new
            {
                year  = SafeParser.ToNumber <int>(x.Key),
                count = x.Count()
            });

            if (decadeInfos?.Any() == true)
            {
                const int decadeInterval = 10;
                var       startingDecade = (decadeInfos.Min(x => x.year) / 10) * 10;
                var       endingDecade   = (decadeInfos.Max(x => x.year) / 10) * 10;
                for (int decade = startingDecade; decade <= endingDecade; decade += decadeInterval)
                {
                    var endOfDecade = decade + 9;
                    var count       = decadeInfos.Where(x => x.year >= decade && x.year <= endOfDecade).Sum(x => x.count);
                    if (count > 0)
                    {
                        result.Add(new DateAndCount
                        {
                            Date  = decade.ToString(),
                            Count = count
                        });
                    }
                }
            }
            sw.Stop();
            return(Task.FromResult(new OperationResult <IEnumerable <DateAndCount> >
            {
                OperationTime = sw.ElapsedMilliseconds,
                IsSuccess = result != null,
                Data = result
            }));
        }
예제 #21
0
        private IMediaItem TracksForPlaylist(string id)
        {
            var playlistId = SafeParser.ToNumber <int>(id.Replace("vf:tracksforplaylist:", ""));
            var playlist   = DbContext.Playlists.FirstOrDefault(x => x.Id == playlistId);
            var result     = new VirtualFolder()
            {
                Name = playlist.Name,
                Id   = id
            };

            foreach (var playlistTrack in TracksForPlaylist(playlist.Id))
            {
                var t = new Track($"r:t:tk:{playlistTrack.ReleaseMedia.Release.Id}:{playlistTrack.Id}:{ Guid.NewGuid() }", playlistTrack.ReleaseMedia.Release.Artist.Name, playlistTrack.ReleaseMedia.Release.Title, playlistTrack.ReleaseMedia.MediaNumber,
                                  playlistTrack.Title, playlistTrack.ReleaseMedia.Release.Genres.Select(x => x.Genre.Name).ToCSV(), playlistTrack.TrackArtist?.Name, playlistTrack.TrackNumber, playlistTrack.ReleaseMedia.Release.ReleaseYear,
                                  TimeSpan.FromMilliseconds(SafeParser.ToNumber <double>(playlistTrack.Duration)), playlistTrack.PartTitles, playlistTrack.LastUpdated ?? playlistTrack.CreatedDate, ReleaseCoverArt(playlistTrack.ReleaseMedia.Release.RoadieId));
                result.AddResource(t);
            }
            return(result);
        }
예제 #22
0
        public override OperationResult <string> Process(DirectoryInfo directory)
        {
            var result   = new OperationResult <string>();
            var data     = string.Empty;
            var found    = 0;
            var modified = 0;
            var metaDatasForFilesInFolder = GetAudioMetaDatasForDirectory(directory);

            if (metaDatasForFilesInFolder.Any())
            {
                found = metaDatasForFilesInFolder.Count();
                var firstMetaData = metaDatasForFilesInFolder.OrderBy(x => x.Filename ?? string.Empty)
                                    .ThenBy(x => SafeParser.ToNumber <short>(x.TrackNumber)).FirstOrDefault();
                if (firstMetaData == null)
                {
                    return new OperationResult <string>("Error Getting First MetaData")
                           {
                               Data = $"Unable to read Metadatas for Directory [{directory.FullName}]"
                           }
                }
                ;
                var artist = firstMetaData.Artist;
                foreach (var metaData in metaDatasForFilesInFolder.Where(x => x.Artist != artist))
                {
                    modified++;

                    Console.WriteLine(
                        $"╟ Setting Artist to [{artist}], was [{metaData.Artist}] on file [{metaData.FileInfo.Name}");
                    metaData.Artist = artist;
                    if (!Configuration.Inspector.IsInReadOnlyMode)
                    {
                        TagsHelper.WriteTags(metaData, metaData.Filename);
                    }
                }

                data = $"Found [{found}] files, Modified [{modified}] files";
            }

            result.Data      = data;
            result.IsSuccess = true;
            return(result);
        }
    }
예제 #23
0
        private IMediaItem TrackDetail(string id, bool isFileRequest)
        {
            lock (lockObject)
            {
                var releaseId  = SafeParser.ToNumber <int>(id.Replace("r:t:tk:", "").Split(':')[0]);
                var trackId    = SafeParser.ToNumber <int>(id.Replace("r:t:tk:", "").Split(':')[1]);
                var trackToken = id.Replace("r:t:tk:", "").Split(':')[2];

                var track = TracksForRelease(releaseId).First(x => x.Id == trackId);

                byte[] trackbytes = null;
                if (isFileRequest)
                {
                    trackbytes = AsyncHelper.RunSync(() => TrackBytesAndMarkPlayed(releaseId, track, trackToken));
                }
                return(new Track($"r:t:tk:{releaseId}:{trackId}:{ Guid.NewGuid() }", track.ReleaseMedia.Release.Artist.Name, track.ReleaseMedia.Release.Title, track.ReleaseMedia.MediaNumber,
                                 track.Title, track.ReleaseMedia.Release.Genres.Select(x => x.Genre.Name).ToCSV(), track.TrackArtist?.Name,
                                 track.TrackNumber, track.ReleaseMedia.Release.ReleaseYear, TimeSpan.FromMilliseconds(SafeParser.ToNumber <double>(track.Duration)),
                                 track.PartTitles, track.LastUpdated ?? track.CreatedDate, ReleaseCoverArt(track.ReleaseMedia.Release.RoadieId), trackbytes));
            }
        }
예제 #24
0
        public static short?DetermineTrackNumber(string filename)
        {
            if (string.IsNullOrEmpty(filename) || filename.Length < 2)
            {
                return(null);
            }
            filename = filename.Replace("(", "");
            filename = filename.Replace("[", "");
            var part = filename.Substring(0, 2);

            part = part.Replace(".", "");
            part = part.Replace("-", "");
            part = part.Replace(" ", "");
            var result = SafeParser.ToNumber <short?>(part);

            if ((result ?? 0) == 0)
            {
                var firstNumber = filename.IndexOfAny("0123456789".ToCharArray());
                part   = filename.Substring(firstNumber, 2);
                result = SafeParser.ToNumber <short?>(part);
            }
            return(result);
        }
예제 #25
0
        public async Task <IActionResult> Scrobble(SubsonicRequest request)
        {
            var authResult = await AuthenticateUser(request).ConfigureAwait(false);

            if (authResult != null)
            {
                return(authResult);
            }
            var timePlayed = string.IsNullOrEmpty(request.time)
                ? DateTime.UtcNow.AddDays(-1)
                : SafeParser.ToNumber <long>(request.time).FromUnixTime();
            var scrobblerResponse = await PlayActivityService.Scrobble(SubsonicUser, new ScrobbleInfo
            {
                TrackId    = request.TrackId.Value,
                TimePlayed = timePlayed
            }).ConfigureAwait(false);

            return(BuildResponse(request, new SubsonicOperationResult <Response>
            {
                IsSuccess = scrobblerResponse.IsSuccess,
                Data = new Response()
            }));
        }
예제 #26
0
        public async Task <Data.Release> ReleaseForMusicBrainzReleaseById(string musicBrainzId)
        {
            var release = await MusicBrainzReleaseById(musicBrainzId);

            if (release == null)
            {
                return(null);
            }
            var media = release.media.First();

            if (media == null)
            {
                return(null);
            }

            var result = new Data.Release
            {
                Title         = release.title.ToTitleCase(false),
                ReleaseDate   = SafeParser.ToDateTime(release.date),
                MusicBrainzId = release.id
            };

            var releaseMedia = new Data.ReleaseMedia
            {
                Tracks = media.tracks.Select(m => new Data.Track
                {
                    TrackNumber   = SafeParser.ToNumber <short>(m.position ?? m.number),
                    Title         = m.title.ToTitleCase(false),
                    MusicBrainzId = m.id,
                }).ToList()
            };

            result.Medias = new List <ReleaseMedia> {
                releaseMedia
            };
            return(result);
        }
예제 #27
0
        private IMediaItem ReleasesForCollectionFolder(string id)
        {
            var collectionId = SafeParser.ToNumber <int>(id.Replace("vf:releasesforcollection:", ""));
            var collection   = DbContext.Collections.FirstOrDefault(x => x.Id == collectionId);
            var result       = new VirtualFolder()
            {
                Name = collection.Name,
                Id   = id
            };

            foreach (var collectionRelease in ReleasesForCollection(collection.Id))
            {
                var fr = new VirtualFolder(result, collectionRelease.Title, $"vf:release:{ collectionRelease.Id }");
                foreach (var releaseTrack in TracksForRelease(collectionRelease.Id))
                {
                    var t = new Track(releaseTrack.RoadieId.ToString(), releaseTrack.ReleaseMedia.Release.Artist.Name, releaseTrack.ReleaseMedia.Release.Title, releaseTrack.ReleaseMedia.MediaNumber,
                                      releaseTrack.Title, releaseTrack.ReleaseMedia.Release.Genres.Select(x => x.Genre.Name).ToCSV(), releaseTrack.TrackArtist?.Name, releaseTrack.TrackNumber, releaseTrack.ReleaseMedia.Release.ReleaseYear,
                                      TimeSpan.FromMilliseconds(SafeParser.ToNumber <double>(releaseTrack.Duration)), releaseTrack.PartTitles, releaseTrack.LastUpdated ?? releaseTrack.CreatedDate, null);
                    fr.AddResource(t);
                }
                result.AddFolder(fr);
            }
            return(result);
        }
예제 #28
0
 public static ArtistList FromDataArtist(Data.Artist artist, Image thumbnail)
 {
     return(new ArtistList
     {
         DatabaseId = artist.Id,
         Id = artist.RoadieId,
         Artist = new DataToken
         {
             Text = artist.Name,
             Value = artist.RoadieId.ToString()
         },
         Thumbnail = thumbnail,
         Rating = artist.Rating,
         Rank = SafeParser.ToNumber <double?>(artist.Rank),
         CreatedDate = artist.CreatedDate,
         LastUpdated = artist.LastUpdated,
         LastPlayed = artist.LastPlayed,
         PlayedCount = artist.PlayedCount,
         ReleaseCount = artist.ReleaseCount,
         TrackCount = artist.TrackCount,
         SortName = artist.SortName,
         Status = artist.Status
     });
 }
예제 #29
0
        public AudioMetaData MetaDataFromFilename(string rawFilename)
        {
            var filename = CleanString(rawFilename);

            if (IsTalbTyerTalbTrckTit2(filename))
            {
                // GUID~TPE1 - [TYER] - TALB~TRCK. TIT2
                var parts = filename.Split('~');

                var firstParts = parts[1].Split('-');
                var artist     = firstParts[0];
                var year       = firstParts[1].Replace("[", "").Replace("]", "");
                var Release    = firstParts[2];

                var trck  = parts[2].Substring(0, 2);
                var title = parts[2].Substring(3, parts[2].Length - 3);

                return(new AudioMetaData
                {
                    Artist = CleanString(artist),
                    Year = SafeParser.ToNumber <int?>(CleanString(year)),
                    Release = CleanString(Release),
                    TrackNumber = SafeParser.ToNumber <short?>(CleanString(trck)),
                    Title = CleanString(title)
                });
            }

            if (IsTpe1TalbTyerTrckTpe1Tit2(filename))
            {
                // GUID~TPE1-TALB-TYER~TRCK-TPE1-TIT2
                var parts = filename.Split('~');

                var firstParts  = parts[1].Split('-');
                var secondParts = parts[2].Split('-');

                var artist  = firstParts[0];
                var Release = firstParts[1];
                var year    = firstParts[2];
                var trck    = secondParts[0].Substring(0, 2);
                var title   = secondParts[1];

                return(new AudioMetaData
                {
                    Artist = CleanString(artist),
                    Year = SafeParser.ToNumber <int?>(CleanString(year)),
                    Release = CleanString(Release),
                    TrackNumber = SafeParser.ToNumber <short?>(CleanString(trck)),
                    Title = CleanString(title)
                });
            }

            if (IsTpe1TalbTyerTrckTit2(filename))
            {
                // GUID~TPE1-TALB (TYER)~TRCK-TIT2
                var parts = filename.Split('~');

                var firstParts  = parts[1].Split('-');
                var secondParts = parts[2].Split('-');

                var artist  = firstParts[0];
                var year    = firstParts[1].Substring(firstParts[1].Length - 6, 6).Replace("(", "").Replace(")", "");
                var Release = firstParts[1].Substring(0, firstParts[1].Length - 6);
                var trck    = secondParts[1];
                var title   = secondParts[2];

                return(new AudioMetaData
                {
                    Artist = CleanString(artist),
                    Year = SafeParser.ToNumber <int?>(CleanString(year)),
                    Release = CleanString(Release),
                    TrackNumber = SafeParser.ToNumber <short?>(CleanString(trck)),
                    Title = CleanString(title)
                });
            }

            if (IsTalbTposTpe1TrckTit2(filename))
            {
                // GUID~TALB~TPOS TPE1 - TRCK - TIT2
                var parts   = filename.Split('~');
                var Release = parts[1];

                var secondParts = parts[2].Split('-');

                var tpos   = secondParts[0].Substring(0, 2);
                var artist = secondParts[0].Substring(2, secondParts[0].Length - 2);
                var trck   = secondParts[1];
                var title  = secondParts[2];

                return(new AudioMetaData
                {
                    Artist = CleanString(artist),
                    Disc = SafeParser.ToNumber <int?>(CleanString(tpos)),
                    Release = CleanString(Release),
                    TrackNumber = SafeParser.ToNumber <short?>(CleanString(trck)),
                    Title = CleanString(title)
                });
            }

            if (IsTyerTalbTrckTit2(filename))
            {
                // GUID~[TYER] TALB~TRCK - TIT2
                var parts = filename.Split('~');
                var year  = parts[1].Split(' ').First().Replace("[", "").Replace("]", "").Replace("(", "")
                            .Replace(")", "");
                var Release = string.Join(" ", parts[1].Split(' ').Skip(1));

                var secondParts = parts[2];
                if (secondParts.StartsWith("-"))
                {
                    secondParts = secondParts.Substring(1, secondParts.Length - 1);
                }
                var track = secondParts.Split('-').First();
                var title = string.Join(" ", secondParts.Split('-').Skip(1));
                return(new AudioMetaData
                {
                    Year = SafeParser.ToNumber <int?>(CleanString(year)),
                    Release = CleanString(Release),
                    TrackNumber = SafeParser.ToNumber <short?>(CleanString(track)),
                    Title = CleanString(title)
                });
            }

            if (IsTyerTalbTpe1Tit2(filename))
            {
                // GUID~TYER - TALB~TPE1 - TIT2
                var parts       = filename.Split('~');
                var secondParts = parts[1].Split('-');

                var year    = secondParts[0];
                var Release = secondParts[1];

                var thirdParts = parts[2].Split('-');
                var artist     = thirdParts[0];
                var title      = thirdParts[1];

                return(new AudioMetaData
                {
                    Year = SafeParser.ToNumber <int?>(CleanString(year)),
                    Artist = CleanString(artist),
                    Release = CleanString(Release),
                    Title = CleanString(title)
                });
            }

            if (IsTpe1TrckTit2(filename))
            {
                // GUID~TPE1~TRCK TIT2
                var parts = filename.Split('~');
                var track = parts[2].Split(' ').First();
                var title = string.Join(" ", parts[2].Split(' ').Skip(1));
                return(new AudioMetaData
                {
                    Artist = CleanString(parts[1]),
                    TrackNumber = SafeParser.ToNumber <short?>(CleanString(track)),
                    Title = CleanString(title)
                });
            }

            if (IsTpe1Tit2(filename))
            {
                var parts = filename.Split('~');
                return(new AudioMetaData
                {
                    Artist = CleanString(parts[1]),
                    Title = CleanString(parts[2])
                });
            }

            return(new AudioMetaData());
        }
예제 #30
0
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }
            var queryDictionary = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(bindingContext.HttpContext.Request.QueryString.ToString());

            // Create a dictionary of all the properties to populate on the result model
            var modelDictionary = new Dictionary <string, object>(StringComparer.InvariantCultureIgnoreCase)
            {
                { "albumCount", null },
                { "albumOffset", null },
                { "artist", null },
                { "artistCount", null },
                { "artistOffset", null },
                { "c", null },
                { "callback", null },
                { "f", null },
                { "fromYear", null },
                { "genre", null },
                { "id", null },
                { "musicFolderId", null },
                { "offset", null },
                { "p", null },
                { "message", null },
                { "query", null },
                { "s", null },
                { "size", null },
                { "songCount", null },
                { "songOffset", null },
                { "t", null },
                { "toYear", null },
                { "type", null },
                { "u", null },
                { "v", null }
            };

            // Setup model dictionary from Query Parameters
            modelDictionary["albumCount"]    = queryDictionary.ContainsKey("albumCount") ? SafeParser.ToNumber <int?>(queryDictionary["albumCount"].First()) : null;
            modelDictionary["albumOffset"]   = queryDictionary.ContainsKey("albumOffset") ? SafeParser.ToNumber <int?>(queryDictionary["albumOffset"].First()) : null;
            modelDictionary["artist"]        = queryDictionary.ContainsKey("artist") ? queryDictionary["artist"].First() : null;
            modelDictionary["artistCount"]   = queryDictionary.ContainsKey("artistCount") ? SafeParser.ToNumber <int?>(queryDictionary["artistCount"].First()) : null;
            modelDictionary["artistOffset"]  = queryDictionary.ContainsKey("artistOffset") ? SafeParser.ToNumber <int?>(queryDictionary["artistOffset"].First()) : null;
            modelDictionary["c"]             = queryDictionary.ContainsKey("c") ? queryDictionary["c"].First() : null;
            modelDictionary["callback"]      = queryDictionary.ContainsKey("callback") ? queryDictionary["callback"].First() : null;
            modelDictionary["f"]             = queryDictionary.ContainsKey("f") ? queryDictionary["f"].First() : null;
            modelDictionary["fromYear"]      = queryDictionary.ContainsKey("fromYear") ? SafeParser.ToNumber <int?>(queryDictionary["fromYear"].First()) : null;
            modelDictionary["genre"]         = queryDictionary.ContainsKey("genre") ? queryDictionary["genre"].First() : null;
            modelDictionary["id"]            = queryDictionary.ContainsKey("id") ? queryDictionary["id"].First() : null;
            modelDictionary["musicFolderId"] = queryDictionary.ContainsKey("musicFolderId") ? SafeParser.ToNumber <int?>(queryDictionary["musicFolderId"].First()) : null;
            modelDictionary["offset"]        = queryDictionary.ContainsKey("offset") ? SafeParser.ToNumber <int?>(queryDictionary["offset"].First()) : null;
            modelDictionary["p"]             = queryDictionary.ContainsKey("p") ? queryDictionary["p"].First() : null;
            modelDictionary["query"]         = queryDictionary.ContainsKey("query") ? queryDictionary["query"].First() : null;
            modelDictionary["s"]             = queryDictionary.ContainsKey("s") ? queryDictionary["s"].First() : null;
            var size  = queryDictionary.ContainsKey("size") ? SafeParser.ToNumber <int?>(queryDictionary["size"].First()) : null;
            var count = queryDictionary.ContainsKey("count") ? SafeParser.ToNumber <int?>(queryDictionary["count"].First()) : null;

            modelDictionary["size"]       = size ?? count ?? 20;
            modelDictionary["songCount"]  = queryDictionary.ContainsKey("songCount") ? SafeParser.ToNumber <int?>(queryDictionary["songCount"].First()) : null;
            modelDictionary["songOffset"] = queryDictionary.ContainsKey("songOffset") ? SafeParser.ToNumber <int?>(queryDictionary["songOffset"].First()) : null;
            modelDictionary["t"]          = queryDictionary.ContainsKey("t") ? queryDictionary["t"].First() : null;
            modelDictionary["toYear"]     = queryDictionary.ContainsKey("toYear") ? SafeParser.ToNumber <int?>(queryDictionary["toYear"].First()) : null;
            modelDictionary["type"]       = queryDictionary.ContainsKey("type") ? SafeParser.ToEnum <ListType>(queryDictionary["type"].First()) : ListType.AlphabeticalByName;
            modelDictionary["u"]          = queryDictionary.ContainsKey("u") ? queryDictionary["u"].First() : null;
            modelDictionary["v"]          = queryDictionary.ContainsKey("v") ? queryDictionary["v"].First() : null;
            modelDictionary["message"]    = queryDictionary.ContainsKey("message") ? queryDictionary["message"].First() : null;


            // Setup model dictionary from Posted Body values
            var postedIds = new List <string>();

            if (!bindingContext.HttpContext.Request.Method.Equals("GET", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(bindingContext.HttpContext.Request.ContentType))
            {
                var formCollection = bindingContext.HttpContext.Request.Form;
                if (formCollection != null && formCollection.Any())
                {
                    foreach (var form in formCollection)
                    {
                        if (modelDictionary.ContainsKey(form.Key))
                        {
                            modelDictionary[form.Key] = form.Value.FirstOrDefault();
                        }
                        else
                        {
                            modelDictionary.Add(form.Key, form.Value.FirstOrDefault());
                        }
                        if (form.Key == "id")
                        {
                            postedIds.AddRange(form.Value.ToArray());
                        }
                    }
                }
            }

            var model = new SubsonicRequest
            {
                AlbumCount    = SafeParser.ToNumber <short?>(modelDictionary["albumCount"]) ?? 20,
                AlbumOffset   = SafeParser.ToNumber <int?>(modelDictionary["albumOffset"]),
                ArtistCount   = SafeParser.ToNumber <short?>(modelDictionary["artistCount"]) ?? 20,
                ArtistName    = SafeParser.ToString(modelDictionary["artist"]),
                ArtistOffset  = SafeParser.ToNumber <int?>(modelDictionary["artistOffset"]),
                c             = SafeParser.ToString(modelDictionary["c"]),
                callback      = SafeParser.ToString(modelDictionary["callback"]),
                f             = SafeParser.ToString(modelDictionary["f"]),
                FromYear      = SafeParser.ToNumber <int?>(modelDictionary["fromYear"]),
                Genre         = SafeParser.ToString(modelDictionary["genre"]),
                id            = SafeParser.ToString(modelDictionary["id"]),
                ids           = postedIds?.ToArray(),
                MusicFolderId = SafeParser.ToNumber <int?>(modelDictionary["musicFolderId"]),
                Message       = SafeParser.ToString(modelDictionary["message"]),
                Offset        = SafeParser.ToNumber <int?>(modelDictionary["offset"]),
                p             = SafeParser.ToString(modelDictionary["p"]),
                Query         = SafeParser.ToString(modelDictionary["query"]),
                s             = SafeParser.ToString(modelDictionary["s"]),
                Size          = SafeParser.ToNumber <short?>(modelDictionary["size"]),
                SongCount     = SafeParser.ToNumber <short?>(modelDictionary["songCount"]) ?? 20,
                SongOffset    = SafeParser.ToNumber <int?>(modelDictionary["songOffset"]),
                t             = SafeParser.ToString(modelDictionary["t"]),
                ToYear        = SafeParser.ToNumber <int?>(modelDictionary["toYear"]),
                Type          = SafeParser.ToEnum <ListType>(modelDictionary["type"]),
                u             = SafeParser.ToString(modelDictionary["u"]),
                v             = SafeParser.ToString(modelDictionary["v"])
            };

            bindingContext.Result = ModelBindingResult.Success(model);

            return(Task.CompletedTask);
        }