PosterEngine.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. using InABox.Clients;
  2. using InABox.Configuration;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. namespace InABox.Core
  8. {
  9. public class RepostedException : Exception
  10. {
  11. public RepostedException(): base("Cannot process an item twice.")
  12. {
  13. }
  14. }
  15. public interface IPosterEngine<TPostable>
  16. where TPostable : Entity, IPostable, IRemotable, IPersistent, new()
  17. {
  18. bool Process(IEnumerable<TPostable> posts);
  19. }
  20. public interface IPosterEngine<TPostable, TPoster, TSettings> : IPosterEngine<TPostable>
  21. where TPostable : Entity, IPostable, IRemotable, IPersistent, new()
  22. where TPoster : IPoster<TPostable, TSettings>
  23. where TSettings : PosterSettings, new()
  24. {
  25. }
  26. public abstract class PosterEngine<TPostable, TPoster, TSettings> : IPosterEngine<TPostable, TPoster, TSettings>
  27. where TPostable : Entity, IPostable, IRemotable, IPersistent, new()
  28. where TPoster : IPoster<TPostable, TSettings>
  29. where TSettings : PosterSettings, new()
  30. {
  31. protected static TPoster Poster = GetPoster();
  32. private static Type[]? _posters;
  33. private static TPoster GetPoster()
  34. {
  35. _posters ??= CoreUtils.TypeList(
  36. AppDomain.CurrentDomain.GetAssemblies(),
  37. x => x.IsClass
  38. && !x.IsAbstract
  39. && !x.IsGenericType
  40. && x.HasInterface(typeof(IPoster<,>))
  41. ).ToArray();
  42. var type = _posters.Where(x => typeof(TPoster).IsAssignableFrom(x)).FirstOrDefault()
  43. ?? throw new Exception($"No poster of type {typeof(TPoster)}.");
  44. return (TPoster)Activator.CreateInstance(type);
  45. }
  46. protected static TSettings GetSettings()
  47. {
  48. return PosterUtils.LoadPosterSettings<TPostable, TSettings>();
  49. }
  50. protected static void SaveSettings(TSettings settings)
  51. {
  52. PosterUtils.SavePosterSettings<TPostable, TSettings>(settings);
  53. }
  54. /// <summary>
  55. /// Returns the <see cref="TSettings.Script"/>, if <see cref="TSettings.ScriptEnabled"/> is <see langword="true"/>;
  56. /// otherwise, returns <see langword="null"/>.
  57. /// </summary>
  58. protected static string? GetScript()
  59. {
  60. var settings = GetSettings();
  61. return settings.ScriptEnabled ? settings.Script : null;
  62. }
  63. protected abstract bool DoProcess(IEnumerable<TPostable> posts);
  64. public bool Process(IEnumerable<TPostable> posts)
  65. {
  66. var list = posts.ToList();
  67. if(list.Any(x => x.PostedStatus == PostedStatus.Posted))
  68. {
  69. throw new RepostedException();
  70. }
  71. try
  72. {
  73. var success = DoProcess(list);
  74. if (success)
  75. {
  76. foreach (var post in list)
  77. {
  78. post.Posted = DateTime.Now;
  79. post.PostedStatus = PostedStatus.Posted;
  80. }
  81. new Client<TPostable>().Save(list, "Posted by user.");
  82. }
  83. else
  84. {
  85. foreach (var post in list)
  86. {
  87. post.PostedStatus = PostedStatus.PostFailed;
  88. }
  89. new Client<TPostable>().Save(list, "Post failed by user.");
  90. }
  91. return success;
  92. }
  93. catch(Exception e)
  94. {
  95. Logger.Send(LogType.Error, "", $"Post Failed: {CoreUtils.FormatException(e)}");
  96. foreach (var post in list)
  97. {
  98. post.PostedStatus = PostedStatus.PostFailed;
  99. }
  100. new Client<TPostable>().Save(list, "Post failed by user.");
  101. throw;
  102. }
  103. }
  104. }
  105. }