Example #1
0
        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);
        }
Example #2
0
 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;
         }
     }
 }