浏览代码

New Timberline Poster

Kenric Nugteren 1 年之前
父节点
当前提交
80affd722c

+ 3 - 0
InABox.Core/Postable/IPostable.cs

@@ -8,6 +8,7 @@ namespace InABox.Core
     {
         NeverPosted,
         PostFailed,
+        RequiresRepost,
         Posted
     }
 
@@ -23,5 +24,7 @@ namespace InABox.Core
         DateTime Posted { get; set; }
 
         PostedStatus PostedStatus { get; set; }
+
+        string PostedNote { get; set; }
     }
 }

+ 32 - 15
InABox.Core/Postable/PosterEngine.cs

@@ -4,6 +4,7 @@ using InABox.Core.Postable;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Reflection;
 using System.Text;
 
 namespace InABox.Core
@@ -22,6 +23,24 @@ namespace InABox.Core
     {
     }
 
+    internal static class PosterEngineUtils
+    {
+        private static Type[]? _posters;
+
+        public static Type GetPoster(Type TPoster)
+        {
+            _posters ??= CoreUtils.TypeList(
+                AppDomain.CurrentDomain.GetAssemblies(),
+                x => x.IsClass
+                    && !x.IsAbstract
+                    && !x.IsGenericType
+                    && x.HasInterface(typeof(IPoster<,>))
+            ).ToArray();
+            return _posters.Where(x => TPoster.IsAssignableFrom(x)).FirstOrDefault()
+                ?? throw new Exception($"No poster of type {TPoster}.");
+        }
+    }
+
     /// <summary>
     /// A base class for all <see cref="IPosterEngine{TPostable}"/>. A concrete instance of this will be loaded by
     /// <see cref="PosterUtils.Process{T}(IDataModel{T})"/>; a new instance is guaranteed to be created each time that method is called.
@@ -31,26 +50,21 @@ namespace InABox.Core
     /// <typeparam name="TSettings"></typeparam>
     public abstract class PosterEngine<TPostable, TPoster, TSettings> : IPosterEngine<TPostable, TPoster, TSettings>
         where TPostable : Entity, IPostable, IRemotable, IPersistent, new()
-        where TPoster : IPoster<TPostable, TSettings>
+        where TPoster : class, IPoster<TPostable, TSettings>
         where TSettings : PosterSettings, new()
     {
-        protected static TPoster Poster = GetPoster();
-
-        private static Type[]? _posters;
+        protected TPoster Poster;
 
-        private static TPoster GetPoster()
+        public PosterEngine()
         {
-            _posters ??= CoreUtils.TypeList(
-                AppDomain.CurrentDomain.GetAssemblies(),
-                x => x.IsClass
-                    && !x.IsAbstract
-                    && !x.IsGenericType
-                    && x.HasInterface(typeof(IPoster<,>))
-            ).ToArray();
+            Poster = CreatePoster();
+        }
+
+        private static readonly Type? PosterType = PosterEngineUtils.GetPoster(typeof(TPoster));
 
-            var type = _posters.Where(x => typeof(TPoster).IsAssignableFrom(x)).FirstOrDefault()
-                ?? throw new Exception($"No poster of type {typeof(TPoster)}.");
-            return (TPoster)Activator.CreateInstance(type);
+        protected virtual TPoster CreatePoster()
+        {
+            return (Activator.CreateInstance(PosterType!) as TPoster)!;
         }
 
         protected static TSettings GetSettings()
@@ -124,6 +138,7 @@ namespace InABox.Core
                     {
                         post.Posted = DateTime.Now;
                         post.PostedStatus = PostedStatus.Posted;
+                        post.PostedNote = "";
                     }
                     new Client<TPostable>().Save(entities, "Posted by user.");
                 }
@@ -132,6 +147,7 @@ namespace InABox.Core
                     foreach (var post in entities)
                     {
                         post.PostedStatus = PostedStatus.PostFailed;
+                        post.PostedNote = "Post failed.";
                     }
                     new Client<TPostable>().Save(entities, "Post failed by user.");
                 }
@@ -145,6 +161,7 @@ namespace InABox.Core
                 foreach (var post in entities)
                 {
                     post.PostedStatus = PostedStatus.PostFailed;
+                    post.PostedNote = e.Message;
                 }
                 new Client<TPostable>().Save(entities, "Post failed by user.");
                 throw;

+ 1 - 0
InABox.Poster.CSV/ICSVPoster.cs

@@ -94,6 +94,7 @@ namespace InABox.Poster.CSV
         bool BeforePost(IDataModel<TEntity> model);
 
         ICSVExport Process(IDataModel<TEntity> model);
+
         void AfterPost(IDataModel<TEntity> model);
     }
 }

+ 1 - 0
InABox.Poster.Custom/ICustomPoster.cs

@@ -2,6 +2,7 @@
 
 namespace InABox.Poster.Custom
 {
+    [Caption("Custom")]
     public interface ICustomPoster<TEntity> : IPoster<TEntity, CustomPosterSettings>
         where TEntity : Entity, IPostable, IRemotable, IPersistent, new()
     {

+ 5 - 0
InABox.Poster.Custom/InABox.Poster.Custom.csproj

@@ -6,4 +6,9 @@
     <Nullable>enable</Nullable>
   </PropertyGroup>
 
+  <ItemGroup>
+    <ProjectReference Include="..\InABox.Core\InABox.Core.csproj" />
+    <ProjectReference Include="..\inabox.scripting\InABox.Scripting.csproj" />
+  </ItemGroup>
+
 </Project>

+ 24 - 0
InABox.Poster.Timberline/ITimberlinePoster.cs

@@ -0,0 +1,24 @@
+using InABox.Core;
+using InABox.Scripting;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace InABox.Poster.Timberline
+{
+    [Caption("Timberline")]
+    public interface ITimberlinePoster<TEntity, TSettings> : IPoster<TEntity, TSettings>
+        where TEntity : Entity, IPostable, IRemotable, IPersistent, new()
+        where TSettings : TimberlinePosterSettings<TEntity>
+    {
+        ScriptDocument? Script { set; }
+
+        bool BeforePost(IDataModel<TEntity> model);
+
+        bool Process(IDataModel<TEntity> model);
+
+        void AfterPost(IDataModel<TEntity> model);
+    }
+}

+ 14 - 0
InABox.Poster.Timberline/InABox.Poster.Timberline.csproj

@@ -0,0 +1,14 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\InABox.Core\InABox.Core.csproj" />
+    <ProjectReference Include="..\inabox.scripting\InABox.Scripting.csproj" />
+  </ItemGroup>
+
+</Project>

+ 69 - 0
InABox.Poster.Timberline/TimberlinePosterEngine.cs

@@ -0,0 +1,69 @@
+using InABox.Core;
+using InABox.Core.Postable;
+using InABox.Scripting;
+using System;
+using System.Collections.Generic;
+using System.Formats.Asn1;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace InABox.Poster.Timberline
+{
+    public class TimberlinePosterEngine<TPostable, TSettings> : PosterEngine<TPostable, ITimberlinePoster<TPostable, TSettings>, TSettings>
+        where TPostable : Entity, IPostable, IRemotable, IPersistent, new()
+        where TSettings : TimberlinePosterSettings<TPostable>, new()
+    {
+
+        private ScriptDocument? _script;
+        private bool _hasCheckedScript;
+
+        protected override ITimberlinePoster<TPostable, TSettings> CreatePoster()
+        {
+            var poster = base.CreatePoster();
+            poster.Script = GetScriptDocument();
+            return poster;
+        }
+
+        private ScriptDocument? GetScriptDocument()
+        {
+            if (_hasCheckedScript)
+            {
+                return _script;
+            }
+
+            var settings = GetSettings();
+            if (settings.ScriptEnabled && !string.IsNullOrWhiteSpace(settings.Script))
+            {
+                var document = new ScriptDocument(settings.Script);
+                if (!document.Compile())
+                {
+                    throw new Exception("Script failed to compile!");
+                }
+                _script = document;
+            }
+            else
+            {
+                _script = null;
+            }
+
+            _hasCheckedScript = true;
+            return _script;
+        }
+
+        public override bool BeforePost(IDataModel<TPostable> model)
+        {
+            return Poster.BeforePost(model);
+        }
+
+        protected override bool DoProcess(IDataModel<TPostable> model)
+        {
+            return Poster.Process(model);
+        }
+        public override void AfterPost(IDataModel<TPostable> model)
+        {
+            Poster.AfterPost(model);
+        }
+    }
+}

+ 16 - 0
InABox.Poster.Timberline/TimberlinePosterSettings.cs

@@ -0,0 +1,16 @@
+using InABox.Core;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace InABox.Poster.Timberline
+{
+    public abstract class TimberlinePosterSettings<TEntity> : PosterSettings
+    {
+        protected abstract string DefaultScript();
+
+        public override string DefaultScript(Type TPostable) => DefaultScript();
+    }
+}

+ 19 - 8
InABox.Server/RPC/Transports/RPCServerTransport.cs

@@ -89,12 +89,17 @@ namespace InABox.Rpc
         /// <returns>The response to be sent back to the client.</returns>
         public RpcMessage? DoMessage(TConnection? connection, RpcMessage? message)
         {
-            var session = GetSession(connection);
-            DoBeforeMessage(session,message);
-            RpcMessage? response = null;
-            if (session != null)
+            if(message is null)
+            {
+                DoException(connection, new Exception("NULL Message Received"));
+                return null;
+            }
+            var response = new RpcMessage() { Id = message.Id, Command = message.Command };
+            try
             {
-                if (message != null)
+                var session = GetSession(connection);
+                DoBeforeMessage(session, message);
+                if (session != null)
                 {
                     response = new RpcMessage() { Id = message.Id, Command = message.Command };
 
@@ -118,10 +123,16 @@ namespace InABox.Rpc
                     DoAfterMessage(session, response);
                 }
                 else
-                    DoException(connection, new Exception("NULL Message Received"));
+                {
+                    DoException(connection, new Exception("Session not Found"));
+                    response.Error = RpcError.SESSIONNOTFOUND;
+                }
+            }
+            catch(Exception e)
+            {
+                DoException(connection, e);
+                response.Error = RpcError.SERVERERROR;
             }
-            else
-                DoException(connection, new Exception("Session not Found"));
 
             return response;
         }