Skip to content

Instantly share code, notes, and snippets.

@evilbloodydemon
Last active August 29, 2015 14:06
Show Gist options
  • Select an option

  • Save evilbloodydemon/314d24e67f10b7baf864 to your computer and use it in GitHub Desktop.

Select an option

Save evilbloodydemon/314d24e67f10b7baf864 to your computer and use it in GitHub Desktop.
//subquery
private void UpdateBestVideoQuality(DbTorronto db, Movie movie)
{
db.Movie
.Where(m => m.ID == movie.ID)
.Set(f => f.BestVideoQuality, m => db.Torrent
.Where(t => t.MovieID == m.ID)
.Select(t => t.VideoQuality)
.Max())
.Update();
}
using LinqToDB;
using NLog;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using Torronto.BLL.Ext;
using Torronto.BLL.Models;
using Torronto.DAL;
using Torronto.DAL.Models;
namespace Torronto.BLL
{
public class MovieService
{
private static readonly bool _isSphinxEnabled = Convert.ToBoolean(ConfigurationManager.AppSettings["Search.IsSphinxEnabled"]);
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
public const int SYSTEM_LIST = -1;
private readonly SearchService _searchService;
public MovieService(SearchService searchService)
{
_searchService = searchService;
}
public IEnumerable<Movie> GetWaitList(int userId)
{
using (var db = new DbTorronto())
{
var movies = (
from mu in db.MovieUser
join m in db.Movie on mu.MovieID equals m.ID
where mu.UserID == userId
orderby m.Title
select m
).ToList();
var movieIds = movies.Select(m => m.ID);
var torrents = db.Torrent.Where(t => movieIds.Contains(t.MovieID)).ToList();
var items = movies.GroupJoin(torrents, m => m.ID, t => t.MovieID, Movie.AddRelated);
return items;
}
}
public MoviePagination GetMovies(int? userId, MovieSearchParams search, PaginationParams pageParams)
{
using (var db = new DbTorronto())
{
var filter = db.Movie
.SelectMany(m => db.MovieUser.Where(x => x.MovieID == m.ID && x.UserID == userId).DefaultIfEmpty(),
(movie, movieUser) => new { movie = movie, muUser = movieUser })
.SelectMany(m => db.MovieUser.Where(x => x.MovieID == m.movie.ID && x.UserID == SYSTEM_LIST).DefaultIfEmpty(),
(m, muSystem) => new
{
M = m.movie,
MuWaitList = m.muUser.IsWaitlist,
MuUserWatched = m.muUser.IsWatched,
MuSystemID = muSystem.ID,
WlDate = m.muUser.Created,
MuMark = m.muUser.Mark,
});
if (!string.IsNullOrEmpty(search.Search))
{
if (_isSphinxEnabled)
{
var movieIds = _searchService.SearchMovieIds(search);
filter = filter.Where(x => movieIds.Contains(x.M.ID));
}
else
{
filter = filter.Where(x => x.M.Title.Contains(search.Search)
|| x.M.OriginalTitle.Contains(search.Search));
}
}
if (search.WaitList)
{
filter = filter.Where(x => x.MuWaitList);
}
if (search.SystemList)
{
filter = filter.Where(x => x.MuSystemID != null
&& (x.MuUserWatched == null || x.MuUserWatched == false)
&& (x.MuWaitList == null || x.MuWaitList == false));
}
if (search.MovieStatus != MovieStatus.Unknown)
{
filter = filter.Where(x => x.M.Status == search.MovieStatus);
}
List<Person> actors = null;
if (!string.IsNullOrEmpty(search.Actors))
{
var actorIds = search.Actors
.Split(',')
.Select(x => Convert.ToInt32(x))
.Cast<int?>()
.ToArray();
actors = db.Person
.Where(p => actorIds.Contains(p.ID))
.ToList();
var movieIds = db.MoviePerson
.Where(mp => actorIds.Contains(mp.PersonID))
.Select(mp => mp.MovieID)
.Cast<int?>()
.ToArray();
filter = filter.Where(x => movieIds.Contains(x.M.ID));
}
switch (pageParams.Order)
{
case "wldate":
filter = filter.OrderByDescending(x => x.WlDate);
break;
case "rkp":
filter = filter.OrderByDescending(f => f.M.RatingKinopoisk);
break;
case "rimdb":
filter = filter.OrderByDescending(f => f.M.RatingImdb);
break;
case "ruser":
filter = filter
.OrderByDescending(f => f.MuMark)
.ThenByDescending(f => f.M.RatingKinopoisk);
break;
case "quality":
filter = filter
.OrderByDescending(f => f.M.BestVideoQuality)
.ThenByDescending(f => f.M.RatingKinopoisk);
break;
case "added":
filter = filter
.OrderByDescending(f => f.M.Created)
.ThenByDescending(f => f.M.ID);
break;
default:
filter = filter.OrderBy(t => t.M.Title);
break;
}
var count = pageParams.NoCount ? 0 : filter.Count();
var movies = filter
.Skip(pageParams.SkipCount)
.Take(pageParams.PageSize)
.Select(t => new MovieItem
{
Self = new Movie
{
ID = t.M.ID,
Title = t.M.Title,
OriginalTitle = t.M.OriginalTitle,
ImdbID = t.M.ImdbID,
KinopoiskID = t.M.KinopoiskID,
RatingImdb = t.M.RatingImdb,
RatingKinopoisk = t.M.RatingKinopoisk,
ReleaseDate = t.M.ReleaseDate,
Status = t.M.Status,
BestVideoQuality = t.M.BestVideoQuality
},
InWaitList = t.MuWaitList,
Mark = t.MuMark,
InSystemList = (t.MuSystemID != null),
IsWatched = t.MuUserWatched
})
.ToList();
return new MoviePagination(movies)
{
PageSize = pageParams.PageSize,
TotalItems = count,
Actors = actors
};
}
}
public void AddMovieUserLink(int movieId, int? userId, bool? waitlist, bool? watched, int? mark)
{
if (userId == null) return;
using (var db = new DbTorronto())
{
//hardcoded check
if (mark >= 1 && mark < 4) mark = 4;
if (mark > 4 && mark < 7) mark = 7;
if (mark > 7) mark = 10;
var update = db.MovieUser
.Where(mu => mu.UserID == userId && mu.MovieID == movieId)
.Set(f => f.MovieID, movieId); //todo find another way to get IUpdatabled from IQueryable
if (waitlist == true) update = update.Set(f => f.IsWaitlist, true);
if (watched == true)
{
update = update
.Set(f => f.IsWatched, true)
.Set(f => f.IsWaitlist, false);
}
if (mark > 0)
{
update = update
.Set(f => f.Mark, mark)
.Set(f => f.IsWatched, true)
.Set(f => f.IsWaitlist, false);
}
var affected = update.Update();
if (affected == 0)
{
var newMu = new MovieUser
{
Created = DateTime.UtcNow,
UserID = userId.GetValueOrDefault(),
MovieID = movieId
};
if (waitlist == true) newMu.IsWaitlist = true;
if (watched == true) newMu.IsWatched = true;
if (mark > 0)
{
newMu.Mark = mark;
newMu.IsWatched = true;
}
db.Insert(newMu);
}
}
}
public void RemoveMovieUserLink(int movieId, int? userId, bool? waitlist = null, bool? watched = null)
{
using (var db = new DbTorronto())
{
var update = db.MovieUser
.Where(mu => mu.UserID == userId && mu.MovieID == movieId)
.Set(f => f.MovieID, movieId);
if (waitlist == true)
{
update = update.Set(f => f.IsWaitlist, false);
}
if (watched == true)
{
update = update
.Set(f => f.IsWatched, false)
.Set(f => f.Mark, (int?)null);
}
update.Update();
}
}
public MovieItem GetMovieSingle(int? userId, int movieId)
{
using (var db = new DbTorronto())
{
var item = db.Movie
.SelectMany(m => db.MovieUser.Where(x => x.MovieID == m.ID && x.UserID == userId).DefaultIfEmpty(),
(m, movieUser) => new { movie = m, muUser = movieUser })
.FirstOrDefault(x => x.movie.ID == movieId);
if (item != null)
{
var torrents = db.Torrent
.Where(t => t.MovieID == item.movie.ID)
.OrderByDescending(t => t.VideoQuality)
.ThenByDescending(t => t.Size)
.Take(100);
var persons =
from p in db.Person
join mp in db.MoviePerson on p.ID equals mp.PersonID
where mp.MovieID == item.movie.ID
orderby mp.Position
select p;
var genres =
from g in db.Genre
join mg in db.MovieGenre on g.ID equals mg.GenreID
where mg.MovieID == item.movie.ID
orderby mg.Position
select g;
Movie.AddRelated(item.movie, torrents);
Movie.AddRelated(item.movie, persons.Take(6));
Movie.AddRelated(item.movie, genres);
var movieItem = new MovieItem
{
Self = item.movie
};
if (item.muUser != null)
{
movieItem.InWaitList = item.muUser.IsWaitlist;
movieItem.IsWatched = item.muUser.IsWatched;
movieItem.Mark = item.muUser.Mark;
}
return movieItem;
}
}
return null;
}
public Movie GetById(int movieId)
{
using (var db = new DbTorronto())
{
return db.Movie
.FirstOrDefault(m => m.ID == movieId);
}
}
public void SaveDetails(Movie detailed)
{
using (var db = new DbTorronto())
{
db.Movie
.Where(x => x.ID == detailed.ID)
.Set(f => f.IsDetailed, detailed.IsDetailed)
.Set(f => f.Title, detailed.Title)
.Set(f => f.OriginalTitle, detailed.OriginalTitle)
.Set(f => f.ReleaseDate, detailed.ReleaseDate)
.Set(f => f.Description, detailed.Description)
.Set(f => f.ImdbID, detailed.ImdbID)
.Set(f => f.DurationMinutes, detailed.DurationMinutes)
.Update();
var actorPosition = 0;
foreach (var actor in detailed.Persons)
{
var existingActor = db.Person.FirstOrDefault(p => p.SiteID == actor.SiteID);
if (existingActor == null)
{
existingActor = new Person
{
Name = actor.Name,
SiteID = actor.SiteID
};
existingActor.ID = Convert.ToInt32(
db.InsertWithIdentity(existingActor)
);
}
db.MoviePerson.InsertOrUpdate(
() => new MoviePerson
{
MovieID = detailed.ID.GetValueOrDefault(),
PersonID = existingActor.ID.GetValueOrDefault(),
Position = actorPosition
},
old => new MoviePerson
{
Position = actorPosition
}
);
actorPosition++;
}
var genrePosition = 0;
foreach (var genre in detailed.Genres)
{
var existingGenre = db.Genre.FirstOrDefault(p => p.SiteID == genre.SiteID);
if (existingGenre == null)
{
existingGenre = new Genre
{
Name = genre.Name,
SiteID = genre.SiteID
};
existingGenre.ID = Convert.ToInt32(
db.InsertWithIdentity(existingGenre)
);
}
db.MovieGenre.InsertOrUpdate(
() => new MovieGenre
{
MovieID = detailed.ID.GetValueOrDefault(),
GenreID = existingGenre.ID.GetValueOrDefault(),
Position = genrePosition
},
old => new MovieGenre
{
Position = genrePosition
}
);
genrePosition++;
}
}
}
public void SaveMovies(List<Movie> movies, int? userId)
{
using (var db = new DbTorronto())
{
foreach (var movie in movies.Where(m => m.KinopoiskID != null))
{
var existing = db.Movie
.FirstOrDefault(x => x.KinopoiskID == movie.KinopoiskID);
int movieId;
if (existing == null)
{
movie.Created = DateTime.UtcNow;
movie.Updated = DateTime.UtcNow;
try
{
movieId = Convert.ToInt32(
db.InsertWithIdentity(movie)
);
}
catch (Exception ex)
{
_logger.Warn("KinopoiskService.SaveToDb", ex);
continue;
}
QueueService.AddMovieForMatch(movieId);
}
else
{
movieId = existing.ID.GetValueOrDefault();
db.Movie
.Where(x => x.ID == existing.ID)
.Set(f => f.Status, movie.Status)
.Set(f => f.Updated, DateTime.UtcNow)
.Update();
}
movie.ID = movieId;
if (userId != null && !db.MovieUser.Any(x => x.MovieID == movieId && x.UserID == userId))
{
db.InsertMovieUser(movieId, userId.GetValueOrDefault());
}
}
}
}
public List<Movie> CreateMoviesFromTorrents()
{
List<Movie> movies;
using (var db = new DbTorronto())
{
var ids = db.Torrent
.Where(t => t.MovieID == null && t.KinopoiskID != null)
.Select(t => t.KinopoiskID)
.Distinct()
.Take(100)
.ToList();
movies = ids
.Where(id => db.Movie.FirstOrDefault(m => m.KinopoiskID == id) == null)
.Select(kinopoiskID => new Movie
{
Title = "Unknown yet",
KinopoiskID = kinopoiskID
})
.ToList();
}
SaveMovies(movies, null);
return movies;
}
}
}
using LinqToDB;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using Torronto.BLL.Ext;
using Torronto.BLL.Models;
using Torronto.DAL;
using Torronto.DAL.Models;
namespace Torronto.BLL
{
public class TorrentService
{
private static readonly bool _isSphinxEnabled = Convert.ToBoolean(ConfigurationManager.AppSettings["Search.IsSphinxEnabled"]);
private readonly SearchService _searchService;
public const int SYSTEM_LIST = -1;
public static readonly Tuple<int, int>[] TorrentSizes =
{
new Tuple<int, int>(0, 1024),
new Tuple<int, int>(1 * 1024 + 1, 3 * 1024),
new Tuple<int, int>(3 * 1024 + 1, 5 * 1024),
new Tuple<int, int>(5 * 1024 + 1, 15 * 1024),
new Tuple<int, int>(15 * 1024 + 1, 1024 * 1024)
};
private class TorrentJoin
{
public Torrent Torrent { get; set; }
public bool MuWaitlist { get; set; }
public int? MuSystemList { get; set; }
}
public TorrentService(SearchService searchService)
{
_searchService = searchService;
}
public Pagination<TorrentItem> GetTorrents(int? userId, TorrentSearchParams search, PaginationParams pageParams)
{
using (var db = new DbTorronto())
{
var filter = from t in db.Torrent
from muSystemList in db.MovieUser.Where(mu => mu.MovieID == t.MovieID && mu.UserID == SYSTEM_LIST).DefaultIfEmpty()
from muWaitList in db.MovieUser.Where(mu => mu.MovieID == t.MovieID && mu.UserID == userId).DefaultIfEmpty()
select new TorrentJoin
{
Torrent = t,
MuWaitlist = muWaitList.IsWaitlist,
MuSystemList = muSystemList.ID
};
if (search.WaitList)
{
filter = filter.Where(x => x.MuWaitlist);
}
if (search.SystemList)
{
filter = filter.Where(x => x.MuSystemList != null);
}
if (!string.IsNullOrEmpty(search.Search))
{
if (_isSphinxEnabled)
{
var torrentIds = _searchService.SearchTorrentIds(search);
filter = filter.Where(x => torrentIds.Contains(x.Torrent.ID));
}
else
{
filter = filter.Where(x => x.Torrent.Title.Contains(search.Search));
}
}
if (search.VideoQuality != VideoQuality.Unknown)
{
var predicate = PredicateBuilder.False<TorrentJoin>();
predicate = Enum.GetValues(typeof(VideoQuality))
.Cast<VideoQuality>()
.Where(vq => vq != VideoQuality.Unknown)
.Where(vq => search.VideoQuality.HasFlag(vq))
.Aggregate(predicate, (current, vq) => current.Or(x => x.Torrent.VideoQuality == vq));
filter = filter.Where(predicate);
}
if (search.AudioQuality != AudioQuality.Unknown)
{
var predicate = PredicateBuilder.False<TorrentJoin>();
predicate = Enum.GetValues(typeof(AudioQuality))
.Cast<AudioQuality>()
.Where(aq => aq != AudioQuality.Unknown)
.Where(aq => search.AudioQuality.HasFlag(aq))
.Aggregate(predicate, (current, aq) => current.Or(x => x.Torrent.AudioQuality == aq));
filter = filter.Where(predicate);
}
if (search.TranslationQuality != Translation.Unknown)
{
var predicate = PredicateBuilder.False<TorrentJoin>();
predicate = Enum.GetValues(typeof(Translation))
.Cast<Translation>()
.Where(translation => translation != Translation.Unknown)
.Where(translation => search.TranslationQuality.HasFlag(translation))
.Aggregate(predicate, (current, translation) => current.Or(x => x.Torrent.Translation == translation));
filter = filter.Where(predicate);
}
if (search.TorrentCategory != TorrentCategory.Unknown)
{
var predicate = PredicateBuilder.False<TorrentJoin>();
predicate = Enum.GetValues(typeof(TorrentCategory))
.Cast<TorrentCategory>()
.Where(category => category != TorrentCategory.Unknown)
.Where(category => search.TorrentCategory.HasFlag(category))
.Aggregate(predicate, (current, category) => current.Or(x => x.Torrent.Category == category));
filter = filter.Where(predicate);
}
if (!string.IsNullOrEmpty(search.Sizes))
{
var index = 0;
var nums = search.Sizes
.Split(',')
.Select(x => Convert.ToInt32(x))
.ToArray();
var predicate = PredicateBuilder.False<TorrentJoin>();
foreach (var tuple in TorrentSizes)
{
if (nums.Contains(index))
{
predicate = predicate.Or(x => x.Torrent.Size >= tuple.Item1 && x.Torrent.Size <= tuple.Item2);
}
index++;
}
filter = filter.Where(predicate);
}
var count = pageParams.NoCount ? 0 : filter.Count();
var items = filter
.OrderByDescending(x => x.Torrent.Created)
.ThenByDescending(x => x.Torrent.ID)
.Skip(pageParams.SkipCount)
.Take(pageParams.PageSize)
.Select(x => new TorrentItem
{
Self = x.Torrent,
InWaitList = x.MuWaitlist,
InSystemList = (x.MuSystemList != null)
});
return new Pagination<TorrentItem>(items.ToList())
{
TotalItems = count,
PageSize = pageParams.PageSize
};
}
}
public TorrentItem GetSingleTorrent(int torrentID)
{
using (var db = new DbTorronto())
{
var item = db.Torrent
.FirstOrDefault(x => x.ID == torrentID);
return new TorrentItem
{
Self = item
};
}
}
public Torrent GetById(int torrentId)
{
using (var db = new DbTorronto())
{
return db.Torrent
.FirstOrDefault(m => m.ID == torrentId);
}
}
public void SaveToDb(List<Torrent> torrents)
{
using (var db = new DbTorronto())
{
foreach (var torrent in torrents)
{
var existing = db.Torrent
.FirstOrDefault(x => x.SiteID == torrent.SiteID);
if (existing == null)
{
torrent.Updated = DateTime.UtcNow;
db.Insert(torrent);
}
else
{
db.Torrent
.Where(x => x.ID == existing.ID && !x.IsDetailed)
.Set(f => f.Title, torrent.Title)
.Set(f => f.InfoHash, torrent.InfoHash)
.Set(f => f.Updated, DateTime.UtcNow)
.Update();
}
}
}
}
public void SaveDetails(Torrent torrent, bool isRemoved)
{
using (var db = new DbTorronto())
{
var filter = db.Torrent
.Where(x => x.ID == torrent.ID)
.Set(f => f.Updated, DateTime.UtcNow)
.Set(f => f.IsDetailed, true);
if (isRemoved)
{
filter = filter.Set(f => f.IsRemoved, true);
}
else
{
filter = filter
.Set(f => f.ImdbID, torrent.ImdbID)
.Set(f => f.KinopoiskID, torrent.KinopoiskID)
.Set(f => f.VideoQuality, torrent.VideoQuality)
.Set(f => f.AudioQuality, torrent.AudioQuality)
.Set(f => f.Translation, torrent.Translation)
.Set(f => f.IsRemoved, false);
}
filter.Update();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment