Using Akismet's API In C#

1/23/2011

I've been working on a number of different things lately. Once their done I'll be posting a couple different series like my ORM series. In the mean time though I'm going to post a couple different small bits of code. For instance, today we're talking about Akismet. Akismet, for those who have not worked with blogs, is a spam fighting service designed for comments. Oh and it's by the same people behind WordPress, so they have a decent amount of experience fighting this sort of stuff.

Anyway, Akismet is available to anyone to sign up and use their service (you'll see the giant "sign up" button on the first page of their site). Once you've signed up you will get an API key, which will be used with their API. So at that point all you need to do is set up your site to use their API. There are a number of .Net libraries that deal with the service but to be honest, you can write the code yourself in a couple of minutes. Or you can simply copy my code below:

   1: /*
   2: Copyright (c) 2011 <a href="http://www.gutgames.com">James Craig</a>
   3: 
   4: Permission is hereby granted, free of charge, to any person obtaining a copy
   5: of this software and associated documentation files (the "Software"), to deal
   6: in the Software without restriction, including without limitation the rights
   7: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   8: copies of the Software, and to permit persons to whom the Software is
   9: furnished to do so, subject to the following conditions:
  10: 
  11: The above copyright notice and this permission notice shall be included in
  12: all copies or substantial portions of the Software.
  13: 
  14: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20: THE SOFTWARE.*/
  21:  
  22: #region Usings
  23: using System.Collections.Generic;
  24: using System.Xml;
  25: using System.Web;
  26: using System;
  27: #endregion
  28:  
  29: namespace Utilities.Web.Akismet
  30: {
  31:     /// <summary>
  32:     /// Akismet helper class
  33:     /// </summary>
  34:     public class Akismet:REST.REST
  35:     {
  36:         #region Constructor
  37:  
  38:         /// <summary>
  39:         /// Constructor
  40:         /// </summary>
  41:         /// <param name="Key">API Key</param>
  42:         /// <param name="Site">Site using Akismet</param>
  43:         public Akismet(string Key, string Site)
  44:             : base()
  45:         {
  46:             this.Key = Key;
  47:             this.Website = Site;
  48:             this.VerifyKeyData = string.Format("key={0}&blog={1}", Key, HttpUtility.UrlEncode(Website));
  49:             this.CommentCheckUrl = new Uri(string.Format("http://{0}.rest.akismet.com/1.1/comment-check", Key));
  50:             this.CommentCheckData = "blog=" + HttpUtility.UrlEncode(Website) + "&user_ip={0}&user_agent={1}&referrer={2}" +
  51:                 "&permalink={3}&comment_type={4}&comment_author={5}&comment_author_email={6}&" +
  52:                 "comment_author_url={7}&comment_content={8}";
  53:             this.SubmitSpamUrl = new Uri(string.Format("http://{0}.rest.akismet.com/1.1/submit-spam", Key));
  54:             this.SubmitHamUrl = new Uri(string.Format("http://{0}.rest.akismet.com/1.1/submit-ham", Key));
  55:         }
  56:  
  57:         #endregion
  58:  
  59:         #region Properties
  60:  
  61:         /// <summary>
  62:         /// API Key
  63:         /// </summary>
  64:         protected string Key { get; set; }
  65:  
  66:         /// <summary>
  67:         /// Website
  68:         /// </summary>
  69:         protected string Website { get; set; }
  70:  
  71:         /// <summary>
  72:         /// Data sent to verify the API key
  73:         /// </summary>
  74:         protected string VerifyKeyData { get; set; }
  75:  
  76:         /// <summary>
  77:         /// Comment check url
  78:         /// </summary>
  79:         protected Uri CommentCheckUrl { get; set; }
  80:  
  81:         /// <summary>
  82:         /// Submit spam url
  83:         /// </summary>
  84:         protected Uri SubmitSpamUrl { get; set; }
  85:  
  86:         /// <summary>
  87:         /// Submit ham url
  88:         /// </summary>
  89:         protected Uri SubmitHamUrl { get; set; }
  90:  
  91:         /// <summary>
  92:         /// Comment check data string
  93:         /// </summary>
  94:         protected string CommentCheckData { get; set; }
  95:  
  96:         #endregion
  97:  
  98:         #region Functions
  99:  
 100:         /// <summary>
 101:         /// Verifies the Key
 102:         /// </summary>
 103:         /// <returns>True if the key is valid, false otherwise</returns>
 104:         public bool VerifyKey()
 105:         {
 106:             this.Url = new Uri("http://rest.akismet.com/1.1/verify-key");
 107:             this.Data = VerifyKeyData;
 108:             return POST() == "valid";
 109:         }
 110:  
 111:         /// <summary>
 112:         /// Checks if a comment is spam or ham
 113:         /// </summary>
 114:         /// <param name="Comment">Comment to check</param>
 115:         /// <returns>True if it is spam, false otherwise</returns>
 116:         public bool IsSpam(Comment Comment)
 117:         {
 118:             this.Url = CommentCheckUrl;
 119:             this.Data = SetupData(Comment);
 120:             return bool.Parse(POST());
 121:         }
 122:  
 123:         /// <summary>
 124:         /// Submits a spam message
 125:         /// </summary>
 126:         /// <param name="Comment">Comment to submit</param>
 127:         public void SubmitSpam(Comment Comment)
 128:         {
 129:             this.Url = SubmitSpamUrl;
 130:             this.Data = SetupData(Comment);
 131:             POST();
 132:         }
 133:  
 134:         /// <summary>
 135:         /// Submits a ham message
 136:         /// </summary>
 137:         /// <param name="Comment">Comment to submit</param>
 138:         public void SubmitHam(Comment Comment)
 139:         {
 140:             this.Url = SubmitHamUrl;
 141:             this.Data = SetupData(Comment);
 142:             POST();
 143:         }
 144:  
 145:         private string SetupData(Comment Comment)
 146:         {
 147:             return string.Format(this.CommentCheckData,
 148:                  HttpUtility.UrlEncode(Comment.UserIP),
 149:                  HttpUtility.UrlEncode(Comment.UserAgent),
 150:                  HttpUtility.UrlEncode(Comment.Referrer),
 151:                  HttpUtility.UrlEncode(Comment.Permalink),
 152:                  HttpUtility.UrlEncode(Comment.CommentType),
 153:                  HttpUtility.UrlEncode(Comment.UserName),
 154:                  HttpUtility.UrlEncode(Comment.UserEmail),
 155:                  HttpUtility.UrlEncode(Comment.UserUrl),
 156:                  HttpUtility.UrlEncode(Comment.Content));
 157:         }
 158:  
 159:         #endregion
 160:     }
 161: }

The code above uses the REST class from my utility library (which simply sets up a web request using POST for the various requests, so either go to the repository and download the code or go here and get the code from this post for the REST class). Other than that, the only bit of code you need is the Comment class:

   1: /*
   2: Copyright (c) 2011 <a href="http://www.gutgames.com">James Craig</a>
   3: 
   4: Permission is hereby granted, free of charge, to any person obtaining a copy
   5: of this software and associated documentation files (the "Software"), to deal
   6: in the Software without restriction, including without limitation the rights
   7: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   8: copies of the Software, and to permit persons to whom the Software is
   9: furnished to do so, subject to the following conditions:
  10: 
  11: The above copyright notice and this permission notice shall be included in
  12: all copies or substantial portions of the Software.
  13: 
  14: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20: THE SOFTWARE.*/
  21:  
  22: #region Usings
  23: using System.Collections.Generic;
  24: using System.Xml;
  25: using System.Web;
  26: using System;
  27: #endregion
  28:  
  29: namespace Utilities.Web.Akismet
  30: {
  31:     /// <summary>
  32:     /// Holds comment data
  33:     /// </summary>
  34:     public class Comment
  35:     {
  36:         #region Properties
  37:  
  38:         public string UserIP { get; set; }
  39:         public string UserAgent { get; set; }
  40:         public string Referrer { get; set; }
  41:         public string Permalink { get; set; }
  42:         public string CommentType { get; set; }
  43:         public string UserName { get; set; }
  44:         public string UserEmail { get; set; }
  45:         public string UserUrl { get; set; }
  46:         public string Content { get; set; }
  47:  
  48:         #endregion
  49:     }
  50: }
The UserIP, UserAgent, UserName, etc. are referring to the person making the comment. The Content is the content of the comment, referrer is how they got to the post, permalink is the permanent link to the post that the comment is on, and the commenttype is generally just going to remain "comment" always... That's it. You create an Akismet object, passing in the API key and link to your website, create a Comment object (with the appropriate fields filled in), and then call IsSpam. And on the off chance that they screw up and you want to correct Akismet, you can send the same Comment object to SubmitSpam and SubmitHam functions. Anyway, that's all there is to it. So try it out and happy coding.


Comments