protected virtual Random ChosenRNG(CommandMatch cmd) { return((cmd.Options.Any(o => o.Key == "--crypto")) ? CryptoRNG : RNG ); }
protected virtual bool CheckAndHandleCooldown(CommandMatch cmd, IChannelMessageEventArgs args) { if (Config.CooldownUpperBoundary < 0) { // the cooldown feature is not being used return(false); } CooldownState cdState; if (!ChannelToCooldown.TryGetValue(args.Channel, out cdState)) { cdState = new CooldownState(); ChannelToCooldown[args.Channel] = cdState; } cdState.CooldownValue += Config.CooldownPerCommandUsage; bool coolingDown = (cdState.CooldownTriggered) ? (cdState.CooldownValue > 0) : (cdState.CooldownValue > Config.CooldownUpperBoundary); if (coolingDown) { cdState.CooldownTriggered = true; string cdAnswer = Config.CooldownAnswers[ChosenRNG(cmd).Next(Config.CooldownAnswers.Count)]; ConnectionManager.SendChannelMessageFormat(args.Channel, "{0}: {1}", args.SenderNickname, cdAnswer); return(true); } return(false); }
protected virtual void HandleAddQuoteCommand(CommandMatch cmd, IChannelMessageEventArgs msg) { string normalizedNick = ConnectionManager.RegisteredNameForNick(msg.SenderNickname) ?? msg.SenderNickname; using (var ctx = GetNewContext()) { var newFreeFormQuote = new Quote { Timestamp = DateTime.Now.ToUniversalTimeForDatabase(), Channel = msg.Channel, Author = normalizedNick, MessageType = "F", Body = (string)cmd.Arguments[0] }; ctx.Quotes.Add(newFreeFormQuote); ctx.SaveChanges(); LastQuoteIDs[msg.Channel] = newFreeFormQuote.ID; } ConnectionManager.SendChannelMessage( msg.Channel, "Done." ); // invalidate these ShuffledAnyQuotes = null; ShuffledBadQuotes = null; ShuffledGoodQuotes = null; }
protected virtual void HandleQuoteUserCommand(CommandMatch cmd, IUserMessageEventArgs msg) { Action <string> postReply; string location; QuoteRating rating; bool addMyRating; GetReplyActionAndLocationForMessage(msg, out postReply, out location); if (!FlagsToQuoteFilter(cmd, out rating, out addMyRating)) { // invalid flags return; } var nick = (string)cmd.Arguments[0]; string lowercaseNick = nick.ToLowerInvariant(); using (var ctx = GetNewContext()) { IQueryable <Quote> quotesWithVotes = ctx.Quotes .Include(q => q.Votes) .Where(q => q.Author.ToLower() == lowercaseNick); PostRandomQuote(msg.SenderNickname, location, quotesWithVotes, rating, addMyRating, postReply); } }
public CommandContext(ProcessRequest request, StringBuilder text, CommandMatch match, Dictionary <string, string> vars) { FromRequest = request; Text = text; Match = match; Vars = vars; }
protected virtual void HandleRegexCountCommand(CommandMatch cmd, IChannelMessageEventArgs msg) { var counterName = (string)cmd.Arguments[0]; var nick = (string)cmd.Arguments[1]; string regexString = ((string)cmd.Arguments[2]).Trim(); Counter counter = Config.Counters.FirstOrDefault(c => c.CommandName == counterName); if (counter == null) { ConnectionManager.SendChannelMessage(msg.Channel, $"{msg.SenderNickname}: Unknown counter '{counterName}'"); return; } Regex regex; try { regex = new Regex(regexString, RegexOptions.Compiled); } catch (ArgumentException ae) { ConnectionManager.SendChannelMessage(msg.Channel, $"{msg.SenderNickname}: Invalid regex: {ae.Message}"); return; } TryToMatch(counter, msg.Channel, msg.SenderNickname, messageSubstring: null, messageRegex: regex); }
protected virtual void HandleTopGratefulCommand(CommandMatch cmd, IChannelMessageEventArgs msg) { List <NicknameAndCount> top; using (var ctx = GetNewContext()) { top = ctx.ThanksEntries .Where(te => !te.Deleted) .GroupBy(te => te.ThankerLowercase, (thanker, thanksEntries) => new NicknameAndCount { Nickname = thanker, Count = thanksEntries.Count() }) .OrderByDescending(teg => teg.Count) .Take(Config.MostThankedCount) .ToList() ; } ConnectionManager.SendChannelMessageFormat( msg.Channel, "{0}: {1}", msg.SenderNickname, top.Select(NicknameAndCountString).StringJoin(", ") ); }
private void HandleWDYTICommandInQuery(CommandMatch cmd, IPrivateMessageEventArgs msg) { HandleMessage( (string)cmd.Arguments[0], body => ConnectionManager.SendQueryMessage(msg.SenderNickname, body) ); }
protected virtual void HandleDealCommand(CommandMatch cmd, IChannelMessageEventArgs msg) { if (msg.Channel != Config.UnoChannel) { return; } lock (TurnLock) { switch (CurrentGameState) { case GameState.NoGame: Logger.LogDebug("{Nickname} is trying to deal no game", msg.SenderNickname); return; default: Logger.LogError("invalid game state when trying to add player to game"); return; case GameState.Preparation: case GameState.InProgress: // continue below break; } DealGame(); } }
protected virtual void HandleProverbCommand(CommandMatch cmd, IChannelMessageEventArgs args) { var client = new HttpClient { Timeout = TimeSpan.FromSeconds(Config.TimeoutSeconds) }; using (var request = new HttpRequestMessage(HttpMethod.Get, Config.ProverbURI)) { var htmlDoc = new HtmlDocument(); using (var response = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).SyncWait()) using (Stream responseStream = response.Content.ReadAsStreamAsync().SyncWait()) { htmlDoc.Load(responseStream); } string proverb = htmlDoc.DocumentNode .SelectSingleNode(Config.NodeSelector) ?.InnerText; if (proverb != null) { ConnectionManager.SendChannelMessage(args.Channel, $"{args.SenderNickname}: {proverb}"); } } }
protected virtual void HandleNextQuoteCommand(CommandMatch cmd, IUserMessageEventArgs msg) { Action <string> postReply; string location; QuoteRating rating; bool addMyRating; GetReplyActionAndLocationForMessage(msg, out postReply, out location); if (!FlagsToQuoteFilter(cmd, out rating, out addMyRating)) { // invalid flags return; } using (var ctx = GetNewContext()) { Quote quote = null; switch (rating) { case QuoteRating.Any: if (ShuffledAnyQuotes == null) { ShuffledAnyQuotes = GetFilteredQuotes(ctx.Quotes.Include(q => q.Votes), QuoteRating.Any) .ToShuffledList(); ShuffledAnyQuotesIndex = 0; } quote = ShuffledAnyQuotes[ShuffledAnyQuotesIndex++]; ShuffledAnyQuotesIndex %= ShuffledAnyQuotes.Count; break; case QuoteRating.High: if (ShuffledGoodQuotes == null) { ShuffledGoodQuotes = GetFilteredQuotes(ctx.Quotes.Include(q => q.Votes), QuoteRating.High) .ToShuffledList(); ShuffledGoodQuotesIndex = 0; } quote = ShuffledGoodQuotes[ShuffledGoodQuotesIndex++]; ShuffledGoodQuotesIndex %= ShuffledGoodQuotes.Count; break; case QuoteRating.Low: if (ShuffledBadQuotes == null) { ShuffledBadQuotes = GetFilteredQuotes(ctx.Quotes.Include(q => q.Votes), QuoteRating.Low) .ToShuffledList(); ShuffledBadQuotesIndex = 0; } quote = ShuffledBadQuotes[ShuffledBadQuotesIndex++]; ShuffledBadQuotesIndex %= ShuffledBadQuotes.Count; break; default: Debug.Fail("unexpected quote rating"); break; } PostQuote(quote, msg.SenderNickname, location, addMyRating, postReply); } }
protected virtual void HandleBaseNickCommand(CommandMatch cmd, IChannelMessageEventArgs msg) { string channel = msg.Channel; string requestor = msg.SenderNickname; var whichNick = (string)cmd.Arguments[0]; using (var ctx = GetNewContext()) { var baseNick = FindBaseNickFor(whichNick, ctx); if (baseNick == null) { ConnectionManager.SendChannelMessage( channel, $"{requestor}: I can't find the nickname {whichNick}." ); } else { ConnectionManager.SendChannelMessage( channel, $"{requestor}: The base nickname for {whichNick} is {baseNick}." ); } } }
protected virtual void HandleBotTestCommand(CommandMatch cmd, IChannelMessageEventArgs msg) { if (msg.Channel != Config.UnoChannel) { return; } lock (TurnLock) { BotTestCount = (long)cmd.Arguments[0]; ConnectionManager.SendChannelMessageFormat( Config.UnoChannel, "{0} engaged bot test mode; {1} games left!", msg.SenderNickname, BotTestCount ); // prepare a game PrepareGame(); // trigger bot joinage ConnectionManager.SendChannelMessage(Config.UnoChannel, "?join"); // wait for bot joinage BotTestJoinRequested = DateTime.UtcNow; } }
protected virtual void HandleIKnewThatChannelCommand(CommandMatch cmd, IChannelMessageEventArgs args) { string senderLower = (ConnectionManager.RegisteredNameForNick(args.SenderNickname) ?? args.SenderNickname) .ToLowerInvariant(); string keywordLower = ((string)cmd.Arguments[0]).ToLowerInvariant(); using (var ctx = GetNewContext()) { IKnewThatEntry matchingEntry = ctx.Entries .FirstOrDefault(e => e.AuthorLowercase == senderLower && e.KeywordLowercase == keywordLower); if (matchingEntry == null) { ConnectionManager.SendChannelMessage( args.Channel, $"{args.SenderNickname}: No, you didn't!" ); return; } DateTimeOffset timestampLocal = matchingEntry.Timestamp.ToLocalTime(); ConnectionManager.SendChannelMessage( args.Channel, $"I confirm that on {timestampLocal:yyyy-MM-dd} at {timestampLocal:HH:mm:ss}, {args.SenderNickname} knew the following: {matchingEntry.Message}" ); ctx.Entries.Remove(matchingEntry); ctx.SaveChanges(); } }
protected virtual void HandleTelCommand(CommandMatch cmd, IChannelMessageEventArgs args) { string telNumber = ((string)cmd.Arguments[0]); if (telNumber.Length > 0) { // remove leading space telNumber = telNumber.Substring(1); } var ret = new StringBuilder(telNumber.Length); foreach (char c in telNumber) { char target; if (TelNoDictionary.TryGetValue(c, out target)) { ret.Append(target); } else { ret.Append(c); } } ConnectionManager.SendChannelMessage(args.Channel, ret.ToString()); }
private void HandleChannelAka([NotNull] CommandMatch cmd, [NotNull] IChannelMessageEventArgs e) { ActuallyHandleChannelOrQueryAka( cmd, e, txt => ConnectionManager.SendChannelMessage(e.Channel, $"{e.SenderNickname}: {txt}") ); }
private void HandleQueryAka([NotNull] CommandMatch cmd, [NotNull] IPrivateMessageEventArgs e) { ActuallyHandleChannelOrQueryAka( cmd, e, txt => ConnectionManager.SendQueryMessage(e.SenderNickname, txt) ); }
private void HandleWDYTICommandInChannel(CommandMatch cmd, IChannelMessageEventArgs msg) { HandleMessage( (string)cmd.Arguments[0], body => ConnectionManager.SendChannelMessage(msg.Channel, $"{msg.SenderNickname}: {body}") ); }
protected virtual void HandlePassCommand(CommandMatch cmd, IChannelMessageEventArgs msg) { if (msg.Channel != Config.UnoChannel) { return; } lock (TurnLock) { if (CurrentPlayer.Nick != msg.SenderNickname) { ConnectionManager.SendChannelMessageFormat( Config.UnoChannel, "It's not your turn, {0}.", msg.SenderNickname ); return; } if (!DrewLast) { ConnectionManager.SendChannelMessageFormat( Config.UnoChannel, "You have to draw first, {0}.", msg.SenderNickname ); return; } // skip to the next player AdvanceToNextPlayer(); } }
private static void RunCommands(CommandMatch match) { RunCommand(match.PrimaryCommand, match.Arguments); foreach (var command in match.PostCommands) { RunCommand(command); } }
/// <summary> /// Constructs a successful command search result. /// </summary> /// <param name="text">The text of the command to execute.</param> /// <param name="commands">The valid command matches.</param> /// <param name="error"></param> /// <param name="errorReason"></param> private BestMatchResult(string text, ICommandContext context, IServiceProvider services, CommandMatch command, ParseResult parseResult) { Text = text; Context = context; Services = services; Command = command; Result = parseResult; }
protected virtual void ActuallyHandleChannelOrQueryAka([NotNull] CommandMatch cmd, [NotNull] IUserMessageEventArgs e, [NotNull] Action <string> respond) { string nickToSearch = (string)cmd.Arguments[0]; if (!NickToMostRecentHost.ContainsKey(nickToSearch)) { respond($"I don\u2019t remember {nickToSearch}."); return; } var identifier = NickToMostRecentHost[nickToSearch]; var identifierParts = identifier.Parts; ImmutableList <HashSet <string> > matches; int matchDepth = HostToNicks.GetBestMatches(identifierParts, out matches); if (matchDepth == -1) { respond($"I don\u2019t remember any other nickname from {identifier} than {nickToSearch}."); return; } ImmutableList <HashSet <string> > fuzzyMatches = null; int fuzzyMatchDepth = -1; if (matchDepth == identifierParts.Count) { // do a fuzzy match too // replace the last item in identifierParts with the empty string var fuzzyIdentifierParts = identifierParts.SetItem(identifierParts.Count - 1, ""); fuzzyMatchDepth = HostToNicks.GetBestMatches(fuzzyIdentifierParts, out fuzzyMatches); } var otherNicks = new SortedSet <string>(matches.SelectMany(x => x)); var fuzzyOtherNicks = (fuzzyMatches == null) ? null : new SortedSet <string>(fuzzyMatches.SelectMany(x => x)); fuzzyOtherNicks?.ExceptWith(otherNicks); if (matchDepth == identifierParts.Count) { if (fuzzyOtherNicks != null && fuzzyOtherNicks.Count > 0) { respond($"{identifier}: {otherNicks.StringJoin(", ")}; fuzzy match ({fuzzyMatchDepth}/{identifierParts.Count}) also: {fuzzyOtherNicks.StringJoin(", ")}"); } else { respond($"{identifier}: {otherNicks.StringJoin(", ")}"); } } else { respond($"{identifier} fuzzy match ({matchDepth}/{identifierParts.Count}): {otherNicks.StringJoin(", ")}"); } }
protected virtual void HandleStopTriviaCommand(CommandMatch cmd, IChannelMessageEventArgs msg) { if (msg.Channel != Config.TriviaChannel) { return; } StopGame(); }
protected virtual void HandleNewCommand(CommandMatch cmd, IChannelMessageEventArgs message) { if (!EnsureOp(message)) { return; } var criterionName = (string)cmd.Arguments[0]; string detectionRegexString = ((string)cmd.Arguments[1]).Trim(); try { RegexCache.GetOrAdd(detectionRegexString); } catch (ArgumentException) { ConnectionManager.SendChannelMessage(message.Channel, $"{message.SenderNickname}: Invalid regular expression."); return; } using (var ctx = GetNewContext()) { // see if a criterion already matches Criterion crit = ctx.Criteria .FirstOrDefault(c => c.Name == criterionName && c.Channel == message.Channel); if (crit == null) { // create a new criterion crit = new Criterion { Name = criterionName, Channel = message.Channel, DetectionRegex = detectionRegexString, Enabled = true }; } else if (crit.Enabled) { ConnectionManager.SendChannelMessage( message.Channel, $"{message.SenderNickname}: That criterion name is already in use." ); return; } else { // modify the existing criterion and re-enable it crit.DetectionRegex = detectionRegexString; crit.Enabled = true; } ctx.SaveChanges(); // update the cache Dictionary <string, long> commandsIDs = ObtainCommandCacheForChannel(message.Channel); commandsIDs[crit.Name] = crit.ID; } }
protected void HandleAutoLinkInfoCommand(CommandMatch cmd, IChannelMessageEventArgs args) { var senderUsername = ConnectionManager.RegisteredNameForNick(args.SenderNickname); if (senderUsername == null) { ConnectionManager.SendChannelMessageFormat(args.Channel, "{0}: You must be registered to use this feature.", args.SenderNickname); return; } bool removeSubscription = (cmd.CommandName == "noautolinkinfo"); using (var ctx = GetNewContext()) { var currentSub = ctx.OptedInUsers.FirstOrDefault(u => u.UserName == senderUsername); if (removeSubscription) { if (currentSub == null) { ConnectionManager.SendChannelMessageFormat(args.Channel, "{0}: You are not subscribed to auto link info.", args.SenderNickname); } else { Logger.LogInformation( "{Nickname} ({Username}) is unsubscribing from auto link info", args.SenderNickname, senderUsername ); ctx.OptedInUsers.Remove(currentSub); ctx.SaveChanges(); ConnectionManager.SendChannelMessageFormat(args.Channel, "{0}: You have been unsubscribed from auto link info.", args.SenderNickname); } } else { // add subscription if (currentSub == null) { Logger.LogInformation( "{Nickname} ({Username}) is subscribing to auto link info", args.SenderNickname, senderUsername ); ctx.OptedInUsers.Add(new OptedInUser { UserName = senderUsername }); ctx.SaveChanges(); ConnectionManager.SendChannelMessageFormat(args.Channel, "{0}: You are now subscribed to auto link info.", args.SenderNickname); } else { ConnectionManager.SendChannelMessageFormat(args.Channel, "{0}: You are already subscribed to auto link info.", args.SenderNickname); } } } }
protected virtual void HandleRollCommand(CommandMatch cmd, IChannelMessageEventArgs args) { var rolls = (List <Match>)cmd.Arguments[0]; var diceGroups = new List <DiceGroup>(); foreach (Match rollMatch in rolls) { var diceGroup = ObtainDiceGroup(rollMatch, args.Channel, args.SenderNickname); if (diceGroup == null) { // error occurred and reported; bail out return; } diceGroups.Add(diceGroup); } if (diceGroups.Count > Config.MaxRollCount) { ConnectionManager.SendChannelMessageFormat(args.Channel, "{0}: Too many rolls.", args.SenderNickname); return; } // special-case 2d1 if (diceGroups.Count == 1 && diceGroups[0].DieCount == 2 && diceGroups[0].SideCount == 1 && diceGroups[0].AddValue == 0) { ConnectionManager.SendChannelAction(args.Channel, "rolls its eyes"); return; } Random rng = ChosenRNG(cmd); var allRolls = new List <string>(); foreach (var diceGroup in diceGroups) { var theseRolls = new List <string>(diceGroup.DieCount); for (int i = 0; i < diceGroup.DieCount; ++i) { if (diceGroup.SideCount == 1 && Config.ObstinateAnswers.Count > 0) { // special case: give an obstinate answer instead since a 1-sided toss has an obvious result string obstinateAnswer = Config.ObstinateAnswers[rng.Next(Config.ObstinateAnswers.Count)]; theseRolls.Add(obstinateAnswer); } else { long roll = rng.Next(diceGroup.SideCount) + 1 + diceGroup.AddValue; theseRolls.Add(roll.ToString(CultureInfo.InvariantCulture)); } } allRolls.Add(theseRolls.StringJoin(" ")); } ConnectionManager.SendChannelMessageFormat(args.Channel, "{0}: {1}", args.SenderNickname, allRolls.StringJoin("; ")); }
protected virtual void HandleYesNoCommand(CommandMatch cmd, IChannelMessageEventArgs args) { if (CheckAndHandleCooldown(cmd, args)) { return; } string yesNoAnswer = Config.YesNoAnswers[ChosenRNG(cmd).Next(Config.YesNoAnswers.Count)]; ConnectionManager.SendChannelMessageFormat(args.Channel, "{0}: {1}", args.SenderNickname, yesNoAnswer); }
protected virtual void HandleWeatherCommand(CommandMatch cmd, IChannelMessageEventArgs msg) { string location = ((string)cmd.Arguments[0]).Trim(); if (location.Length == 0) { location = Config.DefaultLocation; } GetWeatherForLocation(location, msg.Channel, msg.SenderNickname, showLocName: cmd.CommandName == "weather"); }
private async Task <bool> CheckPreconditionsAsync(CommandMatch cmd, ICommandContext context, IServiceProvider service) { foreach (PreconditionAttribute p in cmd.Command.Preconditions.Where(x => !(x is Ignore))) { if (!(await p.CheckPermissions(context, cmd.Command, service)).IsSuccess) { return(false); } } return(true); }
protected virtual void HandleLeaveCommand(CommandMatch cmd, IChannelMessageEventArgs msg) { if (msg.Channel != Config.UnoChannel) { return; } lock (TurnLock) { RemovePlayerFromGame(msg.SenderNickname); } }