mirror of https://github.com/lidarr/Lidarr
New: Update DB to store all releases for an album (#517)
* New: Store all releases for an album and track artists * Add Overview, links and release date by release * Tidy up * Fix metadata refresh errors following musicbrainz edits
This commit is contained in:
parent
24bdb5a891
commit
c392569a63
3
build.sh
3
build.sh
|
@ -84,7 +84,8 @@ BuildWithMSBuild()
|
|||
BuildWithXbuild()
|
||||
{
|
||||
export MONO_IOMAP=case
|
||||
CheckExitCode msbuild /t:Clean $slnFile
|
||||
CheckExitCode msbuild /p:Configuration=Debug /t:Clean $slnFile
|
||||
CheckExitCode msbuild /p:Configuration=Release /t:Clean $slnFile
|
||||
mono $nuget restore $slnFile
|
||||
CheckExitCode msbuild /p:Configuration=Release /p:Platform=x86 /t:Build /p:AllowedReferenceRelatedFileExtensions=.pdb $slnFile
|
||||
}
|
||||
|
|
|
@ -106,6 +106,7 @@
|
|||
|
||||
.sizeOnDisk,
|
||||
.qualityProfileName,
|
||||
.links,
|
||||
.tags {
|
||||
margin-left: 8px;
|
||||
font-weight: 300;
|
||||
|
|
|
@ -2,14 +2,17 @@ import _ from 'lodash';
|
|||
import moment from 'moment';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import TextTruncate from 'react-text-truncate';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import selectAll from 'Utilities/Table/selectAll';
|
||||
import toggleSelected from 'Utilities/Table/toggleSelected';
|
||||
import { align, icons, sizes } from 'Helpers/Props';
|
||||
import { align, icons, kinds, sizes, tooltipPositions } from 'Helpers/Props';
|
||||
import fonts from 'Styles/Variables/fonts';
|
||||
import HeartRating from 'Components/HeartRating';
|
||||
import Icon from 'Components/Icon';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import Label from 'Components/Label';
|
||||
import Tooltip from 'Components/Tooltip/Tooltip';
|
||||
import AlbumCover from 'Album/AlbumCover';
|
||||
import OrganizePreviewModalConnector from 'Organize/OrganizePreviewModalConnector';
|
||||
import EditAlbumModalConnector from 'Album/Edit/EditAlbumModalConnector';
|
||||
|
@ -24,9 +27,12 @@ import AlbumDetailsMediumConnector from './AlbumDetailsMediumConnector';
|
|||
import ArtistHistoryModal from 'Artist/History/ArtistHistoryModal';
|
||||
import InteractiveSearchModal from 'InteractiveSearch/InteractiveSearchModal';
|
||||
import TrackFileEditorModal from 'TrackFile/Editor/TrackFileEditorModal';
|
||||
|
||||
import AlbumDetailsLinks from './AlbumDetailsLinks';
|
||||
import styles from './AlbumDetails.css';
|
||||
|
||||
const defaultFontSize = parseInt(fonts.defaultFontSize);
|
||||
const lineHeight = parseFloat(fonts.lineHeight);
|
||||
|
||||
function getFanartUrl(images) {
|
||||
const fanartImage = _.find(images, { coverType: 'fanart' });
|
||||
if (fanartImage) {
|
||||
|
@ -135,14 +141,17 @@ class AlbumDetails extends Component {
|
|||
render() {
|
||||
const {
|
||||
id,
|
||||
foreignAlbumId,
|
||||
title,
|
||||
disambiguation,
|
||||
overview,
|
||||
albumType,
|
||||
statistics = {},
|
||||
monitored,
|
||||
releaseDate,
|
||||
ratings,
|
||||
images,
|
||||
links,
|
||||
media,
|
||||
isFetching,
|
||||
isPopulated,
|
||||
|
@ -357,6 +366,38 @@ class AlbumDetails extends Component {
|
|||
</Label>
|
||||
}
|
||||
|
||||
<Tooltip
|
||||
anchor={
|
||||
<Label
|
||||
className={styles.detailsLabel}
|
||||
size={sizes.LARGE}
|
||||
>
|
||||
<Icon
|
||||
name={icons.EXTERNAL_LINK}
|
||||
size={17}
|
||||
/>
|
||||
|
||||
<span className={styles.links}>
|
||||
Links
|
||||
</span>
|
||||
</Label>
|
||||
}
|
||||
tooltip={
|
||||
<AlbumDetailsLinks
|
||||
foreignAlbumId={foreignAlbumId}
|
||||
links={links}
|
||||
/>
|
||||
}
|
||||
kind={kinds.INVERSE}
|
||||
position={tooltipPositions.BOTTOM}
|
||||
/>
|
||||
|
||||
</div>
|
||||
<div className={styles.overview}>
|
||||
<TextTruncate
|
||||
line={Math.floor(125 / (defaultFontSize * lineHeight))}
|
||||
text={overview}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -446,11 +487,13 @@ AlbumDetails.propTypes = {
|
|||
foreignAlbumId: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
disambiguation: PropTypes.string,
|
||||
overview: PropTypes.string,
|
||||
albumType: PropTypes.string.isRequired,
|
||||
statistics: PropTypes.object.isRequired,
|
||||
releaseDate: PropTypes.string.isRequired,
|
||||
ratings: PropTypes.object.isRequired,
|
||||
images: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
links: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
media: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
monitored: PropTypes.bool.isRequired,
|
||||
shortDateFormat: PropTypes.string.isRequired,
|
||||
|
|
|
@ -67,6 +67,10 @@ const mapDispatchToProps = {
|
|||
clearTrackFiles
|
||||
};
|
||||
|
||||
function getMonitoredReleases(props) {
|
||||
return _.map(_.filter(props.releases, { monitored: true }), 'id').sort();
|
||||
}
|
||||
|
||||
class AlbumDetailsConnector extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -75,14 +79,8 @@ class AlbumDetailsConnector extends Component {
|
|||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const {
|
||||
id
|
||||
} = this.props;
|
||||
|
||||
// If the id has changed we need to clear the tracks/track
|
||||
// files and fetch from the server.
|
||||
|
||||
if (prevProps.id !== id) {
|
||||
if (!_.isEqual(getMonitoredReleases(prevProps), getMonitoredReleases(this.props)) ||
|
||||
(prevProps.anyReleaseOk === false && this.props.anyReleaseOk === true)) {
|
||||
this.unpopulate();
|
||||
this.populate();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
.links {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.link {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.linkLabel {
|
||||
composes: label from 'Components/Label.css';
|
||||
|
||||
cursor: pointer;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { kinds, sizes } from 'Helpers/Props';
|
||||
import Label from 'Components/Label';
|
||||
import Link from 'Components/Link/Link';
|
||||
import styles from './AlbumDetailsLinks.css';
|
||||
|
||||
function AlbumDetailsLinks(props) {
|
||||
const {
|
||||
foreignAlbumId,
|
||||
links
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div className={styles.links}>
|
||||
|
||||
<Link
|
||||
className={styles.link}
|
||||
to={`https://musicbrainz.org/release-group/${foreignAlbumId}`}
|
||||
>
|
||||
<Label
|
||||
className={styles.linkLabel}
|
||||
kind={kinds.INFO}
|
||||
size={sizes.LARGE}
|
||||
>
|
||||
Musicbrainz
|
||||
</Label>
|
||||
</Link>
|
||||
|
||||
{links.map((link, index) => {
|
||||
return (
|
||||
<span key={index}>
|
||||
<Link className={styles.link}
|
||||
to={link.url}
|
||||
key={index}
|
||||
>
|
||||
<Label
|
||||
className={styles.linkLabel}
|
||||
kind={kinds.INFO}
|
||||
size={sizes.LARGE}
|
||||
>
|
||||
{link.name}
|
||||
</Label>
|
||||
</Link>
|
||||
{(index > 0 && index % 5 === 0) &&
|
||||
<br />
|
||||
}
|
||||
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
AlbumDetailsLinks.propTypes = {
|
||||
foreignAlbumId: PropTypes.string.isRequired,
|
||||
links: PropTypes.arrayOf(PropTypes.object).isRequired
|
||||
};
|
||||
|
||||
export default AlbumDetailsLinks;
|
|
@ -19,7 +19,7 @@ function getMediumStatistics(tracks) {
|
|||
if (track.trackFileId) {
|
||||
trackCount++;
|
||||
trackFileCount++;
|
||||
} else if (track.monitored) {
|
||||
} else {
|
||||
trackCount++;
|
||||
}
|
||||
|
||||
|
|
|
@ -178,7 +178,6 @@ TrackRow.propTypes = {
|
|||
id: PropTypes.number.isRequired,
|
||||
albumId: PropTypes.number.isRequired,
|
||||
trackFileId: PropTypes.number,
|
||||
monitored: PropTypes.bool.isRequired,
|
||||
mediumNumber: PropTypes.number.isRequired,
|
||||
trackNumber: PropTypes.string.isRequired,
|
||||
absoluteTrackNumber: PropTypes.number,
|
||||
|
|
|
@ -43,7 +43,7 @@ class EditAlbumModalContent extends Component {
|
|||
|
||||
const {
|
||||
monitored,
|
||||
currentRelease,
|
||||
anyReleaseOk,
|
||||
releases
|
||||
} = item;
|
||||
|
||||
|
@ -69,15 +69,26 @@ class EditAlbumModalContent extends Component {
|
|||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Automatically Switch Release</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="anyReleaseOk"
|
||||
helpText="Lidarr will automatically switch to the release best matching downloaded tracks"
|
||||
{...anyReleaseOk}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel> Release</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.ALBUM_RELEASE_SELECT}
|
||||
name="currentRelease"
|
||||
name="releases"
|
||||
helpText="Change release for this album"
|
||||
albumReleases={releases}
|
||||
selectedRelease={currentRelease}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
|
|
@ -23,7 +23,7 @@ function createMapStateToProps() {
|
|||
|
||||
const albumSettings = _.pick(album, [
|
||||
'monitored',
|
||||
'currentRelease',
|
||||
'anyReleaseOk',
|
||||
'releases'
|
||||
]);
|
||||
|
||||
|
|
|
@ -344,6 +344,14 @@ class ArtistDetails extends Component {
|
|||
to={`/artist/${previousArtist.foreignArtistId}`}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
className={styles.artistNavigationButton}
|
||||
name={icons.ARROW_UP}
|
||||
size={30}
|
||||
title={'Go to artist listing'}
|
||||
to={'/'}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
className={styles.artistNavigationButton}
|
||||
name={icons.ARROW_RIGHT}
|
||||
|
|
|
@ -9,15 +9,14 @@ import SelectInput from './SelectInput';
|
|||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state, { albumReleases }) => albumReleases,
|
||||
(state, { selectedRelease }) => selectedRelease,
|
||||
(albumReleases, selectedRelease) => {
|
||||
(albumReleases) => {
|
||||
const values = _.map(albumReleases.value, (albumRelease) => {
|
||||
|
||||
return {
|
||||
key: albumRelease.id,
|
||||
key: albumRelease.foreignReleaseId,
|
||||
value: `${albumRelease.title}` +
|
||||
`${albumRelease.disambiguation ? ' (' : ''}${titleCase(albumRelease.disambiguation)}${albumRelease.disambiguation ? ')' : ''}` +
|
||||
`, ${albumRelease.mediaCount} med, ${albumRelease.trackCount} tracks` +
|
||||
`, ${albumRelease.mediumCount} med, ${albumRelease.trackCount} tracks` +
|
||||
`${albumRelease.country.length > 0 ? ', ' : ''}${albumRelease.country}` +
|
||||
`${albumRelease.format ? ', [' : ''}${albumRelease.format}${albumRelease.format ? ']' : ''}`
|
||||
};
|
||||
|
@ -25,7 +24,7 @@ function createMapStateToProps() {
|
|||
|
||||
const sortedValues = _.orderBy(values, ['value']);
|
||||
|
||||
const value = selectedRelease.value.id;
|
||||
const value = _.find(albumReleases.value, { monitored: true }).foreignReleaseId;
|
||||
|
||||
return {
|
||||
values: sortedValues,
|
||||
|
@ -45,7 +44,10 @@ class AlbumReleaseSelectInputConnector extends Component {
|
|||
albumReleases
|
||||
} = this.props;
|
||||
|
||||
this.props.onChange({ name, value: _.find(albumReleases.value, { id: value }) });
|
||||
let updatedReleases = _.map(albumReleases.value, (e) => ({ ...e, monitored: false }));
|
||||
_.find(updatedReleases, { foreignReleaseId: value }).monitored = true;
|
||||
|
||||
this.props.onChange({ name, value: updatedReleases });
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -105,6 +105,7 @@ class InteractiveImportModalContentConnector extends Component {
|
|||
const {
|
||||
artist,
|
||||
album,
|
||||
albumReleaseId,
|
||||
tracks,
|
||||
quality,
|
||||
language
|
||||
|
@ -140,6 +141,7 @@ class InteractiveImportModalContentConnector extends Component {
|
|||
folderName: item.folderName,
|
||||
artistId: artist.id,
|
||||
albumId: album.id,
|
||||
albumReleaseId,
|
||||
trackIds: _.map(tracks, 'id'),
|
||||
quality,
|
||||
language,
|
||||
|
|
|
@ -14,13 +14,16 @@ namespace Lidarr.Api.V1.Albums
|
|||
{
|
||||
public class AlbumModule : AlbumModuleWithSignalR
|
||||
{
|
||||
public AlbumModule(IArtistService artistService,
|
||||
IAlbumService albumService,
|
||||
IArtistStatisticsService artistStatisticsService,
|
||||
IUpgradableSpecification upgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(albumService, artistStatisticsService, artistService, upgradableSpecification, signalRBroadcaster)
|
||||
protected readonly IReleaseService _releaseService;
|
||||
|
||||
public AlbumModule(IAlbumService albumService,
|
||||
IReleaseService releaseService,
|
||||
IArtistStatisticsService artistStatisticsService,
|
||||
IUpgradableSpecification upgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(albumService, artistStatisticsService, upgradableSpecification, signalRBroadcaster)
|
||||
{
|
||||
_releaseService = releaseService;
|
||||
GetResourceAll = GetAlbums;
|
||||
UpdateResource = UpdateAlbum;
|
||||
Put["/monitor"] = x => SetAlbumsMonitored();
|
||||
|
@ -67,8 +70,9 @@ namespace Lidarr.Api.V1.Albums
|
|||
var model = albumResource.ToModel(album);
|
||||
|
||||
_albumService.UpdateAlbum(model);
|
||||
_releaseService.UpdateMany(model.AlbumReleases.Value);
|
||||
|
||||
BroadcastResourceChange(ModelAction.Updated, albumResource);
|
||||
BroadcastResourceChange(ModelAction.Updated, model.Id);
|
||||
}
|
||||
|
||||
private Response SetAlbumsMonitored()
|
||||
|
|
|
@ -24,19 +24,16 @@ namespace Lidarr.Api.V1.Albums
|
|||
{
|
||||
protected readonly IAlbumService _albumService;
|
||||
protected readonly IArtistStatisticsService _artistStatisticsService;
|
||||
protected readonly IArtistService _artistService;
|
||||
protected readonly IUpgradableSpecification _qualityUpgradableSpecification;
|
||||
|
||||
protected AlbumModuleWithSignalR(IAlbumService albumService,
|
||||
IArtistStatisticsService artistStatisticsService,
|
||||
IArtistService artistService,
|
||||
IUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(signalRBroadcaster)
|
||||
{
|
||||
_albumService = albumService;
|
||||
_artistStatisticsService = artistStatisticsService;
|
||||
_artistService = artistService;
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
|
||||
GetResourceById = GetAlbum;
|
||||
|
@ -44,7 +41,6 @@ namespace Lidarr.Api.V1.Albums
|
|||
|
||||
protected AlbumModuleWithSignalR(IAlbumService albumService,
|
||||
IArtistStatisticsService artistStatisticsService,
|
||||
IArtistService artistService,
|
||||
IUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster,
|
||||
string resource)
|
||||
|
@ -52,7 +48,6 @@ namespace Lidarr.Api.V1.Albums
|
|||
{
|
||||
_albumService = albumService;
|
||||
_artistStatisticsService = artistStatisticsService;
|
||||
_artistService = artistService;
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
|
||||
GetResourceById = GetAlbum;
|
||||
|
@ -71,7 +66,7 @@ namespace Lidarr.Api.V1.Albums
|
|||
|
||||
if (includeArtist)
|
||||
{
|
||||
var artist = album.Artist ?? _artistService.GetArtist(album.ArtistId);
|
||||
var artist = album.Artist.Value;
|
||||
|
||||
resource.Artist = artist.ToResource();
|
||||
}
|
||||
|
@ -92,9 +87,8 @@ namespace Lidarr.Api.V1.Albums
|
|||
{
|
||||
var album = albums[i];
|
||||
var resource = result[i];
|
||||
|
||||
var artist = album.Artist ?? artistDict.GetValueOrDefault(albums[i].ArtistId) ?? _artistService.GetArtist(albums[i].ArtistId);
|
||||
artistDict[artist.Id] = artist;
|
||||
var artist = artistDict.GetValueOrDefault(albums[i].ArtistMetadataId) ?? album.Artist?.Value;
|
||||
artistDict[artist.ArtistMetadataId] = artist;
|
||||
|
||||
resource.Artist = artist.ToResource();
|
||||
}
|
||||
|
|
|
@ -7,15 +7,31 @@ namespace Lidarr.Api.V1.Albums
|
|||
{
|
||||
public class AlbumReleaseResource
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public int Id { get; set; }
|
||||
public int AlbumId { get; set; }
|
||||
public string ForeignReleaseId { get; set; }
|
||||
public string Title { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
public string Status { get; set; }
|
||||
public int Duration { get; set; }
|
||||
public int TrackCount { get; set; }
|
||||
public int MediaCount { get; set; }
|
||||
public List<MediumResource> Media { get; set; }
|
||||
public int MediumCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Media == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Media.Where(s => s.MediumNumber > 0).Count();
|
||||
}
|
||||
}
|
||||
public string Disambiguation { get; set; }
|
||||
public List<string> Country { get; set; }
|
||||
public List<string> Label { get; set; }
|
||||
public string Format { get; set; }
|
||||
public bool Monitored { get; set; }
|
||||
}
|
||||
|
||||
public static class AlbumReleaseResourceMapper
|
||||
|
@ -30,14 +46,23 @@ namespace Lidarr.Api.V1.Albums
|
|||
return new AlbumReleaseResource
|
||||
{
|
||||
Id = model.Id,
|
||||
AlbumId = model.AlbumId,
|
||||
ForeignReleaseId = model.ForeignReleaseId,
|
||||
Title = model.Title,
|
||||
ReleaseDate = model.ReleaseDate,
|
||||
Status = model.Status,
|
||||
Duration = model.Duration,
|
||||
TrackCount = model.TrackCount,
|
||||
MediaCount = model.MediaCount,
|
||||
Media = model.Media.ToResource(),
|
||||
Disambiguation = model.Disambiguation,
|
||||
Country = model.Country,
|
||||
Label = model.Label,
|
||||
Format = model.Format
|
||||
Monitored = model.Monitored,
|
||||
Format = string.Join(", ",
|
||||
model.Media.OrderBy(x => x.Number)
|
||||
.GroupBy(x => x.Format)
|
||||
.Select(g => MediaFormatHelper(g.Key, g.Count()))
|
||||
.ToList())
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -51,17 +76,25 @@ namespace Lidarr.Api.V1.Albums
|
|||
return new AlbumRelease
|
||||
{
|
||||
Id = resource.Id,
|
||||
AlbumId = resource.AlbumId,
|
||||
ForeignReleaseId = resource.ForeignReleaseId,
|
||||
Title = resource.Title,
|
||||
ReleaseDate = resource.ReleaseDate,
|
||||
TrackCount = resource.TrackCount,
|
||||
MediaCount = resource.MediaCount,
|
||||
Status = resource.Status,
|
||||
Duration = resource.Duration,
|
||||
Label = resource.Label,
|
||||
Disambiguation = resource.Disambiguation,
|
||||
Country = resource.Country,
|
||||
Label = resource.Label,
|
||||
Format = resource.Format
|
||||
Media = resource.Media.ToModel(),
|
||||
TrackCount = resource.TrackCount,
|
||||
Monitored = resource.Monitored
|
||||
};
|
||||
}
|
||||
|
||||
private static string MediaFormatHelper(string name, int count)
|
||||
{
|
||||
return count == 1 ? name : string.Join("x", new List<string> {count.ToString(), name});
|
||||
}
|
||||
|
||||
public static List<AlbumReleaseResource> ToResource(this IEnumerable<AlbumRelease> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
|
|
|
@ -13,10 +13,11 @@ namespace Lidarr.Api.V1.Albums
|
|||
{
|
||||
public string Title { get; set; }
|
||||
public string Disambiguation { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public int ArtistId { get; set; }
|
||||
public List<string> AlbumLabel { get; set; }
|
||||
public string ForeignAlbumId { get; set; }
|
||||
public bool Monitored { get; set; }
|
||||
public bool AnyReleaseOk { get; set; }
|
||||
public int ProfileId { get; set; }
|
||||
public int Duration { get; set; }
|
||||
public string AlbumType { get; set; }
|
||||
|
@ -35,12 +36,12 @@ namespace Lidarr.Api.V1.Albums
|
|||
}
|
||||
public Ratings Ratings { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
public AlbumRelease CurrentRelease { get; set; }
|
||||
public List<AlbumReleaseResource> Releases { get; set; }
|
||||
public List<string> Genres { get; set; }
|
||||
public List<MediumResource> Media { get; set; }
|
||||
public ArtistResource Artist { get; set; }
|
||||
public List<MediaCover> Images { get; set; }
|
||||
public List<Links> Links { get; set; }
|
||||
public AlbumStatisticsResource Statistics { get; set; }
|
||||
|
||||
public string RemoteCover { get; set; }
|
||||
|
@ -56,27 +57,30 @@ namespace Lidarr.Api.V1.Albums
|
|||
{
|
||||
if (model == null) return null;
|
||||
|
||||
var selectedRelease = model.AlbumReleases.Value.Where(x => x.Monitored).SingleOrDefault();
|
||||
|
||||
return new AlbumResource
|
||||
{
|
||||
Id = model.Id,
|
||||
ArtistId = model.ArtistId,
|
||||
AlbumLabel = model.Label,
|
||||
ForeignAlbumId = model.ForeignAlbumId,
|
||||
ProfileId = model.ProfileId,
|
||||
Monitored = model.Monitored,
|
||||
AnyReleaseOk = model.AnyReleaseOk,
|
||||
ReleaseDate = model.ReleaseDate,
|
||||
Genres = model.Genres,
|
||||
Title = model.Title,
|
||||
Disambiguation = model.Disambiguation,
|
||||
Overview = model.Overview,
|
||||
Images = model.Images,
|
||||
Links = model.Links,
|
||||
Ratings = model.Ratings,
|
||||
Duration = model.Duration,
|
||||
Duration = selectedRelease.Duration,
|
||||
AlbumType = model.AlbumType,
|
||||
SecondaryTypes = model.SecondaryTypes.Select(s => s.Name).ToList(),
|
||||
Media = model.Media.ToResource(),
|
||||
CurrentRelease = model.CurrentRelease,
|
||||
Releases = model.Releases.ToResource(),
|
||||
Artist = model.Artist.ToResource()
|
||||
Releases = model.AlbumReleases.Value.ToResource(),
|
||||
Media = selectedRelease.Media.ToResource(),
|
||||
Artist = model.Artist.Value.ToResource()
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -90,9 +94,11 @@ namespace Lidarr.Api.V1.Albums
|
|||
ForeignAlbumId = resource.ForeignAlbumId,
|
||||
Title = resource.Title,
|
||||
Disambiguation = resource.Disambiguation,
|
||||
Overview = resource.Overview,
|
||||
Images = resource.Images,
|
||||
Monitored = resource.Monitored,
|
||||
CurrentRelease = resource.CurrentRelease
|
||||
AnyReleaseOk = resource.AnyReleaseOk,
|
||||
AlbumReleases = resource.Releases.ToModel()
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -101,6 +107,7 @@ namespace Lidarr.Api.V1.Albums
|
|||
var updatedAlbum = resource.ToModel();
|
||||
|
||||
album.ApplyChanges(updatedAlbum);
|
||||
album.AlbumReleases = updatedAlbum.AlbumReleases;
|
||||
|
||||
return album;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace Lidarr.Api.V1.Artist
|
|||
foreach (var currentArtist in artist)
|
||||
{
|
||||
var resource = currentArtist.ToResource();
|
||||
var poster = currentArtist.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||
var poster = currentArtist.Metadata.Value.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||
if (poster != null)
|
||||
{
|
||||
resource.RemotePoster = poster.Url;
|
||||
|
|
|
@ -238,7 +238,7 @@ namespace Lidarr.Api.V1.Artist
|
|||
|
||||
public void Handle(TrackImportedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.ImportedTrack.ArtistId);
|
||||
BroadcastResourceChange(ModelAction.Updated, message.TrackInfo.Artist.ToResource());
|
||||
}
|
||||
|
||||
public void Handle(TrackFileDeletedEvent message)
|
||||
|
|
|
@ -76,18 +76,18 @@ namespace Lidarr.Api.V1.Artist
|
|||
//AlternateTitles
|
||||
SortName = model.SortName,
|
||||
|
||||
Status = model.Status,
|
||||
Overview = model.Overview,
|
||||
ArtistType = model.ArtistType,
|
||||
Disambiguation = model.Disambiguation,
|
||||
Status = model.Metadata.Value.Status,
|
||||
Overview = model.Metadata.Value.Overview,
|
||||
ArtistType = model.Metadata.Value.Type,
|
||||
Disambiguation = model.Metadata.Value.Disambiguation,
|
||||
|
||||
Images = model.Images,
|
||||
Images = model.Metadata.Value.Images,
|
||||
|
||||
Path = model.Path,
|
||||
QualityProfileId = model.ProfileId,
|
||||
LanguageProfileId = model.LanguageProfileId,
|
||||
MetadataProfileId = model.MetadataProfileId,
|
||||
Links = model.Links,
|
||||
Links = model.Metadata.Value.Links,
|
||||
|
||||
AlbumFolder = model.AlbumFolder,
|
||||
Monitored = model.Monitored,
|
||||
|
@ -95,14 +95,14 @@ namespace Lidarr.Api.V1.Artist
|
|||
LastInfoSync = model.LastInfoSync,
|
||||
|
||||
CleanName = model.CleanName,
|
||||
ForeignArtistId = model.ForeignArtistId,
|
||||
ForeignArtistId = model.Metadata.Value.ForeignArtistId,
|
||||
// Root folder path is now calculated from the artist path
|
||||
// RootFolderPath = model.RootFolderPath,
|
||||
Genres = model.Genres,
|
||||
Genres = model.Metadata.Value.Genres,
|
||||
Tags = model.Tags,
|
||||
Added = model.Added,
|
||||
AddOptions = model.AddOptions,
|
||||
Ratings = model.Ratings,
|
||||
Ratings = model.Metadata.Value.Ratings,
|
||||
|
||||
Statistics = new ArtistStatisticsResource()
|
||||
};
|
||||
|
@ -116,34 +116,38 @@ namespace Lidarr.Api.V1.Artist
|
|||
{
|
||||
Id = resource.Id,
|
||||
|
||||
Name = resource.ArtistName,
|
||||
Metadata = new NzbDrone.Core.Music.ArtistMetadata
|
||||
{
|
||||
ForeignArtistId = resource.ForeignArtistId,
|
||||
Name = resource.ArtistName,
|
||||
Status = resource.Status,
|
||||
Overview = resource.Overview,
|
||||
Links = resource.Links,
|
||||
Images = resource.Images,
|
||||
Genres = resource.Genres,
|
||||
Ratings = resource.Ratings,
|
||||
Type = resource.ArtistType
|
||||
},
|
||||
|
||||
//AlternateTitles
|
||||
SortName = resource.SortName,
|
||||
|
||||
Status = resource.Status,
|
||||
Overview = resource.Overview,
|
||||
|
||||
Images = resource.Images,
|
||||
|
||||
Path = resource.Path,
|
||||
ProfileId = resource.QualityProfileId,
|
||||
LanguageProfileId = resource.LanguageProfileId,
|
||||
MetadataProfileId = resource.MetadataProfileId,
|
||||
Links = resource.Links,
|
||||
|
||||
|
||||
AlbumFolder = resource.AlbumFolder,
|
||||
Monitored = resource.Monitored,
|
||||
|
||||
LastInfoSync = resource.LastInfoSync,
|
||||
ArtistType = resource.ArtistType,
|
||||
CleanName = resource.CleanName,
|
||||
ForeignArtistId = resource.ForeignArtistId,
|
||||
RootFolderPath = resource.RootFolderPath,
|
||||
Genres = resource.Genres,
|
||||
|
||||
Tags = resource.Tags,
|
||||
Added = resource.Added,
|
||||
AddOptions = resource.AddOptions,
|
||||
Ratings = resource.Ratings
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,9 @@ namespace Lidarr.Api.V1.Calendar
|
|||
{
|
||||
public CalendarModule(IAlbumService albumService,
|
||||
IArtistStatisticsService artistStatisticsService,
|
||||
IArtistService artistService,
|
||||
IUpgradableSpecification ugradableSpecification,
|
||||
IUpgradableSpecification upgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(albumService, artistStatisticsService, artistService, ugradableSpecification, signalRBroadcaster, "calendar")
|
||||
: base(albumService, artistStatisticsService, upgradableSpecification, signalRBroadcaster, "calendar")
|
||||
{
|
||||
GetResourceAll = GetCalendar;
|
||||
}
|
||||
|
|
|
@ -15,16 +15,19 @@ namespace Lidarr.Api.V1.ManualImport
|
|||
{
|
||||
private readonly IArtistService _artistService;
|
||||
private readonly IAlbumService _albumService;
|
||||
private readonly IReleaseService _releaseService;
|
||||
|
||||
public ManualImportModule(IManualImportService manualImportService,
|
||||
IArtistService artistService,
|
||||
IAlbumService albumService,
|
||||
IReleaseService releaseService,
|
||||
IBroadcastSignalRMessage signalRBroadcaster,
|
||||
Logger logger)
|
||||
: base(manualImportService, signalRBroadcaster, logger)
|
||||
{
|
||||
_albumService = albumService;
|
||||
_artistService = artistService;
|
||||
_albumService = albumService;
|
||||
_releaseService = releaseService;
|
||||
|
||||
GetResourceAll = GetMediaFiles;
|
||||
UpdateResource = UpdateImportItem;
|
||||
|
@ -62,6 +65,7 @@ namespace Lidarr.Api.V1.ManualImport
|
|||
Size = resource.Size,
|
||||
Artist = resource.Artist == null ? null : _artistService.GetArtist(resource.Artist.Id),
|
||||
Album = resource.Album == null ? null : _albumService.GetAlbum(resource.Album.Id),
|
||||
Release = resource.AlbumReleaseId == 0 ? null : _releaseService.GetRelease(resource.AlbumReleaseId),
|
||||
Quality = resource.Quality,
|
||||
Language = resource.Language,
|
||||
DownloadId = resource.DownloadId
|
||||
|
|
|
@ -9,6 +9,7 @@ using Lidarr.Api.V1.Tracks;
|
|||
using Lidarr.Http.REST;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Music;
|
||||
|
||||
namespace Lidarr.Api.V1.ManualImport
|
||||
{
|
||||
|
@ -21,6 +22,7 @@ namespace Lidarr.Api.V1.ManualImport
|
|||
public long Size { get; set; }
|
||||
public ArtistResource Artist { get; set; }
|
||||
public AlbumResource Album { get; set; }
|
||||
public int AlbumReleaseId { get; set; }
|
||||
public List<TrackResource> Tracks { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public Language Language { get; set; }
|
||||
|
@ -45,6 +47,7 @@ namespace Lidarr.Api.V1.ManualImport
|
|||
Size = model.Size,
|
||||
Artist = model.Artist.ToResource(),
|
||||
Album = model.Album.ToResource(),
|
||||
AlbumReleaseId = model.Release?.Id ?? 0,
|
||||
Tracks = model.Tracks.ToResource(),
|
||||
Quality = model.Quality,
|
||||
Language = model.Language,
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace Lidarr.Api.V1.Tracks
|
|||
|
||||
if (includeArtist || includeTrackFile)
|
||||
{
|
||||
var artist = track.Artist ?? _artistService.GetArtist(track.ArtistId);
|
||||
var artist = track.Artist.Value;
|
||||
|
||||
if (includeArtist)
|
||||
{
|
||||
|
@ -87,17 +87,15 @@ namespace Lidarr.Api.V1.Tracks
|
|||
{
|
||||
var track = tracks[i];
|
||||
var resource = result[i];
|
||||
|
||||
var series = track.Artist ?? artistDict.GetValueOrDefault(tracks[i].ArtistId) ?? _artistService.GetArtist(tracks[i].ArtistId);
|
||||
artistDict[series.Id] = series;
|
||||
var artist = track.Artist.Value;
|
||||
|
||||
if (includeArtist)
|
||||
{
|
||||
resource.Artist = series.ToResource();
|
||||
resource.Artist = artist.ToResource();
|
||||
}
|
||||
if (includeTrackFile && tracks[i].TrackFileId != 0)
|
||||
{
|
||||
resource.TrackFile = tracks[i].TrackFile.Value.ToResource(series, _upgradableSpecification);
|
||||
resource.TrackFile = tracks[i].TrackFile.Value.ToResource(artist, _upgradableSpecification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ namespace Lidarr.Api.V1.Tracks
|
|||
public TrackFileResource TrackFile { get; set; }
|
||||
public int MediumNumber { get; set; }
|
||||
public bool HasFile { get; set; }
|
||||
public bool Monitored { get; set; }
|
||||
|
||||
public ArtistResource Artist { get; set; }
|
||||
public Ratings Ratings { get; set; }
|
||||
|
@ -52,7 +51,6 @@ namespace Lidarr.Api.V1.Tracks
|
|||
Duration = model.Duration,
|
||||
MediumNumber = model.MediumNumber,
|
||||
HasFile = model.HasFile,
|
||||
Monitored = model.Monitored,
|
||||
Ratings = model.Ratings,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -17,10 +17,9 @@ namespace Lidarr.Api.V1.Wanted
|
|||
public CutoffModule(IAlbumCutoffService albumCutoffService,
|
||||
IAlbumService albumService,
|
||||
IArtistStatisticsService artistStatisticsService,
|
||||
IArtistService artistService,
|
||||
IUpgradableSpecification upgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(albumService, artistStatisticsService, artistService, upgradableSpecification, signalRBroadcaster, "wanted/cutoff")
|
||||
: base(albumService, artistStatisticsService, upgradableSpecification, signalRBroadcaster, "wanted/cutoff")
|
||||
{
|
||||
_albumCutoffService = albumCutoffService;
|
||||
GetResourcePaged = GetCutoffUnmetAlbums;
|
||||
|
@ -41,11 +40,11 @@ namespace Lidarr.Api.V1.Wanted
|
|||
|
||||
if (filter != null && filter.Value == "false")
|
||||
{
|
||||
pagingSpec.FilterExpressions.Add(v => v.Monitored == false || v.Artist.Monitored == false);
|
||||
pagingSpec.FilterExpressions.Add(v => v.Monitored == false || v.Artist.Value.Monitored == false);
|
||||
}
|
||||
else
|
||||
{
|
||||
pagingSpec.FilterExpressions.Add(v => v.Monitored == true && v.Artist.Monitored == true);
|
||||
pagingSpec.FilterExpressions.Add(v => v.Monitored == true && v.Artist.Value.Monitored == true);
|
||||
}
|
||||
|
||||
var resource = ApplyToPage(_albumCutoffService.AlbumsWhereCutoffUnmet, pagingSpec, v => MapToResource(v, includeArtist));
|
||||
|
|
|
@ -14,10 +14,9 @@ namespace Lidarr.Api.V1.Wanted
|
|||
{
|
||||
public MissingModule(IAlbumService albumService,
|
||||
IArtistStatisticsService artistStatisticsService,
|
||||
IArtistService artistService,
|
||||
IUpgradableSpecification upgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(albumService, artistStatisticsService, artistService, upgradableSpecification, signalRBroadcaster, "wanted/missing")
|
||||
: base(albumService, artistStatisticsService, upgradableSpecification, signalRBroadcaster, "wanted/missing")
|
||||
{
|
||||
GetResourcePaged = GetMissingAlbums;
|
||||
}
|
||||
|
@ -37,11 +36,11 @@ namespace Lidarr.Api.V1.Wanted
|
|||
|
||||
if (monitoredFilter != null && monitoredFilter.Value == "false")
|
||||
{
|
||||
pagingSpec.FilterExpressions.Add(v => v.Monitored == false || v.Artist.Monitored == false);
|
||||
pagingSpec.FilterExpressions.Add(v => v.Monitored == false || v.Artist.Value.Monitored == false);
|
||||
}
|
||||
else
|
||||
{
|
||||
pagingSpec.FilterExpressions.Add(v => v.Monitored == true && v.Artist.Monitored == true);
|
||||
pagingSpec.FilterExpressions.Add(v => v.Monitored == true && v.Artist.Value.Monitored == true);
|
||||
}
|
||||
|
||||
var resource = ApplyToPage(_albumService.AlbumsWithoutFiles, pagingSpec, v => MapToResource(v, includeArtist));
|
||||
|
|
|
@ -36,6 +36,11 @@ namespace Marr.Data
|
|||
}
|
||||
}
|
||||
|
||||
public bool ShouldSerializeValue()
|
||||
{
|
||||
return IsLoaded;
|
||||
}
|
||||
|
||||
public bool IsLoaded { get; protected set; }
|
||||
|
||||
public virtual void Prepare(Func<IDataMapper> dataMapperFactory, object parent)
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace NzbDrone.Common.Cloud
|
|||
Services = new HttpRequestBuilder("https://services.lidarr.audio/v1/")
|
||||
.CreateFactory();
|
||||
|
||||
Search = new HttpRequestBuilder("https://api.lidarr.audio/api/v0.3/{route}")
|
||||
Search = new HttpRequestBuilder("https://api.lidarr.audio/api/v0.4/{route}")
|
||||
.CreateFactory();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace NzbDrone.Core.Test.ArtistStatsTests
|
|||
{
|
||||
private Artist _artist;
|
||||
private Album _album;
|
||||
private AlbumRelease _release;
|
||||
private Track _track;
|
||||
private TrackFile _trackFile;
|
||||
|
||||
|
@ -23,25 +24,31 @@ namespace NzbDrone.Core.Test.ArtistStatsTests
|
|||
public void Setup()
|
||||
{
|
||||
_artist = Builder<Artist>.CreateNew()
|
||||
.BuildNew();
|
||||
|
||||
.With(a => a.ArtistMetadataId = 10)
|
||||
.BuildNew();
|
||||
Db.Insert(_artist);
|
||||
|
||||
_album = Builder<Album>.CreateNew()
|
||||
.With(e => e.ReleaseDate = DateTime.Today.AddDays(5))
|
||||
.BuildNew();
|
||||
|
||||
_artist.Id = Db.Insert(_artist).Id;
|
||||
_artist.Id = Db.Insert(_album).Id;
|
||||
.With(e => e.ReleaseDate = DateTime.Today.AddDays(-5))
|
||||
.With(e => e.ArtistMetadataId = 10)
|
||||
.BuildNew();
|
||||
Db.Insert(_album);
|
||||
|
||||
_release = Builder<AlbumRelease>.CreateNew()
|
||||
.With(e => e.AlbumId = _album.Id)
|
||||
.With(e => e.Monitored = true)
|
||||
.BuildNew();
|
||||
Db.Insert(_release);
|
||||
|
||||
_track = Builder<Track>.CreateNew()
|
||||
.With(e => e.TrackFileId = 0)
|
||||
.With(e => e.Monitored = false)
|
||||
.With(e => e.ArtistId = _artist.Id)
|
||||
.With(e => e.AlbumId = _album.Id)
|
||||
.With(e => e.Artist = _artist)
|
||||
.With(e => e.AlbumReleaseId = _release.Id)
|
||||
.BuildNew();
|
||||
|
||||
_trackFile = Builder<TrackFile>.CreateNew()
|
||||
.With(e => e.ArtistId = _artist.Id)
|
||||
.With(e => e.AlbumId = _album.Id)
|
||||
.With(e => e.Artist = _artist)
|
||||
.With(e => e.Album = _album)
|
||||
.With(e => e.Quality = new QualityModel(Quality.MP3_256))
|
||||
.BuildNew();
|
||||
|
||||
|
@ -52,11 +59,6 @@ namespace NzbDrone.Core.Test.ArtistStatsTests
|
|||
_track.TrackFileId = 1;
|
||||
}
|
||||
|
||||
private void GivenMonitoredTrack()
|
||||
{
|
||||
_track.Monitored = true;
|
||||
}
|
||||
|
||||
private void GivenTrack()
|
||||
{
|
||||
Db.Insert(_track);
|
||||
|
@ -70,7 +72,6 @@ namespace NzbDrone.Core.Test.ArtistStatsTests
|
|||
[Test]
|
||||
public void should_get_stats_for_artist()
|
||||
{
|
||||
GivenMonitoredTrack();
|
||||
GivenTrack();
|
||||
|
||||
var stats = Subject.ArtistStatistics();
|
||||
|
@ -115,6 +116,7 @@ namespace NzbDrone.Core.Test.ArtistStatsTests
|
|||
[Test]
|
||||
public void should_have_size_on_disk_when_track_file_exists()
|
||||
{
|
||||
GivenTrackWithFile();
|
||||
GivenTrack();
|
||||
GivenTrackFile();
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace NzbDrone.Core.Test.Datastore.Converters
|
|||
public void should_return_enum_when_getting_int_from_db()
|
||||
{
|
||||
var mockMemberInfo = new Mock<MemberInfo>();
|
||||
mockMemberInfo.SetupGet(s => s.DeclaringType).Returns(typeof(Artist));
|
||||
mockMemberInfo.SetupGet(s => s.DeclaringType).Returns(typeof(ArtistMetadata));
|
||||
mockMemberInfo.SetupGet(s => s.Name).Returns("Status");
|
||||
|
||||
var expected = ArtistStatusType.Continuing;
|
||||
|
|
|
@ -17,13 +17,15 @@ namespace NzbDrone.Core.Test.Datastore
|
|||
public void one_to_one()
|
||||
{
|
||||
var trackFile = Builder<TrackFile>.CreateNew()
|
||||
.With(c => c.Quality = new QualityModel())
|
||||
.With(c => c.Language = Language.English)
|
||||
.BuildNew();
|
||||
.With(c => c.Id = 0)
|
||||
.With(c => c.Quality = new QualityModel())
|
||||
.With(c => c.Language = Language.English)
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(trackFile);
|
||||
|
||||
var track = Builder<Track>.CreateNew()
|
||||
.With(c => c.Id = 0)
|
||||
.With(c => c.TrackFileId = trackFile.Id)
|
||||
.BuildNew();
|
||||
|
||||
|
@ -38,7 +40,9 @@ namespace NzbDrone.Core.Test.Datastore
|
|||
.Excluding(c => c.DateAdded)
|
||||
.Excluding(c => c.Path)
|
||||
.Excluding(c => c.Artist)
|
||||
.Excluding(c => c.Tracks));
|
||||
.Excluding(c => c.Tracks)
|
||||
.Excluding(c => c.Album)
|
||||
.Excluding(c => c.ArtistId));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -9,6 +9,8 @@ using NzbDrone.Core.MediaFiles;
|
|||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Profiles.Languages;
|
||||
using NzbDrone.Core.Test.Languages;
|
||||
using Marr.Data.QGen;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Test.Datastore
|
||||
{
|
||||
|
@ -38,24 +40,44 @@ namespace NzbDrone.Core.Test.Datastore
|
|||
profile = Db.Insert(profile);
|
||||
languageProfile = Db.Insert(languageProfile);
|
||||
|
||||
var metadata = Builder<ArtistMetadata>.CreateNew()
|
||||
.With(v => v.Id = 0)
|
||||
.Build();
|
||||
Db.Insert(metadata);
|
||||
|
||||
var artist = Builder<Artist>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(v => v.Id = 0)
|
||||
.With(v => v.ProfileId = profile.Id)
|
||||
.With(v => v.LanguageProfileId = languageProfile.Id)
|
||||
.With(v => v.ArtistMetadataId = metadata.Id)
|
||||
.BuildListOfNew();
|
||||
|
||||
Db.InsertMany(artist);
|
||||
|
||||
var albums = Builder<Album>.CreateListOfSize(3)
|
||||
.All()
|
||||
.With(v => v.ArtistId = artist[0].Id)
|
||||
.With(v => v.Id = 0)
|
||||
.With(v => v.ArtistMetadataId = metadata.Id)
|
||||
.BuildListOfNew();
|
||||
|
||||
Db.InsertMany(albums);
|
||||
|
||||
var releases = new List<AlbumRelease>();
|
||||
foreach (var album in albums)
|
||||
{
|
||||
releases.Add(
|
||||
Builder<AlbumRelease>.CreateNew()
|
||||
.With(v => v.Id = 0)
|
||||
.With(v => v.AlbumId = album.Id)
|
||||
.With(v => v.ForeignReleaseId = "test" + album.Id)
|
||||
.Build());
|
||||
}
|
||||
Db.InsertMany(releases);
|
||||
|
||||
var trackFiles = Builder<TrackFile>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(v => v.ArtistId = artist[0].Id)
|
||||
.With(v => v.Id = 0)
|
||||
.With(v => v.Quality = new QualityModel())
|
||||
.BuildListOfNew();
|
||||
|
||||
|
@ -63,23 +85,22 @@ namespace NzbDrone.Core.Test.Datastore
|
|||
|
||||
var tracks = Builder<Track>.CreateListOfSize(10)
|
||||
.All()
|
||||
.With(v => v.Monitored = true)
|
||||
.With(v => v.Id = 0)
|
||||
.With(v => v.TrackFileId = trackFiles[0].Id)
|
||||
.With(v => v.ArtistId = artist[0].Id)
|
||||
.With(v => v.AlbumReleaseId = releases[0].Id)
|
||||
.BuildListOfNew();
|
||||
|
||||
Db.InsertMany(tracks);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("This does not currently join correctly, however we are not using the joined info")]
|
||||
public void should_join_artist_when_query_for_albums()
|
||||
{
|
||||
var db = Mocker.Resolve<IDatabase>();
|
||||
var DataMapper = db.GetDataMapper();
|
||||
|
||||
var albums = DataMapper.Query<Album>()
|
||||
.Join<Album, Artist>(Marr.Data.QGen.JoinType.Inner, v => v.Artist, (l, r) => l.ArtistId == r.Id)
|
||||
.Join<Album, Artist>(JoinType.Inner, v => v.Artist, (l, r) => l.ArtistMetadataId == r.ArtistMetadataId)
|
||||
.ToList();
|
||||
|
||||
foreach (var album in albums)
|
||||
|
@ -95,14 +116,19 @@ namespace NzbDrone.Core.Test.Datastore
|
|||
var DataMapper = db.GetDataMapper();
|
||||
|
||||
var tracks = DataMapper.Query<Track>()
|
||||
.Join<Track, Artist>(Marr.Data.QGen.JoinType.Inner, v => v.Artist, (l, r) => l.ArtistId == r.Id)
|
||||
.Join<Track, AlbumRelease>(JoinType.Inner, v => v.AlbumRelease, (l, r) => l.AlbumReleaseId == r.Id)
|
||||
.Join<AlbumRelease, Album>(JoinType.Inner, v => v.Album, (l, r) => l.AlbumId == r.Id)
|
||||
.Join<Album, Artist>(JoinType.Inner, v => v.Artist, (l, r) => l.ArtistMetadataId == r.ArtistMetadataId)
|
||||
.ToList();
|
||||
|
||||
foreach (var track in tracks)
|
||||
{
|
||||
Assert.IsNotNull(track.Artist);
|
||||
Assert.IsFalse(track.Artist.Profile.IsLoaded);
|
||||
Assert.IsFalse(track.Artist.LanguageProfile.IsLoaded);
|
||||
Assert.IsTrue(track.AlbumRelease.IsLoaded);
|
||||
Assert.IsTrue(track.AlbumRelease.Value.Album.IsLoaded);
|
||||
Assert.IsTrue(track.AlbumRelease.Value.Album.Value.Artist.IsLoaded);
|
||||
Assert.IsNotNull(track.AlbumRelease.Value.Album.Value.Artist.Value);
|
||||
Assert.IsFalse(track.AlbumRelease.Value.Album.Value.Artist.Value.Profile.IsLoaded);
|
||||
Assert.IsFalse(track.AlbumRelease.Value.Album.Value.Artist.Value.LanguageProfile.IsLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,12 +139,12 @@ namespace NzbDrone.Core.Test.Datastore
|
|||
var DataMapper = db.GetDataMapper();
|
||||
|
||||
var tracks = DataMapper.Query<Track>()
|
||||
.Join<Track, TrackFile>(Marr.Data.QGen.JoinType.Inner, v => v.TrackFile, (l, r) => l.TrackFileId == r.Id)
|
||||
.Join<Track, TrackFile>(JoinType.Inner, v => v.TrackFile, (l, r) => l.TrackFileId == r.Id)
|
||||
.ToList();
|
||||
|
||||
foreach (var track in tracks)
|
||||
{
|
||||
Assert.IsNull(track.Artist);
|
||||
Assert.IsFalse(track.Artist.IsLoaded);
|
||||
Assert.IsTrue(track.TrackFile.IsLoaded);
|
||||
}
|
||||
}
|
||||
|
@ -130,15 +156,20 @@ namespace NzbDrone.Core.Test.Datastore
|
|||
var DataMapper = db.GetDataMapper();
|
||||
|
||||
var tracks = DataMapper.Query<Track>()
|
||||
.Join<Track, Artist>(Marr.Data.QGen.JoinType.Inner, v => v.Artist, (l, r) => l.ArtistId == r.Id)
|
||||
.Join<Artist, Profile>(Marr.Data.QGen.JoinType.Inner, v => v.Profile, (l, r) => l.ProfileId == r.Id)
|
||||
.Join<Track, AlbumRelease>(JoinType.Inner, v => v.AlbumRelease, (l, r) => l.AlbumReleaseId == r.Id)
|
||||
.Join<AlbumRelease, Album>(JoinType.Inner, v => v.Album, (l, r) => l.AlbumId == r.Id)
|
||||
.Join<Album, Artist>(JoinType.Inner, v => v.Artist, (l, r) => l.ArtistMetadataId == r.ArtistMetadataId)
|
||||
.Join<Artist, Profile>(JoinType.Inner, v => v.Profile, (l, r) => l.ProfileId == r.Id)
|
||||
.ToList();
|
||||
|
||||
foreach (var track in tracks)
|
||||
{
|
||||
Assert.IsNotNull(track.Artist);
|
||||
Assert.IsTrue(track.Artist.Profile.IsLoaded);
|
||||
Assert.IsFalse(track.Artist.LanguageProfile.IsLoaded);
|
||||
Assert.IsTrue(track.AlbumRelease.IsLoaded);
|
||||
Assert.IsTrue(track.AlbumRelease.Value.Album.IsLoaded);
|
||||
Assert.IsTrue(track.AlbumRelease.Value.Album.Value.Artist.IsLoaded);
|
||||
Assert.IsNotNull(track.AlbumRelease.Value.Album.Value.Artist.Value);
|
||||
Assert.IsTrue(track.AlbumRelease.Value.Album.Value.Artist.Value.Profile.IsLoaded);
|
||||
Assert.IsFalse(track.AlbumRelease.Value.Album.Value.Artist.Value.LanguageProfile.IsLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,15 +180,20 @@ namespace NzbDrone.Core.Test.Datastore
|
|||
var DataMapper = db.GetDataMapper();
|
||||
|
||||
var tracks = DataMapper.Query<Track>()
|
||||
.Join<Track, Artist>(Marr.Data.QGen.JoinType.Inner, v => v.Artist, (l, r) => l.ArtistId == r.Id)
|
||||
.Join<Artist, LanguageProfile>(Marr.Data.QGen.JoinType.Inner, v => v.LanguageProfile, (l, r) => l.ProfileId == r.Id)
|
||||
.ToList();
|
||||
.Join<Track, AlbumRelease>(JoinType.Inner, v => v.AlbumRelease, (l, r) => l.AlbumReleaseId == r.Id)
|
||||
.Join<AlbumRelease, Album>(JoinType.Inner, v => v.Album, (l, r) => l.AlbumId == r.Id)
|
||||
.Join<Album, Artist>(JoinType.Inner, v => v.Artist, (l, r) => l.ArtistMetadataId == r.ArtistMetadataId)
|
||||
.Join<Artist, LanguageProfile>(JoinType.Inner, v => v.LanguageProfile, (l, r) => l.LanguageProfileId == r.Id)
|
||||
.ToList();
|
||||
|
||||
foreach (var track in tracks)
|
||||
{
|
||||
Assert.IsNotNull(track.Artist);
|
||||
Assert.IsFalse(track.Artist.Profile.IsLoaded);
|
||||
Assert.IsTrue(track.Artist.LanguageProfile.IsLoaded);
|
||||
Assert.IsTrue(track.AlbumRelease.IsLoaded);
|
||||
Assert.IsTrue(track.AlbumRelease.Value.Album.IsLoaded);
|
||||
Assert.IsTrue(track.AlbumRelease.Value.Album.Value.Artist.IsLoaded);
|
||||
Assert.IsNotNull(track.AlbumRelease.Value.Album.Value.Artist.Value);
|
||||
Assert.IsFalse(track.AlbumRelease.Value.Album.Value.Artist.Value.Profile.IsLoaded);
|
||||
Assert.IsTrue(track.AlbumRelease.Value.Album.Value.Artist.Value.LanguageProfile.IsLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,20 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
private Artist artist;
|
||||
private QualityDefinition qualityType;
|
||||
|
||||
private Album AlbumBuilder(int id = 0)
|
||||
{
|
||||
return new Album
|
||||
{
|
||||
Id = id,
|
||||
AlbumReleases = new List<AlbumRelease> { new AlbumRelease
|
||||
{
|
||||
Duration = 0,
|
||||
Monitored = true
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
|
@ -36,7 +50,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Artist = artist,
|
||||
Release = new ReleaseInfo(),
|
||||
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
|
||||
Albums = new List<Album> { new Album(), new Album(), new Album(), new Album(), new Album(), new Album() }
|
||||
Albums = new List<Album> { AlbumBuilder(), AlbumBuilder(), AlbumBuilder(), AlbumBuilder(), AlbumBuilder(), AlbumBuilder() }
|
||||
};
|
||||
|
||||
parseResultMulti = new RemoteAlbum
|
||||
|
@ -44,7 +58,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Artist = artist,
|
||||
Release = new ReleaseInfo(),
|
||||
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
|
||||
Albums = new List<Album> { new Album(), new Album() }
|
||||
Albums = new List<Album> { AlbumBuilder(), AlbumBuilder() }
|
||||
};
|
||||
|
||||
parseResultSingle = new RemoteAlbum
|
||||
|
@ -52,7 +66,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Artist = artist,
|
||||
Release = new ReleaseInfo(),
|
||||
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
|
||||
Albums = new List<Album> { new Album { Id = 2 } }
|
||||
Albums = new List<Album> { AlbumBuilder(2) }
|
||||
|
||||
};
|
||||
|
||||
|
@ -71,8 +85,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Mocker.GetMock<IAlbumService>().Setup(
|
||||
s => s.GetAlbumsByArtist(It.IsAny<int>()))
|
||||
.Returns(new List<Album>() {
|
||||
new Album(), new Album(), new Album(), new Album(), new Album(),
|
||||
new Album(), new Album(), new Album(), new Album { Id = 2 }, new Album() });
|
||||
AlbumBuilder(), AlbumBuilder(), AlbumBuilder(), AlbumBuilder(), AlbumBuilder(),
|
||||
AlbumBuilder(), AlbumBuilder(), AlbumBuilder(), AlbumBuilder(2), AlbumBuilder() });
|
||||
}
|
||||
|
||||
private void GivenLastAlbum()
|
||||
|
@ -80,8 +94,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Mocker.GetMock<IAlbumService>().Setup(
|
||||
s => s.GetAlbumsByArtist(It.IsAny<int>()))
|
||||
.Returns(new List<Album> {
|
||||
new Album(), new Album(), new Album(), new Album(), new Album(),
|
||||
new Album(), new Album(), new Album(), new Album(), new Album { Id = 2 } });
|
||||
AlbumBuilder(), AlbumBuilder(), AlbumBuilder(), AlbumBuilder(), AlbumBuilder(),
|
||||
AlbumBuilder(), AlbumBuilder(), AlbumBuilder(), AlbumBuilder(), AlbumBuilder(2) });
|
||||
}
|
||||
|
||||
[TestCase(TWENTY_MINUTE_EP_MILLIS, 20, false)]
|
||||
|
@ -92,7 +106,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
[TestCase(FORTY_FIVE_MINUTE_LP_MILLIS, 75, false)]
|
||||
public void single_album(int runtime, int sizeInMegaBytes, bool expectedResult)
|
||||
{
|
||||
parseResultSingle.Albums.Select(c => { c.Duration = runtime; return c; }).ToList();
|
||||
parseResultSingle.Albums.Select(c => { c.AlbumReleases.Value[0].Duration = runtime; return c; }).ToList();
|
||||
parseResultSingle.Artist = artist;
|
||||
parseResultSingle.Release.Size = sizeInMegaBytes.Megabytes();
|
||||
|
||||
|
@ -107,7 +121,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
[TestCase(FORTY_FIVE_MINUTE_LP_MILLIS, 75 * 2, false)]
|
||||
public void multi_album(int runtime, int sizeInMegaBytes, bool expectedResult)
|
||||
{
|
||||
parseResultMulti.Albums.Select(c => { c.Duration = runtime; return c; }).ToList();
|
||||
parseResultMulti.Albums.Select(c => { c.AlbumReleases.Value[0].Duration = runtime; return c; }).ToList();
|
||||
parseResultMulti.Artist = artist;
|
||||
parseResultMulti.Release.Size = sizeInMegaBytes.Megabytes();
|
||||
|
||||
|
@ -122,7 +136,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
[TestCase(FORTY_FIVE_MINUTE_LP_MILLIS, 75 * 6, false)]
|
||||
public void multiset_album(int runtime, int sizeInMegaBytes, bool expectedResult)
|
||||
{
|
||||
parseResultMultiSet.Albums.Select(c => { c.Duration = runtime; return c; }).ToList();
|
||||
parseResultMultiSet.Albums.Select(c => { c.AlbumReleases.Value[0].Duration = runtime; return c; }).ToList();
|
||||
parseResultMultiSet.Artist = artist;
|
||||
parseResultMultiSet.Release.Size = sizeInMegaBytes.Megabytes();
|
||||
|
||||
|
@ -133,7 +147,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
public void should_return_true_if_size_is_zero()
|
||||
{
|
||||
GivenLastAlbum();
|
||||
parseResultSingle.Albums.Select(c => { c.Duration = TWENTY_MINUTE_EP_MILLIS; return c; }).ToList();
|
||||
parseResultSingle.Albums.Select(c => { c.AlbumReleases.Value[0].Duration = TWENTY_MINUTE_EP_MILLIS; return c; }).ToList();
|
||||
parseResultSingle.Artist = artist;
|
||||
parseResultSingle.Release.Size = 0;
|
||||
qualityType.MinSize = 150;
|
||||
|
@ -146,7 +160,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
public void should_return_true_if_unlimited_20_minute()
|
||||
{
|
||||
GivenLastAlbum();
|
||||
parseResultSingle.Albums.Select(c => { c.Duration = TWENTY_MINUTE_EP_MILLIS; return c; }).ToList();
|
||||
parseResultSingle.Albums.Select(c => { c.AlbumReleases.Value[0].Duration = TWENTY_MINUTE_EP_MILLIS; return c; }).ToList();
|
||||
parseResultSingle.Artist = artist;
|
||||
parseResultSingle.Release.Size = (HIGH_KBPS_BITRATE * 128) * (TWENTY_MINUTE_EP_MILLIS / 1000);
|
||||
qualityType.MaxSize = null;
|
||||
|
@ -158,7 +172,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
public void should_return_true_if_unlimited_45_minute()
|
||||
{
|
||||
GivenLastAlbum();
|
||||
parseResultSingle.Albums.Select(c => { c.Duration = FORTY_FIVE_MINUTE_LP_MILLIS; return c; }).ToList();
|
||||
parseResultSingle.Albums.Select(c => { c.AlbumReleases.Value[0].Duration = FORTY_FIVE_MINUTE_LP_MILLIS; return c; }).ToList();
|
||||
parseResultSingle.Artist = artist;
|
||||
parseResultSingle.Release.Size = (HIGH_KBPS_BITRATE * 128) * (FORTY_FIVE_MINUTE_LP_MILLIS / 1000);
|
||||
qualityType.MaxSize = null;
|
||||
|
|
|
@ -11,6 +11,7 @@ using NzbDrone.Core.Test.Framework;
|
|||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.Test.Common;
|
||||
using FizzWare.NBuilder;
|
||||
using Marr.Data;
|
||||
|
||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
{
|
||||
|
@ -233,7 +234,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
var albums = Builder<Album>.CreateListOfSize(2)
|
||||
.All()
|
||||
.With(v => v.ArtistId, artist.Id)
|
||||
.With(v => v.Artist, artist)
|
||||
.With(v => v.Artist, new LazyLoaded<Artist>(artist))
|
||||
.BuildList();
|
||||
|
||||
var criteria = new ArtistSearchCriteria { Albums = albums.Take(1).ToList()};
|
||||
|
|
|
@ -84,7 +84,7 @@ namespace NzbDrone.Core.Test.Download
|
|||
.Setup(v => v.ProcessPath(It.IsAny<string>(), It.IsAny<ImportMode>(), It.IsAny<Artist>(), It.IsAny<DownloadClientItem>()))
|
||||
.Returns(new List<ImportResult>
|
||||
{
|
||||
new ImportResult(new ImportDecision(new LocalTrack() { Path = @"C:\TestPath\Droned.S01E01.mkv" }))
|
||||
new ImportResult(new ImportDecision(new LocalTrack() { Path = @"C:\TestPath\Droned.S01E01.mkv".AsOsAgnostic() }))
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -170,11 +170,11 @@ namespace NzbDrone.Core.Test.Download
|
|||
{
|
||||
new ImportResult(
|
||||
new ImportDecision(
|
||||
new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv"})),
|
||||
new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv".AsOsAgnostic()})),
|
||||
|
||||
new ImportResult(
|
||||
new ImportDecision(
|
||||
new LocalTrack {Path = @"C:\TestPath\Droned.S01E02.mkv"}))
|
||||
new LocalTrack {Path = @"C:\TestPath\Droned.S01E02.mkv".AsOsAgnostic()}))
|
||||
});
|
||||
|
||||
Subject.Process(_trackedDownload);
|
||||
|
@ -191,11 +191,11 @@ namespace NzbDrone.Core.Test.Download
|
|||
{
|
||||
new ImportResult(
|
||||
new ImportDecision(
|
||||
new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv"}, new Rejection("Rejected!")), "Test Failure"),
|
||||
new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv".AsOsAgnostic()}, new Rejection("Rejected!")), "Test Failure"),
|
||||
|
||||
new ImportResult(
|
||||
new ImportDecision(
|
||||
new LocalTrack {Path = @"C:\TestPath\Droned.S01E02.mkv"},new Rejection("Rejected!")), "Test Failure")
|
||||
new LocalTrack {Path = @"C:\TestPath\Droned.S01E02.mkv".AsOsAgnostic()},new Rejection("Rejected!")), "Test Failure")
|
||||
});
|
||||
|
||||
Subject.Process(_trackedDownload);
|
||||
|
@ -215,11 +215,11 @@ namespace NzbDrone.Core.Test.Download
|
|||
{
|
||||
new ImportResult(
|
||||
new ImportDecision(
|
||||
new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv"}, new Rejection("Rejected!")), "Test Failure"),
|
||||
new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv".AsOsAgnostic()}, new Rejection("Rejected!")), "Test Failure"),
|
||||
|
||||
new ImportResult(
|
||||
new ImportDecision(
|
||||
new LocalTrack {Path = @"C:\TestPath\Droned.S01E02.mkv"},new Rejection("Rejected!")), "Test Failure")
|
||||
new LocalTrack {Path = @"C:\TestPath\Droned.S01E02.mkv".AsOsAgnostic()},new Rejection("Rejected!")), "Test Failure")
|
||||
});
|
||||
|
||||
_trackedDownload.RemoteAlbum.Albums.Clear();
|
||||
|
@ -236,8 +236,8 @@ namespace NzbDrone.Core.Test.Download
|
|||
.Setup(v => v.ProcessPath(It.IsAny<string>(), It.IsAny<ImportMode>(), It.IsAny<Artist>(), It.IsAny<DownloadClientItem>()))
|
||||
.Returns(new List<ImportResult>
|
||||
{
|
||||
new ImportResult(new ImportDecision(new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv"}),"Test Failure"),
|
||||
new ImportResult(new ImportDecision(new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv"}),"Test Failure")
|
||||
new ImportResult(new ImportDecision(new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv".AsOsAgnostic()}),"Test Failure"),
|
||||
new ImportResult(new ImportDecision(new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv".AsOsAgnostic()}),"Test Failure")
|
||||
});
|
||||
|
||||
|
||||
|
@ -260,8 +260,8 @@ namespace NzbDrone.Core.Test.Download
|
|||
.Setup(v => v.ProcessPath(It.IsAny<string>(), It.IsAny<ImportMode>(), It.IsAny<Artist>(), It.IsAny<DownloadClientItem>()))
|
||||
.Returns(new List<ImportResult>
|
||||
{
|
||||
new ImportResult(new ImportDecision(new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv"})),
|
||||
new ImportResult(new ImportDecision(new LocalTrack{Path = @"C:\TestPath\Droned.S01E01.mkv"}),"Test Failure")
|
||||
new ImportResult(new ImportDecision(new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv".AsOsAgnostic()})),
|
||||
new ImportResult(new ImportDecision(new LocalTrack{Path = @"C:\TestPath\Droned.S01E01.mkv".AsOsAgnostic()}),"Test Failure")
|
||||
});
|
||||
|
||||
Subject.Process(_trackedDownload);
|
||||
|
@ -283,9 +283,9 @@ namespace NzbDrone.Core.Test.Download
|
|||
.Setup(v => v.ProcessPath(It.IsAny<string>(), It.IsAny<ImportMode>(), It.IsAny<Artist>(), It.IsAny<DownloadClientItem>()))
|
||||
.Returns(new List<ImportResult>
|
||||
{
|
||||
new ImportResult(new ImportDecision(new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv"})),
|
||||
new ImportResult(new ImportDecision(new LocalTrack{Path = @"C:\TestPath\Droned.S01E01.mkv"}),"Test Failure"),
|
||||
new ImportResult(new ImportDecision(new LocalTrack{Path = @"C:\TestPath\Droned.S01E01.mkv"}),"Test Failure")
|
||||
new ImportResult(new ImportDecision(new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv".AsOsAgnostic()})),
|
||||
new ImportResult(new ImportDecision(new LocalTrack{Path = @"C:\TestPath\Droned.S01E01.mkv".AsOsAgnostic()}),"Test Failure"),
|
||||
new ImportResult(new ImportDecision(new LocalTrack{Path = @"C:\TestPath\Droned.S01E01.mkv".AsOsAgnostic()}),"Test Failure")
|
||||
});
|
||||
|
||||
|
||||
|
@ -303,7 +303,7 @@ namespace NzbDrone.Core.Test.Download
|
|||
.Setup(v => v.ProcessPath(It.IsAny<string>(), It.IsAny<ImportMode>(), It.IsAny<Artist>(), It.IsAny<DownloadClientItem>()))
|
||||
.Returns(new List<ImportResult>
|
||||
{
|
||||
new ImportResult(new ImportDecision(new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv"}))
|
||||
new ImportResult(new ImportDecision(new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv".AsOsAgnostic()}))
|
||||
});
|
||||
|
||||
Mocker.GetMock<IArtistService>()
|
||||
|
@ -324,7 +324,7 @@ namespace NzbDrone.Core.Test.Download
|
|||
.Setup(v => v.ProcessPath(It.IsAny<string>(), It.IsAny<ImportMode>(), It.IsAny<Artist>(), It.IsAny<DownloadClientItem>()))
|
||||
.Returns(new List<ImportResult>
|
||||
{
|
||||
new ImportResult(new ImportDecision(new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv"}))
|
||||
new ImportResult(new ImportDecision(new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv".AsOsAgnostic()}))
|
||||
});
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
|
@ -359,7 +359,7 @@ namespace NzbDrone.Core.Test.Download
|
|||
.Setup(v => v.ProcessPath(It.IsAny<string>(), It.IsAny<ImportMode>(), It.IsAny<Artist>(), It.IsAny<DownloadClientItem>()))
|
||||
.Returns(new List<ImportResult>
|
||||
{
|
||||
new ImportResult(new ImportDecision(new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv"}))
|
||||
new ImportResult(new ImportDecision(new LocalTrack {Path = @"C:\TestPath\Droned.S01E01.mkv".AsOsAgnostic()}))
|
||||
});
|
||||
|
||||
Subject.Process(_trackedDownload, true);
|
||||
|
|
|
@ -59,8 +59,10 @@ namespace NzbDrone.Core.Test.HistoryTests
|
|||
var artist = Builder<Artist>.CreateNew().Build();
|
||||
var tracks = Builder<Track>.CreateListOfSize(1).Build().ToList();
|
||||
var trackFile = Builder<TrackFile>.CreateNew()
|
||||
.With(f => f.SceneName = null)
|
||||
.Build();
|
||||
.With(f => f.SceneName = null)
|
||||
.With(f => f.Artist = artist)
|
||||
.With(f => f.Album = new Album())
|
||||
.Build();
|
||||
|
||||
var localTrack = new LocalTrack
|
||||
{
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
|||
public void should_delete_orphaned_albums()
|
||||
{
|
||||
var album = Builder<Album>.CreateNew()
|
||||
.BuildNew();
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(album);
|
||||
Subject.Clean();
|
||||
|
@ -25,19 +25,20 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
|||
public void should_not_delete_unorphaned_albums()
|
||||
{
|
||||
var artist = Builder<Artist>.CreateNew()
|
||||
.BuildNew();
|
||||
.With(e => e.Metadata = new ArtistMetadata {Id = 1})
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(artist);
|
||||
|
||||
var albums = Builder<Album>.CreateListOfSize(2)
|
||||
.TheFirst(1)
|
||||
.With(e => e.ArtistId = artist.Id)
|
||||
.BuildListOfNew();
|
||||
.TheFirst(1)
|
||||
.With(e => e.ArtistMetadataId = artist.Metadata.Value.Id)
|
||||
.BuildListOfNew();
|
||||
|
||||
Db.InsertMany(albums);
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().HaveCount(1);
|
||||
AllStoredModels.Should().Contain(e => e.ArtistId == artist.Id);
|
||||
AllStoredModels.Should().Contain(e => e.ArtistMetadataId == artist.Metadata.Value.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
|||
.BuildNew();
|
||||
|
||||
_album = Builder<Album>.CreateNew()
|
||||
.BuildNew();
|
||||
.BuildNew();
|
||||
}
|
||||
|
||||
private void GivenArtist()
|
||||
|
@ -106,4 +106,4 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
|||
AllStoredModels.Should().Contain(h => h.AlbumId == _album.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
|||
.BuildNew();
|
||||
|
||||
var album = Builder<Album>.CreateNew()
|
||||
.BuildNew();
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(artist);
|
||||
Db.Insert(album);
|
||||
|
|
|
@ -24,20 +24,20 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
|||
[Test]
|
||||
public void should_not_delete_unorphaned_tracks()
|
||||
{
|
||||
var album = Builder<Album>.CreateNew()
|
||||
var release = Builder<AlbumRelease>.CreateNew()
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(album);
|
||||
Db.Insert(release);
|
||||
|
||||
var tracks = Builder<Track>.CreateListOfSize(2)
|
||||
.TheFirst(1)
|
||||
.With(e => e.AlbumId = album.Id)
|
||||
.With(e => e.AlbumReleaseId = release.Id)
|
||||
.BuildListOfNew();
|
||||
|
||||
Db.InsertMany(tracks);
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().HaveCount(1);
|
||||
AllStoredModels.Should().Contain(e => e.AlbumId == album.Id);
|
||||
AllStoredModels.Should().Contain(e => e.AlbumReleaseId == release.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
|
|||
|
||||
Mocker.GetMock<ISearchForNzb>()
|
||||
.Verify(v => v.ArtistSearch(_artist.Id, false, true, false),
|
||||
Times.Exactly(_artist.Albums.Count(s => s.Monitored)));
|
||||
Times.Exactly(_artist.Albums.Value.Count(s => s.Monitored)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
|
|||
|
||||
_artist = Builder<Artist>.CreateNew()
|
||||
.With(v => v.Id = 2)
|
||||
.With(v => v.Images = new List<MediaCover.MediaCover> { new MediaCover.MediaCover(MediaCoverTypes.Poster, "") })
|
||||
.With(v => v.Metadata.Value.Images = new List<MediaCover.MediaCover> { new MediaCover.MediaCover(MediaCoverTypes.Poster, "") })
|
||||
.Build();
|
||||
|
||||
_album = Builder<Album>.CreateNew()
|
||||
|
|
|
@ -49,7 +49,10 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
var album = Builder<Album>.CreateNew()
|
||||
.With(e => e.Artist = artist)
|
||||
.Build();
|
||||
|
||||
|
||||
var release = Builder<AlbumRelease>.CreateNew()
|
||||
.With(e => e.AlbumId = album.Id)
|
||||
.Build();
|
||||
|
||||
var tracks = Builder<Track>.CreateListOfSize(5)
|
||||
.Build();
|
||||
|
@ -68,6 +71,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
{
|
||||
Artist = artist,
|
||||
Album = album,
|
||||
Release = release,
|
||||
Tracks = new List<Track> { track },
|
||||
Path = Path.Combine(artist.Path, "Alien Ant Farm - 01 - Pilot.mp3"),
|
||||
Quality = new QualityModel(Quality.MP3_256),
|
||||
|
|
|
@ -3,6 +3,7 @@ using FluentAssertions;
|
|||
using NUnit.Framework;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.MediaFiles
|
||||
|
@ -13,22 +14,61 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
[Test]
|
||||
public void get_files_by_artist()
|
||||
{
|
||||
|
||||
var files = Builder<TrackFile>.CreateListOfSize(10)
|
||||
.All()
|
||||
.With(c => c.Id = 0)
|
||||
.With(c => c.Quality =new QualityModel(Quality.MP3_192))
|
||||
.Random(4)
|
||||
.With(s => s.ArtistId = 12)
|
||||
.BuildListOfNew();
|
||||
|
||||
|
||||
Db.InsertMany(files);
|
||||
Db.All<TrackFile>().Should().HaveCount(10);
|
||||
|
||||
var artist = Builder<Artist>.CreateNew()
|
||||
.With(a => a.ArtistMetadataId = 11)
|
||||
.With(a => a.Id = 0)
|
||||
.Build();
|
||||
Db.Insert(artist);
|
||||
|
||||
var artistFiles = Subject.GetFilesByArtist(12);
|
||||
var album = Builder<Album>.CreateNew()
|
||||
.With(a => a.Id = 0)
|
||||
.With(a => a.ArtistMetadataId = artist.ArtistMetadataId)
|
||||
.Build();
|
||||
Db.Insert(album);
|
||||
|
||||
var release = Builder<AlbumRelease>.CreateNew()
|
||||
.With(a => a.Id = 0)
|
||||
.With(a => a.AlbumId = album.Id)
|
||||
.With(a => a.Monitored = true)
|
||||
.Build();
|
||||
Db.Insert(release);
|
||||
|
||||
var track = Builder<Track>.CreateListOfSize(10)
|
||||
.TheFirst(1)
|
||||
.With(a => a.TrackFileId = files[1].Id)
|
||||
.TheNext(1)
|
||||
.With(a => a.TrackFileId = files[2].Id)
|
||||
.TheNext(1)
|
||||
.With(a => a.TrackFileId = files[3].Id)
|
||||
.TheNext(1)
|
||||
.With(a => a.TrackFileId = files[4].Id)
|
||||
.TheNext(6)
|
||||
.With(a => a.TrackFileId = 0)
|
||||
.All()
|
||||
.With(a => a.Id = 0)
|
||||
.With(a => a.AlbumReleaseId = release.Id)
|
||||
.Build();
|
||||
Db.InsertMany(track);
|
||||
|
||||
Db.All<Artist>().Should().HaveCount(1);
|
||||
Db.All<Album>().Should().HaveCount(1);
|
||||
Db.All<Track>().Should().HaveCount(10);
|
||||
|
||||
var artistFiles = Subject.GetFilesByArtist(artist.Id);
|
||||
|
||||
artistFiles.Should().HaveCount(4);
|
||||
artistFiles.Should().OnlyContain(c => c.ArtistId == 12);
|
||||
|
||||
artistFiles.Should().OnlyContain(c => c.ArtistId == artist.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
|
||||
_trackFiles = Builder<TrackFile>.CreateListOfSize(2)
|
||||
.All()
|
||||
.With(e => e.ArtistId = _artist.Id)
|
||||
.With(e => e.Artist = _artist)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
|
|
|
@ -41,6 +41,14 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
|
|||
Allowed = true
|
||||
}
|
||||
},
|
||||
ReleaseStatuses = new List<ProfileReleaseStatusItem>
|
||||
{
|
||||
new ProfileReleaseStatusItem
|
||||
{
|
||||
ReleaseStatus = ReleaseStatus.Official,
|
||||
Allowed = true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Mocker.GetMock<IMetadataProfileService>()
|
||||
|
@ -58,34 +66,33 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
|
|||
{
|
||||
var details = Subject.GetArtistInfo(mbId, 1);
|
||||
|
||||
ValidateArtist(details.Item1);
|
||||
ValidateAlbums(details.Item2);
|
||||
ValidateArtist(details);
|
||||
ValidateAlbums(details.Albums.Value);
|
||||
|
||||
details.Item1.Name.Should().Be(name);
|
||||
details.Name.Should().Be(name);
|
||||
}
|
||||
|
||||
[TestCase("12fa3845-7c62-36e5-a8da-8be137155a72", null, "Hysteria")]
|
||||
public void should_be_able_to_get_album_detail(string mbId, string release, string name)
|
||||
[TestCase("12fa3845-7c62-36e5-a8da-8be137155a72", "Hysteria")]
|
||||
public void should_be_able_to_get_album_detail(string mbId, string name)
|
||||
{
|
||||
var details = Subject.GetAlbumInfo(mbId, release);
|
||||
var details = Subject.GetAlbumInfo(mbId);
|
||||
|
||||
ValidateAlbums(new List<Album> {details.Item1});
|
||||
ValidateAlbums(new List<Album> {details.Item2});
|
||||
|
||||
details.Item1.Title.Should().Be(name);
|
||||
details.Item2.Title.Should().Be(name);
|
||||
}
|
||||
|
||||
[TestCase("12fa3845-7c62-36e5-a8da-8be137155a72", "3c186b52-ca73-46a3-a8e6-04559bfbb581",1, 13, "Hysteria")]
|
||||
[TestCase("12fa3845-7c62-36e5-a8da-8be137155a72", "dee9ca6f-4f84-4359-82a9-b75a37ffc316",2, 27,"Hysteria")]
|
||||
public void should_be_able_to_get_album_detail_with_release(string mbId, string release, int mediaCount, int trackCount, string name)
|
||||
{
|
||||
var details = Subject.GetAlbumInfo(mbId, release);
|
||||
var details = Subject.GetAlbumInfo(mbId);
|
||||
|
||||
ValidateAlbums(new List<Album> { details.Item1 });
|
||||
ValidateAlbums(new List<Album> { details.Item2 });
|
||||
|
||||
details.Item1.Media.Count.Should().Be(mediaCount);
|
||||
details.Item2.Count.Should().Be(trackCount);
|
||||
|
||||
details.Item1.Title.Should().Be(name);
|
||||
details.Item2.AlbumReleases.Value.Single(r => r.ForeignReleaseId == release).Media.Count.Should().Be(mediaCount);
|
||||
details.Item2.AlbumReleases.Value.Single(r => r.ForeignReleaseId == release).Tracks.Value.Count.Should().Be(trackCount);
|
||||
details.Item2.Title.Should().Be(name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -103,13 +110,13 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
|
|||
[Test]
|
||||
public void getting_details_of_invalid_album()
|
||||
{
|
||||
Assert.Throws<AlbumNotFoundException>(() => Subject.GetAlbumInfo("66c66aaa-6e2f-4930-8610-912e24c63ed1",null));
|
||||
Assert.Throws<AlbumNotFoundException>(() => Subject.GetAlbumInfo("66c66aaa-6e2f-4930-8610-912e24c63ed1"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void getting_details_of_invalid_guid_for_album()
|
||||
{
|
||||
Assert.Throws<BadRequestException>(() => Subject.GetAlbumInfo("66c66aaa-6e2f-4930-aaaaaa", null));
|
||||
Assert.Throws<BadRequestException>(() => Subject.GetAlbumInfo("66c66aaa-6e2f-4930-aaaaaa"));
|
||||
}
|
||||
|
||||
private void ValidateArtist(Artist artist)
|
||||
|
@ -118,8 +125,8 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
|
|||
artist.Name.Should().NotBeNullOrWhiteSpace();
|
||||
artist.CleanName.Should().Be(Parser.Parser.CleanArtistName(artist.Name));
|
||||
artist.SortName.Should().Be(Parser.Parser.NormalizeTitle(artist.Name));
|
||||
artist.Overview.Should().NotBeNullOrWhiteSpace();
|
||||
artist.Images.Should().NotBeEmpty();
|
||||
artist.Metadata.Value.Overview.Should().NotBeNullOrWhiteSpace();
|
||||
artist.Metadata.Value.Images.Should().NotBeEmpty();
|
||||
artist.ForeignArtistId.Should().NotBeNullOrWhiteSpace();
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,14 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
|
|||
Allowed = true
|
||||
}
|
||||
},
|
||||
ReleaseStatuses = new List<ProfileReleaseStatusItem>
|
||||
{
|
||||
new ProfileReleaseStatusItem
|
||||
{
|
||||
ReleaseStatus = ReleaseStatus.Official,
|
||||
Allowed = true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Mocker.GetMock<IMetadataProfileService>()
|
||||
|
|
|
@ -19,6 +19,9 @@ namespace NzbDrone.Core.Test.MusicTests
|
|||
public class AddAlbumFixture : CoreTest<AddAlbumService>
|
||||
{
|
||||
private Album _fakeAlbum;
|
||||
private AlbumRelease _fakeRelease;
|
||||
private readonly string _fakeArtistForeignId = "xxx-xxx-xxx";
|
||||
private readonly List<ArtistMetadata> _fakeArtists = new List<ArtistMetadata> { new ArtistMetadata() };
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
|
@ -26,13 +29,18 @@ namespace NzbDrone.Core.Test.MusicTests
|
|||
_fakeAlbum = Builder<Album>
|
||||
.CreateNew()
|
||||
.Build();
|
||||
_fakeRelease = Builder<AlbumRelease>
|
||||
.CreateNew()
|
||||
.Build();
|
||||
_fakeRelease.Tracks = new List<Track>();
|
||||
_fakeAlbum.AlbumReleases = new List<AlbumRelease> {_fakeRelease};
|
||||
}
|
||||
|
||||
private void GivenValidAlbum(string lidarrId)
|
||||
{
|
||||
Mocker.GetMock<IProvideAlbumInfo>()
|
||||
.Setup(s => s.GetAlbumInfo(lidarrId, It.IsAny<string>()))
|
||||
.Returns(new Tuple<Album, List<Track>>(_fakeAlbum, new List<Track>()));
|
||||
.Setup(s => s.GetAlbumInfo(lidarrId))
|
||||
.Returns(new Tuple<string, Album, List<ArtistMetadata>>(_fakeArtistForeignId, _fakeAlbum, _fakeArtists));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -59,8 +67,8 @@ namespace NzbDrone.Core.Test.MusicTests
|
|||
};
|
||||
|
||||
Mocker.GetMock<IProvideAlbumInfo>()
|
||||
.Setup(s => s.GetAlbumInfo(newAlbum.ForeignAlbumId, It.IsAny<string>()))
|
||||
.Throws(new AlbumNotFoundException(newAlbum.ForeignAlbumId));
|
||||
.Setup(s => s.GetAlbumInfo(newAlbum.ForeignAlbumId))
|
||||
.Throws(new AlbumNotFoundException(newAlbum.ForeignAlbumId));
|
||||
|
||||
Assert.Throws<ValidationException>(() => Subject.AddAlbum(newAlbum));
|
||||
|
||||
|
|
|
@ -28,13 +28,14 @@ namespace NzbDrone.Core.Test.MusicTests
|
|||
.CreateNew()
|
||||
.With(s => s.Path = null)
|
||||
.Build();
|
||||
_fakeArtist.Albums = new List<Album>();
|
||||
}
|
||||
|
||||
private void GivenValidArtist(string lidarrId)
|
||||
{
|
||||
Mocker.GetMock<IProvideArtistInfo>()
|
||||
.Setup(s => s.GetArtistInfo(lidarrId, It.IsAny<int>()))
|
||||
.Returns(new Tuple<Artist, List<Album>>(_fakeArtist, new List<Album>()));
|
||||
.Setup(s => s.GetArtistInfo(lidarrId, It.IsAny<int>()))
|
||||
.Returns(_fakeArtist);
|
||||
}
|
||||
|
||||
private void GivenValidPath()
|
||||
|
|
|
@ -3,12 +3,7 @@ using FluentAssertions;
|
|||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
|
||||
namespace NzbDrone.Core.Test.MusicTests.AlbumRepositoryTests
|
||||
{
|
||||
|
@ -19,7 +14,9 @@ namespace NzbDrone.Core.Test.MusicTests.AlbumRepositoryTests
|
|||
private Album _album;
|
||||
private Album _albumSpecial;
|
||||
private Album _albumSimilar;
|
||||
private AlbumRelease _release;
|
||||
private AlbumRepository _albumRepo;
|
||||
private ReleaseRepository _releaseRepo;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
|
@ -28,11 +25,22 @@ namespace NzbDrone.Core.Test.MusicTests.AlbumRepositoryTests
|
|||
{
|
||||
Name = "Alien Ant Farm",
|
||||
Monitored = true,
|
||||
MBId = "this is a fake id",
|
||||
Id = 1
|
||||
ForeignArtistId = "this is a fake id",
|
||||
Id = 1,
|
||||
Metadata = new ArtistMetadata {
|
||||
Id = 1
|
||||
}
|
||||
};
|
||||
|
||||
_albumRepo = Mocker.Resolve<AlbumRepository>();
|
||||
_releaseRepo = Mocker.Resolve<ReleaseRepository>();
|
||||
|
||||
_release = Builder<AlbumRelease>
|
||||
.CreateNew()
|
||||
.With(e => e.Id = 0)
|
||||
.With(e => e.ForeignReleaseId = "e00e40a3-5ed5-4ed3-9c22-0a8ff4119bdf" )
|
||||
.With(e => e.Monitored = true)
|
||||
.Build();
|
||||
|
||||
_album = new Album
|
||||
{
|
||||
|
@ -40,19 +48,14 @@ namespace NzbDrone.Core.Test.MusicTests.AlbumRepositoryTests
|
|||
ForeignAlbumId = "1",
|
||||
CleanTitle = "anthology",
|
||||
Artist = _artist,
|
||||
ArtistId = _artist.Id,
|
||||
AlbumType = "",
|
||||
Releases = new List<AlbumRelease>
|
||||
{
|
||||
new AlbumRelease
|
||||
{
|
||||
Id = "e00e40a3-5ed5-4ed3-9c22-0a8ff4119bdf"
|
||||
}
|
||||
}
|
||||
|
||||
AlbumReleases = new List<AlbumRelease> {_release },
|
||||
};
|
||||
|
||||
_albumRepo.Insert(_album);
|
||||
_release.AlbumId = _album.Id;
|
||||
_releaseRepo.Insert(_release);
|
||||
_albumRepo.Update(_album);
|
||||
|
||||
_albumSpecial = new Album
|
||||
{
|
||||
|
@ -60,13 +63,13 @@ namespace NzbDrone.Core.Test.MusicTests.AlbumRepositoryTests
|
|||
ForeignAlbumId = "2",
|
||||
CleanTitle = "",
|
||||
Artist = _artist,
|
||||
ArtistId = _artist.Id,
|
||||
ArtistId = _artist.ArtistMetadataId,
|
||||
AlbumType = "",
|
||||
Releases = new List<AlbumRelease>
|
||||
AlbumReleases = new List<AlbumRelease>
|
||||
{
|
||||
new AlbumRelease
|
||||
{
|
||||
Id = "fake id"
|
||||
ForeignReleaseId = "fake id"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,13 +83,13 @@ namespace NzbDrone.Core.Test.MusicTests.AlbumRepositoryTests
|
|||
ForeignAlbumId = "3",
|
||||
CleanTitle = "anthology2",
|
||||
Artist = _artist,
|
||||
ArtistId = _artist.Id,
|
||||
ArtistId = _artist.ArtistMetadataId,
|
||||
AlbumType = "",
|
||||
Releases = new List<AlbumRelease>
|
||||
AlbumReleases = new List<AlbumRelease>
|
||||
{
|
||||
new AlbumRelease
|
||||
{
|
||||
Id = "fake id 2"
|
||||
ForeignReleaseId = "fake id 2"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +113,7 @@ namespace NzbDrone.Core.Test.MusicTests.AlbumRepositoryTests
|
|||
[TestCase("anthology!")]
|
||||
public void should_find_album_in_db_by_title(string title)
|
||||
{
|
||||
var album = _albumRepo.FindByTitle(_artist.Id, title);
|
||||
var album = _albumRepo.FindByTitle(_artist.ArtistMetadataId, title);
|
||||
|
||||
album.Should().NotBeNull();
|
||||
album.Title.Should().Be(_album.Title);
|
||||
|
@ -119,7 +122,7 @@ namespace NzbDrone.Core.Test.MusicTests.AlbumRepositoryTests
|
|||
[Test]
|
||||
public void should_find_album_in_db_by_title_all_special_characters()
|
||||
{
|
||||
var album = _albumRepo.FindByTitle(_artist.Id, "+");
|
||||
var album = _albumRepo.FindByTitle(_artist.ArtistMetadataId, "+");
|
||||
|
||||
album.Should().NotBeNull();
|
||||
album.Title.Should().Be(_albumSpecial.Title);
|
||||
|
@ -131,7 +134,7 @@ namespace NzbDrone.Core.Test.MusicTests.AlbumRepositoryTests
|
|||
[TestCase("÷")]
|
||||
public void should_not_find_album_in_db_by_incorrect_title(string title)
|
||||
{
|
||||
var album = _albumRepo.FindByTitle(_artist.Id, title);
|
||||
var album = _albumRepo.FindByTitle(_artist.ArtistMetadataId, title);
|
||||
|
||||
album.Should().BeNull();
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace NzbDrone.Core.Test.MusicTests.AlbumRepositoryTests
|
|||
});
|
||||
|
||||
Mocker.GetMock<IAlbumRepository>()
|
||||
.Setup(s => s.GetAlbums(It.IsAny<int>()))
|
||||
.Setup(s => s.GetAlbumsByArtistMetadataId(It.IsAny<int>()))
|
||||
.Returns(_albums);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,21 +18,32 @@ namespace NzbDrone.Core.Test.MusicTests.ArtistRepositoryTests
|
|||
public class ArtistRepositoryFixture : DbTest<ArtistRepository, Artist>
|
||||
{
|
||||
private ArtistRepository _artistRepo;
|
||||
private ArtistMetadataRepository _artistMetadataRepo;
|
||||
|
||||
private Artist CreateArtist(string name)
|
||||
private void AddArtist(string name)
|
||||
{
|
||||
return Builder<Artist>.CreateNew()
|
||||
var metadata = Builder<ArtistMetadata>.CreateNew()
|
||||
.With(a => a.Id = 0)
|
||||
.With(a => a.Name = name)
|
||||
.BuildNew();
|
||||
|
||||
var artist = Builder<Artist>.CreateNew()
|
||||
.With(a => a.Id = 0)
|
||||
.With(a => a.Metadata = metadata)
|
||||
.With(a => a.CleanName = Parser.Parser.CleanArtistName(name))
|
||||
.With(a => a.ForeignArtistId = name)
|
||||
.BuildNew();
|
||||
|
||||
_artistMetadataRepo.Insert(artist);
|
||||
_artistRepo.Insert(artist);
|
||||
}
|
||||
|
||||
private void GivenArtists()
|
||||
{
|
||||
_artistRepo = Mocker.Resolve<ArtistRepository>();
|
||||
_artistRepo.Insert(CreateArtist("The Black Eyed Peas"));
|
||||
_artistRepo.Insert(CreateArtist("The Black Keys"));
|
||||
_artistMetadataRepo = Mocker.Resolve<ArtistMetadataRepository>();
|
||||
AddArtist("The Black Eyed Peas");
|
||||
AddArtist("The Black Keys");
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -19,29 +19,46 @@ namespace NzbDrone.Core.Test.MusicTests
|
|||
{
|
||||
private Artist _artist;
|
||||
private List<Album> _albums;
|
||||
private List<AlbumRelease> _releases;
|
||||
private readonly string _fakeArtistForeignId = "xxx-xxx-xxx";
|
||||
private readonly List<ArtistMetadata> _fakeArtists = new List<ArtistMetadata> { new ArtistMetadata() };
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var album1 = Builder<Album>.CreateNew()
|
||||
.With(s => s.ForeignAlbumId = "1")
|
||||
|
||||
var release = Builder<AlbumRelease>
|
||||
.CreateNew()
|
||||
.With(s => s.Media = new List<Medium> { new Medium { Number = 1 } })
|
||||
.With(s => s.ForeignReleaseId = "xxx-xxx-xxx-xxx")
|
||||
.With(s => s.Monitored = true)
|
||||
.With(s => s.TrackCount = 10)
|
||||
.Build();
|
||||
|
||||
_albums = new List<Album>{album1};
|
||||
_releases = new List<AlbumRelease> { release };
|
||||
|
||||
var album1 = Builder<Album>.CreateNew()
|
||||
.With(s => s.Id = 1234)
|
||||
.With(s => s.ForeignAlbumId = "1")
|
||||
.With(s => s.AlbumReleases = _releases)
|
||||
.Build();
|
||||
|
||||
_albums = new List<Album>{ album1 };
|
||||
|
||||
_artist = Builder<Artist>.CreateNew()
|
||||
.With(s => s.Albums = new List<Album>
|
||||
{
|
||||
album1
|
||||
})
|
||||
.Build();
|
||||
.With(s => s.Albums = _albums)
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<IArtistService>()
|
||||
.Setup(s => s.GetArtist(_artist.Id))
|
||||
.Returns(_artist);
|
||||
|
||||
Mocker.GetMock<IReleaseService>()
|
||||
.Setup(s => s.GetReleasesByAlbum(album1.Id))
|
||||
.Returns(new List<AlbumRelease> { release });
|
||||
|
||||
Mocker.GetMock<IProvideAlbumInfo>()
|
||||
.Setup(s => s.GetAlbumInfo(It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Setup(s => s.GetAlbumInfo(It.IsAny<string>()))
|
||||
.Callback(() => { throw new AlbumNotFoundException(album1.ForeignAlbumId); });
|
||||
|
||||
Mocker.GetMock<ICheckIfAlbumShouldBeRefreshed>()
|
||||
|
@ -52,8 +69,8 @@ namespace NzbDrone.Core.Test.MusicTests
|
|||
private void GivenNewAlbumInfo(Album album)
|
||||
{
|
||||
Mocker.GetMock<IProvideAlbumInfo>()
|
||||
.Setup(s => s.GetAlbumInfo(_albums.First().ForeignAlbumId, It.IsAny<string>()))
|
||||
.Returns(new Tuple<Album, List<Track>>(album, new List<Track>()));
|
||||
.Setup(s => s.GetAlbumInfo(_albums.First().ForeignAlbumId))
|
||||
.Returns(new Tuple<string, Album, List<ArtistMetadata>>(_fakeArtistForeignId, album, _fakeArtists));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -72,6 +89,7 @@ namespace NzbDrone.Core.Test.MusicTests
|
|||
{
|
||||
var newAlbumInfo = _albums.FirstOrDefault().JsonClone();
|
||||
newAlbumInfo.ForeignAlbumId = _albums.First().ForeignAlbumId + 1;
|
||||
newAlbumInfo.AlbumReleases = _releases;
|
||||
|
||||
GivenNewAlbumInfo(newAlbumInfo);
|
||||
|
||||
|
|
|
@ -35,8 +35,11 @@ namespace NzbDrone.Core.Test.MusicTests
|
|||
|
||||
_albums = new List<Album> {_album1, _album2};
|
||||
|
||||
var metadata = Builder<ArtistMetadata>.CreateNew().Build();
|
||||
|
||||
_artist = Builder<Artist>.CreateNew()
|
||||
.Build();
|
||||
.With(a => a.Metadata = metadata)
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<IArtistService>()
|
||||
.Setup(s => s.GetArtist(_artist.Id))
|
||||
|
@ -55,7 +58,7 @@ namespace NzbDrone.Core.Test.MusicTests
|
|||
{
|
||||
Mocker.GetMock<IProvideArtistInfo>()
|
||||
.Setup(s => s.GetArtistInfo(_artist.ForeignArtistId, _artist.MetadataProfileId))
|
||||
.Returns(new Tuple<Artist, List<Album>>(artist, _albums));
|
||||
.Returns(artist);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -73,6 +76,8 @@ namespace NzbDrone.Core.Test.MusicTests
|
|||
public void should_update_if_musicbrainz_id_changed()
|
||||
{
|
||||
var newArtistInfo = _artist.JsonClone();
|
||||
newArtistInfo.Metadata = _artist.Metadata.Value.JsonClone();
|
||||
newArtistInfo.Albums = _albums;
|
||||
newArtistInfo.ForeignArtistId = _artist.ForeignArtistId + 1;
|
||||
|
||||
GivenNewArtistInfo(newArtistInfo);
|
||||
|
@ -90,24 +95,24 @@ namespace NzbDrone.Core.Test.MusicTests
|
|||
public void should_not_throw_if_duplicate_album_is_in_existing_info()
|
||||
{
|
||||
var newArtistInfo = _artist.JsonClone();
|
||||
newArtistInfo.Albums.Add(Builder<Album>.CreateNew()
|
||||
.With(s => s.ForeignAlbumId = "2")
|
||||
.Build());
|
||||
newArtistInfo.Albums.Value.Add(Builder<Album>.CreateNew()
|
||||
.With(s => s.ForeignAlbumId = "2")
|
||||
.Build());
|
||||
|
||||
_artist.Albums.Add(Builder<Album>.CreateNew()
|
||||
.With(s => s.ForeignAlbumId = "2")
|
||||
.Build());
|
||||
_artist.Albums.Value.Add(Builder<Album>.CreateNew()
|
||||
.With(s => s.ForeignAlbumId = "2")
|
||||
.Build());
|
||||
|
||||
_artist.Albums.Add(Builder<Album>.CreateNew()
|
||||
.With(s => s.ForeignAlbumId = "2")
|
||||
.Build());
|
||||
_artist.Albums.Value.Add(Builder<Album>.CreateNew()
|
||||
.With(s => s.ForeignAlbumId = "2")
|
||||
.Build());
|
||||
|
||||
GivenNewArtistInfo(newArtistInfo);
|
||||
|
||||
Subject.Execute(new RefreshArtistCommand(_artist.Id));
|
||||
|
||||
Mocker.GetMock<IArtistService>()
|
||||
.Verify(v => v.UpdateArtist(It.Is<Artist>(s => s.Albums.Count == 2)));
|
||||
.Verify(v => v.UpdateArtist(It.Is<Artist>(s => s.Albums.Value.Count == 2)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -115,20 +120,20 @@ namespace NzbDrone.Core.Test.MusicTests
|
|||
public void should_filter_duplicate_albums()
|
||||
{
|
||||
var newArtistInfo = _artist.JsonClone();
|
||||
newArtistInfo.Albums.Add(Builder<Album>.CreateNew()
|
||||
.With(s => s.ForeignAlbumId = "2")
|
||||
.Build());
|
||||
newArtistInfo.Albums.Value.Add(Builder<Album>.CreateNew()
|
||||
.With(s => s.ForeignAlbumId = "2")
|
||||
.Build());
|
||||
|
||||
newArtistInfo.Albums.Add(Builder<Album>.CreateNew()
|
||||
.With(s => s.ForeignAlbumId = "2")
|
||||
.Build());
|
||||
newArtistInfo.Albums.Value.Add(Builder<Album>.CreateNew()
|
||||
.With(s => s.ForeignAlbumId = "2")
|
||||
.Build());
|
||||
|
||||
GivenNewArtistInfo(newArtistInfo);
|
||||
|
||||
Subject.Execute(new RefreshArtistCommand(_artist.Id));
|
||||
|
||||
Mocker.GetMock<IArtistService>()
|
||||
.Verify(v => v.UpdateArtist(It.Is<Artist>(s => s.Albums.Count == 2)));
|
||||
.Verify(v => v.UpdateArtist(It.Is<Artist>(s => s.Albums.Value.Count == 2)));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace NzbDrone.Core.Test.MusicTests
|
|||
public void Setup()
|
||||
{
|
||||
_artist = Builder<Artist>.CreateNew()
|
||||
.With(v => v.Status == ArtistStatusType.Continuing)
|
||||
.With(v => v.Metadata.Value.Status == ArtistStatusType.Continuing)
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<IAlbumService>()
|
||||
|
@ -31,7 +31,7 @@ namespace NzbDrone.Core.Test.MusicTests
|
|||
|
||||
private void GivenArtistIsEnded()
|
||||
{
|
||||
_artist.Status = ArtistStatusType.Ended;
|
||||
_artist.Metadata.Value.Status = ArtistStatusType.Ended;
|
||||
}
|
||||
|
||||
private void GivenArtistLastRefreshedMonthsAgo()
|
||||
|
|
|
@ -174,7 +174,5 @@ namespace NzbDrone.Core.Test.MusicTests.TitleMatchingTests
|
|||
|
||||
track.Should().BeNull();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
|||
{
|
||||
private Artist _artist;
|
||||
private Album _album;
|
||||
private AlbumRelease _release;
|
||||
private Track _track;
|
||||
private TrackFile _trackFile;
|
||||
private NamingConfig _namingConfig;
|
||||
|
@ -33,9 +34,15 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
|||
.With(s => s.Title = "Hail to the King")
|
||||
.Build();
|
||||
|
||||
_release = Builder<AlbumRelease>
|
||||
.CreateNew()
|
||||
.With(s => s.Media = new List<Medium> { new Medium { Number = 1 } })
|
||||
.Build();
|
||||
|
||||
_track = Builder<Track>.CreateNew()
|
||||
.With(e => e.Title = "Doing Time")
|
||||
.With(e => e.AbsoluteTrackNumber = 3)
|
||||
.With(e => e.AlbumRelease = _release)
|
||||
.Build();
|
||||
|
||||
_trackFile = new TrackFile { Quality = new QualityModel(Quality.MP3_256), ReleaseGroup = "LidarrTest" };
|
||||
|
@ -86,6 +93,8 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
|||
.With(e => e.Title = "Surrender Benson")
|
||||
.TheNext(1)
|
||||
.With(e => e.Title = "Imprisoned Lives")
|
||||
.All()
|
||||
.With(e => e.AlbumRelease = _release)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
|||
{
|
||||
private Artist _artist;
|
||||
private Album _album;
|
||||
private AlbumRelease _release;
|
||||
private Track _track1;
|
||||
private TrackFile _trackFile;
|
||||
private NamingConfig _namingConfig;
|
||||
|
@ -37,6 +38,11 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
|||
.With(s => s.Disambiguation = "The Best Album")
|
||||
.Build();
|
||||
|
||||
_release = Builder<AlbumRelease>
|
||||
.CreateNew()
|
||||
.With(s => s.Media = new List<Medium> { new Medium { Number = 1 } })
|
||||
.Build();
|
||||
|
||||
|
||||
_namingConfig = NamingConfig.Default;
|
||||
_namingConfig.RenameTracks = true;
|
||||
|
@ -48,6 +54,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
|||
_track1 = Builder<Track>.CreateNew()
|
||||
.With(e => e.Title = "City Sushi")
|
||||
.With(e => e.AbsoluteTrackNumber = 6)
|
||||
.With(e => e.AlbumRelease = _release)
|
||||
.Build();
|
||||
|
||||
_trackFile = new TrackFile { Quality = new QualityModel(Quality.MP3_256), ReleaseGroup = "LidarrTest" };
|
||||
|
@ -351,6 +358,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
|||
var track = Builder<Track>.CreateNew()
|
||||
.With(e => e.Title = "Part 1")
|
||||
.With(e => e.AbsoluteTrackNumber = 6)
|
||||
.With(e => e.AlbumRelease = _release)
|
||||
.Build();
|
||||
|
||||
Subject.BuildTrackFileName(new List<Track> { track }, new Artist { Name = "In The Woods." }, new Album { Title = "30 Rock" }, _trackFile)
|
||||
|
@ -365,6 +373,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
|||
var track = Builder<Track>.CreateNew()
|
||||
.With(e => e.Title = "Part 1")
|
||||
.With(e => e.AbsoluteTrackNumber = 6)
|
||||
.With(e => e.AlbumRelease = _release)
|
||||
.Build();
|
||||
|
||||
Subject.BuildTrackFileName(new List<Track> { track }, new Artist { Name = "In The Woods..." }, new Album { Title = "30 Rock" }, _trackFile)
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
|||
{
|
||||
private Artist _artist;
|
||||
private Album _album;
|
||||
private AlbumRelease _release;
|
||||
private Track _track;
|
||||
private TrackFile _trackFile;
|
||||
private NamingConfig _namingConfig;
|
||||
|
@ -32,10 +33,16 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
|||
.CreateNew()
|
||||
.With(s => s.Title = "Anthology")
|
||||
.Build();
|
||||
|
||||
_release = Builder<AlbumRelease>
|
||||
.CreateNew()
|
||||
.With(s => s.Media = new List<Medium> { new Medium { Number = 1 } })
|
||||
.Build();
|
||||
|
||||
_track = Builder<Track>.CreateNew()
|
||||
.With(e => e.Title = "City Sushi")
|
||||
.With(e => e.AbsoluteTrackNumber = 6)
|
||||
.With(e => e.AlbumRelease = _release)
|
||||
.Build();
|
||||
|
||||
_trackFile = new TrackFile { Quality = new QualityModel(Quality.MP3_320), ReleaseGroup = "LidarrTest" };
|
||||
|
|
|
@ -33,18 +33,19 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
_fakeAlbum = Builder<Album>
|
||||
.CreateNew()
|
||||
.With(e => e.ArtistId = _fakeArtist.Id)
|
||||
.With(e => e.Releases = new List<AlbumRelease>
|
||||
.With(e => e.AlbumReleases = new List<AlbumRelease>
|
||||
{
|
||||
new AlbumRelease
|
||||
{
|
||||
Id = "5ecd552b-e54b-4c37-b62c-9d6234834bad"
|
||||
ForeignReleaseId = "5ecd552b-e54b-4c37-b62c-9d6234834bad",
|
||||
Monitored = true
|
||||
}
|
||||
})
|
||||
.Build();
|
||||
|
||||
_fakeTrack = Builder<Track>
|
||||
.CreateNew()
|
||||
.With(e => e.ArtistId = _fakeArtist.Id)
|
||||
.With(e => e.Artist = _fakeArtist)
|
||||
.With(e => e.AlbumId = _fakeAlbum.Id)
|
||||
.With(e => e.Album = null)
|
||||
.Build();
|
||||
|
@ -61,7 +62,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
.Returns(_fakeAlbum);
|
||||
|
||||
Mocker.GetMock<IAlbumService>()
|
||||
.Setup(s => s.FindAlbumByRelease(_fakeAlbum.Releases.First().Id))
|
||||
.Setup(s => s.FindAlbumByRelease(_fakeAlbum.AlbumReleases.Value.First().ForeignReleaseId))
|
||||
.Returns(_fakeAlbum);
|
||||
|
||||
Mocker.GetMock<ITrackService>()
|
||||
|
@ -78,7 +79,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
private void HasReleaseMbIdNoTitle()
|
||||
{
|
||||
_parsedTrackInfo.AlbumTitle = "";
|
||||
_parsedTrackInfo.ReleaseMBId = _fakeAlbum.Releases.First().Id;
|
||||
_parsedTrackInfo.ReleaseMBId = _fakeAlbum.AlbumReleases.Value.First().ForeignReleaseId;
|
||||
}
|
||||
|
||||
private void HasNoReleaseIdOrTitle()
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Test.Common;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Music;
|
||||
|
||||
namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests
|
||||
{
|
||||
|
||||
public class GetAudioFilesFixture : CoreTest<DiskScanService>
|
||||
{
|
||||
private string[] _fileNames;
|
||||
private readonly string path = @"C:\Test\".AsOsAgnostic();
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
|
@ -48,8 +47,6 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests
|
|||
[Test]
|
||||
public void should_check_all_directories()
|
||||
{
|
||||
var path = @"C:\Test\";
|
||||
|
||||
Subject.GetAudioFiles(path);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFiles(path, SearchOption.AllDirectories), Times.Once());
|
||||
|
@ -59,8 +56,6 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests
|
|||
[Test]
|
||||
public void should_check_all_directories_when_allDirectories_is_true()
|
||||
{
|
||||
var path = @"C:\Test\";
|
||||
|
||||
Subject.GetAudioFiles(path, true);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFiles(path, SearchOption.AllDirectories), Times.Once());
|
||||
|
@ -70,8 +65,6 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests
|
|||
[Test]
|
||||
public void should_check_top_level_directory_only_when_allDirectories_is_false()
|
||||
{
|
||||
var path = @"C:\Test\";
|
||||
|
||||
Subject.GetAudioFiles(path, false);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFiles(path, SearchOption.AllDirectories), Times.Never());
|
||||
|
@ -81,7 +74,6 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests
|
|||
[Test]
|
||||
public void should_return_audio_files_only()
|
||||
{
|
||||
var path = @"C:\Test\";
|
||||
GivenFiles(GetFiles(path));
|
||||
|
||||
Subject.GetAudioFiles(path).Should().HaveCount(4);
|
||||
|
@ -96,7 +88,6 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests
|
|||
[TestCase(".unwanted")]
|
||||
public void should_filter_certain_sub_folders(string subFolder)
|
||||
{
|
||||
var path = @"C:\Test\";
|
||||
var files = GetFiles(path).ToList();
|
||||
var specialFiles = GetFiles(path, subFolder).ToList();
|
||||
var allFiles = files.Concat(specialFiles);
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace NzbDrone.Core.ArtistStats
|
|||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine(GetSelectClause());
|
||||
sb.AppendLine(GetTrackFilesJoin());
|
||||
sb.AppendLine("AND Albums.ReleaseDate < @currentDate");
|
||||
sb.AppendLine(GetGroupByClause());
|
||||
var queryText = sb.ToString();
|
||||
|
||||
|
@ -44,8 +44,8 @@ namespace NzbDrone.Core.ArtistStats
|
|||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine(GetSelectClause());
|
||||
sb.AppendLine(GetTrackFilesJoin());
|
||||
sb.AppendLine("WHERE Tracks.ArtistId = @artistId");
|
||||
sb.AppendLine("AND Artists.Id = @artistId");
|
||||
sb.AppendLine("AND Albums.ReleaseDate < @currentDate");
|
||||
sb.AppendLine(GetGroupByClause());
|
||||
var queryText = sb.ToString();
|
||||
|
||||
|
@ -54,28 +54,25 @@ namespace NzbDrone.Core.ArtistStats
|
|||
|
||||
private string GetSelectClause()
|
||||
{
|
||||
return @"SELECT Tracks.*, SUM(TrackFiles.Size) as SizeOnDisk FROM
|
||||
(SELECT
|
||||
Tracks.ArtistId,
|
||||
Tracks.AlbumId,
|
||||
COUNT(*) AS TotalTrackCount,
|
||||
SUM(CASE WHEN TrackFileId > 0 THEN 1 ELSE 0 END) AS AvailableTrackCount,
|
||||
SUM(CASE WHEN Monitored = 1 OR TrackFileId > 0 THEN 1 ELSE 0 END) AS TrackCount,
|
||||
SUM(CASE WHEN TrackFileId > 0 THEN 1 ELSE 0 END) AS TrackFileCount
|
||||
return @"SELECT
|
||||
Artists.Id AS ArtistId,
|
||||
Albums.Id AS AlbumId,
|
||||
SUM(COALESCE(TrackFiles.Size, 0)) AS SizeOnDisk,
|
||||
COUNT(Tracks.Id) AS TotalTrackCount,
|
||||
SUM(CASE WHEN Tracks.TrackFileId > 0 THEN 1 ELSE 0 END) AS AvailableTrackCount,
|
||||
SUM(CASE WHEN Albums.Monitored = 1 OR Tracks.TrackFileId > 0 THEN 1 ELSE 0 END) AS TrackCount,
|
||||
SUM(CASE WHEN TrackFiles.Id IS NULL THEN 0 ELSE 1 END) AS TrackFileCount
|
||||
FROM Tracks
|
||||
GROUP BY Tracks.ArtistId, Tracks.AlbumId) as Tracks";
|
||||
JOIN AlbumReleases ON Tracks.AlbumReleaseId = AlbumReleases.Id
|
||||
JOIN Albums ON AlbumReleases.AlbumId = Albums.Id
|
||||
JOIN Artists on Albums.ArtistMetadataId = Artists.ArtistMetadataId
|
||||
LEFT OUTER JOIN TrackFiles ON Tracks.TrackFileId = TrackFiles.Id
|
||||
WHERE AlbumReleases.Monitored = 1";
|
||||
}
|
||||
|
||||
private string GetGroupByClause()
|
||||
{
|
||||
return "GROUP BY Tracks.ArtistId, Tracks.AlbumId";
|
||||
}
|
||||
|
||||
private string GetTrackFilesJoin()
|
||||
{
|
||||
return @"LEFT OUTER JOIN TrackFiles
|
||||
ON TrackFiles.ArtistId = Tracks.ArtistId
|
||||
AND TrackFiles.AlbumId = Tracks.AlbumId";
|
||||
return "GROUP BY Artists.Id, Albums.Id";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace NzbDrone.Core.Datastore
|
|||
_eventAggregator = eventAggregator;
|
||||
}
|
||||
|
||||
protected QueryBuilder<TModel> Query => DataMapper.Query<TModel>();
|
||||
protected virtual QueryBuilder<TModel> Query => DataMapper.Query<TModel>();
|
||||
|
||||
protected void Delete(Expression<Func<TModel, bool>> filter)
|
||||
{
|
||||
|
@ -80,7 +80,7 @@ namespace NzbDrone.Core.Datastore
|
|||
public IEnumerable<TModel> Get(IEnumerable<int> ids)
|
||||
{
|
||||
var idList = ids.ToList();
|
||||
var query = string.Format("Id IN ({0})", string.Join(",", idList));
|
||||
var query = string.Format("[t0].[Id] IN ({0})", string.Join(",", idList));
|
||||
var result = Query.Where(query).ToList();
|
||||
|
||||
if (result.Count != idList.Count())
|
||||
|
|
|
@ -25,15 +25,7 @@ namespace NzbDrone.Core.Datastore.Extensions
|
|||
|
||||
public static RelationshipBuilder<TParent> Relationship<TParent>(this ColumnMapBuilder<TParent> mapBuilder)
|
||||
{
|
||||
return mapBuilder.Relationships.AutoMapComplexTypeProperties<ILazyLoaded>();
|
||||
}
|
||||
|
||||
public static RelationshipBuilder<TParent> HasMany<TParent, TChild>(this RelationshipBuilder<TParent> relationshipBuilder, Expression<Func<TParent, LazyList<TChild>>> portalExpression, Func<TParent, int> childIdSelector)
|
||||
where TParent : ModelBase
|
||||
where TChild : ModelBase
|
||||
{
|
||||
return relationshipBuilder.For(portalExpression.GetMemberName())
|
||||
.LazyLoad((db, parent) => db.Query<TChild>().Where(c => c.Id == childIdSelector(parent)).ToList());
|
||||
return mapBuilder.Relationships.MapProperties<TParent>();
|
||||
}
|
||||
|
||||
private static string GetMemberName<T, TMember>(this Expression<Func<T, TMember>> member)
|
||||
|
|
|
@ -0,0 +1,247 @@
|
|||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Music;
|
||||
using System.Data;
|
||||
using System;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(023)]
|
||||
public class add_release_groups_etc : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
// ARTISTS TABLE
|
||||
|
||||
Create.TableForModel("ArtistMetadata")
|
||||
.WithColumn("ForeignArtistId").AsString().Unique()
|
||||
.WithColumn("Name").AsString()
|
||||
.WithColumn("Overview").AsString().Nullable()
|
||||
.WithColumn("Disambiguation").AsString().Nullable()
|
||||
.WithColumn("Type").AsString().Nullable()
|
||||
.WithColumn("Status").AsInt32()
|
||||
.WithColumn("Images").AsString()
|
||||
.WithColumn("Links").AsString().Nullable()
|
||||
.WithColumn("Genres").AsString().Nullable()
|
||||
.WithColumn("Ratings").AsString().Nullable()
|
||||
.WithColumn("Members").AsString().Nullable();
|
||||
|
||||
// we want to preserve the artist ID. Shove all the metadata into the metadata table.
|
||||
Execute.Sql(@"INSERT INTO ArtistMetadata (ForeignArtistId, Name, Overview, Disambiguation, Type, Status, Images, Links, Genres, Ratings, Members)
|
||||
SELECT ForeignArtistId, Name, Overview, Disambiguation, ArtistType, Status, Images, Links, Genres, Ratings, Members
|
||||
FROM Artists");
|
||||
|
||||
// Add an ArtistMetadataId column to Artists
|
||||
Alter.Table("Artists").AddColumn("ArtistMetadataId").AsInt32().WithDefaultValue(0);
|
||||
|
||||
// Update artistmetadataId
|
||||
Execute.Sql(@"UPDATE Artists
|
||||
SET ArtistMetadataId = (SELECT ArtistMetadata.Id
|
||||
FROM ArtistMetadata
|
||||
WHERE ArtistMetadata.ForeignArtistId = Artists.ForeignArtistId)");
|
||||
|
||||
// ALBUM RELEASES TABLE - Do this before we mess with the Albums table
|
||||
|
||||
Create.TableForModel("AlbumReleases")
|
||||
.WithColumn("ForeignReleaseId").AsString().Unique()
|
||||
.WithColumn("AlbumId").AsInt32().Indexed()
|
||||
.WithColumn("Title").AsString()
|
||||
.WithColumn("Status").AsString()
|
||||
.WithColumn("Duration").AsInt32().WithDefaultValue(0)
|
||||
.WithColumn("Label").AsString().Nullable()
|
||||
.WithColumn("Disambiguation").AsString().Nullable()
|
||||
.WithColumn("Country").AsString().Nullable()
|
||||
.WithColumn("ReleaseDate").AsDateTime().Nullable()
|
||||
.WithColumn("Media").AsString().Nullable()
|
||||
.WithColumn("TrackCount").AsInt32().Nullable()
|
||||
.WithColumn("Monitored").AsBoolean();
|
||||
|
||||
Execute.WithConnection(PopulateReleases);
|
||||
|
||||
// ALBUMS TABLE
|
||||
|
||||
// Add in the extra columns and update artist metadata id
|
||||
Alter.Table("Albums").AddColumn("ArtistMetadataId").AsInt32().WithDefaultValue(0);
|
||||
Alter.Table("Albums").AddColumn("AnyReleaseOk").AsBoolean().WithDefaultValue(true);
|
||||
Alter.Table("Albums").AddColumn("Links").AsString().Nullable();
|
||||
|
||||
// Set metadata ID
|
||||
Execute.Sql(@"UPDATE Albums
|
||||
SET ArtistMetadataId = (SELECT ArtistMetadata.Id
|
||||
FROM ArtistMetadata
|
||||
JOIN Artists ON ArtistMetadata.Id = Artists.ArtistMetadataId
|
||||
WHERE Albums.ArtistId = Artists.Id)");
|
||||
|
||||
// TRACKS TABLE
|
||||
Alter.Table("Tracks").AddColumn("ForeignRecordingId").AsString().WithDefaultValue("0");
|
||||
Alter.Table("Tracks").AddColumn("AlbumReleaseId").AsInt32().WithDefaultValue(0);
|
||||
Alter.Table("Tracks").AddColumn("ArtistMetadataId").AsInt32().WithDefaultValue(0);
|
||||
|
||||
// Set track release to the only release we've bothered populating
|
||||
Execute.Sql(@"UPDATE Tracks
|
||||
SET AlbumReleaseId = (SELECT AlbumReleases.Id
|
||||
FROM AlbumReleases
|
||||
JOIN Albums ON AlbumReleases.AlbumId = Albums.Id
|
||||
WHERE Albums.Id = Tracks.AlbumId)");
|
||||
|
||||
// CLEAR OUT OLD COLUMNS
|
||||
|
||||
// Remove the columns in Artists now in ArtistMetadata
|
||||
Delete.Column("ForeignArtistId")
|
||||
.Column("Name")
|
||||
.Column("Overview")
|
||||
.Column("Disambiguation")
|
||||
.Column("ArtistType")
|
||||
.Column("Status")
|
||||
.Column("Images")
|
||||
.Column("Links")
|
||||
.Column("Genres")
|
||||
.Column("Ratings")
|
||||
.Column("Members")
|
||||
// as well as the ones no longer used
|
||||
.Column("MBId")
|
||||
.Column("AMId")
|
||||
.Column("TADBId")
|
||||
.Column("DiscogsId")
|
||||
.Column("NameSlug")
|
||||
.Column("LastDiskSync")
|
||||
.Column("DateFormed")
|
||||
.FromTable("Artists");
|
||||
|
||||
// Remove old columns from Albums
|
||||
Delete.Column("ArtistId")
|
||||
.Column("MBId")
|
||||
.Column("AMId")
|
||||
.Column("TADBId")
|
||||
.Column("DiscogsId")
|
||||
.Column("TitleSlug")
|
||||
.Column("Label")
|
||||
.Column("SortTitle")
|
||||
.Column("Tags")
|
||||
.Column("Duration")
|
||||
.Column("Media")
|
||||
.Column("Releases")
|
||||
.Column("CurrentRelease")
|
||||
.Column("LastDiskSync")
|
||||
.FromTable("Albums");
|
||||
|
||||
// Remove old columns from Tracks
|
||||
Delete.Column("ArtistId")
|
||||
.Column("AlbumId")
|
||||
.Column("Compilation")
|
||||
.Column("DiscNumber")
|
||||
.Column("Monitored")
|
||||
.FromTable("Tracks");
|
||||
|
||||
// Remove old columns from TrackFiles
|
||||
Delete.Column("ArtistId").FromTable("TrackFiles");
|
||||
|
||||
// Add indices
|
||||
Create.Index().OnTable("Artists").OnColumn("ArtistMetadataId").Ascending();
|
||||
Create.Index().OnTable("Artists").OnColumn("Monitored").Ascending();
|
||||
Create.Index().OnTable("Albums").OnColumn("ArtistMetadataId").Ascending();
|
||||
Create.Index().OnTable("Tracks").OnColumn("ArtistMetadataId").Ascending();
|
||||
Create.Index().OnTable("Tracks").OnColumn("AlbumReleaseId").Ascending();
|
||||
Create.Index().OnTable("Tracks").OnColumn("ForeignRecordingId").Ascending();
|
||||
|
||||
// Force a metadata refresh
|
||||
Update.Table("Artists").Set(new { LastInfoSync = new System.DateTime(2018, 1, 1, 0, 0, 1)}).AllRows();
|
||||
Update.Table("Albums").Set(new { LastInfoSync = new System.DateTime(2018, 1, 1, 0, 0, 1)}).AllRows();
|
||||
Update.Table("ScheduledTasks")
|
||||
.Set(new { LastExecution = new System.DateTime(2018, 1, 1, 0, 0, 1)})
|
||||
.Where(new { TypeName = "NzbDrone.Core.Music.Commands.RefreshArtistCommand" });
|
||||
|
||||
}
|
||||
|
||||
private void PopulateReleases(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
var releases = ReadReleasesFromAlbums(conn, tran);
|
||||
WriteReleasesToReleases(releases,conn, tran);
|
||||
}
|
||||
|
||||
public class LegacyAlbumRelease : IEmbeddedDocument
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
public int TrackCount { get; set; }
|
||||
public int MediaCount { get; set; }
|
||||
public string Disambiguation { get; set; }
|
||||
public List<string> Country { get; set; }
|
||||
public string Format { get; set; }
|
||||
public List<string> Label { get; set; }
|
||||
}
|
||||
|
||||
private List<AlbumRelease> ReadReleasesFromAlbums(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
|
||||
// need to get all the old albums
|
||||
var releases = new List<AlbumRelease>();
|
||||
|
||||
using (var getReleasesCmd = conn.CreateCommand())
|
||||
{
|
||||
getReleasesCmd.Transaction = tran;
|
||||
getReleasesCmd.CommandText = @"SELECT Id, CurrentRelease FROM Albums";
|
||||
|
||||
using (var releaseReader = getReleasesCmd.ExecuteReader())
|
||||
{
|
||||
while (releaseReader.Read())
|
||||
{
|
||||
int rgId = releaseReader.GetInt32(0);
|
||||
var albumRelease = Json.Deserialize<LegacyAlbumRelease>(releaseReader.GetString(1));
|
||||
var media = new List<Medium>();
|
||||
for (var i = 1; i <= albumRelease.MediaCount; i++)
|
||||
{
|
||||
media.Add(new Medium { Number = i, Name = "", Format = albumRelease.Format } );
|
||||
}
|
||||
|
||||
releases.Add(new AlbumRelease {
|
||||
AlbumId = rgId,
|
||||
ForeignReleaseId = albumRelease.Id,
|
||||
Title = albumRelease.Title,
|
||||
Status = "",
|
||||
Duration = 0,
|
||||
Label = albumRelease.Label,
|
||||
Disambiguation = albumRelease.Disambiguation,
|
||||
Country = albumRelease.Country,
|
||||
Media=media,
|
||||
TrackCount = albumRelease.TrackCount,
|
||||
Monitored = true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return releases;
|
||||
}
|
||||
|
||||
private void WriteReleasesToReleases(List<AlbumRelease> releases, IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
foreach (var release in releases)
|
||||
{
|
||||
using (var writeReleaseCmd = conn.CreateCommand())
|
||||
{
|
||||
writeReleaseCmd.Transaction = tran;
|
||||
writeReleaseCmd.CommandText =
|
||||
"INSERT INTO AlbumReleases (AlbumId, ForeignReleaseId, Title, Status, Duration, Label, Disambiguation, Country, Media, TrackCount, Monitored) " +
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
writeReleaseCmd.AddParameter(release.AlbumId);
|
||||
writeReleaseCmd.AddParameter(release.ForeignReleaseId);
|
||||
writeReleaseCmd.AddParameter(release.Title);
|
||||
writeReleaseCmd.AddParameter(release.Status);
|
||||
writeReleaseCmd.AddParameter(release.Duration);
|
||||
writeReleaseCmd.AddParameter(release.Label.ToJson());
|
||||
writeReleaseCmd.AddParameter(release.Disambiguation);
|
||||
writeReleaseCmd.AddParameter(release.Country.ToJson());
|
||||
writeReleaseCmd.AddParameter(release.Media.ToJson());
|
||||
writeReleaseCmd.AddParameter(release.TrackCount);
|
||||
writeReleaseCmd.AddParameter(release.Monitored);
|
||||
|
||||
writeReleaseCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Marr.Data;
|
||||
using Marr.Data.Mapping;
|
||||
using NzbDrone.Common.Reflection;
|
||||
|
@ -87,28 +88,71 @@ namespace NzbDrone.Core.Datastore
|
|||
|
||||
Mapper.Entity<Artist>().RegisterModel("Artists")
|
||||
.Ignore(s => s.RootFolderPath)
|
||||
.Ignore(s => s.Name)
|
||||
.Ignore(s => s.ForeignArtistId)
|
||||
.Relationship()
|
||||
.HasOne(a => a.Metadata, a => a.ArtistMetadataId)
|
||||
.HasOne(a => a.Profile, a => a.ProfileId)
|
||||
.HasOne(s => s.LanguageProfile, s => s.LanguageProfileId)
|
||||
.HasOne(s => s.MetadataProfile, s => s.MetadataProfileId);
|
||||
.HasOne(s => s.MetadataProfile, s => s.MetadataProfileId)
|
||||
.For(a => a.Albums)
|
||||
.LazyLoad(condition: a => a.Id > 0, query: (db, a) => db.Query<Album>().Where(rg => rg.ArtistMetadataId == a.Id).ToList());
|
||||
|
||||
Mapper.Entity<Album>().RegisterModel("Albums");
|
||||
Mapper.Entity<ArtistMetadata>().RegisterModel("ArtistMetadata");
|
||||
|
||||
Mapper.Entity<TrackFile>().RegisterModel("TrackFiles")
|
||||
.Ignore(f => f.Path)
|
||||
.Relationships.AutoMapICollectionOrComplexProperties()
|
||||
.For("Tracks")
|
||||
.LazyLoad(condition: parent => parent.Id > 0,
|
||||
query: (db, parent) => db.Query<Track>().Where(c => c.TrackFileId == parent.Id).ToList()) // TODO: Figure what the hell to do here
|
||||
.HasOne(file => file.Artist, file => file.ArtistId);
|
||||
Mapper.Entity<Album>().RegisterModel("Albums")
|
||||
.Ignore(r => r.ArtistId)
|
||||
.Relationship()
|
||||
.HasOne(r => r.ArtistMetadata, r => r.ArtistMetadataId)
|
||||
.For(rg => rg.AlbumReleases)
|
||||
.LazyLoad(condition: rg => rg.Id > 0, query: (db, rg) => db.Query<AlbumRelease>().Where(r => r.AlbumId == rg.Id).ToList())
|
||||
.For(rg => rg.Artist)
|
||||
.LazyLoad(condition: rg => rg.ArtistMetadataId > 0, query: (db, rg) => db.Query<Artist>().Where(a => a.ArtistMetadataId == rg.ArtistMetadataId).SingleOrDefault());
|
||||
|
||||
|
||||
Mapper.Entity<AlbumRelease>().RegisterModel("AlbumReleases")
|
||||
.Relationship()
|
||||
.HasOne(r => r.Album, r => r.AlbumId)
|
||||
.For(r => r.Tracks)
|
||||
.LazyLoad(condition: r => r.Id > 0, query: (db, r) => db.Query<Track>().Where(t => t.AlbumReleaseId == r.Id).ToList());
|
||||
|
||||
Mapper.Entity<Track>().RegisterModel("Tracks")
|
||||
//.Ignore(e => e.SeriesTitle)
|
||||
.Ignore(e => e.Album)
|
||||
.Ignore(e => e.HasFile)
|
||||
.Relationship()
|
||||
// TODO: Need to implement ArtistId to Artist.Id here
|
||||
.HasOne(track => track.TrackFile, track => track.TrackFileId); // TODO: Check lazy load for artists
|
||||
.Ignore(t => t.HasFile)
|
||||
.Ignore(t => t.AlbumId)
|
||||
.Ignore(t => t.ArtistId)
|
||||
.Ignore(t => t.Album)
|
||||
.Relationship()
|
||||
.HasOne(track => track.AlbumRelease, track => track.AlbumReleaseId)
|
||||
.HasOne(track => track.ArtistMetadata, track => track.ArtistMetadataId)
|
||||
.HasOne(track => track.TrackFile, track => track.TrackFileId)
|
||||
.For(t => t.Artist)
|
||||
.LazyLoad(condition: t => t.AlbumReleaseId > 0, query: (db, t) => db.Query<Artist>().QueryText(string.Format(
|
||||
"/* LazyLoading Artist for Track */\n" +
|
||||
"SELECT Artists.* " +
|
||||
"FROM Artists " +
|
||||
"JOIN Albums ON Albums.ArtistMetadataId = Artists.ArtistMetadataId " +
|
||||
"JOIN AlbumReleases ON AlbumReleases.AlbumId = Albums.Id " +
|
||||
"WHERE AlbumReleases.Id = {0}",
|
||||
t.AlbumReleaseId)).SingleOrDefault());
|
||||
|
||||
Mapper.Entity<TrackFile>().RegisterModel("TrackFiles")
|
||||
.Ignore(f => f.Path)
|
||||
.Relationship()
|
||||
.HasOne(f => f.Album, f => f.AlbumId)
|
||||
.For("Tracks")
|
||||
.LazyLoad(condition: parent => parent.Id > 0,
|
||||
query: (db, parent) => db.Query<Track>().Where(c => c.TrackFileId == parent.Id).ToList())
|
||||
.For(t => t.Artist)
|
||||
.LazyLoad(condition: f => f.Id > 0, query: (db, f) => db.Query<Artist>().QueryText(string.Format(
|
||||
"/* LazyLoading Artist for TrackFile */\n" +
|
||||
"SELECT Artists.* " +
|
||||
"FROM Artists " +
|
||||
"JOIN Albums ON Albums.ArtistMetadataId = Artists.ArtistMetadataId " +
|
||||
"JOIN AlbumReleases ON AlbumReleases.AlbumId = Albums.Id " +
|
||||
"JOIN Tracks ON Tracks.AlbumReleaseId = AlbumReleases.Id " +
|
||||
"JOIN TrackFiles ON TrackFiles.Id = Tracks.TrackFileId " +
|
||||
"WHERE TrackFiles.Id = {0}",
|
||||
f.Id)).SingleOrDefault());
|
||||
|
||||
Mapper.Entity<QualityDefinition>().RegisterModel("QualityDefinitions")
|
||||
.Ignore(d => d.GroupName)
|
||||
|
|
|
@ -35,19 +35,19 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
}
|
||||
|
||||
var qualityDefinition = _qualityDefinitionService.Get(quality);
|
||||
var albumsDuration = subject.Albums.Sum(album => album.Duration) / 1000;
|
||||
|
||||
if (qualityDefinition.MinSize.HasValue)
|
||||
{
|
||||
var minSize = qualityDefinition.MinSize.Value.Kilobits();
|
||||
var minReleaseDuration = subject.Albums.Select(a => a.AlbumReleases.Value.Where(r => r.Monitored || a.AnyReleaseOk).Select(r => r.Duration).Min()).Sum() / 1000;
|
||||
|
||||
//Multiply minSize by Album.Duration
|
||||
minSize = minSize * albumsDuration;
|
||||
//Multiply minSize by smallest release duration
|
||||
minSize = minSize * minReleaseDuration;
|
||||
|
||||
//If the parsed size is smaller than minSize we don't want it
|
||||
if (subject.Release.Size < minSize)
|
||||
{
|
||||
var runtimeMessage = $"{albumsDuration}sec";
|
||||
var runtimeMessage = $"{minReleaseDuration}sec";
|
||||
|
||||
_logger.Debug("Item: {0}, Size: {1} is smaller than minimum allowed size ({2} bytes for {3}), rejecting.", subject, subject.Release.Size, minSize, runtimeMessage);
|
||||
return Decision.Reject("{0} is smaller than minimum allowed {1}", subject.Release.Size.SizeSuffix(), minSize.SizeSuffix());
|
||||
|
@ -60,14 +60,15 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
else
|
||||
{
|
||||
var maxSize = qualityDefinition.MaxSize.Value.Kilobits();
|
||||
|
||||
var maxReleaseDuration = subject.Albums.Select(a => a.AlbumReleases.Value.Where(r => r.Monitored || a.AnyReleaseOk).Select(r => r.Duration).Max()).Sum() / 1000;
|
||||
|
||||
//Multiply maxSize by Album.Duration
|
||||
maxSize = maxSize * albumsDuration;
|
||||
maxSize = maxSize * maxReleaseDuration;
|
||||
|
||||
//If the parsed size is greater than maxSize we don't want it
|
||||
if (subject.Release.Size > maxSize)
|
||||
{
|
||||
var runtimeMessage = $"{albumsDuration}sec";
|
||||
var runtimeMessage = $"{maxReleaseDuration}sec";
|
||||
|
||||
_logger.Debug("Item: {0}, Size: {1} is greater than maximum allowed size ({2} bytes for {3}), rejecting.", subject, subject.Release.Size, maxSize, runtimeMessage);
|
||||
return Decision.Reject("{0} is larger than maximum allowed {1}", subject.Release.Size.SizeSuffix(), maxSize.SizeSuffix());
|
||||
|
|
|
@ -112,7 +112,7 @@ namespace NzbDrone.Core.Extras.Files
|
|||
|
||||
else
|
||||
{
|
||||
var artist = _artistService.GetArtist(message.TrackFile.ArtistId);
|
||||
var artist = trackFile.Artist.Value;
|
||||
|
||||
foreach (var extra in _repository.GetFilesByTrackFile(trackFile.Id))
|
||||
{
|
||||
|
|
|
@ -158,7 +158,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Roksbox
|
|||
return new List<ImageFileResult>();
|
||||
}
|
||||
|
||||
var image = artist.Images.SingleOrDefault(c => c.CoverType == MediaCoverTypes.Poster) ?? artist.Images.FirstOrDefault();
|
||||
var image = artist.Metadata.Value.Images.SingleOrDefault(c => c.CoverType == MediaCoverTypes.Poster) ?? artist.Metadata.Value.Images.FirstOrDefault();
|
||||
if (image == null)
|
||||
{
|
||||
_logger.Trace("Failed to find suitable Artist image for artist {0}.", artist.Name);
|
||||
|
|
|
@ -111,10 +111,10 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Wdtv
|
|||
var details = new XElement("details");
|
||||
details.Add(new XElement("id", artist.Id));
|
||||
details.Add(new XElement("title", string.Format("{0} - {1} - {2}", artist.Name, track.TrackNumber, track.Title)));
|
||||
details.Add(new XElement("artist_name", artist.Name));
|
||||
details.Add(new XElement("artist_name", artist.Metadata.Value.Name));
|
||||
details.Add(new XElement("track_name", track.Title));
|
||||
details.Add(new XElement("track_number", track.AbsoluteTrackNumber.ToString("00")));
|
||||
details.Add(new XElement("member", string.Join(" / ", artist.Members.ConvertAll(c => c.Name + " - " + c.Instrument))));
|
||||
details.Add(new XElement("member", string.Join(" / ", artist.Metadata.Value.Members.ConvertAll(c => c.Name + " - " + c.Instrument))));
|
||||
|
||||
|
||||
//Todo: get guest stars, writer and director
|
||||
|
|
|
@ -113,19 +113,19 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
|
|||
|
||||
artistElement.Add(new XElement("title", artist.Name));
|
||||
|
||||
if (artist.Ratings != null && artist.Ratings.Votes > 0)
|
||||
if (artist.Metadata.Value.Ratings != null && artist.Metadata.Value.Ratings.Votes > 0)
|
||||
{
|
||||
artistElement.Add(new XElement("rating", artist.Ratings.Value));
|
||||
artistElement.Add(new XElement("rating", artist.Metadata.Value.Ratings.Value));
|
||||
}
|
||||
|
||||
artistElement.Add(new XElement("musicbrainzartistid", artist.ForeignArtistId));
|
||||
artistElement.Add(new XElement("biography", artist.Overview));
|
||||
artistElement.Add(new XElement("outline", artist.Overview));
|
||||
artistElement.Add(new XElement("musicbrainzartistid", artist.Metadata.Value.ForeignArtistId));
|
||||
artistElement.Add(new XElement("biography", artist.Metadata.Value.Overview));
|
||||
artistElement.Add(new XElement("outline", artist.Metadata.Value.Overview));
|
||||
|
||||
var doc = new XDocument(artistElement);
|
||||
doc.Save(xw);
|
||||
|
||||
_logger.Debug("Saving artist.nfo for {0}", artist.Name);
|
||||
_logger.Debug("Saving artist.nfo for {0}", artist.Metadata.Value.Name);
|
||||
|
||||
return new MetadataFileResult("artist.nfo", doc.ToString());
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
|
|||
}
|
||||
|
||||
albumElement.Add(new XElement("musicbrainzalbumid", album.ForeignAlbumId));
|
||||
albumElement.Add(new XElement("artistdesc", artist.Overview));
|
||||
albumElement.Add(new XElement("artistdesc", artist.Metadata.Value.Overview));
|
||||
albumElement.Add(new XElement("releasedate", album.ReleaseDate.Value.ToShortDateString()));
|
||||
|
||||
var doc = new XDocument(albumElement);
|
||||
|
@ -203,7 +203,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
|
|||
|
||||
private IEnumerable<ImageFileResult> ProcessArtistImages(Artist artist)
|
||||
{
|
||||
foreach (var image in artist.Images)
|
||||
foreach (var image in artist.Metadata.Value.Images)
|
||||
{
|
||||
var source = _mediaCoverService.GetCoverPath(artist.Id, image.CoverType);
|
||||
var destination = image.CoverType.ToString().ToLowerInvariant() + Path.GetExtension(image.Url);
|
||||
|
|
|
@ -202,8 +202,8 @@ namespace NzbDrone.Core.History
|
|||
Date = DateTime.UtcNow,
|
||||
Quality = message.TrackInfo.Quality,
|
||||
SourceTitle = message.ImportedTrack.SceneName ?? Path.GetFileNameWithoutExtension(message.TrackInfo.Path),
|
||||
ArtistId = message.ImportedTrack.ArtistId,
|
||||
AlbumId = message.ImportedTrack.AlbumId,
|
||||
ArtistId = message.TrackInfo.Artist.Id,
|
||||
AlbumId = message.TrackInfo.Album.Id,
|
||||
TrackId = track.Id,
|
||||
DownloadId = downloadId,
|
||||
Language = message.TrackInfo.Language
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
|||
WHERE Id IN (
|
||||
SELECT Albums.Id FROM Albums
|
||||
LEFT OUTER JOIN Artists
|
||||
ON Albums.ArtistId = Artists.Id
|
||||
ON Albums.ArtistMetadataId = Artists.ArtistMetadataId
|
||||
WHERE Artists.Id IS NULL)");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
{
|
||||
public class CleanupOrphanedArtistMetadata : IHousekeepingTask
|
||||
{
|
||||
private readonly IMainDatabase _database;
|
||||
|
||||
public CleanupOrphanedArtistMetadata(IMainDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
var mapper = _database.GetDataMapper();
|
||||
|
||||
mapper.ExecuteNonQuery(@"DELETE FROM ArtistMetadata
|
||||
WHERE Id IN (
|
||||
SELECT ArtistMetadata.Id FROM ArtistMetadata
|
||||
LEFT OUTER JOIN Albums ON Albums.ArtistMetadataId = ArtistMetadata.Id
|
||||
LEFT OUTER JOIN Tracks ON Tracks.ArtistMetadataId = ArtistMetadata.Id
|
||||
WHERE Albums.Id IS NULL AND Tracks.Id IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
{
|
||||
public class CleanupOrphanedReleases : IHousekeepingTask
|
||||
{
|
||||
private readonly IMainDatabase _database;
|
||||
|
||||
public CleanupOrphanedReleases(IMainDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
var mapper = _database.GetDataMapper();
|
||||
|
||||
mapper.ExecuteNonQuery(@"DELETE FROM AlbumReleases
|
||||
WHERE Id IN (
|
||||
SELECT AlbumReleases.Id FROM AlbumReleases
|
||||
LEFT OUTER JOIN Albums
|
||||
ON AlbumReleases.AlbumId = Albums.Id
|
||||
WHERE Albums.Id IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,12 +15,31 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
|||
{
|
||||
var mapper = _database.GetDataMapper();
|
||||
|
||||
// Delete where track no longer exists
|
||||
mapper.ExecuteNonQuery(@"DELETE FROM TrackFiles
|
||||
WHERE Id IN (
|
||||
SELECT TrackFiles.Id FROM TrackFiles
|
||||
LEFT OUTER JOIN Tracks
|
||||
ON TrackFiles.Id = Tracks.TrackFileId
|
||||
WHERE Tracks.Id IS NULL)");
|
||||
|
||||
// Delete trackfiles associated with releases that are not currently selected
|
||||
mapper.ExecuteNonQuery(@"DELETE FROM TrackFiles
|
||||
WHERE Id IN (
|
||||
SELECT TrackFiles.Id FROM TrackFiles
|
||||
JOIN Tracks ON TrackFiles.Id = Tracks.TrackFileId
|
||||
JOIN AlbumReleases ON Tracks.AlbumReleaseId = AlbumReleases.Id
|
||||
JOIN Albums ON AlbumReleases.AlbumId = Albums.Id
|
||||
WHERE AlbumReleases.Monitored = 0)");
|
||||
|
||||
// Unlink Tracks where the Trackfiles entry no longer exists
|
||||
mapper.ExecuteNonQuery(@"UPDATE Tracks
|
||||
SET TrackFileId = 0
|
||||
WHERE Id IN (
|
||||
SELECT Tracks.Id FROM Tracks
|
||||
LEFT OUTER JOIN TrackFiles
|
||||
ON Tracks.TrackFileId = TrackFiles.Id
|
||||
WHERE TrackFiles.Id IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
|||
mapper.ExecuteNonQuery(@"DELETE FROM Tracks
|
||||
WHERE Id IN (
|
||||
SELECT Tracks.Id FROM Tracks
|
||||
LEFT OUTER JOIN Albums
|
||||
ON Tracks.AlbumId = Albums.Id
|
||||
WHERE Albums.Id IS NULL)");
|
||||
LEFT OUTER JOIN AlbumReleases
|
||||
ON Tracks.AlbumReleaseId = AlbumReleases.Id
|
||||
WHERE AlbumReleases.Id IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,8 +96,8 @@ namespace NzbDrone.Core.ImportLists
|
|||
|
||||
report.AlbumMusicBrainzId = mappedAlbum.ForeignAlbumId;
|
||||
report.Album = mappedAlbum.Title;
|
||||
report.Artist = mappedAlbum.Artist?.Name;
|
||||
report.ArtistMusicBrainzId = mappedAlbum?.Artist?.ForeignArtistId;
|
||||
report.Artist = mappedAlbum.ArtistMetadata?.Value?.Name;
|
||||
report.ArtistMusicBrainzId = mappedAlbum?.ArtistMetadata?.Value?.ForeignArtistId;
|
||||
|
||||
}
|
||||
|
||||
|
@ -106,20 +106,22 @@ namespace NzbDrone.Core.ImportLists
|
|||
{
|
||||
var mappedArtist = _artistSearchService.SearchForNewArtist(report.Artist)
|
||||
.FirstOrDefault();
|
||||
report.ArtistMusicBrainzId = mappedArtist?.ForeignArtistId;
|
||||
report.Artist = mappedArtist?.Name;
|
||||
report.ArtistMusicBrainzId = mappedArtist?.Metadata.Value?.ForeignArtistId;
|
||||
report.Artist = mappedArtist?.Metadata.Value?.Name;
|
||||
}
|
||||
|
||||
// Check to see if artist in DB
|
||||
var existingArtist = _artistService.FindById(report.ArtistMusicBrainzId);
|
||||
|
||||
// Append Artist if not already in DB or already on add list
|
||||
if (existingArtist == null && artistsToAdd.All(s => s.ForeignArtistId != report.ArtistMusicBrainzId))
|
||||
if (existingArtist == null && artistsToAdd.All(s => s.Metadata.Value.ForeignArtistId != report.ArtistMusicBrainzId))
|
||||
{
|
||||
artistsToAdd.Add(new Artist
|
||||
{
|
||||
ForeignArtistId = report.ArtistMusicBrainzId,
|
||||
Name = report.Artist,
|
||||
Metadata = new ArtistMetadata {
|
||||
ForeignArtistId = report.ArtistMusicBrainzId,
|
||||
Name = report.Artist
|
||||
},
|
||||
Monitored = importList.ShouldMonitor,
|
||||
RootFolderPath = importList.RootFolderPath,
|
||||
ProfileId = importList.ProfileId,
|
||||
|
@ -132,9 +134,9 @@ namespace NzbDrone.Core.ImportLists
|
|||
}
|
||||
|
||||
// Add Album so we know what to monitor
|
||||
if (report.AlbumMusicBrainzId.IsNotNullOrWhiteSpace() && artistsToAdd.Any(s => s.ForeignArtistId == report.ArtistMusicBrainzId) && importList.ShouldMonitor)
|
||||
if (report.AlbumMusicBrainzId.IsNotNullOrWhiteSpace() && artistsToAdd.Any(s => s.Metadata.Value.ForeignArtistId == report.ArtistMusicBrainzId) && importList.ShouldMonitor)
|
||||
{
|
||||
artistsToAdd.Find(s => s.ForeignArtistId == report.ArtistMusicBrainzId).AddOptions.AlbumsToMonitor.Add(report.AlbumMusicBrainzId);
|
||||
artistsToAdd.Find(s => s.Metadata.Value.ForeignArtistId == report.ArtistMusicBrainzId).AddOptions.AlbumsToMonitor.Add(report.AlbumMusicBrainzId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace NzbDrone.Core.IndexerSearch
|
|||
SortKey = "Id"
|
||||
};
|
||||
|
||||
pagingSpec.FilterExpressions.Add(v => v.Monitored == true && v.Artist.Monitored == true);
|
||||
pagingSpec.FilterExpressions.Add(v => v.Monitored == true && v.Artist.Value.Monitored == true);
|
||||
|
||||
albums = _albumService.AlbumsWithoutFiles(pagingSpec).Records.Where(e => e.ArtistId.Equals(artistId)).ToList();
|
||||
|
||||
|
@ -102,7 +102,7 @@ namespace NzbDrone.Core.IndexerSearch
|
|||
SortKey = "Id"
|
||||
};
|
||||
|
||||
pagingSpec.FilterExpressions.Add(v => v.Monitored == true && v.Artist.Monitored == true);
|
||||
pagingSpec.FilterExpressions.Add(v => v.Monitored == true && v.Artist.Value.Monitored == true);
|
||||
|
||||
albums = _albumService.AlbumsWithoutFiles(pagingSpec).Records.ToList();
|
||||
|
||||
|
@ -118,20 +118,9 @@ namespace NzbDrone.Core.IndexerSearch
|
|||
{
|
||||
Expression<Func<Album, bool>> filterExpression;
|
||||
|
||||
if (message.ArtistId.HasValue)
|
||||
{
|
||||
filterExpression = v =>
|
||||
v.ArtistId == message.ArtistId.Value &&
|
||||
v.Monitored == true &&
|
||||
v.Artist.Monitored == true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
filterExpression = v =>
|
||||
v.Monitored == true &&
|
||||
v.Artist.Monitored == true;
|
||||
}
|
||||
filterExpression = v =>
|
||||
v.Monitored == true &&
|
||||
v.Artist.Value.Monitored == true;
|
||||
|
||||
var pagingSpec = new PagingSpec<Album>
|
||||
{
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace NzbDrone.Core.MediaCover
|
|||
|
||||
private void EnsureCovers(Artist artist)
|
||||
{
|
||||
foreach (var cover in artist.Images)
|
||||
foreach (var cover in artist.Metadata.Value.Images)
|
||||
{
|
||||
var fileName = GetCoverPath(artist.Id, cover.CoverType);
|
||||
var alreadyExists = false;
|
||||
|
|
|
@ -29,7 +29,17 @@ namespace NzbDrone.Core.MediaFiles
|
|||
|
||||
public List<TrackFile> GetFilesByArtist(int artistId)
|
||||
{
|
||||
return Query.Where(c => c.ArtistId == artistId).ToList();
|
||||
string query = string.Format("SELECT TrackFiles.* " +
|
||||
"FROM Artists " +
|
||||
"JOIN Albums ON Albums.ArtistMetadataId = Artists.ArtistMetadataId " +
|
||||
"JOIN AlbumReleases ON AlbumReleases.AlbumId == Albums.Id " +
|
||||
"JOIN Tracks ON Tracks.AlbumReleaseId == AlbumReleases.Id " +
|
||||
"JOIN TrackFiles ON TrackFiles.Id == Tracks.TrackFileId " +
|
||||
"WHERE Artists.Id == {0} " +
|
||||
"AND AlbumReleases.Monitored = 1",
|
||||
artistId);
|
||||
|
||||
return Query.QueryText(query).ToList();
|
||||
}
|
||||
|
||||
public List<TrackFile> GetFilesByAlbum(int albumId)
|
||||
|
@ -39,9 +49,20 @@ namespace NzbDrone.Core.MediaFiles
|
|||
|
||||
public List<TrackFile> GetFilesWithRelativePath(int artistId, string relativePath)
|
||||
{
|
||||
return Query.Where(c => c.ArtistId == artistId)
|
||||
.AndWhere(c => c.RelativePath == relativePath)
|
||||
.ToList();
|
||||
var mapper = DataMapper;
|
||||
mapper.AddParameter("artistId", artistId);
|
||||
mapper.AddParameter("relativePath", relativePath);
|
||||
string query = "SELECT TrackFiles.* " +
|
||||
"FROM Artists " +
|
||||
"JOIN Albums ON Albums.ArtistMetadataId = Artists.ArtistMetadataId " +
|
||||
"JOIN AlbumReleases ON AlbumReleases.AlbumId == Albums.Id " +
|
||||
"JOIN Tracks ON Tracks.AlbumReleaseId == AlbumReleases.Id " +
|
||||
"JOIN TrackFiles ON TrackFiles.Id == Tracks.TrackFileId " +
|
||||
"WHERE Artists.Id == @artistId " +
|
||||
"AND AlbumReleases.Monitored = 1 " +
|
||||
"AND TrackFiles.RelativePath == @relativePath";
|
||||
|
||||
return mapper.Query<TrackFile>(query);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||
|
||||
}
|
||||
|
||||
public class MediaFileService : IMediaFileService, IHandleAsync<ArtistDeletedEvent>, IHandleAsync<AlbumDeletedEvent>
|
||||
public class MediaFileService : IMediaFileService, IHandleAsync<AlbumDeletedEvent>
|
||||
{
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly IMediaFileRepository _mediaFileRepository;
|
||||
|
@ -104,12 +104,6 @@ namespace NzbDrone.Core.MediaFiles
|
|||
return _mediaFileRepository.GetFilesWithRelativePath(artistId, relativePath);
|
||||
}
|
||||
|
||||
public void HandleAsync(ArtistDeletedEvent message)
|
||||
{
|
||||
var files = GetFilesByArtist(message.Artist.Id);
|
||||
_mediaFileRepository.DeleteMany(files);
|
||||
}
|
||||
|
||||
public void HandleAsync(AlbumDeletedEvent message)
|
||||
{
|
||||
var files = GetFilesByAlbum(message.Album.Id);
|
||||
|
|
|
@ -13,10 +13,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||
{
|
||||
public class TrackFile : ModelBase
|
||||
{
|
||||
//public string ForeignTrackId { get; set; }
|
||||
//public string ForeignArtistId { get; set; }
|
||||
public int AlbumId { get; set; }
|
||||
public int ArtistId { get; set; }
|
||||
// these are model properties
|
||||
public string RelativePath { get; set; }
|
||||
public string Path { get; set; }
|
||||
public long Size { get; set; }
|
||||
|
@ -25,10 +22,16 @@ namespace NzbDrone.Core.MediaFiles
|
|||
public string ReleaseGroup { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public MediaInfoModel MediaInfo { get; set; }
|
||||
//public LazyLoaded<List<Track>> Episodes { get; set; }
|
||||
public LazyLoaded<Artist> Artist { get; set; }
|
||||
public LazyLoaded<List<Track>> Tracks { get; set; }
|
||||
public Language Language { get; set; }
|
||||
public int AlbumId { get; set; }
|
||||
|
||||
// These are queried from the database
|
||||
public LazyLoaded<List<Track>> Tracks { get; set; }
|
||||
public LazyLoaded<Artist> Artist { get; set; }
|
||||
public LazyLoaded<Album> Album { get; set; }
|
||||
|
||||
// these are ignored by the database but retained/populated for compatibility
|
||||
public int ArtistId { get { return Artist.Value?.Id ?? 0; } }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
|
|
@ -9,6 +9,8 @@ using NzbDrone.Core.Extras;
|
|||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.Core.Music.Events;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.TrackImport
|
||||
|
@ -24,20 +26,23 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
|||
private readonly IMediaFileService _mediaFileService;
|
||||
private readonly IExtraService _extraService;
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IReleaseService _releaseService;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public ImportApprovedTracks(IUpgradeMediaFiles trackFileUpgrader,
|
||||
IMediaFileService mediaFileService,
|
||||
IExtraService extraService,
|
||||
IDiskProvider diskProvider,
|
||||
IEventAggregator eventAggregator,
|
||||
Logger logger)
|
||||
IMediaFileService mediaFileService,
|
||||
IExtraService extraService,
|
||||
IDiskProvider diskProvider,
|
||||
IReleaseService releaseService,
|
||||
IEventAggregator eventAggregator,
|
||||
Logger logger)
|
||||
{
|
||||
_trackFileUpgrader = trackFileUpgrader;
|
||||
_mediaFileService = mediaFileService;
|
||||
_extraService = extraService;
|
||||
_diskProvider = diskProvider;
|
||||
_releaseService = releaseService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_logger = logger;
|
||||
}
|
||||
|
@ -56,6 +61,22 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
|||
var allImportedTrackFiles = new List<TrackFile>();
|
||||
var allOldTrackFiles = new List<TrackFile>();
|
||||
|
||||
var albumDecisions = decisions.Where(e => e.LocalTrack.Album != null)
|
||||
.GroupBy(e => e.LocalTrack.Album.Id).ToList();
|
||||
|
||||
foreach (var albumDecision in albumDecisions)
|
||||
{
|
||||
// set the correct release to be monitored after doing the import
|
||||
var album = albumDecision.First().LocalTrack.Album;
|
||||
var release = albumDecision.First().LocalTrack.Release;
|
||||
_logger.Debug("Updating release to {0} [{1} tracks]", release, release.TrackCount);
|
||||
_releaseService.SetMonitored(release);
|
||||
|
||||
// Publish album edited event.
|
||||
// Deliberatly don't put in the old album since we don't want to trigger an ArtistScan.
|
||||
_eventAggregator.PublishEvent(new AlbumEditedEvent(album, album));
|
||||
}
|
||||
|
||||
foreach (var importDecision in qualifiedImports.OrderBy(e => e.LocalTrack.Tracks.Select(track => track.AbsoluteTrackNumber).MinOrDefault())
|
||||
.ThenByDescending(e => e.LocalTrack.Size))
|
||||
{
|
||||
|
@ -74,17 +95,18 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
|||
continue;
|
||||
}
|
||||
|
||||
var trackFile = new TrackFile();
|
||||
trackFile.DateAdded = DateTime.UtcNow;
|
||||
trackFile.ArtistId = localTrack.Artist.Id;
|
||||
trackFile.Path = localTrack.Path.CleanFilePath();
|
||||
trackFile.Size = _diskProvider.GetFileSize(localTrack.Path);
|
||||
trackFile.Quality = localTrack.Quality;
|
||||
trackFile.MediaInfo = localTrack.MediaInfo;
|
||||
trackFile.AlbumId = localTrack.Album.Id;
|
||||
trackFile.ReleaseGroup = localTrack.ParsedTrackInfo.ReleaseGroup;
|
||||
trackFile.Tracks = localTrack.Tracks;
|
||||
trackFile.Language = localTrack.Language;
|
||||
|
||||
var trackFile = new TrackFile {
|
||||
Path = localTrack.Path.CleanFilePath(),
|
||||
Size = _diskProvider.GetFileSize(localTrack.Path),
|
||||
DateAdded = DateTime.UtcNow,
|
||||
ReleaseGroup = localTrack.ParsedTrackInfo.ReleaseGroup,
|
||||
Quality = localTrack.Quality,
|
||||
MediaInfo = localTrack.MediaInfo,
|
||||
Language = localTrack.Language,
|
||||
AlbumId = localTrack.Album.Id,
|
||||
Tracks = localTrack.Tracks
|
||||
};
|
||||
|
||||
bool copyOnly;
|
||||
switch (importMode)
|
||||
|
@ -177,6 +199,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
|||
allOldTrackFiles.Where(s => s.AlbumId == album.Id).ToList(), newDownload,
|
||||
downloadClientItem));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Adding all the rejected decisions
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
|||
public class ImportDecision
|
||||
{
|
||||
public LocalTrack LocalTrack { get; private set; }
|
||||
public IEnumerable<Rejection> Rejections { get; private set; }
|
||||
public IList<Rejection> Rejections { get; private set; }
|
||||
|
||||
public bool Approved => Rejections.Empty();
|
||||
|
||||
|
@ -20,5 +20,10 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
|||
LocalTrack = localTrack;
|
||||
Rejections = rejections.ToList();
|
||||
}
|
||||
|
||||
public void Reject(Rejection rejection)
|
||||
{
|
||||
Rejections.Add(rejection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,10 @@ using NzbDrone.Core.Qualities;
|
|||
using NzbDrone.Core.MediaFiles.MediaInfo;
|
||||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Music.Events;
|
||||
using System.Diagnostics;
|
||||
using NzbDrone.Common.EnsureThat;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.TrackImport
|
||||
{
|
||||
|
@ -19,7 +23,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
|||
{
|
||||
List<ImportDecision> GetImportDecisions(List<string> musicFiles, Artist artist);
|
||||
List<ImportDecision> GetImportDecisions(List<string> musicFiles, Artist artist, ParsedTrackInfo folderInfo);
|
||||
List<ImportDecision> GetImportDecisions(List<string> musicFiles, Artist artist, ParsedTrackInfo folderInfo, bool filterExistingFiles);
|
||||
List<ImportDecision> GetImportDecisions(List<string> musicFiles, Artist artist, ParsedTrackInfo folderInfo, bool filterExistingFiles, bool timidReleaseSwitching);
|
||||
ImportDecision GetImportDecision(string musicFile, Artist artist, Album album);
|
||||
}
|
||||
|
||||
|
@ -28,6 +32,9 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
|||
private readonly IEnumerable<IImportDecisionEngineSpecification> _specifications;
|
||||
private readonly IParsingService _parsingService;
|
||||
private readonly IMediaFileService _mediaFileService;
|
||||
private readonly IAlbumService _albumService;
|
||||
private readonly IReleaseService _releaseService;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IVideoFileInfoReader _videoFileInfoReader;
|
||||
private readonly Logger _logger;
|
||||
|
@ -35,6 +42,9 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
|||
public ImportDecisionMaker(IEnumerable<IImportDecisionEngineSpecification> specifications,
|
||||
IParsingService parsingService,
|
||||
IMediaFileService mediaFileService,
|
||||
IAlbumService albumService,
|
||||
IReleaseService releaseService,
|
||||
IEventAggregator eventAggregator,
|
||||
IDiskProvider diskProvider,
|
||||
IVideoFileInfoReader videoFileInfoReader,
|
||||
Logger logger)
|
||||
|
@ -42,6 +52,9 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
|||
_specifications = specifications;
|
||||
_parsingService = parsingService;
|
||||
_mediaFileService = mediaFileService;
|
||||
_albumService = albumService;
|
||||
_releaseService = releaseService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_diskProvider = diskProvider;
|
||||
_videoFileInfoReader = videoFileInfoReader;
|
||||
_logger = logger;
|
||||
|
@ -54,16 +67,47 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
|||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> musicFiles, Artist artist, ParsedTrackInfo folderInfo)
|
||||
{
|
||||
return GetImportDecisions(musicFiles, artist, folderInfo, false);
|
||||
return GetImportDecisions(musicFiles, artist, folderInfo, false, false);
|
||||
}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> musicFiles, Artist artist, ParsedTrackInfo folderInfo, bool filterExistingFiles)
|
||||
private bool MatchesCurrentRelease(ImportDecision decision)
|
||||
{
|
||||
return decision.Approved || decision.Rejections.Select(x => x.Reason).Contains("Has the same filesize as existing file");
|
||||
}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> musicFiles, Artist artist, ParsedTrackInfo folderInfo, bool filterExistingFiles, bool timidReleaseSwitching)
|
||||
{
|
||||
var files = filterExistingFiles ? _mediaFileService.FilterExistingFiles(musicFiles.ToList(), artist) : musicFiles.ToList();
|
||||
|
||||
_logger.Debug("Analyzing {0}/{1} files.", files.Count, musicFiles.Count);
|
||||
|
||||
var shouldUseFolderName = ShouldUseFolderName(musicFiles, artist, folderInfo);
|
||||
|
||||
// We have to do this once to match against albums
|
||||
var decisions = GetImportDecisionsForCurrentRelease(files, artist, folderInfo, shouldUseFolderName);
|
||||
|
||||
// Now we have matched the files against albums, we can group by album and check for the best release
|
||||
var albums = decisions.Where(x => x.LocalTrack.Album != null)
|
||||
.Select(x => x.LocalTrack.Album)
|
||||
.GroupBy(x => x.Id)
|
||||
.Select(x => x.First())
|
||||
.ToList();
|
||||
|
||||
var revisedDecisions = decisions.Where(x => x.LocalTrack.Album == null).ToList();
|
||||
|
||||
foreach (var album in albums)
|
||||
{
|
||||
var albumDecisions = decisions.Where(x => x.LocalTrack.Album != null && x.LocalTrack.Album.Id == album.Id).ToList();
|
||||
revisedDecisions.AddRange(GetImportDecisions(albumDecisions, artist, album, folderInfo, shouldUseFolderName, timidReleaseSwitching));
|
||||
}
|
||||
|
||||
Ensure.That(decisions.Count == revisedDecisions.Count).IsTrue();
|
||||
|
||||
return revisedDecisions;
|
||||
}
|
||||
|
||||
private List<ImportDecision> GetImportDecisionsForCurrentRelease(List<string> files, Artist artist, ParsedTrackInfo folderInfo, bool shouldUseFolderName)
|
||||
{
|
||||
var decisions = new List<ImportDecision>();
|
||||
|
||||
foreach (var file in files)
|
||||
|
@ -78,6 +122,90 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
|||
{
|
||||
return GetDecision(file, artist, album, null, false);
|
||||
}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<ImportDecision> decisions, Artist artist, Album album, ParsedTrackInfo folderInfo, bool shouldUseFolderName, bool timidReleaseSwitching)
|
||||
{
|
||||
_logger.Debug("Importing {0}", album);
|
||||
var maxTrackCount = album.AlbumReleases.Value.Where(x => x.Monitored).Select(x => x.TrackCount).Max();
|
||||
var haveExistingFiles = _mediaFileService.GetFilesByAlbum(album.Id).Any();
|
||||
var releaseSwitchingAllowed = !(haveExistingFiles && timidReleaseSwitching);
|
||||
|
||||
if (album.AnyReleaseOk && releaseSwitchingAllowed)
|
||||
{
|
||||
if (decisions.Any(x => !MatchesCurrentRelease(x)) || decisions.Count != maxTrackCount)
|
||||
{
|
||||
_logger.Debug("Importing {0}: {1}/{2} files approved for {3} track release",
|
||||
album,
|
||||
decisions.Count(x => MatchesCurrentRelease(x)),
|
||||
decisions.Count,
|
||||
maxTrackCount);
|
||||
return GetImportDecisionsForBestRelease(decisions, artist, album, folderInfo, shouldUseFolderName);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("Importing {0}: All files approved and all tracks have a file", album);
|
||||
return decisions;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("Importing {0}: {1}/{2} files approved for {3} track release. Release switching not allowed.",
|
||||
album,
|
||||
decisions.Count(x => MatchesCurrentRelease(x)),
|
||||
decisions.Count,
|
||||
maxTrackCount);
|
||||
return decisions;
|
||||
}
|
||||
}
|
||||
|
||||
private List<ImportDecision> GetImportDecisionsForBestRelease(List<ImportDecision> decisions, Artist artist, Album album, ParsedTrackInfo folderInfo, bool shouldUseFolderName)
|
||||
{
|
||||
var files = decisions.Select(x => x.LocalTrack.Path).ToList();
|
||||
|
||||
// At the moment we assume only one release can be monitored at a time
|
||||
var originalRelease = album.AlbumReleases.Value.Where(x => x.Monitored).Single();
|
||||
var candidateReleases = album.AlbumReleases.Value.Where(x => x.TrackCount >= files.Count && x.Id != originalRelease.Id).ToList();
|
||||
var bestRelease = originalRelease;
|
||||
var bestMatchCount = decisions.Count(x => MatchesCurrentRelease(x));
|
||||
var bestDecisions = decisions;
|
||||
|
||||
foreach (var release in candidateReleases)
|
||||
{
|
||||
_logger.Debug("Trying Release {0} [{1} tracks]", release, release.TrackCount);
|
||||
album.AlbumReleases = _releaseService.SetMonitored(release);
|
||||
var newDecisions = GetImportDecisionsForCurrentRelease(files, artist, folderInfo, shouldUseFolderName);
|
||||
|
||||
_logger.Debug("Importing {0}: {1}/{2} files approved for {3} track release {4}",
|
||||
album,
|
||||
newDecisions.Count(x => MatchesCurrentRelease(x)),
|
||||
newDecisions.Count,
|
||||
release.TrackCount,
|
||||
release);
|
||||
|
||||
// We want the release that matches the most tracks. If there's a tie,
|
||||
// we want the release with the fewest entries (i.e. fewest missing)
|
||||
var currentMatchCount = newDecisions.Count(x => MatchesCurrentRelease(x));
|
||||
if (currentMatchCount > bestMatchCount
|
||||
|| (currentMatchCount == bestMatchCount && release.TrackCount < bestRelease.TrackCount))
|
||||
{
|
||||
bestMatchCount = currentMatchCount;
|
||||
bestRelease = release;
|
||||
bestDecisions = newDecisions;
|
||||
|
||||
if (currentMatchCount == release.TrackCount && newDecisions.All(x => MatchesCurrentRelease(x)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug("{0} Best release: {1}", album, bestRelease);
|
||||
|
||||
// reinstate the original release in case the import isn't run (manual import)
|
||||
album.AlbumReleases = _releaseService.SetMonitored(originalRelease);
|
||||
|
||||
return bestDecisions;
|
||||
}
|
||||
|
||||
private ImportDecision GetDecision(string file, Artist artist, Album album, ParsedTrackInfo folderInfo, bool shouldUseFolderName)
|
||||
{
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
|||
public string FolderName { get; set; }
|
||||
public int ArtistId { get; set; }
|
||||
public int AlbumId { get; set; }
|
||||
public int AlbumReleaseId { get; set; }
|
||||
public List<int> TrackIds { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public Language Language { get; set; }
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
|||
public long Size { get; set; }
|
||||
public Artist Artist { get; set; }
|
||||
public Album Album { get; set; }
|
||||
public AlbumRelease Release { get; set; }
|
||||
public List<Track> Tracks { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public Language Language { get; set; }
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
|||
private readonly IMakeImportDecision _importDecisionMaker;
|
||||
private readonly IArtistService _artistService;
|
||||
private readonly IAlbumService _albumService;
|
||||
private readonly IReleaseService _releaseService;
|
||||
private readonly ITrackService _trackService;
|
||||
private readonly IVideoFileInfoReader _videoFileInfoReader;
|
||||
private readonly IImportApprovedTracks _importApprovedTracks;
|
||||
|
@ -50,6 +51,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
|||
IMakeImportDecision importDecisionMaker,
|
||||
IArtistService artistService,
|
||||
IAlbumService albumService,
|
||||
IReleaseService releaseService,
|
||||
ITrackService trackService,
|
||||
IVideoFileInfoReader videoFileInfoReader,
|
||||
IImportApprovedTracks importApprovedTracks,
|
||||
|
@ -65,6 +67,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
|||
_importDecisionMaker = importDecisionMaker;
|
||||
_artistService = artistService;
|
||||
_albumService = albumService;
|
||||
_releaseService = releaseService;
|
||||
_trackService = trackService;
|
||||
_videoFileInfoReader = videoFileInfoReader;
|
||||
_importApprovedTracks = importApprovedTracks;
|
||||
|
@ -138,7 +141,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
|||
|
||||
var folderInfo = Parser.Parser.ParseMusicTitle(directoryInfo.Name);
|
||||
var artistFiles = _diskScanService.GetAudioFiles(folder).ToList();
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(artistFiles, artist, folderInfo, filterExistingFiles);
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(artistFiles, artist, folderInfo, filterExistingFiles, true);
|
||||
|
||||
return decisions.Select(decision => MapItem(decision, folder, downloadId)).ToList();
|
||||
}
|
||||
|
@ -155,6 +158,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
|||
if (decision.LocalTrack.Album != null)
|
||||
{
|
||||
item.Album = decision.LocalTrack.Album;
|
||||
item.Release = decision.LocalTrack.Release;
|
||||
}
|
||||
|
||||
if (decision.LocalTrack.Tracks.Any())
|
||||
|
@ -240,6 +244,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
|||
if (decision.LocalTrack.Album != null)
|
||||
{
|
||||
item.Album = decision.LocalTrack.Album;
|
||||
item.Release = decision.LocalTrack.Release;
|
||||
}
|
||||
|
||||
if (decision.LocalTrack.Tracks.Any())
|
||||
|
@ -269,6 +274,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
|||
var file = message.Files[i];
|
||||
var artist = _artistService.GetArtist(file.ArtistId);
|
||||
var album = _albumService.GetAlbum(file.AlbumId);
|
||||
var release = _releaseService.GetRelease(file.AlbumReleaseId);
|
||||
var tracks = _trackService.GetTracks(file.TrackIds);
|
||||
var parsedTrackInfo = Parser.Parser.ParseMusicPath(file.Path) ?? new ParsedTrackInfo();
|
||||
var mediaInfo = _videoFileInfoReader.GetMediaInfo(file.Path);
|
||||
|
@ -285,6 +291,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
|||
Language = file.Language,
|
||||
Artist = artist,
|
||||
Album = album,
|
||||
Release = release,
|
||||
Size = 0
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,6 @@ namespace NzbDrone.Core.MetadataSource
|
|||
{
|
||||
public interface IProvideAlbumInfo
|
||||
{
|
||||
Tuple<Album, List<Track>> GetAlbumInfo(string lidarrId, string releaseId);
|
||||
Tuple<string, Album, List<ArtistMetadata>> GetAlbumInfo(string id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,6 @@ namespace NzbDrone.Core.MetadataSource
|
|||
{
|
||||
public interface IProvideArtistInfo
|
||||
{
|
||||
Tuple<Artist, List<Album>> GetArtistInfo(string lidarrId, int metadataProfileId);
|
||||
Artist GetArtistInfo(string lidarrId, int metadataProfileId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||
{
|
||||
public class AlbumArtistResource
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
|
@ -7,31 +7,18 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
|||
{
|
||||
public class AlbumResource
|
||||
{
|
||||
public AlbumResource()
|
||||
{
|
||||
Media = new List<MediumResource>();
|
||||
Releases = new List<ReleaseResource>();
|
||||
}
|
||||
|
||||
public List<ArtistResource> Artists { get; set; } // Will always be length of 1 unless a compilation
|
||||
public string Url { get; set; } // Link to the endpoint api to give full info for this object
|
||||
public string Id { get; set; } // This is a unique Album ID. Needed for all future API calls
|
||||
public DateTime ReleaseDate { get; set; }
|
||||
public List<ImageResource> Images { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string ArtistId { get; set; }
|
||||
public List<ArtistResource> Artists { get; set; }
|
||||
public string Disambiguation { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public List<string> Genres { get; set; }
|
||||
public List<string> Labels { get; set; }
|
||||
public string Type { get; set; }
|
||||
public List<string> SecondaryTypes { get; set; }
|
||||
public List<MediumResource> Media { get; set; }
|
||||
public List<TrackResource> Tracks { get; set; }
|
||||
public List<ReleaseResource> Releases { get; set; }
|
||||
public string Id { get; set; }
|
||||
public List<ImageResource> Images { get; set; }
|
||||
public List<LinkResource> Links { get; set; }
|
||||
public RatingResource Rating { get; set; }
|
||||
public string SelectedRelease { get; set; }
|
||||
public AlbumArtistResource Artist { get; set; }
|
||||
public DateTime ReleaseDate { get; set; }
|
||||
public List<ReleaseResource> Releases { get; set; }
|
||||
public List<string> SecondaryTypes { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Type { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||
{
|
||||
public class MemberResource
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Instrument { get; set; }
|
||||
public string Image { get; set; }
|
||||
}
|
||||
}
|
|
@ -5,14 +5,15 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
|||
{
|
||||
public class ReleaseResource
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public DateTime ReleaseDate { get; set; }
|
||||
public int MediaCount { get; set; }
|
||||
public int TrackCount { get; set; }
|
||||
public string Disambiguation { get; set; }
|
||||
public List<string> Label {get; set;}
|
||||
public List<string> Country { get; set; }
|
||||
public DateTime ReleaseDate { get; set; }
|
||||
public string Id { get; set; }
|
||||
public List<string> Label { get; set; }
|
||||
public List<MediumResource> Media { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Format { get; set; }
|
||||
public string Status { get; set; }
|
||||
public int TrackCount { get; set; }
|
||||
public List<TrackResource> Tracks { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||
{
|
||||
public class TimeOfDayResource
|
||||
{
|
||||
public int Hours { get; set; }
|
||||
public int Minutes { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,8 +1,3 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||
{
|
||||
public class TrackResource
|
||||
|
@ -12,16 +7,15 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
|||
|
||||
}
|
||||
|
||||
public int DiscNumber { get; set; }
|
||||
public string ArtistId { get; set; }
|
||||
public int DurationMs { get; set; }
|
||||
public string Href { get; set; }
|
||||
public string Id { get; set; }
|
||||
public string RecordingId { get; set; }
|
||||
public string TrackName { get; set; }
|
||||
public string TrackNumber { get; set; }
|
||||
public int TrackPosition { get; set; }
|
||||
public bool Explicit { get; set; }
|
||||
public int MediumNumber { get; set; }
|
||||
public List<ArtistResource> Artists { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public Tuple<Artist, List<Album>> GetArtistInfo(string foreignArtistId, int metadataProfileId)
|
||||
public Artist GetArtistInfo(string foreignArtistId, int metadataProfileId)
|
||||
{
|
||||
|
||||
_logger.Debug("Getting Artist with LidarrAPI.MetadataID of {0}", foreignArtistId);
|
||||
|
@ -87,13 +87,16 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
}
|
||||
}
|
||||
|
||||
var albums = httpResponse.Resource.Albums.Select(MapAlbum);
|
||||
var artist = MapArtist(httpResponse.Resource);
|
||||
var artist = new Artist();
|
||||
artist.Metadata = MapArtistMetadata(httpResponse.Resource);
|
||||
artist.CleanName = Parser.Parser.CleanArtistName(artist.Metadata.Value.Name);
|
||||
artist.SortName = Parser.Parser.NormalizeTitle(artist.Metadata.Value.Name);
|
||||
artist.Albums = httpResponse.Resource.Albums.Select(x => MapAlbum(x, null)).ToList();
|
||||
|
||||
return new Tuple<Artist, List<Album>>(artist, albums.ToList());
|
||||
return artist;
|
||||
}
|
||||
|
||||
public Tuple<Album, List<Track>> GetAlbumInfo(string foreignAlbumId, string releaseId)
|
||||
public Tuple<string, Album, List<ArtistMetadata>> GetAlbumInfo(string foreignAlbumId)
|
||||
{
|
||||
_logger.Debug("Getting Album with LidarrAPI.MetadataID of {0}", foreignAlbumId);
|
||||
|
||||
|
@ -101,7 +104,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
|
||||
var httpRequest = _customerRequestBuilder.Create()
|
||||
.SetSegment("route", "album/" + foreignAlbumId)
|
||||
.AddQueryParam("release", releaseId ?? string.Empty)
|
||||
.Build();
|
||||
|
||||
httpRequest.AllowAutoRedirect = true;
|
||||
|
@ -109,7 +111,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
|
||||
var httpResponse = _httpClient.Get<AlbumResource>(httpRequest);
|
||||
|
||||
|
||||
if (httpResponse.HasHttpError)
|
||||
{
|
||||
if (httpResponse.StatusCode == HttpStatusCode.NotFound)
|
||||
|
@ -126,10 +127,11 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
}
|
||||
}
|
||||
|
||||
var tracks = httpResponse.Resource.Tracks.Select(MapTrack);
|
||||
var album = MapAlbum(httpResponse.Resource);
|
||||
var artists = httpResponse.Resource.Artists.Select(MapArtistMetadata).ToList();
|
||||
var artistDict = artists.ToDictionary(x => x.ForeignArtistId, x => x);
|
||||
var album = MapAlbum(httpResponse.Resource, artistDict);
|
||||
|
||||
return new Tuple<Album, List<Track>>(album, tracks.ToList());
|
||||
return new Tuple<string, Album, List<ArtistMetadata>>(httpResponse.Resource.ArtistId, album, artists);
|
||||
}
|
||||
|
||||
public List<Artist> SearchForNewArtist(string title)
|
||||
|
@ -161,7 +163,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
|
||||
var metadataProfile = _metadataProfileService.All().First().Id; //Change this to Use last Used profile?
|
||||
|
||||
return new List<Artist> { GetArtistInfo(searchGuid.ToString(), metadataProfile).Item1 };
|
||||
return new List<Artist> { GetArtistInfo(searchGuid.ToString(), metadataProfile) };
|
||||
}
|
||||
catch (ArtistNotFoundException)
|
||||
{
|
||||
|
@ -183,7 +185,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
|
||||
var httpResponse = _httpClient.Get<List<ArtistResource>>(httpRequest);
|
||||
|
||||
return httpResponse.Resource.SelectList(MapSearhResult);
|
||||
return httpResponse.Resource.SelectList(MapSearchResult);
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -221,7 +223,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
|
||||
if (existingAlbum == null)
|
||||
{
|
||||
return new List<Album> {GetAlbumInfo(searchGuid.ToString(), null).Item1};
|
||||
return new List<Album> { GetAlbumInfo(searchGuid.ToString()).Item2 };
|
||||
}
|
||||
|
||||
existingAlbum.Artist = _artistService.GetArtist(existingAlbum.ArtistId);
|
||||
|
@ -247,7 +249,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
|
||||
var httpResponse = _httpClient.Get<List<AlbumResource>>(httpRequest);
|
||||
|
||||
return httpResponse.Resource.SelectList(MapSearhResult);
|
||||
return httpResponse.Resource.SelectList(MapSearchResult);
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -260,16 +262,21 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
}
|
||||
}
|
||||
|
||||
private Artist MapSearhResult(ArtistResource resource)
|
||||
private Artist MapSearchResult(ArtistResource resource)
|
||||
{
|
||||
var artist = _artistService.FindById(resource.Id) ?? MapArtist(resource);
|
||||
var artist = _artistService.FindById(resource.Id);
|
||||
if (artist == null)
|
||||
{
|
||||
artist = new Artist();
|
||||
artist.Metadata = MapArtistMetadata(resource);
|
||||
}
|
||||
|
||||
return artist;
|
||||
}
|
||||
|
||||
private Album MapSearhResult(AlbumResource resource)
|
||||
private Album MapSearchResult(AlbumResource resource)
|
||||
{
|
||||
var album = _albumService.FindById(resource.Id) ?? MapAlbum(resource);
|
||||
var album = _albumService.FindById(resource.Id) ?? MapAlbum(resource, null);
|
||||
|
||||
if (album.Artist == null)
|
||||
{
|
||||
|
@ -279,45 +286,62 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
return album;
|
||||
}
|
||||
|
||||
private static Album MapAlbum(AlbumResource resource)
|
||||
private static Album MapAlbum(AlbumResource resource, Dictionary<string, ArtistMetadata> artistDict)
|
||||
{
|
||||
Album album = new Album();
|
||||
album.Title = resource.Title;
|
||||
album.Disambiguation = resource.Disambiguation;
|
||||
album.ForeignAlbumId = resource.Id;
|
||||
album.Title = resource.Title;
|
||||
album.Overview = resource.Overview;
|
||||
album.Disambiguation = resource.Disambiguation;
|
||||
album.ReleaseDate = resource.ReleaseDate;
|
||||
album.CleanTitle = Parser.Parser.CleanArtistName(album.Title);
|
||||
album.Ratings = MapRatings(resource.Rating);
|
||||
album.AlbumType = resource.Type;
|
||||
|
||||
if (resource.Images != null)
|
||||
{
|
||||
album.Images = resource.Images.Select(MapImage).ToList();
|
||||
}
|
||||
|
||||
album.Label = resource.Labels;
|
||||
album.Media = resource.Media.Select(MapMedium).ToList();
|
||||
album.AlbumType = resource.Type;
|
||||
album.SecondaryTypes = resource.SecondaryTypes.Select(MapSecondaryTypes).ToList();
|
||||
album.Ratings = MapRatings(resource.Rating);
|
||||
album.Links = resource.Links?.Select(MapLink).ToList();
|
||||
album.CleanTitle = Parser.Parser.CleanArtistName(album.Title);
|
||||
|
||||
if (resource.Releases != null)
|
||||
{
|
||||
album.Releases = resource.Releases.Select(MapAlbumRelease).ToList();
|
||||
album.CurrentRelease = album.Releases.FirstOrDefault(s => s.Id == resource.SelectedRelease);
|
||||
album.AlbumReleases = resource.Releases.Select(x => MapRelease(x, artistDict)).ToList();
|
||||
album.AlbumReleases.Value.OrderByDescending(x => x.TrackCount).First().Monitored = true;
|
||||
}
|
||||
|
||||
if (resource.Artist != null)
|
||||
{
|
||||
album.Artist = new Artist
|
||||
{
|
||||
ForeignArtistId = resource.Artist.Id,
|
||||
Name = resource.Artist.Name
|
||||
};
|
||||
}
|
||||
|
||||
album.AnyReleaseOk = true;
|
||||
|
||||
return album;
|
||||
}
|
||||
|
||||
private static AlbumRelease MapRelease(ReleaseResource resource, Dictionary<string, ArtistMetadata> artistDict)
|
||||
{
|
||||
AlbumRelease release = new AlbumRelease();
|
||||
release.ForeignReleaseId = resource.Id;
|
||||
release.Title = resource.Title;
|
||||
release.Status = resource.Status;
|
||||
release.Label = resource.Label;
|
||||
release.Disambiguation = resource.Disambiguation;
|
||||
release.Country = resource.Country;
|
||||
release.ReleaseDate = resource.ReleaseDate;
|
||||
release.TrackCount = resource.TrackCount;
|
||||
release.Tracks = resource.Tracks.Select(x => MapTrack(x, artistDict)).ToList();
|
||||
release.Media = resource.Media.Select(MapMedium).ToList();
|
||||
if (!release.Media.Any())
|
||||
{
|
||||
foreach(int n in release.Tracks.Value.Select(x => x.MediumNumber).Distinct())
|
||||
{
|
||||
release.Media.Add(new Medium { Name = "Unknown", Number = n, Format = "Unknown" });
|
||||
}
|
||||
}
|
||||
release.Duration = release.Tracks.Value.Sum(x => x.Duration);
|
||||
|
||||
return release;
|
||||
}
|
||||
|
||||
private static Medium MapMedium(MediumResource resource)
|
||||
{
|
||||
Medium medium = new Medium
|
||||
|
@ -330,30 +354,14 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
return medium;
|
||||
}
|
||||
|
||||
private static AlbumRelease MapAlbumRelease(ReleaseResource resource)
|
||||
{
|
||||
AlbumRelease albumRelease = new AlbumRelease
|
||||
{
|
||||
Id = resource.Id,
|
||||
Title = resource.Title,
|
||||
ReleaseDate = resource.ReleaseDate,
|
||||
TrackCount = resource.TrackCount,
|
||||
Format = resource.Format,
|
||||
MediaCount = resource.MediaCount,
|
||||
Country = resource.Country,
|
||||
Disambiguation = resource.Disambiguation,
|
||||
Label = resource.Label
|
||||
};
|
||||
|
||||
return albumRelease;
|
||||
}
|
||||
|
||||
private static Track MapTrack(TrackResource resource)
|
||||
private static Track MapTrack(TrackResource resource, Dictionary<string, ArtistMetadata> artistDict)
|
||||
{
|
||||
Track track = new Track
|
||||
{
|
||||
ArtistMetadata = artistDict[resource.ArtistId],
|
||||
Title = resource.TrackName,
|
||||
ForeignTrackId = resource.Id,
|
||||
ForeignRecordingId = resource.RecordingId,
|
||||
TrackNumber = resource.TrackNumber,
|
||||
AbsoluteTrackNumber = resource.TrackPosition,
|
||||
Duration = resource.DurationMs,
|
||||
|
@ -363,45 +371,24 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
return track;
|
||||
}
|
||||
|
||||
private static Artist MapArtist(ArtistResource resource)
|
||||
private static ArtistMetadata MapArtistMetadata(ArtistResource resource)
|
||||
{
|
||||
|
||||
Artist artist = new Artist();
|
||||
ArtistMetadata artist = new ArtistMetadata();
|
||||
|
||||
artist.Name = resource.ArtistName;
|
||||
artist.ForeignArtistId = resource.Id;
|
||||
artist.Genres = resource.Genres;
|
||||
artist.Overview = resource.Overview;
|
||||
artist.CleanName = Parser.Parser.CleanArtistName(artist.Name);
|
||||
artist.SortName = Parser.Parser.NormalizeTitle(artist.Name);
|
||||
artist.Disambiguation = resource.Disambiguation;
|
||||
artist.ArtistType = resource.Type;
|
||||
artist.Images = resource.Images.Select(MapImage).ToList();
|
||||
artist.Type = resource.Type;
|
||||
artist.Status = MapArtistStatus(resource.Status);
|
||||
artist.Ratings = MapRatings(resource.Rating);
|
||||
artist.Links = resource.Links.Select(MapLink).ToList();
|
||||
artist.Images = resource.Images?.Select(MapImage).ToList();
|
||||
artist.Links = resource.Links?.Select(MapLink).ToList();
|
||||
return artist;
|
||||
}
|
||||
|
||||
private static Member MapMembers(MemberResource arg)
|
||||
{
|
||||
var newMember = new Member
|
||||
{
|
||||
Name = arg.Name,
|
||||
Instrument = arg.Instrument
|
||||
};
|
||||
|
||||
if (arg.Image != null)
|
||||
{
|
||||
newMember.Images = new List<MediaCover.MediaCover>
|
||||
{
|
||||
new MediaCover.MediaCover(MediaCoverTypes.Headshot, arg.Image)
|
||||
};
|
||||
}
|
||||
|
||||
return newMember;
|
||||
}
|
||||
|
||||
private static ArtistStatusType MapArtistStatus(string status)
|
||||
{
|
||||
if (status == null)
|
||||
|
|
|
@ -21,16 +21,19 @@ namespace NzbDrone.Core.Music
|
|||
{
|
||||
private readonly IAlbumService _albumService;
|
||||
private readonly IProvideAlbumInfo _albumInfo;
|
||||
private readonly IArtistMetadataRepository _artistMetadataRepository;
|
||||
private readonly IRefreshTrackService _refreshTrackService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public AddAlbumService(IAlbumService albumService,
|
||||
IProvideAlbumInfo albumInfo,
|
||||
IRefreshTrackService refreshTrackService,
|
||||
Logger logger)
|
||||
IProvideAlbumInfo albumInfo,
|
||||
IArtistMetadataRepository artistMetadataRepository,
|
||||
IRefreshTrackService refreshTrackService,
|
||||
Logger logger)
|
||||
{
|
||||
_albumService = albumService;
|
||||
_albumInfo = albumInfo;
|
||||
_artistMetadataRepository = artistMetadataRepository;
|
||||
_refreshTrackService = refreshTrackService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
@ -40,10 +43,11 @@ namespace NzbDrone.Core.Music
|
|||
Ensure.That(newAlbum, () => newAlbum).IsNotNull();
|
||||
|
||||
var tuple = AddSkyhookData(newAlbum);
|
||||
newAlbum = tuple.Item1;
|
||||
_refreshTrackService.RefreshTrackInfo(newAlbum, tuple.Item2);
|
||||
newAlbum = tuple.Item2;
|
||||
_logger.ProgressInfo("Adding Album {0}", newAlbum.Title);
|
||||
_albumService.AddAlbum(newAlbum);
|
||||
_artistMetadataRepository.UpsertMany(tuple.Item3);
|
||||
_albumService.AddAlbum(newAlbum, tuple.Item1);
|
||||
_refreshTrackService.RefreshTrackInfo(newAlbum);
|
||||
|
||||
return newAlbum;
|
||||
}
|
||||
|
@ -56,25 +60,26 @@ namespace NzbDrone.Core.Music
|
|||
foreach (var newAlbum in newAlbums)
|
||||
{
|
||||
var tuple = AddSkyhookData(newAlbum);
|
||||
var album = tuple.Item1;
|
||||
var album = tuple.Item2;
|
||||
album.Added = added;
|
||||
album.LastInfoSync = added;
|
||||
album = _albumService.AddAlbum(album);
|
||||
_refreshTrackService.RefreshTrackInfo(album,tuple.Item2);
|
||||
_logger.ProgressInfo("Adding Album {0}", newAlbum.Title);
|
||||
_artistMetadataRepository.UpsertMany(tuple.Item3);
|
||||
album = _albumService.AddAlbum(album, tuple.Item1);
|
||||
_refreshTrackService.RefreshTrackInfo(album);
|
||||
albumsToAdd.Add(album);
|
||||
}
|
||||
|
||||
return albumsToAdd;
|
||||
}
|
||||
|
||||
private Tuple<Album, List<Track>> AddSkyhookData(Album newAlbum)
|
||||
private Tuple<string, Album, List<ArtistMetadata>> AddSkyhookData(Album newAlbum)
|
||||
{
|
||||
Tuple<Album, List<Track>> tuple;
|
||||
Tuple<string, Album, List<ArtistMetadata>> tuple;
|
||||
|
||||
try
|
||||
{
|
||||
tuple = _albumInfo.GetAlbumInfo(newAlbum.ForeignAlbumId, null);
|
||||
tuple = _albumInfo.GetAlbumInfo(newAlbum.ForeignAlbumId);
|
||||
}
|
||||
catch (AlbumNotFoundException)
|
||||
{
|
||||
|
@ -86,10 +91,8 @@ namespace NzbDrone.Core.Music
|
|||
});
|
||||
}
|
||||
|
||||
tuple.Item1.ArtistId = newAlbum.ArtistId;
|
||||
tuple.Item1.Monitored = newAlbum.Monitored;
|
||||
tuple.Item1.ProfileId = newAlbum.ProfileId;
|
||||
tuple.Item1.Duration = tuple.Item2.Sum(track => track.Duration);
|
||||
tuple.Item2.Monitored = newAlbum.Monitored;
|
||||
tuple.Item2.ProfileId = newAlbum.ProfileId;
|
||||
|
||||
return tuple;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue