Skip to content

Instantly share code, notes, and snippets.

@AndroPlus-org AndroPlus-org/Upload.ps1
Last active Jun 17, 2018

Embed
What would you like to do?
Upload recorded files to Google Drive (use with Mirakurun + EPGStation + rclone)
#某所のチューニングです 各自地上波は再設定して下さい
#UHFチャンネルナンバーではなくch13を0と見たときの数字です
- name: NHK総合・大阪
type: GR
channel: '11'
- name: NHKテレ・大阪
type: GR
channel: '0'
#- name: サンテレビ
# type: GR
# channel: '13'
- name: KBS京都
type: GR
channel: '10'
- name: MBS毎日放送
type: GR
channel: '3'
- name: ABCテレビ
type: GR
channel: '2'
- name: テレビ大阪
type: GR
channel: '5'
- name: 関西テレビ
type: GR
channel: '4'
- name: 読売テレビ
type: GR
channel: '1'
#====================================
#BS
#radi-sh製BonDriver_BDAを使用する場合S.iniに記載されているCHナンバーを使用すること
- name: NHK BS1
type: BS
channel: '017'
serviceId: 101
- name: NHK BS1 (サブ)
type: BS
channel: '017'
serviceId: 102
- name: NHK BSプレミアム
type: BS
channel: '018'
serviceId: 103
- name: NHK BSプレミアム (サブ)
type: BS
channel: '018'
serviceId: 104
- name: BS日テレ
type: BS
channel: '015'
serviceId: 141
- name: BS日テレ (サブ)
type: BS
channel: '015'
serviceId: 142
- name: BS朝日
type: BS
channel: '000'
serviceId: 151
- name: BS朝日 (サブ)
type: BS
channel: '000'
serviceId: 152
- name: BS-TBS
type: BS
channel: '001'
serviceId: 161
- name: BSジャパン
type: BS
channel: '003'
serviceId: 171
- name: BSフジ
type: BS
channel: '016'
serviceId: 181
- name: WOWOWプライム
type: BS
channel: '002'
serviceId: 191
isDisabled: true
- name: WOWOWライブ
type: BS
channel: '004'
serviceId: 192
isDisabled: true
- name: WOWOWシネマ
type: BS
channel: '005'
serviceId: 193
isDisabled: true
- name: スター・チャンネル1
type: BS
channel: '010'
serviceId: 200
isDisabled: true
- name: スター・チャンネル2
type: BS
channel: '006'
serviceId: 201
isDisabled: true
- name: スター・チャンネル3
type: BS
channel: '006'
serviceId: 202
isDisabled: true
- name: BS11
type: BS
channel: '009'
serviceId: 211
isDisabled: true
- name: TwellV
type: BS
channel: '011'
serviceId: 222
- name: 放送大学BS1
type: BS
channel: '014'
serviceId: 231
- name: 放送大学BS2
type: BS
channel: '014'
serviceId: 232
- name: 放送大学BS3
type: BS
channel: '014'
serviceId: 233
- name: グリーンチャンネル
type: BS
channel: '021'
serviceId: 234
isDisabled: true
- name: BSアニマックス
type: BS
channel: '007'
serviceId: 236
isDisabled: true
- name: FOXスポーツ&エンターテイメント
type: BS
channel: '012'
serviceId: 238
isDisabled: true
- name: BSスカパー!
type: BS
channel: '013'
serviceId: 241
isDisabled: true
- name: PX-W3U4-S0
types:
- BS
command: D:\DTV\bin\BonRecTest\BonRecTest.exe --decoder D:\DTV\bin\BonRecTest\B25Decoder.dll --driver D:\DTV\bin\BonRecTest\BonDriver_PX_x3U4_S.dll --space <satelite> --channel <channel> --output -
decoder: ~
isDisabled: false
- name: PX-W3U4-S1
types:
- BS
command: D:\DTV\bin\BonRecTest\BonRecTest.exe --decoder D:\DTV\bin\BonRecTest\B25Decoder.dll --driver D:\DTV\bin\BonRecTest\BonDriver_PX_x3U4_S.dll --space <satelite> --channel <channel> --output -
decoder: ~
isDisabled: false
- name: PX-W3U4-T0
types:
- GR
command: D:\DTV\bin\BonRecTest\BonRecTest.exe --decoder D:\DTV\bin\BonRecTest\B25Decoder.dll --driver D:\DTV\bin\BonRecTest\BonDriver_PX_x3U4_T.dll --output - --channel <channel>
decoder: ~
isDisabled: false
- name: PX-W3U4-T1
types:
- GR
command: D:\DTV\bin\BonRecTest\BonRecTest.exe --decoder D:\DTV\bin\BonRecTest\B25Decoder.dll --driver D:\DTV\bin\BonRecTest\BonDriver_PX_x3U4_T.dll --output - --channel <channel>
decoder: ~
isDisabled: false
#config.jsonの変更が必要です
#識別するため%ID%をファイル名の最後に追加
#"recordedFormat": "%YEAR%年%MONTH%月%DAY%日%HOUR%時%MIN%分-
#Googleドライブでは.m2ts拡張子でないとエンコードされません
#"fileExtension": ".m2ts",
#プログラムID
$program_id = "$env:PROGRAMID"
#今日の月
$this_month = Get-Date -UFormat "%Y年%m月"
#====================ユーザ設定====================
#--------------------Google ドライブへアップロード--------------------
#0=無効、1=有効
$gdrive_toggle = 1
#アップロード用ディレクトリ
$bas_folder_path = 'D:\DTV\upload'
#アップロード中の一時ディレクトリ
$tmp_bas_folder_path = 'D:\DTV\uploadtmp\'
#rclone.exeのパス
$rclone_path = 'D:\DTV\bin\rclone\rclone.exe'
#rcloneの設定ファイルのパス
#あらかじめrclone configで認証を済ませてください
$config_path = 'C:\Users\user\.config\rclone\rclone.conf'
#アップロード先のフォルダ指定
#driveはrclone configで設定したremoteの名前です
$dest_folder_path = "drive:@録画/${this_month}"
#--------------------一時パスやログなどの設定--------------------
#実行日時
$run_datetime = Get-Date -UFormat "%Y%m%d-%H%M%S"
#$run_datetime="20180602-231420"
#一時フォルダのパス
$tmp_folder_path = "${tmp_bas_folder_path}${run_datetime}"
# ログのパスと名前
$log_path = "D:\DTV\logs"
$log_file = "${log_path}\uploadlog_${run_datetime}.txt"
#ログ取得開始
Start-transcript -path "${log_file}"
#"--------環境変数--------"
#Get-ChildItem env:
#"--------環境変数--------"
Write-Output "プログラムID: $program_id"
#====================ファイルがロックされているか確認する====================
#Thanks guitarrapc!
#https://github.com/guitarrapc/PowerShellUtil/blob/master/Test-FileLock/Test-FileLock.psm1
function Filelock {
# ファイルロック中のファイルを検査する
param (
[parameter(
position = 0,
mandatory
)]
[System.IO.FileInfo]
$Path
)
try {
# initialise variables
$script:filelocked = $false
# attempt to open file and detect file lock
$script:fileInfo = New-Object System.IO.FileInfo $Path
$script:fileStream = $fileInfo.Open([System.IO.FileMode]::OpenOrCreate,
[System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)
# close stream if not lock
$f1 = $fileStream
Write-Host $f1
$f2 = $filelocked
if ($fileStream) {
$fileStream.Close()
$f3 = $fileStream
$f4 = $filelocked
}
}
catch {
# catch fileStream had falied
$filelocked = $true
}
finally {
# return result
[PSCustomObject]@{
path = $Path
filelocked = $filelocked
}
}
}
function Test-FileLock {
param (
[parameter(
position = 0,
mandatory
)]
[string]
$Path
)
try {
if (Test-Path -LiteralPath $Path) {
if ((Get-Item -path $path) -is [System.IO.FileInfo]) {
return (filelock -Path $Path).filelocked
}
elseif ((Get-Item -LiteralPath $Path) -is [System.IO.DirectoryInfo]) {
Write-Verbose "[$Path] detect as $((Get-Item -LiteralPath -path $Path).GetType().FullName).
Skip cehck."
}
}
else {
Write-Error "[$Path] could not find.
+ CategoryInfo : ObjectNotFound: ($Path), ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand"
}
}
catch {
Write-Error $_
}
}
#====================8.3形式のファイル名を取得する====================
Function Get-ShortPath {
Param([string]$name)
BEGIN { $fso = New-Object -ComObject Scripting.FileSystemObject }
PROCESS {
try {
$fsi = (Get-Item -LiteralPath $name -ErrorAction Stop)
}
catch {
return $name
}
$fullname = $fsi.FullName
if ($fsi.psiscontainer) {
return $fso.GetFolder($fullname).ShortPath
}
else {
return $fso.GetFile($fullname).ShortPath
}
}
}
#====================アップロードできなかった時のアラートメール====================
Function Send-Aleart {
$mail = @{
from = "XXXXXXXXXX@example.com";
to = "XXXXXXXXXX@example.com";
smtp_server = "smtp.gmail.com";
smtp_port = 587;
user = "XXXXXXXXXX@example.com";
password = "XXXXXXXXXX";
}
$password = ConvertTo-SecureString $mail["password"] -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $mail["user"], $password
Send-MailMessage -To $mail["to"] `
-From $mail["from"] `
-SmtpServer $mail["smtp_server"] `
-Credential $credential `
-Port $mail["smtp_port"] `
-Subject "録画鯖 アップロード失敗" `
-Body "録画したファイルをアップロードできませんでした。" `
-Encoding UTF8 `
-UseSsl
}
#====================ファイルがロックされていないか確認する====================
#mp4ファイルが存在する = エンコードした場合
Write-Output "Checking MP4 file..."
if ( Test-Path "${bas_folder_path}\*${program_id}.mp4" ) {
#録画したファイルのパスを取得する
$mp4_file = Get-ChildItem -LiteralPath "${bas_folder_path}" | where { $_.Name -match "${program_id}.mp4"}
$mp4_file_83path = Get-ShortPath("${bas_folder_path}\${mp4_file}")
#エンコード完了するまで待機する
Write-Output "Wait for file to be freed by process..."
while (Test-FileLock -Path "${mp4_file_83path}") { Start-Sleep 10 }
Write-Output "MP4 file ready!"
}
#念のため5秒待機
Write-Output "Waiting..."
Start-Sleep 5
#m2tsファイルが存在する = エンコードしていないかTS削除しなかった場合
Write-Output "Checking TS file..."
if ( Test-Path "${bas_folder_path}\*${program_id}.m2ts" ) {
#録画したファイルのパスを取得する
$ts_file = Get-ChildItem -LiteralPath "${bas_folder_path}" | where { $_.Name -match "${program_id}.m2ts"}
$ts_file_83path = Get-ShortPath("${bas_folder_path}\${ts_file}")
#使用中かどうか確認し、使用中なら10秒待機して再確認する
Write-Output "Wait for file to be freed by process..."
while (Test-FileLock -Path "${ts_file_83path}") { Start-Sleep 10 }
Write-Output "TS file ready!"
}
#====================Google ドライブへアップロードする====================
#Google ドライブの指定したフォルダへアップロード後、削除する
if ("${gdrive_toggle}" -eq "1") {
#一時フォルダを作成
Write-Output "Creating temp folder..."
New-Item "${tmp_folder_path}" -itemType Directory -Force
#念のため10秒待機
Write-Output "Waiting..."
Start-Sleep 10
#出力されたファイルを一時フォルダへ移動
Write-Output "Moving files to temp folder..."
Get-ChildItem "${bas_folder_path}" | where { $_.Name -match "${program_id}"} | Move-Item -Destination "${tmp_folder_path}"
Write-Output "Uploading..."
$arg = "copy ${tmp_folder_path} ${dest_folder_path} -v --config ${config_path}"
$proc = Start-Process -FilePath "${rclone_path}" -ArgumentList ${arg} -PassThru -NoNewWindow
#タイムアウトの初期化
$timeouted = $null
#3時間 (10800秒) 経ってもアップロード完了していなければエラーで止まったと見なす
#Google ドライブは通常13GBのファイルを30分程度でアップロードできる
#よほど遅い回線か、長時間番組を録らない限り大丈夫なはず
$proc | Wait-Process -Timeout 10800 -ea 0 -ev timeouted
if ( $timeouted ) {
Write-Output "Upload failed with timeout..."
#プロセスを終了する
$proc | kill
#アラートメールを送信する
Send-Aleart
}
elseif ($proc.ExitCode -eq 0) {
#Google ドライブへのアップロードが完了したら一時フォルダを削除
Write-Output "Upload completed!"
Write-Output "Cleaning temp folder..."
Remove-Item "${tmp_folder_path}" -Recurse
}
#空フォルダを削除
Set-Location ${tmp_bas_folder_path}
Get-ChildItem -Recurse | Where-Object { $_.GetType().Name -eq "DirectoryInfo" -and $_.GetFiles().Count -eq 0 } | Remove-Item -Recurse
#ログ取得終了
Stop-transcript
#古いログファイルを最終更新日順に並べ、最新30個は除外して削除する
Get-ChildItem "${log_path}" |
Sort-Object LastWriteTime -Descending |
Select-Object -Skip 30 |
foreach {Remove-Item $_.FullName}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.