LostFilm.TVのbash上のパーサーRSS:Transmission + SQLite + mkvtools

あなたの健康を祈っています、Habr!



RSSフィードのパーサーに関する前のトピックLostFilm.TVに応えて、約4か月間エラーなく動作しているバージョンをレイアウトしたいと思います。

このアイデアの本質は、サーバーがシリーズをダウンロードしてフォルダーに入れ、カバーと通常のヘッダーでファイルを埋めることです。

ただし、システム全体に関与するスクリプトは1つだけではなく、スクリプトのセット全体も含まれます。 このようなシステムでは、スクリプトは前処理と後処理に分けられます。

そしてもちろん、麻酔薬の場合:各シリーズのファイルは美しく見え、フォルダーに配置される必要があります。





プリハンドラー



パーサー操作アルゴリズム


•RSSフィードを読む

•個々の要素に解析する

•古いアイテムを取り除く

•データベースと伝送ダウンロードキューに新しい要素を追加する



パーサーコード


#!/bin/bash export PRFX="/var/lib/transmission-daemon" export SELF=$(basename $(readlink -f $0)) #   . $PRFX/.$SELF/config #    . $PRFX/.funcs/sqlite . $PRFX/.funcs/transmission #       check_last() { if [ ! -f $LFW_RSS_LAST ] || [ $1 -gt $(cat $LFW_RSS_LAST) ]; then printf "$1" > $LFW_RSS_LAST return 0 else return 1 fi } #    parse_title() { echo "$1" | sed -r 's/^([^(]+)[. ]+\((.+)\)[. ]+([^(]+)[. ]+\((.+)\)[. ]*(\[720p\]){0,1}[. ]*\(S0*([0-9]+)E0*([0-9]+).*\)$/\1|\2|\3|\4|\5|\6|\7/' } logger -t $SELF -- '  RSS/Atom' #  RSS- rsstail -1NHlp -n 30 -u "$LFW_RSS_URL" | #        iconv -f cp1251 | sed -r '/^\s*$/d; s/^\s+//; s/\s+$//' | sed -r '$!N; s/\n/|/; $!N; s/\n/|/' | #    UNIXTIME      (IFS='|'; while read item_title item_link item_date; do printf '%s|%s|%s\n' $(date -d "$item_date" +%s) "$item_title" "$item_link" done) | sort | #    (IFS='|'; while read item_date item_title item_link; do if check_last $item_date; then printf '%s|%s|%s\n' $item_date "$(parse_title "$item_title")" "$item_link" fi done) | #    (IFS='|'; while read date name_ru name_en title_ru title_en hd season episode link; do #      id=$(printf 'SELECT id FROM series WHERE title_en = "%s";' "$name_en" | db_query $LFW_DB) #    ,   if [ -n "$id" ]; then #  -     tr_file="/tmp/lostfilm_$(uuidgen).torrent" if wget -nv -q --header "$LFW_WGET_AUTH" "$link" -O "$tr_file"; then #         ,     if [ -z $(printf 'SELECT id FROM episodes WHERE series = %d AND season = %d AND episode = %d;' $id $season $episode | db_query $LFW_DB) ]; then printf 'INSERT INTO episodes (series, season, episode, title_en, title_ru) VALUES (%d, %d, %d, "%s", "%s");' \ $id $season $episode $title_en $title_ru | db_query $LFW_DB fi #     HD  SD   if [ -z "$hd" ]; then file=$(transmission-show "$tr_file" | sed -r '/^Name:/!d; s/^Name:\s*(.+)\s*$/\1/') #' printf 'INSERT INTO files (id, date, filename) VALUES ((SELECT id FROM episodes WHERE series = %d AND season = %d AND episode = %d), %d, "%s");' \ $id $season $episode $date $file | db_query $LFW_DB if [ $(printf 'SELECT tracked FROM series WHERE id = %d;' $id | db_query $LFW_DB) -ne 0 ]; then transmission --add "$tr_file" --start > /dev/null fi logger -t $SELF -- $(printf '  SD  «%s» ( %s,  %s) — «%s»' "$name_ru" "$season" "$episode" "$title_ru") #' else file=$(transmission-show "$tr_file" | sed -r '/^Name:/!d; s/^Name:\s*(.+)\s*$/\1/') #' printf 'INSERT INTO files_hd (id, date, filename) VALUES ((SELECT id FROM episodes WHERE series = %d AND season = %d AND episode = %d), %d, "%s");' \ $id $season $episode $date $file | db_query $LFW_DB if [ $(printf 'SELECT tracked_hd FROM series WHERE id = %d;' $id | db_query $LFW_DB) -ne 0 ]; then transmission --add "$tr_file" --start > /dev/null fi logger -t $SELF -- $(printf '  HD  «%s» ( %s,  %s) — «%s»' "$name_ru" "$season" "$episode" "$title_ru") #' fi fi [ -f "$tr_file" ] && rm -f "$tr_file" fi done) logger -t $SELF -- ''
      
      







ポストハンドラー



さらに、ファイルをダウンロードするときは、美的な外観にする必要があります(私の妻は、シリーズの名前を持つフォルダーに配置されたすべてのシリーズを見て、シーズン/エピソード番号とシリーズの名前、およびシリーズの美しいカバーアイコンを含むファイル名を持つことを好む)

シリーズをダウンロードした後、lostfilm.tvを含むさまざまな種類のファイルの処理を目的とした一連のスクリプトが起動されます。



後処理スクリプトアルゴリズム


•デーモンから受け取ったファイル名のデータベース内の存在を確認します。そうでない場合はシャットダウンします

•ベースからカバーを取り外します

•mkvtoolsの適用(英語のトラックのフィルター、カバーの挿入、レコードのタイトル)

•シリーズの名前でフォルダーに入れる(作成しない場合は作成する)

•署名者にメールとSMSで通知する(私の電話、妻にメールで)



後処理スクリプト


 #!/bin/bash export SELF="lostfilm-rss" #   . $PRFX/.$SELF/config #    . $PRFX/.funcs/sqlite . $PRFX/.funcs/transmission . $PRFX/.funcs/mkv_tools . $PRFX/.funcs/mail_notify . $PRFX/.funcs/utils . $PRFX/.funcs/sms_notify MAIL_LIST_HD="me@a***n.ru" #        data="$(printf 'SELECT s.title_ru, e.season, e.episode, e.title_ru, s.id FROM episodes e, series s, files_hd f WHERE e.series = s.id AND e.id = f.id AND f.filename = "%s";' "$TR_TORRENT_NAME" | db_query $LFW_DB)" #    ,   if [ -n "$data" ]; then #    name=$(echo $data | cut -d'|' -f1) s=$(echo $data | cut -d'|' -f2) e=$(echo $data | cut -d'|' -f3) part=$(echo $data | cut -d'|' -f4) id=$(echo $data | cut -d'|' -f5) #    mkv_file=$(printf '/mnt/videos/Series.HD/%s [%s.%s] — %s.mkv' "$name" "$s" "$e" "$part") #   - mkv_title=$(printf '«%s» •  %s,  %s • «%s»' "$name" "$s" "$e" "$part") #     mkv_poster="/tmp/mkv_poster_$(uuidgen).jpg" printf 'SELECT data FROM posters WHERE series = %d ORDER BY date DESC LIMIT 1;' $id | db_query $LFW_DB | base64 -d - > $mkv_poster logger -t $SELF -- $(printf ' HD  «%s» ( %s,  %s) — «%s»' "$name" "$s" "$e" "$part") #' #  -    if to_mkv "/mnt/torrent/$TR_TORRENT_NAME" "$mkv_file" "$mkv_title" "$mkv_poster"; then logger -t $SELF -- $(printf ' HD  «%s» ( %s,  %s) — «%s»' "$name" "$s" "$e" "$part") #' #    ,       ,     ,      transmission -t $TR_TORRENT_ID --remove-and-delete > /dev/null logger -t $SELF -- $(printf '   HD  «%s» ( %s,  %s) — «%s»' "$name" "$s" "$e" "$part") #' #    mail_notify "$MAIL_LIST_HD" "$(printf '   «%s» ( %s,  %s) — «%s»' "$name" "$s" "$e" "$part")" \ "$(printf '<h3>«%s» ( %s,  %s) — «%s»</h3><br/><i>: HD</i>' "$name" "$s" "$e" "$part")" #   sms_notify a***n "$(printf '  «%s» ( %s,  %s) — «%s» \n[%s]' "$name" "$s" "$e" "$part" "$(disk_info)")" else logger -t $SELF -- $(printf '    HD  «%s» ( %s,  %s) — «%s»' "$name" "$s" "$e" "$part") #' fi rm -f $mkv_poster fi
      
      







データベース



スクリプトから、作業はデータベースに関するものであることがわかります。私のバージョンではSQLite3が使用されています



データベース構造


 CREATE TABLE episodes ( id INTEGER PRIMARY KEY AUTOINCREMENT, series INTEGER REFERENCES series(id) ON UPDATE CASCADE ON DELETE CASCADE, season INTEGER NOT NULL, episode INTEGER NOT NULL, title_en TEXT NOT NULL, title_ru TEXT NOT NULL, UNIQUE(series, season, episode) ); CREATE TABLE files ( id INTEGER PRIMARY KEY REFERENCES episodes(id) ON UPDATE CASCADE ON DELETE CASCADE, date INTEGER NOT NULL, filename TEXT NOT NULL ); CREATE TABLE files_hd ( id INTEGER PRIMARY KEY REFERENCES episodes(id) ON UPDATE CASCADE ON DELETE CASCADE, date INTEGER NOT NULL, filename TEXT NOT NULL ); CREATE TABLE posters ( id INTEGER PRIMARY KEY AUTOINCREMENT, series INTEGER REFERENCES series(id) ON UPDATE CASCADE ON DELETE CASCADE, date INTEGER NOT NULL, data TEXT NOT NULL ); CREATE TABLE series ( id INTEGER PRIMARY KEY AUTOINCREMENT, title_en TEXT NOT NULL, title_ru TEXT NOT NULL, tracked INTEGER DEFAULT 0 , tracked_hd integer default 1);
      
      







表紙はデータベース内にbase64の形式で保存されます。これによりデータベースが太くなることは明らかですが、それでもシリーズに関するすべてを1つのデータベースに保存することを好みました。



TODOとPS



私にとってそれほど重要ではなく、いつかできることをやることは残っています。

1.データベースをMySQL / PostgreSQLに転送します

2.データベースへのWebインターフェイスを作成します

3.データベースに新しいシリーズを自動的に追加します(カバー付き)

n RSSフィード認識の将来の修正



残りは一般に公開される必要があります。 コードにはコメントがあります。



このスクリプトは、エラーやエラーなしで4か月間実行されています(今日はシーズン番号0のユーレカがありましたが、サイト自体にはできませんでした)。 私自身は軍人であり、1〜2週間に1回程度家に帰るので、すべてがまれに制御されて自動的に機能します。



ご清聴ありがとうございました!



All Articles