private bool IsDuplicateInput(PublicMessageEventArgs e) { // clean up the input, lowercase it and replace all consecutive non-readable characters to a single _ string str = Regex.Replace($"{e.Message?.Text}{e.Message?.Caption}".ToLowerInvariant(), "[^a-zA-Z0-9]*", "_"); if (str.Length < 256) { return(false); } var hash = HashUtils.CalculateSHA1Hash(str); var hashCollection = DB.GetCollection <MessageHash>(); hashCollection.Delete(x => (DateTime.UtcNow - x.UtcWhen) > TimeSpan.FromDays(3)); // keep it clean var hashRecord = hashCollection.Find(x => x.Hash == hash).FirstOrDefault(); if (hashRecord != null) { InsultUserForCopyPasting(e, hashRecord); return(true); } else { hashRecord = new MessageHash { Hash = hash, User = e.Message.From, UtcWhen = DateTime.UtcNow, MessageID = e.Message.MessageID, ChatID = e.Message.Chat.ID }; hashCollection.Insert(hashRecord); _log.Info($"{e.Message.From.ShortName()} just sent a long message with hash {hash}, which I promptly stored."); return(false); } }
private void Run() { var channelID = Settings.PublicationChannel.Value; _log.Info($"Starting worker thread for {nameof(SummarizeActiveRaids)}"); while (!_cts.IsCancellationRequested) { _log.Info("Run"); try { if (DateTime.UtcNow.Hour >= 21 || DateTime.UtcNow.Hour < 4) { _log.Trace($"Skipping summary update cycle because the server rests."); continue; } var publishedRaids = DB.GetCollection <RaidParticipation>().Find(x => x.Raid != null && x.Raid.RaidEndTime >= DateTime.UtcNow && x.Raid.RaidUnlockTime <= (DateTime.UtcNow + TimeSpan.FromHours(1)) && x.IsPublished).ToArray(); List <long> channels = new List <long> { Settings.PublicationChannel ?? 0 }; // (only main channel) channels.AddRange(publishedRaids.SelectMany(r => r.Raid?.Publications?.Select(x => x.ChannelID) ?? new long[] { })); // Restricted to only the main channel. All other channels are managed separately by different code. foreach (var channel in channels.Distinct().ToArray()) { StringBuilder message = new StringBuilder(); var raidsForChannel = publishedRaids.Where(x => (channel == Settings.PublicationChannel) && x.IsPublished).ToArray(); foreach (var raid in raidsForChannel.OrderBy(x => x.Raid.RaidEndTime)) { string url = $"{Settings.BotAddress}raids/{raid.PublicID}"; message.AppendLine($"{TimeService.AsShortTime(raid.Raid.RaidUnlockTime)}: {_HTML_(raid.Raid.Raid)} @ {_HTML_(raid.Raid.Gym)} ({raid.NumberOfParticipants()})\r\n<a href=\"{url}\">Online inschrijven (nieuw)</a>"); } var updateRecord = DB.GetCollection <ChannelUpdateMessage>().Find(x => x.ChannelID == channel).FirstOrDefault(); if (null == updateRecord) { updateRecord = new ChannelUpdateMessage { ChannelID = channel, MessageID = long.MaxValue, Hash = string.Empty }; DB.GetCollection <ChannelUpdateMessage>().Insert(updateRecord); } var hash = HashUtils.CalculateSHA1Hash(message.ToString()); if (!string.Equals(hash, updateRecord.Hash) /*|| (DateTime.UtcNow - updateRecord.LastModificationDate > TimeSpan.FromSeconds(60))*/) { if (NewRaidPosted || updateRecord.MessageID == long.MaxValue) { NewRaidPosted = false; // A new message was posted or the summary was never posted yet, delete the current message and posty a new summary if (updateRecord.MessageID != long.MaxValue) { try { Client.DeleteMessage(channel, updateRecord.MessageID); updateRecord.MessageID = long.MaxValue; updateRecord.Hash = hash; } catch (Exception ex) { _log.Warn(ex, $"Could not delete summary-message {updateRecord.MessageID} from channel {channel}"); } } try { var postedMessage = Client.SendMessageToChat(channel, message.ToString(), "HTML", true, true, null, null); if (null != postedMessage) { updateRecord.MessageID = postedMessage.MessageID; } else { _log.Warn($"Could not post summary-message to channel {channel} - null reply"); } } catch (Exception ex) { _log.Warn(ex, $"Could not post summary-message to channel {channel}"); } } else if (updateRecord.MessageID != long.MaxValue) { // There is no new raid posted, so update the current one Client.EditMessageText($"{channel}", updateRecord.MessageID, null, message.ToString(), "HTML", true, null, "channel"); updateRecord.Hash = hash; } } updateRecord.LastModificationDate = DateTime.UtcNow; DB.GetCollection <ChannelUpdateMessage>().Update(updateRecord); } } catch (ThreadAbortException) { _log.Info($"Abort requested for thread."); break; } catch (Exception ex) { _log.Error(ex, "Error in SummarizeActiveRaids thread. Ignoring."); } finally { Thread.Sleep(Interval); } } _log.Info($"Stopped worker thread for {nameof(SummarizeActiveRaids)}"); }