Example #1
0
        /// <inheritdoc />
        public void RecordScanFile(AnalyzedFile file, Movie movie)
        {
            using (var db = new LiteDatabase(GlobalSettings.Default.ConnectionString))
            {
                // update movie data
                var movieCollection = db.GetCollection <Movie>();
                movieCollection.Upsert(movie);

                // update data hash
                var hashCollection = db.GetCollection <MediaFileHash>();
                var hashEntity     = hashCollection.FindOne(x => x.Hash == file.Hash) ?? new MediaFileHash();
                hashEntity.Hash   = file.Hash;
                hashEntity.ImdbId = movie.ImdbId;
                hashEntity.Title  = movie.Title;
                hashEntity.Year   = movie.Year;

                hashCollection.Upsert(hashEntity);

                // update media file
                var mediaCollection = db.GetCollection <MediaFile>();
                var mediaEntity     = mediaCollection.FindOne(x => x.Hash == file.Hash) ?? new MediaFile();
                mediaEntity.TmdbId   = movie.TmdbId;
                mediaEntity.Hash     = file.Hash;
                mediaEntity.FullPath = file.FullPath;
                mediaEntity.LastSync = DateTime.Now;

                mediaCollection.Upsert(mediaEntity);
            }
        }
Example #2
0
        // identify a file
        private async Task <Movie> IdentifyFile(AnalyzedFile item)
        {
            Log.DebugFormat("Querying remote: {0} ({1})", item.Title, item.Year);
            Movie movie = null;

            try
            {
                List <SearchMovie> listContainer;

                // remote find
                if (!string.IsNullOrWhiteSpace(item.ImdbId))
                {
                    // search by id
                    var results = await _apiClient.FindAsync(FindExternalSource.Imdb, item.ImdbId);

                    listContainer = results.MovieResults;
                    Log.Debug($"Got {results.MovieResults.Count:N0} of {results.MovieResults.Count:N0} results");
                }
                else
                {
                    // search by title
                    var results = await _apiClient.SearchMovieAsync(item.Title);

                    listContainer = results.Results;
                    Log.Debug($"Got {results.Results.Count:N0} of {results.TotalResults:N0} results");
                }

                // get most candidate
                var candidateMovieRaw = listContainer.OrderByDescending(x => GetMatch(x, item)).FirstOrDefault();
                if (candidateMovieRaw == null)
                {
                    return(null);
                }

                movie = _dal.MapMovieToEntity(await _apiClient.GetMovieAsync(candidateMovieRaw.Id),
                                              _apiClient.GetImageUrl("w185", candidateMovieRaw.PosterPath).ToString());
            }
            catch (Exception e)
            {
                Log.Error("Unable to process request", e);
            }

            // return fetched or fallback
            return(movie ?? GetByFilename());

            Movie GetByFilename()
            {
                // the file is not identified by guessing algorithm
                Log.Debug("Unable to guess title, fallback to filename");
                return(new Movie
                {
                    Title = Path.GetFileName(item.FullPath),
                });
            }
        }
Example #3
0
        /// <inheritdoc />
        public async Task <AnalyzedFile> Analyze(string filePath)
        {
            var file = new FileInfo(filePath);
            var item = new AnalyzedFile(filePath);

            Log.DebugFormat("Analyzing: {0}", file.Name);

            using (var db = new LiteDatabase(GlobalSettings.Default.ConnectionString))
            {
                var hashCollection = db.GetCollection <MediaFileHash>();
                var fileCollection = db.GetCollection <MediaFile>();

                // lookup for hash
                var hash = IOExtension.QuickHash(filePath);
                item.Hash = hash;
                var hashEntity = hashCollection.FindOne(x => x.Hash == hash);

                // the file has recognized hash on database and has matching movie information
                if (hashEntity != null && fileCollection.Exists(x => x.Hash == hashEntity.Hash))
                {
                    item.Title   = hashEntity.Title;
                    item.Year    = hashEntity.Year;
                    item.ImdbId  = hashEntity.ImdbId;
                    item.IsKnown = true;

                    Log.DebugFormat("File found on hash table: {0}", hash);
                }
                else
                {
                    // the file only has one information on database, guessing is needed
                    var cleaned = await _provider.GuessTitle(item.FullPath);

                    item.Title   = cleaned.Title;
                    item.Year    = cleaned.Year;
                    item.ImdbId  = cleaned.ImdbId;
                    item.IsKnown = false;

                    Log.DebugFormat("File hash recorded: {0}", hash);
                }
            }

            // find subtitle and poster
            var extraFile = FindAssociatedFiles(Path.GetDirectoryName(filePath));

            item.SubtitlePath = extraFile.Item1;
            item.PosterPath   = extraFile.Item2;

            return(item);
        }
Example #4
0
        // get a value how it's likely the candidate is the guessed movie
        private float GetMatch(SearchMovie movie, AnalyzedFile candidate)
        {
            float res = 0;

            var dtt = DamerauLevenshtein.Calculate(candidate.Title.ToUpper(), movie.Title.ToUpper());
            var dto = DamerauLevenshtein.Calculate(candidate.Title.ToUpper(), movie.OriginalTitle.ToUpper());

            res += Math.Max(0, 5 - Math.Min(dtt, dto));

            if (Math.Abs(candidate.Year - (movie.ReleaseDate?.Year ?? 0)) <= 1)
            {
                res += 3;
            }
            return(res); // TODO: return value unchecked for 0<x<1 interval
        }
Example #5
0
        // Write to string builder the information used in csv file
        private void WriteCsvInformation(StringBuilder sb, OptionalInformation optionalInformation, AnalyzedFile file, string csvSeparator)
        {
            sb.Append(file.FileName).Append(csvSeparator).Append(file.Repeated.Words).Append(csvSeparator);

            if (optionalInformation.IncludeLocked)
            {
                sb.Append(file.Locked.Words).Append(csvSeparator);
            }
            if (optionalInformation.IncludePerfectMatch)
            {
                sb.Append(file.Perfect.Words).Append(csvSeparator);
            }
            if (optionalInformation.IncludeContextMatch)
            {
                sb.Append(file.InContextExact.Words).Append(csvSeparator);
            }
            if (optionalInformation.IncludeCrossRep)
            {
                sb.Append(file.CrossRep.Words).Append(csvSeparator);
            }

            // the 100% match is actually a sum of Exact, Perfect and InContextExact matches
            sb.Append((file.Exact.Words + file.Perfect.Words + file.InContextExact.Words).ToString()).Append(csvSeparator);

            foreach (var fuzzy in file.Fuzzies.OrderByDescending(fz => fz.Max))
            {
                sb.Append(fuzzy.Words).Append(csvSeparator);

                var internalFuzzy = file.InternalFuzzy(fuzzy.Min, fuzzy.Max);
                sb.Append(internalFuzzy != null ? internalFuzzy.Words : 0).Append(csvSeparator);
                if (optionalInformation.IncludeInternalFuzzies)
                {
                    sb.Append(internalFuzzy != null ? internalFuzzy.FullRecallWords : 0).Append(csvSeparator);
                }
            }

            if (optionalInformation.IncludeAdaptiveBaseline)
            {
                sb.Append(file.NewBaseline.FullRecallWords).Append(csvSeparator);
            }
            if (optionalInformation.IncludeAdaptiveLearnings)
            {
                sb.Append(file.NewLearnings.FullRecallWords).Append(csvSeparator);
            }

            sb.Append(file.Untranslated.Words).Append(csvSeparator).Append(file.Total.Words).Append(csvSeparator).Append(Environment.NewLine);
        }