にたまごほうれん草アーカイブ

はてなダイアリーで書いてた「にたまごほうれん草」という日記のアーカイブです。現在は「にたまごほうれん草ブログ」を運営中です。

フィードの重複を取り除くプラグインFilter::deduped.rb

cronで定期的にフィードを取得して(例えばはてダなどに)投稿する場合、フィードの重複を取り除きたい場合があるかもしれません。
というわけで、名前をPlaggerのDedupedプラグインから拝借して、(かなり手抜きの)deduped.rbを作成してみました。メソッドmkdir_pは、キャッシュ用のディレクトリを再帰的に作成するものです。

## Filter::deduped - Plugin to get Deduped entries -- emergent
## 
## Plugin to get Deduped entries
## Cache path can be set.
##
## - module: Filter::deduped
##   config:
##    path: /tmp/cache/hoge
##
require 'pathname'
require 'digest/md5'

def mkdir_p path
  begin
    Dir.mkdir(path)
  rescue Errno::ENOENT
    mkdir_p Pathname.new(path).parent
    retry
  rescue Errno::EACCES
    raise
  end
  0
end

def deduped config, data
  cacheroot = Pathname(__FILE__).parent.parent.parent.realpath + 'cache'
  cachepath = Pathname.new(config['path']) || root
  if cachepath.relative?
    cachepath = cacheroot + cachepath
  end
  puts cachepath

  if !File.exists?(cachepath)
    begin
      mkdir_p cachepath
    rescue
      puts "could'nt make cache directory"
      return data
    end
  end
  
  deduped_data = data.select {|d|
    hashpath = cachepath.to_s + '/' + Digest::MD5.hexdigest(d.to_s)
    if File.exists?(hashpath)
      false
    else 
      File.open(hashpath, "wb").write(d.to_s) rescue false
    end
  }
  return deduped_data
end

単にキャッシュ用のディレクトリを作成してフィードの内容からMD5ハッシュを作成し一致を確認しているだけです。履歴の数が増えるともっといい方法が必要かもしれませんが、とりあえずはこれでいいのではないかと。

使い方

フィードをpublishする前に以下のモジュール記述を噛ませてください。

- module: Filter::deduped

パスを指定しない場合は、pragger.rbと同じディレクトリにcacheというディレクトリを作成してそこに保存します。
キャッシュパスを指定したいときは、以下のように。(自動作成はしないのであらかじめ作成しておいてください)
→パスが存在しない場合は作成するようにしました。ただし、パーミッションがないパスは作成しません。

- module: deduped
  config:
    path: /tmp/cache

絶対パスで指定した場合は、そのままのパスで指定しますが、相対パスで指定した場合は、上記のcacheディレクトリからの相対パスとなります。例えば

PlaggerのDedupedとはちょっと(かなり?)異なりますね。
# ひょっとしたらPlaggerの記述仕様に合わせた方が何かと都合よかったりして。

TODO

というわけで考えられるだけのTODOリスト

  • フィードごとにディレクトリ分けをする。(キャッシュを削除したい場合など、現状ではどれがどのフィードのキャッシュかわかりにくい)YAMLで指定してユーザごとにわける、でいいような気がしました
  • DBを利用できるように

追記

こんなまんまmkdir_pなモジュールがあった…
http://www.ruby-lang.org/ja/man/index.cgi?cmd=view;name=fileutils
というわけでいずれ修正。