iTunes にお仕事をしてもらうために書いた使い捨てツール

| 0 Comments | 0 TrackBacks

iTunes で CD をエンコードする場合、初めて突っ込む CD だと CDDB に問い合わせてくれるようになっています。だれかが入力してくれてて CDDB に曲名が存在すれば、楽を出来る仕組みですね。

ただ、1 つの CD に複数のデータが存在する場合、ダイアログが出てきて、どのデータを使うのか聞かれることになります。エンコードする枚数が多いと、問い詰められる回数も当然増えます。

こいつが今回の敵です。

何かダイアログが出てきたら OK を押すだけの簡単なお仕事をするアルバイトの子を雇うことにしました。

またこの子には、うちのマシンの CPU の処理速度に応じて、約 4 分を測定してもらうお仕事も兼ねてもらうことにしました。

一応、エンコード中なのかどうかは以下のようなコードで教えてもらえるっぽいことを、あとで知りました。次回大量エンコードする際は使おうと思います。

var	iTunesApp = WScript.CreateObject("iTunes.Application");
var objConversionstatus = iTunesApp.ConvertOperationStatus;
WScript.Echo(objConversionstatus.ProgressValue);

以下が今回雇ったアルバイトの子です。

// itunes-clicker.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include <windows.h>
#include <shlobj.h>
#include <string.h>

#define strdup _strdup

#define MAX_NUM_ENUMWND  100
int  g_cnt = 0;                  // カウンタ
HWND targetWnd;
char *targetText;
char *targetClass;
BOOL CALLBACK MankoProc(HWND hWnd, LPARAM lParam)
{
	if (g_cnt >= MAX_NUM_ENUMWND) return FALSE;

	char buf[1024];
	char *tocmp;
	if (targetText != NULL) {
		tocmp = strdup(targetText);
		GetWindowText(hWnd, buf, 1024);
	} else {
		tocmp = strdup(targetClass);
		GetClassName(hWnd, buf, 1024);
	}
	if (strcmp(buf, tocmp) == 0) {
		targetWnd = hWnd;
		return FALSE;
	}
    g_cnt++;
    return TRUE;
}

HWND Manko(HWND hWnd, char *textName, char *className)
{
	targetWnd = NULL;
	if (textName != NULL) {
		targetText = strdup(textName);
		targetClass = NULL;
	} else {
		targetText = NULL;
		targetClass = strdup(className);
	}
	g_cnt = 0;
	EnumChildWindows(hWnd, MankoProc, 0);
	return targetWnd;
}

void dialog_clicker(void) {
  HWND hWnd = FindWindow("iTunesCustomModalDialog", NULL);
	HWND hdialog;
	if (hWnd != NULL) {
		hdialog = Manko(hWnd, "OK", NULL);
		if (hdialog != NULL) {
			PostMessage(hWnd, WM_COMMAND, MAKEWPARAM(101, BN_CLICKED), 0);
		}
	}
}


int _tmain(int argc, _TCHAR* argv[])
{
  int c;
	for (c = 0; c < 240; c++) {
	  dialog_clicker();
	  Sleep(1000);
	}
	return 0;
}
@rem encodeall.bat
@echo off
FOR /D %%x IN (???) DO CALL encode.bat %%x
@rem encode.bat
@echo off
echo run %1
set loc=0,X:\cds-wav\%1\CDImage.cue

echo %loc%
"c:\Program Files\D-Tools\daemon.exe" -mount %loc%
X:\itunes-clicker.exe
"c:\Program Files\D-Tools\daemon.exe" -unmount 0

Puregeek ブログについてお知らせ

| 0 Comments | 0 TrackBacks

ご存じの通り、Puregeek ブログという形で、hkn さんにブログを書いてもらう企画をやっていました。

突然ですが、Puregeek ブログは7月8日に終了という形をとらせていただくことになりました。

記事を書いてくださった hkn さん、企画に関わってくれた皆さん、読者の皆さん、ありがとうございました。

Fixdapbot というボットを作ってみた

| 0 Comments | 0 TrackBacks

Web::Scraper でスクレイピングしまくり。

自分の ID/password で、タスクを一覧、追加、完了という最低限の実装でとりあえず。

使用例

19:32 (woremacx) list
19:32 (fixdapbot) woremacx: #1 mt の permalink を直す
19:32 (woremacx) k
19:32 (woremacx) add TENGA 買い占める!
19:32 (fixdapbot) woremacx: task added: http://fixdap.com/p/woremacx/14711/
19:33 (woremacx) list
19:33 (fixdapbot) woremacx: #5 TENGA 買い占める!
19:33 (fixdapbot) woremacx: #1 mt の permalink を直す
19:33 (woremacx) done 5
19:33 (fixdapbot) woremacx: task done: http://fixdap.com/p/woremacx/14711/
19:33 (woremacx) わーい
19:33 (yusukebe_x61) TENGA破産ふらぐktkr
19:33 (woremacx) wwwww
19:34 (woremacx) 自分しか使えないボットを書いてみた
19:34 (woremacx) なんかこう、他の人のもいじれるといいんだけどなぁ

ファイル置き場

Rails2 PDF が改訂されていた!

| 0 Comments | 0 TrackBacks
rails-pdf.png

ちょっと前に、Rails2 PDF という pdf をなんとなく買いました。PeepCode というサイトで、DRM フリーな pdf とスクリーンキャストを売り物にしているサイトです。ほかには、The Pragmatic Bookshelf とかがあるかと思います。

PeepCode の pdf を買うきっかけになったのは、Rails ML での宣伝を見かけたことです。宣伝から Web を開いて、掲載されているサンプルを見ました。サンプルの pdf は、レイアウトが心地よく、なにかにとりつかれて初 Paypal したのを覚えています。

残念ながら、ぼくが買った pdf は、Rails 2 の内容でした。確かその前後で Rails 2.1 が出ました。賢者モードになった自分に「レイアウトに感動するためだけに $9 払ったのか」と問い詰められ、少し落ち込んでました。


ところが、と・こ・ろ・がです!、今日、久しぶりにサイトを見たところ、

Updated for Rails 2.1! Previous purchasers can login or revisit the link originally sent via email to download the updated version.

Rails2 PDF

と書いてあるではありませんか!

なんということでしょう!さっそくダウンロードしましたとも!

Rails2 PDF の更新履歴

  • june 11, 2008
    • Updated for Rails 2.1
    • New sections on Enhanced Migrations, Change Table, Named Scope, Dirty Objects & Partial Updates, Timezone Support, Gem Dependencies and Git.
  • december 3, 2007
    • Minor bugfixes.
  • october 31, 2007
    • Added section about Foxy Fixtures.
  • october 19, 2007
    • Correctly identified forward-slash on p16.
    • Added section on asset servers and asset tags.
    • Added debugger example, with sample session.
    • Added appendix with changelogs from ActionMailer, ActionPack, ActiveRecord, and ActiveSupport.
  • october 17, 2007
    • First release

何度も改訂を重ねていてとても良心的ですね。

感想

同じタイトルの専門書を 4 冊買ったぼくとしては、コロコロ中身が変わる分野で物理的な本を少しだけ改訂、出版するビジネスモデルって、ちょっとひどいなぁと思いました。

少し高くてもいいから、DRM フリーの pdf で、かつ、定期的な改訂ありのものを平行して売ってくれたらなぁと。

*::Nowa をアップデートした

| 0 Comments | 0 TrackBacks

xcezx さんから、utf-8 フラグ周りで化けていると思われるバグの報告受けました。

encode_utf8 するオプションを追加して対策しました。

これはひどい。woremacx 自重。

Net::Amazon::S3 を Park Place のホストに使う

| 0 Comments | 0 TrackBacks

ローカルに建てた Park Place で使いたかったので。

$ diff -u Net/Amazon/S3.pm.orig  Net/Amazon/S3.pm
--- Net/Amazon/S3.pm.orig       2008-03-27 17:40:40.000000000 +0900
+++ Net/Amazon/S3.pm    2008-06-18 05:10:04.323364757 +0900
@@ -110,7 +110,7 @@

 use base qw(Class::Accessor::Fast);
 __PACKAGE__->mk_accessors(
-    qw(libxml aws_access_key_id aws_secret_access_key secure ua err errstr timeout retry)
+    qw(libxml aws_access_key_id aws_secret_access_key secure ua err errstr timeout retry s3_host)
 );
 our $VERSION = '0.44';

@@ -672,9 +672,10 @@
     $self->_add_auth_header( $http_headers, $method, $path )
         unless exists $headers->{Authorization};
     my $protocol = $self->secure ? 'https' : 'http';
-    my $url = "$protocol://s3.amazonaws.com/$path";
-    if ( $path =~ m{^([^/?]+)(.*)} && _is_dns_bucket($1) ) {
-        $url = "$protocol://$1.s3.amazonaws.com$2";
+    my $host = $self->s3_host || "s3.amazonaws.com";
+    my $url = "$protocol://$host/$path";
+    if ( !$self->s3_host && $path =~ m{^([^/?]+)(.*)} && _is_dns_bucket($1) ) {
+        $url = "$protocol://$1.$host$2";
     }

     my $request = HTTP::Request->new( $method, $url, $http_headers );

Firestorage.jp を Perl スクリプトから使う

| 0 Comments | 0 TrackBacks

LWP::UserAgent をつかってファイルをアップロードしてみましたよ!

コマンドラインからサクっと使えて便利ですよ!


あと、人には絶対見られたくない恥ずかしい写真とか動画とか送るとき用に、AES かけれるようにしてみたよ!

一時ファイルを作らずに、AES で暗号化しながらアップロード、ダウンロードしながら AES で解読とかしてみました。

どう考えても汚い書き方なので、なんかもっとキレイかつ楽ちんに書ける方法あったらおしえてください。

ふつうに使う

firestorage-put.pl

usage:
# 2 つめのパラメータは省略可
$ firestorage-put.pl "/path/to/your/file.avi" label.avi
#!/usr/bin/perl

use strict;
use HTTP::Request::Common;
use LWP::UserAgent ();

{
    sub HTTP::Request::Common::boundary {
        my @chr = ('A' .. 'Z', 'a' .. 'z', '0' .. '9');
        my @buf;
        push(@buf, $chr[int(rand(@chr))]) for (1..30);
        return '-' x 10 . join(q{}, @buf);
    }
}

sub upload {
    my $filebody = shift;
    my $filename = shift || $filebody;

    local $HTTP::Request::Common::DYNAMIC_FILE_UPLOAD = 1;

    my $ua = LWP::UserAgent->new(agent => "Shockwave Flash");
    my ($sec, $min, $hour, $mday, $mon, $year) = localtime(time);
    my $id = sprintf("%4d%02d%02d%02d%02d%02d%d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec, $$);

    my $exp = 7;

    my $url = "http://firestorage.jp/upload.cgi";
    my $res = $ua->post($url,
                        Content_Type => 'form-data',
                        Content => [
                            Filename => $filename,
                            processid => $id,
                            exp => $exp,
                            Filedata => [$filebody, $filename],
                            Upload => "Submit Query",
                        ]);
    if ($res->content =~ m!(http://firestorage.jp/download/\w+)!s) {
        return $1;
    }
    undef;
}

die unless @ARGV;
my $res = upload(@ARGV);
print $res ? $res : "failed";
print "\n";

AES で暗号化しながらつかう

usage:

$ dd if=/dev/zero of=2048 bs=2048 count=1
1+0 records in
1+0 records out
2048 bytes (2.0 kB) copied, 0.0172761 s, 119 kB/s

$ perl firestorage-aes-put.pl 2048
url: http://firestorage.jp/download/c56e...
key: 88c0f6d8a4e6aca71ccee0b2b022bf0c

$ perl firestorage-aes-get.pl http://firestorage.jp/download/c56e...
AES key: (キー 88c0f6d8a4e6aca71ccee0b2b022bf0c を入力)
saving 2048 ...done

firestorage-aes-put.pl

#!/usr/bin/perl

use strict;
use HTTP::Request::Common;
use LWP::UserAgent ();
use Crypt::CBC;
use Digest::MD5;

{
    sub HTTP::Request::Common::boundary {
        my @chr = ('A' .. 'Z', 'a' .. 'z', '0' .. '9');
        my @buf;
        push(@buf, $chr[int(rand(@chr))]) for (1..30);
        return '-' x 10 . join(q{}, @buf);
    }
}

sub upload {
    my $filebody = shift;
    my $filename = shift || $filebody;

    local $HTTP::Request::Common::DYNAMIC_FILE_UPLOAD = 1;

    my $ua = LWP::UserAgent->new(agent => "Shockwave Flash");
    my ($sec, $min, $hour, $mday, $mon, $year) = localtime(time);
    my $id = sprintf("%4d%02d%02d%02d%02d%02d%d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec, $$);

    my $exp = 7;

    require HTTP::Request::Common;
    my $url = "http://firestorage.jp/upload.cgi";
    my $request = HTTP::Request::Common::POST($url,
                        Content_Type => 'form-data',
                        Content => [
                            Filename => $filename,
                            processid => $id,
                            exp => $exp,
                            Filedata => [$filebody, $filename],
                            Upload => "Submit Query",
                        ]);
    my $code = $request->{_content};
    my $in_cd = 0;
    my $cb_looping;

    my $md5_inst;
    my $crypt_inst;

    my $len = $request->header('Content-Length');
    my $file_len = -s $filebody;
    my $new_len = $file_len + ($file_len % 16 ? 16 - $file_len % 16 : 16);
    $len += $new_len - $file_len;
    $request->header('Content-Length', $len);

    my $key;
    $request->{_content} = sub {
        my $coderes = $code->();
        unless ($cb_looping) {
            if ($coderes =~ /^(.*?)\015\012/) {
                $cb_looping = $1;
            }
        }
        my $payload;
        my $finish = 0;
        my $header_of_payload;
        if (!$in_cd && $coderes =~ /^Content-Disposition[^\012]+?; filename=/) {
            $in_cd++;
            my $loc = index($coderes, "\015\012\015\012");
            $header_of_payload = substr($coderes, 0, $loc + 4);
            $payload = substr($coderes, $loc + 4);
        } elsif ($in_cd && $coderes =~ /$cb_looping/) {
            $in_cd = 0;
            $finish++;
        } elsif ($in_cd) {
            $payload = $coderes;
        }

        if (length($payload)) {
            unless($md5_inst) {
                $key = Digest::MD5->md5_hex(time().$$.$payload);
                $crypt_inst = Crypt::CBC->new({
                    key            => $key,
                    cipher         => 'Rijndael',
                    iv             => Digest::MD5->md5('woremacx'),
                    regenerate_key => 0,
                    padding        => 'standard',
                    prepend_iv     => 0,
                });
                $crypt_inst->start('encrypt');
                $md5_inst = Digest::MD5->new;
            }
            $md5_inst->add($payload);
            $coderes = $crypt_inst->crypt($payload);
            if (length($header_of_payload)) {
                $coderes = $header_of_payload . $coderes;
            }
        }
        if ($finish) {
            # warn $md5_inst->hexdigest;
            my $left = $crypt_inst->finish;
            $coderes = $left . $coderes;
            $finish = 0;
        }
        $coderes;
    };

    my $res = $ua->request($request);
    if ($res->content =~ m!(http://firestorage.jp/download/\w+)!s) {
        return "url: $1\nkey: $key";
    }
    undef;
}

die unless @ARGV;
my $res = upload(@ARGV);
print $res ? $res : "failed";
print "\n";

firestorage-aes-get.pl

#!/usr/bin/perl

use strict;
use LWP::UserAgent;
use Digest::MD5;
use Crypt::CBC;

my $ua = LWP::UserAgent->new;
for my $url (@ARGV) {
    my $res = $ua->get($url);
    my $content = $res->content;
    while ($content =~ m!"(http://\w+\.firestorage\.jp/download[^\"]+?act=download_file[^\"]+)".*?>(.*?)</a>!g) {
        my ($url, $saveto) = ($1, $2);
        unless (-e $saveto) {
            my $key = get_key();
            # warn $key;
            my $cipher = Crypt::CBC->new({
                    key            => $key,
                    cipher         => 'Rijndael',
                    iv             => Digest::MD5->md5('woremacx'),
                    regenerate_key => 0,
                    padding        => 'standard',
                    prepend_iv     => 0,
                }) or die;
                $cipher->start('decrypt');

            open(my $fh, "> $saveto");
            my $total_len;
            my $recieved;
            my $decrypt = sub {
                my ($payload, $pp, $qq) = @_;
                $total_len ||= $pp->{_headers}->{'content-length'};
                $recieved += length($payload);
                print $fh $cipher->crypt($payload);
                if ($total_len == $recieved) {
                    print $fh $cipher->finish;
                }
            };
            print "saving $saveto ...";
            $ua->get($url, ':content_cb'   => $decrypt);
            close($fh);
            print "done\n";

        } else {
            print "$saveto already exists\n";
        }
    }
}

sub get_key {
    local($|) = 1;
    local(*TTY);
    open(TTY,"/dev/tty");
    my ($key1,$key2);
    system "stty -echo </dev/tty";
    do {
        print STDERR "AES key: ";
        chomp($key1 = <TTY>);
    } until $key1 =~ /^[a-f0-9]{32}$/;
    system "stty echo </dev/tty";
    close(TTY);
    $key1;
}

PicLens で AV 女優ブログの画像でハァハァする

| 0 Comments | 0 TrackBacks

PicLens がほんとすごい!

ぼくが PicLens を最初に知ったのは、june29 さんの TumbLensをHerokuにてリリース - cameraLady というエントリでした。june29 さんが、Tumblr を PicLens で見る TumbLens というサイトを作っのです。PicLens に感動するとともに、Tumblr を PicLens で見る発想に感動しました。


で、最近のぼくは、Flickr の新着ページ (Flickr: Photos & video from everyone in Flickr) を見るのに PicLens を使っていました。適当にカワイイ子が映っている写真を選んで、PicLens でひたすらその子が映ってる色々な写真を見るという使い方です。


そんな中、新たな PicLens サイトが現れました。

avmaster さんの AV女優ブログ検索 です。

AV女優ブログ検索運用日記 : Piclensを使って、スライドショーでみよう! - livedoor Blog(ブログ) で avmaster さんがエントリされているとおり、『女優さんの画像がスライドショーでみれる』のです!

画像集めてくるのめんどくせーなーと思ってたぼくにピッタリのサービスです!!


PicLens 対応のサービスがもっと増えるといいですね!

ciao!

なんか

| 0 Comments | 0 TrackBacks

優秀なハカーの皆さんならすでにご検討されたようなことなんでしょうけど、思いついたので一応書いておきますね。

DBIC って、redhat 系由来の遅くなるパッチの当たってる環境では、DBIC_NO_WARN_BAD_PERL=1 をつけないと STDERR にうざいメッセージを吐く機構が DBIx::Class::StartupCheck にあります。

それみたく、Catalyst では使っていいプラグインのホワイトリストを持っておいて、うざいメッセージを吐くだけじゃなくて CATALYST_ENABLE_BACKWARD_COMPATIBLE_PLUGIN=1 (英語適当) みたいなのをつけないと起動しない仕組みとか入れればいいんじゃないのかなと思いました。

perl-mongers.org の障害回復のお知らせ

| 0 Comments | 0 TrackBacks

こんにちは、woremacx です。

perl-mongers.org を含む、woremacx.com でホストしている全てのサービスがほぼ半日間(午前8時前から午後6時前くらいまで)アクセスできない状態となっておりました。

これまでは、アナウンスなしに突然繋がらなくなることが多々ありました。がしかし、現在は perl-mongers.org という公共性の高いサイトをホストしていることから、ご報告させていただくことにしました。

繋がらなくなっていた原因は、スイッチングハブの電源が抜けていたことです。単純ミスです。

perl-mongers.org をはじめ、woremacx.com でホストしている各種サービスをご利用のみなさまにご迷惑おかけしました。

今後とも、perl-mongers.org をよろしくお願いいたします!

Find recent content on the main index or look in the archives to find all content.

Recent Assets

  • rails-pdf.png
  • tenga.jpg

Categories

Pages

Powered by Movable Type 4.15b5-en