private System.IO.Stream InternalGetFile(int userid, string Id) { int id; if (!int.TryParse(Id, out id)) { return(new MemoryStream()); } KodiObject ret = new KodiObject(KodiHelper.NewMediaContainer("Unsort", true)); if (!ret.Init()) { return(new MemoryStream()); } List <Video> dirs = new List <Video>(); Video v = new Video(); dirs.Add(v); VideoLocalRepository repVids = new VideoLocalRepository(); VideoLocal vi = repVids.GetByID(id); if (vi == null) { return(new MemoryStream()); } KodiHelper.PopulateVideo(v, vi, JMMType.File, userid); ret.Childrens = dirs; ret.MediaContainer.Art = v.Art; return(ret.GetStream()); }
public override void ProcessCommand() { logger.Info("Processing CommandRequest_UpdateMyListFileStatus: {0}", Hash); try { VideoLocalRepository repVids = new VideoLocalRepository(); AnimeEpisodeRepository repEpisodes = new AnimeEpisodeRepository(); // NOTE - we might return more than one VideoLocal record here, if there are duplicates by hash VideoLocal vid = repVids.GetByHash(this.Hash); if (vid != null) { bool isManualLink = false; List <CrossRef_File_Episode> xrefs = vid.EpisodeCrossRefs; if (xrefs.Count > 0) { isManualLink = xrefs[0].CrossRefSource != (int)CrossRefSource.AniDB; } if (isManualLink) { JMMService.AnidbProcessor.UpdateMyListFileStatus(xrefs[0].AnimeID, xrefs[0].Episode.EpisodeNumber, this.Watched); logger.Info("Updating file list status (GENERIC): {0} - {1}", vid.ToString(), this.Watched); } else { if (WatchedDateAsSecs > 0) { DateTime?watchedDate = Utils.GetAniDBDateAsDate(WatchedDateAsSecs); JMMService.AnidbProcessor.UpdateMyListFileStatus(vid, this.Watched, watchedDate); } else { JMMService.AnidbProcessor.UpdateMyListFileStatus(vid, this.Watched, null); } logger.Info("Updating file list status: {0} - {1}", vid.ToString(), this.Watched); } if (UpdateSeriesStats) { // update watched stats List <AnimeEpisode> eps = repEpisodes.GetByHash(vid.ED2KHash); if (eps.Count > 0) { // all the eps should belong to the same anime eps[0].GetAnimeSeries().QueueUpdateStats(); //eps[0].AnimeSeries.TopLevelAnimeGroup.UpdateStatsFromTopLevel(true, true, false); } } } } catch (Exception ex) { logger.Error("Error processing CommandRequest_UpdateMyListFileStatus: {0} - {1}", Hash, ex.ToString()); return; } }
private System.IO.Stream GetUnsort(int userid, HistoryInfo info) { PlexObject ret = new PlexObject(PlexHelper.NewMediaContainer(MediaContainerTypes.Video, info, true)); if (!ret.Init()) { return(new MemoryStream()); } List <Video> dirs = new List <Video>(); VideoLocalRepository repVids = new VideoLocalRepository(); List <VideoLocal> vids = repVids.GetVideosWithoutEpisode(); foreach (VideoLocal v in vids.OrderByDescending(a => a.DateTimeCreated)) { Video m = new Video(); try { PlexHelper.PopulateVideo(m, v, JMMType.File, userid); m.GrandparentKey = null; if (!string.IsNullOrEmpty(m.Duration)) { dirs.Add(m, info); } } catch (Exception e) { //Fast fix if file do not exist, and still is in db. (Xml Serialization of video info will fail on null) } } ret.Childrens = dirs; return(ret.GetStream()); }
private System.IO.Stream GetUnsort(int userid) { KodiObject ret = new KodiObject(KodiHelper.NewMediaContainer("Unsort", true)); if (!ret.Init()) { return(new MemoryStream()); } List <Video> dirs = new List <Video>(); ret.MediaContainer.ViewMode = "65586"; ret.MediaContainer.ViewGroup = "video"; VideoLocalRepository repVids = new VideoLocalRepository(); List <VideoLocal> vids = repVids.GetVideosWithoutEpisode(); foreach (VideoLocal v in vids.OrderByDescending(a => a.DateTimeCreated)) { Video m = new Video(); try { KodiHelper.PopulateVideo(m, v, JMMType.File, userid); if (!string.IsNullOrEmpty(m.Duration)) { dirs.Add(m); } } catch (Exception e) { //Fast fix if file do not exist, and still is in db. (Xml Serialization of video info will fail on null) } } ret.Childrens = dirs; return(ret.GetStream()); }
public override void ProcessCommand() { logger.Info("Processing File: {0}", VideoLocalID); try { VideoLocalRepository repVids = new VideoLocalRepository(); vlocal = repVids.GetByID(VideoLocalID); if (vlocal == null) { return; } //now that we have all the has info, we can get the AniDB Info ProcessFile_AniDB(vlocal); } catch (Exception ex) { logger.Error("Error processing CommandRequest_ProcessFile: {0} - {1}", VideoLocalID, ex.ToString()); return; } // TODO update stats for group and series // TODO check for TvDB }
public static Video VideoFromVideoLocal(IProvider prov, VideoLocal v, int userid) { Video l = new Video(); l.AnimeType = JMMContracts.PlexAndKodi.AnimeTypes.AnimeFile.ToString(); l.Id = v.VideoLocalID.ToString(); l.Type = "episode"; l.Summary = "Episode Overview Not Available"; //TODO Intenationalization l.Title = Path.GetFileNameWithoutExtension(v.FilePath); l.AddedAt = v.DateTimeCreated.ToUnixTime(); l.UpdatedAt = v.DateTimeUpdated.ToUnixTime(); l.OriginallyAvailableAt = v.DateTimeCreated.ToPlexDate(); l.Year = v.DateTimeCreated.Year.ToString(); l.Medias = new List <Media>(); Media m = v.Media; if (m == null) { VideoLocalRepository lrepo = new VideoLocalRepository(); lrepo.Save(v, true); m = v.Media; } if (m != null) { l.Medias.Add(m); l.Duration = m.Duration; } AddLinksToAnimeEpisodeVideo(prov, l, userid); return(l); }
public static string DeleteImportFolder(int importFolderID) { try { ImportFolderRepository repNS = new ImportFolderRepository(); ImportFolder ns = repNS.GetByID(importFolderID); if (ns == null) return "Could not find Import Folder ID: " + importFolderID; // first delete all the files attached to this import folder Dictionary<int, AnimeSeries> affectedSeries = new Dictionary<int, AnimeSeries>(); VideoLocalRepository repVids = new VideoLocalRepository(); foreach (VideoLocal vid in repVids.GetByImportFolder(importFolderID)) { //Thread.Sleep(5000); logger.Info("Deleting video local record: {0}", vid.FullServerPath); AnimeSeries ser = null; List<AnimeEpisode> animeEpisodes = vid.GetAnimeEpisodes(); if (animeEpisodes.Count > 0) { ser = animeEpisodes[0].GetAnimeSeries(); if (ser != null && !affectedSeries.ContainsKey(ser.AnimeSeriesID)) affectedSeries.Add(ser.AnimeSeriesID, ser); } repVids.Delete(vid.VideoLocalID); } // delete any duplicate file records which reference this folder DuplicateFileRepository repDupFiles = new DuplicateFileRepository(); foreach (DuplicateFile df in repDupFiles.GetByImportFolder1(importFolderID)) repDupFiles.Delete(df.DuplicateFileID); foreach (DuplicateFile df in repDupFiles.GetByImportFolder2(importFolderID)) repDupFiles.Delete(df.DuplicateFileID); // delete the import folder repNS.Delete(importFolderID); ServerInfo.Instance.RefreshImportFolders(); foreach (AnimeSeries ser in affectedSeries.Values) { ser.QueueUpdateStats(); //StatsCache.Instance.UpdateUsingSeries(ser.AnimeSeriesID); } return ""; } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); return ex.Message; } }
public void RenameFile(string renameScript) { string renamed = RenameFileHelper.GetNewFileName(this, renameScript); if (string.IsNullOrEmpty(renamed)) { return; } ImportFolderRepository repFolders = new ImportFolderRepository(); VideoLocalRepository repVids = new VideoLocalRepository(); // actually rename the file string fullFileName = this.FullServerPath; // check if the file exists if (!File.Exists(fullFileName)) { logger.Error("Error could not find the original file for renaming: " + fullFileName); return; } // actually rename the file string path = Path.GetDirectoryName(fullFileName); string newFullName = Path.Combine(path, renamed); try { logger.Info(string.Format("Renaming file From ({0}) to ({1})....", fullFileName, newFullName)); if (fullFileName.Equals(newFullName, StringComparison.InvariantCultureIgnoreCase)) { logger.Info(string.Format("Renaming file SKIPPED, no change From ({0}) to ({1})", fullFileName, newFullName)); } else { File.Move(fullFileName, newFullName); logger.Info(string.Format("Renaming file SUCCESS From ({0}) to ({1})", fullFileName, newFullName)); string newPartialPath = ""; int folderID = this.ImportFolderID; DataAccessHelper.GetShareAndPath(newFullName, repFolders.GetAll(), ref folderID, ref newPartialPath); this.FilePath = newPartialPath; repVids.Save(this, true); } } catch (Exception ex) { logger.Info(string.Format("Renaming file FAIL From ({0}) to ({1}) - {2}", fullFileName, newFullName, ex.Message)); logger.ErrorException(ex.ToString(), ex); } }
public static bool RefreshIfMediaEmpty(VideoLocal vl, Video v) { if (v.Medias == null || v.Medias.Count == 0) { VideoLocalRepository lrepo = new VideoLocalRepository(); lrepo.Save(vl, true); return(true); } return(false); }
public static Video VideoFromAnimeEpisode(IProvider prov, List <Contract_CrossRef_AniDB_TvDBV2> cross, KeyValuePair <AnimeEpisode, Contract_AnimeEpisode> e, int userid) { Video v = (Video)e.Key.PlexContract?.Clone <Video>(); if (v?.Thumb != null) { v.Thumb = ReplaceSchemeHost(v.Thumb); } if (v != null && (v.Medias == null || v.Medias.Count == 0)) { List <VideoLocal> locals = e.Key.GetVideoLocals(); if (locals.Count > 0) { VideoLocalRepository lrepo = new VideoLocalRepository(); AnimeEpisodeRepository erepo = new AnimeEpisodeRepository(); foreach (VideoLocal n in locals) { lrepo.Save(n, false); } erepo.Save(e.Key); } v = (Video)e.Key.PlexContract?.Clone <Video>(); } if (v != null) { if (e.Value != null) { v.ViewCount = e.Value.WatchedCount.ToString(); if (e.Value.WatchedDate.HasValue) { v.LastViewedAt = e.Value.WatchedDate.Value.ToUnixTime(); } } v.ParentIndex = "1"; if (e.Key.EpisodeTypeEnum != enEpisodeType.Episode) { v.ParentIndex = null; } if (cross != null && cross.Count > 0) { Contract_CrossRef_AniDB_TvDBV2 c2 = cross.FirstOrDefault( a => a.AniDBStartEpisodeType == int.Parse(v.EpisodeType) && a.AniDBStartEpisodeNumber <= int.Parse(v.EpisodeNumber)); if (c2?.TvDBSeasonNumber > 0) { v.ParentIndex = c2.TvDBSeasonNumber.ToString(); } } AddLinksToAnimeEpisodeVideo(prov, v, userid); } return(v); }
public static int UpdateAniDBFileData(bool missingInfo, bool outOfDate, bool countOnly) { List<int> vidsToUpdate = new List<int>(); try { AniDB_FileRepository repFiles = new AniDB_FileRepository(); VideoLocalRepository repVids = new VideoLocalRepository(); if (missingInfo) { List<VideoLocal> vids = repVids.GetByAniDBResolution("0x0"); foreach (VideoLocal vid in vids) { if (!vidsToUpdate.Contains(vid.VideoLocalID)) vidsToUpdate.Add(vid.VideoLocalID); } } if (outOfDate) { List<VideoLocal> vids = repVids.GetByInternalVersion(1); foreach (VideoLocal vid in vids) { if (!vidsToUpdate.Contains(vid.VideoLocalID)) vidsToUpdate.Add(vid.VideoLocalID); } } if (!countOnly) { foreach (int id in vidsToUpdate) { CommandRequest_GetFile cmd = new CommandRequest_GetFile(id, true); cmd.Save(); } } } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); } return vidsToUpdate.Count; }
public VideoLocal_User GetVideoLocalUserRecord(int userID) { VideoLocalRepository repVids = new VideoLocalRepository(); VideoLocal vid = repVids.GetByHash(Hash); if (vid != null) { VideoLocal_User vidUser = vid.GetUserRecord(userID); if (vidUser != null) { return(vidUser); } } return(null); }
public static void CheckForAniDBFileUpdate(bool forceRefresh) { if (ServerSettings.AniDB_File_UpdateFrequency == ScheduledUpdateFrequency.Never && !forceRefresh) return; int freqHours = Utils.GetScheduledHours(ServerSettings.AniDB_File_UpdateFrequency); // check for any updated anime info every 12 hours ScheduledUpdateRepository repSched = new ScheduledUpdateRepository(); AniDB_AnimeRepository repAnime = new AniDB_AnimeRepository(); ScheduledUpdate sched = repSched.GetByUpdateType((int)ScheduledUpdateType.AniDBFileUpdates); if (sched != null) { // if we have run this in the last 12 hours and are not forcing it, then exit TimeSpan tsLastRun = DateTime.Now - sched.LastUpdate; if (tsLastRun.TotalHours < freqHours) { if (!forceRefresh) return; } } UpdateAniDBFileData(true, false, false); // files which have been hashed, but don't have an associated episode VideoLocalRepository repVidLocals = new VideoLocalRepository(); List<VideoLocal> filesWithoutEpisode = repVidLocals.GetVideosWithoutEpisode(); foreach (VideoLocal vl in filesWithoutEpisode) { CommandRequest_ProcessFile cmd = new CommandRequest_ProcessFile(vl.VideoLocalID, true); cmd.Save(); } // now check for any files which have been manually linked and are less than 30 days old if (sched == null) { sched = new ScheduledUpdate(); sched.UpdateType = (int)ScheduledUpdateType.AniDBFileUpdates; sched.UpdateDetails = ""; } sched.LastUpdate = DateTime.Now; repSched.Save(sched); }
private static void InitCache(this IDatabase db) { JMMUserRepository.InitCache(); AniDB_AnimeRepository.InitCache(); VideoInfoRepository.InitCache(); VideoLocalRepository.InitCache(); VideoLocal_UserRepository.InitCache(); List <GroupFilter> recalc = GroupFilterRepository.InitCache(); AnimeEpisodeRepository.InitCache(); AnimeEpisode_UserRepository.InitCache(); AnimeSeriesRepository.InitCache(); AnimeSeries_UserRepository.InitCache(); AnimeGroupRepository.InitCache(); AnimeGroup_UserRepository.InitCache(); GroupFilterRepository.InitCacheSecondPart(recalc); DatabaseFixes.ExecuteDatabaseFixes(); db.CleanUpMemory(); }
public override void ProcessCommand() { try { VideoLocalRepository repVids = new VideoLocalRepository(); VideoLocal vlocal = repVids.GetByID(VideoLocalID); if (vlocal == null) { return; } XMLService.Send_FileHash(vlocal); } catch (Exception ex) { logger.Error("Error processing CommandRequest_WebCacheSendFileHash: {0} - {1}", VideoLocalID, ex.ToString()); return; } }
public Media GetMediaFromUser(int userID) { Media n = null; if (Media == null) { if (File.Exists(FullServerPath)) { VideoLocalRepository repo = new VideoLocalRepository(); repo.Save(this, false); } } if (Media != null) { n = (Media)Media.DeepCopy(); if (n?.Parts != null) { foreach (Part p in n?.Parts) { string name = UrlSafe.Replace(Path.GetFileName(FilePath), " ").Replace(" ", " ").Replace(" ", " ").Trim(); name = UrlSafe2.Replace(name, string.Empty).Trim().Replace("..", ".").Replace("..", ".").Replace("__", "_").Replace("__", "_").Replace(" ", "_").Replace("_.", "."); while (name.StartsWith("_")) { name = name.Substring(1); } while (name.StartsWith(".")) { name = name.Substring(1); } p.Key = PlexAndKodi.Helper.ReplaceSchemeHost(PlexAndKodi.Helper.ConstructVideoLocalStream(userID, VideoLocalID.ToString(), name, false)); if (p.Streams != null) { foreach (Stream s in p.Streams.Where(a => a.File != null && a.StreamType == "3")) { s.Key = PlexAndKodi.Helper.ReplaceSchemeHost(PlexAndKodi.Helper.ConstructFileStream(userID, s.File, false)); } } } } } return(n); }
public static void RemoveRecordsWithoutPhysicalFiles() { VideoLocalRepository repVidLocals = new VideoLocalRepository(); CrossRef_File_EpisodeRepository repXRefs = new CrossRef_File_EpisodeRepository(); // get a full list of files List<VideoLocal> filesAll = repVidLocals.GetAll(); foreach (VideoLocal vl in filesAll) { if (!File.Exists(vl.FullServerPath)) { // delete video local record logger.Info("RemoveRecordsWithoutPhysicalFiles : {0}", vl.FullServerPath); repVidLocals.Delete(vl.VideoLocalID); CommandRequest_DeleteFileFromMyList cmdDel = new CommandRequest_DeleteFileFromMyList(vl.Hash, vl.FileSize); cmdDel.Save(); } } UpdateAllStats(); }
private System.IO.Stream InternalGetFile(int userid, string Id, HistoryInfo info) { int id; if (!int.TryParse(Id, out id)) { return(new MemoryStream()); } VideoLocalRepository repVids = new VideoLocalRepository(); PlexObject ret = new PlexObject(PlexHelper.NewMediaContainer(MediaContainerTypes.File, info, true)); VideoLocal vi = repVids.GetByID(id); if (vi == null) { return(new MemoryStream()); } List <Video> dirs = new List <Video>(); Video v2 = new Video(); PlexHelper.PopulateVideo(v2, vi, JMMType.File, userid); dirs.Add(v2, info); ret.MediaContainer.Childrens = dirs; return(ret.GetStream()); }
public static void FixHashes() { try { VideoLocalRepository repVids = new VideoLocalRepository(); foreach (VideoLocal vid in repVids.GetAll()) { bool fixedHash = false; if (vid.CRC32.Equals("00000000")) { vid.CRC32 = null; fixedHash = true; } if (vid.MD5.Equals("00000000000000000000000000000000")) { vid.MD5 = null; fixedHash = true; } if (vid.SHA1.Equals("0000000000000000000000000000000000000000")) { vid.SHA1 = null; fixedHash = true; } if (fixedHash) { repVids.Save(vid); logger.Info("Fixed hashes on file: {0}", vid.FullServerPath); } } } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); } }
public override void ProcessCommand() { logger.Info("Get AniDB file info: {0}", VideoLocalID); try { AniDB_FileRepository repAniFile = new AniDB_FileRepository(); VideoLocalRepository repVids = new VideoLocalRepository(); vlocal = repVids.GetByID(VideoLocalID); if (vlocal == null) { return; } AniDB_File aniFile = repAniFile.GetByHashAndFileSize(vlocal.Hash, vlocal.FileSize); /*// get anidb file info from web cache * if (aniFile == null && ServerSettings.WebCache_AniDB_File_Get) * { * AniDB_FileRequest fr = XMLService.Get_AniDB_File(vlocal.Hash, vlocal.FileSize); * if (fr != null) * { * aniFile = new AniDB_File(); * aniFile.Populate(fr); * * //overwrite with local file name * string localFileName = Path.GetFileName(vlocal.FilePath); * aniFile.FileName = localFileName; * * repAniFile.Save(aniFile, false); * aniFile.CreateLanguages(); * aniFile.CreateCrossEpisodes(localFileName); * * StatsCache.Instance.UpdateUsingAniDBFile(vlocal.Hash); * } * }*/ Raw_AniDB_File fileInfo = null; if (aniFile == null || ForceAniDB) { fileInfo = JMMService.AnidbProcessor.GetFileInfo(vlocal); } if (fileInfo != null) { // save to the database if (aniFile == null) { aniFile = new AniDB_File(); } aniFile.Populate(fileInfo); //overwrite with local file name string localFileName = Path.GetFileName(vlocal.FilePath); aniFile.FileName = localFileName; repAniFile.Save(aniFile, false); aniFile.CreateLanguages(); aniFile.CreateCrossEpisodes(localFileName); if (!string.IsNullOrEmpty(fileInfo.OtherEpisodesRAW)) { string[] epIDs = fileInfo.OtherEpisodesRAW.Split(','); foreach (string epid in epIDs) { int id = 0; if (int.TryParse(epid, out id)) { CommandRequest_GetEpisode cmdEp = new CommandRequest_GetEpisode(id); cmdEp.Save(); } } } StatsCache.Instance.UpdateUsingAniDBFile(vlocal.Hash); } } catch (Exception ex) { logger.Error("Error processing CommandRequest_GetFile: {0} - {1}", VideoLocalID, ex.ToString()); return; } }
public static Video GenerateVideoFromAnimeEpisode(AnimeEpisode ep) { Video l = new Video(); List <VideoLocal> vids = ep.GetVideoLocals(); l.Type = "episode"; l.Summary = "Episode Overview Not Available"; //TODO Intenationalization l.Id = ep.AnimeEpisodeID.ToString(); l.AnimeType = JMMContracts.PlexAndKodi.AnimeTypes.AnimeEpisode.ToString(); VideoLocalRepository repo = new VideoLocalRepository(); if (vids.Count > 0) { l.Title = Path.GetFileNameWithoutExtension(vids[0].FilePath); l.AddedAt = vids[0].DateTimeCreated.ToUnixTime(); l.UpdatedAt = vids[0].DateTimeUpdated.ToUnixTime(); l.OriginallyAvailableAt = vids[0].DateTimeCreated.ToPlexDate(); l.Year = vids[0].DateTimeCreated.Year.ToString(); l.Medias = new List <Media>(); foreach (VideoLocal v in vids) { Media m = v.Media; if (m == null) { if (File.Exists(v.FullServerPath)) { repo.Save(v, false); } } if (m != null) { l.Medias.Add(m); l.Duration = m.Duration; } } } AniDB_Episode aep = ep?.AniDB_Episode; if (aep != null) { l.EpisodeNumber = aep.EpisodeNumber.ToString(); l.Index = aep.EpisodeNumber.ToString(); l.Title = aep.EnglishName; l.OriginalTitle = aep.RomajiName; l.EpisodeType = aep.EpisodeType.ToString(); l.Rating = float.Parse(aep.Rating, CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture); if (aep.AirDateAsDate.HasValue) { l.Year = aep.AirDateAsDate.Value.Year.ToString(); l.OriginallyAvailableAt = aep.AirDateAsDate.Value.ToPlexDate(); } //FIX THIS MetroContract_Anime_Episode contract = new MetroContract_Anime_Episode(); JMMServiceImplementationMetro.SetTvDBInfo(aep.AnimeID, aep, ref contract); l.Thumb = contract.GenPoster(); l.Summary = contract.EpisodeOverview; } l.Id = ep.AnimeEpisodeID.ToString(); return(l); }
public void ToggleWatchedStatus(bool watched, bool updateOnline, DateTime?watchedDate, bool updateStats, bool updateStatsCache, int userID, bool scrobbleTrakt, bool updateWatchedDate) { VideoLocalRepository repVids = new VideoLocalRepository(); AnimeEpisodeRepository repEpisodes = new AnimeEpisodeRepository(); AniDB_FileRepository repAniFile = new AniDB_FileRepository(); CrossRef_File_EpisodeRepository repCross = new CrossRef_File_EpisodeRepository(); VideoLocal_UserRepository repVidUsers = new VideoLocal_UserRepository(); JMMUserRepository repUsers = new JMMUserRepository(); AnimeEpisode_UserRepository repEpisodeUsers = new AnimeEpisode_UserRepository(); JMMUser user = repUsers.GetByID(userID); if (user == null) { return; } List <JMMUser> aniDBUsers = repUsers.GetAniDBUsers(); // update the video file to watched int mywatched = watched ? 1 : 0; if (user.IsAniDBUser == 0) { SaveWatchedStatus(watched, userID, watchedDate, updateWatchedDate); } else { // if the user is AniDB user we also want to update any other AniDB // users to keep them in sync foreach (JMMUser juser in aniDBUsers) { if (juser.IsAniDBUser == 1) { SaveWatchedStatus(watched, juser.JMMUserID, watchedDate, updateWatchedDate); } } } // now lets find all the associated AniDB_File record if there is one if (user.IsAniDBUser == 1) { AniDB_File aniFile = repAniFile.GetByHash(this.Hash); if (aniFile != null) { aniFile.IsWatched = mywatched; if (watched) { if (watchedDate.HasValue) { aniFile.WatchedDate = watchedDate; } else { aniFile.WatchedDate = DateTime.Now; } } else { aniFile.WatchedDate = null; } repAniFile.Save(aniFile, false); } if (updateOnline) { if ((watched && ServerSettings.AniDB_MyList_SetWatched) || (!watched && ServerSettings.AniDB_MyList_SetUnwatched)) { CommandRequest_UpdateMyListFileStatus cmd = new CommandRequest_UpdateMyListFileStatus(this.Hash, watched, false, watchedDate.HasValue ? Utils.GetAniDBDateAsSeconds(watchedDate) : 0); cmd.Save(); } } } // now find all the episode records associated with this video file // but we also need to check if theer are any other files attached to this episode with a watched // status, AnimeSeries ser = null; // get all files associated with this episode List <CrossRef_File_Episode> xrefs = repCross.GetByHash(this.Hash); if (watched) { // find the total watched percentage // eg one file can have a % = 100 // or if 2 files make up one episodes they will each have a % = 50 foreach (CrossRef_File_Episode xref in xrefs) { // get the episode for this file AnimeEpisode ep = repEpisodes.GetByAniDBEpisodeID(xref.EpisodeID); if (ep == null) { continue; } // get all the files for this episode int epPercentWatched = 0; foreach (CrossRef_File_Episode filexref in ep.FileCrossRefs) { VideoLocal_User vidUser = filexref.GetVideoLocalUserRecord(userID); if (vidUser != null) { // if not null means it is watched epPercentWatched += filexref.Percentage; } if (epPercentWatched > 95) { break; } } if (epPercentWatched > 95) { ser = ep.GetAnimeSeries(); if (user.IsAniDBUser == 0) { ep.SaveWatchedStatus(true, userID, watchedDate, updateWatchedDate); } else { // if the user is AniDB user we also want to update any other AniDB // users to keep them in sync foreach (JMMUser juser in aniDBUsers) { if (juser.IsAniDBUser == 1) { ep.SaveWatchedStatus(true, juser.JMMUserID, watchedDate, updateWatchedDate); } } } if (scrobbleTrakt && !string.IsNullOrEmpty(ServerSettings.Trakt_Username) && !string.IsNullOrEmpty(ServerSettings.Trakt_Password)) { CommandRequest_TraktShowScrobble cmdScrobble = new CommandRequest_TraktShowScrobble(ep.AnimeEpisodeID); cmdScrobble.Save(); } if (!string.IsNullOrEmpty(ServerSettings.MAL_Username) && !string.IsNullOrEmpty(ServerSettings.MAL_Password)) { CommandRequest_MALUpdatedWatchedStatus cmdMAL = new CommandRequest_MALUpdatedWatchedStatus(ser.AniDB_ID); cmdMAL.Save(); } } } } else { // if setting a file to unwatched only set the episode unwatched, if ALL the files are unwatched foreach (CrossRef_File_Episode xrefEp in xrefs) { AnimeEpisode ep = repEpisodes.GetByAniDBEpisodeID(xrefEp.EpisodeID); if (ep == null) { continue; } ser = ep.GetAnimeSeries(); // get all the files for this episode int epPercentWatched = 0; foreach (CrossRef_File_Episode filexref in ep.FileCrossRefs) { VideoLocal_User vidUser = filexref.GetVideoLocalUserRecord(userID); if (vidUser != null) { epPercentWatched += filexref.Percentage; } if (epPercentWatched > 95) { break; } } if (epPercentWatched < 95) { if (user.IsAniDBUser == 0) { ep.SaveWatchedStatus(false, userID, watchedDate, true); } else { // if the user is AniDB user we also want to update any other AniDB // users to keep them in sync foreach (JMMUser juser in aniDBUsers) { if (juser.IsAniDBUser == 1) { ep.SaveWatchedStatus(false, juser.JMMUserID, watchedDate, true); } } } CommandRequest_TraktShowEpisodeUnseen cmdUnseen = new CommandRequest_TraktShowEpisodeUnseen(ep.AnimeEpisodeID); cmdUnseen.Save(); } } if (!string.IsNullOrEmpty(ServerSettings.MAL_Username) && !string.IsNullOrEmpty(ServerSettings.MAL_Password)) { CommandRequest_MALUpdatedWatchedStatus cmdMAL = new CommandRequest_MALUpdatedWatchedStatus(ser.AniDB_ID); cmdMAL.Save(); } } // update stats for groups and series if (ser != null && updateStats) { // update all the groups above this series in the heirarchy ser.UpdateStats(true, true, true); //ser.TopLevelAnimeGroup.UpdateStatsFromTopLevel(true, true, true); } if (ser != null && updateStatsCache) { StatsCache.Instance.UpdateUsingSeries(ser.AnimeSeriesID); } }
public override void ProcessCommand() { logger.Info("Reading Media Info for File: {0}", VideoLocalID); try { VideoLocalRepository repVids = new VideoLocalRepository(); VideoLocal vlocal = repVids.GetByID(VideoLocalID); if (vlocal == null) { logger.Error("Cound not find Video: {0}", VideoLocalID); return; } if (!File.Exists(vlocal.FullServerPath)) { logger.Error("Cound not find physical file: {0}", vlocal.FullServerPath); return; } int nshareID = -1; VideoInfoRepository repVidInfo = new VideoInfoRepository(); VideoInfo vinfo = repVidInfo.GetByHash(vlocal.Hash); ImportFolderRepository repNS = new ImportFolderRepository(); List <ImportFolder> shares = repNS.GetAll(); string fileName = vlocal.FullServerPath; string filePath = ""; DataAccessHelper.GetShareAndPath(fileName, shares, ref nshareID, ref filePath); FileInfo fi = new FileInfo(fileName); if (vinfo == null) { vinfo = new VideoInfo(); vinfo.Hash = vlocal.Hash; vinfo.Duration = 0; vinfo.FileSize = fi.Length; vinfo.DateTimeUpdated = DateTime.Now; vinfo.FileName = filePath; vinfo.AudioBitrate = ""; vinfo.AudioCodec = ""; vinfo.VideoBitrate = ""; vinfo.VideoBitDepth = ""; vinfo.VideoCodec = ""; vinfo.VideoFrameRate = ""; vinfo.VideoResolution = ""; } logger.Trace("Getting media info for: {0}", fileName); MediaInfoResult mInfo = FileHashHelper.GetMediaInfo(fileName, true); vinfo.AudioBitrate = string.IsNullOrEmpty(mInfo.AudioBitrate) ? "" : mInfo.AudioBitrate; vinfo.AudioCodec = string.IsNullOrEmpty(mInfo.AudioCodec) ? "" : mInfo.AudioCodec; vinfo.DateTimeUpdated = vlocal.DateTimeUpdated; vinfo.Duration = mInfo.Duration; vinfo.FileName = filePath; vinfo.FileSize = fi.Length; vinfo.VideoBitrate = string.IsNullOrEmpty(mInfo.VideoBitrate) ? "" : mInfo.VideoBitrate; vinfo.VideoBitDepth = string.IsNullOrEmpty(mInfo.VideoBitDepth) ? "" : mInfo.VideoBitDepth; vinfo.VideoCodec = string.IsNullOrEmpty(mInfo.VideoCodec) ? "" : mInfo.VideoCodec; vinfo.VideoFrameRate = string.IsNullOrEmpty(mInfo.VideoFrameRate) ? "" : mInfo.VideoFrameRate; vinfo.VideoResolution = string.IsNullOrEmpty(mInfo.VideoResolution) ? "" : mInfo.VideoResolution; vinfo.FullInfo = string.IsNullOrEmpty(mInfo.FullInfo) ? "" : mInfo.FullInfo; repVidInfo.Save(vinfo); } catch (Exception ex) { logger.Error("Error processing CommandRequest_ReadMediaInfo: {0} - {1}", VideoLocalID, ex.ToString()); return; } }
public void MoveFileIfRequired() { // check if this file is in the drop folder // otherwise we don't need to move it if (this.ImportFolder.IsDropSource == 0) { return; } if (!File.Exists(this.FullServerPath)) { return; } // find the default destination ImportFolder destFolder = null; ImportFolderRepository repFolders = new ImportFolderRepository(); foreach (ImportFolder fldr in repFolders.GetAll()) { if (fldr.IsDropDestination == 1) { destFolder = fldr; break; } } if (destFolder == null) { return; } if (!Directory.Exists(destFolder.ImportFolderLocation)) { return; } // we can only move the file if it has an anime associated with it List <CrossRef_File_Episode> xrefs = this.EpisodeCrossRefs; if (xrefs.Count == 0) { return; } CrossRef_File_Episode xref = xrefs[0]; // find the series associated with this episode AnimeSeriesRepository repSeries = new AnimeSeriesRepository(); AnimeSeries series = repSeries.GetByAnimeID(xref.AnimeID); if (series == null) { return; } // find where the other files are stored for this series // if there are no other files except for this one, it means we need to create a new location bool foundLocation = false; string newFullPath = ""; // sort the episodes by air date, so that we will move the file to the location of the latest episode List <AnimeEpisode> allEps = series.GetAnimeEpisodes(); List <SortPropOrFieldAndDirection> sortCriteria = new List <SortPropOrFieldAndDirection>(); sortCriteria.Add(new SortPropOrFieldAndDirection("AniDB_EpisodeID", true, SortType.eInteger)); allEps = Sorting.MultiSort <AnimeEpisode>(allEps, sortCriteria); foreach (AnimeEpisode ep in allEps) { foreach (VideoLocal vid in ep.GetVideoLocals()) { if (vid.VideoLocalID != this.VideoLocalID) { // make sure this folder is not the drop source if (vid.ImportFolder.IsDropSource == 1) { continue; } string thisFileName = vid.FullServerPath; string folderName = Path.GetDirectoryName(thisFileName); if (Directory.Exists(folderName)) { newFullPath = folderName; foundLocation = true; break; } } } if (foundLocation) { break; } } if (!foundLocation) { // we need to create a new folder string newFolderName = Utils.RemoveInvalidFolderNameCharacters(series.GetAnime().MainTitle); newFullPath = Path.Combine(destFolder.ImportFolderLocation, newFolderName); if (!Directory.Exists(newFullPath)) { Directory.CreateDirectory(newFullPath); } } int newFolderID = 0; string newPartialPath = ""; string newFullServerPath = Path.Combine(newFullPath, Path.GetFileName(this.FullServerPath)); DataAccessHelper.GetShareAndPath(newFullServerPath, repFolders.GetAll(), ref newFolderID, ref newPartialPath); logger.Info("Moving file from {0} to {1}", this.FullServerPath, newFullServerPath); if (File.Exists(newFullServerPath)) { // if the file already exists, we can just delete the source file instead // this is safer than deleting and moving File.Delete(this.FullServerPath); this.ImportFolderID = newFolderID; this.FilePath = newPartialPath; VideoLocalRepository repVids = new VideoLocalRepository(); repVids.Save(this); } else { string originalFileName = this.FullServerPath; FileInfo fi = new FileInfo(originalFileName); // now move the file File.Move(this.FullServerPath, newFullServerPath); this.ImportFolderID = newFolderID; this.FilePath = newPartialPath; VideoLocalRepository repVids = new VideoLocalRepository(); repVids.Save(this); try { // move any subtitle files foreach (string subtitleFile in Utils.GetPossibleSubtitleFiles(originalFileName)) { if (File.Exists(subtitleFile)) { FileInfo fiSub = new FileInfo(subtitleFile); string newSubPath = Path.Combine(Path.GetDirectoryName(newFullServerPath), fiSub.Name); if (File.Exists(newSubPath)) { // if the file already exists, we can just delete the source file instead // this is safer than deleting and moving File.Delete(newSubPath); } else { File.Move(subtitleFile, newSubPath); } } } } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); } // check for any empty folders in drop folder // only for the drop folder if (this.ImportFolder.IsDropSource == 1) { foreach (string folderName in Directory.GetDirectories(this.ImportFolder.ImportFolderLocation, "*", SearchOption.AllDirectories)) { if (Directory.Exists(folderName)) { if (Directory.GetFiles(folderName, "*", SearchOption.AllDirectories).Length == 0) { try { Directory.Delete(folderName, true); } /*catch (IOException) * { * Thread.Sleep(0); * Directory.Delete(folderName, false); * }*/ catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); } } } } } } }
private void ProcessFile_AniDB(VideoLocal vidLocal) { logger.Trace("Checking for AniDB_File record for: {0} --- {1}", vidLocal.Hash, vidLocal.FilePath); // check if we already have this AniDB_File info in the database AniDB_FileRepository repAniFile = new AniDB_FileRepository(); AniDB_EpisodeRepository repAniEps = new AniDB_EpisodeRepository(); AniDB_AnimeRepository repAniAnime = new AniDB_AnimeRepository(); AnimeSeriesRepository repSeries = new AnimeSeriesRepository(); VideoLocalRepository repVidLocals = new VideoLocalRepository(); AnimeEpisodeRepository repEps = new AnimeEpisodeRepository(); CrossRef_File_EpisodeRepository repXrefFE = new CrossRef_File_EpisodeRepository(); AniDB_File aniFile = null; if (!ForceAniDB) { aniFile = repAniFile.GetByHashAndFileSize(vidLocal.Hash, vlocal.FileSize); if (aniFile == null) { logger.Trace("AniDB_File record not found"); } } int animeID = 0; if (aniFile == null) { // get info from AniDB logger.Debug("Getting AniDB_File record from AniDB...."); Raw_AniDB_File fileInfo = JMMService.AnidbProcessor.GetFileInfo(vidLocal); if (fileInfo != null) { // check if we already have a record aniFile = repAniFile.GetByHashAndFileSize(vidLocal.Hash, vlocal.FileSize); if (aniFile == null) { aniFile = new AniDB_File(); } aniFile.Populate(fileInfo); //overwrite with local file name string localFileName = Path.GetFileName(vidLocal.FilePath); aniFile.FileName = localFileName; repAniFile.Save(aniFile, false); aniFile.CreateLanguages(); aniFile.CreateCrossEpisodes(localFileName); if (!string.IsNullOrEmpty(fileInfo.OtherEpisodesRAW)) { string[] epIDs = fileInfo.OtherEpisodesRAW.Split(','); foreach (string epid in epIDs) { int id = 0; if (int.TryParse(epid, out id)) { CommandRequest_GetEpisode cmdEp = new CommandRequest_GetEpisode(id); cmdEp.Save(); } } } animeID = aniFile.AnimeID; } } bool missingEpisodes = false; // if we still haven't got the AniDB_File Info we try the web cache or local records if (aniFile == null) { // check if we have any records from previous imports List <CrossRef_File_Episode> crossRefs = repXrefFE.GetByHash(vidLocal.Hash); if (crossRefs == null || crossRefs.Count == 0) { // lets see if we can find the episode/anime info from the web cache if (ServerSettings.WebCache_XRefFileEpisode_Get) { List <JMMServer.Providers.Azure.CrossRef_File_Episode> xrefs = JMMServer.Providers.Azure.AzureWebAPI.Get_CrossRefFileEpisode(vidLocal); crossRefs = new List <CrossRef_File_Episode>(); if (xrefs == null || xrefs.Count == 0) { logger.Debug("Cannot find AniDB_File record or get cross ref from web cache record so exiting: {0}", vidLocal.ED2KHash); return; } else { foreach (JMMServer.Providers.Azure.CrossRef_File_Episode xref in xrefs) { CrossRef_File_Episode xrefEnt = new CrossRef_File_Episode(); xrefEnt.Hash = vidLocal.ED2KHash; xrefEnt.FileName = Path.GetFileName(vidLocal.FullServerPath); xrefEnt.FileSize = vidLocal.FileSize; xrefEnt.CrossRefSource = (int)JMMServer.CrossRefSource.WebCache; xrefEnt.AnimeID = animeID; xrefEnt.EpisodeID = xref.EpisodeID; xrefEnt.Percentage = xref.Percentage; xrefEnt.EpisodeOrder = xref.EpisodeOrder; crossRefs.Add(xrefEnt); // in this case we need to save the cross refs manually as AniDB did not provide them repXrefFE.Save(xrefEnt); } } } else { logger.Debug("Cannot get AniDB_File record so exiting: {0}", vidLocal.ED2KHash); return; } } // we assume that all episodes belong to the same anime foreach (CrossRef_File_Episode xref in crossRefs) { animeID = xref.AnimeID; AniDB_Episode ep = repAniEps.GetByEpisodeID(xref.EpisodeID); if (ep == null) { missingEpisodes = true; } } } else { // check if we have the episode info // if we don't, we will need to re-download the anime info (which also has episode info) if (aniFile.EpisodeCrossRefs.Count == 0) { animeID = aniFile.AnimeID; // if we have the anidb file, but no cross refs it means something has been broken logger.Debug("Could not find any cross ref records for: {0}", vidLocal.ED2KHash); missingEpisodes = true; } else { foreach (CrossRef_File_Episode xref in aniFile.EpisodeCrossRefs) { AniDB_Episode ep = repAniEps.GetByEpisodeID(xref.EpisodeID); if (ep == null) { missingEpisodes = true; } animeID = xref.AnimeID; } } } // get from DB AniDB_Anime anime = repAniAnime.GetByAnimeID(animeID); bool animeRecentlyUpdated = false; if (anime != null) { TimeSpan ts = DateTime.Now - anime.DateTimeUpdated; if (ts.TotalHours < 4) { animeRecentlyUpdated = true; } } // even if we are missing episode info, don't get data more than once every 4 hours // this is to prevent banning if (missingEpisodes && !animeRecentlyUpdated) { logger.Debug("Getting Anime record from AniDB...."); anime = JMMService.AnidbProcessor.GetAnimeInfoHTTP(animeID, true, ServerSettings.AutoGroupSeries); } // create the group/series/episode records if needed AnimeSeries ser = null; if (anime != null) { logger.Debug("Creating groups, series and episodes...."); // check if there is an AnimeSeries Record associated with this AnimeID ser = repSeries.GetByAnimeID(animeID); if (ser == null) { // create a new AnimeSeries record ser = anime.CreateAnimeSeriesAndGroup(); } ser.CreateAnimeEpisodes(); // check if we have any group status data for this associated anime // if not we will download it now AniDB_GroupStatusRepository repStatus = new AniDB_GroupStatusRepository(); if (repStatus.GetByAnimeID(anime.AnimeID).Count == 0) { CommandRequest_GetReleaseGroupStatus cmdStatus = new CommandRequest_GetReleaseGroupStatus(anime.AnimeID, false); cmdStatus.Save(); } // update stats ser.EpisodeAddedDate = DateTime.Now; repSeries.Save(ser); AnimeGroupRepository repGroups = new AnimeGroupRepository(); foreach (AnimeGroup grp in ser.AllGroupsAbove) { grp.EpisodeAddedDate = DateTime.Now; repGroups.Save(grp); } } vidLocal.RenameIfRequired(); vidLocal.MoveFileIfRequired(); // update stats for groups and series if (ser != null) { // update all the groups above this series in the heirarchy ser.UpdateStats(true, true, true); StatsCache.Instance.UpdateUsingSeries(ser.AnimeSeriesID); } // Add this file to the users list if (ServerSettings.AniDB_MyList_AddFiles) { CommandRequest_AddFileToMyList cmd = new CommandRequest_AddFileToMyList(vidLocal.ED2KHash); cmd.Save(); } // lets also try adding to the users trakt collecion by sync'ing the series if (ser != null) { if (ServerSettings.WebCache_Trakt_Send && !string.IsNullOrEmpty(ServerSettings.Trakt_Username)) { CommandRequest_TraktSyncCollectionSeries cmdTrakt = new CommandRequest_TraktSyncCollectionSeries(ser.AnimeSeriesID, ser.GetAnime().MainTitle); cmdTrakt.Save(); } } // sync the series on MAL if (ser != null) { CommandRequest_MALUpdatedWatchedStatus cmdMAL = new CommandRequest_MALUpdatedWatchedStatus(ser.AniDB_ID); cmdMAL.Save(); } }
private void Process(System.Net.HttpListenerContext obj) { Stream org = null; try { bool fname = false; string[] dta = obj.Request.RawUrl.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); if (dta.Length < 4) { return; } string cmd = dta[0].ToLower(); string user = dta[1]; string aw = dta[2]; string arg = dta[3]; string fullname; int userid = 0; int autowatch = 0; int.TryParse(user, out userid); int.TryParse(aw, out autowatch); VideoLocal loc = null; if (cmd == "videolocal") { int sid = 0; int.TryParse(arg, out sid); if (sid == 0) { obj.Response.StatusCode = (int)HttpStatusCode.BadRequest; obj.Response.StatusDescription = "Stream Id missing."; return; } VideoLocalRepository rep = new VideoLocalRepository(); loc = rep.GetByID(sid); if (loc == null) { obj.Response.StatusCode = (int)HttpStatusCode.NotFound; obj.Response.StatusDescription = "Stream Id not found."; return; } fullname = loc.FullServerPath; } else if (cmd == "file") { fullname = Base64DecodeUrl(arg); } else { obj.Response.StatusCode = (int)HttpStatusCode.BadRequest; obj.Response.StatusDescription = "Not know command"; return; } bool range = false; try { if (!File.Exists(fullname)) { obj.Response.StatusCode = (int)HttpStatusCode.NotFound; obj.Response.StatusDescription = "File '" + fullname + "' not found."; return; } } catch (Exception) { obj.Response.StatusCode = (int)HttpStatusCode.InternalServerError; obj.Response.StatusDescription = "Unable to access File '" + fullname + "'."; return; } obj.Response.ContentType = GetMime(fullname); obj.Response.AddHeader("Accept-Ranges", "bytes"); obj.Response.AddHeader("X-Plex-Protocol", "1.0"); if (obj.Request.HttpMethod == "OPTIONS") { obj.Response.AddHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, HEAD"); obj.Response.AddHeader("Access-Control-Max-Age", "1209600"); obj.Response.AddHeader("Access-Control-Allow-Headers", "accept, x-plex-token, x-plex-client-identifier, x-plex-username, x-plex-product, x-plex-device, x-plex-platform, x-plex-platform-version, x-plex-version, x-plex-device-name"); obj.Response.AddHeader("Cache-Control", "no-cache"); obj.Response.ContentType = "text/plain"; return; } string rangevalue = null; if (obj.Request.Headers.AllKeys.Contains("Range")) { rangevalue = obj.Request.Headers["Range"].Replace("bytes=", string.Empty).Trim(); } if (obj.Request.Headers.AllKeys.Contains("range")) { rangevalue = obj.Request.Headers["range"].Replace("bytes=", string.Empty).Trim(); } if (obj.Request.HttpMethod != "HEAD") { org = new FileStream(fullname, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); long totalsize = org.Length; long start = 0; long end = 0; if (!string.IsNullOrEmpty(rangevalue)) { range = true; string[] split = rangevalue.Split('-'); if (split.Length == 2) { if (string.IsNullOrEmpty(split[0]) && !string.IsNullOrEmpty(split[1])) { long e = long.Parse(split[1]); start = totalsize - e; end = totalsize - 1; } else if (!string.IsNullOrEmpty(split[0]) && string.IsNullOrEmpty(split[1])) { start = long.Parse(split[0]); end = totalsize - 1; } else if (!string.IsNullOrEmpty(split[0]) && !string.IsNullOrEmpty(split[1])) { start = long.Parse(split[0]); end = long.Parse(split[1]); if (start > totalsize - 1) { start = totalsize - 1; } if (end > totalsize - 1) { end = totalsize - 1; } } else { start = 0; end = totalsize - 1; } } } SubStream outstream; if (range) { obj.Response.StatusCode = (int)HttpStatusCode.PartialContent; obj.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + totalsize); outstream = new SubStream(org, start, end - start + 1); obj.Response.ContentLength64 = end - start + 1; } else { outstream = new SubStream(org, 0, totalsize); obj.Response.ContentLength64 = totalsize; obj.Response.StatusCode = (int)HttpStatusCode.OK; } if ((userid != 0) && (loc != null) && autowatch == 1) { outstream.CrossPosition = (long)((double)totalsize * WatchedThreshold); outstream.CrossPositionCrossed += (a) => { Task.Factory.StartNew(() => { loc.ToggleWatchedStatus(true, userid); }, new CancellationToken(), TaskCreationOptions.LongRunning, TaskScheduler.Default); }; } obj.Response.SendChunked = false; outstream.CopyTo(obj.Response.OutputStream); obj.Response.OutputStream.Close(); outstream.Close(); } else { obj.Response.SendChunked = false; obj.Response.StatusCode = (int)HttpStatusCode.OK; obj.Response.ContentLength64 = new FileInfo(fullname).Length; obj.Response.KeepAlive = false; obj.Response.OutputStream.Close(); } } catch (HttpListenerException e) { } catch (Exception e) { logger.Error(e.ToString); } finally { if (org != null) { org.Close(); } if ((obj != null) && (obj.Response != null) && (obj.Response.OutputStream != null)) { obj.Response.OutputStream.Close(); } } }
public override void ProcessCommand() { logger.Info("Processing CommandRequest_SyncMyList"); try { // we will always assume that an anime was downloaded via http first ScheduledUpdateRepository repSched = new ScheduledUpdateRepository(); AniDB_FileRepository repAniFile = new AniDB_FileRepository(); VideoLocalRepository repVidLocals = new VideoLocalRepository(); ScheduledUpdate sched = repSched.GetByUpdateType((int)ScheduledUpdateType.AniDBMyListSync); if (sched == null) { sched = new ScheduledUpdate(); sched.UpdateType = (int)ScheduledUpdateType.AniDBMyListSync; sched.UpdateDetails = ""; } else { int freqHours = Utils.GetScheduledHours(ServerSettings.AniDB_MyList_UpdateFrequency); // if we have run this in the last 24 hours and are not forcing it, then exit TimeSpan tsLastRun = DateTime.Now - sched.LastUpdate; if (tsLastRun.TotalHours < freqHours) { if (!ForceRefresh) { return; } } } AniDBHTTPCommand_GetMyList cmd = new AniDBHTTPCommand_GetMyList(); cmd.Init(ServerSettings.AniDB_Username, ServerSettings.AniDB_Password); enHelperActivityType ev = cmd.Process(); if (ev == enHelperActivityType.GotMyListHTTP && cmd.MyListItems.Count > 1) { int totalItems = 0; int watchedItems = 0; int modifiedItems = 0; double pct = 0; // 2. find files locally for the user, which are not recorded on anidb // and then add them to anidb Dictionary <int, Raw_AniDB_MyListFile> onlineFiles = new Dictionary <int, Raw_AniDB_MyListFile>(); foreach (Raw_AniDB_MyListFile myitem in cmd.MyListItems) { onlineFiles[myitem.FileID] = myitem; } Dictionary <string, AniDB_File> dictAniFiles = new Dictionary <string, AniDB_File>(); List <AniDB_File> allAniFiles = repAniFile.GetAll(); foreach (AniDB_File anifile in allAniFiles) { dictAniFiles[anifile.Hash] = anifile; } int missingFiles = 0; foreach (VideoLocal vid in repVidLocals.GetAll()) { if (!dictAniFiles.ContainsKey(vid.Hash)) { continue; } int fileID = dictAniFiles[vid.Hash].FileID; if (!onlineFiles.ContainsKey(fileID)) { // means we have found a file in our local collection, which is not recorded online CommandRequest_AddFileToMyList cmdAddFile = new CommandRequest_AddFileToMyList(vid.Hash); cmdAddFile.Save(); missingFiles++; } } logger.Info(string.Format("MYLIST Missing Files: {0} Added to queue for inclusion", missingFiles)); JMMUserRepository repUsers = new JMMUserRepository(); List <JMMUser> aniDBUsers = repUsers.GetAniDBUsers(); VideoLocal_UserRepository repVidUsers = new VideoLocal_UserRepository(); CrossRef_File_EpisodeRepository repFileEp = new CrossRef_File_EpisodeRepository(); // 1 . sync mylist items foreach (Raw_AniDB_MyListFile myitem in cmd.MyListItems) { // ignore files mark as deleted by the user if (myitem.State == (int)AniDBFileStatus.Deleted) { continue; } totalItems++; if (myitem.IsWatched) { watchedItems++; } //calculate percentage pct = (double)totalItems / (double)cmd.MyListItems.Count * (double)100; string spct = pct.ToString("#0.0"); string hash = string.Empty; AniDB_File anifile = repAniFile.GetByFileID(myitem.FileID); if (anifile != null) { hash = anifile.Hash; } else { // look for manually linked files List <CrossRef_File_Episode> xrefs = repFileEp.GetByEpisodeID(myitem.EpisodeID); foreach (CrossRef_File_Episode xref in xrefs) { if (xref.CrossRefSource != (int)CrossRefSource.AniDB) { hash = xref.Hash; break; } } } if (!string.IsNullOrEmpty(hash)) { // find the video associated with this record VideoLocal vl = repVidLocals.GetByHash(hash); if (vl == null) { continue; } foreach (JMMUser juser in aniDBUsers) { bool localStatus = false; int? jmmUserID = null; // doesn't matter which anidb user we use jmmUserID = juser.JMMUserID; VideoLocal_User userRecord = vl.GetUserRecord(juser.JMMUserID); if (userRecord != null) { localStatus = true; } string action = ""; if (localStatus != myitem.IsWatched) { if (localStatus == true) { // local = watched, anidb = unwatched if (ServerSettings.AniDB_MyList_ReadUnwatched) { modifiedItems++; if (jmmUserID.HasValue) { vl.ToggleWatchedStatus(myitem.IsWatched, false, myitem.WatchedDate, false, false, jmmUserID.Value, false, true); } action = "Used AniDB Status"; } } else { // means local is un-watched, and anidb is watched if (ServerSettings.AniDB_MyList_ReadWatched) { modifiedItems++; if (jmmUserID.HasValue) { vl.ToggleWatchedStatus(true, false, myitem.WatchedDate, false, false, jmmUserID.Value, false, true); } action = "Updated Local record to Watched"; } } string msg = string.Format( "MYLISTDIFF:: File {0} - Local Status = {1}, AniDB Status = {2} --- {3}", vl.FullServerPath, localStatus, myitem.IsWatched, action); logger.Info(msg); } } //string msg = string.Format("MYLIST:: File {0} - Local Status = {1}, AniDB Status = {2} --- {3}", // vl.FullServerPath, localStatus, myitem.IsWatched, action); //logger.Info(msg); } } // now update all stats Importer.UpdateAllStats(); logger.Info("Process MyList: {0} Items, {1} Watched, {2} Modified", totalItems, watchedItems, modifiedItems); sched.LastUpdate = DateTime.Now; repSched.Save(sched); } } catch (Exception ex) { logger.Error("Error processing CommandRequest_SyncMyList: {0} ", ex.ToString()); return; } }
public void UpdateStats(bool watchedStats, bool missingEpsStats, bool updateAllGroupsAbove) { DateTime start = DateTime.Now; DateTime startOverall = DateTime.Now; logger.Info("Starting Updating STATS for SERIES {0} ({1} - {2} - {3})", this.ToString(), watchedStats, missingEpsStats, updateAllGroupsAbove); AnimeSeries_UserRepository repSeriesUser = new AnimeSeries_UserRepository(); AnimeEpisode_UserRepository repEpisodeUser = new AnimeEpisode_UserRepository(); VideoLocalRepository repVids = new VideoLocalRepository(); CrossRef_File_EpisodeRepository repXrefs = new CrossRef_File_EpisodeRepository(); JMMUserRepository repUsers = new JMMUserRepository(); List <JMMUser> allUsers = repUsers.GetAll(); DateTime startEps = DateTime.Now; List <AnimeEpisode> eps = GetAnimeEpisodes(); TimeSpan tsEps = DateTime.Now - startEps; logger.Trace("Got episodes for SERIES {0} in {1}ms", this.ToString(), tsEps.TotalMilliseconds); DateTime startVids = DateTime.Now; List <VideoLocal> vidsTemp = repVids.GetByAniDBAnimeID(this.AniDB_ID); List <CrossRef_File_Episode> crossRefs = repXrefs.GetByAnimeID(this.AniDB_ID); Dictionary <int, List <CrossRef_File_Episode> > dictCrossRefs = new Dictionary <int, List <CrossRef_File_Episode> >(); foreach (CrossRef_File_Episode xref in crossRefs) { if (!dictCrossRefs.ContainsKey(xref.EpisodeID)) { dictCrossRefs[xref.EpisodeID] = new List <CrossRef_File_Episode>(); } dictCrossRefs[xref.EpisodeID].Add(xref); } Dictionary <string, VideoLocal> dictVids = new Dictionary <string, VideoLocal>(); foreach (VideoLocal vid in vidsTemp) { dictVids[vid.Hash] = vid; } TimeSpan tsVids = DateTime.Now - startVids; logger.Trace("Got video locals for SERIES {0} in {1}ms", this.ToString(), tsVids.TotalMilliseconds); if (watchedStats) { foreach (JMMUser juser in allUsers) { //this.WatchedCount = 0; AnimeSeries_User userRecord = GetUserRecord(juser.JMMUserID); if (userRecord == null) { userRecord = new AnimeSeries_User(juser.JMMUserID, this.AnimeSeriesID); } // reset stats userRecord.UnwatchedEpisodeCount = 0; userRecord.WatchedEpisodeCount = 0; userRecord.WatchedCount = 0; userRecord.WatchedDate = null; DateTime startUser = DateTime.Now; List <AnimeEpisode_User> epUserRecords = repEpisodeUser.GetByUserID(juser.JMMUserID); Dictionary <int, AnimeEpisode_User> dictUserRecords = new Dictionary <int, AnimeEpisode_User>(); foreach (AnimeEpisode_User usrec in epUserRecords) { dictUserRecords[usrec.AnimeEpisodeID] = usrec; } TimeSpan tsUser = DateTime.Now - startUser; logger.Trace("Got user records for SERIES {0}/{1} in {2}ms", this.ToString(), juser.Username, tsUser.TotalMilliseconds); foreach (AnimeEpisode ep in eps) { // if the episode doesn't have any files then it won't count towards watched/unwatched counts List <VideoLocal> epVids = new List <VideoLocal>(); if (dictCrossRefs.ContainsKey(ep.AniDB_EpisodeID)) { foreach (CrossRef_File_Episode xref in dictCrossRefs[ep.AniDB_EpisodeID]) { if (xref.EpisodeID == ep.AniDB_EpisodeID) { if (dictVids.ContainsKey(xref.Hash)) { epVids.Add(dictVids[xref.Hash]); } } } } if (epVids.Count == 0) { continue; } if (ep.EpisodeTypeEnum == AniDBAPI.enEpisodeType.Episode || ep.EpisodeTypeEnum == AniDBAPI.enEpisodeType.Special) { AnimeEpisode_User epUserRecord = null; if (dictUserRecords.ContainsKey(ep.AnimeEpisodeID)) { epUserRecord = dictUserRecords[ep.AnimeEpisodeID]; } if (epUserRecord != null && epUserRecord.WatchedDate.HasValue) { userRecord.WatchedEpisodeCount++; } else { userRecord.UnwatchedEpisodeCount++; } if (epUserRecord != null) { if (userRecord.WatchedDate.HasValue) { if (epUserRecord.WatchedDate > userRecord.WatchedDate) { userRecord.WatchedDate = epUserRecord.WatchedDate; } } else { userRecord.WatchedDate = epUserRecord.WatchedDate; } userRecord.WatchedCount += epUserRecord.WatchedCount; } } } repSeriesUser.Save(userRecord); } } TimeSpan ts = DateTime.Now - start; logger.Trace("Updated WATCHED stats for SERIES {0} in {1}ms", this.ToString(), ts.TotalMilliseconds); start = DateTime.Now; if (missingEpsStats) { enAnimeType animeType = enAnimeType.TVSeries; AniDB_Anime aniDB_Anime = this.GetAnime(); if (aniDB_Anime != null) { animeType = aniDB_Anime.AnimeTypeEnum; } MissingEpisodeCount = 0; MissingEpisodeCountGroups = 0; // get all the group status records AniDB_GroupStatusRepository repGrpStat = new AniDB_GroupStatusRepository(); List <AniDB_GroupStatus> grpStatuses = repGrpStat.GetByAnimeID(this.AniDB_ID); // find all the episodes for which the user has a file // from this we can determine what their latest episode number is // find out which groups the user is collecting List <int> userReleaseGroups = new List <int>(); foreach (AnimeEpisode ep in eps) { List <VideoLocal> vids = new List <VideoLocal>(); if (dictCrossRefs.ContainsKey(ep.AniDB_EpisodeID)) { foreach (CrossRef_File_Episode xref in dictCrossRefs[ep.AniDB_EpisodeID]) { if (xref.EpisodeID == ep.AniDB_EpisodeID) { if (dictVids.ContainsKey(xref.Hash)) { vids.Add(dictVids[xref.Hash]); } } } } //List<VideoLocal> vids = ep.VideoLocals; foreach (VideoLocal vid in vids) { AniDB_File anifile = vid.GetAniDBFile(); if (anifile != null) { if (!userReleaseGroups.Contains(anifile.GroupID)) { userReleaseGroups.Add(anifile.GroupID); } } } } int latestLocalEpNumber = 0; EpisodeList epReleasedList = new EpisodeList(animeType); EpisodeList epGroupReleasedList = new EpisodeList(animeType); foreach (AnimeEpisode ep in eps) { //List<VideoLocal> vids = ep.VideoLocals; if (ep.EpisodeTypeEnum != AniDBAPI.enEpisodeType.Episode) { continue; } List <VideoLocal> vids = new List <VideoLocal>(); if (dictCrossRefs.ContainsKey(ep.AniDB_EpisodeID)) { foreach (CrossRef_File_Episode xref in dictCrossRefs[ep.AniDB_EpisodeID]) { if (xref.EpisodeID == ep.AniDB_EpisodeID) { if (dictVids.ContainsKey(xref.Hash)) { vids.Add(dictVids[xref.Hash]); } } } } AniDB_Episode aniEp = ep.AniDB_Episode; int thisEpNum = aniEp.EpisodeNumber; if (thisEpNum > latestLocalEpNumber && vids.Count > 0) { latestLocalEpNumber = thisEpNum; } // does this episode have a file released // does this episode have a file released by the group the user is collecting bool epReleased = false; bool epReleasedGroup = false; foreach (AniDB_GroupStatus gs in grpStatuses) { if (gs.LastEpisodeNumber >= thisEpNum) { epReleased = true; } if (userReleaseGroups.Contains(gs.GroupID) && gs.HasGroupReleasedEpisode(thisEpNum)) { epReleasedGroup = true; } } try { epReleasedList.Add(ep, (!epReleased || vids.Count != 0)); epGroupReleasedList.Add(ep, (!epReleasedGroup || vids.Count != 0)); } catch (Exception e) { logger.Trace("Error {0}", e.ToString()); throw; } } foreach (EpisodeList.StatEpisodes eplst in epReleasedList) { if (!eplst.Available) { MissingEpisodeCount++; } } foreach (EpisodeList.StatEpisodes eplst in epGroupReleasedList) { if (!eplst.Available) { MissingEpisodeCountGroups++; } } this.LatestLocalEpisodeNumber = latestLocalEpNumber; } ts = DateTime.Now - start; logger.Trace("Updated MISSING EPS stats for SERIES {0} in {1}ms", this.ToString(), ts.TotalMilliseconds); start = DateTime.Now; AnimeSeriesRepository rep = new AnimeSeriesRepository(); rep.Save(this); if (updateAllGroupsAbove) { foreach (AnimeGroup grp in AllGroupsAbove) { grp.UpdateStats(watchedStats, missingEpsStats); } } ts = DateTime.Now - start; logger.Trace("Updated GROUPS ABOVE stats for SERIES {0} in {1}ms", this.ToString(), ts.TotalMilliseconds); start = DateTime.Now; TimeSpan tsOverall = DateTime.Now - startOverall; logger.Info("Finished Updating STATS for SERIES {0} in {1}ms ({2} - {3} - {4})", this.ToString(), tsOverall.TotalMilliseconds, watchedStats, missingEpsStats, updateAllGroupsAbove); }
private VideoLocal ProcessFile_LocalInfo() { // hash and read media info for file int nshareID = -1; string filePath = ""; ImportFolderRepository repNS = new ImportFolderRepository(); List <ImportFolder> shares = repNS.GetAll(); DataAccessHelper.GetShareAndPath(FileName, shares, ref nshareID, ref filePath); if (!File.Exists(FileName)) { logger.Error("File does not exist: {0}", FileName); return(null); } int numAttempts = 0; // Wait 3 minutes seconds before giving up on trying to access the file while ((!CanAccessFile(FileName)) && (numAttempts < 180)) { numAttempts++; Thread.Sleep(1000); Console.WriteLine("Attempt # " + numAttempts.ToString()); } // if we failed to access the file, get ouuta here if (numAttempts == 180) { logger.Error("Could not access file: " + FileName); return(null); } // check if we have already processed this file VideoLocal vlocal = null; VideoLocalRepository repVidLocal = new VideoLocalRepository(); FileNameHashRepository repFNHash = new FileNameHashRepository(); List <VideoLocal> vidLocals = repVidLocal.GetByFilePathAndShareID(filePath, nshareID); FileInfo fi = new FileInfo(FileName); if (vidLocals.Count > 0) { vlocal = vidLocals[0]; logger.Trace("VideoLocal record found in database: {0}", vlocal.VideoLocalID); if (ForceHash) { vlocal.FileSize = fi.Length; vlocal.DateTimeUpdated = DateTime.Now; } } else { logger.Trace("VideoLocal, creating new record"); vlocal = new VideoLocal(); vlocal.DateTimeUpdated = DateTime.Now; vlocal.DateTimeCreated = vlocal.DateTimeUpdated; vlocal.FilePath = filePath; vlocal.FileSize = fi.Length; vlocal.ImportFolderID = nshareID; vlocal.Hash = ""; vlocal.CRC32 = ""; vlocal.MD5 = ""; vlocal.SHA1 = ""; vlocal.IsIgnored = 0; vlocal.IsVariation = 0; } // check if we need to get a hash this file Hashes hashes = null; if (string.IsNullOrEmpty(vlocal.Hash) || ForceHash) { // try getting the hash from the CrossRef if (!ForceHash) { CrossRef_File_EpisodeRepository repCrossRefs = new CrossRef_File_EpisodeRepository(); List <CrossRef_File_Episode> crossRefs = repCrossRefs.GetByFileNameAndSize(Path.GetFileName(vlocal.FilePath), vlocal.FileSize); if (crossRefs.Count == 1) { vlocal.Hash = crossRefs[0].Hash; vlocal.HashSource = (int)HashSource.DirectHash; } } // try getting the hash from the LOCAL cache if (!ForceHash && string.IsNullOrEmpty(vlocal.Hash)) { List <FileNameHash> fnhashes = repFNHash.GetByFileNameAndSize(Path.GetFileName(vlocal.FilePath), vlocal.FileSize); if (fnhashes != null && fnhashes.Count > 1) { // if we have more than one record it probably means there is some sort of corruption // lets delete the local records foreach (FileNameHash fnh in fnhashes) { repFNHash.Delete(fnh.FileNameHashID); } } if (fnhashes != null && fnhashes.Count == 1) { logger.Trace("Got hash from LOCAL cache: {0} ({1})", FileName, fnhashes[0].Hash); vlocal.Hash = fnhashes[0].Hash; vlocal.HashSource = (int)HashSource.WebCacheFileName; } } // hash the file if (string.IsNullOrEmpty(vlocal.Hash) || ForceHash) { DateTime start = DateTime.Now; logger.Trace("Calculating hashes for: {0}", FileName); // update the VideoLocal record with the Hash hashes = FileHashHelper.GetHashInfo(FileName, true, MainWindow.OnHashProgress, ServerSettings.Hash_CRC32, ServerSettings.Hash_MD5, ServerSettings.Hash_SHA1); TimeSpan ts = DateTime.Now - start; logger.Trace("Hashed file in {0} seconds --- {1} ({2})", ts.TotalSeconds.ToString("#0.0"), FileName, Utils.FormatByteSize(vlocal.FileSize)); vlocal.Hash = hashes.ed2k; vlocal.CRC32 = hashes.crc32; vlocal.MD5 = hashes.md5; vlocal.SHA1 = hashes.sha1; vlocal.HashSource = (int)HashSource.DirectHash; } // We should have a hash by now // before we save it, lets make sure there is not any other record with this hash (possible duplicate file) VideoLocal vidTemp = repVidLocal.GetByHash(vlocal.Hash); if (vidTemp != null) { // don't delete it, if it is actually the same record if (vidTemp.VideoLocalID != vlocal.VideoLocalID) { // delete the VideoLocal record logger.Warn("Deleting duplicate video file record"); logger.Warn("---------------------------------------------"); logger.Warn("Keeping record for: {0}", vlocal.FullServerPath); logger.Warn("Deleting record for: {0}", vidTemp.FullServerPath); logger.Warn("---------------------------------------------"); // check if we have a record of this in the database, if not create one DuplicateFileRepository repDups = new DuplicateFileRepository(); List <DuplicateFile> dupFiles = repDups.GetByFilePathsAndImportFolder(vlocal.FilePath, vidTemp.FilePath, vlocal.ImportFolderID, vidTemp.ImportFolderID); if (dupFiles.Count == 0) { dupFiles = repDups.GetByFilePathsAndImportFolder(vidTemp.FilePath, vlocal.FilePath, vidTemp.ImportFolderID, vlocal.ImportFolderID); } if (dupFiles.Count == 0) { DuplicateFile dup = new DuplicateFile(); dup.DateTimeUpdated = DateTime.Now; dup.FilePathFile1 = vlocal.FilePath; dup.FilePathFile2 = vidTemp.FilePath; dup.ImportFolderIDFile1 = vlocal.ImportFolderID; dup.ImportFolderIDFile2 = vidTemp.ImportFolderID; dup.Hash = vlocal.Hash; repDups.Save(dup); } repVidLocal.Delete(vidTemp.VideoLocalID); } } repVidLocal.Save(vlocal); // also save the filename to hash record // replace the existing records just in case it was corrupt FileNameHash fnhash = null; List <FileNameHash> fnhashes2 = repFNHash.GetByFileNameAndSize(Path.GetFileName(vlocal.FilePath), vlocal.FileSize); if (fnhashes2 != null && fnhashes2.Count > 1) { // if we have more than one record it probably means there is some sort of corruption // lets delete the local records foreach (FileNameHash fnh in fnhashes2) { repFNHash.Delete(fnh.FileNameHashID); } } if (fnhashes2 != null && fnhashes2.Count == 1) { fnhash = fnhashes2[0]; } else { fnhash = new FileNameHash(); } fnhash.FileName = Path.GetFileName(vlocal.FilePath); fnhash.FileSize = vlocal.FileSize; fnhash.Hash = vlocal.Hash; fnhash.DateTimeUpdated = DateTime.Now; repFNHash.Save(fnhash); } // now check if we have stored a VideoInfo record bool refreshMediaInfo = false; VideoInfoRepository repVidInfo = new VideoInfoRepository(); VideoInfo vinfo = repVidInfo.GetByHash(vlocal.Hash); if (vinfo == null) { refreshMediaInfo = true; vinfo = new VideoInfo(); vinfo.Hash = vlocal.Hash; vinfo.Duration = 0; vinfo.FileSize = fi.Length; vinfo.DateTimeUpdated = DateTime.Now; vinfo.FileName = filePath; vinfo.AudioBitrate = ""; vinfo.AudioCodec = ""; vinfo.VideoBitrate = ""; vinfo.VideoBitDepth = ""; vinfo.VideoCodec = ""; vinfo.VideoFrameRate = ""; vinfo.VideoResolution = ""; repVidInfo.Save(vinfo); } else { // check if we need to update the media info if (vinfo.VideoCodec.Trim().Length == 0) { refreshMediaInfo = true; } else { refreshMediaInfo = false; } } if (refreshMediaInfo) { logger.Trace("Getting media info for: {0}", FileName); MediaInfoResult mInfo = FileHashHelper.GetMediaInfo(FileName, true); vinfo.AudioBitrate = string.IsNullOrEmpty(mInfo.AudioBitrate) ? "" : mInfo.AudioBitrate; vinfo.AudioCodec = string.IsNullOrEmpty(mInfo.AudioCodec) ? "" : mInfo.AudioCodec; vinfo.DateTimeUpdated = vlocal.DateTimeUpdated; vinfo.Duration = mInfo.Duration; vinfo.FileName = filePath; vinfo.FileSize = fi.Length; vinfo.VideoBitrate = string.IsNullOrEmpty(mInfo.VideoBitrate) ? "" : mInfo.VideoBitrate; vinfo.VideoBitDepth = string.IsNullOrEmpty(mInfo.VideoBitDepth) ? "" : mInfo.VideoBitDepth; vinfo.VideoCodec = string.IsNullOrEmpty(mInfo.VideoCodec) ? "" : mInfo.VideoCodec; vinfo.VideoFrameRate = string.IsNullOrEmpty(mInfo.VideoFrameRate) ? "" : mInfo.VideoFrameRate; vinfo.VideoResolution = string.IsNullOrEmpty(mInfo.VideoResolution) ? "" : mInfo.VideoResolution; vinfo.FullInfo = string.IsNullOrEmpty(mInfo.FullInfo) ? "" : mInfo.FullInfo; repVidInfo.Save(vinfo); } // now add a command to process the file CommandRequest_ProcessFile cr_procfile = new CommandRequest_ProcessFile(vlocal.VideoLocalID, false); cr_procfile.Save(); return(vlocal); }
public System.IO.Stream GetFilters(string uid) { JMMUser user = KodiHelper.GetUser(uid); if (user == null) { return(new MemoryStream()); } int userid = user.JMMUserID; KodiObject ret = new KodiObject(KodiHelper.NewMediaContainer("Anime", false)); if (!ret.Init()) { return(new MemoryStream()); } List <Video> dirs = new List <Video>(); try { using (var session = JMMService.SessionFactory.OpenSession()) { GroupFilterRepository repGF = new GroupFilterRepository(); List <GroupFilter> allGfs = repGF.GetAll(session); Dictionary <int, HashSet <int> > gstats = StatsCache.Instance.StatUserGroupFilter[userid]; foreach (GroupFilter gg in allGfs.ToArray()) { if ((!StatsCache.Instance.StatUserGroupFilter.ContainsKey(userid)) || (!StatsCache.Instance.StatUserGroupFilter[userid].ContainsKey(gg.GroupFilterID))) { allGfs.Remove(gg); } } AnimeGroupRepository repGroups = new AnimeGroupRepository(); allGfs.Insert(0, new GroupFilter() { GroupFilterName = "All", GroupFilterID = -999 }); foreach (GroupFilter gg in allGfs) { Random rnd = new Random(123456789); Directory pp = new Directory(); pp.Key = KodiHelper.ServerUrl(int.Parse(ServerSettings.JMMServerPort), MainWindow.PathAddressKodi + "/GetMetadata/" + userid + "/" + (int)JMMType.GroupFilter + "/" + gg.GroupFilterID); pp.PrimaryExtraKey = pp.Key; pp.Title = gg.GroupFilterName; HashSet <int> groups; groups = gg.GroupFilterID == -999 ? new HashSet <int>(repGroups.GetAllTopLevelGroups(session).Select(a => a.AnimeGroupID)) : gstats[gg.GroupFilterID]; if (groups.Count != 0) { bool repeat; int nn = 0; pp.LeafCount = groups.Count.ToString(); pp.ViewedLeafCount = "0"; do { repeat = true; int grp = groups.ElementAt(rnd.Next(groups.Count)); AnimeGroup ag = repGroups.GetByID(grp); List <AnimeSeries> sers = ag.GetSeries(session); if (sers.Count > 0) { AnimeSeries ser = sers[rnd.Next(sers.Count)]; AniDB_Anime anim = ser.GetAnime(session); if (anim != null) { ImageDetails poster = anim.GetDefaultPosterDetailsNoBlanks(session); ImageDetails fanart = anim.GetDefaultFanartDetailsNoBlanks(session); if (poster != null) { pp.Thumb = poster.GenPoster(); } if (fanart != null) { pp.Art = fanart.GenArt(); } if (poster != null) { repeat = false; } } } nn++; if ((repeat) && (nn == 15)) { repeat = false; } } while (repeat); dirs.Add(pp); } } VideoLocalRepository repVids = new VideoLocalRepository(); List <VideoLocal> vids = repVids.GetVideosWithoutEpisode(); if (vids.Count > 0) { JMMContracts.KodiContracts.Directory pp = new JMMContracts.KodiContracts.Directory(); pp.Key = pp.PrimaryExtraKey = KodiHelper.ServerUrl(int.Parse(ServerSettings.JMMServerPort), MainWindow.PathAddressKodi + "/GetMetadata/0/" + (int)JMMType.GroupUnsort + "/0"); pp.Title = "Unsort"; pp.Thumb = KodiHelper.ServerUrl(int.Parse(ServerSettings.JMMServerPort), MainWindow.PathAddressKodi + "/GetSupportImage/plex_unsort.png"); pp.LeafCount = vids.Count.ToString(); pp.ViewedLeafCount = "0"; dirs.Add(pp); } dirs = dirs.OrderBy(a => a.Title).ToList(); } ret.Childrens = dirs; return(ret.GetStream()); } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); return(new MemoryStream()); } }