Another release of Akismet spam rule

My Akismet spam rule has a second home. Originally I contributed it to CSMVP's CSModules package aka Alabaster. A couple of days ago José Lema informed me that Telligent wants to release a free dedicated spam rule package, and they would like to include my rule as well. First I hesitated relinquishing my baby, but hey, the more users get easier access to that rule, the less spam they'll get. So finally I agreed José to include my rule in their package.

Yesterday José announced the availability of that spam rule package, and indeed my spam rule is not included in it, but available on its own. That means I still have full control over it and more people will use it. So if you don't want to use Alabaster (though you might miss other great CSModules) you can get the Akismet spam rule as a stand-alone component.

Happy spam-fighting.

KDE Mouse Emulator

Software, Tools Comments

Jörgen Sigvardsson published his KDE Mouse Emulator at CodeProject:

In KDE (a desktop environment for Unix operating systems), windows can be moved and resized without having to click on window edges or going through menus. To move a window, simply press ALT and press left mouse button and reposition the window by moving the mouse. To resize a window, press the right mouse button instead, and adjust the position of the bottom right corner by moving the mouse.

I installed it only a few hours ago and am already used to it.

The Akismet Spam Rule included in Alabaster

Though I spoke about my Akismet spam rule a couple of weeks ago, I didn't draw that much attention to it. However, now that the first version of CSMVP's CSModules package, code name Alabaster, is released for more than a week, I'd like to spent some words on it, though Jayson mentioned it in his CS Tidbits: Exploring The CS Spam Blocker.

Akismet provides a web service, which evaluates a comment or trackback based on several tests and returns a thumb up or thumb down. (Additionally, it can be trained, but that's not supported by my spam rule.)

The spam rule I wrote and contributed to Alabaster calls this Akismet web service. The implementation is straight forward, for a general spam rule implementation see Jose Lema's instructions on the CS Forum. Well, there some tips missing, but Keyvan forwarded me an advice from Jose: if you use a web service in a spam rule, make that external call only if absolutely necessary. If the "cheaper" spam rules such as link count already identifies a comment as spam, an "expensive" call to an external service would be redundant.

The spam rule engine in Community Server evaluates comments three-stage. In the implementation of your spam rule you can specify at which stage your rule should be visited. Additionally, you can restrict your rule based on the result of previously visited spam rules. In the case of the Akismet spam rule, I specified that the rule should be visited in the third stage, and only if the comment is not considered spam yet:

/// <summary>
/// Gets the pass criteria.
/// </summary>
/// <value>The pass criteria.</value>
public override PassCriteria PassCriteria
{
    get { return PassCriteria.ThirdPass; }
}

/// <summary>
/// Gets the status criteria.
/// </summary>
/// <value>The status criteria.</value>
public override StatusCriteria StatusCriteria
{
    get { return StatusCriteria.NotSpam; }
}

Ok, enough about the implementation. The installation is pretty easy. Contrary to CSModules, spam rules do not need to be registered in any .config files. Instead, the spam rule engine finds all rules via reflection on all assemblies in CS' bin folder.

For the configuration, first of all you need a WordPress API key, because Akismet requires it. Though you can get a key for free, the Akismet is free only for personal use. If you are a commercial entity or making more than $500 from your personal blog, you need a commercial key.

Akismet configuration

Pretending you have your API key now, go to Control Panel -> Administration -> System Tools -> Manage Spam Blocker (~/ControlPanel/Tools/ManageSpamRules.aspx). Tick the Akismet.com spam rule and click on Configure. In the configuration window enter your API key and your desired points for detected spam (I chose 5, so it gets moderated automatically. I trust Akismet [;)]). Click Save to close the configuration window and again Save to accept the selected spam rules.

Windows Live Writer and WLWPlugins

Development, Software Comments

I just want to note that my last post was brought to you by Windows Live Writer and Code Syntax Highlighter.

Till now I always used Community Server's editing facilities, but often enough I lost my drafts for several reasons. WLW provides an auto-save option, which would have saved me a lot of time in the past.

But the coolest feature of WLW is its extensibility. Keyvan Nayyeri wrote a nice tutorial about how to create a Technorati tag plugin.

Mixing C# and VB.NET in one assembly

Development, MSBuild, CSMVPs Comments

A couple of weeks ago Jayson Knight invited me to join the CSMVP's' CSModules package. This project was created to incorporate several CSModules written by CS MVP's. So I bought into that project by bringing along my Akismet spam rule.

At that point in time, for each CSModule there was a single Visual Studio project, all bound together in a Visual Studio solution. But our goal was to incorporate all modules into a single assembly, so the user only has to copy one DLL to his /bin web folder.

My first idea was to put all sources into a single project. However, since every CS MVP wrote his module in his favorite language, there were both C# and VB.NET projects. Unfortunately, in Visual Studio projects have a certain type supporting only a single language.

But luckily, even if there's no support by the IDE, you still can compile different .NET languages into one assembly. The solution are modules. A module is a unit of compilation, comparable to .obj files in C++. It can't stand by its own, but must be linked into an assembly before it can be used. Basically, a module is an assembly without a manifest. You can get more details on MSDN at .netmodule Files as Linker Input. Additionally I recommend reading Junfeng Zhang's Netmodule vs. Assembly and Multimodule Assemblies.

Knowing the concept of modules, I was able to write a MSBuild project file to compile all CSModules into a single assembly. Here's an (extremely) simplified version:

<Project
  DefaultTargets="build"
  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
        
  <!-- Target folders -->
  <PropertyGroup>
    <SourcePath>src</SourcePath>
  </PropertyGroup>

  <!-- Specify the sources to include, excluding any assembly info's -->
  <ItemGroup>
    <CSFiles
      Include="$(SourcePath)/**/*.cs"
      Exclude="$(SourcePath)/**/assemblyinfo.cs"/>
    <VBFiles 
      Include="$(SourcePath)/**/*.vb" 
      Exclude="$(SourcePath)/**/assemblyinfo.vb;$(SourcePath)/**/My Project/*"/>
  </ItemGroup>

  <!-- Specify all referenced assembly -->
  <ItemGroup>
    <References Include="lib/2.1 RTM/*.dll" />
  </ItemGroup>

  <!-- Target files -->
  <PropertyGroup>
    <OutputModule>MyModule</OutputModule>
  </PropertyGroup>

  <!-- builds the CSMVPs.CSModules assembly -->
  <Target 
    Name="build"
    Inputs="@(CSFiles);@(VBFiles);@(References)" 
    Outputs="$(OutputModule).dll">

    <!-- compile C# sources -->
    <CSC
      Sources="@(CSFiles)"
      References="@(References)" 
      OutputAssembly="$(OutputModule).CS.netmodule"
      TargetType="module">
    </CSC>
      
    <!-- compile VB.NET sources -->
    <VBC
      Sources="@(VBFiles)"
      References="@(References)" 
      OutputAssembly="$(OutputModule).VB.netmodule"
      TargetType="module">
    </VBC>

    <!-- link the C# and VB.NET modules -->
    <Exec 
      Command="link /dll /ltcg /out:$(OutputModule).dll *.netmodule" />
  </Target>
</Project>