さくらインターネットにお金を払い忘れた

設定残したまま期限を越えてしまった...

ということで再契約したけどniconico.seelz.netを再設定出来ないや...

しょうがないのでURLをnico.seelz.netに変更してニコニコLinkを再設定。

はてなブックマーク4人くらいつけてくれていたのにな...
もったいない事した...

気を取り直して再度宣伝。
ニコニコLinkはニコニコ動画への被リンク数を集計するサイトです。
URLは↓です。よろしくね!
http://nico.seelz.net/indexes/

cakePHPでPEAR::Cache_Liteを使う

cakePHPのcachehelperについて、cacheしていてもControllerが動作してしまう...

http://cakephp.jp/modules/newbb/viewtopic.php?topic_id=1075&forum=7

原因が特定出来なかったので、しょうがないからPEAR::Cache_Liteを使用する事にした。

しかし、Cache_Liteはcacheする時に

$cache_lite->save($output);

この様に出力結果をsave()関数に渡さなければいけないのだけれど、cakePHPで出力結果を変数に渡す方法が判らない...

Contorollerで

$this->render();

とすれば出力されるのは判るんだけど、欲しいのは出力される内容なので$this->render();では駄目。

しょうがないのでgetRenderという関数を作った。

libs/controller/controller.php

<?php
function getRender($action = null, $layout = null, $file = null) {
	$viewClass = $this->view;
	if ($this->view != 'View') {
		$viewClass = $this->view . 'View';
		loadView($this->view);
	}
	$this->beforeRender();
	$this->__viewClass =& new $viewClass($this);

	if (!empty($this->modelNames)) {
		$models = array();
		foreach ($this->modelNames as $currentModel) {
			if (isset($this->$currentModel) && is_a($this->$currentModel, 'Model')) {
				$models[] = Inflector::underscore($currentModel);
			}
			if (isset($this->$currentModel) && is_a($this->$currentModel, 'Model') && !empty($this->$currentModel->validationErrors)) {
				$this->__viewClass->validationErrors[Inflector::camelize($currentModel)] =& $this->$currentModel->validationErrors;
			}
		}
		$models = array_diff(ClassRegistry::keys(), $models);
		foreach ($models as $currentModel) {
			if (ClassRegistry::isKeySet($currentModel)) {
				$currentObject =& ClassRegistry::getObject($currentModel);
				if (is_a($currentObject, 'Model') && !empty($currentObject->validationErrors)) {
					$this->__viewClass->validationErrors[Inflector::camelize($currentModel)] =& $currentObject->validationErrors;
				}
			}
		}
	}
	$this->autoRender = false;
	return $this->__viewClass->getRender($action, $layout, $file);
}
?>

libs/view/view.php

<?php
	function getRender($action = null, $layout = null, $file = null) {

		if (isset($this->_hasRendered) && $this->_hasRendered) {
			return true;
		} else {
			$this->_hasRendered = false;
		}

		if (!$action) {
			$action = $this->action;
		}
		$tempLayout = $this->layout;

		if ($layout) {
			$this->setLayout($layout);
		}

		if ($file) {
			$viewFileName = $file;
		} else {
			$viewFileName = $this->_getViewFileName($action);
		}

		if (!is_null($this->plugin) && is_null($file)) {
			return $this->pluginView($action, $layout);
		}

		if (!is_file($viewFileName) && !fileExistsInPath($viewFileName) || $viewFileName === '/' || $viewFileName === '\\') {
			if (strpos($action, 'missingAction') !== false) {
				$errorAction = 'missingAction';
			} else {
				$errorAction = 'missingView';
			}

			foreach (array($this->name, 'errors') as $viewDir) {
				$errorAction = Inflector::underscore($errorAction);

				if (file_exists(VIEWS . $viewDir . DS . $errorAction . $this->ext)) {
					$missingViewFileName = VIEWS . $viewDir . DS . $errorAction . $this->ext;
				} elseif ($missingViewFileName = fileExistsInPath(LIBS . 'view' . DS . 'templates' . DS . $viewDir . DS . $errorAction . '.thtml')) {
				} else {
					$missingViewFileName = false;
				}

				$missingViewExists = is_file($missingViewFileName);

				if ($missingViewExists) {
					break;
				}
			}

			if (strpos($action, 'missingView') === false) {
				return $this->cakeError('missingView', array(array('className' => $this->controller->name,
																					'action' => $action,
																					'file' => $viewFileName,
																					'base' => $this->base)));

				$isFatal = isset($this->isFatal) ? $this->isFatal : false;

				if (!$isFatal) {
					$viewFileName = $missingViewFileName;
				}
			} else {
				$missingViewExists = false;
			}

			if (!$missingViewExists || $isFatal) {
				if (Configure::read() > 0) {
					trigger_error(sprintf("No template file for view %s (expected %s), create it first'", $action, $viewFileName), E_USER_ERROR);
				} else {
					$this->error('404', 'Not found', sprintf("The requested address %s was not found on this server.", '', "missing view \"{$action}\""));
				}
				die();
			}
		}

		if ($viewFileName && !$this->_hasRendered) {
			if (substr($viewFileName, -5) === 'thtml') {
				$out = View::_render($viewFileName, $this->viewVars);
			} else {
				$out = $this->_render($viewFileName, $this->viewVars);
			}

			if ($out !== false) {
				if ($this->layout && $this->autoLayout) {
					$out = $this->renderLayout($out);
					if (isset($this->loaded['cache']) && ((isset($this->controller) && $this->controller->cacheAction != false)) && (defined('CACHE_CHECK') && CACHE_CHECK === true)) {
						$replace = array('<cake:nocache>', '</cake:nocache>');
						$out = str_replace($replace, '', $out);
					}
				}

				#print $out;
				$this->setLayout($tempLayout);
				$this->_hasRendered = true;
			} else {
				$out = $this->_render($viewFileName, $this->viewVars);
				trigger_error(sprintf("Error in view %s, got: <blockquote>%s</blockquote>", $viewFileName, $out), E_USER_ERROR);
			}
			return $out;
		}
	}

?>

これでControllerで

	$cache_lite = new Cache_Lite($cache_options);
	$cache_lite->save($this->getRender());

の様にすれば、Cache_Liteのsave()関数にviewを渡せるので、

cakePHPでCache_Liteを利用してしてcacheする事が出来る。

ニコニコLinkのトップページが今まで12秒かかっていたのがCache_Lite使用後は1秒程度になった。
これでようやく前進できそうだ。
明日からはニコニコ動画への負荷をもうちょっと減らせる修正をしよう。

ニコニコ動画への被リンク数を集計して表示するサイト

ニコニコLink

ニコニコLinkはBlogからニコニコ動画への被リンク数を調べてデータベース化したサイトです。

本当はウィークリーランキングとかマンスリーランキングとか、後Bloggerの方が
動画に対して言及したコメントを表示したりしたかったんですが、最初から機能
を増やすと何時まで経っても公開できないのでとりあえずまだα版ですが、公開します。

開発動機について、個人的な感覚ですが多くのニコニコユーザは本家のランキングしか見ない
様な気がします。手軽に面白い動画を探すのは確かに本家ランキングは便利なんですが
それだけだと人気動画は益々人気になり、本当は面白いはずの動画が中々注目されない事になってしまいます。
じゃあ今回作ったニコニコLinkが解決策になりえるのかというと、現状無理ですね(笑
やっぱり本家ランキングに乗った動画はBloggerにも注目されます。
それはしょうがないです、実際面白いですから。
ただ、将来的には今はまだ注目されていないけど面白い動画をピックアップできる
様なサイトにして行きたいなと思っています。

恐らく機能が不足していたりバグが出たりすると思いますのでその際には、はてブなり
メールなりで教えて頂けると嬉しいです。レスポンスがあると嬉しいんです。開発意欲になります。
メールアドレスはharu1234 at gmail.com です。

では、よろしければぜひお立ち寄り下さい。


ニコニコLink
http://niconico.seelz.net/indexes/

TechnoratiのURL検索がイマイチ使い勝手が良くない

TechnoratiURL検索
精度がイマイチ良くない。

何がしたいかと言うと、ニコニコ動画へリンクしているブログをかき集めて、ニコニコ動画
のタグを検索して、どのタグがBlogでは人気か、またBlogではどんなニコニコ動画が流行っている
のかを調べたい。後Blogでは面白い動画が紹介されやすいので集計すれば面白い結果に
なるんじゃないかと思った。

この仕様を実現するためにTechnoratiのURL検索が必要なんだけどイマイチ使い勝手が良くない。

第1に偶にRequestがこける。Technoratiに問い合わせたところ、偶にこういう事はあるらしい。

第2に重複が多すぎる。
試しに50000件検索して見たが、同一Blogで同じ動画を紹介しているのが49591件も有った。
同一記事は必要ないので完全にゴミデータだ。
結局ゴミデータを取り除くと50000件検索して使用できる動画は409件しか無い。

第3に、これが致命的で最大50000件までしか検索できない
2007年3月6日現在、ニコニコ動画にリンクしているBlogが824639件ある。
つまり全Blogのうち10%以下しか網羅出来ていない。

折角良いサービス提供しているんだから、2と3だけでも改善してくれないかな
Technoratiさん...

Courierでメール転送する方法

80code.comCourierというMTAを使っている模様。

Courierの場合、メール転送先を記述するファイル名は.courierになる。

記述方法はSendmailと同じで.courierファイルに転送先のメールアドレスを記述するだけ。

.courier

info@example.jp
メールが届いた時にスクリプトを動かす方法もSendmailと同じ

.courier

|/usr/bin/php /var/www/home/ユーザディレクトリ/mobile.php