protected override UDPBaseResponse <ResponseVote> ParseResponse(UDPReturnCode code, string receivedData) { string[] parts = receivedData.Split('|'); if (parts.Length != 4) { throw new UnexpectedUDPResponseException("Incorrect Number of Parts Returned", code, receivedData); } if (!int.TryParse(parts[1], out int value)) { throw new UnexpectedUDPResponseException("Value should be an int, but it's not", code, receivedData); } if (!int.TryParse(parts[2], out int type)) { throw new UnexpectedUDPResponseException("Vote type should be an int, but it's not", code, receivedData); } if (!int.TryParse(parts[3], out int id)) { throw new UnexpectedUDPResponseException("ID should be an int, but it's not", code, receivedData); } return(new UDPBaseResponse <ResponseVote> { Code = code, Response = new ResponseVote { EntityName = parts[0], Value = value, Type = (VoteType)type, EntityID = id } }); }
public UnexpectedUDPResponseException(string message, UDPReturnCode code, string response) : base( $"Unexpected AniDB Response: {message} -- {code} | {response}") { Response = response; ReturnCode = code; Message = message; }
protected override UDPBaseResponse <ResponseMyListStats> ParseResponse(UDPReturnCode code, string receivedData) { var parsedData = receivedData.Split('|').Select(a => !long.TryParse(a.Trim(), out var result) ? 0 : result) .ToArray(); // 222 MYLIST STATS // 281|3539|4025|1509124|0|0|0|0|100|100|0|3|5|170|23|0|4001 ResponseMyListStats stats = new ResponseMyListStats { Anime = (int)parsedData[0], Episodes = (int)parsedData[1], Files = (int)parsedData[2], SizeOfFiles = parsedData[3], AddedAnime = (int)parsedData[4], AddedEpisodes = (int)parsedData[5], AddedFiles = (int)parsedData[6], AddedGroups = (int)parsedData[7], LeechPercent = (int)parsedData[8], GloryPercent = (int)parsedData[9], ViewedPercent = (int)parsedData[10], MyListPercent = (int)parsedData[11], ViewedMyListPercent = (int)parsedData[12], EpisodesViewed = (int)parsedData[13], Votes = (int)parsedData[14], Reviews = (int)parsedData[15], ViewedLength = parsedData[16] }; return(new UDPBaseResponse <ResponseMyListStats> { Code = code, Response = stats }); }
protected override UDPBaseResponse <Void> ParseResponse(UDPReturnCode code, string receivedData) { if (code != UDPReturnCode.PONG) { throw new UnexpectedUDPResponseException(code, receivedData); } return(new UDPBaseResponse <Void> { Code = code }); }
protected override UDPBaseResponse <Void> ParseResponse(UDPReturnCode code, string receivedData) { switch (code) { case UDPReturnCode.MYLIST_ENTRY_EDITED: case UDPReturnCode.NO_SUCH_MYLIST_ENTRY: return(new UDPBaseResponse <Void> { Code = code }); } throw new UnexpectedUDPResponseException(code, receivedData); }
protected override UDPBaseResponse <ResponseLogin> ParseResponse(UDPReturnCode code, string receivedData) { int i = receivedData.IndexOf("LOGIN", StringComparison.Ordinal); if (i < 0) { throw new UnexpectedUDPResponseException(code, receivedData); } // after response code, before "LOGIN" string sessionID = receivedData.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Skip(1).FirstOrDefault(); if (string.IsNullOrWhiteSpace(sessionID)) { throw new UnexpectedUDPResponseException(code, receivedData); } string imageServer = receivedData.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault(); return(new UDPBaseResponse <ResponseLogin> { Response = new ResponseLogin { SessionID = sessionID, ImageServer = imageServer }, Code = code }); }
protected override UDPBaseResponse <ResponseAddFile> ParseResponse(UDPReturnCode code, string receivedData) { switch (code) { case UDPReturnCode.MYLIST_ENTRY_ADDED: { /* Response Format * {int4 mylist id of new entry} */ // parse the MyList ID string[] arrResult = receivedData.Split('\n'); if (arrResult.Length >= 2) { int.TryParse(arrResult[1], out int myListID); return(new UDPBaseResponse <ResponseAddFile> { Code = code, Response = new ResponseAddFile { MyListID = myListID, State = State, IsWatched = IsWatched, WatchedDate = WatchedDate } }); } break; } case UDPReturnCode.FILE_ALREADY_IN_MYLIST: { /* Response Format * {int4 lid}|{int4 fid}|{int4 eid}|{int4 aid}|{int4 gid}|{int4 date}|{int2 state}|{int4 viewdate}|{str storage}|{str source}|{str other}|{int2 filestate} */ //file already exists: read 'watched' status string[] arrResult = receivedData.Split('\n'); if (arrResult.Length >= 2) { string[] arrStatus = arrResult[1].Split('|'); bool hasMyListID = int.TryParse(arrStatus[0], out int myListID); if (!hasMyListID) { throw new UnexpectedUDPResponseException { Message = "MyListID was not provided. Use AniDBMyList_RequestAddEpisode for generic files.", Response = receivedData, ReturnCode = code } } ; GetFile_State state = (GetFile_State)int.Parse(arrStatus[6]); int viewdate = int.Parse(arrStatus[7]); bool watched = viewdate > 0; DateTime?watchedDate = null; if (watched) { DateTime utcDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); utcDate = utcDate.AddSeconds(viewdate); watchedDate = utcDate.ToLocalTime(); } return(new UDPBaseResponse <ResponseAddFile> { Code = code, Response = new ResponseAddFile { MyListID = myListID, State = state, IsWatched = watched, WatchedDate = watchedDate } }); } break; } } throw new UnexpectedUDPResponseException(code, receivedData); } }
protected override UDPBaseResponse <Void> ParseResponse(UDPReturnCode code, string receivedData) { return(new UDPBaseResponse <Void> { Code = code }); }
protected override UDPBaseResponse <ResponseAddFile> ParseResponse(UDPReturnCode code, string receivedData) { switch (code) { case UDPReturnCode.MYLIST_ENTRY_ADDED: { // We're adding a generic file, so it won't return a MyListID return(new UDPBaseResponse <ResponseAddFile> { Code = code, Response = new ResponseAddFile { State = State, IsWatched = IsWatched, WatchedDate = WatchedDate } }); } case UDPReturnCode.FILE_ALREADY_IN_MYLIST: { /* Response Format * {int4 lid}|{int4 fid}|{int4 eid}|{int4 aid}|{int4 gid}|{int4 date}|{int2 state}|{int4 viewdate}|{str storage}|{str source}|{str other}|{int2 filestate} */ //file already exists: read 'watched' status string[] arrResult = receivedData.Split('\n'); if (arrResult.Length >= 2) { string[] arrStatus = arrResult[1].Split('|'); // We expect 0 for a MyListID int.TryParse(arrStatus[0], out int myListID); GetFile_State state = (GetFile_State)int.Parse(arrStatus[6]); int viewdate = int.Parse(arrStatus[7]); bool watched = viewdate > 0; DateTime?watchedDate = null; if (watched) { DateTime utcDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); utcDate = utcDate.AddSeconds(viewdate); watchedDate = utcDate.ToLocalTime(); } return(new UDPBaseResponse <ResponseAddFile> { Code = code, Response = new ResponseAddFile { MyListID = myListID, State = state, IsWatched = watched, WatchedDate = watchedDate } }); } break; } } throw new UnexpectedUDPResponseException(code, receivedData); }
protected override UDPBaseResponse <ResponseCalendar> ParseResponse(UDPReturnCode code, string receivedData) { if (code == UDPReturnCode.CALENDAR_EMPTY) { return new UDPBaseResponse <ResponseCalendar> { Response = null, Code = code } } ; var calendar = new ResponseCalendar { Next25Anime = new List <ResponseCalendar.CalendarEntry>(), Previous25Anime = new List <ResponseCalendar.CalendarEntry>() }; foreach (var parts in receivedData.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries) .Select(line => line.Split('\n'))) { if (parts.Length != 3) { continue; } if (!int.TryParse(parts[0], out int animeID)) { continue; } if (!int.TryParse(parts[1], out int epochElapsed)) { continue; } if (!int.TryParse(parts[2], out int flagInt)) { continue; } var flags = (ResponseCalendar.CalendarFlags)flagInt; var date = Commons.Utils.AniDB.GetAniDBDateAsDate(epochElapsed); var entry = new ResponseCalendar.CalendarEntry { AnimeID = animeID, ReleaseDate = date, DateFlags = flags }; bool known = !flags.HasFlag(ResponseCalendar.CalendarFlags.StartUnknown) && !flags.HasFlag(ResponseCalendar.CalendarFlags.StartDayUnknown) && !flags.HasFlag(ResponseCalendar.CalendarFlags.StartMonthDayUnknown); if (known && date.HasValue && date.Value < DateTime.UtcNow.Date) { calendar.Previous25Anime.Add(entry); } else { calendar.Next25Anime.Add(entry); } } return(new UDPBaseResponse <ResponseCalendar> { Response = calendar, Code = code }); } }
protected override UDPBaseResponse <ResponseReleaseGroup> ParseResponse(UDPReturnCode code, string receivedData) { switch (code) { case UDPReturnCode.GROUP: { // {int gid}|{int4 rating}|{int votes}|{int4 acount}|{int fcount}|{str name}|{str short}|{str irc channel}|{str irc server}|{str url}|{str picname}|{int4 foundeddate}|{int4 disbandeddate}|{int2 dateflags}|{int4 lastreleasedate}|{int4 lastactivitydate}|{list grouprelations} /* * dateflags values: * bit0 set == Foundeddate, Unknown Day * bit1 set == Foundeddate, Unknown Month, Day * bit2 set == Disbandeddate, Unknown Day * bit3 set == Disbandeddate, Unknown Month, Day * bit5 set == Foundeddate, Unknown Year * bit6 set == Disbandeddate, Unknown Year * releasedate and activitydate are distinct. releasedate is the date a file was actually released by the group, where activitydate is the date of a file being added to AniDB. As such, lastrelease may very well be much older than lastactivity. * groupreleations is a list of apostrophe-separated pairs, where each pair consists of {int4 othergroupid},{int2 relationtype} * relationtype: * 1 => "Participant in" * 2 => "Parent of" * 4 => "Merged from" * 5 => "Now known as" * 6 => "Other" */ string[] parts = receivedData.Split('|').Select(a => a.Trim()).ToArray(); if (!int.TryParse(parts[0], out int gid)) { throw new UnexpectedUDPResponseException("Group ID was not an int", code, receivedData); } if (!int.TryParse(parts[1], out int intRating)) { throw new UnexpectedUDPResponseException("Rating was not an int", code, receivedData); } decimal rating = intRating / 100M; if (!int.TryParse(parts[2], out int votes)) { throw new UnexpectedUDPResponseException("Votes was not an int", code, receivedData); } if (!int.TryParse(parts[3], out int aCount)) { throw new UnexpectedUDPResponseException("Anime Count was not an int", code, receivedData); } if (!int.TryParse(parts[4], out int fCount)) { throw new UnexpectedUDPResponseException("File Count was not an int", code, receivedData); } var name = parts[5]; var shortName = parts[6]; var ircChannel = parts[7]; var ircServer = parts[8]; var url = parts[9]; var pic = parts[10]; return(new UDPBaseResponse <ResponseReleaseGroup>() { Code = code, Response = new ResponseReleaseGroup { ID = gid, Rating = rating, Votes = votes, AnimeCount = aCount, FileCount = fCount, Name = name, ShortName = shortName, IrcChannel = ircChannel, IrcServer = ircServer, URL = url, Picture = pic } }); } case UDPReturnCode.NO_SUCH_GROUP: { return(new UDPBaseResponse <ResponseReleaseGroup>() { Code = code, Response = null }); } default: throw new UnexpectedUDPResponseException(code, receivedData); } }
protected abstract UDPBaseResponse <T> ParseResponse(UDPReturnCode code, string receivedData);
public UnexpectedUDPResponseException(UDPReturnCode code, string response) : base( $"Unexpected AniDB Response: {code} | {response}") { Response = response; ReturnCode = code; }