/// <summary> /// Create user from Contract_JMMUser /// </summary> /// <returns></returns> private object CreateUser() { Request request = this.Request; SVR_JMMUser _user = (SVR_JMMUser)this.Context.CurrentUser; if (_user.IsAdmin == 1) { JMMUser user = this.Bind(); user.Password = Digest.Hash(user.Password); user.HideCategories = ""; user.PlexUsers = ""; if (new ShokoServiceImplementation().SaveUser(user) == "") { return(APIStatus.statusOK()); } else { return(APIStatus.internalError()); } } else { return(APIStatus.adminNeeded()); } }
public List <SVR_VideoLocal> GetMostRecentlyAdded(int maxResults, int jmmuserID) { SVR_JMMUser user = RepoFactory.JMMUser.GetByID(jmmuserID); if (user == null) { lock (Cache) { if (maxResults == -1) { return(Cache.Values.OrderByDescending(a => a.DateTimeCreated).ToList()); } return(Cache.Values.OrderByDescending(a => a.DateTimeCreated).Take(maxResults).ToList()); } } if (maxResults == -1) { return(Cache.Values.OrderByDescending(a => a.DateTimeCreated).Where(a => { var series = a.GetAnimeEpisodes().Select(b => b.GetAnimeSeries()).Where(b => b != null) .DistinctBy(b => b.AniDB_ID); return series.All(user.AllowedSeries); }).ToList()); } return(Cache.Values.OrderByDescending(a => a.DateTimeCreated).Where(a => { var series = a.GetAnimeEpisodes().Select(b => b.GetAnimeSeries()).Where(b => b != null) .DistinctBy(b => b.AniDB_ID); return series.All(user.AllowedSeries); }).Take(maxResults).ToList()); }
private void CreateInitialUsers() { if (RepoFactory.JMMUser.GetAll().Count() > 0) { return; } Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(ServerSettings.Culture); SVR_JMMUser defaultUser = new SVR_JMMUser(); defaultUser.CanEditServerSettings = 1; defaultUser.HideCategories = ""; defaultUser.IsAdmin = 1; defaultUser.IsAniDBUser = 1; defaultUser.IsTraktUser = 1; defaultUser.Password = ""; defaultUser.Username = Shoko.Commons.Properties.Resources.Users_Default; RepoFactory.JMMUser.Save(defaultUser, true); SVR_JMMUser familyUser = new SVR_JMMUser(); familyUser.CanEditServerSettings = 1; familyUser.HideCategories = "ecchi,nudity,sex,sexual abuse,horror,erotic game,incest,18 restricted"; familyUser.IsAdmin = 1; familyUser.IsAniDBUser = 1; familyUser.IsTraktUser = 1; familyUser.Password = ""; familyUser.Username = Shoko.Commons.Properties.Resources.Users_FamilyFriendly; RepoFactory.JMMUser.Save(familyUser, true); }
private void CreateInitialUsers() { if (RepoFactory.JMMUser.GetAll().Any()) { return; } Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(ServerSettings.Culture); SVR_JMMUser defaultUser = new SVR_JMMUser { CanEditServerSettings = 1, HideCategories = string.Empty, IsAdmin = 1, IsAniDBUser = 1, IsTraktUser = 1, Password = ServerSettings.DefaultUserPassword, Username = ServerSettings.DefaultUserUsername }; RepoFactory.JMMUser.Save(defaultUser, true); SVR_JMMUser familyUser = new SVR_JMMUser { CanEditServerSettings = 1, HideCategories = "ecchi,nudity,sex,sexual abuse,horror,erotic game,incest,18 restricted", IsAdmin = 1, IsAniDBUser = 1, IsTraktUser = 1, Password = string.Empty, Username = Commons.Properties.Resources.Users_FamilyFriendly }; RepoFactory.JMMUser.Save(familyUser, true); }
public List <Dashboard.EpisodeDetails> GetAniDBCalendarInDays([FromQuery] int numberOfDays = 7, [FromQuery] bool showAll = false) { SVR_JMMUser user = HttpContext.GetUser(); var episodeList = RepoFactory.AniDB_Episode.GetForDate(DateTime.Today, DateTime.Today.AddDays(numberOfDays)).ToList(); var animeDict = episodeList .Select(episode => RepoFactory.AniDB_Anime.GetByAnimeID(episode.AnimeID)) .Distinct() .ToDictionary(anime => anime.AnimeID); var seriesDict = episodeList .Select(episode => RepoFactory.AnimeSeries.GetByAnimeID(episode.AnimeID)) .Where(series => series != null) .Distinct() .ToDictionary(anime => anime.AniDB_ID); return(episodeList .Where(episode => user.AllowedAnime(animeDict[episode.AnimeID]) && (showAll || seriesDict.Keys.Contains(episode.AnimeID))) .OrderBy(episode => episode.GetAirDateAsDate()) .Select(episode => { var anime = animeDict[episode.AnimeID]; if (seriesDict.TryGetValue(episode.AnimeID, out var series)) { return new Dashboard.EpisodeDetails(episode, anime, series); } return new Dashboard.EpisodeDetails(episode, anime); }) .ToList()); }
/// <summary> /// change current user password /// </summary> /// <returns></returns> private object ChangePassword() { Request request = this.Request; SVR_JMMUser user = (SVR_JMMUser)this.Context.CurrentUser; return(ChangePassword(user.JMMUserID)); }
public ActionResult ChangePassword(int userID, [FromBody] string password, bool revokeAPIKeys = true) { try { SVR_JMMUser jmmUser = RepoFactory.JMMUser.GetByID(userID); if (jmmUser == null) { return(BadRequest("User not found")); } if (jmmUser.JMMUserID != User.JMMUserID && !User.IsAdminUser()) { return(Unauthorized()); } jmmUser.Password = Digest.Hash(password); RepoFactory.JMMUser.Save(jmmUser, false); if (revokeAPIKeys) { RepoFactory.AuthTokens.DeleteAllWithUserID(jmmUser.JMMUserID); } } catch (Exception ex) { return(InternalError(ex.ToString())); } return(Ok()); }
private static List <SearchResult> SearchTagsEquals(string query, int limit, SVR_JMMUser user, ParallelQuery <AniDB_Tag> allTags) { List <SearchResult> series = new List <SearchResult>(); IEnumerable <CustomTag> customTags = RepoFactory.CustomTag.GetAll(); series.AddRange(customTags.Where(a => a.TagName.Equals(query, StringComparison.InvariantCultureIgnoreCase)).SelectMany(tag => { return(RepoFactory.CrossRef_CustomTag.GetByCustomTagID(tag.CustomTagID) .Select(xref => { if (xref.CrossRefType != (int)CustomTagCrossRefType.Anime) { return null; } var anime = RepoFactory.AnimeSeries.GetByAnimeID(xref.CrossRefID); // Because we are searching tags, then getting series from it, we need to make sure it's allowed // for example, p**n could have the drugs tag, even though it's not a "p**n tag" if (anime?.GetAnime()?.GetAllTags().FindInEnumerable(user.GetHideCategories()) ?? true) { return null; } return new SearchResult { Distance = 0, Index = 0, Match = tag.TagName, Result = anime, ExactMatch = true }; }).Where(a => a != null).OrderBy(a => a.Distance).ThenBy(a => a.Result.GetSeriesName())); }).Take(limit)); limit -= series.Count; series.AddRange(allTags.Where(a => a.TagName.Equals(query, StringComparison.InvariantCultureIgnoreCase)).SelectMany(tag => { return(RepoFactory.AniDB_Anime_Tag.GetByTagID(tag.TagID) .Select(xref => { var anime = RepoFactory.AnimeSeries.GetByAnimeID(xref.AnimeID); // Because we are searching tags, then getting series from it, we need to make sure it's allowed // for example, p**n could have the drugs tag, even though it's not a "p**n tag" if (anime?.GetAnime()?.GetAllTags().FindInEnumerable(user.GetHideCategories()) ?? true) { return null; } return new SearchResult { Distance = (600 - xref.Weight) / 600D, Index = 0, Match = tag.TagName, Result = anime, ExactMatch = true }; }).Where(a => a != null).OrderBy(a => a.Distance).ThenBy(a => a.Result.GetSeriesName())); }).Take(limit)); return(series); }
/// <summary> /// Delete user from his ID /// </summary> /// <returns></returns> private object DeleteUser() { SVR_JMMUser _user = (SVR_JMMUser)Context.CurrentUser; if (_user.IsAdmin == 1) { SVR_JMMUser user = this.Bind(); return(new ShokoServiceImplementation().DeleteUser(user.JMMUserID) == string.Empty ? APIStatus.OK() : APIStatus.InternalError()); } return(APIStatus.AdminNeeded()); }
public SVR_JMMUser GetServerModel() { var user = new SVR_JMMUser { Username = Username, JMMUserID = ID, Password = Password, HideCategories = string.Join(',', TagBlacklist), IsAdmin = IsAdmin ? 1 : 0, IsTraktUser = CommunitySites.Contains(global::Shoko.Models.Enums.CommunitySites.Trakt) ? 1 : 0, CanEditServerSettings = IsAdmin ? 1 : 0, IsAniDBUser = CommunitySites.Contains(global::Shoko.Models.Enums.CommunitySites.AniDB) ? 1 : 0, }; return(user); }
/// <summary> /// Create user from Contract_JMMUser /// </summary> /// <returns></returns> private object CreateUser() { SVR_JMMUser _user = (SVR_JMMUser)Context.CurrentUser; if (_user.IsAdmin == 1) { JMMUser user = this.Bind(); user.Password = Digest.Hash(user.Password); user.HideCategories = string.Empty; user.PlexUsers = string.Empty; return(new ShokoServiceImplementation().SaveUser(user) == string.Empty ? APIStatus.OK() : APIStatus.InternalError()); } return(APIStatus.AdminNeeded()); }
/// <summary> /// Set settings for LogRotator /// </summary> /// <returns></returns> private object SetRotateLogs() { Request request = Request; SVR_JMMUser user = (SVR_JMMUser)Context.CurrentUser; Logs rotator = this.Bind(); if (user.IsAdmin == 1) { ServerSettings.RotateLogs = rotator.rotate; ServerSettings.RotateLogs_Zip = rotator.zip; ServerSettings.RotateLogs_Delete = rotator.delete; ServerSettings.RotateLogs_Delete_Days = rotator.days.ToString(); return(APIStatus.OK()); } return(APIStatus.AdminNeeded()); }
public SVR_JMMUser MergeServerModel(SVR_JMMUser existing) { var user = new SVR_JMMUser { Username = Username, JMMUserID = ID, HideCategories = string.Join(',', TagBlacklist), IsAdmin = IsAdmin ? 1 : 0, IsTraktUser = CommunitySites.Contains(global::Shoko.Models.Enums.CommunitySites.Trakt) ? 1 : 0, CanEditServerSettings = IsAdmin ? 1 : 0, IsAniDBUser = CommunitySites.Contains(global::Shoko.Models.Enums.CommunitySites.AniDB) ? 1 : 0, Password = existing?.Password ?? string.Empty, PlexToken = existing?.PlexToken, PlexUsers = existing?.PlexUsers ?? string.Empty }; return(user); }
public ActionResult <User> AddUser(User.FullUser user) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } try { SVR_JMMUser jmmUser = user.GetServerModel(); RepoFactory.JMMUser.Save(jmmUser); return(new User(jmmUser)); } catch (Exception e) { return(InternalError(e.Message)); } }
public User(SVR_JMMUser user) { ID = user.JMMUserID; Username = user.Username; IsAdmin = user.IsAdmin == 1; CommunitySites = new List <CommunitySites>(); if (user.IsAniDBUser == 1) { CommunitySites.Add(global::Shoko.Models.Enums.CommunitySites.AniDB); } if (user.IsTraktUser == 1) { CommunitySites.Add(global::Shoko.Models.Enums.CommunitySites.Trakt); } if (!string.IsNullOrEmpty(user.PlexToken)) { CommunitySites.Add(global::Shoko.Models.Enums.CommunitySites.Plex); } TagBlacklist = user.GetHideCategories().ToList(); }
/// <summary> /// change given user (by uid) password /// </summary> /// <returns></returns> private object ChangePassword(int uid) { SVR_JMMUser thisuser = (SVR_JMMUser)Context.CurrentUser; SVR_JMMUser user = this.Bind(); if (thisuser.IsAdmin == 1) { return(new ShokoServiceImplementation().ChangePassword(uid, user.Password) == string.Empty ? APIStatus.OK() : APIStatus.InternalError()); } if (thisuser.JMMUserID == user.JMMUserID) { return(new ShokoServiceImplementation().ChangePassword(uid, user.Password) == string.Empty ? APIStatus.OK() : APIStatus.InternalError()); } return(APIStatus.AdminNeeded()); }
public List <SVR_VideoLocal> GetMostRecentlyAdded(int take, int skip, int jmmuserID = -1) { if (skip < 0) { skip = 0; } if (take == 0) { return(new List <SVR_VideoLocal>()); } SVR_JMMUser user = jmmuserID == -1 ? null : RepoFactory.JMMUser.GetByID(jmmuserID); if (user == null) { lock (Cache) { if (take == -1) { return(Cache.Values.OrderByDescending(a => a.DateTimeCreated).Skip(skip).ToList()); } return(Cache.Values.OrderByDescending(a => a.DateTimeCreated).Skip(skip).Take(take).ToList()); } } if (take == -1) { return(Cache.Values .Where(a => a.GetAnimeEpisodes().Select(b => b.GetAnimeSeries()).Where(b => b != null).DistinctBy(b => b.AniDB_ID).All(user.AllowedSeries)) .OrderByDescending(a => a.DateTimeCreated) .Skip(skip) .ToList()); } return(Cache.Values .Where(a => a.GetAnimeEpisodes().Select(b => b.GetAnimeSeries()).Where(b => b != null).DistinctBy(b => b.AniDB_ID).All(user.AllowedSeries)) .OrderByDescending(a => a.DateTimeCreated) .Skip(skip) .Take(take) .ToList()); }
/// <summary> /// Delete user from his ID /// </summary> /// <returns></returns> private object DeleteUser() { Request request = this.Request; SVR_JMMUser _user = (SVR_JMMUser)this.Context.CurrentUser; if (_user.IsAdmin == 1) { SVR_JMMUser user = this.Bind(); if (new ShokoServiceImplementation().DeleteUser(user.JMMUserID) == "") { return(APIStatus.statusOK()); } else { return(APIStatus.internalError()); } } else { return(APIStatus.adminNeeded()); } }
/// <summary> /// change given user (by uid) password /// </summary> /// <returns></returns> private object ChangePassword(int uid) { Request request = this.Request; SVR_JMMUser _user = (SVR_JMMUser)this.Context.CurrentUser; if (_user.IsAdmin == 1) { SVR_JMMUser user = this.Bind(); if (new ShokoServiceImplementation().ChangePassword(uid, user.Password) == "") { return(APIStatus.statusOK()); } else { return(APIStatus.internalError()); } } else { return(APIStatus.adminNeeded()); } }
private void CreateInitialUsers() { if (RepoFactory.JMMUser.GetAll().Any()) { return; } Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(ServerSettings.Instance.Culture); string defaultPassword = ServerSettings.Instance.Database.DefaultUserPassword == "" ? "" : Digest.Hash(ServerSettings.Instance.Database.DefaultUserPassword); SVR_JMMUser defaultUser = new SVR_JMMUser { CanEditServerSettings = 1, HideCategories = string.Empty, IsAdmin = 1, IsAniDBUser = 1, IsTraktUser = 1, Password = defaultPassword, Username = ServerSettings.Instance.Database.DefaultUserUsername }; RepoFactory.JMMUser.Save(defaultUser, true); SVR_JMMUser familyUser = new SVR_JMMUser { CanEditServerSettings = 1, HideCategories = "ecchi,nudity,sex,sexual abuse,horror,erotic game,incest,18 restricted", IsAdmin = 1, IsAniDBUser = 1, IsTraktUser = 1, Password = string.Empty, Username = "******" }; RepoFactory.JMMUser.Save(familyUser, true); }
public static string ValidateUser(string username, string password, string device) { //in case of login before database have been loaded if (Users.Count == 0) { UserDatabase.Refresh(); } var userRecord = Users.FirstOrDefault(u => u.Item2.Equals(username, StringComparison.OrdinalIgnoreCase) && u.Item3 == password); if (userRecord == null) { //if user is invalid try to refresh cache so we add any newly added users to cache just in case UserDatabase.Refresh(); return(null); } int uid = new SVR_JMMUser(username).JMMUserID; string apiKey = ""; try { var apiKeys = ActiveApiKeys.First(u => u.Item1 == uid && u.Item2 == device.ToLower()); apiKey = apiKeys.Item3; } catch { apiKey = Guid.NewGuid().ToString(); ActiveApiKeys.Add(new Tuple <int, string, string>(uid, device.ToLower(), apiKey)); AuthTokens token = new AuthTokens { UserID = uid, DeviceName = (device).ToLower(), Token = apiKey }; RepoFactory.AuthTokens.Save(token); } return(apiKey); }
public Filter(HttpContext ctx, SVR_GroupFilter gf) { IDs = new IDs { ID = gf.GroupFilterID }; Name = gf.GroupFilterName; SVR_JMMUser user = ctx.GetUser(); Directory = ((GroupFilterType)gf.FilterType).HasFlag(GroupFilterType.Directory); // This can be used to exclude from client visibility for user Size = gf.GroupsIds.ContainsKey(user.JMMUserID) ? gf.GroupsIds[user.JMMUserID].Count : 0; if (Directory) { Size += RepoFactory.GroupFilter.GetByParentID(gf.GroupFilterID).Count; } ApplyAtSeriesLevel = gf.ApplyToSeries == 1; // It's never null, just marked Nullable for some reason Locked = gf.Locked != null && gf.Locked.Value == 1; HideInAPI = gf.InvisibleInClients == 1; }
private static List <SearchResult> SearchTagsFuzzy(string query, int limit, SVR_JMMUser user, ParallelQuery <AniDB_Tag> allTags) { List <SearchResult> series = new List <SearchResult>(); IEnumerable <Misc.SearchInfo <CustomTag> > customTags = RepoFactory.CustomTag.GetAll().Select(a => { if (user.GetHideCategories().Contains(a.TagName)) { return(null); } Misc.SearchInfo <CustomTag> tag = Misc.DiceFuzzySearch(a.TagName, query, 0, a); if (tag.Index == -1 || tag.Result == null) { return(null); } return(tag); }).Where(a => a != null).OrderBy(a => a.Distance); series.AddRange(customTags.SelectMany(tag => { return(RepoFactory.CrossRef_CustomTag.GetByCustomTagID(tag.Result.CustomTagID) .Select(xref => { if (xref.CrossRefType != (int)CustomTagCrossRefType.Anime) { return null; } SVR_AnimeSeries anime = RepoFactory.AnimeSeries.GetByAnimeID(xref.CrossRefID); // Because we are searching tags, then getting series from it, we need to make sure it's allowed // for example, p**n could have the drugs tag, even though it's not a "p**n tag" if (anime?.GetAnime()?.GetAllTags().FindInEnumerable(user.GetHideCategories()) ?? true) { return null; } return new SearchResult { Distance = tag.Distance, Index = tag.Index, Match = tag.Result.TagName, Result = anime, ExactMatch = tag.ExactMatch }; }).Where(b => b != null).OrderBy(b => b.Distance).ThenBy(b => b.Result.GetSeriesName()).ToList()); }).Take(limit)); limit -= series.Count; var tags = allTags.Select(tag => { var result = Misc.DiceFuzzySearch(tag.TagName, query, 0, tag); if (result.Index == -1 || result.Result == null) { return(null); } return(result); }).Where(a => a != null).OrderBy(a => a.Distance); series.AddRange(tags.SelectMany(tag => { return(RepoFactory.AniDB_Anime_Tag.GetByTagID(tag.Result.TagID) .Select(xref => { var anime = RepoFactory.AnimeSeries.GetByAnimeID(xref.AnimeID); // Because we are searching tags, then getting series from it, we need to make sure it's allowed // for example, p**n could have the drugs tag, even though it's not a "p**n tag" if (anime?.GetAnime()?.GetAllTags().FindInEnumerable(user.GetHideCategories()) ?? true) { return null; } return new SearchResult { Distance = (600D - xref.Weight) / 600, Index = tag.Index, Match = tag.Result.TagName, Result = anime, ExactMatch = tag.ExactMatch }; }).Where(a => a != null).OrderBy(a => a.Distance).ThenBy(a => a.Result.GetSeriesName()).ToList()); }).Take(limit)); return(series); }
public override void ProcessCommand() { logger.Info("Processing CommandRequest_AddFileToMyList: {0}", Hash); try { vid = RepoFactory.VideoLocal.GetByHash(this.Hash); List <SVR_AnimeEpisode> animeEpisodes = new List <SVR_AnimeEpisode>(); if (vid != null) { animeEpisodes = vid.GetAnimeEpisodes(); } if (vid != null) { // when adding a file via the API, newWatchedStatus will return with current watched status on AniDB // if the file is already on the user's list bool isManualLink = false; List <CrossRef_File_Episode> xrefs = vid.EpisodeCrossRefs; if (xrefs.Count > 0) { isManualLink = xrefs[0].CrossRefSource != (int)CrossRefSource.AniDB; } // mark the video file as watched DateTime?watchedDate = null; bool newWatchedStatus = false; if (isManualLink) { newWatchedStatus = ShokoService.AnidbProcessor.AddFileToMyList(xrefs[0].AnimeID, xrefs[0].GetEpisode().EpisodeNumber, ref watchedDate); } else { newWatchedStatus = ShokoService.AnidbProcessor.AddFileToMyList(vid, ref watchedDate); } // do for all AniDB users List <SVR_JMMUser> aniDBUsers = RepoFactory.JMMUser.GetAniDBUsers(); if (aniDBUsers.Count > 0) { SVR_JMMUser juser = aniDBUsers[0]; vid.ToggleWatchedStatus(newWatchedStatus, false, watchedDate, false, false, juser.JMMUserID, false, true); logger.Info("Adding file to list: {0} - {1}", vid.ToString(), watchedDate); // if the the episode is watched we may want to set the file to watched as well if (ServerSettings.Import_UseExistingFileWatchedStatus && !newWatchedStatus) { if (animeEpisodes.Count > 0) { SVR_AnimeEpisode ep = animeEpisodes[0]; SVR_AnimeEpisode_User epUser = null; foreach (SVR_JMMUser tempuser in aniDBUsers) { // only find the first user who watched this if (epUser == null) { epUser = ep.GetUserRecord(tempuser.JMMUserID); } } if (epUser != null) { logger.Info( "Setting file as watched, because episode was already watched: {0} - user: {1}", vid.ToString(), juser.Username); vid.ToggleWatchedStatus(true, true, epUser.WatchedDate, false, false, epUser.JMMUserID, false, true); } } } } SVR_AnimeSeries ser = animeEpisodes[0].GetAnimeSeries(); // all the eps should belong to the same anime ser.QueueUpdateStats(); //StatsCache.Instance.UpdateUsingSeries(ser.AnimeSeriesID); // lets also try adding to the users trakt collecion if (ser != null && ServerSettings.Trakt_IsEnabled && !string.IsNullOrEmpty(ServerSettings.Trakt_AuthToken)) { foreach (SVR_AnimeEpisode aep in animeEpisodes) { CommandRequest_TraktCollectionEpisode cmdSyncTrakt = new CommandRequest_TraktCollectionEpisode ( aep.AnimeEpisodeID, TraktSyncAction.Add); cmdSyncTrakt.Save(); } } // sync the series on MAL if (ser != null && !string.IsNullOrEmpty(ServerSettings.MAL_Username) && !string.IsNullOrEmpty(ServerSettings.MAL_Password)) { CommandRequest_MALUpdatedWatchedStatus cmdMAL = new CommandRequest_MALUpdatedWatchedStatus(ser.AniDB_ID); cmdMAL.Save(); } } } catch (Exception ex) { logger.Error("Error processing CommandRequest_AddFileToMyList: {0} - {1}", Hash, ex.ToString()); return; } }
/// <summary> /// Search for series with given query in name or tag /// </summary> /// <param name="query">target string</param> /// <param name="userID">user id</param> /// <param name="limit">The number of results to return</param> /// <param name="flags">The SearchFlags to determine the type of search</param> /// <returns> /// <see cref="List{SearchResult}" /> /// </returns> public static List <SearchResult> Search(int userID, string query, int limit, SearchFlags flags, TagFilter.Filter tagFilter = TagFilter.Filter.None) { query = query.ToLowerInvariant(); SVR_JMMUser user = RepoFactory.JMMUser.GetByID(userID); if (user == null) { throw new Exception("User not found"); } ParallelQuery <SVR_AnimeSeries> allSeries = RepoFactory.AnimeSeries.GetAll().AsParallel().Where(a => a?.GetAnime() != null && (a.GetAnime().GetAllTags().Count == 0 || !a.GetAnime().GetAllTags().FindInEnumerable(user.GetHideCategories()))); ParallelQuery <AniDB_Tag> allTags = RepoFactory.AniDB_Tag.GetAll().AsParallel() .Where(a => { List <string> _ = new List <string>(); return(!user.GetHideCategories().Contains(a.TagName) && !TagFilter.IsTagBlackListed(a.TagName, tagFilter, ref _)); }); //search by anime id if (int.TryParse(query, out int aid)) { var aidResults = SearchTitlesByAnimeID(aid, allSeries); if (aidResults.Count > 0) { return(aidResults); } } #region Search_TitlesOnly switch (flags) { case SearchFlags.Titles: return(SearchTitlesIndexOf(query, limit, allSeries)); case SearchFlags.Fuzzy | SearchFlags.Titles: return(SearchTitlesFuzzy(query, limit, allSeries)); case SearchFlags.Tags: return(SearchTagsEquals(query, limit, user, allTags)); case SearchFlags.Fuzzy | SearchFlags.Tags: return(SearchTagsFuzzy(query, limit, user, allTags)); case SearchFlags.Tags | SearchFlags.Titles: List <SearchResult> titleResult = SearchTitlesIndexOf(query, limit, allSeries); int tagLimit = limit - titleResult.Count; if (tagLimit <= 0) { return(titleResult); } titleResult.AddRange(SearchTagsEquals(query, tagLimit, user, allTags)); return(titleResult); case SearchFlags.Fuzzy | SearchFlags.Tags | SearchFlags.Titles: List <SearchResult> titles = SearchTitlesFuzzy(query, limit, allSeries); int tagLimit2 = limit - titles.Count; if (tagLimit2 <= 0) { return(titles); } titles.AddRange(SearchTagsFuzzy(query, tagLimit2, user, allTags)); return(titles); } #endregion return(new List <SearchResult>()); }
/// <summary> /// change current user password /// </summary> /// <returns></returns> private object ChangePassword() { SVR_JMMUser user = this.Bind(); return(ChangePassword(user.JMMUserID)); }
public object GetStats() { SVR_JMMUser user = HttpContext.User.Identity as SVR_JMMUser; int series_count; int file_count; string size; int watched_files = 0; int watched_series = 0; long hours = 0; List <string> tags; if (user != null) { var series = Repo.Instance.AnimeSeries.GetAll().Where(a => !a.GetAnime()?.GetAllTags().FindInEnumerable(user.GetHideCategories()) ?? false).ToList(); series_count = series.Count; var files = series.SelectMany(a => a.GetAnimeEpisodes()).SelectMany(a => a.GetVideoLocals()) .DistinctBy(a => a.VideoLocalID).ToList(); file_count = files.Count; size = SizeSuffix(files.Sum(a => a.FileSize)); var watched = Repo.Instance.VideoLocal_User.GetByUserID(user.JMMUserID) .Where(a => a.WatchedDate != null).ToList(); watched_files = watched.Count; watched_series = Repo.Instance.AnimeSeries.GetAll().Count(a => { var contract = a.GetUserContract(user.JMMUserID); if (contract?.MissingEpisodeCount > 0) { return(false); } return(contract?.UnwatchedEpisodeCount == 0); }); hours = watched.Select(a => Repo.Instance.VideoLocal.GetByID(a.VideoLocalID)).Where(a => a != null) .Sum(a => a.Duration) / 3600000; // 1000ms * 60s * 60m = ?h tags = Repo.Instance.AniDB_Anime_Tag.GetAllForLocalSeries().GroupBy(a => a.TagID) .ToDictionary(a => a.Key, a => a.Count()).OrderByDescending(a => a.Value) .Select(a => Repo.Instance.AniDB_Tag.GetByID(a.Key)?.TagName) .Where(a => a != null && !user.GetHideCategories().Contains(a)).ToList(); var tagfilter = TagFilter.Filter.AnidbInternal | TagFilter.Filter.Misc | TagFilter.Filter.Source; tags = TagFilter.ProcessTags(tagfilter, tags).Take(10).ToList(); } else { var series = Repo.Instance.AnimeSeries.GetAll(); series_count = series.Count; var files = series.SelectMany(a => a.GetAnimeEpisodes()).SelectMany(a => a.GetVideoLocals()) .DistinctBy(a => a.VideoLocalID).ToList(); file_count = files.Count; size = SizeSuffix(files.Sum(a => a.FileSize)); tags = Repo.Instance.AniDB_Anime_Tag.GetAllForLocalSeries().GroupBy(a => a.TagID) .ToDictionary(a => a.Key, a => a.Count()).OrderByDescending(a => a.Value) .Select(a => Repo.Instance.AniDB_Tag.GetByID(a.Key)?.TagName) .Where(a => a != null).ToList(); var tagfilter = TagFilter.Filter.AnidbInternal | TagFilter.Filter.Misc | TagFilter.Filter.Source; tags = TagFilter.ProcessTags(tagfilter, tags).Take(10).ToList(); } return(new Dictionary <string, object> { { "queue", Repo.Instance.CommandRequest.GetByClasses().ToDictionary(a => FromLastPoint(a.Key), a => a.Value) }, { "file_count", file_count }, { "series_count", series_count }, { "collection_size", size }, { "watched_files", watched_files }, { "watched_series", watched_series }, { "hours_watched", hours }, { "tags", tags } }); }
/*public static void UpdateWatchedStatus(int animeID, enEpisodeType epType, int lastWatchedEpNumber) * { * try * { * if (string.IsNullOrEmpty(ServerSettings.MAL_Username) || string.IsNullOrEmpty(ServerSettings.MAL_Password)) * return; * * AniDB_EpisodeRepository repAniEps = new AniDB_EpisodeRepository(); * List<AniDB_Episode> aniEps = repAniEps.GetByAnimeIDAndEpisodeTypeNumber(animeID, epType, lastWatchedEpNumber); * if (aniEps.Count == 0) return; * * AnimeEpisodeRepository repEp = new AnimeEpisodeRepository(); * AnimeEpisode ep = repEp.GetByAniDBEpisodeID(aniEps[0].EpisodeID); * if (ep == null) return; * * MALHelper.UpdateMAL(ep); * } * catch (Exception ex) * { * logger.Error( ex,ex.ToString()); * } * }*/ public static void UpdateMALSeries(SVR_AnimeSeries ser) { try { if (string.IsNullOrEmpty(ServerSettings.MAL_Username) || string.IsNullOrEmpty(ServerSettings.MAL_Password)) { return; } // Populate MAL animelist hashtable if isNeverDecreaseWatched set Hashtable animeListHashtable = new Hashtable(); myanimelist malAnimeList = GetMALAnimeList(); if (ServerSettings.MAL_NeverDecreaseWatchedNums) //if set, check watched number before update: take some time, as user anime list must be loaded { if (malAnimeList != null && malAnimeList.anime != null) { for (int i = 0; i < malAnimeList.anime.Length; i++) { animeListHashtable.Add(malAnimeList.anime[i].series_animedb_id, malAnimeList.anime[i]); } } } // look for MAL Links List <CrossRef_AniDB_MAL> crossRefs = ser.GetAnime().GetCrossRefMAL(); if (crossRefs == null || crossRefs.Count == 0) { logger.Warn("Could not find MAL link for : {0} ({1})", ser.GetAnime().GetFormattedTitle(), ser.GetAnime().AnimeID); return; } List <SVR_AnimeEpisode> eps = ser.GetAnimeEpisodes(); // find the anidb user List <SVR_JMMUser> aniDBUsers = RepoFactory.JMMUser.GetAniDBUsers(); if (aniDBUsers.Count == 0) { return; } SVR_JMMUser user = aniDBUsers[0]; int score = 0; if (ser.GetAnime().UserVote != null) { score = (int)(ser.GetAnime().UserVote.VoteValue / 100); } // e.g. // AniDB - Code Geass R2 // MAL Equivalent = AniDB Normal Eps 1 - 25 / Code Geass: Hangyaku no Lelouch R2 / hxxp://myanimelist.net/anime/2904/Code_Geass:_Hangyaku_no_Lelouch_R2 // MAL Equivalent = AniDB Special Eps 1 - 9 / Code Geass: Hangyaku no Lelouch R2 Picture Drama / hxxp://myanimelist.net/anime/5163/Code_Geass:_Hangyaku_no_Lelouch_R2_Picture_Drama // MAL Equivalent = AniDB Special Eps 9 - 18 / Code Geass: Hangyaku no Lelouch R2: Flash Specials / hxxp://myanimelist.net/anime/9591/Code_Geass:_Hangyaku_no_Lelouch_R2:_Flash_Specials // MAL Equivalent = AniDB Special Eps 20 / Code Geass: Hangyaku no Lelouch - Kiseki no Birthday Picture Drama / hxxp://myanimelist.net/anime/8728/Code_Geass:_Hangyaku_no_Lelouch_-_Kiseki_no_Birthday_Picture_Drama foreach (CrossRef_AniDB_MAL xref in crossRefs) { // look for the right MAL id int malID = -1; int epNumber = -1; int totalEpCount = -1; List <string> fanSubGroups = new List <string>(); // for each cross ref (which is a series on MAL) we need to update the data // so find all the episodes which apply to this cross ref int lastWatchedEpNumber = 0; int downloadedEps = 0; foreach (SVR_AnimeEpisode ep in eps) { int epNum = ep.AniDB_Episode.EpisodeNumber; if (xref.StartEpisodeType == (int)ep.EpisodeTypeEnum && epNum >= xref.StartEpisodeNumber && epNum <= GetUpperEpisodeLimit(crossRefs, xref)) { malID = xref.MALID; epNumber = epNum - xref.StartEpisodeNumber + 1; // find the total episode count if (totalEpCount < 0) { if (ep.EpisodeTypeEnum == enEpisodeType.Episode) { totalEpCount = ser.GetAnime().EpisodeCountNormal; } if (ep.EpisodeTypeEnum == enEpisodeType.Special) { totalEpCount = ser.GetAnime().EpisodeCountSpecial; } totalEpCount = totalEpCount - xref.StartEpisodeNumber + 1; } // any episodes here belong to the MAL series // find the latest watched episod enumber SVR_AnimeEpisode_User usrRecord = ep.GetUserRecord(user.JMMUserID); if (usrRecord != null && usrRecord.WatchedDate.HasValue && epNum > lastWatchedEpNumber) { lastWatchedEpNumber = epNum; } List <CL_VideoDetailed> contracts = ep.GetVideoDetailedContracts(user.JMMUserID); // find the latest episode number in the collection if (contracts.Count > 0) { downloadedEps++; } foreach (CL_VideoDetailed contract in contracts) { if (!string.IsNullOrEmpty(contract.AniDB_Anime_GroupNameShort) && !fanSubGroups.Contains(contract.AniDB_Anime_GroupNameShort)) { fanSubGroups.Add(contract.AniDB_Anime_GroupNameShort); } } } } string fanSubs = ""; foreach (string fgrp in fanSubGroups) { if (!string.IsNullOrEmpty(fanSubs)) { fanSubs += ","; } fanSubs += fgrp; } // determine status int status = 1; //watching if (animeListHashtable.ContainsKey(malID)) { myanimelistAnime animeInList = (myanimelistAnime)animeListHashtable[malID]; status = animeInList.my_status; } // over-ride is user has watched an episode // don't override on hold (3) or dropped (4) but do override plan to watch (6) if (status == 6 && lastWatchedEpNumber > 0) { status = 1; //watching } if (lastWatchedEpNumber == totalEpCount) { status = 2; //completed } if (lastWatchedEpNumber > totalEpCount) { logger.Error("updateMAL, episode number > matching anime episode total : {0} ({1}) / {2}", ser.GetAnime().GetFormattedTitle(), ser.GetAnime().AnimeID, epNumber); continue; } if (malID <= 0 || totalEpCount <= 0) { logger.Warn("Could not find MAL link for : {0} ({1})", ser.GetAnime().GetFormattedTitle(), ser.GetAnime().AnimeID); continue; } string confirmationMessage = ""; if (animeListHashtable.ContainsKey(malID)) { ModifyAnime(malID, lastWatchedEpNumber, status, score, downloadedEps, fanSubs); confirmationMessage = string.Format( "MAL successfully updated (MAL MODIFY), mal id: {0}, ep: {1}, score: {2}", malID, lastWatchedEpNumber, score); } else { AddAnime(malID, lastWatchedEpNumber, status, score, downloadedEps, fanSubs); confirmationMessage = string.Format( "MAL successfully updated (MAL ADD), mal id: {0}, ep: {1}, score: {2}", malID, lastWatchedEpNumber, score); } logger.Trace(confirmationMessage); } } catch (Exception ex) { logger.Error(ex, ex.ToString()); } }
public override void ProcessCommand() { logger.Info("Processing CommandRequest_MALDownloadStatusFromMAL"); try { if (string.IsNullOrEmpty(ServerSettings.MAL_Username) || string.IsNullOrEmpty(ServerSettings.MAL_Password)) { return; } // find the latest eps to update myanimelist mal = MALHelper.GetMALAnimeList(); if (mal == null || mal.anime == null) { return; } // find the anidb user List <SVR_JMMUser> aniDBUsers = RepoFactory.JMMUser.GetAniDBUsers(); if (aniDBUsers.Count == 0) { return; } SVR_JMMUser user = aniDBUsers[0]; foreach (myanimelistAnime malAnime in mal.anime) { // look up the anime CrossRef_AniDB_MAL xref = RepoFactory.CrossRef_AniDB_MAL.GetByMALID(malAnime.series_animedb_id); if (xref == null) { continue; } if (malAnime.series_animedb_id == 8107 || malAnime.series_animedb_id == 10737) { Console.Write(""); } // check if this anime has any other links List <CrossRef_AniDB_MAL> allXrefs = RepoFactory.CrossRef_AniDB_MAL.GetByAnimeID(xref.AnimeID); if (allXrefs.Count == 0) { continue; } // find the range of watched episodes that this applies to int startEpNumber = xref.StartEpisodeNumber; int endEpNumber = GetUpperEpisodeLimit(allXrefs, xref); List <AniDB_Episode> aniEps = RepoFactory.AniDB_Episode.GetByAnimeID(xref.AnimeID); foreach (AniDB_Episode aniep in aniEps) { if (aniep.EpisodeType != xref.StartEpisodeType) { continue; } SVR_AnimeEpisode ep = RepoFactory.AnimeEpisode.GetByAniDBEpisodeID(aniep.EpisodeID); if (ep == null) { continue; } int adjustedWatchedEps = malAnime.my_watched_episodes + xref.StartEpisodeNumber - 1; int epNum = aniep.EpisodeNumber; if (epNum < startEpNumber || epNum > endEpNumber) { continue; } SVR_AnimeEpisode_User usrRec = ep.GetUserRecord(user.JMMUserID); if (epNum <= adjustedWatchedEps) { // update if the user doesn't have a record (means not watched) // or it is currently un-watched bool update = false; if (usrRec == null) { update = true; } else if (!usrRec.WatchedDate.HasValue) { update = true; } if (update) { ep.ToggleWatchedStatus(true, true, DateTime.Now, user.JMMUserID, false); } } else { if (usrRec != null && usrRec.WatchedDate.HasValue) { ep.ToggleWatchedStatus(false, true, DateTime.Now, user.JMMUserID, false); } } } } } catch (Exception ex) { logger.Error("Error processing CommandRequest_MALDownloadStatusFromMAL: {0}", ex); } }
public override void ProcessCommand() { logger.Info($"Processing CommandRequest_AddFileToMyList: {vid?.FileName} - {Hash} - {ReadStates}"); try { if (vid == null) { return; } // when adding a file via the API, newWatchedStatus will return with current watched status on AniDB // if the file is already on the user's list bool isManualLink = false; List <CrossRef_File_Episode> xrefs = vid.EpisodeCrossRefs.DistinctBy(a => Tuple.Create(a.AnimeID, a.EpisodeID)).ToList(); if (xrefs.Count > 0) { isManualLink = xrefs[0].CrossRefSource != (int)CrossRefSource.AniDB; } // mark the video file as watched List <SVR_JMMUser> aniDBUsers = RepoFactory.JMMUser.GetAniDBUsers(); SVR_JMMUser juser = aniDBUsers.FirstOrDefault(); DateTime? originalWatchedDate = null; if (juser != null) { originalWatchedDate = vid.GetUserRecord(juser.JMMUserID)?.WatchedDate?.ToUniversalTime(); } DateTime?newWatchedDate = null; int? lid = null; // this only gets overwritten if the response is File Already in MyList AniDBFile_State?state = ServerSettings.Instance.AniDb.MyList_StorageState; if (isManualLink) { foreach (var xref in xrefs) { (lid, newWatchedDate) = ShokoService.AnidbProcessor.AddFileToMyList(xref.AnimeID, xref.GetEpisode().EpisodeNumber, originalWatchedDate, ref state); } } else { (lid, newWatchedDate) = ShokoService.AnidbProcessor.AddFileToMyList(vid, originalWatchedDate, ref state); } // never true for Manual Links, so no worries about the loop overwriting it if (lid != null && lid.Value > 0) { vid.MyListID = lid.Value; RepoFactory.VideoLocal.Save(vid); } logger.Info($"Added File to MyList. File: {vid.FileName} Manual Link: {isManualLink} Watched Locally: {originalWatchedDate != null} Watched AniDB: {newWatchedDate != null} Local State: {ServerSettings.Instance.AniDb.MyList_StorageState} AniDB State: {state} ReadStates: {ReadStates} ReadWatched Setting: {ServerSettings.Instance.AniDb.MyList_ReadWatched} ReadUnwatched Setting: {ServerSettings.Instance.AniDb.MyList_ReadUnwatched}"); if (juser != null) { bool watched = newWatchedDate != null; bool watchedLocally = originalWatchedDate != null; bool watchedChanged = watched != watchedLocally; if (ReadStates) { // handle import watched settings. Don't update AniDB in either case, we'll do that with the storage state if (ServerSettings.Instance.AniDb.MyList_ReadWatched && watched && !watchedLocally) { vid.ToggleWatchedStatus(true, false, newWatchedDate, false, juser.JMMUserID, false, false); } else if (ServerSettings.Instance.AniDb.MyList_ReadUnwatched && !watched && watchedLocally) { vid.ToggleWatchedStatus(false, false, null, false, juser.JMMUserID, false, false); } } // We should have a MyListID at this point, so hopefully this will prevent looping if (watchedChanged || state != ServerSettings.Instance.AniDb.MyList_StorageState) { // if vid.MyListID > 0, isManualLink _should_ always be false, but _should_ isn't good enough if (vid.MyListID > 0 && !isManualLink) { if (ServerSettings.Instance.AniDb.MyList_SetWatched && watchedLocally) { ShokoService.AnidbProcessor.UpdateMyListFileStatus(vid, true, originalWatchedDate); } else if (ServerSettings.Instance.AniDb.MyList_SetUnwatched && !watchedLocally) { ShokoService.AnidbProcessor.UpdateMyListFileStatus(vid, false); } } else if (isManualLink) { foreach (var xref in xrefs) { if (ServerSettings.Instance.AniDb.MyList_SetWatched && watchedLocally) { ShokoService.AnidbProcessor.UpdateMyListFileStatus(vid, xref.AnimeID, xref.GetEpisode().EpisodeNumber, true, originalWatchedDate); } else if (ServerSettings.Instance.AniDb.MyList_SetUnwatched && !watchedLocally) { ShokoService.AnidbProcessor.UpdateMyListFileStatus(vid, xref.AnimeID, xref.GetEpisode().EpisodeNumber, false); } } } } } // if we don't have xrefs, then no series or eps. if (xrefs.Count <= 0) { return; } SVR_AnimeSeries ser = RepoFactory.AnimeSeries.GetByAnimeID(xrefs[0].AnimeID); // all the eps should belong to the same anime ser.QueueUpdateStats(); //StatsCache.Instance.UpdateUsingSeries(ser.AnimeSeriesID); // lets also try adding to the users trakt collecion if (ServerSettings.Instance.TraktTv.Enabled && !string.IsNullOrEmpty(ServerSettings.Instance.TraktTv.AuthToken)) { foreach (SVR_AnimeEpisode aep in vid.GetAnimeEpisodes()) { CommandRequest_TraktCollectionEpisode cmdSyncTrakt = new CommandRequest_TraktCollectionEpisode(aep.AnimeEpisodeID, TraktSyncAction.Add); cmdSyncTrakt.Save(); } } } catch (Exception ex) { logger.Error($"Error processing CommandRequest_AddFileToMyList: {Hash} - {ex}"); } }