PageRenderTime 43ms CodeModel.GetById 21ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 1ms

/BlogEngine/BlogEngine.NET/App_Code/Extensions/TypePadFilter.cs

#
C# | 262 lines | 169 code | 45 blank | 48 comment | 12 complexity | c68e4d51834cc3c5233eccc339b670a8 MD5 | raw file
  1namespace App_Code.Extensions
  2{
  3    using BlogEngine.Core;
  4    using BlogEngine.Core.Web.Controls;
  5    using BlogEngine.Core.Web.Extensions;
  6
  7    using Joel.Net;
  8    using System.Collections.Generic;
  9    using System;
 10
 11    /// <summary>
 12    /// The type pad filter.
 13    /// </summary>
 14    [Extension("TypePad anti-spam comment filter (based on AkismetFilter)", "1.0", 
 15        "<a href=\"http://lucsiferre.net\">By Chris Nicola</a>")]
 16    public class TypePadFilter : ICustomFilter
 17    {
 18        #region Constants and Fields
 19
 20        /// <summary>
 21        /// The sync root.
 22        /// </summary>
 23        private static readonly object syncRoot = new object();
 24
 25        /// <summary>
 26        /// The Akismet api.
 27        /// </summary>
 28        private static Dictionary<Guid, Akismet> blogsApi = new Dictionary<Guid, Akismet>();
 29
 30        /// <summary>
 31        /// The fall through.
 32        /// </summary>
 33        private bool fallThrough = true;
 34
 35        /// <summary>
 36        /// The TypePad key.
 37        /// </summary>
 38        private static Dictionary<Guid, string> blogsKey = new Dictionary<Guid, string>();
 39
 40        /// <summary>
 41        /// The settings.
 42        /// </summary>
 43        private static Dictionary<Guid, ExtensionSettings> blogsSettings = new Dictionary<Guid, ExtensionSettings>();
 44
 45        /// <summary>
 46        /// The TypePad site.
 47        /// </summary>
 48        private static Dictionary<Guid, string> blogsSite = new Dictionary<Guid, string>();
 49
 50        #endregion
 51
 52        #region Constructors and Destructors
 53
 54        /// <summary>
 55        /// Initializes a new instance of the <see cref="TypePadFilter"/> class.
 56        /// </summary>
 57        public TypePadFilter()
 58        {
 59            InitSettings();
 60        }
 61
 62        #endregion
 63
 64        #region Properties
 65
 66        private static Akismet Api
 67        {
 68            get
 69            {
 70                Akismet akismet = null;
 71                blogsApi.TryGetValue(Blog.CurrentInstance.Id, out akismet);
 72
 73                return akismet;
 74            }
 75            set
 76            {
 77                blogsApi[Blog.CurrentInstance.Id] = value;
 78            }
 79        }
 80
 81        private static string Key
 82        {
 83            get
 84            {
 85                string key = null;
 86                blogsKey.TryGetValue(Blog.CurrentInstance.Id, out key);
 87
 88                return key;
 89            }
 90            set
 91            {
 92                blogsKey[Blog.CurrentInstance.Id] = value;
 93            }
 94        }
 95
 96        private static string Site
 97        {
 98            get
 99            {
100                string key = null;
101                blogsSite.TryGetValue(Blog.CurrentInstance.Id, out key);
102
103                return key;
104            }
105            set
106            {
107                blogsSite[Blog.CurrentInstance.Id] = value;
108            }
109        }
110
111        private static ExtensionSettings Settings
112        {
113            get
114            {
115                Guid blogId = Blog.CurrentInstance.Id;
116                ExtensionSettings settings = null;
117                blogsSettings.TryGetValue(blogId, out settings);
118
119                if (settings == null)
120                {
121                    lock (syncRoot)
122                    {
123                        blogsSettings.TryGetValue(blogId, out settings);
124
125                        if (settings == null)
126                        {
127                            var extensionSettings = new ExtensionSettings("TypePadFilter") { IsScalar = true };
128
129                            extensionSettings.AddParameter("SiteURL", "Site URL");
130                            extensionSettings.AddParameter("ApiKey", "API Key");
131
132                            extensionSettings.AddValue("SiteURL", "http://example.com/blog");
133                            extensionSettings.AddValue("ApiKey", "123456789");
134
135                            blogsSettings[blogId] = ExtensionManager.InitSettings("TypePadFilter", extensionSettings);
136                            ExtensionManager.SetStatus("TypePadFilter", false);
137                        }
138                    }
139                }
140
141                return settings;
142            }
143        }
144
145        /// <summary>
146        /// Gets a value indicating whether FallThrough.
147        /// </summary>
148        public bool FallThrough
149        {
150            get
151            {
152                return fallThrough;
153            }
154        }
155
156        #endregion
157
158        #region Implemented Interfaces
159
160        #region ICustomFilter
161
162        /// <summary>
163        /// Check if comment is spam
164        /// </summary>
165        /// <param name="comment">BlogEngine comment</param>
166        /// <returns>True if comment is spam</returns>
167        public bool Check(Comment comment)
168        {
169            if (Api == null)
170            {
171                this.Initialize();
172            }
173
174            var typePadComment = GetAkismetComment(comment);
175            var isspam = Api.CommentCheck(typePadComment);
176            fallThrough = !isspam;
177            return isspam;
178        }
179
180        /// <summary>
181        /// Initializes anti-spam service
182        /// </summary>
183        /// <returns>
184        /// True if service online and credentials validated
185        /// </returns>
186        public bool Initialize()
187        {
188            if (!ExtensionManager.ExtensionEnabled("TypePadFilter"))
189            {
190                return false;
191            }
192
193            Site = Settings.GetSingleValue("SiteURL");
194            Key = Settings.GetSingleValue("ApiKey");
195            Api = new Akismet(Key, Site, "BlogEngine.NET 1.5", "api.antispam.typepad.com");
196
197            return Api.VerifyKey();
198        }
199
200        /// <summary>
201        /// Report mistakes back to service
202        /// </summary>
203        /// <param name="comment">BlogEngine comment</param>
204        public void Report(Comment comment)
205        {
206            if (Api == null)
207            {
208                this.Initialize();
209            }
210
211            var akismetComment = GetAkismetComment(comment);
212
213            if (comment.IsApproved)
214            {
215                Utils.Log(string.Format("TypePad: Reporting NOT spam from \"{0}\" at \"{1}\"", comment.Author, comment.IP));
216                Api.SubmitHam(akismetComment);
217            }
218            else
219            {
220                Utils.Log(string.Format("TypePad: Reporting SPAM from \"{0}\" at \"{1}\"", comment.Author, comment.IP));
221                Api.SubmitSpam(akismetComment);
222            }
223        }
224
225        #endregion
226
227        #endregion
228
229        #region Methods
230
231        /// <summary>
232        /// Gets the akismet comment.
233        /// </summary>
234        /// <param name="comment">The comment.</param>
235        /// <returns>An Akismet Comment.</returns>
236        private static AkismetComment GetAkismetComment(Comment comment)
237        {
238            var akismetComment = new AkismetComment
239                {
240                    Blog = Settings.GetSingleValue("SiteURL"),
241                    UserIp = comment.IP,
242                    CommentContent = comment.Content,
243                    CommentAuthor = comment.Author,
244                    CommentAuthorEmail = comment.Email
245                };
246            if (comment.Website != null)
247            {
248                akismetComment.CommentAuthorUrl = comment.Website.OriginalString;
249            }
250
251            return akismetComment;
252        }
253
254        public void InitSettings()
255        {
256            // call Settings getter so default settings are loaded on application start.
257            var s = Settings;
258        }
259
260        #endregion
261    }
262}