Skip to content

Instantly share code, notes, and snippets.

@panam510
Last active June 1, 2023 05:27
Show Gist options
  • Select an option

  • Save panam510/c5d0fd8cd969e2809f87ced217a4f6d8 to your computer and use it in GitHub Desktop.

Select an option

Save panam510/c5d0fd8cd969e2809f87ced217a4f6d8 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
# ニコニコ生放送 タイムシフト予約スクリプト
use 5.14.2;
use warnings;
use utf8;
use Encode;
use LWP::UserAgent;
use HTTP::Cookies;
use HTTP::Request::Common;
use Getopt::Std;
$Getopt::Std::STANDARD_HELP_VERSION = 1;
our $VERSION = 20230601;
binmode STDOUT, ":utf8";
# 引数の処理
our($opt_d, $opt_f, $opt_u, $opt_p);
getopts("dfu:p:");
#ID・パスワードは、以下シングルクォーテーション内に直書き。
#ただし、-u,-pオプションで渡されたらそちらを優先。
my $user = $opt_u // '[email protected]';
my $pass = $opt_p // 'password';
my $is_debug = $opt_d; #エラー時にサーバからの応答を出す(デバッグ用)
#my $is_force = $opt_f; #タイムシフト上書きフラグ(デフォルト上書きになったため廃止)
my $liveurl = shift;
my $vid;
#URLから動画ID取得
if ( !(defined($liveurl)) ){
#URLの指定がない
die "liveurl is required.\nUsage: $0 [-d] [-f] [-u userid] [-p password] liveurl\n";
}elsif( $liveurl !~ /\A(?:https?.*\/)?((?:lv)?(\d+))\z/){
#動画IDっぽい文字列がない
die "liveurl is not valid.\nUsage: $0 [-d] [-f] [-u userid] [-p password] liveurl\n";
}else{
#URLの「lv+数字」部分を取得
$vid = $1;
}
#ログイン部
my $url = 'https://account.nicovideo.jp/api/v1/login';
my %account = (
mail_tel => $user,
password => $pass,
);
my %ua_option = (
agent => "nicotsreserve.pl",
timeout => 30,
);
my $ua = LWP::UserAgent->new(%ua_option);
my $request = POST($url, [%account]);
my $cookie_jar = HTTP::Cookies->new;
my $response = $ua->request($request); #ログインを試行
$cookie_jar->extract_cookies($response); #user_sessionを取得
#予約部
$url = sprintf("https://live2.nicovideo.jp/api/v2/programs/%s/timeshift/reservation",$vid);
$request = POST($url);
$cookie_jar->add_cookie_header( $request );
$response = $ua->request($request);
my $authflag = $response->header("X-Niconico-Authflag");
unless (defined $authflag && ($authflag == 1 || $authflag == 3)){
#ログイン失敗。
#アカウントID・パスワードが違うか、ニコニコのメンテナンス中?
&debugmsg;
die "Can't login. Incorrect account, or under maintenance.\n";
}
my $content = $response->content;
if ( $content =~ /\"status\":200/){
#うまく行ったっぽい
&debugmsg;
say "Hoolay! Reservation succeeded. liveid: ".$vid;
}elsif( $content =~ /PROGRAM_NOT_FOUND/){
#生放送が存在しない
&debugmsg;
die "Reservation failed. Program not found.\n";
}elsif( $content =~ /EXPIRED_(GENERAL|PREMIUM)/){
#予約期限が切れている。一般会員だと「EXPIRED_GENERAL」、プレミアム会員だと「EXPIRED_PREMIUM」が返る
&debugmsg;
die "Reservation failed. Reservation has expired.\n";
}elsif( $content =~ /DUPLICATED/){
#すでに予約されている
&debugmsg;
die "Already reserved.\n";
}else{
#未検証エラー
#予約件数の上限に達しているなど?
&debugmsg;
die "Reservation failed. Add the -d flag and check the cause.\n";
}
#デバッグ用関数
sub debugmsg {
if($is_debug){
say STDERR "An error occurred. The response is shown below:";
say STDERR $response->as_string;
}
}
sub HELP_MESSAGE {
say "Usage: $0 [-d] [-f] [-u userid] [-p password] liveurl";
say '';
say 'liveurlは以下いずれかの形式で指定:';
say ' http://live.nicovideo.jp/watch/lv012345678';
say ' lv012345678';
# say ' 012345678';
say '';
say 'Option:';
say ' -d 予約できなかった際、サーバからの応答を標準エラーへ出力する(デバッグ用)';
# say ' -f 予約件数の上限に達しているとき、期限切れの予約があれば上書きする';
say ' -u \'[email protected]\' ユーザID。スクリプト内の記述より優先される';
say ' -p \'password\' パスワード。同上';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment