private static Embed CreateEmbed(AnnounceModel announceModel) { var title = announceModel.AnimeGuildModel.AnimeTitle; var embedBuilder = new EmbedBuilder() .WithTitle($"Episode {announceModel.Episode} of {title.EnglishTitle ?? title.RomajiTitle} just came out!"); var links = new StringBuilder(); foreach (var q in announceModel.QualityLinks) { if (q.Value.Link == null) { continue; } string subgroup = q.Value.Subgroup == null ? "" : $"[{q.Value.Subgroup}]"; links.AppendLine($"[{subgroup} - {QualityString.GetQualityString(q.Key)}]({q.Value.Link})"); } string imageLink = null; try { var images = DuckDuckGoImageSearch.SearchImage(announceModel.AnimeGuildModel.AnimeTitle.RomajiTitle); imageLink = images[Program.Randomizer.Next(images.Length)]; } catch (Exception e) { Console.WriteLine(e); } var quote = Quotes.AnnounceQuotes.GetRandomQuote(announceModel.AnimeGuildModel.Guild); if (quote != null) { embedBuilder.AddField(x => { x.Name = $"Wise words of {quote.Author}"; x.Value = quote.Message; }); } if (imageLink != null) { embedBuilder.ImageUrl = imageLink; } embedBuilder.Description = links.ToString(); embedBuilder.Color = new Color(255, 255, 255); return(embedBuilder.Build()); }
private static async Task AnnounceEdit(AnnounceModel announceModel) { var originalEmbed = announceModel.AnnouncedMessage.Embeds.First(); var embed = CreateEmbed(announceModel); embed = originalEmbed.ToEmbedBuilder().WithDescription(embed.Description).Build(); if (!AnnouncedAnime.TryGetValue(announceModel.AnimeGuildModel.AnimeID, out var model) || model.AnnouncedMessage == null) { return; } await model.AnnouncedMessage.ModifyAsync(x => x.Embed = embed); }
public static void UpdateAnime(AnnounceModel announceModel) { if (!AnnouncedAnime.ContainsKey(announceModel.AnimeGuildModel.AnimeID)) { // If it doesn't contain the key, it's very simple. Just add it, // and then add the self destruct anonymous method. // check if the subgroup is even correct var(subgroup, _, _) = GetSubgroupFromAnnounceModel(announceModel); if (subgroup == null || !announceModel.AnimeGuildModel .WantedSubgroupTitle.Select(x => x.ToLower()) .Contains(subgroup.ToLower())) { return; } AnnouncedAnime.Add(announceModel.AnimeGuildModel.AnimeID, announceModel); Task.Factory.StartNew(() => { Thread.Sleep(TimeSpan.FromMinutes(20)); AnnouncedAnime.Remove(announceModel.AnimeGuildModel.AnimeID); }).ConfigureAwait(false); } else { // If it does contain the key, it's a bit harder.. var a = AnnouncedAnime[announceModel.AnimeGuildModel.AnimeID]; // Get the important subgroup. the parameter announceModel // will have only 1 correct subgroup. // So we will get the current subgroup and the "new" subgroup and compare them against each other. // If the important subgroup equals the new subgroup, we edit the anime model to be that one. :)) var result = GetSubgroupFromAnnounceModel(announceModel); string newSubgroup = result.Item1; if (result.quality == Quality.Unknown) { return; } string currentSubgroup = a.QualityLinks[result.quality].Subgroup; string importantSubgroup = GetImportantSubgroup(newSubgroup, currentSubgroup, a.AnimeGuildModel); if (string.Equals(importantSubgroup, newSubgroup, StringComparison.CurrentCultureIgnoreCase)) { a.QualityLinks[result.quality] = new SubgroupTorrentLink(result.link, result.subgroup); } } }
public static void Announce(AnnounceModel model) { if (!AnnouncedAnime.TryGetValue(model.AnimeGuildModel.AnimeID, out var anime)) { return; } if (anime.AnnouncedMessage != null) { AnnounceEdit(anime).ConfigureAwait(false); } else if (model.Episode > model.AnimeGuildModel.LastAnnouncedEpisode && anime.AnnouncedMessage == null) { AnnounceNew(model).Wait(); } }
private static async Task AnnounceNew(AnnounceModel model) { var embed = CreateEmbed(model); var mentions = GetMentions(model.AnimeGuildModel); var client = Program.ServiceProvider.GetRequiredService <DiscordSocketClient>(); var guild = client.GetGuild(model.AnimeGuildModel.Guild); var channel = guild?.GetTextChannel(model.AnimeGuildModel.Channel); if (channel == null) { return; // This would be very bad!!! } var message = await channel.SendMessageAsync(mentions, embed : embed); AnnouncedAnime[model.AnimeGuildModel.AnimeID].AnnouncedMessage = message; Quotes.AnnounceQuotes.AddQuoteWaiter(model.AnimeGuildModel); }
/// <summary> /// This method is only for temporary models, which are created by the checker. /// It will find the first correct Quality link where the subgroup is not null, and return it. /// </summary> private static (string subgroup, Quality quality, string link) GetSubgroupFromAnnounceModel(AnnounceModel announceModel) { foreach (var q in announceModel.QualityLinks) { if (q.Value.Link != null) { return(q.Value.Subgroup, q.Key, q.Value.Link); } } return(null, Quality.Unknown, null); // I mean... this should theoratically not happen... but ehh... }
/// <summary> /// Performs the actual check for the anime /// </summary> /// <returns>true if something has been found</returns> public static async Task <bool> Check() { // get the XML, and parse it var xml = await NyaaRSSFeed.GetRSSFeed(); var parsedXML = NyaaXMLConverter.ParseXML(xml); NyaaTorrentModel[] rawTorrents = NyaaXMLConverter.GetTorrents(parsedXML); string lastChecked = Database.Database.GetLastChecked(); ParsedNyaaTorrentModel[] parsedTorrents = NyaaParser.ParseNyaaTorrents(rawTorrents) .TakeWhile(x => x.NyaaTorrentModel.InfoHash != lastChecked).ToArray(); // if the list is empty, return false. if (parsedTorrents.Length == 0) { return(false); } // set the lastChecked to the first occurence fiaojfoiasoi jdsfjsdoif doisf Database.Database.SetLastChecked(parsedTorrents[0].NyaaTorrentModel.InfoHash); // get ALL EPIC ANIME var(_, collection) = Database.Database.GetDatabaseAndSubscriptionCollection(); var guildAnimes = collection.FindAll().ToList(); var animeToAnnounce = new List <AnnounceModel>(); bool foundSomething = false; foreach (var parsedTorrent in parsedTorrents) { // if the title is correct, add it to the update list. var validAnime = guildAnimes.Where(x => { bool valid = true; const double minSim = 0.55; double confidence = Math.Max( (x.AnimeTitle.EnglishTitle ?? "").ToLower().GetSimilarity((parsedTorrent.AnimeTitle ?? "").ToLower()), x.AnimeTitle.RomajiTitle.ToLower().GetSimilarity((parsedTorrent.AnimeTitle ?? "").ToLower())); valid = confidence >= minSim; valid = valid && x.WantedSubgroupTitle.Contains(parsedTorrent.SubGroup.ToLower()); valid = valid && parsedTorrent.Episode >= x.LastAnnouncedEpisode; return(valid); }); foreach (var anime in validAnime) { var m = new AnnounceModel() { AnimeGuildModel = anime, Episode = parsedTorrent.Episode }; if (parsedTorrent.Quality != Quality.Unknown) { m.QualityLinks[parsedTorrent.Quality] = new SubgroupTorrentLink(parsedTorrent.NyaaTorrentModel.Link, parsedTorrent.SubGroup); } if (!animeToAnnounce.Any(x => x.AnimeGuildModel.AnimeID == anime.AnimeID && animeToAnnounce.Any(y => y.AnimeGuildModel.Guild == x.AnimeGuildModel.Guild))) { animeToAnnounce.Add(m); } AnimeReminderAnnouncer.UpdateAnime(m); foundSomething = true; } } foreach (var anime in animeToAnnounce) { AnimeReminderAnnouncer.Announce(anime); anime.AnimeGuildModel.LastAnnouncedEpisode = anime.Episode; collection.Update(anime.AnimeGuildModel); } return(foundSomething); }
// // GET: /Announce/Announce/ // GET: /announce/123af0c917876f6d4711654b2293895f public ActionResult Announce(AnnounceModel announceModel) { if (!announceModel.IsValidRequest()) { return(new BTErrorResult("Invalid request (see specification: http://bit.ly/bcYmSu)")); } if (!Regex.IsMatch(announceModel.Passkey, "[0-9a-fA-F]{32}")) { return(new BTErrorResult("Invalid passkey.")); } if (BLACKLIST_PORTS && IsPortBlackListed(Convert.ToInt32(announceModel.port))) { return(new BTErrorResult(string.Format("Port {0} is blacklisted", announceModel.port))); } try { using (var context = new OpenTrackerDbContext()) { var crntUser = (from u in context.users where u.passkey == announceModel.Passkey select u).Take(1).FirstOrDefault(); if (crntUser == null) { return(new BTErrorResult(string.Format("Unknown passkey. Please re-download the torrent from {0}.", TrackerSettings.BASE_URL))); } if (crntUser.activated == 0) { return(new BTErrorResult("Permission denied, you\'re not activated.")); } var seeder = false; if (announceModel.left == 0) { seeder = true; } // Entity Framework does not support BINARY keys var EncodedPeerId = Convert.ToBase64String(Encoding.ASCII.GetBytes(announceModel.peer_id)); var EncodedInfoHash = BEncoder.FormatUrlInfoHash(); var torrentExist = (from t in context.torrents where t.info_hash == EncodedInfoHash select t).Take(1).FirstOrDefault(); if (torrentExist == null) { return(new BTErrorResult("Torrent not registered with this tracker.")); } var peerAlreadyExist = (from t in context.peers where t.torrentid == torrentExist.id && t.peer_id == EncodedPeerId && t.passkey == announceModel.Passkey select t).Take(1); var existingPeerCount = peerAlreadyExist.Count(); peers p; if (existingPeerCount == 1) { p = peerAlreadyExist.First(); } else { var connectionLimit = (from t in context.peers where t.torrentid == torrentExist.id && t.passkey == announceModel.Passkey select t).Count(); if (connectionLimit >= 1 && !seeder) { return(new BTErrorResult("Connection limit exceeded! " + "You may only leech from one location at a time.")); } if (connectionLimit >= 3 && seeder) { return(new BTErrorResult("Connection limit exceeded.")); } if (announceModel.left > 0 && crntUser.@class < (decimal)AccountValidation.Class.Administrator) { var epoch = Unix.ConvertToUnixTimestamp(DateTime.UtcNow); var elapsed = Math.Floor((epoch - torrentExist.added) / 3600); var uploadedGigs = crntUser.uploaded / (1024 * 1024 * 1024); var ratio = ((crntUser.downloaded > 0) ? (crntUser.uploaded / crntUser.downloaded) : 1); int wait; if (ratio < (decimal)0.5 || uploadedGigs < 5) { wait = 48; } else if (ratio < (decimal)0.65 || uploadedGigs < (decimal)6.5) { wait = 24; } else if (ratio < (decimal)0.8 || uploadedGigs < 8) { wait = 12; } else if (ratio < (decimal)0.95 || uploadedGigs < (decimal)9.5) { wait = 6; } else { wait = 0; } if (elapsed < wait) { return(new BTErrorResult(string.Format("Not authorized (wait {0}h) - READ THE FAQ!", (wait - elapsed)))); } } p = new peers { torrentid = torrentExist.id, peer_id = EncodedPeerId, userid = crntUser.id, passkey = announceModel.Passkey, useragent = Request.UserAgent }; } var remoteHost = Request.ServerVariables["REMOTE_HOST"]; var ip = !string.IsNullOrEmpty(announceModel.ip) ? announceModel.ip : remoteHost; if (CHECK_CONNECTABLE) { p.connectable = IsConnectable(ip, Convert.ToInt32(announceModel.port)) ? 1 : 0; } if (announceModel.left != null) { p.left = (decimal)announceModel.left; } p.port = Convert.ToInt32(announceModel.port); p.ip = ip; p.seeding = seeder ? 1 : 0; if (existingPeerCount == 0) { context.AddTopeers(p); } else { if (crntUser.@class < (decimal)AccountValidation.Class.Administrator) { var nonUpdatedPeer = peerAlreadyExist.First(); var thisUploaded = (announceModel.uploaded - nonUpdatedPeer.uploaded); var thisDownloaded = (announceModel.downloaded - nonUpdatedPeer.downloaded); p.uploaded += (decimal)thisUploaded; p.downloaded += (decimal)thisDownloaded; if (thisUploaded > 0) { crntUser.uploaded = (crntUser.uploaded + Convert.ToInt64(thisUploaded)); } if (thisDownloaded > 0) { crntUser.downloaded = (crntUser.downloaded + Convert.ToInt64(thisDownloaded)); } } if (announceModel.Event == "completed") { torrentExist.snatches = torrentExist.snatches + 1; // torrentExist.snatches++; } } context.SaveChanges(); if (announceModel.Event == "stopped") { var removePeer = (from pr in context.peers where pr.torrentid == torrentExist.id && pr.peer_id == EncodedPeerId select pr).Take(1).FirstOrDefault(); context.peers.DeleteObject(removePeer); context.SaveChanges(); var announceResultStop = new AnnounceResult { Interval = ANNOUNCE_INTERVAL }; return(announceResultStop); } var announceResult = new AnnounceResult { Interval = ANNOUNCE_INTERVAL }; var existingPeers = (from t in context.peers where t.torrentid == torrentExist.id select t).ToList(); foreach (var peer in existingPeers) { announceResult.AddPeer(peer.peer_id, peer.ip, peer.port); } return(announceResult); } } catch (Exception) { return(new BTErrorResult("Database unavailable")); } }