2009年 05月 30日

はてブの非表示ユーザ関係の Greasemonkey script

  • 「うぜーなー」と思っても、永遠に非表示になってしまうと思うと非表示に入れにくい
    • → もっとカジュアルに非表示に追加したい
  • 非表示にしたときが、たまたまつまらないタイミングというだけだったかもしれない
    • → ずっと非表示なのは本位じゃない

ので3ヶ月で非表示ユーザを期限ぎれにして解除するユーザスクリプトを書きました。

http://gist.github.com/raw/117826/2085144424e6d5cd1e8cc93f74c988a8d81256ac/hatena.bookmark.expire_ignore_user.user.js

はてブの設定ページもついでに拡張していて、追加したユーザについて一覧できるようにしてあります。

  • いつ解除されるか、とかのデータははてブの custom_style にコメントとしてうめこんでいます
    • custom_style は公開情報なので、AES で暗号化しています
    • その関係で最初に起動したときキーを作ります
    • そこまでしなくてもいい気もしたのですがやっても損はしないのでやってみました
  • 設定ページから非表示ユーザを追加できなくなる (殆どしないし……)
  • 設定ページのリストで期限を再設定できる
    • 期限がすくなくとも生きている間にはこないようにできるように
  • 1日に1回 (はてブにアクセスしたとき) 非表示ユーザの更新をチェックして更新をかけます。
    • なので微妙にズレが生じます
  • 作ってから3ヶ月経ってないので使い勝手はわかりません


あとついでに「あるエントリをブックマークしているユーザ」を一括して非表示に追加できるスクリプトも書きました

http://gist.github.com/raw/117376/d7d23472e1af915df608d6f4f611998704723639/hatena.bookmark.ignoreentriesuser.user.js

ボタンがエントリページにでてきます。一度 confirm できかれます。

2009年 05月 29日

web.xml filter, 自分で Dispatch

Lift 見つつ最低限な部分を自分で再実装

  • 全部のリクエストを受け取ってなんかしたいなら filter を使う
  • filter では、何もせずに chain.doFilter すれば static ファイルとかをいい感じにやってくれる。

web.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
	<filter>
		<filter-name>HttpRequestDispatcher</filter-name>
		<filter-class>net.lowreal.skirts.HttpRequestDispatcher</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>HttpRequestDispatcher</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>
package net.lowreal.skirts

import javax.servlet._
import javax.servlet.http.{HttpServlet, HttpServletResponse, HttpServletRequest}

class HttpRequestDispatcher extends Filter {
	val static = """^/(?:css|js|images|static).*""".r

	def init (filterConfig: FilterConfig) = {
		println("init")
	}

	def doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) = {
		println("doFilter")
		(request, response) match {
			case (req: HttpServletRequest, res: HttpServletResponse) =>
				println("")
				println(req)
				req.getRequestURI match {
					case static() =>
						println("static")
						chain.doFilter(request, response)
					case _ =>
						println("dispatch")
						res.setContentType("text/html")
						res.getWriter.println { """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">""" }
						res.getWriter.println {
							<html>
								<head><title>Hello World</title></head>

								<link rel="stylesheet" type="text/css" href="/css/base.css" media="screen,tv"/>
								<!-- script type="text/javascript" src="/js/site-script.js"></script -->
							<body>
								<h1>Request</h1>
								<pre>Method: { req.getMethod }</pre>
								<pre>RequestURI: { req.getRequestURI }</pre>
								<pre>QueryString: { req.getQueryString }</pre>
								<h1>Raw</h1>
								<pre>{ req }</pre>
							</body>
							</html>
						}
				}
			case _ => chain.doFilter(request, response)
		}
	}

	def destroy () = {
		println("destroy")
	}
}

skirts っていう名前で簡単なフレームワークを作ろうと思ってる。とりあえず Lift は気にいらなかったので、コードは参考にしつつも使わない方向に……

skirts = scala / 周りをとりまく何か / 美少女

2009年 05月 28日

GDHM の「陽だまりを越えて」を買ってきた。これからも楽しみだなぁ。発売日を意識して買うアーティストは唯一 GDHM だけです。

したいことがあったら声に出せ、というのが印象に残っていて、微妙に実践しようと思ってどうすればいいかなーという感じだったけど、「GAE やるんよ、やりたいんよー」っていってたら datastore のクセのイメージをタイミングよく教えてもらえたらいしたので、こういうことなんだなぁと思った。

一番嫌なのはやっぱファイルが増える、ということなんだと実感した。Scala で Java ラップするために沢山クラス作っても別に嫌ではない。ファイルが増えるだけで普段の作業のオペレーションが増えるんだもんなぁ…… 開く・閉じる・選択する・grep する。

GAE はとりあえずローカルの開発サーバが起動して、Scala で書いた HttpServlet に dispatch は簡単にできた。java class の自動コンパイル・自動リロードとか、リクエストフィルタを使った URL の dispatch とかが解らなくてとまってる。Lift とか読みつつやってるけど、そもそも Java war の流儀がよくわからない。

Scala だと Java の資源が使えるのが本当にとてもよくて、Rhino とか使ってスクリプト実行させたりもできるし、JRuby をテンプレートエンジンのためだけに使う (謎の XML 書きたくないし……) とかいう贅沢もできそうで夢が広がる。

Java は単体で書きたいとは全く思わないけど、Scala は書いていてすごく楽しい。ピタっとハマっていく感じがする。Ruby とかにはない型厳密な関数っぽい感覚。でも関数型ほど新しい考えかたをしなくても書けるから気持ちいい。しかも Scala はコンパイルすると Java クラスに変換されて JVM で直接動くのだから、JVM もすごいなーと思った。

gerry++

三日連続

スカラクロウラ - アクター

うーんよくわからない。while(true)/receive と loop/react の違いもよくわからない (スレッド作るかそうじゃないかだけの違い?)

クローラっぽいのを練習がてら書いてみた。あんまりわかりやすくはないなぁという気もする。もっといい書きかたあるのかな。

  • 一度に走るリクエストは2つまで
    • あらかじめ2つリクエストを出す Actor を作ってそれのキューにいれていく
  • List あたりが微妙にわかりにくい。普通に shift/push したい

http://gist.github.com/119257

あれこれ最初、スカラクロウラとかエントリで言いたかっただけだったのに、全くそんなこと忘れてエントリ書いてた

MP3 ID3 文字コード関係を仕様書にあたってみる

仕様がどうなっていようと使ってるやつが対応してないと意味ないですけどね!!

ID3v1

http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm#MPEGTAG

  • 文字コードについて記述なし
  • title, artist, album それぞれ 30bytes しか書けない

ID3v2

2.3

http://www.id3.org/id3v2.3.0

  • If nothing else is said a string is represented as ISO-8859-1 characters in the range $20 - $FF. Such strings are represented as , or if newlines are allowed, in the frame descriptions. All Unicode strings use 16-bit unicode 2.0 (ISO/IEC 10646-1:1993, UCS-2). Unicode strings must begin with the Unicode BOM ($FF FE or $FE FF) to identify the byte order.

要は

  • ISO-8859-1
  • UTF-16
  • UTF-16BE

でしか書けない。

2.4

http://www.id3.org/id3v2.4.0-structure

   Frames that allow different types of text encoding contains a text
   encoding description byte. Possible encodings:

     $00   ISO-8859-1 [ISO-8859-1]. Terminated with $00.
     $01   UTF-16 [UTF-16] encoded Unicode [UNICODE] with BOM. All
           strings in the same frame SHALL have the same byteorder.
           Terminated with $00 00.
     $02   UTF-16BE [UTF-16] encoded Unicode [UNICODE] without BOM.
           Terminated with $00 00.
     $03   UTF-8 [UTF-8] encoded Unicode [UNICODE]. Terminated with $00.
  • ISO-8859-1
  • UTF-16
  • UTF-16BE
  • UTF-8

で書ける。場合によっては ISO-8859-1 と UTF-8 でしか書けない場合がある? (Tag restriction あたり。よくわからない)

個人的なベスト

  • ID3v1 は書かない
    • 今時 ID3v2 に対応してないプレイヤーとか捨てればいい
    • 文字化けの元
  • ID3v2.3 にしておく
    • 文字コードは UTF-16(LE)