public void HandleOne(ActionEntry entry, MessageContext context) { if (entry.State is int errorCount && errorCount >= 3) { if (errorCount == 3) { _logger.LogWarning("An Action has met its error limit and has been disabled: " + entry); } return; } #region Extract Check ExtractAttribute extract = entry.Action.GetCustomAttribute <ExtractAttribute>(); Dictionary <string, MessageChain> dict = new Dictionary <string, MessageChain>(); if (extract != null) { Match match = extract.Pattern.Match(_formatter.Format(context.Message.AsReadable())); if (match.Success) { string[] names = extract.Names.ToArray(); for (int i = 1; i < match.Groups.Count; i++) { dict.Add(names[i - 1], _parser.Parse(match.Groups[i].Value)); } } else { return; } } #endregion Extract Check #region Filter Check object[] filterBys = entry.Action.GetCustomAttributes(typeof(FilterByAttribute), false); string failureMessage = null; bool pass = filterBys.All(x => { FilterByAttribute filter = (FilterByAttribute)x; if (!filter.Filter.Check(context)) { failureMessage = filter.FailureMessage; return(false); } return(true); }); if (!pass) { if (failureMessage != null) { MessageChain chain = new MessageChain(new MessageComponent[] { new Plain(entry.Action.Name + ": " + failureMessage) }); context.ReplyAsync(chain).Wait(); } return; } #endregion Filter Check InvokeOne(entry, context, dict); }
private void InvokeOne(ActionEntry entry, MessageContext context, Dictionary <string, MessageChain> names) { ParameterInfo[] paras = entry.Action.GetParameters(); object[] paList = new object[paras.Length]; try { foreach (ParameterInfo para in paras) { if (names.ContainsKey(para.Name)) { // pattern paList[para.Position] = para.ParameterType switch { _ when para.ParameterType == typeof(string) => _formatter.Format(names[para.Name]), _ when para.ParameterType == typeof(MessageChain) => names[para.Name], _ when typeof(MessageComponent).IsAssignableFrom(para.ParameterType) => names[para.Name].FirstOrDefault(x => x.GetType() == para.ParameterType), // _ when para.ParameterType == typeof(Member) && names[para.Name].Any(x // => x is At) => GetMember(((At)names[para.Name].First(x => x is At)).TargetId), // unit 不应该即时计算 _ when para.ParameterType != typeof(string) && para.ParameterType.IsValueType => typeof(Convert).GetMethod("To" + para.ParameterType.Name, new Type[] { typeof(string) }).Invoke(null, new object[] { _formatter.Format(names[para.Name]) }), _ => throw new NotImplementedException("Pattern type not supported: " + para.ParameterType.FullName), }; } else { // context paList[para.Position] = para.ParameterType switch { _ when para.ParameterType == typeof(string) => _formatter.Format(context.Message), _ when para.ParameterType == typeof(Relations.Group) => context.Group, _ when para.ParameterType == typeof(Self) => context.Me, _ when para.ParameterType == typeof(MessageChain) => context.Message, _ when para.ParameterType == typeof(DateTime) => context.SentAt, _ when para.ParameterType == typeof(IApiClient) => context.Client, _ when para.ParameterType == typeof(MessageEventType) => context.Type, _ when para.ParameterType.IsAssignableFrom(context.User.GetType()) => context.User, _ => throw new NotImplementedException("Context type not supported: " + para.ParameterType.FullName), }; } } } catch (Exception) { if (entry.State is int cnt) { entry.State = cnt + 1; return; } } object unit = ActivatorUtilities.CreateInstance(_provider, entry.Unit); _logger.LogInformation($"Action hit: {entry}"); entry.Action.Invoke(unit, paList.ToArray()); if (entry.State is int count) { entry.State = count - 1; if (count < 0) { entry.State = 0; } } }