ジャンル不定の日記です。

VirtualboxでVM起動してると母艦で音がでない

メイン機を今のマザーに変えてからなんだが、
VirtualboxでVMを起動してるとホストPCの方で音が出なくなる。

先日書いたが、今のマザーがサウンドデバイスがアナログとHDMIで2つあって何も設定しないとHDMIが先。
アナログで音出してるからHDMIの優先順位下げてるんで、それとの関係だと思うんだが、どうにかならんもんだろうか・・・


eBayで詐欺の返金

先日eBayで、

Android5.1
サイズ: 10インチ
メモリ: 1GB
ストレージ: 8GB
解像度: 1024x600

って、とりあえず使えそうなスペックのタブが、送料込み€11.0、なにこれ安いって感じで出品されてるのを見つけて、
出品者が作ったばっかのアカウントだったから詐欺じゃないかと思ったが、PayPalは詐欺で返金してもらいやすいようなんで即落してみた。

[流れ]
注文→決済
翌日連絡がなかったので、さらに次の日「いつ発送するの?」的な文で連絡。
相手から返信はなく、数日後にeBayから、「出品が消えたから返金求められるよ」的なメール。
メールに従って返金請求。
相手から連絡無しで、PayPal(eBay?)が全額返金。

ってな感じになった。
カードの方はまだ反映してないが、PayPalの履歴には「カードに返金」となってた。

80人近く買ってる人いたけど、返金求めない人がいたらお金GET!の詐欺なのかな?


PayPalアカウントに返金だったら、PCIeのSATA増設かUSB接続のテレビチューナー買おうかと思ってたが、カードに返金なんだね。

日本で使えそうな南米向けのテレビチューナーが1000円ちょいで存在するらしいんで、
日本のテレビチューナーは暗号化されててLinuxで動かないから、南米チューナー欲しい。

Google Drive API使えた

先程はGoogle Developer Consoleで認証情報が設定できなくて後日にしようと思ってたが、Googleさん治ってたんで、Google Drive APIを使ったバックアップを導入した。
APIは、怪しいプログラムをインストールするよりも自分で作っちゃおう。って考えたので、慣れたPerl使った。


導入手順は、
  1. Google Developer Consoleでプロジェクトを作成。
  2. Drive APIを有効にして他は無効に。
  3. OAuth2.0クライアントIDを作成。(種類は「その他」で作った)
  4. "code"の取得。
  5. "refresh_token"の取得。
さっきできなくてハマったが、DNS関連だと思うがタイミングが悪いと3.のクライアントIDの作成ができない。

3.でクライアントIDを作成すると"クライアントID"と"クライアント シークレット"が表示されるが、両方共プログラムで使うのでメモっとく。

4.の"code"は、5.の"refresh_token"を取得するために必要でブラウザでURLにアクセスしてプログラムを許可すると表示される。
https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/drive&response_type=code&redirect_uri=urn:ietf:wg:oauth:2.0:oob&client_id=[クライアント ID]
↑接続するURLはこんな感じ。
scopeはプログラムに与える権限で、"https://www.googleapis.com/auth/drive"はGoogle Driveの全権限。リードオンリーとかもできる。
response_typeは、"code"の場合はredirect_uriで指定したURLの末尾にクエリでつけられてリダイレクトされる。
クライアントプログラムを作るのでリダイレクト用のページなど存在しないが、その場合は"urn:ietf:wg:oauth:2.0:oob"を指定するとGoogleのページでコードを表示してくれる。
取得できたコードは5.の"refresh_token"を取得するために1回だけ必要。

5.の"refresh_token"の取得は、POSTでリクエストしないといけないので、curlコマンドを使って、
curl -d redirect_uri=urn:ietf:wg:oauth:2.0:oob -d client_id=[クライアント ID] -d client_secret=[クライアント シークレット] -d grant_type=authorization_code -d code=[ブラウザで取得したコード] https://accounts.google.com/o/oauth2/token
こんな感じでリクエストを投げるとJSON形式で返ってくる。
"refresh_token"だけが必要。


で、ファイルPATH(又はカレントディレクトリのファイル名)をパラメータで渡すとGoogle DriveにアップロードするPerlスクリプトを作った。
#!/usr/bin/perl
###
$userId='Google ID';
$client_id='クライアントID';
$client_secret='クライアント シークレット';
$refresh_token='refresh_token';

$Folder='フォルダID';

$Type{'gz'}='application/gzip';
###
###
use LWP::UserAgent;
use JSON;
###
my $res=&HttpRequest('POST',"https://www.googleapis.com/oauth2/v3/token","client_id=$client_id&client_secret=$client_secret&refresh_token=$refresh_token&grant_type=refresh_token");
our ($access_token)=$res=~/"access_token": "([^"]+)"/;
die if(!$access_token);

foreach(@ARGV){
    my ($dir,$name)=$_=~/^(.*?)\/?([^\/]+)$/;
    my ($ext)=$name=~/\.([^\.]+)$/;
    my $type=$Type{$ext}||'application/octet-stream';
    my $old=JSON::from_json(&HttpRequest('GET',"https://www.googleapis.com/drive/v2/files?q=@{[&UrlEncode('\''.$Folder.'\' in parents and title=\''.$name.'\'')]}"));
    my $new=JSON::from_json(&FileUpload($dir,$name,$type));
    if($new->{'id'}){
        foreach(@{$old->{'items'}}){
            &HttpRequest('DELETE',"https://www.googleapis.com/drive/v2/files/$_->{'id'}");
        }
    }
    sleep(1);
}
###
sub HttpRequest{
    my $method=shift;
    my $url=shift;
    my $body=shift;
    my $ua=LWP::UserAgent->new;
    my $req;
    if($method eq 'GET' || $method eq 'DELETE'){
        $req=HTTP::Request->new($method=>$url);
    }else{
        $req=HTTP::Request->new(POST=>$url);
        $req->content_type('application/x-www-form-urlencoded');
        $req->header(Content_length=>0) if(!$body);
        $req->content($body);
    }
    $req->header(Authorization=>"OAuth $access_token") if($access_token);
    my $res=$ua->request($req);
    return($res->content);
}
###
sub FileUpload{
    my $dir=shift;
    my $name=shift;
    my $type=shift;
    my($file,$count,$body);
    open(FILE,"$dir/$name");
    while(<FILE>){
        $file.=$_;
    }
    close(FILE);
    while($file=~/\-\-$name$count/){
        $count++;
    }
    $body="--$name$count\nContent-Type: application/json; charset=UTF-8\n\n{'title':'$name','parents':[{'id':'$Folder'}]}\n";
    $body.="--$name$count\nContent-Type: $type\n\n".$file."\n--$name$count--\n";
    my $ua=LWP::UserAgent->new;
    my $req=HTTP::Request->new(POST=>"https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart");
    $req->content_type("multipart/related; boundary=\"$name$count\"");
    $req->content_length(length($body));
    $req->content($body);
    $req->header(Authorization=>"OAuth $access_token");
    my $res=$ua->request($req);
    return($res->content);
}
###
sub UrlEncode{
    my $str=shift;
    $str=~s/([^\w\-\.\~])/'%'.uc(unpack('H2',$1))/eg;
    return($str);
}
###
こんな感じ。
赤字のとこは自分用に入力。

普通にファイルシステムを使う感じとはだいぶ違ってて、把握するのが結構難しかった。
普通のファイルシステムと一番違うのが、PATH的な概念がなくPATH指定で対象を選択できない。
ローテートするのが面倒かと思ったんだが、PATHが無いので同じ場所に同名ファイルを置けるんで、同じ場所にアップロードして成功したら古いの削除しちゃうだけで良いことに気づいたんで、そうした。
アップロードするファイルを置くフォルダは、PATHが無いので毎回検索クエリを投げなきゃダメかとも思ったが、
フォルダのIDはブラウザでフォルダにアクセスした時のURL末尾の文字列と同じだったんで、プログラムに直接設定する仕様にした。

%Typeで拡張子を設定しておけばアップロード時にファイルタイプを指定して送るが、未設定のファイル場合は"application/octet-stream"で送る。

ファイルPATHをパラメータとして渡すとアップロードするけど、パラメータのPATHはスペース区切りで複数可。
アップロードに1秒以上かかるだろうが、秒間10リクエストまでの制限があるようなので、1ファイル毎に1秒寝る。

アップロード成功したら対象フォルダ内の古い同名ファイルは削除するが、
失敗した場合(idが取得できなかった場合)は、古いのそのままにしとく。



てな感じで、Google DriveのAPIが使えたんで、
先日のファイル暗号化をバックアップスクリプトに導入して、今回のGoogle Driveのアップロードスクリプトを使ってクラウドでバックアップするようにした。
これで万が一自宅PCのデータがバックアップストレージからの復元すらできないような状況に陥っても、致命的な状況に陥るのは回避できそう。

Google Driveでのバックアップを導入しようとしたが・・・

昨日バックアップファイルの暗号化をシェルスクリプトでやるようにして、暗号化したファイルをGoogle Driveに保存するようにしようとした。

Google DriveはArch Linux + KDEの標準では使えず、AURで「google drive」で検索すると、それっぽいのが複数出てきて迷う。
google-drive-ocamlfuse ってのが、マウントできるツール。
grive ってのが、同期ツール。
その他複数あるのは、Google Drive のAPIコマンドをCUIから使うためのコマンド。
って感じぽい。


AURのプログラムはどれもきちんとメンテされるのか怪しいし、APIコマンドを使うなら、Perlで自分で作っちゃえばよくね?
ってことに気づいた。
手元のマインOSが変わることや、Google以外のストレージに移行する場合なんかも、自前で作っちゃったほうが流用効くし。

以前PerlでGmailのAPI使うプログラムを作ったんで、それ参考にGoogle Drive のAPIを・・・
とやったんだが、なんかGoogle Developer Consoleで認証情報のところに行くと、
「サービス アカウントを読み込めませんでした。」
とエラーが出る。
無視してOAuthのキーを作成しようとすると、
「読み込めませんでした」
と表示されて無理・・・

FirefoxではなくChromeで試したりしてもダメ。
わからなくて、表示を英語にしてみてググったが、DNSの不整合でつながってないぽい?
日を改めてやることにするかな。


先日Windows10入れたらoneDriveとかってのがあったから、
GoogleじゃなくてMicrosoftのストレージも試してみようかな。APIあるよね?