From c700997ed3b16595980f1a7febfedddc74c15e6e Mon Sep 17 00:00:00 2001 From: "pavel.muhortov" Date: Fri, 17 Mar 2023 20:26:03 +0300 Subject: [PATCH] streaming.py absorbed cctv-scheduler.py --- .vscode/launch.json | 11 + README.md | 48 +- archive/0.1/converter.conf | 11 + archive/0.1/converter.sh | 208 +++ archive/0.1/publisher-template-page-1007.xml | 525 ++++++++ archive/0.1/publisher.conf | 86 ++ archive/0.1/publisher.sh | 599 +++++++++ streaming.py => archive/0.1/streaming.py | 0 archive/0.2/README.md | 237 ++++ archive/0.2/cctv-scheduler.conf | 81 ++ archive/0.2/cctv-scheduler.py | 1240 ++++++++++++++++++ archive/0.2/converter.conf | 11 + archive/0.2/converter.sh | 208 +++ archive/0.2/publisher-template-page-1007.xml | 525 ++++++++ archive/0.2/publisher.conf | 86 ++ archive/0.2/publisher.sh | 599 +++++++++ archive/0.2/streaming.py | 297 +++++ cctv-scheduler.conf | 41 +- cctv-scheduler.py | 396 +++++- info/images/cctv-scheduler-0.3.png | Bin 0 -> 284467 bytes 20 files changed, 5159 insertions(+), 50 deletions(-) create mode 100644 archive/0.1/converter.conf create mode 100644 archive/0.1/converter.sh create mode 100644 archive/0.1/publisher-template-page-1007.xml create mode 100644 archive/0.1/publisher.conf create mode 100644 archive/0.1/publisher.sh rename streaming.py => archive/0.1/streaming.py (100%) create mode 100644 archive/0.2/README.md create mode 100644 archive/0.2/cctv-scheduler.conf create mode 100644 archive/0.2/cctv-scheduler.py create mode 100644 archive/0.2/converter.conf create mode 100644 archive/0.2/converter.sh create mode 100644 archive/0.2/publisher-template-page-1007.xml create mode 100644 archive/0.2/publisher.conf create mode 100644 archive/0.2/publisher.sh create mode 100644 archive/0.2/streaming.py create mode 100644 info/images/cctv-scheduler-0.3.png diff --git a/.vscode/launch.json b/.vscode/launch.json index ae932d2..28e25af 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -19,6 +19,17 @@ ], "console": "integratedTerminal", "justMyCode": true + }, + { + "name": "Python: cctv-scheduler -b", + "type": "python", + "request": "launch", + "program": "${file}", + "args": [ + "-b" + ], + "console": "integratedTerminal", + "justMyCode": true } ] } \ No newline at end of file diff --git a/README.md b/README.md index e53bdd7..21d3a03 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,10 @@ ____ - [`cctv-scheduler.py`](https://git.hmp.today/pavel.muhortov/cctv-scheduler#cctv-scheduler-py) - [`converter.sh`](https://git.hmp.today/pavel.muhortov/cctv-scheduler#converter-sh) - [`publisher.sh`](https://git.hmp.today/pavel.muhortov/cctv-scheduler#publisher-sh) -- [`streaming.py`](https://git.hmp.today/pavel.muhortov/cctv-scheduler#streaming-py) ____ -![cctv-scheduler](info/images/cctv-scheduler-0.2.png) +![cctv-scheduler](info/images/cctv-scheduler-0.3.png) ## `Installation` @@ -37,7 +36,6 @@ wget https://git.hmp.today/pavel.muhortov/cctv-scheduler/raw/branch/master/conve wget https://git.hmp.today/pavel.muhortov/cctv-scheduler/raw/branch/master/publisher.sh -O /home/user/cctv-scheduler/publisher.sh wget https://git.hmp.today/pavel.muhortov/cctv-scheduler/raw/branch/master/publisher.conf -O /home/user/cctv-scheduler/publisher.conf wget https://git.hmp.today/pavel.muhortov/cctv-scheduler/raw/branch/master/publisher-template-page-1007.xml -O /home/user/cctv-scheduler/publisher-template-page-1007.xml -wget https://git.hmp.today/pavel.muhortov/cctv-scheduler/raw/branch/master/streaming.py -O /home/user/cctv-scheduler/streaming.py ``` ### `Configuration` @@ -61,7 +59,7 @@ crontab -e ## `cctv-scheduler`.py **Description:** -> [Hikvision](https://git.hmp.today/pavel.muhortov/cctv-scheduler/src/branch/master/info/hikvision/manual/isapi.pdf) PTZ IP-Camera management. +> [Hikvision](https://git.hmp.today/pavel.muhortov/cctv-scheduler/src/branch/master/info/hikvision/manual/isapi.pdf) PTZ IP-Camera management. Media streaming. > Additionally: > > - getting temperature from DS18B20 over SSH, @@ -73,10 +71,12 @@ crontab -e > > - [Python 3](https://www.python.org/downloads/) (tested version 3.9.5 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/)) > - [paramiko](https://www.paramiko.org/) Python 3 module (tested version 3.1.0) +> - [ffmpeg](https://ffmpeg.org) (tested version 4.3.4 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/)) | PARAMETERS | DESCRIPTION | DEFAULT| |-------------|-------------|--------| |**[-h]**|print help and exit|| +|**[-b, --broadcast]**|streaming media to destination|`None`| |**[-s, --sequences]**|run sequences from config file|`None`| |**[--config]**|custom configuration file path|`./cctv-scheduler.conf`| @@ -91,6 +91,7 @@ Example usage with cron: ```bash # crontab -e +* * * * * /usr/bin/python3 /home/user/cctv-scheduler/cctv-scheduler.py -b 0 * * * * /usr/bin/python3 /home/user/cctv-scheduler/cctv-scheduler.py -s ``` @@ -196,42 +197,3 @@ Example usage with cron: 30 1 1 * * bash /home/user/cctv-scheduler/publisher.sh qn - -m 36 1 1 1 * bash /home/user/cctv-scheduler/publisher.sh qn - -y ``` - -____ - -## `streaming`.py - -**Description:** -> FFmpeg management from Python - -**Dependencies:** -> -> - [Python 3](https://www.python.org/downloads/) (tested version 3.9.5 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/)) -> - [ffmpeg](https://ffmpeg.org/download.html) (tested version 4.3.4 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/)) - -| PARAMETERS | DESCRIPTION | DEFAULT| -|-------------|-------------|--------| -|**-s**, **--src**|sources urls|**REQUIRED**| -|**[-h]**|print help and exit|| -|**[--preset]**|240p, 360p, 480p, 720p, 1080p, 1440p, 2160p|`None`| -|**[--fps]**|frame per second encoding output|`None`| -|**[--dst]**|destination url|`None`| -|**[--ffpath]**|alternative path to bin|`None`| -|**[--watchdog]**|detect ffmpeg freeze and terminate|| -|**[--sec]**|seconds to wait before the watchdog terminates|15| -|**[--mono]**|detect ffmpeg running copy and terminate|| - -Example usage in terminal with make the script executable: - -```bash -chmod u+x ./streaming.py -./streaming.py -s rtsp://user:pass@host:554/Streaming/Channels/101 --dst rtp://239.0.0.1:5554 -``` - -Example usage with cron: - -```bash -# crontab -e -* * * * * /usr/bin/python3 /home/user/cctv-scheduler/streaming.py -s rtsp://user:pass@host:554/Streaming/Channels/video,http://Streaming/Channels/audio --dst rtmp://a.rtmp.youtube.com/live2/YOUKEY --mono --watchdog --sec 30 >> /dev/null 2>&1 -* * * * * /usr/bin/python3 /home/user/cctv-scheduler/streaming.py -s ~/media.mp4 --dst rtmp://b.rtmp.youtube.com/live2?backup=1/YOUKEY --mono >> /dev/null 2>&1 -``` diff --git a/archive/0.1/converter.conf b/archive/0.1/converter.conf new file mode 100644 index 0000000..97c039b --- /dev/null +++ b/archive/0.1/converter.conf @@ -0,0 +1,11 @@ +logs=./converter.log + +list=./converter.list +imgroot=/home/user/cctv-scheduler/records +imgnames=point-01 point-02 point-04 point-05 point-11 point-12 +xscale=1920 +yscale=1080 +mp4fps=25 + +telegramapiurl=https://api.telegram.org/bot1234567890:YOURAPIKEY +telegramchatid=123456789 \ No newline at end of file diff --git a/archive/0.1/converter.sh b/archive/0.1/converter.sh new file mode 100644 index 0000000..a231db3 --- /dev/null +++ b/archive/0.1/converter.sh @@ -0,0 +1,208 @@ +#! /bin/bash + +# DESCRIPTION: +# Converting JPEG collection to MP4. +# This is only a local "proof of conept" for testing and debugging. +# +# DEPENDENCIES: +# - ffmpeg +# +# PARAMETERS: +# 1: "qn" - execution without pauses +# 2: custom configuration file path +# 3: periods: '' - today | '-d' - yesterday | '-w' - last week | '-m' - last month | '-y' - last year +# +# FUNCTIONS: +# + +####################################### +# Print message and add to log. +# Globals: +# logs +# Arguments: +# 1: message to print and logging +####################################### +addtologs() { + echo "$(date +'%Y.%m.%d-%H:%M:%S') $1" | tee -a "${logs}" +} + +####################################### +# Waiting for press [ENTER]. +# Globals: +# None +# Arguments: +# None +####################################### +execpause() { + read -r -p "Press [ENTER] to continue... " +} + +####################################### +# Exit procedure. +# Globals: +# show +# Arguments: +# None +####################################### +execquite() { + addtologs "execution time is $(($(date +%s)-time)) seconds, exit" + if [ "${show}" != "qn" ]; then + execpause + fi + exit +} + +####################################### +# Error exit procedure with Telegram notification. +# Globals: +# telegramapiurl +# telegramchatid +# Arguments: +# 1: message to print and logging +####################################### +execerror() { + addtologs "error: $1" + curl -s -X POST "${telegramapiurl}/sendMessage" \ + -d "chat_id=${telegramchatid}" \ + -d "text=$(basename -s .sh "$0") error: $1" \ + >> /dev/null 2>&1 + execquite +} + +####################################### +# Parsing config file and creating global vars. +# Globals: +# None +# Arguments: +# None +####################################### +getconfig() { + logs=$(grep "logs=" "${conf}" | cut -d= -f2) + list=$(grep "list=" "${conf}" | cut -d= -f2) + imgroot=$(grep "imgroot=" "${conf}" | cut -d= -f2) + IFS=" " read -r -a imgnames <<< "$(grep "imgnames=" "${conf}" | cut -d= -f2)" + xscale=$(grep "xscale=" "${conf}" | cut -d= -f2) + yscale=$(grep "yscale=" "${conf}" | cut -d= -f2) + mp4fps=$(grep "mp4fps=" "${conf}" | cut -d= -f2) + telegramapiurl=$(grep "telegramapiurl=" "${conf}" | cut -d= -f2) + telegramchatid=$(grep "telegramchatid=" "${conf}" | cut -d= -f2) +} + +# +# VARIABLES: +# + +show=$1 +conf=$2 +if [ -z "${conf}" ] || [ "${conf}" == "-" ]; then + conf="$(dirname "$(realpath "$0")")/$(basename -s .sh "$0").conf" +fi +when=$3 +if [ -z "${when}" ]; then + d=$(date +"%d") + w=$(date +"%V") + m=$(date +"%m") + y=$(date +"%Y") + duration=1 + imgpath="${y}/${m}/${w}/${d}" + imgname="${y}.${m}.${d}" +fi +if [ "${when}" == "-d" ]; then + d=$(date -d "-1 day" +"%d") + m=$(date +"%m") + if [ "$(date -d '-1 day' +'%m')" != "$(date +'%m')" ]; then + m=$(date -d '-1 day' +'%m') + fi + y=$(date +"%Y") + if [ "$(date -d '-1 day' +'%Y')" != "$(date +'%Y')" ]; then + y=$(date -d '-1 day' +'%Y') + fi + w=$(date +"%V") + if [ "$(date +'%w')" == "1" ]; then + w=$(date -d "-1 week" +"%V") + fi + duration=1 + imgpath="${y}/${m}/${w}/${d}" + imgname="${y}.${m}.${d}" +fi +if [ "${when}" == "-w" ]; then + w=$(date -d "-1 week" +"%V") + m=$(date +"%m") + if [ "$(date -d '-1 week' +'%m')" != "$(date +'%m')" ]; then + m=$(date -d '-1 week' +'%m') + fi + y=$(date +"%Y") + if [ "$(date -d '-1 week' +'%Y')" != "$(date +'%Y')" ]; then + y=$(date -d '-1 week' +'%Y') + fi + duration=7 + imgpath="${y}/*/${w}" + imgname="${y}-w${w}" +fi +if [ "${when}" == "-m" ]; then + m=$(date -d "-1 month" +"%m") + y=$(date +"%Y") + if [ "$(date -d '-1 month' +'%Y')" != "$(date +'%Y')" ]; then + y=$(date -d '-1 month' +'%Y') + fi + duration=30 + imgpath="${y}/${m}" + imgname="${y}.${m}" +fi +if [ "${when}" == "-y" ]; then + y=$(date -d "-1 year" +"%Y") + duration=360 + imgpath="${y}" + imgname="${y}" +fi + +time=$(date +%s) +cd "$(dirname "$(realpath "$0")")" || execerror +if [ ! -e "${conf}" ]; then + execerror "Not found config file: ${conf}" +else + getconfig +fi +if [ -z "${logs}" ];then + logs=/dev/null +elif [ ! -e "${logs}" ];then + touch "${logs}" +fi +if [ -z "${list}" ];then + list="$(dirname "$(realpath "$0")")/$(basename -s .sh "$0").list" +fi +if [ ! -e "${list}" ];then + touch "${list}" +fi +if ! command -v ffmpeg &> /dev/null; then + execerror "Not found dependencies" +fi + +# +# MAIN: +# + +for name in "${imgnames[@]}"; do + imgmatch="*${name}*.jpeg" + imgarray=() + while read -r FILE; do + imgarray+=("${FILE}") + done < <(find "${imgroot}/${imgpath}" -name "${imgmatch}" | sort) + imgcount=${#imgarray[*]} + + echo '' > "${list}" + for item in "${imgarray[@]}"; do + echo file \'"${item}"\' >> "${list}" + done + + imgdest="${imgroot}/${name}_${imgname}.mp4" + echo "${imgdest}" + if ffmpeg -r "${imgcount}/${duration}" -f concat -safe 0 -i "${list}" \ + -c:v libx264 -vf "scale=${xscale}:${yscale},fps=${mp4fps},format=yuv420p" \ + "${imgdest}" -y; then + addtologs "converted ${imgcount} images to ${imgdest} with duration ${duration}" + else + execerror "converted ${imgcount} images to ${imgdest} with duration ${duration}" + fi +done +execquite diff --git a/archive/0.1/publisher-template-page-1007.xml b/archive/0.1/publisher-template-page-1007.xml new file mode 100644 index 0000000..4b8ab60 --- /dev/null +++ b/archive/0.1/publisher-template-page-1007.xml @@ -0,0 +1,525 @@ + +wp.editPage + + 1 + wpeditpageid + wpxmlrpcuser + wpxmlrpcpass + + dateCreatedwpeditdateis + useridwpedituserid + page_idwpeditpageid + page_statuspublish + description + + + + <!-- wp:heading {"level":3} --><h3>Now</h3><!-- /wp:heading --> + <!-- wp:embed {"url":"youtubelink","type":"video","providerNameSlug":"youtube", + "responsive":true,"className":"wp-embed-aspect-4-3 wp-has-aspect-ratio"} --> + <figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"> + <div class="wp-block-embed__wrapper"> + youtubelink + </div></figure><!-- /wp:embed --> + + + <!-- wp:heading {"level":3} --><h3>Yesterday</h3><!-- /wp:heading --> + <!-- wp:uagb/tabs {"block_id":"yesterday", + "tabHeaders":["currentdp01[0]", + "currentdp02[0]", + "currentdp04[0]", + "currentdp05[0]", + "currentdp11[0]", + "currentdp12[0]"],"tabActive":5,"activeTabBgColor":"#4b4b4b", + "tabTitleLeftMargin":1,"tabTitleRightMargin":1,"tabTitleTopMargin":1,"tabTitleBottomMargin":1} --> + <div class="wp-block-uagb-tabs uagb-block-yesterday uagb-tabs__wrap uagb-tabs__hstyle1-desktop uagb-tabs__vstyle6-tablet uagb-tabs__vstyle6-mobile" data-tab-active="0"> + <ul class="uagb-tabs__panel uagb-tabs__align-left"><li class="uagb-tab uagb-tabs__active"> + <a href="#uagb-tabs__tab0" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="0"> + <span>currentdp01[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab1" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="1"> + <span>currentdp02[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab2" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="2"> + <span>currentdp04[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab3" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="3"> + <span>currentdp05[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab4" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="4"> + <span>currentdp11[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab5" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="5"> + <span>currentdp12[0]</span></a></li></ul> + + <div class="uagb-tabs__body-wrap"> + <!-- wp:uagb/tabs-child {"block_id":"daypoint01", + "header":"currentdp01[0]","tabActive":5, + "tabHeaders":["currentdp01[0]", + "currentdp02[0]", + "currentdp04[0]", + "currentdp05[0]", + "currentdp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-0"> + <div class="uagb-blocks__daypoint01 uagb-tabs__body" aria-labelledby="uagb-tabs__tab0"> + <!-- wp:video {"id":1036} --><figure class="wp-block-video"> + <video controls loop src="currentdp01[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"daypoint02","id":1, + "header":"currentdp02[0]","tabActive":5, + "tabHeaders":["currentdp01[0]", + "currentdp02[0]", + "currentdp04[0]", + "currentdp05[0]", + "currentdp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-1"> + <div class="uagb-blocks__daypoint02 uagb-tabs__body" aria-labelledby="uagb-tabs__tab1"> + <!-- wp:video {"id":1041} --><figure class="wp-block-video"> + <video controls loop src="currentdp02[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"daypoint04","id":2, + "header":"currentdp04[0]","tabActive":5, + "tabHeaders":["currentdp01[0]", + "currentdp02[0]", + "currentdp04[0]", + "currentdp05[0]", + "currentdp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-2"> + <div class="uagb-blocks__daypoint04 uagb-tabs__body" aria-labelledby="uagb-tabs__tab2"> + <!-- wp:video {"id":1046} --><figure class="wp-block-video"> + <video controls loop src="currentdp04[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"daypoint05","id":3, + "header":"currentdp05[0]","tabActive":5, + "tabHeaders":["currentdp01[0]", + "currentdp02[0]", + "currentdp04[0]", + "currentdp05[0]", + "currentdp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-3"> + <div class="uagb-blocks__daypoint05 uagb-tabs__body" aria-labelledby="uagb-tabs__tab3"> + <!-- wp:video {"id":1051} --><figure class="wp-block-video"> + <video controls loop src="currentdp05[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"daypoint11","id":4, + "header":"currentdp11[0]","tabActive":5, + "tabHeaders":["currentdp01[0]", + "currentdp02[0]", + "currentdp04[0]", + "currentdp05[0]", + "currentdp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-4"> + <div class="uagb-blocks__daypoint11 uagb-tabs__body" aria-labelledby="uagb-tabs__tab4"> + <!-- wp:video {"id":1056} --><figure class="wp-block-video"> + <video controls loop src="currentdp11[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"daypoint12","id":5, + "header":"currentdp12[0]","tabActive":5, + "tabHeaders":["currentdp01[0]", + "currentdp02[0]", + "currentdp04[0]", + "currentdp05[0]", + "currentdp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-5"> + <div class="uagb-blocks__daypoint12 uagb-tabs__body" aria-labelledby="uagb-tabs__tab5"> + <!-- wp:video {"id":1061} --><figure class="wp-block-video"> + <video controls loop src="currentdp12[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --></div></div> + <!-- /wp:uagb/tabs --> + + + <!-- wp:heading {"level":3} --><h3>Last week</h3><!-- /wp:heading --> + <!-- wp:uagb/tabs {"block_id":"lastweek", + "tabHeaders":["currentwp01[0]", + "currentwp02[0]", + "currentwp04[0]", + "currentwp05[0]", + "currentwp11[0]", + "currentwp12[0]"],"tabActive":5,"activeTabBgColor":"#4b4b4b", + "tabTitleLeftMargin":1,"tabTitleRightMargin":1,"tabTitleTopMargin":1,"tabTitleBottomMargin":1} --> + <div class="wp-block-uagb-tabs uagb-block-lastweek uagb-tabs__wrap uagb-tabs__hstyle1-desktop uagb-tabs__vstyle6-tablet uagb-tabs__vstyle6-mobile" data-tab-active="0"> + <ul class="uagb-tabs__panel uagb-tabs__align-left"><li class="uagb-tab uagb-tabs__active"> + <a href="#uagb-tabs__tab0" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="0"> + <span>currentwp01[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab1" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="1"> + <span>currentwp02[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab2" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="2"> + <span>currentwp04[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab3" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="3"> + <span>currentwp05[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab4" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="4"> + <span>currentwp11[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab5" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="5"> + <span>currentwp12[0]</span></a></li></ul> + + <div class="uagb-tabs__body-wrap"> + <!-- wp:uagb/tabs-child {"block_id":"weekpoint01", + "header":"currentwp01[0]","tabActive":5, + "tabHeaders":["currentwp01[0]", + "currentwp02[0]", + "currentwp04[0]", + "currentwp05[0]", + "currentwp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-0"> + <div class="uagb-blocks__weekpoint01 uagb-tabs__body" aria-labelledby="uagb-tabs__tab0"> + <!-- wp:video {"id":1036} --><figure class="wp-block-video"> + <video controls loop src="currentwp01[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"weekpoint02","id":1, + "header":"currentwp02[0]","tabActive":5, + "tabHeaders":["currentwp01[0]", + "currentwp02[0]", + "currentwp04[0]", + "currentwp05[0]", + "currentwp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-1"> + <div class="uagb-blocks__weekpoint02 uagb-tabs__body" aria-labelledby="uagb-tabs__tab1"> + <!-- wp:video {"id":1041} --><figure class="wp-block-video"> + <video controls loop src="currentwp02[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"weekpoint04","id":2, + "header":"currentwp04[0]","tabActive":5, + "tabHeaders":["currentwp01[0]", + "currentwp02[0]", + "currentwp04[0]", + "currentwp05[0]", + "currentwp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-2"> + <div class="uagb-blocks__weekpoint04 uagb-tabs__body" aria-labelledby="uagb-tabs__tab2"> + <!-- wp:video {"id":1046} --><figure class="wp-block-video"> + <video controls loop src="currentwp04[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"weekpoint05","id":3, + "header":"currentwp05[0]","tabActive":5, + "tabHeaders":["currentwp01[0]", + "currentwp02[0]", + "currentwp04[0]", + "currentwp05[0]", + "currentwp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-3"> + <div class="uagb-blocks__weekpoint05 uagb-tabs__body" aria-labelledby="uagb-tabs__tab3"> + <!-- wp:video {"id":1051} --><figure class="wp-block-video"> + <video controls loop src="currentwp05[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"weekpoint11","id":4, + "header":"currentwp11[0]","tabActive":5, + "tabHeaders":["currentwp01[0]", + "currentwp02[0]", + "currentwp04[0]", + "currentwp05[0]", + "currentwp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-4"> + <div class="uagb-blocks__weekpoint11 uagb-tabs__body" aria-labelledby="uagb-tabs__tab4"> + <!-- wp:video {"id":1056} --><figure class="wp-block-video"> + <video controls loop src="currentwp11[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"weekpoint12","id":5, + "header":"currentwp12[0]","tabActive":5, + "tabHeaders":["currentwp01[0]", + "currentwp02[0]", + "currentwp04[0]", + "currentwp05[0]", + "currentwp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-5"> + <div class="uagb-blocks__weekpoint12 uagb-tabs__body" aria-labelledby="uagb-tabs__tab5"> + <!-- wp:video {"id":1061} --><figure class="wp-block-video"> + <video controls loop src="currentwp12[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --></div></div> + <!-- /wp:uagb/tabs --> + + + <!-- wp:heading {"level":3} --><h3>Last month</h3><!-- /wp:heading --> + <!-- wp:uagb/tabs {"block_id":"lastmonth", + "tabHeaders":["currentmp01[0]", + "currentmp02[0]", + "currentmp04[0]", + "currentmp05[0]", + "currentmp11[0]", + "currentmp12[0]"],"tabActive":5,"activeTabBgColor":"#4b4b4b", + "tabTitleLeftMargin":1,"tabTitleRightMargin":1,"tabTitleTopMargin":1,"tabTitleBottomMargin":1} --> + <div class="wp-block-uagb-tabs uagb-block-lastmonth uagb-tabs__wrap uagb-tabs__hstyle1-desktop uagb-tabs__vstyle6-tablet uagb-tabs__vstyle6-mobile" data-tab-active="0"> + <ul class="uagb-tabs__panel uagb-tabs__align-left"><li class="uagb-tab uagb-tabs__active"> + <a href="#uagb-tabs__tab0" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="0"> + <span>currentmp01[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab1" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="1"> + <span>currentmp02[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab2" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="2"> + <span>currentmp04[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab3" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="3"> + <span>currentmp05[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab4" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="4"> + <span>currentmp11[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab5" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="5"> + <span>currentmp12[0]</span></a></li></ul> + + <div class="uagb-tabs__body-wrap"> + <!-- wp:uagb/tabs-child {"block_id":"monthpoint01", + "header":"currentmp01[0]","tabActive":5, + "tabHeaders":["currentmp01[0]", + "currentmp02[0]", + "currentmp04[0]", + "currentmp05[0]", + "currentmp11[0]","mp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-0"> + <div class="uagb-blocks__monthpoint01 uagb-tabs__body" aria-labelledby="uagb-tabs__tab0"> + <!-- wp:video {"id":1037} --><figure class="wp-block-video"> + <video controls loop src="currentmp01[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"monthpoint02","id":1, + "header":"currentmp02[0]","tabActive":5, + "tabHeaders":["currentmp01[0]", + "currentmp02[0]", + "currentmp04[0]", + "currentmp05[0]", + "currentmp11[0]","mp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-1"> + <div class="uagb-blocks__monthpoint02 uagb-tabs__body" aria-labelledby="uagb-tabs__tab1"> + <!-- wp:video {"id":1042} --><figure class="wp-block-video"> + <video controls loop src="currentmp02[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"monthpoint04","id":2, + "header":"currentmp04[0]","tabActive":5, + "tabHeaders":["currentmp01[0]", + "currentmp02[0]", + "currentmp04[0]", + "currentmp05[0]", + "currentmp11[0]","mp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-2"> + <div class="uagb-blocks__monthpoint04 uagb-tabs__body" aria-labelledby="uagb-tabs__tab2"> + <!-- wp:video {"id":1047} --><figure class="wp-block-video"> + <video controls loop src="currentmp04[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"monthpoint05","id":3, + "header":"currentmp05[0]","tabActive":5, + "tabHeaders":["currentmp01[0]", + "currentmp02[0]", + "currentmp04[0]", + "currentmp05[0]", + "currentmp11[0]","mp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-3"> + <div class="uagb-blocks__monthpoint05 uagb-tabs__body" aria-labelledby="uagb-tabs__tab3"> + <!-- wp:video {"id":1052} --><figure class="wp-block-video"> + <video controls loop src="currentmp05[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"monthpoint11","id":4, + "header":"currentmp11[0]","tabActive":5, + "tabHeaders":["currentmp01[0]", + "currentmp02[0]", + "currentmp04[0]", + "currentmp05[0]", + "currentmp11[0]","mp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-4"> + <div class="uagb-blocks__monthpoint11 uagb-tabs__body" aria-labelledby="uagb-tabs__tab4"> + <!-- wp:video {"id":1057} --><figure class="wp-block-video"> + <video controls loop src="currentmp11[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"monthpoint12","id":5, + "header":"currentmp12[0]","tabActive":5, + "tabHeaders":["currentmp01[0]", + "currentmp02[0]", + "currentmp04[0]", + "currentmp05[0]", + "currentmp11[0]","mp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-5"> + <div class="uagb-blocks__monthpoint12 uagb-tabs__body" aria-labelledby="uagb-tabs__tab5"> + <!-- wp:video {"id":1062} --><figure class="wp-block-video"> + <video controls loop src="currentmp12[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --></div></div> + <!-- /wp:uagb/tabs --> + + + <!-- wp:heading {"level":3} --><h3>Last year</h3><!-- /wp:heading --> + <!-- wp:uagb/tabs {"block_id":"lastyear", + "tabHeaders":["currentyp01[0]", + "currentyp02[0]", + "currentyp04[0]", + "currentyp05[0]", + "currentyp11[0]", + "currentyp12[0]"],"tabActive":5,"activeTabBgColor":"#4b4b4b", + "tabTitleLeftMargin":1,"tabTitleRightMargin":1,"tabTitleTopMargin":1,"tabTitleBottomMargin":1} --> + <div class="wp-block-uagb-tabs uagb-block-lastyear uagb-tabs__wrap uagb-tabs__hstyle1-desktop uagb-tabs__vstyle6-tablet uagb-tabs__vstyle6-mobile" data-tab-active="0"> + <ul class="uagb-tabs__panel uagb-tabs__align-left"><li class="uagb-tab uagb-tabs__active"> + <a href="#uagb-tabs__tab0" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="0"> + <span>currentyp01[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab1" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="1"> + <span>currentyp02[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab2" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="2"> + <span>currentyp04[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab3" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="3"> + <span>currentyp05[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab4" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="4"> + <span>currentyp11[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab5" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="5"> + <span>currentyp12[0]</span></a></li></ul> + + <div class="uagb-tabs__body-wrap"> + <!-- wp:uagb/tabs-child {"block_id":"yearpoint01", + "header":"currentyp01[0]","tabActive":5, + "tabHeaders":["currentyp01[0]", + "currentyp02[0]", + "currentyp04[0]", + "currentyp05[0]", + "currentyp11[0]","yp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-0"> + <div class="uagb-blocks__yearpoint01 uagb-tabs__body" aria-labelledby="uagb-tabs__tab0"> + <!-- wp:video {"id":1038} --><figure class="wp-block-video"> + <video controls loop src="currentyp01[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"yearpoint02","id":1, + "header":"currentyp02[0]","tabActive":5, + "tabHeaders":["currentyp01[0]", + "currentyp02[0]", + "currentyp04[0]", + "currentyp05[0]", + "currentyp11[0]","yp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-1"> + <div class="uagb-blocks__yearpoint02 uagb-tabs__body" aria-labelledby="uagb-tabs__tab1"> + <!-- wp:video {"id":1043} --><figure class="wp-block-video"> + <video controls loop src="currentyp02[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"yearpoint04","id":2, + "header":"currentyp04[0]","tabActive":5, + "tabHeaders":["currentyp01[0]", + "currentyp02[0]", + "currentyp04[0]", + "currentyp05[0]", + "currentyp11[0]","yp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-2"> + <div class="uagb-blocks__yearpoint04 uagb-tabs__body" aria-labelledby="uagb-tabs__tab2"> + <!-- wp:video {"id":1048} --><figure class="wp-block-video"> + <video controls loop src="currentyp04[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"yearpoint05","id":3, + "header":"currentyp05[0]","tabActive":5, + "tabHeaders":["currentyp01[0]", + "currentyp02[0]", + "currentyp04[0]", + "currentyp05[0]", + "currentyp11[0]","yp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-3"> + <div class="uagb-blocks__yearpoint05 uagb-tabs__body" aria-labelledby="uagb-tabs__tab3"> + <!-- wp:video {"id":1053} --><figure class="wp-block-video"> + <video controls loop src="currentyp05[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"yearpoint11","id":4, + "header":"currentyp11[0]","tabActive":5, + "tabHeaders":["currentyp01[0]", + "currentyp02[0]", + "currentyp04[0]", + "currentyp05[0]", + "currentyp11[0]","yp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-4"> + <div class="uagb-blocks__yearpoint11 uagb-tabs__body" aria-labelledby="uagb-tabs__tab4"> + <!-- wp:video {"id":1058} --><figure class="wp-block-video"> + <video controls loop src="currentyp11[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"yearpoint12","id":5, + "header":"currentyp12[0]","tabActive":5, + "tabHeaders":["currentyp01[0]", + "currentyp02[0]", + "currentyp04[0]", + "currentyp05[0]", + "currentyp11[0]","yp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-5"> + <div class="uagb-blocks__yearpoint12 uagb-tabs__body" aria-labelledby="uagb-tabs__tab5"> + <!-- wp:video {"id":1063} --><figure class="wp-block-video"> + <video controls loop src="currentyp12[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --></div></div> + <!-- /wp:uagb/tabs --> + + + + + titleMedia + linkwppagelinkis + permaLinkwppagelinkis + categories + excerpt + text_more + mt_allow_comments0 + mt_allow_pings0 + wp_slugmedia + wp_password + wp_authorwppageauthor + wp_page_parent_id0 + wp_page_parent_title + wp_page_order0 + wp_author_idwpedituserid + wp_author_display_namewppageauthor + date_created_gmtwpeditdateis + custom_fields + + id4258 + keycontent_display_featured_image + value0 + + + id4257 + keycontent_display_title + value0 + + + id4259 + keycontent_width + valuecontainer + + + id4253 + keydisable_space_above_footer + value0 + + + id4252 + keydisable_space_below_header + value0 + + + id4251 + keyhide_footer + value0 + + + id4250 + keyhide_header + value0 + + + id4254 + keyhide_titlebar + value0 + + + id4255 + keypage_overwrite_defaults + value0 + + + id4260 + keysidebar_layout + valuedefault-sidebar + + + id4256 + keytitlebar_padding + value80 + + + wp_page_templatedefault + + + \ No newline at end of file diff --git a/archive/0.1/publisher.conf b/archive/0.1/publisher.conf new file mode 100644 index 0000000..e9b7d94 --- /dev/null +++ b/archive/0.1/publisher.conf @@ -0,0 +1,86 @@ +logs=./publisher.log + +pathroot=/home/user/cctv-scheduler/records +vidnamesarray=point-01 point-02 point-04 point-05 point-11 point-12 + + +telegramapiurl=https://api.telegram.org/bot1234567890:YOURAPIKEY +telegramchatid=123456789 +tgpreviewlink=https://www.hmp.today/wp-content/uploads/2021/02/site-slider_hmp-qr_bwg-3840x1705-1.png +tgpreviewtext=https://www.hmp.today/media + + +wpxmlrpclink=https://www.hmp.today/xmlrpc.php +wpxmlrpcuser=user +wpxmlrpcpass=pass +wppageauthor=author +wppagelinkis=https://www.hmp.today/media +wpeditpageid=1007 +wpedituserid=0 +wpeditdateis=20220707T00:00:00 +wptemplateis=./publisher-template-page-1007.xml + + +youtubelink=https://youtu.be/link + + +defaultdp01=point-01 https://www.hmp.today/wp-content/uploads/2022/07/point-01_yyyy.mm_.dd_.mp4 +defaultwp01=point-01 https://www.hmp.today/wp-content/uploads/2022/07/point-01_w.mp4 +defaultmp01=point-01 https://www.hmp.today/wp-content/uploads/2022/07/point-01_yyyy.mm_.mp4 +defaultyp01=point-01 https://www.hmp.today/wp-content/uploads/2022/07/point-01_yyyy.mp4 + +defaultdp02=point-02 https://www.hmp.today/wp-content/uploads/2022/07/point-02_yyyy.mm_.dd_.mp4 +defaultwp02=point-02 https://www.hmp.today/wp-content/uploads/2022/07/point-02_w.mp4 +defaultmp02=point-02 https://www.hmp.today/wp-content/uploads/2022/07/point-02_yyyy.mm_.mp4 +defaultyp02=point-02 https://www.hmp.today/wp-content/uploads/2022/07/point-02_yyyy.mp4 + +defaultdp04=point-04 https://www.hmp.today/wp-content/uploads/2022/07/point-04_yyyy.mm_.dd_.mp4 +defaultwp04=point-04 https://www.hmp.today/wp-content/uploads/2022/07/point-04_w.mp4 +defaultmp04=point-04 https://www.hmp.today/wp-content/uploads/2022/07/point-04_yyyy.mm_.mp4 +defaultyp04=point-04 https://www.hmp.today/wp-content/uploads/2022/07/point-04_yyyy.mp4 + +defaultdp05=point-05 https://www.hmp.today/wp-content/uploads/2022/07/point-05_yyyy.mm_.dd_.mp4 +defaultwp05=point-05 https://www.hmp.today/wp-content/uploads/2022/07/point-05_w.mp4 +defaultmp05=point-05 https://www.hmp.today/wp-content/uploads/2022/07/point-05_yyyy.mm_.mp4 +defaultyp05=point-05 https://www.hmp.today/wp-content/uploads/2022/07/point-05_yyyy.mp4 + +defaultdp11=point-11 https://www.hmp.today/wp-content/uploads/2022/07/point-11_yyyy.mm_.dd_.mp4 +defaultwp11=point-11 https://www.hmp.today/wp-content/uploads/2022/07/point-11_w.mp4 +defaultmp11=point-11 https://www.hmp.today/wp-content/uploads/2022/07/point-11_yyyy.mm_.mp4 +defaultyp11=point-11 https://www.hmp.today/wp-content/uploads/2022/07/point-11_yyyy.mp4 + +defaultdp12=point-12 https://www.hmp.today/wp-content/uploads/2022/07/point-12_yyyy.mm_.dd_.mp4 +defaultwp12=point-12 https://www.hmp.today/wp-content/uploads/2022/07/point-12_w.mp4 +defaultmp12=point-12 https://www.hmp.today/wp-content/uploads/2022/07/point-12_yyyy.mm_.mp4 +defaultyp12=point-12 https://www.hmp.today/wp-content/uploads/2022/07/point-12_yyyy.mp4 + + +currentdp01=point-01 +currentwp01=point-01 +currentmp01=point-01 +currentyp01=point-01 + +currentdp02=point-02 +currentwp02=point-02 +currentmp02=point-02 +currentyp02=point-02 + +currentdp04=point-04 +currentwp04=point-04 +currentmp04=point-04 +currentyp04=point-04 + +currentdp05=point-05 +currentwp05=point-05 +currentmp05=point-05 +currentyp05=point-05 + +currentdp11=point-11 +currentwp11=point-11 +currentmp11=point-11 +currentyp11=point-11 + +currentdp12=point-12 +currentwp12=point-12 +currentmp12=point-12 +currentyp12=point-12 diff --git a/archive/0.1/publisher.sh b/archive/0.1/publisher.sh new file mode 100644 index 0000000..205da6d --- /dev/null +++ b/archive/0.1/publisher.sh @@ -0,0 +1,599 @@ +#! /bin/bash + +# DESCRIPTION: +# Uploading MP4 to Wordpress and Telegram. +# Additionally: +# - editing Wordpress page from template +# - recompressing video if size over 50MB +# This is only a local "proof of conept" for testing and debugging. +# +# DEPENDENCIES: +# - curl +# - ffmpeg +# - libxml2-utils +# - jq +# +# PARAMETERS: +# 1: "qn" - execution without pauses +# 2: custom configuration file path +# 3: periods: '' - today | '-d' - yesterday | '-w' - last week | '-m' - last month | '-y' - last year +# 4: period multiplier: '' - 1 day|week|month|year +# 5: publishing '--onlytg' - only to Telegram | '--onlywp' - only to Wordpress +# +# FUNCTIONS: +# + +####################################### +# Print message and add to log. +# Globals: +# logs +# Arguments: +# 1: message to print and logging +####################################### +addtologs() { + echo "$(date +'%Y.%m.%d-%H:%M:%S') $1" | tee -a "${logs}" +} + +####################################### +# Waiting for press [ENTER]. +# Globals: +# None +# Arguments: +# None +####################################### +execpause() { + read -r -p "Press [ENTER] to continue... " +} + +####################################### +# Exit procedure. +# Globals: +# show +# Arguments: +# None +####################################### +execquite() { + addtologs "execution time is $(($(date +%s)-time)) seconds, exit" + if [ "${show}" != "qn" ]; then + execpause + fi + exit +} + +####################################### +# Error exit procedure with Telegram notification. +# Globals: +# telegramapiurl +# telegramchatid +# Arguments: +# 1: message to print and logging +####################################### +execerror() { + addtologs "error: $1" + curl -s -X POST "${telegramapiurl}/sendMessage" \ + -d "chat_id=${telegramchatid}" \ + -d "text=$(basename -s .sh "$0") error: $1" \ + >> /dev/null 2>&1 + execquite +} + +####################################### +# Parsing config file and creating global vars. +# Globals: +# None +# Arguments: +# None +####################################### +getconfig() { + logs=$(grep "logs=" "${conf}" | cut -d= -f2) + pathroot=$(grep "pathroot=" "${conf}" | cut -d= -f2) + IFS=" " read -r -a vidnamesarray <<< "$(grep "vidnamesarray=" "${conf}" | cut -d= -f2)" + telegramapiurl=$(grep "telegramapiurl=" "${conf}" | cut -d= -f2) + telegramchatid=$(grep "telegramchatid=" "${conf}" | cut -d= -f2) + tgpreviewlink=$(grep "tgpreviewlink=" "${conf}" | cut -d= -f2) + tgpreviewtext=$(grep "tgpreviewtext=" "${conf}" | cut -d= -f2) + wpxmlrpclink=$(grep "wpxmlrpclink=" "${conf}" | cut -d= -f2) + wpxmlrpcuser=$(grep "wpxmlrpcuser=" "${conf}" | cut -d= -f2) + wpxmlrpcpass=$(grep "wpxmlrpcpass=" "${conf}" | cut -d= -f2) + wppageauthor=$(grep "wppageauthor=" "${conf}" | cut -d= -f2) + wppagelinkis=$(grep "wppagelinkis=" "${conf}" | cut -d= -f2) + wpeditpageid=$(grep "wpeditpageid=" "${conf}" | cut -d= -f2) + wpedituserid=$(grep "wpedituserid=" "${conf}" | cut -d= -f2) + wpeditdateis=$(grep "wpeditdateis=" "${conf}" | cut -d= -f2) + wptemplateis=$(grep "wptemplateis=" "${conf}" | cut -d= -f2) + youtubelink=$(grep "youtubelink=" "${conf}" | cut -d= -f2) + + IFS=" " read -r -a defaultdp01 <<< "$(grep "defaultdp01=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultwp01 <<< "$(grep "defaultwp01=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultmp01 <<< "$(grep "defaultmp01=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultyp01 <<< "$(grep "defaultyp01=" "${conf}" | cut -d= -f2)" + + IFS=" " read -r -a defaultdp02 <<< "$(grep "defaultdp02=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultwp02 <<< "$(grep "defaultwp02=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultmp02 <<< "$(grep "defaultmp02=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultyp02 <<< "$(grep "defaultyp02=" "${conf}" | cut -d= -f2)" + + IFS=" " read -r -a defaultdp04 <<< "$(grep "defaultdp04=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultwp04 <<< "$(grep "defaultwp04=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultmp04 <<< "$(grep "defaultmp04=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultyp04 <<< "$(grep "defaultyp04=" "${conf}" | cut -d= -f2)" + + IFS=" " read -r -a defaultdp05 <<< "$(grep "defaultdp05=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultwp05 <<< "$(grep "defaultwp05=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultmp05 <<< "$(grep "defaultmp05=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultyp05 <<< "$(grep "defaultyp05=" "${conf}" | cut -d= -f2)" + + IFS=" " read -r -a defaultdp11 <<< "$(grep "defaultdp11=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultwp11 <<< "$(grep "defaultwp11=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultmp11 <<< "$(grep "defaultmp11=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultyp11 <<< "$(grep "defaultyp11=" "${conf}" | cut -d= -f2)" + + IFS=" " read -r -a defaultdp12 <<< "$(grep "defaultdp12=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultwp12 <<< "$(grep "defaultwp12=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultmp12 <<< "$(grep "defaultmp12=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultyp12 <<< "$(grep "defaultyp12=" "${conf}" | cut -d= -f2)" + + IFS=" " read -r -a currentdp01 <<< "$(grep "currentdp01=" "${conf}" | cut -d= -f2)" + if [ -z "${currentdp01[1]}" ]; then + currentdp01=${defaultdp01[*]} + fi + IFS=" " read -r -a currentwp01 <<< "$(grep "currentwp01=" "${conf}" | cut -d= -f2)" + if [ -z "${currentwp01[1]}" ]; then + currentwp01=${defaultwp01[*]} + fi + IFS=" " read -r -a currentmp01 <<< "$(grep "currentmp01=" "${conf}" | cut -d= -f2)" + if [ -z "${currentmp01[1]}" ]; then + currentmp01=${defaultmp01[*]} + fi + IFS=" " read -r -a currentyp01 <<< "$(grep "currentyp01=" "${conf}" | cut -d= -f2)" + if [ -z "${currentyp01[1]}" ]; then + currentyp01=${defaultyp01[*]} + fi + + IFS=" " read -r -a currentdp02 <<< "$(grep "currentdp02=" "${conf}" | cut -d= -f2)" + if [ -z "${currentdp02[1]}" ]; then + currentdp02=${defaultdp02[*]} + fi + IFS=" " read -r -a currentwp02 <<< "$(grep "currentwp02=" "${conf}" | cut -d= -f2)" + if [ -z "${currentwp02[1]}" ]; then + currentwp02=${defaultwp02[*]} + fi + IFS=" " read -r -a currentmp02 <<< "$(grep "currentmp02=" "${conf}" | cut -d= -f2)" + if [ -z "${currentmp02[1]}" ]; then + currentmp02=${defaultmp02[*]} + fi + IFS=" " read -r -a currentyp02 <<< "$(grep "currentyp02=" "${conf}" | cut -d= -f2)" + if [ -z "${currentyp02[1]}" ]; then + currentyp02=${defaultyp02[*]} + fi + + IFS=" " read -r -a currentdp04 <<< "$(grep "currentdp04=" "${conf}" | cut -d= -f2)" + if [ -z "${currentdp04[1]}" ]; then + currentdp04=${defaultdp04[*]} + fi + IFS=" " read -r -a currentwp04 <<< "$(grep "currentwp04=" "${conf}" | cut -d= -f2)" + if [ -z "${currentwp04[1]}" ]; then + currentwp04=${defaultwp04[*]} + fi + IFS=" " read -r -a currentmp04 <<< "$(grep "currentmp04=" "${conf}" | cut -d= -f2)" + if [ -z "${currentmp04[1]}" ]; then + currentmp04=${defaultmp04[*]} + fi + IFS=" " read -r -a currentyp04 <<< "$(grep "currentyp04=" "${conf}" | cut -d= -f2)" + if [ -z "${currentyp04[1]}" ]; then + currentyp04=${defaultyp04[*]} + fi + + IFS=" " read -r -a currentdp05 <<< "$(grep "currentdp05=" "${conf}" | cut -d= -f2)" + if [ -z "${currentdp05[1]}" ]; then + currentdp05=${defaultdp05[*]} + fi + IFS=" " read -r -a currentwp05 <<< "$(grep "currentwp05=" "${conf}" | cut -d= -f2)" + if [ -z "${currentwp05[1]}" ]; then + currentwp05=${defaultwp05[*]} + fi + IFS=" " read -r -a currentmp05 <<< "$(grep "currentmp05=" "${conf}" | cut -d= -f2)" + if [ -z "${currentmp05[1]}" ]; then + currentmp05=${defaultmp05[*]} + fi + IFS=" " read -r -a currentyp05 <<< "$(grep "currentyp05=" "${conf}" | cut -d= -f2)" + if [ -z "${currentyp05[1]}" ]; then + currentyp05=${defaultyp05[*]} + fi + + IFS=" " read -r -a currentdp11 <<< "$(grep "currentdp11=" "${conf}" | cut -d= -f2)" + if [ -z "${currentdp11[1]}" ]; then + currentdp11=${defaultdp11[*]} + fi + IFS=" " read -r -a currentwp11 <<< "$(grep "currentwp11=" "${conf}" | cut -d= -f2)" + if [ -z "${currentwp11[1]}" ]; then + currentwp11=${defaultwp11[*]} + fi + IFS=" " read -r -a currentmp11 <<< "$(grep "currentmp11=" "${conf}" | cut -d= -f2)" + if [ -z "${currentmp11[1]}" ]; then + currentmp11=${defaultmp11[*]} + fi + IFS=" " read -r -a currentyp11 <<< "$(grep "currentyp11=" "${conf}" | cut -d= -f2)" + if [ -z "${currentyp11[1]}" ]; then + currentyp11=${defaultyp11[*]} + fi + + IFS=" " read -r -a currentdp12 <<< "$(grep "currentdp12=" "${conf}" | cut -d= -f2)" + if [ -z "${currentdp12[1]}" ]; then + currentdp12=${defaultdp12[*]} + fi + IFS=" " read -r -a currentwp12 <<< "$(grep "currentwp12=" "${conf}" | cut -d= -f2)" + if [ -z "${currentwp12[1]}" ]; then + currentwp12=${defaultwp12[*]} + fi + IFS=" " read -r -a currentmp12 <<< "$(grep "currentmp12=" "${conf}" | cut -d= -f2)" + if [ -z "${currentmp12[1]}" ]; then + currentmp12=${defaultmp12[*]} + fi + IFS=" " read -r -a currentyp12 <<< "$(grep "currentyp12=" "${conf}" | cut -d= -f2)" + if [ -z "${currentyp12[1]}" ]; then + currentyp12=${defaultyp12[*]} + fi +} + +####################################### +# Writing changes to configuration file. +# Globals: +# conf +# when +# vidnamesarray +# vidlinksarray +# Arguments: +# None +####################################### +setconfig() { + if [ -z "${when}" ] || [ "${when}" == "-d" ]; then + if [ -n "${vidnamesarray[0]}" ] && [ -n "${vidlinksarray[0]}" ]; then + sed -i "s#$(grep 'currentdp01=' "${conf}")#currentdp01=${vidnamesarray[0]} ${vidlinksarray[0]}#" "${conf}" + fi + if [ -n "${vidnamesarray[1]}" ] && [ -n "${vidlinksarray[1]}" ]; then + sed -i "s#$(grep 'currentdp02=' "${conf}")#currentdp02=${vidnamesarray[1]} ${vidlinksarray[1]}#" "${conf}" + fi + if [ -n "${vidnamesarray[2]}" ] && [ -n "${vidlinksarray[2]}" ]; then + sed -i "s#$(grep 'currentdp04=' "${conf}")#currentdp04=${vidnamesarray[2]} ${vidlinksarray[2]}#" "${conf}" + fi + if [ -n "${vidnamesarray[3]}" ] && [ -n "${vidlinksarray[3]}" ]; then + sed -i "s#$(grep 'currentdp05=' "${conf}")#currentdp05=${vidnamesarray[3]} ${vidlinksarray[3]}#" "${conf}" + fi + if [ -n "${vidnamesarray[4]}" ] && [ -n "${vidlinksarray[4]}" ]; then + sed -i "s#$(grep 'currentdp11=' "${conf}")#currentdp11=${vidnamesarray[4]} ${vidlinksarray[4]}#" "${conf}" + fi + if [ -n "${vidnamesarray[5]}" ] && [ -n "${vidlinksarray[5]}" ]; then + sed -i "s#$(grep 'currentdp12=' "${conf}")#currentdp12=${vidnamesarray[5]} ${vidlinksarray[5]}#" "${conf}" + fi + fi + if [ "${when}" == "-w" ]; then + if [ -n "${vidnamesarray[0]}" ] && [ -n "${vidlinksarray[0]}" ]; then + sed -i "s#$(grep 'currentwp01=' "${conf}")#currentwp01=${vidnamesarray[0]} ${vidlinksarray[0]}#" "${conf}" + fi + if [ -n "${vidnamesarray[1]}" ] && [ -n "${vidlinksarray[1]}" ]; then + sed -i "s#$(grep 'currentwp02=' "${conf}")#currentwp02=${vidnamesarray[1]} ${vidlinksarray[1]}#" "${conf}" + fi + if [ -n "${vidnamesarray[2]}" ] && [ -n "${vidlinksarray[2]}" ]; then + sed -i "s#$(grep 'currentwp04=' "${conf}")#currentwp04=${vidnamesarray[2]} ${vidlinksarray[2]}#" "${conf}" + fi + if [ -n "${vidnamesarray[3]}" ] && [ -n "${vidlinksarray[3]}" ]; then + sed -i "s#$(grep 'currentwp05=' "${conf}")#currentwp05=${vidnamesarray[3]} ${vidlinksarray[3]}#" "${conf}" + fi + if [ -n "${vidnamesarray[4]}" ] && [ -n "${vidlinksarray[4]}" ]; then + sed -i "s#$(grep 'currentwp11=' "${conf}")#currentwp11=${vidnamesarray[4]} ${vidlinksarray[4]}#" "${conf}" + fi + if [ -n "${vidnamesarray[5]}" ] && [ -n "${vidlinksarray[5]}" ]; then + sed -i "s#$(grep 'currentwp12=' "${conf}")#currentwp12=${vidnamesarray[5]} ${vidlinksarray[5]}#" "${conf}" + fi + fi + if [ "${when}" == "-m" ]; then + if [ -n "${vidnamesarray[0]}" ] && [ -n "${vidlinksarray[0]}" ]; then + sed -i "s#$(grep 'currentmp01=' "${conf}")#currentmp01=${vidnamesarray[0]} ${vidlinksarray[0]}#" "${conf}" + fi + if [ -n "${vidnamesarray[1]}" ] && [ -n "${vidlinksarray[1]}" ]; then + sed -i "s#$(grep 'currentmp02=' "${conf}")#currentmp02=${vidnamesarray[1]} ${vidlinksarray[1]}#" "${conf}" + fi + if [ -n "${vidnamesarray[2]}" ] && [ -n "${vidlinksarray[2]}" ]; then + sed -i "s#$(grep 'currentmp04=' "${conf}")#currentmp04=${vidnamesarray[2]} ${vidlinksarray[2]}#" "${conf}" + fi + if [ -n "${vidnamesarray[3]}" ] && [ -n "${vidlinksarray[3]}" ]; then + sed -i "s#$(grep 'currentmp05=' "${conf}")#currentmp05=${vidnamesarray[3]} ${vidlinksarray[3]}#" "${conf}" + fi + if [ -n "${vidnamesarray[4]}" ] && [ -n "${vidlinksarray[4]}" ]; then + sed -i "s#$(grep 'currentmp11=' "${conf}")#currentmp11=${vidnamesarray[4]} ${vidlinksarray[4]}#" "${conf}" + fi + if [ -n "${vidnamesarray[5]}" ] && [ -n "${vidlinksarray[5]}" ]; then + sed -i "s#$(grep 'currentmp12=' "${conf}")#currentmp12=${vidnamesarray[5]} ${vidlinksarray[5]}#" "${conf}" + fi + fi + if [ "${when}" == "-y" ]; then + if [ -n "${vidnamesarray[0]}" ] && [ -n "${vidlinksarray[0]}" ]; then + sed -i "s#$(grep 'currentyp01=' "${conf}")#currentyp01=${vidnamesarray[0]} ${vidlinksarray[0]}#" "${conf}" + fi + if [ -n "${vidnamesarray[1]}" ] && [ -n "${vidlinksarray[1]}" ]; then + sed -i "s#$(grep 'currentyp02=' "${conf}")#currentyp02=${vidnamesarray[1]} ${vidlinksarray[1]}#" "${conf}" + fi + if [ -n "${vidnamesarray[2]}" ] && [ -n "${vidlinksarray[2]}" ]; then + sed -i "s#$(grep 'currentyp04=' "${conf}")#currentyp04=${vidnamesarray[2]} ${vidlinksarray[2]}#" "${conf}" + fi + if [ -n "${vidnamesarray[3]}" ] && [ -n "${vidlinksarray[3]}" ]; then + sed -i "s#$(grep 'currentyp05=' "${conf}")#currentyp05=${vidnamesarray[3]} ${vidlinksarray[3]}#" "${conf}" + fi + if [ -n "${vidnamesarray[4]}" ] && [ -n "${vidlinksarray[4]}" ]; then + sed -i "s#$(grep 'currentyp11=' "${conf}")#currentyp11=${vidnamesarray[4]} ${vidlinksarray[4]}#" "${conf}" + fi + if [ -n "${vidnamesarray[5]}" ] && [ -n "${vidlinksarray[5]}" ]; then + sed -i "s#$(grep 'currentyp12=' "${conf}")#currentyp12=${vidnamesarray[5]} ${vidlinksarray[5]}#" "${conf}" + fi + fi +} + +# +# VARIABLES: +# + +show=$1 +conf=$2 +if [ -z "${conf}" ] || [ "${conf}" == "-" ]; then + conf="$(dirname "$(realpath "$0")")/$(basename -s .sh "$0").conf" +fi +ever=$4 +if [ -z "${ever}" ] || [ "${ever}" == "-" ]; then + ever=1 +fi +if grep -q -o "^[0-9][0-9]*$" <<< "${ever}"; then + : +else + execerror "${ever} - wrong argument" +fi +when=$3 +if [ -z "${when}" ]; then + viddate=$(date +"%Y").$(date +"%m").$(date +"%d") +fi +if [ "${when}" == "-d" ]; then + d=$(date -d "-${ever} day" +"%d") + m=$(date +"%m") + if [ "$(date -d "-${ever} day" +'%m')" != "$(date +'%m')" ]; then + m=$(date -d "-${ever} day" +'%m') + fi + y=$(date +"%Y") + if [ "$(date -d "-${ever} day" +'%Y')" != "$(date +'%Y')" ]; then + y=$(date -d "-${ever} day" +'%Y') + fi + viddate="${y}.${m}.${d}" +fi +if [ "${when}" == "-w" ]; then + w=$(date -d "-${ever} week" +"%V") + y=$(date +"%Y") + if [ "$(date -d "-${ever} week" +'%Y')" != "$(date +'%Y')" ]; then + y=$(date -d "-${ever} week" +'%Y') + fi + viddate="${y}-w${w}" +fi +if [ "${when}" == "-m" ]; then + m=$(date -d "-${ever} month" +"%m") + y=$(date +"%Y") + if [ "$(date -d "-${ever} month" +'%Y')" != "$(date +'%Y')" ]; then + y=$(date -d "-${ever} month" +'%Y') + fi + viddate="${y}.${m}" +fi +if [ "${when}" == "-y" ]; then + y=$(date -d "-${ever} year" +"%Y") + viddate="${y}" +fi +vidname="${viddate}.mp4" +only=$5 + +time=$(date +%s) +cd "$(dirname "$(realpath "$0")")" || execerror +if [ ! -e "${conf}" ]; then + execerror "Not found config file: ${conf}" +else + getconfig +fi +if [ -z "${logs}" ]; then + logs=/dev/null +elif [ ! -e "${logs}" ]; then + touch "${logs}" +fi +if ! command -v curl &> /dev/null || \ + ! command -v ffmpeg &> /dev/null || \ + ! command -v xmllint &> /dev/null || \ + ! command -v jq &> /dev/null; then + execerror "Not found dependencies" +fi + +# +# MAIN: +# + +vidpathsarray=() +vidlinksarray=() +vidtgidsarray=() +vidtgcpsarray=() +for name in "${vidnamesarray[@]}"; do + vidmatch="${name}_${vidname}" + while read -r FILE; do + vidpathsarray+=("${FILE}") + done < <(find "${pathroot}" -name "*${vidmatch}" | sort) +done +for item in "${!vidpathsarray[@]}"; do + # WORDPRESS UPLOAD VIDEO + if [ ! "$only" == "--onlytg" ]; then + # This realisation isn't optimal, but it fixes a few issues with large files: + # variable=$(base64 $file) -> "xrealloc: cannot allocate" + # response=$(curl -X POST -d @${file}.xml $url) -> "curl: option -d: out of memory" + filetype="video/mp4" + echo ' + wp.uploadFile + + 1 + '"${wpxmlrpcuser}"' + '"${wpxmlrpcpass}"' + + name'"$(basename "${vidpathsarray[$item]}")"' + type'"${filetype}"' + bits' > "${vidpathsarray[$item]}.xml" + base64 --wrap=0 "${vidpathsarray[$item]}" >> "${vidpathsarray[$item]}.xml" + echo ' + + + ' >> "${vidpathsarray[$item]}.xml" + response="${vidpathsarray[$item]}-response.xml" + if curl -X POST -T "${vidpathsarray[$item]}.xml" "${wpxmlrpclink}" > "${response}"; then + vidlinksarray+=("$(xmllint --xpath '//member[contains(name,"link")]/value/string/text()' "${response}")") + vidlinkcodeis=$(curl --output /dev/null --silent --write-out "%{http_code}" "${vidlinksarray[$item]}") + else + execerror "${response}" + fi + if [[ ${vidlinkcodeis} -eq 200 ]]; then + rm "${vidpathsarray[$item]}.xml" + rm "${response}" + echo "$(date +'%Y.%m.%d-%H:%M:%S') sent ${vidpathsarray[$item]} to ${vidlinksarray[$item]}" | tee -a "${logs}" + echo -e "WORDPRESS UPLOAD VIDEO RESULT:" + echo -e "item: ${item}" + echo -e "type: ${filetype}" + echo -e "name: ${vidnamesarray[$item]}" + echo -e "base: $(basename "${vidpathsarray[$item]}")" + echo -e "path: ${vidpathsarray[$item]}" + echo -e "link: ${vidlinksarray[$item]}" + echo -e "code: ${vidlinkcodeis}" + else + vidlinksarray[item]='' + fi + fi + + # TELEGRAM SEND/UPLOAD VIDEO + if [ ! "${only}" == "--onlywp" ]; then + videofullpath=${vidpathsarray[$item]} + vidcompressed=${videofullpath//".mp4"/"-compressed.mp4"} + if [ -n "$(find "${videofullpath}" -prune -size +51380224c)" ]; then + duration=$(ffprobe -i "${videofullpath}" \ + -show_entries format=duration -v quiet -of csv="p=0" | cut -d'.' -f 1) + if ffmpeg -i "${videofullpath}" \ + -c:v libx264 -b:v "$((49*8*1000/duration))k" \ + -vf "scale=960:540,fps=25,format=yuv420p" \ + -preset veryslow "${vidcompressed}" -y -loglevel quiet -stats; then + videofullpath=${vidcompressed} + else + execerror "ffmpeg convert ${videofullpath} to ${vidcompressed}" + fi + fi + videobasename=$(basename "${videofullpath}") + videobasename=${videobasename//".mp4"/""} + response=$(curl -s \ + -F "chat_id=${telegramchatid}" \ + -F "video=@${videofullpath}" \ + -F "caption=${videobasename}" \ + "${telegramapiurl}/sendVideo") + if curl -s -F "chat_id=${telegramchatid}" \ + -F "message_id=$(echo "${response}" | jq -r '.result.message_id')" \ + "${telegramapiurl}/deleteMessage"; then + vidtgidsarray+=("$(echo "${response}" | jq -r '.result.video.file_id')") + vidtgcpsarray+=("$(echo "${response}" | jq -r '.result.caption')") + addtologs "sent ${videofullpath} to ${vidtgidsarray[$item]} Telegram file ID" + else + execerror "sent ${videofullpath} to ${telegramchatid} Telegram Chat ID" + fi + if [ -e "${vidcompressed}" ]; then + rm "${vidcompressed}" + fi + fi +done + +# TELEGRAM SEND MEDIAGROUP +if [ ! "${only}" == "--onlywp" ]; then + response=$(curl -s -F "chat_id=${telegramchatid}" \ + -F media='[ + {"type":"photo","media":"'"${tgpreviewlink}"'", + "caption":"period: '"${viddate}"'\nsource: '"${tgpreviewtext}"'\nstream: '"${youtubelink}"'"}, + {"type":"video","media":"'"${vidtgidsarray[0]}"'"}, + {"type":"video","media":"'"${vidtgidsarray[1]}"'"}, + {"type":"video","media":"'"${vidtgidsarray[2]}"'"}, + {"type":"video","media":"'"${vidtgidsarray[3]}"'"}, + {"type":"video","media":"'"${vidtgidsarray[4]}"'"}, + {"type":"video","media":"'"${vidtgidsarray[5]}"'"}]' \ + -H "Content-Type:multipart/form-data" \ + "${telegramapiurl}/sendMediaGroup") +fi + +# WORDPRESS UPDATE PAGE +if [ ! "${only}" == "--onlytg" ]; then + setconfig + getconfig + xml=$(cat "./${wptemplateis}") + + xml=${xml//wpeditpageid/${wpeditpageid}} + xml=${xml//wpxmlrpcuser/${wpxmlrpcuser}} + xml=${xml//wpxmlrpcpass/${wpxmlrpcpass}} + + xml=${xml//youtubelink/${youtubelink}} + + xml=${xml//"currentdp01[0]"/${currentdp01[0]}} + xml=${xml//"currentdp01[1]"/${currentdp01[1]}} + xml=${xml//"currentdp02[0]"/${currentdp02[0]}} + xml=${xml//"currentdp02[1]"/${currentdp02[1]}} + xml=${xml//"currentdp04[0]"/${currentdp04[0]}} + xml=${xml//"currentdp04[1]"/${currentdp04[1]}} + xml=${xml//"currentdp05[0]"/${currentdp05[0]}} + xml=${xml//"currentdp05[1]"/${currentdp05[1]}} + xml=${xml//"currentdp11[0]"/${currentdp11[0]}} + xml=${xml//"currentdp11[1]"/${currentdp11[1]}} + xml=${xml//"currentdp12[0]"/${currentdp12[0]}} + xml=${xml//"currentdp12[1]"/${currentdp12[1]}} + + xml=${xml//"currentwp01[0]"/${currentwp01[0]}} + xml=${xml//"currentwp01[1]"/${currentwp01[1]}} + xml=${xml//"currentwp02[0]"/${currentwp02[0]}} + xml=${xml//"currentwp02[1]"/${currentwp02[1]}} + xml=${xml//"currentwp04[0]"/${currentwp04[0]}} + xml=${xml//"currentwp04[1]"/${currentwp04[1]}} + xml=${xml//"currentwp05[0]"/${currentwp05[0]}} + xml=${xml//"currentwp05[1]"/${currentwp05[1]}} + xml=${xml//"currentwp11[0]"/${currentwp11[0]}} + xml=${xml//"currentwp11[1]"/${currentwp11[1]}} + xml=${xml//"currentwp12[0]"/${currentwp12[0]}} + xml=${xml//"currentwp12[1]"/${currentwp12[1]}} + + xml=${xml//"currentmp01[0]"/${currentmp01[0]}} + xml=${xml//"currentmp01[1]"/${currentmp01[1]}} + xml=${xml//"currentmp02[0]"/${currentmp02[0]}} + xml=${xml//"currentmp02[1]"/${currentmp02[1]}} + xml=${xml//"currentmp04[0]"/${currentmp04[0]}} + xml=${xml//"currentmp04[1]"/${currentmp04[1]}} + xml=${xml//"currentmp05[0]"/${currentmp05[0]}} + xml=${xml//"currentmp05[1]"/${currentmp05[1]}} + xml=${xml//"currentmp11[0]"/${currentmp11[0]}} + xml=${xml//"currentmp11[1]"/${currentmp11[1]}} + xml=${xml//"currentmp12[0]"/${currentmp12[0]}} + xml=${xml//"currentmp12[1]"/${currentmp12[1]}} + + xml=${xml//"currentyp01[0]"/${currentyp01[0]}} + xml=${xml//"currentyp01[1]"/${currentyp01[1]}} + xml=${xml//"currentyp02[0]"/${currentyp02[0]}} + xml=${xml//"currentyp02[1]"/${currentyp02[1]}} + xml=${xml//"currentyp04[0]"/${currentyp04[0]}} + xml=${xml//"currentyp04[1]"/${currentyp04[1]}} + xml=${xml//"currentyp05[0]"/${currentyp05[0]}} + xml=${xml//"currentyp05[1]"/${currentyp05[1]}} + xml=${xml//"currentyp11[0]"/${currentyp11[0]}} + xml=${xml//"currentyp11[1]"/${currentyp11[1]}} + xml=${xml//"currentyp12[0]"/${currentyp12[0]}} + xml=${xml//"currentyp12[1]"/${currentyp12[1]}} + + xml=${xml//wpedituserid/${wpedituserid}} + xml=${xml//wppageauthor/${wppageauthor}} + xml=${xml//wppagelinkis/${wppagelinkis}} + xml=${xml//wpeditdateis/${wpeditdateis}} + + response=$(curl -d "${xml}" "${wpxmlrpclink}") + if echo "${response}" | grep -q '1'; then + addtologs "update $(grep 'Link' "${xml}" | cut -d'>' -f 6 | cut -d'<' -f 1))" + else + echo "${response}" | xmllint --format - > "${pathroot}/wp-page${wpeditpageid}-response.xml" 2>/dev/null + execerror "${pathroot}/wp-page${wpeditpageid}-response.xml" + fi +fi +execquite diff --git a/streaming.py b/archive/0.1/streaming.py similarity index 100% rename from streaming.py rename to archive/0.1/streaming.py diff --git a/archive/0.2/README.md b/archive/0.2/README.md new file mode 100644 index 0000000..e53bdd7 --- /dev/null +++ b/archive/0.2/README.md @@ -0,0 +1,237 @@ +# cctv-scheduler + +PTZ IP-Camera management +____ + +- [`cctv-scheduler.py`](https://git.hmp.today/pavel.muhortov/cctv-scheduler#cctv-scheduler-py) +- [`converter.sh`](https://git.hmp.today/pavel.muhortov/cctv-scheduler#converter-sh) +- [`publisher.sh`](https://git.hmp.today/pavel.muhortov/cctv-scheduler#publisher-sh) +- [`streaming.py`](https://git.hmp.today/pavel.muhortov/cctv-scheduler#streaming-py) + +____ + +![cctv-scheduler](info/images/cctv-scheduler-0.2.png) + +## `Installation` + +### `Requirements` + +Cameras settings: +> +> - Configuration -> System -> Security -> Authentication -> RTSP Authentication: digest/basic +> - Configuration -> System -> Security -> Authentication -> WEB Authentication: digest/basic +> - Configuration -> Network -> Advanced Settings -> Integration Protocol -> Enable Hikvision-CGI: Enabled +> - Configuration -> Network -> Advanced Settings -> Integration Protocol -> Hikvision-CGI Authentication: digest/basic + +Look at the description of dependencies and install the necessary. + +### `Downloading` + +Download scripts and configs. + +```bash +wget https://git.hmp.today/pavel.muhortov/cctv-scheduler/raw/branch/master/cctv-scheduler.py -O /home/user/cctv-scheduler/cctv-scheduler.py +wget https://git.hmp.today/pavel.muhortov/cctv-scheduler/raw/branch/master/cctv-scheduler.conf -O /home/user/cctv-scheduler/cctv-scheduler.conf +wget https://git.hmp.today/pavel.muhortov/cctv-scheduler/raw/branch/master/converter.sh -O /home/user/cctv-scheduler/converter.sh +wget https://git.hmp.today/pavel.muhortov/cctv-scheduler/raw/branch/master/converter.conf -O /home/user/cctv-scheduler/converter.conf +wget https://git.hmp.today/pavel.muhortov/cctv-scheduler/raw/branch/master/publisher.sh -O /home/user/cctv-scheduler/publisher.sh +wget https://git.hmp.today/pavel.muhortov/cctv-scheduler/raw/branch/master/publisher.conf -O /home/user/cctv-scheduler/publisher.conf +wget https://git.hmp.today/pavel.muhortov/cctv-scheduler/raw/branch/master/publisher-template-page-1007.xml -O /home/user/cctv-scheduler/publisher-template-page-1007.xml +wget https://git.hmp.today/pavel.muhortov/cctv-scheduler/raw/branch/master/streaming.py -O /home/user/cctv-scheduler/streaming.py +``` + +### `Configuration` + +Edit configs. + +```bash +nano /home/user/cctv-scheduler/cctv-scheduler.conf +nano /home/user/cctv-scheduler/converter.conf +nano /home/user/cctv-scheduler/publisher.conf +``` + +### `Scheduler` + +Look at examples and edit scheduler tasks: + +```bash +crontab -e +``` + +## `cctv-scheduler`.py + +**Description:** +> [Hikvision](https://git.hmp.today/pavel.muhortov/cctv-scheduler/src/branch/master/info/hikvision/manual/isapi.pdf) PTZ IP-Camera management. +> Additionally: +> +> - getting temperature from DS18B20 over SSH, +> - saving pictures to FTP. +> +> This is only a local "proof of conept" for testing and debugging. + +**Dependencies:** +> +> - [Python 3](https://www.python.org/downloads/) (tested version 3.9.5 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/)) +> - [paramiko](https://www.paramiko.org/) Python 3 module (tested version 3.1.0) + +| PARAMETERS | DESCRIPTION | DEFAULT| +|-------------|-------------|--------| +|**[-h]**|print help and exit|| +|**[-s, --sequences]**|run sequences from config file|`None`| +|**[--config]**|custom configuration file path|`./cctv-scheduler.conf`| + +Example usage in terminal with make the script executable: + +```bash +chmod u+x ./cctv-scheduler.py +./cctv-scheduler.py -s --config /home/user/cctv-scheduler/cctv-scheduler.conf +``` + +Example usage with cron: + +```bash +# crontab -e +0 * * * * /usr/bin/python3 /home/user/cctv-scheduler/cctv-scheduler.py -s +``` + +____ + +## `converter`.sh + +**Description:** +> JPEG to MP4 converter. +> +> This is only a local "proof of conept" for testing and debugging. + +**Dependencies:** +> +> - [bash](https://www.gnu.org/software/bash/) (tested version 5.1.4 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/)) +> - [ffmpeg](https://ffmpeg.org/download.html) (tested version 4.3.4 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/)) +> - filesystem organization: +> +>```bash +> # filesystem organisation example +>/root/ +> /2022/ +> /12/ +> /52/ +> /31/ +> /image-01_2022.12.31_time.jpeg +> /image-02_2022.12.31_time.jpeg +> /2023/ +> /01/ +> /01/ +> /02/ +> /image-01_2023.01.02_time.jpeg +> /image-02_2023.01.02_time.jpeg +> /03/ +> /image-01_2023.01.03_time.jpeg +> /image-02_2023.01.03_time.jpeg +>``` + +| POSITION | PARAMETERS | DESCRIPTION | DEFAULT | +|-----------|--------------|------------------------|---------------| +| 1 | **[qn]** |execution without pauses|| +| 2 | **[/path/to/conf]** |path to config| `./converter.conf` | +| 3 | **[-d\|-w\|-m\|-y]** |periods: '' - today \| '-d' - yesterday \| '-w' - last week \| '-m' - last month \| '-y' - last year|`''`| + +Example usage in terminal with bash for today's MP4 making: + +```bash +bash ./converter.sh - ./converter.conf +``` + +Example usage with cron: + +```bash +# crontab -e +1 0 * * * bash /home/user/cctv-scheduler/converter.sh qn - -d +7 0 * * 1 bash /home/user/cctv-scheduler/converter.sh qn - -w +30 0 1 * * bash /home/user/cctv-scheduler/converter.sh qn - -m +36 0 1 1 * bash /home/user/cctv-scheduler/converter.sh qn - -y +``` + +____ + +## `publisher`.sh + +**Description:** +> Uploading MP4 to [Wordpress](https://wordpress.com/) and [Telegram](https://web.telegram.org/). +> Additionally: +> +> - editing [Wordpress](https://codex.wordpress.org/XML-RPC_WordPress_API) page from template +> - recompressing video if size [over 50MB](https://core.telegram.org/bots/api#sendvideo) +> +> This is only a local "proof of conept" for testing and debugging. + +**Dependencies:** +> +> - [bash](https://www.gnu.org/software/bash/) (tested version 5.1.4 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/)) +> - [curl](https://curl.se/download.html) (tested version 7.74 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/)) +> - [ffmpeg](https://ffmpeg.org/download.html) (tested version 4.3.4 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/)) +> - [libxml2-utils](https://gitlab.gnome.org/GNOME/libxml2) (tested version 2.9.10 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/)) +> - [jq](https://stedolan.github.io/jq/download/) (tested version 1.6 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/)) +> + +| POSITION | PARAMETERS | DESCRIPTION | DEFAULT | +|-----------|--------------|------------------------|---------------| +| 1 | **[qn]** |execution without pauses|| +| 2 | **[/path/to/conf]** |path to config| `./publisher.conf` | +| 3 | **[-d\|-w\|-m\|-y]** |periods: '' - 0 day \| '-d' - -X day \| '-w' - -X week \| '-m' - -X month \| '-y' - -X year|`''`| +| 4 | **[1\|2\|3..XXX]** |multiplier for period: '' - 1 day\|week\|month\|year|`1`| +| 5 | **[--onlytg\|--onlywp]** |'--onlytg' - only publish to Telegram \|'--onlywp' - only publish to Wordpress|| + +Example usage in terminal with bash for publish to Telegram today's MP4: + +```bash +bash ./publisher.sh - ./publisher.conf - - - - --onlytg +``` + +Example usage with cron: + +```bash +# crontab -e +1 1 * * * bash /home/user/cctv-scheduler/publisher.sh qn - -d +7 1 * * 1 bash /home/user/cctv-scheduler/publisher.sh qn - -w +30 1 1 * * bash /home/user/cctv-scheduler/publisher.sh qn - -m +36 1 1 1 * bash /home/user/cctv-scheduler/publisher.sh qn - -y +``` + +____ + +## `streaming`.py + +**Description:** +> FFmpeg management from Python + +**Dependencies:** +> +> - [Python 3](https://www.python.org/downloads/) (tested version 3.9.5 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/)) +> - [ffmpeg](https://ffmpeg.org/download.html) (tested version 4.3.4 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/)) + +| PARAMETERS | DESCRIPTION | DEFAULT| +|-------------|-------------|--------| +|**-s**, **--src**|sources urls|**REQUIRED**| +|**[-h]**|print help and exit|| +|**[--preset]**|240p, 360p, 480p, 720p, 1080p, 1440p, 2160p|`None`| +|**[--fps]**|frame per second encoding output|`None`| +|**[--dst]**|destination url|`None`| +|**[--ffpath]**|alternative path to bin|`None`| +|**[--watchdog]**|detect ffmpeg freeze and terminate|| +|**[--sec]**|seconds to wait before the watchdog terminates|15| +|**[--mono]**|detect ffmpeg running copy and terminate|| + +Example usage in terminal with make the script executable: + +```bash +chmod u+x ./streaming.py +./streaming.py -s rtsp://user:pass@host:554/Streaming/Channels/101 --dst rtp://239.0.0.1:5554 +``` + +Example usage with cron: + +```bash +# crontab -e +* * * * * /usr/bin/python3 /home/user/cctv-scheduler/streaming.py -s rtsp://user:pass@host:554/Streaming/Channels/video,http://Streaming/Channels/audio --dst rtmp://a.rtmp.youtube.com/live2/YOUKEY --mono --watchdog --sec 30 >> /dev/null 2>&1 +* * * * * /usr/bin/python3 /home/user/cctv-scheduler/streaming.py -s ~/media.mp4 --dst rtmp://b.rtmp.youtube.com/live2?backup=1/YOUKEY --mono >> /dev/null 2>&1 +``` diff --git a/archive/0.2/cctv-scheduler.conf b/archive/0.2/cctv-scheduler.conf new file mode 100644 index 0000000..36acf93 --- /dev/null +++ b/archive/0.2/cctv-scheduler.conf @@ -0,0 +1,81 @@ +[common] +# By default, a temporary files directory is created in the same path where the script is located. +# If you need change it, uncomment the parameter and set the path you want. +#temp_path = /tmp/cctv-scheduler +# +# By default, logs use the same directory where the script is located. +# If you need change it, uncomment the parameter and set the path you want. +#log_root = /var/log/cctv-scheduler +# +# The default log level is "INFO". +# If you get errors or want to change the logging level, uncomment the parameter and set the level you want: +# DEBUG, INFO, WARNING, ERROR, CRITICAL. +#log_level = DEBUG + + +[enable-sensors] +# List the sensor block names. Only blocks with the TRUE value will be used. +sensor.test.local = true + + +[sensor-config:sensor.test.local] +# Remote host's sensor parameter description block always starts with "sensor-config:". +hostname = 192.168.254.252 +username = user +userpass = pass +# To recognize options for polling a sensor, you must specify the type of sensor. +# Supported types: +# ds18b20 +nodetype = ds18b20 +nodename = 28-1a2b3c4d5e6f + + +[enable-sequences] +# List the sequence/camera block names. Only blocks with the TRUE value will be used. +camera.test.local = true + + +[camera-config:camera.test.local] +# Camera parameter description block always starts with "camera-config:". +hostname = 192.168.254.253 +username = user +userpass = pass +# If a record directory on a remote host is used, a username and password must be specified. +# Supported protocols: +# FTP, SFTP. +records_root_path = ftp://192.168.254.254/Records/camera.test.local +records_root_user = user +records_root_pass = pass + + +[camera-sequences:camera.test.local] +# Camera sequence description block always starts with "camera-sequences:". +# Place only the sequence of PTZ-actions in this block! +# Variable name can be anything. Only 'downloadjpeg' is using this for filename prefix. +# Available actions: +# setcamerapos, setcameramov, settextonosd, downloadjpeg, capabilities, getcamerapos, +# setptzmovyyu, setptzmovyyd, setptzmovxxl, setptzmovxxr, setptzmovzzi, setptzmovzzo, +# setptzpreset, setptztostop, setmovtohome, setposashome, rebootcamera. +# +# Format (spaces are used for readability only): +# name = action, x, y, zoom, preset, speed, d(ms), w(s), text, notes or anything +step001 = capabilities, -, -, -, -, -, -, 3, , +step002 = getcamerapos, -, -, -, -, -, -, 3, , +step011 = setmovtohome, -, -, -, -, -, -, 15, , +step021 = setptzmovyyd, -, -, -, -, 2, -, 5, , 'speed: 1..7' +step022 = setptzmovyyu, -, -, -, -, 4, -, 3, , 'speed: 1..7' +step023 = setptzmovxxl, -, -, -, -, 4, -, 3, , 'speed: 1..7' +step024 = setptzmovxxr, -, -, -, -, 2, -, 5, , 'speed: 1..7' +step025 = setptzmovzzi, -, -, -, -, 7, -, 3, , 'speed: 1..7' +step026 = setptzmovzzo, -, -, -, -, 7, -, 3, , 'speed: 1..7' +step027 = setptztostop, -, -, -, -, -, -, 3, , +step031 = setptzpreset, -, -, -, 2, 1, -, 15, , 'speed: 1..7' +step041 = setcameramov, 33, 33, 66, -, -, -, 5, , 'x: -100..100, y: -100..100, z: -100..100, duration: 0..180000' +step042 = setcameramov, -66, -66, -99, -, -, 5000, 0, , 'x: -100..100, y: -100..100, z: -100..100, duration: 0..180000' +step043 = setcamerapos, 0, 0, 0, -, -, -, 15, , 'x: 0..3600, y: -900..2700, z: 0..1000' +step051 = setposashome, -, -, -, -, -, -, 3.5, , +step061 = settextonosd, 0, 0, -, -, -, -, 3, hello, 'x|y: osd text position, text: text for osd without quotes or commas' +step062 = settextonosd, 0, 0, -, -, -, -, 3, sensor-config:sensor.test.local, 'if a sensor configuration is specified, the sensor value is used instead of text' +step063 = settextonosd, 0, 0, -, -, -, -, 3, , 'an empty text value is used to clear the osd' +step071 = downloadjpeg, 1280, 720, -, -, -, -, 5, , 'name: filename prefix, x|y: camera width|height resolution' +step999 = rebootcamera, -, -, -, -, -, -, 120, , diff --git a/archive/0.2/cctv-scheduler.py b/archive/0.2/cctv-scheduler.py new file mode 100644 index 0000000..e119e78 --- /dev/null +++ b/archive/0.2/cctv-scheduler.py @@ -0,0 +1,1240 @@ +#!/usr/bin/env python3 + + +import logging +import urllib.request +from argparse import ArgumentParser +from datetime import datetime +from ftplib import FTP +from os import path, sep, makedirs, remove, replace +from time import sleep +from paramiko import SSHClient, AutoAddPolicy + + +class Parse: + """Parser of configs, arguments, parameters. + """ + def __init__(self, parameters, block: str = None) -> None: + """Object constructor. + + Args: + parameters: dictionary as "key":"value" or + ArgumentParser class object or + string path to the file or + string as "var1=val1;var2=val2". + block (str, optional): name of target block from text. Defaults to None. + """ + self.path = '' + self.data = {} + if type(parameters) is dict: + self._dict2dict(parameters) + if type(parameters) is ArgumentParser: + self._dict2dict(self.argv2dict(parameters)) + if type(parameters) is str: + if path.exists(parameters): + self._dict2dict( + self.strs2dict( + self.conf2strs(parameters), + block + ) + ) + self.path = parameters + else: + self._dict2dict(self.strs2dict(parameters, block)) + + def __str__(self) -> str: + """Overrides method for print(object). + + Returns: + str: string with contents of the object's dictionary. + """ + string = '' + for key, val in self.data.items(): + string += str(type(val)) + ' ' + str(key) + ' = ' + str(val) + '\n' + return string + + def _dict2dict(self, dictionary: dict) -> None: + """Updates or adds dictionary data. + + Args: + dictionary (dict): dictionary as "key":"value". + """ + self.data.update(dictionary) + + def expand(self, store: str = None) -> dict: + """Expand dictionary "key":"name.conf" to dictionary "key":{subkey: subval}. + + Args: + store (str, optional): path to directory with name.conf. Defaults to None. + + Returns: + dict: expanded dictionary as "key":{subkey: subval}. + """ + for key in self.data: + if store: + config = store + sep + self.data[key] + else: + config = self.data[key] + with open(config) as file: + self.data[key] = Parse(file.read()).data + return self.data + + @classmethod + def argv2dict(cls, parser: ArgumentParser) -> dict: + """Converts startup arguments to a dictionary. + + Args: + parser (ArgumentParser): argparse.ArgumentParser class object. + + Returns: + dict: dictionary as "key":"value". + """ + parser = ArgumentParser(add_help=False, parents=[parser]) + return vars(parser.parse_args()) + + @classmethod + def conf2strs(cls, config: str) -> str: + """Builds a dictionary from a file containing parameters. + + Args: + config (str): path to the config file. + + Returns: + str: string as "var1=val1;\nvar2=val2;". + """ + with open(config) as file: + raw = file.read() + strs = '' + for line in raw.splitlines(): + if not line.lstrip().startswith('#'): + strs += line + '\n' + return strs + + @classmethod + def strs2dict(cls, strings: str, blockname: str) -> dict: + """Builds a dictionary from a strings containing parameters. + + Args: + strings (str): string as "var1=val1;var2=val2;". + blockname (str): name of target block from text. + + Returns: + dict: dictionary as "key":"value". + """ + dictionary = {} + if blockname: + strings = cls.block(blockname, strings) + for line in strings.replace('\n', ';').split(';'): + if not line.lstrip().startswith('#') and "=" in line: + dictionary[line.split('=')[0].strip()] = line.split('=')[1].strip().split(';')[0].strip() + return dictionary + + @classmethod + def str2bool(cls, value: str) -> bool: + """Converts a string value to boolean. + + Args: + value (str): string containing "true" or "false", "yes" or "no", "1" or "0". + + Returns: + bool: bool True or False. + """ + return str(value).lower() in ("true", "yes", "1") + + @classmethod + def block(cls, blockname: str, text: str) -> str: + """Cuts a block of text between line [blockname] and line [next block] or EOF. + + Args: + blockname (str): string in [] after which the block starts. + text (str): string of text from which the block is needed. + + Returns: + str: string of text between line [block name] and line [next block]. + """ + level = 1 + save = False + result = '' + for line in text.splitlines(): + if line.startswith('[') and blockname in line: + level = line.count('[') + save = True + elif line.startswith('[') and '['*level in line: + save = False + elif save: + result += line + '\n' + return result + + +class Connect: + """Set of connection methods (functions) for various protocols. + """ + @staticmethod + def http( + url: str, method: str = 'GET', + username: str = '', password: str = '', authtype: str = None, + contenttype: str = 'text/plain', contentdata: str = '' + ) -> str: + """Handling HTTP request. + + Args: + url (str): request url. + method (str, optional): HTTP request method. Defaults to 'GET'. + username (str, optional): username for url authentication. Defaults to ''. + password (str, optional): password for url authentication. Defaults to ''. + authtype (str, optional): digest|basic authentication type. Defaults to None. + contenttype (str, optional): 'Content-Type' header. Defaults to 'text/plain'. + contentdata (str, optional): content data. Defaults to ''. + + Returns: + str: HTTP response or 'ERROR'. + """ + + # Preparing authorization + if authtype: + pswd = urllib.request.HTTPPasswordMgrWithDefaultRealm() + pswd.add_password(None, url, username, password) + if authtype == 'basic': + auth = urllib.request.HTTPBasicAuthHandler(pswd) + if authtype == 'digest': + auth = urllib.request.HTTPDigestAuthHandler(pswd) + urllib.request.install_opener(urllib.request.build_opener(auth)) + + # Preparing request + request = urllib.request.Request(url=url, data=bytes(contentdata.encode('utf-8')), method=method) + request.add_header('Content-Type', contenttype) + + # Response + try: + response = urllib.request.urlopen(request).read() + logging.debug( + msg='' + + '\n' + 'uri: ' + url + + '\n' + 'method: ' + method + + '\n' + 'username: ' + username + + '\n' + 'password: ' + password + + '\n' + 'authtype: ' + authtype + + '\n' + 'content-type: ' + contenttype + + '\n' + 'content-data: ' + contentdata + ) + if response.startswith(b'\xff\xd8'): + return response + else: + return str(response.decode('utf-8')) + except Exception as error: + logging.debug(msg='\n' + 'error: ' + str(error)) + return 'ERROR' + + @staticmethod + def ssh_commands(command: str, hostname: str, username: str, password: str, port: int = 22) -> str: + """Handling SSH command executing. + + Args: + command (str): command for executing. + hostname (str): remote hostname or ip address. + username (str): remote host username. + password (str): remote host password. + port (int, optional): remote host connection port. Defaults to 22. + + Returns: + str: terminal response or 'ERROR'. + """ + client = SSHClient() + client.set_missing_host_key_policy(AutoAddPolicy()) + try: + client.connect(hostname=hostname, username=username, password=password, port=port) + stdin, stdout, stderr = client.exec_command(command=command, get_pty=True) + if 'sudo' in command: + stdin.write(password + '\n') + stdin.flush() + stdout.flush() + data = stdout.read() + stderr.read() + client.close() + return data.decode('utf-8') + except Exception as error: + logging.debug( + msg='' + + '\n' + 'host: ' + hostname + ':' + str(port) + + '\n' + 'user: ' + username + + '\n' + 'pass: ' + password + + '\n' + 'command: ' + command + + '\n' + 'error: ' + str(error) + ) + return 'ERROR' + + @staticmethod + def ssh_put_file(src_file: str, dst_file: str, hostname: str, username: str, password: str, port: int = 22) -> str: + """Handling SFTP upload file. + + Args: + src_file (str): /local/path/to/file. + dst_file (str): /remote/path/to/file. + hostname (str): remote hostname or ip address. + username (str): remote host username. + password (str): remote host password. + port (int, optional): remote host connection port. Defaults to 22. + + Returns: + str: '/remote/path/to/file' or 'ERROR'. + """ + client = SSHClient() + client.set_missing_host_key_policy(AutoAddPolicy()) + try: + client.connect(hostname=hostname, username=username, password=password, port=port) + client.exec_command('mkdir -p ' + path.dirname(dst_file)) + try: + sftp = client.open_sftp() + sftp.put(localpath=src_file, remotepath=dst_file) + sftp.stat(dst_file) + sftp.close() + return dst_file + except Exception as error: + logging.debug( + msg='' + + '\n' + 'dst_file: ' + dst_file + + '\n' + 'error: ' + str(error) + ) + return 'ERROR' + except Exception as error: + logging.debug( + msg='' + + '\n' + 'host: ' + hostname + ':' + str(port) + + '\n' + 'user: ' + username + + '\n' + 'pass: ' + password + + '\n' + 'src_file: ' + src_file + + '\n' + 'dst_file: ' + dst_file + + '\n' + 'error: ' + str(error) + ) + return 'ERROR' + ''' + @staticmethod + def ssh_get_file(src_file: str, dst_file: str, hostname: str, username: str, password: str, port: int = 22) -> str: + """Handling SFTP download file. + + Args: + src_file (str): /remote/path/to/file. + dst_file (str): /local/path/to/file. + hostname (str): remote hostname or ip address. + username (str): remote host username. + password (str): remote host password. + port (int, optional): remote host connection port. Defaults to 22. + + Returns: + str: '/local/path/to/file' or 'ERROR'. + """ + client = SSHClient() + client.set_missing_host_key_policy(AutoAddPolicy()) + try: + client.connect(hostname=hostname, username=username, password=password, port=port) + with client.open_sftp() as sftp: + sftp.get(remotepath=src_file, localpath=dst_file) + client.close() + except Exception as error: + logging.debug( + msg='' + + '\n' + 'host: ' + hostname + ':' + str(port) + + '\n' + 'user: ' + username + + '\n' + 'pass: ' + password + + '\n' + 'src_file: ' + src_file + + '\n' + 'dst_file: ' + dst_file + + '\n' + 'error: ' + str(error) + ) + return 'ERROR' + ''' + @staticmethod + def ftp_put_file(src_file: str, dst_file: str, hostname: str, username: str, password: str) -> bool: + dst_path = dst_file.split('/')[:-1] + ftp = FTP(host=hostname) + try: + ftp.login(user=username, passwd=password) + for path_item in dst_path: + if path_item.strip() == '': + continue + path_item = path_item.replace('/', '') + try: + ftp.cwd(path_item) + except Exception: + ftp.mkd(path_item) + ftp.cwd(path_item) + except Exception: + pass + + with open(src_file, "rb") as file: + ftp.storbinary(f"STOR {dst_file}", file) + ftp.quit() + return True + ''' + @staticmethod + def ftp_get_file(src_file: str, dst_file: str, hostname: str, username: str, password: str): + ftp = FTP(host=hostname) + try: + ftp.login(user=username, passwd=password) + with open(dst_file, "wb") as file: + ftp.retrbinary(f"RETR {src_file}", file.write) + ftp.quit() + except Exception: + pass + ''' + ''' + @staticmethod + def xmlrpc(): + pass + ''' + + +class HikISAPI(Connect): + """Representing Hikvision device with ISAPI. + The class inherits the necessary connection methods of the Connect class + """ + def __init__( + self, + hostname: str, + username: str, userpass: str, + authtype: str = 'digest', + hostport: int = 80, protocol: str = 'http', + channel: int = 101, videoid: int = 1 + ) -> None: + """Object constructor. + + Args: + hostname (str): camera hostname or ip address. + username (str): camera admin username. + userpass (str): camera admin password. + authtype (str, optional): digest|basic camera authentication type. Defaults to 'digest'. + hostport (int, optional): camera connection port. Defaults to 80. + protocol (str, optional): camera connection protocol. Defaults to 'http'. + channel (int, optional): camera channel id. Defaults to 101. + videoid (int, optional): camera video id. Defaults to 1. + """ + self._host = hostname + self._port = hostport + self._user = username + self._pswd = userpass + self._auth = authtype + self._prot = protocol + self._chan = channel + self._viid = videoid + + def __call( + self, + url: str, method: str = 'GET', + contenttype: str = 'application/x-www-form-urlencoded', + contentdata: str = '' + ) -> str: + """Send request to camera. + + Args: + url (str): API path for request. + method (str, optional): HTTP request method. Defaults to 'GET'. + contenttype (str, optional): Content-Type header. Defaults to 'application/x-www-form-urlencoded'. + contentdata (str, optional): data for send with request. Defaults to ''. + + Returns: + str: HTTP response content. + """ + return self.http( + url=url, method=method, + username=self._user, password=self._pswd, authtype=self._auth, + contenttype=contenttype, contentdata=contentdata + ) + + def capabilities(self) -> bool: + """Get camera capabilities. + + Returns: + bool: True if successed. Printing a response with a logger at the INFO level. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/ISAPI/PTZCtrl/channels/" + str(self._viid) + "/capabilities" + ) + response = self.__call(url=url, method='GET') + if response != 'ERROR': + logging.info(msg='\n' + response + '\n') + return True + else: + return False + + def downloadjpeg(self, dst_file: str = path.splitext(__file__)[0] + '.jpeg', x: int = 1920, y: int = 1080) -> bool: + """Get static picture from camera. + + Args: + dst_file (str, optional): absolute path of picture to save. Defaults to scriptname+'.jpeg'. + x (int, optional): picture width. Defaults to 1920. + y (int, optional): picture height. Defaults to 1080. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/Streaming/channels/" + str(self._viid) + + "/picture?snapShotImageType=JPEG&videoResolutionWidth=" + + str(x) + "&videoResolutionHeight=" + str(y) + ) + with open(dst_file, "wb") as file: + response = self.__call(url=url, method='GET') + if response != 'ERROR': + file.write(response) + logging.debug(msg='\n' + dst_file + '\n') + return True + else: + return False + + def getcamerapos(self) -> bool: + """Get current camera position. + + Returns: + bool: True if successed. Printing a response with a logger at the INFO level. + """ + url = (self._prot + '://' + self._host + ':' + str(self._port) + + "/ISAPI/PTZCtrl/channels/" + str(self._chan) + "/status") + response = self.__call(url=url, method='GET') + if response != 'ERROR': + logging.info(msg='\n' + response + '\n') + return True + else: + return False + + def rebootcamera(self) -> bool: + """Set camera reboot command. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/ISAPI/System/reboot" + ) + response = self.__call(url=url, method="PUT") + if response != 'ERROR': + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + def setptzmovyyu(self, speed: int = 1) -> bool: + """Start camera moving to up. + + Args: + speed (int, optional): moving speed from 1 to 7. Defaults to 1. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/PTZ/channels/" + str(self._viid) + + "/PTZControl?command=TILT_UP&speed=" + str(speed) + + "&mode=start" + ) + response = self.__call(url=url, method='GET') + if response != 'ERROR': + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + def setptzmovyyd(self, speed: int = 1) -> bool: + """Start camera moving to down. + + Args: + speed (int, optional): moving speed from 1 to 7. Defaults to 1. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/PTZ/channels/" + str(self._viid) + + "/PTZControl?command=TILT_DOWN&speed=" + str(speed) + + "&mode=start" + ) + response = self.__call(url=url, method='GET') + if response != 'ERROR': + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + def setptzmovxxl(self, speed: int = 1) -> bool: + """Start camera moving to left. + + Args: + speed (int, optional): moving speed from 1 to 7. Defaults to 1. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/PTZ/channels/" + str(self._viid) + + "/PTZControl?command=PAN_LEFT&speed=" + str(speed) + + "&mode=start" + ) + response = self.__call(url=url, method='GET') + if response != 'ERROR': + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + def setptzmovxxr(self, speed: int = 1) -> bool: + """Start camera moving to right. + + Args: + speed (int, optional): moving speed from 1 to 7. Defaults to 1. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/PTZ/channels/" + str(self._viid) + + "/PTZControl?command=PAN_RIGHT&speed=" + str(speed) + + "&mode=start" + ) + response = self.__call(url=url, method='GET') + if response != 'ERROR': + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + def setptzmovzzi(self, speed: int = 1) -> bool: + """Start camera zoom in. + + Args: + speed (int, optional): moving speed from 1 to 7. Defaults to 1. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/PTZ/channels/" + str(self._viid) + + "/PTZControl?command=ZOOM_OUT&speed=" + str(speed) + + "&mode=start" + ) + response = self.__call(url=url, method='GET') + if response != 'ERROR': + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + def setptzmovzzo(self, speed: int = 1) -> bool: + """Start camera zoom out. + + Args: + speed (int, optional): moving speed from 1 to 7. Defaults to 1. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/PTZ/channels/" + str(self._viid) + + "/PTZControl?command=ZOOM_IN&speed=" + str(speed) + + "&mode=start" + ) + response = self.__call(url=url, method='GET') + if response != 'ERROR': + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + def setptzpreset(self, preset: int, speed: int = 1) -> bool: + """Start camera moving to preset. + + Args: + preset (int): saved preset number. + speed (int, optional): moving speed from 1 to 7. Defaults to 1. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/PTZ/channels/" + str(self._viid) + + "/PTZControl?command=GOTO_PRESET&presetNo=" + str(preset) + + "&speed=" + str(speed) + + "&mode=start" + ) + response = self.__call(url=url, method='GET') + if response != 'ERROR': + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + def setptztostop(self) -> bool: + """Stop any camera moving. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/PTZ/channels/" + str(self._viid) + + "/PTZControl?command=GOTO_PRESET&mode=stop" + ) + response = self.__call(url=url, method='GET') + if response != 'ERROR': + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + def setcamerapos(self, x: int = 0, y: int = 0, z: int = 0) -> bool: + """Set camera moving to absolute position. + + Args: + x (int, optional): horisontal camera position from 0 to 3600. Defaults to 0. + y (int, optional): vertical camera position from -900 to 2700. Defaults to 0. + z (int, optional): zoom camera position from 0 to 1000. Defaults to 0. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/ISAPI/PTZCtrl/channels/" + str(self._chan) + + "/absolute" + ) + xml = ''.join( + '' + + '' + + '' + str(y) + '' + + '' + str(x) + '' + + '' + str(z) + '' + + '' + ) + response = self.__call(url=url, method="PUT", contenttype="text/xml", contentdata=xml) + if response != 'ERROR': + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + def __setcameramovcon(self, x: int = 0, y: int = 0, z: int = 0) -> bool: + """Set camera moving to direction until other signal or 180 seconds elapse. + + Args: + x (int, optional): acceleration of horizontal camera movement from -100 to 100. Defaults to 0. + y (int, optional): acceleration of vertical camera movement from -100 to 100. Defaults to 0. + z (int, optional): acceleration of zoom camera movement from -100 to 100. Defaults to 0. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/ISAPI/PTZCtrl/channels/" + str(self._chan) + + "/continuous" + ) + xml = ''.join( + '' + + '' + + '' + str(x) + '' + + '' + str(y) + '' + + '' + str(z) + '' + + '' + ) + response = self.__call(url=url, method="PUT", contenttype="text/xml", contentdata=xml) + if response != 'ERROR': + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + def __setcameramovmom(self, x: int = 0, y: int = 0, z: int = 0, t: int = 180000) -> bool: + """Set camera moving to direction until other signal or duration elapse. + + Args: + x (int, optional): acceleration of horizontal camera movement from -100 to 100. Defaults to 0. + y (int, optional): acceleration of vertical camera movement from -100 to 100. Defaults to 0. + z (int, optional): acceleration of zoom camera movement from -100 to 100. Defaults to 0. + t (int, optional): duration in ms of acceleration from 0 to 180000. Defaults to 180000. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/ISAPI/PTZCtrl/channels/" + str(self._chan) + + "/momentary" + ) + xml = ''.join( + '' + + '' + + '' + str(x) + '' + + '' + str(y) + '' + + '' + str(z) + '' + + '' + str(t) + '' + + '' + ) + response = self.__call(url=url, method="PUT", contenttype="text/xml", contentdata=xml) + if response != 'ERROR': + sleep(t/1000) + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + def setcameramov(self, x: int = 0, y: int = 0, z: int = 0, t: int = 0) -> bool: + """Set camera moving to direction (polymorph abstraction). + + Args: + x (int, optional): acceleration of horizontal camera movement from -100 to 100. Defaults to 0. + y (int, optional): acceleration of vertical camera movement from -100 to 100. Defaults to 0. + z (int, optional): acceleration of zoom camera movement from -100 to 100. Defaults to 0. + t (int, optional): duration in ms of acceleration from 0 to 180000. Defaults to 0. + + Returns: + bool: True if successed. + """ + if t == '-' or int(t) == 0: + return self.__setcameramovcon(x=int(x), y=int(y), z=int(z)) + else: + return self.__setcameramovmom(x=int(x), y=int(y), z=int(z), t=int(t)) + + def setmovtohome(self) -> bool: + """Set camera moving to homeposition. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/ISAPI/PTZCtrl/channels/" + str(self._chan) + + "/homeposition/goto" + ) + xml = ''.join( + '' + + '' + ) + response = self.__call(url=url, method="PUT", contenttype="text/xml", contentdata=xml) + if response != 'ERROR': + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + def setposashome(self) -> bool: + """Save current camera position as homeposition. + + Returns: + bool: True if successed. + """ + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/ISAPI/PTZCtrl/channels/" + str(self._chan) + + "/homeposition" + ) + xml = ''.join( + '' + + '' + ) + response = self.__call(url=url, method="PUT", contenttype="text/xml", contentdata=xml) + if response != 'ERROR': + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + def settextonosd(self, enabled: str = "true", x: int = 0, y: int = 0, message: str = "") -> bool: + """Set message as video overlay text. + + Args: + enabled (str, optional): true or false. Defaults to "true". + x (int, optional): horizontal text position from 0 to video width. Defaults to 0. + y (int, optional): vertical text position from 0 to video heith. Defaults to 0. + message (str, optional): overlay text content. Defaults to "". + + Returns: + bool: True if successed. + """ + if message == '-': + message = "" + url = ( + self._prot + '://' + self._host + ':' + str(self._port) + + "/ISAPI/System/Video/inputs/channels/" + str(self._chan) + + "/overlays/text" + ) + xml = ''.join( + '' + + '' + + '' + + '1' + + '' + enabled + '' + + '' + str(x) + '' + + '' + str(y) + '' + + '' + message + '' + + '' + + '' + ) + response = self.__call(url=url, method="PUT", contenttype="text/xml", contentdata=xml) + if response != 'ERROR': + logging.debug(msg='\n' + response + '\n') + return True + else: + return False + + +class Sensor(Connect): + """Representing sensor connected to remote host. + The class inherits the necessary connection methods of the Connect class + """ + def __init__( + self, + hostname: str, username: str, userpass: str, + nodetype: str, nodename: str, + hostport: int = 22 + ) -> None: + """Object constructor. + + Args: + hostname (str): sensor's remote host hostname or ip address. + username (str): sensor's remote host username. + userpass (str): sensor's remote host password. + nodetype (str): 'ds18b20' or other sensor type. + nodename (str): 28-1a2b3c4d5e6f (ds18b20 example). + hostport (int, optional): sensor's remote host connection port. Defaults to 22. + """ + self._host = hostname + self._port = hostport + self._user = username + self._pswd = userpass + self._type = nodetype + self._node = nodename + + def __call(self, command: str) -> str: + """Send request to sensor's remote host. + + Args: + command (str): command to poll the sensor. + + Returns: + str: sensor's remote host response content. + """ + return self.ssh_commands( + command=command, + hostname=self._host, port=self._port, + username=self._user, password=self._pswd + ) + + def __temperature(self, nodename: str) -> str: + """Preparating request for ds18b20 sensor type. + + Args: + nodename (str): 28-1a2b3c4d5e6f (ds18b20 example). + + Returns: + str: formatted string with temperature in Celsius. + """ + command = 'cat /sys/bus/w1/devices/' + nodename + '/temperature' + response = self.__call(command=command) + if response != 'ERROR': + try: + temperature = str(int(response)//1000) + "'C" + return temperature + except Exception as error: + logging.debug( + msg='' + + '\n' + 'host: ' + self._host + ':' + str(self._port) + + '\n' + 'user: ' + self._user + + '\n' + 'pass: ' + self._pswd + + '\n' + 'command: ' + command + + '\n' + 'error: ' + str(error) + ) + return 'ERROR' + + def value(self) -> str: + """Public method to get sensor value. + + Returns: + str: sensor value. + """ + if self._type == 'ds18b20': + return self.__temperature(nodename=self._node) + + +class Sequence: + """Sequence handling. + """ + @staticmethod + def run( + device: HikISAPI, sensors: dict, sequence: dict, + records_root_path: str = None, + records_root_user: str = None, + records_root_pass: str = None + ) -> None: + """Sequences executor. + + Args: + device (HikISAPI): HikISAPI object. + sensors (dict): collection as key=sensorname:value=Sensor object. + sequence (dict): sequence steps collection. + records_root_path (str, optional): path (local|smb|ftp,sftp) to records directory. Defaults to None. + records_root_user (str, optional): username if path on remote host. Defaults to None. + records_root_pass (str, optional): password if path on remote host. Defaults to None. + """ + for key, value in sequence.items(): + action = value.split(',')[0].strip() + x = value.split(',')[1].strip() + y = value.split(',')[2].strip() + z = value.split(',')[3].strip() + p = value.split(',')[4].strip() + s = value.split(',')[5].strip() + t = value.split(',')[6].strip() + w = value.split(',')[7].strip() + m = value.split(',')[8].strip() + if 'sensor-config:' in m: + sensor_name = m.split(':')[1].strip() + sensor_value = sensors[sensor_name].value() + if sensor_value != 'ERROR': + m = sensor_value + else: + m = '' + logging.info( + msg=' action:' + key + ' = ' + action + + ',' + x + ',' + y + ',' + z + + ',' + p + ',' + s + ',' + t + + ',' + w + ',' + m + ) + if action == 'capabilities': + response = device.capabilities() + elif action == 'getcamerapos': + response = device.getcamerapos() + elif action == 'rebootcamera': + response = device.rebootcamera() + elif action == 'setptzmovyyu': + response = device.setptzmovyyu(speed=int(s)) + elif action == 'setptzmovyyd': + response = device.setptzmovyyd(speed=int(s)) + elif action == 'setptzmovxxl': + response = device.setptzmovxxl(speed=int(s)) + elif action == 'setptzmovxxr': + response = device.setptzmovxxr(speed=int(s)) + elif action == 'setptzmovzzi': + response = device.setptzmovzzi(speed=int(s)) + elif action == 'setptzmovzzo': + response = device.setptzmovzzo(speed=int(s)) + elif action == 'setptzpreset': + response = device.setptzpreset(preset=int(p), speed=int(s)) + elif action == 'setptztostop': + response = device.setptztostop() + elif action == 'setcamerapos': + response = device.setcamerapos(x=int(x), y=int(y), z=int(z)) + elif action == 'setcameramov': + response = device.setcameramov(x=int(x), y=int(y), z=int(z), t=t) + elif action == 'setmovtohome': + response = device.setmovtohome() + elif action == 'setposashome': + response = device.setposashome() + elif action == 'settextonosd': + response = device.settextonosd(x=int(x), y=int(y), message=m) + elif action == 'downloadjpeg': + records_root_temp = records_root_path + if records_root_temp != path.dirname(path.realpath(__file__)): + records_root_temp = path.dirname(path.realpath(__file__)) + sep + 'temp' + makedirs(records_root_temp, exist_ok=True) + dy = datetime.now().strftime('%Y') + dm = datetime.now().strftime('%m') + dv = datetime.now().strftime('%V') + dd = datetime.now().strftime('%d') + th = datetime.now().strftime('%H') + tm = datetime.now().strftime('%M') + ts = datetime.now().strftime('%S') + records_file_name = (key + '_' + dy + '-' + dm + '-' + dd + '_' + th + '.' + tm + '.' + ts + '.jpeg') + if device.downloadjpeg(x=int(x), y=int(y), dst_file=records_root_temp + sep + records_file_name): + hostname = 'localhost' + hostport, hosttype = None, None + username = records_root_user + userpass = records_root_pass + hostpath = records_root_path + if '://' in records_root_path: + hostname = records_root_path.split('/')[2] + hosttype = records_root_path.split('://')[0] + if hosttype == 'ftp': + hostport = 21 + if hosttype == 'sftp': + hostport = 22 + if hosttype == 'smb': + hostport = 445 + hostpath = records_root_path.replace(hosttype + '://' + hostname, '') + if '@' in hostname: + username = hostname.split('@')[0].split(':')[0] + userpass = hostname.split('@')[0].split(':')[1] + hostname = hostname.split('@')[1] + if ':' in hostname: + hostport = int(hostname.split(':')[1]) + hostname = hostname.split(':')[0] + if hosttype == 'ftp': + src_file = records_root_temp + sep + records_file_name + dst_file = hostpath + '/' + dy + '/' + dm + '/' + dv + '/' + dd + '/' + records_file_name + if Connect.ftp_put_file( + src_file=src_file, + dst_file=dst_file, + hostname=hostname, + username=username, + password=userpass + ): + try: + remove(src_file) + except OSError: + pass + elif hosttype == 'sftp': + src_file = records_root_temp + sep + records_file_name + dst_file = hostpath + '/' + dy + '/' + dm + '/' + dv + '/' + dd + '/' + records_file_name + response = Connect.ssh_put_file( + src_file=src_file, dst_file=dst_file, + hostname=hostname, port=hostport, + username=username, password=userpass) + if response != 'ERROR': + try: + remove(src_file) + except OSError: + pass + response = True + else: + response = False + else: + src_file = records_root_temp + sep + records_file_name + dst_file = hostpath + sep + dy + sep + dm + sep + dv + sep + dd + sep + records_file_name + try: + makedirs(hostpath + sep + dy + sep + dm + sep + dv + sep + dd, exist_ok=True) + replace(src=src_file, dst=dst_file) + response = True + except Exception as error: + logging.debug( + msg='' + + '\n' + 'src_file: ' + src_file + + '\n' + 'dst_file: ' + dst_file + + '\n' + 'error: ' + str(error) + ) + response = False + else: + response = False + if w != '-' or float(w) != 0: + sleep(float(w)) + if response: + logging.info(msg=' result:' + key + ' = OK') + else: + logging.warning(msg='result:' + key + ' = ERROR') + + +if __name__ == "__main__": + time_start = datetime.now() + + args = ArgumentParser( + prog='cctv-scheduler', + description='Hikvision PTZ IP-Camera management.', + epilog='Dependencies: ' + '- Python 3 (tested version 3.9.5), ' + '- Python 3 modules: paramiko ' + ) + args.add_argument('--config', type=str, default=path.splitext(__file__)[0] + '.conf', required=False, + help='custom configuration file path') + args.add_argument('-s', '--sequences', action='store_true', required=False, + help='run sequences from config file') + args.add_argument('-c', '--converter', action='store_true', required=False, + help='convert JPEG collection to MP4') + args.add_argument('-p', '--publisher', action='store_true', required=False, + help='publish content from templates') + args = vars(args.parse_args()) + + log_root = path.dirname(path.realpath(__file__)) + log_level = 'INFO' + if path.exists(args['config']): + conf = Parse(parameters=args['config'], block='common') + if 'log_root' in conf.data: + log_root = conf.data['log_root'] + if 'log_level' in conf.data: + if conf.data['log_level'] == 'DEBUG': + log_level = logging.DEBUG + elif conf.data['log_level'] == 'INFO': + log_level = logging.INFO + elif conf.data['log_level'] == 'WARNING': + log_level = logging.WARNING + elif conf.data['log_level'] == 'ERROR': + log_level = logging.ERROR + elif conf.data['log_level'] == 'CRITICAL': + log_level = logging.CRITICAL + logging.basicConfig( + format='%(asctime)s %(levelname)s: %(message)s', + datefmt='%Y-%m-%d_%H.%M.%S', + handlers=[ + logging.FileHandler( + filename=log_root + sep + path.splitext(path.basename(__file__))[0] + '.log', + mode='a' + ), + logging.StreamHandler() + ], + level=log_level + ) + logging.getLogger("paramiko").setLevel(logging.WARNING) + + if args['sequences']: + logging.info(msg='Starting PTZ sequences from config file') + sensors = {} + conf = Parse(parameters=args['config'], block='enable-sensor') + for key, value in conf.data.items(): + if value == 'true': + device_config = Parse( + parameters=args['config'], + block='sensor-config:' + key + ).data + device_entity = Sensor( + hostname=device_config['hostname'], + username=device_config['username'], + userpass=device_config['userpass'], + nodetype=device_config['nodetype'], + nodename=device_config['nodename'] + ) + sensors[key] = device_entity + + conf = Parse(parameters=args['config'], block='enable-sequences') + for key, value in conf.data.items(): + if value == 'true': + device_sequence = Parse( + parameters=args['config'], + block='camera-sequences:' + key + ).data + device_config = Parse( + parameters=args['config'], + block='camera-config:' + key + ).data + device_entity = HikISAPI( + hostname=device_config['hostname'], + username=device_config['username'], + userpass=device_config['userpass'] + ) + records_root_path = path.dirname(path.realpath(__file__)) + records_root_user = None + records_root_pass = None + if 'records_root_path' in device_config: + records_root_path = device_config['records_root_path'] + if 'records_root_user' in device_config: + records_root_user = device_config['records_root_user'] + if 'records_root_pass' in device_config: + records_root_pass = device_config['records_root_pass'] + Sequence.run( + device=device_entity, + sensors=sensors, + sequence=device_sequence, + records_root_path=records_root_path, + records_root_user=records_root_user, + records_root_pass=records_root_pass + ) + elif args['converter']: + logging.info(msg='Starting convert JPEG collection to MP4') + elif args['publisher']: + logging.info(msg='Starting publish content from templates') + else: + logging.info(msg='Start arguments was not selected. Exit.') + + time_execute = datetime.now() - time_start + logging.info(msg='execution time is ' + str(time_execute) + '. Exit.') diff --git a/archive/0.2/converter.conf b/archive/0.2/converter.conf new file mode 100644 index 0000000..97c039b --- /dev/null +++ b/archive/0.2/converter.conf @@ -0,0 +1,11 @@ +logs=./converter.log + +list=./converter.list +imgroot=/home/user/cctv-scheduler/records +imgnames=point-01 point-02 point-04 point-05 point-11 point-12 +xscale=1920 +yscale=1080 +mp4fps=25 + +telegramapiurl=https://api.telegram.org/bot1234567890:YOURAPIKEY +telegramchatid=123456789 \ No newline at end of file diff --git a/archive/0.2/converter.sh b/archive/0.2/converter.sh new file mode 100644 index 0000000..a231db3 --- /dev/null +++ b/archive/0.2/converter.sh @@ -0,0 +1,208 @@ +#! /bin/bash + +# DESCRIPTION: +# Converting JPEG collection to MP4. +# This is only a local "proof of conept" for testing and debugging. +# +# DEPENDENCIES: +# - ffmpeg +# +# PARAMETERS: +# 1: "qn" - execution without pauses +# 2: custom configuration file path +# 3: periods: '' - today | '-d' - yesterday | '-w' - last week | '-m' - last month | '-y' - last year +# +# FUNCTIONS: +# + +####################################### +# Print message and add to log. +# Globals: +# logs +# Arguments: +# 1: message to print and logging +####################################### +addtologs() { + echo "$(date +'%Y.%m.%d-%H:%M:%S') $1" | tee -a "${logs}" +} + +####################################### +# Waiting for press [ENTER]. +# Globals: +# None +# Arguments: +# None +####################################### +execpause() { + read -r -p "Press [ENTER] to continue... " +} + +####################################### +# Exit procedure. +# Globals: +# show +# Arguments: +# None +####################################### +execquite() { + addtologs "execution time is $(($(date +%s)-time)) seconds, exit" + if [ "${show}" != "qn" ]; then + execpause + fi + exit +} + +####################################### +# Error exit procedure with Telegram notification. +# Globals: +# telegramapiurl +# telegramchatid +# Arguments: +# 1: message to print and logging +####################################### +execerror() { + addtologs "error: $1" + curl -s -X POST "${telegramapiurl}/sendMessage" \ + -d "chat_id=${telegramchatid}" \ + -d "text=$(basename -s .sh "$0") error: $1" \ + >> /dev/null 2>&1 + execquite +} + +####################################### +# Parsing config file and creating global vars. +# Globals: +# None +# Arguments: +# None +####################################### +getconfig() { + logs=$(grep "logs=" "${conf}" | cut -d= -f2) + list=$(grep "list=" "${conf}" | cut -d= -f2) + imgroot=$(grep "imgroot=" "${conf}" | cut -d= -f2) + IFS=" " read -r -a imgnames <<< "$(grep "imgnames=" "${conf}" | cut -d= -f2)" + xscale=$(grep "xscale=" "${conf}" | cut -d= -f2) + yscale=$(grep "yscale=" "${conf}" | cut -d= -f2) + mp4fps=$(grep "mp4fps=" "${conf}" | cut -d= -f2) + telegramapiurl=$(grep "telegramapiurl=" "${conf}" | cut -d= -f2) + telegramchatid=$(grep "telegramchatid=" "${conf}" | cut -d= -f2) +} + +# +# VARIABLES: +# + +show=$1 +conf=$2 +if [ -z "${conf}" ] || [ "${conf}" == "-" ]; then + conf="$(dirname "$(realpath "$0")")/$(basename -s .sh "$0").conf" +fi +when=$3 +if [ -z "${when}" ]; then + d=$(date +"%d") + w=$(date +"%V") + m=$(date +"%m") + y=$(date +"%Y") + duration=1 + imgpath="${y}/${m}/${w}/${d}" + imgname="${y}.${m}.${d}" +fi +if [ "${when}" == "-d" ]; then + d=$(date -d "-1 day" +"%d") + m=$(date +"%m") + if [ "$(date -d '-1 day' +'%m')" != "$(date +'%m')" ]; then + m=$(date -d '-1 day' +'%m') + fi + y=$(date +"%Y") + if [ "$(date -d '-1 day' +'%Y')" != "$(date +'%Y')" ]; then + y=$(date -d '-1 day' +'%Y') + fi + w=$(date +"%V") + if [ "$(date +'%w')" == "1" ]; then + w=$(date -d "-1 week" +"%V") + fi + duration=1 + imgpath="${y}/${m}/${w}/${d}" + imgname="${y}.${m}.${d}" +fi +if [ "${when}" == "-w" ]; then + w=$(date -d "-1 week" +"%V") + m=$(date +"%m") + if [ "$(date -d '-1 week' +'%m')" != "$(date +'%m')" ]; then + m=$(date -d '-1 week' +'%m') + fi + y=$(date +"%Y") + if [ "$(date -d '-1 week' +'%Y')" != "$(date +'%Y')" ]; then + y=$(date -d '-1 week' +'%Y') + fi + duration=7 + imgpath="${y}/*/${w}" + imgname="${y}-w${w}" +fi +if [ "${when}" == "-m" ]; then + m=$(date -d "-1 month" +"%m") + y=$(date +"%Y") + if [ "$(date -d '-1 month' +'%Y')" != "$(date +'%Y')" ]; then + y=$(date -d '-1 month' +'%Y') + fi + duration=30 + imgpath="${y}/${m}" + imgname="${y}.${m}" +fi +if [ "${when}" == "-y" ]; then + y=$(date -d "-1 year" +"%Y") + duration=360 + imgpath="${y}" + imgname="${y}" +fi + +time=$(date +%s) +cd "$(dirname "$(realpath "$0")")" || execerror +if [ ! -e "${conf}" ]; then + execerror "Not found config file: ${conf}" +else + getconfig +fi +if [ -z "${logs}" ];then + logs=/dev/null +elif [ ! -e "${logs}" ];then + touch "${logs}" +fi +if [ -z "${list}" ];then + list="$(dirname "$(realpath "$0")")/$(basename -s .sh "$0").list" +fi +if [ ! -e "${list}" ];then + touch "${list}" +fi +if ! command -v ffmpeg &> /dev/null; then + execerror "Not found dependencies" +fi + +# +# MAIN: +# + +for name in "${imgnames[@]}"; do + imgmatch="*${name}*.jpeg" + imgarray=() + while read -r FILE; do + imgarray+=("${FILE}") + done < <(find "${imgroot}/${imgpath}" -name "${imgmatch}" | sort) + imgcount=${#imgarray[*]} + + echo '' > "${list}" + for item in "${imgarray[@]}"; do + echo file \'"${item}"\' >> "${list}" + done + + imgdest="${imgroot}/${name}_${imgname}.mp4" + echo "${imgdest}" + if ffmpeg -r "${imgcount}/${duration}" -f concat -safe 0 -i "${list}" \ + -c:v libx264 -vf "scale=${xscale}:${yscale},fps=${mp4fps},format=yuv420p" \ + "${imgdest}" -y; then + addtologs "converted ${imgcount} images to ${imgdest} with duration ${duration}" + else + execerror "converted ${imgcount} images to ${imgdest} with duration ${duration}" + fi +done +execquite diff --git a/archive/0.2/publisher-template-page-1007.xml b/archive/0.2/publisher-template-page-1007.xml new file mode 100644 index 0000000..4b8ab60 --- /dev/null +++ b/archive/0.2/publisher-template-page-1007.xml @@ -0,0 +1,525 @@ + +wp.editPage + + 1 + wpeditpageid + wpxmlrpcuser + wpxmlrpcpass + + dateCreatedwpeditdateis + useridwpedituserid + page_idwpeditpageid + page_statuspublish + description + + + + <!-- wp:heading {"level":3} --><h3>Now</h3><!-- /wp:heading --> + <!-- wp:embed {"url":"youtubelink","type":"video","providerNameSlug":"youtube", + "responsive":true,"className":"wp-embed-aspect-4-3 wp-has-aspect-ratio"} --> + <figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"> + <div class="wp-block-embed__wrapper"> + youtubelink + </div></figure><!-- /wp:embed --> + + + <!-- wp:heading {"level":3} --><h3>Yesterday</h3><!-- /wp:heading --> + <!-- wp:uagb/tabs {"block_id":"yesterday", + "tabHeaders":["currentdp01[0]", + "currentdp02[0]", + "currentdp04[0]", + "currentdp05[0]", + "currentdp11[0]", + "currentdp12[0]"],"tabActive":5,"activeTabBgColor":"#4b4b4b", + "tabTitleLeftMargin":1,"tabTitleRightMargin":1,"tabTitleTopMargin":1,"tabTitleBottomMargin":1} --> + <div class="wp-block-uagb-tabs uagb-block-yesterday uagb-tabs__wrap uagb-tabs__hstyle1-desktop uagb-tabs__vstyle6-tablet uagb-tabs__vstyle6-mobile" data-tab-active="0"> + <ul class="uagb-tabs__panel uagb-tabs__align-left"><li class="uagb-tab uagb-tabs__active"> + <a href="#uagb-tabs__tab0" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="0"> + <span>currentdp01[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab1" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="1"> + <span>currentdp02[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab2" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="2"> + <span>currentdp04[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab3" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="3"> + <span>currentdp05[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab4" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="4"> + <span>currentdp11[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab5" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="5"> + <span>currentdp12[0]</span></a></li></ul> + + <div class="uagb-tabs__body-wrap"> + <!-- wp:uagb/tabs-child {"block_id":"daypoint01", + "header":"currentdp01[0]","tabActive":5, + "tabHeaders":["currentdp01[0]", + "currentdp02[0]", + "currentdp04[0]", + "currentdp05[0]", + "currentdp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-0"> + <div class="uagb-blocks__daypoint01 uagb-tabs__body" aria-labelledby="uagb-tabs__tab0"> + <!-- wp:video {"id":1036} --><figure class="wp-block-video"> + <video controls loop src="currentdp01[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"daypoint02","id":1, + "header":"currentdp02[0]","tabActive":5, + "tabHeaders":["currentdp01[0]", + "currentdp02[0]", + "currentdp04[0]", + "currentdp05[0]", + "currentdp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-1"> + <div class="uagb-blocks__daypoint02 uagb-tabs__body" aria-labelledby="uagb-tabs__tab1"> + <!-- wp:video {"id":1041} --><figure class="wp-block-video"> + <video controls loop src="currentdp02[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"daypoint04","id":2, + "header":"currentdp04[0]","tabActive":5, + "tabHeaders":["currentdp01[0]", + "currentdp02[0]", + "currentdp04[0]", + "currentdp05[0]", + "currentdp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-2"> + <div class="uagb-blocks__daypoint04 uagb-tabs__body" aria-labelledby="uagb-tabs__tab2"> + <!-- wp:video {"id":1046} --><figure class="wp-block-video"> + <video controls loop src="currentdp04[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"daypoint05","id":3, + "header":"currentdp05[0]","tabActive":5, + "tabHeaders":["currentdp01[0]", + "currentdp02[0]", + "currentdp04[0]", + "currentdp05[0]", + "currentdp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-3"> + <div class="uagb-blocks__daypoint05 uagb-tabs__body" aria-labelledby="uagb-tabs__tab3"> + <!-- wp:video {"id":1051} --><figure class="wp-block-video"> + <video controls loop src="currentdp05[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"daypoint11","id":4, + "header":"currentdp11[0]","tabActive":5, + "tabHeaders":["currentdp01[0]", + "currentdp02[0]", + "currentdp04[0]", + "currentdp05[0]", + "currentdp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-4"> + <div class="uagb-blocks__daypoint11 uagb-tabs__body" aria-labelledby="uagb-tabs__tab4"> + <!-- wp:video {"id":1056} --><figure class="wp-block-video"> + <video controls loop src="currentdp11[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"daypoint12","id":5, + "header":"currentdp12[0]","tabActive":5, + "tabHeaders":["currentdp01[0]", + "currentdp02[0]", + "currentdp04[0]", + "currentdp05[0]", + "currentdp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-5"> + <div class="uagb-blocks__daypoint12 uagb-tabs__body" aria-labelledby="uagb-tabs__tab5"> + <!-- wp:video {"id":1061} --><figure class="wp-block-video"> + <video controls loop src="currentdp12[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --></div></div> + <!-- /wp:uagb/tabs --> + + + <!-- wp:heading {"level":3} --><h3>Last week</h3><!-- /wp:heading --> + <!-- wp:uagb/tabs {"block_id":"lastweek", + "tabHeaders":["currentwp01[0]", + "currentwp02[0]", + "currentwp04[0]", + "currentwp05[0]", + "currentwp11[0]", + "currentwp12[0]"],"tabActive":5,"activeTabBgColor":"#4b4b4b", + "tabTitleLeftMargin":1,"tabTitleRightMargin":1,"tabTitleTopMargin":1,"tabTitleBottomMargin":1} --> + <div class="wp-block-uagb-tabs uagb-block-lastweek uagb-tabs__wrap uagb-tabs__hstyle1-desktop uagb-tabs__vstyle6-tablet uagb-tabs__vstyle6-mobile" data-tab-active="0"> + <ul class="uagb-tabs__panel uagb-tabs__align-left"><li class="uagb-tab uagb-tabs__active"> + <a href="#uagb-tabs__tab0" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="0"> + <span>currentwp01[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab1" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="1"> + <span>currentwp02[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab2" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="2"> + <span>currentwp04[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab3" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="3"> + <span>currentwp05[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab4" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="4"> + <span>currentwp11[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab5" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="5"> + <span>currentwp12[0]</span></a></li></ul> + + <div class="uagb-tabs__body-wrap"> + <!-- wp:uagb/tabs-child {"block_id":"weekpoint01", + "header":"currentwp01[0]","tabActive":5, + "tabHeaders":["currentwp01[0]", + "currentwp02[0]", + "currentwp04[0]", + "currentwp05[0]", + "currentwp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-0"> + <div class="uagb-blocks__weekpoint01 uagb-tabs__body" aria-labelledby="uagb-tabs__tab0"> + <!-- wp:video {"id":1036} --><figure class="wp-block-video"> + <video controls loop src="currentwp01[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"weekpoint02","id":1, + "header":"currentwp02[0]","tabActive":5, + "tabHeaders":["currentwp01[0]", + "currentwp02[0]", + "currentwp04[0]", + "currentwp05[0]", + "currentwp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-1"> + <div class="uagb-blocks__weekpoint02 uagb-tabs__body" aria-labelledby="uagb-tabs__tab1"> + <!-- wp:video {"id":1041} --><figure class="wp-block-video"> + <video controls loop src="currentwp02[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"weekpoint04","id":2, + "header":"currentwp04[0]","tabActive":5, + "tabHeaders":["currentwp01[0]", + "currentwp02[0]", + "currentwp04[0]", + "currentwp05[0]", + "currentwp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-2"> + <div class="uagb-blocks__weekpoint04 uagb-tabs__body" aria-labelledby="uagb-tabs__tab2"> + <!-- wp:video {"id":1046} --><figure class="wp-block-video"> + <video controls loop src="currentwp04[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"weekpoint05","id":3, + "header":"currentwp05[0]","tabActive":5, + "tabHeaders":["currentwp01[0]", + "currentwp02[0]", + "currentwp04[0]", + "currentwp05[0]", + "currentwp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-3"> + <div class="uagb-blocks__weekpoint05 uagb-tabs__body" aria-labelledby="uagb-tabs__tab3"> + <!-- wp:video {"id":1051} --><figure class="wp-block-video"> + <video controls loop src="currentwp05[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"weekpoint11","id":4, + "header":"currentwp11[0]","tabActive":5, + "tabHeaders":["currentwp01[0]", + "currentwp02[0]", + "currentwp04[0]", + "currentwp05[0]", + "currentwp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-4"> + <div class="uagb-blocks__weekpoint11 uagb-tabs__body" aria-labelledby="uagb-tabs__tab4"> + <!-- wp:video {"id":1056} --><figure class="wp-block-video"> + <video controls loop src="currentwp11[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"weekpoint12","id":5, + "header":"currentwp12[0]","tabActive":5, + "tabHeaders":["currentwp01[0]", + "currentwp02[0]", + "currentwp04[0]", + "currentwp05[0]", + "currentwp11[0]","wp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-5"> + <div class="uagb-blocks__weekpoint12 uagb-tabs__body" aria-labelledby="uagb-tabs__tab5"> + <!-- wp:video {"id":1061} --><figure class="wp-block-video"> + <video controls loop src="currentwp12[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --></div></div> + <!-- /wp:uagb/tabs --> + + + <!-- wp:heading {"level":3} --><h3>Last month</h3><!-- /wp:heading --> + <!-- wp:uagb/tabs {"block_id":"lastmonth", + "tabHeaders":["currentmp01[0]", + "currentmp02[0]", + "currentmp04[0]", + "currentmp05[0]", + "currentmp11[0]", + "currentmp12[0]"],"tabActive":5,"activeTabBgColor":"#4b4b4b", + "tabTitleLeftMargin":1,"tabTitleRightMargin":1,"tabTitleTopMargin":1,"tabTitleBottomMargin":1} --> + <div class="wp-block-uagb-tabs uagb-block-lastmonth uagb-tabs__wrap uagb-tabs__hstyle1-desktop uagb-tabs__vstyle6-tablet uagb-tabs__vstyle6-mobile" data-tab-active="0"> + <ul class="uagb-tabs__panel uagb-tabs__align-left"><li class="uagb-tab uagb-tabs__active"> + <a href="#uagb-tabs__tab0" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="0"> + <span>currentmp01[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab1" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="1"> + <span>currentmp02[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab2" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="2"> + <span>currentmp04[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab3" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="3"> + <span>currentmp05[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab4" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="4"> + <span>currentmp11[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab5" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="5"> + <span>currentmp12[0]</span></a></li></ul> + + <div class="uagb-tabs__body-wrap"> + <!-- wp:uagb/tabs-child {"block_id":"monthpoint01", + "header":"currentmp01[0]","tabActive":5, + "tabHeaders":["currentmp01[0]", + "currentmp02[0]", + "currentmp04[0]", + "currentmp05[0]", + "currentmp11[0]","mp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-0"> + <div class="uagb-blocks__monthpoint01 uagb-tabs__body" aria-labelledby="uagb-tabs__tab0"> + <!-- wp:video {"id":1037} --><figure class="wp-block-video"> + <video controls loop src="currentmp01[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"monthpoint02","id":1, + "header":"currentmp02[0]","tabActive":5, + "tabHeaders":["currentmp01[0]", + "currentmp02[0]", + "currentmp04[0]", + "currentmp05[0]", + "currentmp11[0]","mp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-1"> + <div class="uagb-blocks__monthpoint02 uagb-tabs__body" aria-labelledby="uagb-tabs__tab1"> + <!-- wp:video {"id":1042} --><figure class="wp-block-video"> + <video controls loop src="currentmp02[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"monthpoint04","id":2, + "header":"currentmp04[0]","tabActive":5, + "tabHeaders":["currentmp01[0]", + "currentmp02[0]", + "currentmp04[0]", + "currentmp05[0]", + "currentmp11[0]","mp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-2"> + <div class="uagb-blocks__monthpoint04 uagb-tabs__body" aria-labelledby="uagb-tabs__tab2"> + <!-- wp:video {"id":1047} --><figure class="wp-block-video"> + <video controls loop src="currentmp04[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"monthpoint05","id":3, + "header":"currentmp05[0]","tabActive":5, + "tabHeaders":["currentmp01[0]", + "currentmp02[0]", + "currentmp04[0]", + "currentmp05[0]", + "currentmp11[0]","mp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-3"> + <div class="uagb-blocks__monthpoint05 uagb-tabs__body" aria-labelledby="uagb-tabs__tab3"> + <!-- wp:video {"id":1052} --><figure class="wp-block-video"> + <video controls loop src="currentmp05[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"monthpoint11","id":4, + "header":"currentmp11[0]","tabActive":5, + "tabHeaders":["currentmp01[0]", + "currentmp02[0]", + "currentmp04[0]", + "currentmp05[0]", + "currentmp11[0]","mp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-4"> + <div class="uagb-blocks__monthpoint11 uagb-tabs__body" aria-labelledby="uagb-tabs__tab4"> + <!-- wp:video {"id":1057} --><figure class="wp-block-video"> + <video controls loop src="currentmp11[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"monthpoint12","id":5, + "header":"currentmp12[0]","tabActive":5, + "tabHeaders":["currentmp01[0]", + "currentmp02[0]", + "currentmp04[0]", + "currentmp05[0]", + "currentmp11[0]","mp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-5"> + <div class="uagb-blocks__monthpoint12 uagb-tabs__body" aria-labelledby="uagb-tabs__tab5"> + <!-- wp:video {"id":1062} --><figure class="wp-block-video"> + <video controls loop src="currentmp12[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --></div></div> + <!-- /wp:uagb/tabs --> + + + <!-- wp:heading {"level":3} --><h3>Last year</h3><!-- /wp:heading --> + <!-- wp:uagb/tabs {"block_id":"lastyear", + "tabHeaders":["currentyp01[0]", + "currentyp02[0]", + "currentyp04[0]", + "currentyp05[0]", + "currentyp11[0]", + "currentyp12[0]"],"tabActive":5,"activeTabBgColor":"#4b4b4b", + "tabTitleLeftMargin":1,"tabTitleRightMargin":1,"tabTitleTopMargin":1,"tabTitleBottomMargin":1} --> + <div class="wp-block-uagb-tabs uagb-block-lastyear uagb-tabs__wrap uagb-tabs__hstyle1-desktop uagb-tabs__vstyle6-tablet uagb-tabs__vstyle6-mobile" data-tab-active="0"> + <ul class="uagb-tabs__panel uagb-tabs__align-left"><li class="uagb-tab uagb-tabs__active"> + <a href="#uagb-tabs__tab0" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="0"> + <span>currentyp01[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab1" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="1"> + <span>currentyp02[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab2" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="2"> + <span>currentyp04[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab3" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="3"> + <span>currentyp05[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab4" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="4"> + <span>currentyp11[0]</span></a></li><li class="uagb-tab "> + <a href="#uagb-tabs__tab5" class="uagb-tabs-list uagb-tabs__icon-position-left" data-tab="5"> + <span>currentyp12[0]</span></a></li></ul> + + <div class="uagb-tabs__body-wrap"> + <!-- wp:uagb/tabs-child {"block_id":"yearpoint01", + "header":"currentyp01[0]","tabActive":5, + "tabHeaders":["currentyp01[0]", + "currentyp02[0]", + "currentyp04[0]", + "currentyp05[0]", + "currentyp11[0]","yp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-0"> + <div class="uagb-blocks__yearpoint01 uagb-tabs__body" aria-labelledby="uagb-tabs__tab0"> + <!-- wp:video {"id":1038} --><figure class="wp-block-video"> + <video controls loop src="currentyp01[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"yearpoint02","id":1, + "header":"currentyp02[0]","tabActive":5, + "tabHeaders":["currentyp01[0]", + "currentyp02[0]", + "currentyp04[0]", + "currentyp05[0]", + "currentyp11[0]","yp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-1"> + <div class="uagb-blocks__yearpoint02 uagb-tabs__body" aria-labelledby="uagb-tabs__tab1"> + <!-- wp:video {"id":1043} --><figure class="wp-block-video"> + <video controls loop src="currentyp02[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"yearpoint04","id":2, + "header":"currentyp04[0]","tabActive":5, + "tabHeaders":["currentyp01[0]", + "currentyp02[0]", + "currentyp04[0]", + "currentyp05[0]", + "currentyp11[0]","yp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-2"> + <div class="uagb-blocks__yearpoint04 uagb-tabs__body" aria-labelledby="uagb-tabs__tab2"> + <!-- wp:video {"id":1048} --><figure class="wp-block-video"> + <video controls loop src="currentyp04[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"yearpoint05","id":3, + "header":"currentyp05[0]","tabActive":5, + "tabHeaders":["currentyp01[0]", + "currentyp02[0]", + "currentyp04[0]", + "currentyp05[0]", + "currentyp11[0]","yp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-3"> + <div class="uagb-blocks__yearpoint05 uagb-tabs__body" aria-labelledby="uagb-tabs__tab3"> + <!-- wp:video {"id":1053} --><figure class="wp-block-video"> + <video controls loop src="currentyp05[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"yearpoint11","id":4, + "header":"currentyp11[0]","tabActive":5, + "tabHeaders":["currentyp01[0]", + "currentyp02[0]", + "currentyp04[0]", + "currentyp05[0]", + "currentyp11[0]","yp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-4"> + <div class="uagb-blocks__yearpoint11 uagb-tabs__body" aria-labelledby="uagb-tabs__tab4"> + <!-- wp:video {"id":1058} --><figure class="wp-block-video"> + <video controls loop src="currentyp11[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --> + + <!-- wp:uagb/tabs-child {"block_id":"yearpoint12","id":5, + "header":"currentyp12[0]","tabActive":5, + "tabHeaders":["currentyp01[0]", + "currentyp02[0]", + "currentyp04[0]", + "currentyp05[0]", + "currentyp11[0]","yp1tab"]} --> + <div class="wp-block-uagb-tabs-child uagb-tabs__body-container uagb-tabs__inner-tab uagb-inner-tab-5"> + <div class="uagb-blocks__yearpoint12 uagb-tabs__body" aria-labelledby="uagb-tabs__tab5"> + <!-- wp:video {"id":1063} --><figure class="wp-block-video"> + <video controls loop src="currentyp12[1]"> + </video></figure><!-- /wp:video --></div></div><!-- /wp:uagb/tabs-child --></div></div> + <!-- /wp:uagb/tabs --> + + + + + titleMedia + linkwppagelinkis + permaLinkwppagelinkis + categories + excerpt + text_more + mt_allow_comments0 + mt_allow_pings0 + wp_slugmedia + wp_password + wp_authorwppageauthor + wp_page_parent_id0 + wp_page_parent_title + wp_page_order0 + wp_author_idwpedituserid + wp_author_display_namewppageauthor + date_created_gmtwpeditdateis + custom_fields + + id4258 + keycontent_display_featured_image + value0 + + + id4257 + keycontent_display_title + value0 + + + id4259 + keycontent_width + valuecontainer + + + id4253 + keydisable_space_above_footer + value0 + + + id4252 + keydisable_space_below_header + value0 + + + id4251 + keyhide_footer + value0 + + + id4250 + keyhide_header + value0 + + + id4254 + keyhide_titlebar + value0 + + + id4255 + keypage_overwrite_defaults + value0 + + + id4260 + keysidebar_layout + valuedefault-sidebar + + + id4256 + keytitlebar_padding + value80 + + + wp_page_templatedefault + + + \ No newline at end of file diff --git a/archive/0.2/publisher.conf b/archive/0.2/publisher.conf new file mode 100644 index 0000000..e9b7d94 --- /dev/null +++ b/archive/0.2/publisher.conf @@ -0,0 +1,86 @@ +logs=./publisher.log + +pathroot=/home/user/cctv-scheduler/records +vidnamesarray=point-01 point-02 point-04 point-05 point-11 point-12 + + +telegramapiurl=https://api.telegram.org/bot1234567890:YOURAPIKEY +telegramchatid=123456789 +tgpreviewlink=https://www.hmp.today/wp-content/uploads/2021/02/site-slider_hmp-qr_bwg-3840x1705-1.png +tgpreviewtext=https://www.hmp.today/media + + +wpxmlrpclink=https://www.hmp.today/xmlrpc.php +wpxmlrpcuser=user +wpxmlrpcpass=pass +wppageauthor=author +wppagelinkis=https://www.hmp.today/media +wpeditpageid=1007 +wpedituserid=0 +wpeditdateis=20220707T00:00:00 +wptemplateis=./publisher-template-page-1007.xml + + +youtubelink=https://youtu.be/link + + +defaultdp01=point-01 https://www.hmp.today/wp-content/uploads/2022/07/point-01_yyyy.mm_.dd_.mp4 +defaultwp01=point-01 https://www.hmp.today/wp-content/uploads/2022/07/point-01_w.mp4 +defaultmp01=point-01 https://www.hmp.today/wp-content/uploads/2022/07/point-01_yyyy.mm_.mp4 +defaultyp01=point-01 https://www.hmp.today/wp-content/uploads/2022/07/point-01_yyyy.mp4 + +defaultdp02=point-02 https://www.hmp.today/wp-content/uploads/2022/07/point-02_yyyy.mm_.dd_.mp4 +defaultwp02=point-02 https://www.hmp.today/wp-content/uploads/2022/07/point-02_w.mp4 +defaultmp02=point-02 https://www.hmp.today/wp-content/uploads/2022/07/point-02_yyyy.mm_.mp4 +defaultyp02=point-02 https://www.hmp.today/wp-content/uploads/2022/07/point-02_yyyy.mp4 + +defaultdp04=point-04 https://www.hmp.today/wp-content/uploads/2022/07/point-04_yyyy.mm_.dd_.mp4 +defaultwp04=point-04 https://www.hmp.today/wp-content/uploads/2022/07/point-04_w.mp4 +defaultmp04=point-04 https://www.hmp.today/wp-content/uploads/2022/07/point-04_yyyy.mm_.mp4 +defaultyp04=point-04 https://www.hmp.today/wp-content/uploads/2022/07/point-04_yyyy.mp4 + +defaultdp05=point-05 https://www.hmp.today/wp-content/uploads/2022/07/point-05_yyyy.mm_.dd_.mp4 +defaultwp05=point-05 https://www.hmp.today/wp-content/uploads/2022/07/point-05_w.mp4 +defaultmp05=point-05 https://www.hmp.today/wp-content/uploads/2022/07/point-05_yyyy.mm_.mp4 +defaultyp05=point-05 https://www.hmp.today/wp-content/uploads/2022/07/point-05_yyyy.mp4 + +defaultdp11=point-11 https://www.hmp.today/wp-content/uploads/2022/07/point-11_yyyy.mm_.dd_.mp4 +defaultwp11=point-11 https://www.hmp.today/wp-content/uploads/2022/07/point-11_w.mp4 +defaultmp11=point-11 https://www.hmp.today/wp-content/uploads/2022/07/point-11_yyyy.mm_.mp4 +defaultyp11=point-11 https://www.hmp.today/wp-content/uploads/2022/07/point-11_yyyy.mp4 + +defaultdp12=point-12 https://www.hmp.today/wp-content/uploads/2022/07/point-12_yyyy.mm_.dd_.mp4 +defaultwp12=point-12 https://www.hmp.today/wp-content/uploads/2022/07/point-12_w.mp4 +defaultmp12=point-12 https://www.hmp.today/wp-content/uploads/2022/07/point-12_yyyy.mm_.mp4 +defaultyp12=point-12 https://www.hmp.today/wp-content/uploads/2022/07/point-12_yyyy.mp4 + + +currentdp01=point-01 +currentwp01=point-01 +currentmp01=point-01 +currentyp01=point-01 + +currentdp02=point-02 +currentwp02=point-02 +currentmp02=point-02 +currentyp02=point-02 + +currentdp04=point-04 +currentwp04=point-04 +currentmp04=point-04 +currentyp04=point-04 + +currentdp05=point-05 +currentwp05=point-05 +currentmp05=point-05 +currentyp05=point-05 + +currentdp11=point-11 +currentwp11=point-11 +currentmp11=point-11 +currentyp11=point-11 + +currentdp12=point-12 +currentwp12=point-12 +currentmp12=point-12 +currentyp12=point-12 diff --git a/archive/0.2/publisher.sh b/archive/0.2/publisher.sh new file mode 100644 index 0000000..205da6d --- /dev/null +++ b/archive/0.2/publisher.sh @@ -0,0 +1,599 @@ +#! /bin/bash + +# DESCRIPTION: +# Uploading MP4 to Wordpress and Telegram. +# Additionally: +# - editing Wordpress page from template +# - recompressing video if size over 50MB +# This is only a local "proof of conept" for testing and debugging. +# +# DEPENDENCIES: +# - curl +# - ffmpeg +# - libxml2-utils +# - jq +# +# PARAMETERS: +# 1: "qn" - execution without pauses +# 2: custom configuration file path +# 3: periods: '' - today | '-d' - yesterday | '-w' - last week | '-m' - last month | '-y' - last year +# 4: period multiplier: '' - 1 day|week|month|year +# 5: publishing '--onlytg' - only to Telegram | '--onlywp' - only to Wordpress +# +# FUNCTIONS: +# + +####################################### +# Print message and add to log. +# Globals: +# logs +# Arguments: +# 1: message to print and logging +####################################### +addtologs() { + echo "$(date +'%Y.%m.%d-%H:%M:%S') $1" | tee -a "${logs}" +} + +####################################### +# Waiting for press [ENTER]. +# Globals: +# None +# Arguments: +# None +####################################### +execpause() { + read -r -p "Press [ENTER] to continue... " +} + +####################################### +# Exit procedure. +# Globals: +# show +# Arguments: +# None +####################################### +execquite() { + addtologs "execution time is $(($(date +%s)-time)) seconds, exit" + if [ "${show}" != "qn" ]; then + execpause + fi + exit +} + +####################################### +# Error exit procedure with Telegram notification. +# Globals: +# telegramapiurl +# telegramchatid +# Arguments: +# 1: message to print and logging +####################################### +execerror() { + addtologs "error: $1" + curl -s -X POST "${telegramapiurl}/sendMessage" \ + -d "chat_id=${telegramchatid}" \ + -d "text=$(basename -s .sh "$0") error: $1" \ + >> /dev/null 2>&1 + execquite +} + +####################################### +# Parsing config file and creating global vars. +# Globals: +# None +# Arguments: +# None +####################################### +getconfig() { + logs=$(grep "logs=" "${conf}" | cut -d= -f2) + pathroot=$(grep "pathroot=" "${conf}" | cut -d= -f2) + IFS=" " read -r -a vidnamesarray <<< "$(grep "vidnamesarray=" "${conf}" | cut -d= -f2)" + telegramapiurl=$(grep "telegramapiurl=" "${conf}" | cut -d= -f2) + telegramchatid=$(grep "telegramchatid=" "${conf}" | cut -d= -f2) + tgpreviewlink=$(grep "tgpreviewlink=" "${conf}" | cut -d= -f2) + tgpreviewtext=$(grep "tgpreviewtext=" "${conf}" | cut -d= -f2) + wpxmlrpclink=$(grep "wpxmlrpclink=" "${conf}" | cut -d= -f2) + wpxmlrpcuser=$(grep "wpxmlrpcuser=" "${conf}" | cut -d= -f2) + wpxmlrpcpass=$(grep "wpxmlrpcpass=" "${conf}" | cut -d= -f2) + wppageauthor=$(grep "wppageauthor=" "${conf}" | cut -d= -f2) + wppagelinkis=$(grep "wppagelinkis=" "${conf}" | cut -d= -f2) + wpeditpageid=$(grep "wpeditpageid=" "${conf}" | cut -d= -f2) + wpedituserid=$(grep "wpedituserid=" "${conf}" | cut -d= -f2) + wpeditdateis=$(grep "wpeditdateis=" "${conf}" | cut -d= -f2) + wptemplateis=$(grep "wptemplateis=" "${conf}" | cut -d= -f2) + youtubelink=$(grep "youtubelink=" "${conf}" | cut -d= -f2) + + IFS=" " read -r -a defaultdp01 <<< "$(grep "defaultdp01=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultwp01 <<< "$(grep "defaultwp01=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultmp01 <<< "$(grep "defaultmp01=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultyp01 <<< "$(grep "defaultyp01=" "${conf}" | cut -d= -f2)" + + IFS=" " read -r -a defaultdp02 <<< "$(grep "defaultdp02=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultwp02 <<< "$(grep "defaultwp02=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultmp02 <<< "$(grep "defaultmp02=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultyp02 <<< "$(grep "defaultyp02=" "${conf}" | cut -d= -f2)" + + IFS=" " read -r -a defaultdp04 <<< "$(grep "defaultdp04=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultwp04 <<< "$(grep "defaultwp04=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultmp04 <<< "$(grep "defaultmp04=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultyp04 <<< "$(grep "defaultyp04=" "${conf}" | cut -d= -f2)" + + IFS=" " read -r -a defaultdp05 <<< "$(grep "defaultdp05=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultwp05 <<< "$(grep "defaultwp05=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultmp05 <<< "$(grep "defaultmp05=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultyp05 <<< "$(grep "defaultyp05=" "${conf}" | cut -d= -f2)" + + IFS=" " read -r -a defaultdp11 <<< "$(grep "defaultdp11=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultwp11 <<< "$(grep "defaultwp11=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultmp11 <<< "$(grep "defaultmp11=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultyp11 <<< "$(grep "defaultyp11=" "${conf}" | cut -d= -f2)" + + IFS=" " read -r -a defaultdp12 <<< "$(grep "defaultdp12=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultwp12 <<< "$(grep "defaultwp12=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultmp12 <<< "$(grep "defaultmp12=" "${conf}" | cut -d= -f2)" + IFS=" " read -r -a defaultyp12 <<< "$(grep "defaultyp12=" "${conf}" | cut -d= -f2)" + + IFS=" " read -r -a currentdp01 <<< "$(grep "currentdp01=" "${conf}" | cut -d= -f2)" + if [ -z "${currentdp01[1]}" ]; then + currentdp01=${defaultdp01[*]} + fi + IFS=" " read -r -a currentwp01 <<< "$(grep "currentwp01=" "${conf}" | cut -d= -f2)" + if [ -z "${currentwp01[1]}" ]; then + currentwp01=${defaultwp01[*]} + fi + IFS=" " read -r -a currentmp01 <<< "$(grep "currentmp01=" "${conf}" | cut -d= -f2)" + if [ -z "${currentmp01[1]}" ]; then + currentmp01=${defaultmp01[*]} + fi + IFS=" " read -r -a currentyp01 <<< "$(grep "currentyp01=" "${conf}" | cut -d= -f2)" + if [ -z "${currentyp01[1]}" ]; then + currentyp01=${defaultyp01[*]} + fi + + IFS=" " read -r -a currentdp02 <<< "$(grep "currentdp02=" "${conf}" | cut -d= -f2)" + if [ -z "${currentdp02[1]}" ]; then + currentdp02=${defaultdp02[*]} + fi + IFS=" " read -r -a currentwp02 <<< "$(grep "currentwp02=" "${conf}" | cut -d= -f2)" + if [ -z "${currentwp02[1]}" ]; then + currentwp02=${defaultwp02[*]} + fi + IFS=" " read -r -a currentmp02 <<< "$(grep "currentmp02=" "${conf}" | cut -d= -f2)" + if [ -z "${currentmp02[1]}" ]; then + currentmp02=${defaultmp02[*]} + fi + IFS=" " read -r -a currentyp02 <<< "$(grep "currentyp02=" "${conf}" | cut -d= -f2)" + if [ -z "${currentyp02[1]}" ]; then + currentyp02=${defaultyp02[*]} + fi + + IFS=" " read -r -a currentdp04 <<< "$(grep "currentdp04=" "${conf}" | cut -d= -f2)" + if [ -z "${currentdp04[1]}" ]; then + currentdp04=${defaultdp04[*]} + fi + IFS=" " read -r -a currentwp04 <<< "$(grep "currentwp04=" "${conf}" | cut -d= -f2)" + if [ -z "${currentwp04[1]}" ]; then + currentwp04=${defaultwp04[*]} + fi + IFS=" " read -r -a currentmp04 <<< "$(grep "currentmp04=" "${conf}" | cut -d= -f2)" + if [ -z "${currentmp04[1]}" ]; then + currentmp04=${defaultmp04[*]} + fi + IFS=" " read -r -a currentyp04 <<< "$(grep "currentyp04=" "${conf}" | cut -d= -f2)" + if [ -z "${currentyp04[1]}" ]; then + currentyp04=${defaultyp04[*]} + fi + + IFS=" " read -r -a currentdp05 <<< "$(grep "currentdp05=" "${conf}" | cut -d= -f2)" + if [ -z "${currentdp05[1]}" ]; then + currentdp05=${defaultdp05[*]} + fi + IFS=" " read -r -a currentwp05 <<< "$(grep "currentwp05=" "${conf}" | cut -d= -f2)" + if [ -z "${currentwp05[1]}" ]; then + currentwp05=${defaultwp05[*]} + fi + IFS=" " read -r -a currentmp05 <<< "$(grep "currentmp05=" "${conf}" | cut -d= -f2)" + if [ -z "${currentmp05[1]}" ]; then + currentmp05=${defaultmp05[*]} + fi + IFS=" " read -r -a currentyp05 <<< "$(grep "currentyp05=" "${conf}" | cut -d= -f2)" + if [ -z "${currentyp05[1]}" ]; then + currentyp05=${defaultyp05[*]} + fi + + IFS=" " read -r -a currentdp11 <<< "$(grep "currentdp11=" "${conf}" | cut -d= -f2)" + if [ -z "${currentdp11[1]}" ]; then + currentdp11=${defaultdp11[*]} + fi + IFS=" " read -r -a currentwp11 <<< "$(grep "currentwp11=" "${conf}" | cut -d= -f2)" + if [ -z "${currentwp11[1]}" ]; then + currentwp11=${defaultwp11[*]} + fi + IFS=" " read -r -a currentmp11 <<< "$(grep "currentmp11=" "${conf}" | cut -d= -f2)" + if [ -z "${currentmp11[1]}" ]; then + currentmp11=${defaultmp11[*]} + fi + IFS=" " read -r -a currentyp11 <<< "$(grep "currentyp11=" "${conf}" | cut -d= -f2)" + if [ -z "${currentyp11[1]}" ]; then + currentyp11=${defaultyp11[*]} + fi + + IFS=" " read -r -a currentdp12 <<< "$(grep "currentdp12=" "${conf}" | cut -d= -f2)" + if [ -z "${currentdp12[1]}" ]; then + currentdp12=${defaultdp12[*]} + fi + IFS=" " read -r -a currentwp12 <<< "$(grep "currentwp12=" "${conf}" | cut -d= -f2)" + if [ -z "${currentwp12[1]}" ]; then + currentwp12=${defaultwp12[*]} + fi + IFS=" " read -r -a currentmp12 <<< "$(grep "currentmp12=" "${conf}" | cut -d= -f2)" + if [ -z "${currentmp12[1]}" ]; then + currentmp12=${defaultmp12[*]} + fi + IFS=" " read -r -a currentyp12 <<< "$(grep "currentyp12=" "${conf}" | cut -d= -f2)" + if [ -z "${currentyp12[1]}" ]; then + currentyp12=${defaultyp12[*]} + fi +} + +####################################### +# Writing changes to configuration file. +# Globals: +# conf +# when +# vidnamesarray +# vidlinksarray +# Arguments: +# None +####################################### +setconfig() { + if [ -z "${when}" ] || [ "${when}" == "-d" ]; then + if [ -n "${vidnamesarray[0]}" ] && [ -n "${vidlinksarray[0]}" ]; then + sed -i "s#$(grep 'currentdp01=' "${conf}")#currentdp01=${vidnamesarray[0]} ${vidlinksarray[0]}#" "${conf}" + fi + if [ -n "${vidnamesarray[1]}" ] && [ -n "${vidlinksarray[1]}" ]; then + sed -i "s#$(grep 'currentdp02=' "${conf}")#currentdp02=${vidnamesarray[1]} ${vidlinksarray[1]}#" "${conf}" + fi + if [ -n "${vidnamesarray[2]}" ] && [ -n "${vidlinksarray[2]}" ]; then + sed -i "s#$(grep 'currentdp04=' "${conf}")#currentdp04=${vidnamesarray[2]} ${vidlinksarray[2]}#" "${conf}" + fi + if [ -n "${vidnamesarray[3]}" ] && [ -n "${vidlinksarray[3]}" ]; then + sed -i "s#$(grep 'currentdp05=' "${conf}")#currentdp05=${vidnamesarray[3]} ${vidlinksarray[3]}#" "${conf}" + fi + if [ -n "${vidnamesarray[4]}" ] && [ -n "${vidlinksarray[4]}" ]; then + sed -i "s#$(grep 'currentdp11=' "${conf}")#currentdp11=${vidnamesarray[4]} ${vidlinksarray[4]}#" "${conf}" + fi + if [ -n "${vidnamesarray[5]}" ] && [ -n "${vidlinksarray[5]}" ]; then + sed -i "s#$(grep 'currentdp12=' "${conf}")#currentdp12=${vidnamesarray[5]} ${vidlinksarray[5]}#" "${conf}" + fi + fi + if [ "${when}" == "-w" ]; then + if [ -n "${vidnamesarray[0]}" ] && [ -n "${vidlinksarray[0]}" ]; then + sed -i "s#$(grep 'currentwp01=' "${conf}")#currentwp01=${vidnamesarray[0]} ${vidlinksarray[0]}#" "${conf}" + fi + if [ -n "${vidnamesarray[1]}" ] && [ -n "${vidlinksarray[1]}" ]; then + sed -i "s#$(grep 'currentwp02=' "${conf}")#currentwp02=${vidnamesarray[1]} ${vidlinksarray[1]}#" "${conf}" + fi + if [ -n "${vidnamesarray[2]}" ] && [ -n "${vidlinksarray[2]}" ]; then + sed -i "s#$(grep 'currentwp04=' "${conf}")#currentwp04=${vidnamesarray[2]} ${vidlinksarray[2]}#" "${conf}" + fi + if [ -n "${vidnamesarray[3]}" ] && [ -n "${vidlinksarray[3]}" ]; then + sed -i "s#$(grep 'currentwp05=' "${conf}")#currentwp05=${vidnamesarray[3]} ${vidlinksarray[3]}#" "${conf}" + fi + if [ -n "${vidnamesarray[4]}" ] && [ -n "${vidlinksarray[4]}" ]; then + sed -i "s#$(grep 'currentwp11=' "${conf}")#currentwp11=${vidnamesarray[4]} ${vidlinksarray[4]}#" "${conf}" + fi + if [ -n "${vidnamesarray[5]}" ] && [ -n "${vidlinksarray[5]}" ]; then + sed -i "s#$(grep 'currentwp12=' "${conf}")#currentwp12=${vidnamesarray[5]} ${vidlinksarray[5]}#" "${conf}" + fi + fi + if [ "${when}" == "-m" ]; then + if [ -n "${vidnamesarray[0]}" ] && [ -n "${vidlinksarray[0]}" ]; then + sed -i "s#$(grep 'currentmp01=' "${conf}")#currentmp01=${vidnamesarray[0]} ${vidlinksarray[0]}#" "${conf}" + fi + if [ -n "${vidnamesarray[1]}" ] && [ -n "${vidlinksarray[1]}" ]; then + sed -i "s#$(grep 'currentmp02=' "${conf}")#currentmp02=${vidnamesarray[1]} ${vidlinksarray[1]}#" "${conf}" + fi + if [ -n "${vidnamesarray[2]}" ] && [ -n "${vidlinksarray[2]}" ]; then + sed -i "s#$(grep 'currentmp04=' "${conf}")#currentmp04=${vidnamesarray[2]} ${vidlinksarray[2]}#" "${conf}" + fi + if [ -n "${vidnamesarray[3]}" ] && [ -n "${vidlinksarray[3]}" ]; then + sed -i "s#$(grep 'currentmp05=' "${conf}")#currentmp05=${vidnamesarray[3]} ${vidlinksarray[3]}#" "${conf}" + fi + if [ -n "${vidnamesarray[4]}" ] && [ -n "${vidlinksarray[4]}" ]; then + sed -i "s#$(grep 'currentmp11=' "${conf}")#currentmp11=${vidnamesarray[4]} ${vidlinksarray[4]}#" "${conf}" + fi + if [ -n "${vidnamesarray[5]}" ] && [ -n "${vidlinksarray[5]}" ]; then + sed -i "s#$(grep 'currentmp12=' "${conf}")#currentmp12=${vidnamesarray[5]} ${vidlinksarray[5]}#" "${conf}" + fi + fi + if [ "${when}" == "-y" ]; then + if [ -n "${vidnamesarray[0]}" ] && [ -n "${vidlinksarray[0]}" ]; then + sed -i "s#$(grep 'currentyp01=' "${conf}")#currentyp01=${vidnamesarray[0]} ${vidlinksarray[0]}#" "${conf}" + fi + if [ -n "${vidnamesarray[1]}" ] && [ -n "${vidlinksarray[1]}" ]; then + sed -i "s#$(grep 'currentyp02=' "${conf}")#currentyp02=${vidnamesarray[1]} ${vidlinksarray[1]}#" "${conf}" + fi + if [ -n "${vidnamesarray[2]}" ] && [ -n "${vidlinksarray[2]}" ]; then + sed -i "s#$(grep 'currentyp04=' "${conf}")#currentyp04=${vidnamesarray[2]} ${vidlinksarray[2]}#" "${conf}" + fi + if [ -n "${vidnamesarray[3]}" ] && [ -n "${vidlinksarray[3]}" ]; then + sed -i "s#$(grep 'currentyp05=' "${conf}")#currentyp05=${vidnamesarray[3]} ${vidlinksarray[3]}#" "${conf}" + fi + if [ -n "${vidnamesarray[4]}" ] && [ -n "${vidlinksarray[4]}" ]; then + sed -i "s#$(grep 'currentyp11=' "${conf}")#currentyp11=${vidnamesarray[4]} ${vidlinksarray[4]}#" "${conf}" + fi + if [ -n "${vidnamesarray[5]}" ] && [ -n "${vidlinksarray[5]}" ]; then + sed -i "s#$(grep 'currentyp12=' "${conf}")#currentyp12=${vidnamesarray[5]} ${vidlinksarray[5]}#" "${conf}" + fi + fi +} + +# +# VARIABLES: +# + +show=$1 +conf=$2 +if [ -z "${conf}" ] || [ "${conf}" == "-" ]; then + conf="$(dirname "$(realpath "$0")")/$(basename -s .sh "$0").conf" +fi +ever=$4 +if [ -z "${ever}" ] || [ "${ever}" == "-" ]; then + ever=1 +fi +if grep -q -o "^[0-9][0-9]*$" <<< "${ever}"; then + : +else + execerror "${ever} - wrong argument" +fi +when=$3 +if [ -z "${when}" ]; then + viddate=$(date +"%Y").$(date +"%m").$(date +"%d") +fi +if [ "${when}" == "-d" ]; then + d=$(date -d "-${ever} day" +"%d") + m=$(date +"%m") + if [ "$(date -d "-${ever} day" +'%m')" != "$(date +'%m')" ]; then + m=$(date -d "-${ever} day" +'%m') + fi + y=$(date +"%Y") + if [ "$(date -d "-${ever} day" +'%Y')" != "$(date +'%Y')" ]; then + y=$(date -d "-${ever} day" +'%Y') + fi + viddate="${y}.${m}.${d}" +fi +if [ "${when}" == "-w" ]; then + w=$(date -d "-${ever} week" +"%V") + y=$(date +"%Y") + if [ "$(date -d "-${ever} week" +'%Y')" != "$(date +'%Y')" ]; then + y=$(date -d "-${ever} week" +'%Y') + fi + viddate="${y}-w${w}" +fi +if [ "${when}" == "-m" ]; then + m=$(date -d "-${ever} month" +"%m") + y=$(date +"%Y") + if [ "$(date -d "-${ever} month" +'%Y')" != "$(date +'%Y')" ]; then + y=$(date -d "-${ever} month" +'%Y') + fi + viddate="${y}.${m}" +fi +if [ "${when}" == "-y" ]; then + y=$(date -d "-${ever} year" +"%Y") + viddate="${y}" +fi +vidname="${viddate}.mp4" +only=$5 + +time=$(date +%s) +cd "$(dirname "$(realpath "$0")")" || execerror +if [ ! -e "${conf}" ]; then + execerror "Not found config file: ${conf}" +else + getconfig +fi +if [ -z "${logs}" ]; then + logs=/dev/null +elif [ ! -e "${logs}" ]; then + touch "${logs}" +fi +if ! command -v curl &> /dev/null || \ + ! command -v ffmpeg &> /dev/null || \ + ! command -v xmllint &> /dev/null || \ + ! command -v jq &> /dev/null; then + execerror "Not found dependencies" +fi + +# +# MAIN: +# + +vidpathsarray=() +vidlinksarray=() +vidtgidsarray=() +vidtgcpsarray=() +for name in "${vidnamesarray[@]}"; do + vidmatch="${name}_${vidname}" + while read -r FILE; do + vidpathsarray+=("${FILE}") + done < <(find "${pathroot}" -name "*${vidmatch}" | sort) +done +for item in "${!vidpathsarray[@]}"; do + # WORDPRESS UPLOAD VIDEO + if [ ! "$only" == "--onlytg" ]; then + # This realisation isn't optimal, but it fixes a few issues with large files: + # variable=$(base64 $file) -> "xrealloc: cannot allocate" + # response=$(curl -X POST -d @${file}.xml $url) -> "curl: option -d: out of memory" + filetype="video/mp4" + echo ' + wp.uploadFile + + 1 + '"${wpxmlrpcuser}"' + '"${wpxmlrpcpass}"' + + name'"$(basename "${vidpathsarray[$item]}")"' + type'"${filetype}"' + bits' > "${vidpathsarray[$item]}.xml" + base64 --wrap=0 "${vidpathsarray[$item]}" >> "${vidpathsarray[$item]}.xml" + echo ' + + + ' >> "${vidpathsarray[$item]}.xml" + response="${vidpathsarray[$item]}-response.xml" + if curl -X POST -T "${vidpathsarray[$item]}.xml" "${wpxmlrpclink}" > "${response}"; then + vidlinksarray+=("$(xmllint --xpath '//member[contains(name,"link")]/value/string/text()' "${response}")") + vidlinkcodeis=$(curl --output /dev/null --silent --write-out "%{http_code}" "${vidlinksarray[$item]}") + else + execerror "${response}" + fi + if [[ ${vidlinkcodeis} -eq 200 ]]; then + rm "${vidpathsarray[$item]}.xml" + rm "${response}" + echo "$(date +'%Y.%m.%d-%H:%M:%S') sent ${vidpathsarray[$item]} to ${vidlinksarray[$item]}" | tee -a "${logs}" + echo -e "WORDPRESS UPLOAD VIDEO RESULT:" + echo -e "item: ${item}" + echo -e "type: ${filetype}" + echo -e "name: ${vidnamesarray[$item]}" + echo -e "base: $(basename "${vidpathsarray[$item]}")" + echo -e "path: ${vidpathsarray[$item]}" + echo -e "link: ${vidlinksarray[$item]}" + echo -e "code: ${vidlinkcodeis}" + else + vidlinksarray[item]='' + fi + fi + + # TELEGRAM SEND/UPLOAD VIDEO + if [ ! "${only}" == "--onlywp" ]; then + videofullpath=${vidpathsarray[$item]} + vidcompressed=${videofullpath//".mp4"/"-compressed.mp4"} + if [ -n "$(find "${videofullpath}" -prune -size +51380224c)" ]; then + duration=$(ffprobe -i "${videofullpath}" \ + -show_entries format=duration -v quiet -of csv="p=0" | cut -d'.' -f 1) + if ffmpeg -i "${videofullpath}" \ + -c:v libx264 -b:v "$((49*8*1000/duration))k" \ + -vf "scale=960:540,fps=25,format=yuv420p" \ + -preset veryslow "${vidcompressed}" -y -loglevel quiet -stats; then + videofullpath=${vidcompressed} + else + execerror "ffmpeg convert ${videofullpath} to ${vidcompressed}" + fi + fi + videobasename=$(basename "${videofullpath}") + videobasename=${videobasename//".mp4"/""} + response=$(curl -s \ + -F "chat_id=${telegramchatid}" \ + -F "video=@${videofullpath}" \ + -F "caption=${videobasename}" \ + "${telegramapiurl}/sendVideo") + if curl -s -F "chat_id=${telegramchatid}" \ + -F "message_id=$(echo "${response}" | jq -r '.result.message_id')" \ + "${telegramapiurl}/deleteMessage"; then + vidtgidsarray+=("$(echo "${response}" | jq -r '.result.video.file_id')") + vidtgcpsarray+=("$(echo "${response}" | jq -r '.result.caption')") + addtologs "sent ${videofullpath} to ${vidtgidsarray[$item]} Telegram file ID" + else + execerror "sent ${videofullpath} to ${telegramchatid} Telegram Chat ID" + fi + if [ -e "${vidcompressed}" ]; then + rm "${vidcompressed}" + fi + fi +done + +# TELEGRAM SEND MEDIAGROUP +if [ ! "${only}" == "--onlywp" ]; then + response=$(curl -s -F "chat_id=${telegramchatid}" \ + -F media='[ + {"type":"photo","media":"'"${tgpreviewlink}"'", + "caption":"period: '"${viddate}"'\nsource: '"${tgpreviewtext}"'\nstream: '"${youtubelink}"'"}, + {"type":"video","media":"'"${vidtgidsarray[0]}"'"}, + {"type":"video","media":"'"${vidtgidsarray[1]}"'"}, + {"type":"video","media":"'"${vidtgidsarray[2]}"'"}, + {"type":"video","media":"'"${vidtgidsarray[3]}"'"}, + {"type":"video","media":"'"${vidtgidsarray[4]}"'"}, + {"type":"video","media":"'"${vidtgidsarray[5]}"'"}]' \ + -H "Content-Type:multipart/form-data" \ + "${telegramapiurl}/sendMediaGroup") +fi + +# WORDPRESS UPDATE PAGE +if [ ! "${only}" == "--onlytg" ]; then + setconfig + getconfig + xml=$(cat "./${wptemplateis}") + + xml=${xml//wpeditpageid/${wpeditpageid}} + xml=${xml//wpxmlrpcuser/${wpxmlrpcuser}} + xml=${xml//wpxmlrpcpass/${wpxmlrpcpass}} + + xml=${xml//youtubelink/${youtubelink}} + + xml=${xml//"currentdp01[0]"/${currentdp01[0]}} + xml=${xml//"currentdp01[1]"/${currentdp01[1]}} + xml=${xml//"currentdp02[0]"/${currentdp02[0]}} + xml=${xml//"currentdp02[1]"/${currentdp02[1]}} + xml=${xml//"currentdp04[0]"/${currentdp04[0]}} + xml=${xml//"currentdp04[1]"/${currentdp04[1]}} + xml=${xml//"currentdp05[0]"/${currentdp05[0]}} + xml=${xml//"currentdp05[1]"/${currentdp05[1]}} + xml=${xml//"currentdp11[0]"/${currentdp11[0]}} + xml=${xml//"currentdp11[1]"/${currentdp11[1]}} + xml=${xml//"currentdp12[0]"/${currentdp12[0]}} + xml=${xml//"currentdp12[1]"/${currentdp12[1]}} + + xml=${xml//"currentwp01[0]"/${currentwp01[0]}} + xml=${xml//"currentwp01[1]"/${currentwp01[1]}} + xml=${xml//"currentwp02[0]"/${currentwp02[0]}} + xml=${xml//"currentwp02[1]"/${currentwp02[1]}} + xml=${xml//"currentwp04[0]"/${currentwp04[0]}} + xml=${xml//"currentwp04[1]"/${currentwp04[1]}} + xml=${xml//"currentwp05[0]"/${currentwp05[0]}} + xml=${xml//"currentwp05[1]"/${currentwp05[1]}} + xml=${xml//"currentwp11[0]"/${currentwp11[0]}} + xml=${xml//"currentwp11[1]"/${currentwp11[1]}} + xml=${xml//"currentwp12[0]"/${currentwp12[0]}} + xml=${xml//"currentwp12[1]"/${currentwp12[1]}} + + xml=${xml//"currentmp01[0]"/${currentmp01[0]}} + xml=${xml//"currentmp01[1]"/${currentmp01[1]}} + xml=${xml//"currentmp02[0]"/${currentmp02[0]}} + xml=${xml//"currentmp02[1]"/${currentmp02[1]}} + xml=${xml//"currentmp04[0]"/${currentmp04[0]}} + xml=${xml//"currentmp04[1]"/${currentmp04[1]}} + xml=${xml//"currentmp05[0]"/${currentmp05[0]}} + xml=${xml//"currentmp05[1]"/${currentmp05[1]}} + xml=${xml//"currentmp11[0]"/${currentmp11[0]}} + xml=${xml//"currentmp11[1]"/${currentmp11[1]}} + xml=${xml//"currentmp12[0]"/${currentmp12[0]}} + xml=${xml//"currentmp12[1]"/${currentmp12[1]}} + + xml=${xml//"currentyp01[0]"/${currentyp01[0]}} + xml=${xml//"currentyp01[1]"/${currentyp01[1]}} + xml=${xml//"currentyp02[0]"/${currentyp02[0]}} + xml=${xml//"currentyp02[1]"/${currentyp02[1]}} + xml=${xml//"currentyp04[0]"/${currentyp04[0]}} + xml=${xml//"currentyp04[1]"/${currentyp04[1]}} + xml=${xml//"currentyp05[0]"/${currentyp05[0]}} + xml=${xml//"currentyp05[1]"/${currentyp05[1]}} + xml=${xml//"currentyp11[0]"/${currentyp11[0]}} + xml=${xml//"currentyp11[1]"/${currentyp11[1]}} + xml=${xml//"currentyp12[0]"/${currentyp12[0]}} + xml=${xml//"currentyp12[1]"/${currentyp12[1]}} + + xml=${xml//wpedituserid/${wpedituserid}} + xml=${xml//wppageauthor/${wppageauthor}} + xml=${xml//wppagelinkis/${wppagelinkis}} + xml=${xml//wpeditdateis/${wpeditdateis}} + + response=$(curl -d "${xml}" "${wpxmlrpclink}") + if echo "${response}" | grep -q '1'; then + addtologs "update $(grep 'Link' "${xml}" | cut -d'>' -f 6 | cut -d'<' -f 1))" + else + echo "${response}" | xmllint --format - > "${pathroot}/wp-page${wpeditpageid}-response.xml" 2>/dev/null + execerror "${pathroot}/wp-page${wpeditpageid}-response.xml" + fi +fi +execquite diff --git a/archive/0.2/streaming.py b/archive/0.2/streaming.py new file mode 100644 index 0000000..b19da1d --- /dev/null +++ b/archive/0.2/streaming.py @@ -0,0 +1,297 @@ +#!/usr/bin/env python3 + + +from multiprocessing import Process, Queue +from os import path, environ +from subprocess import Popen, PIPE, STDOUT +from sys import platform +from time import sleep + + +class Proc: + """ + Find a running process from Python + """ + @classmethod + def _list_windows(cls) -> list: + """ + Find all running process with wmi + :return: list of dictionaries with descriptions of found processes + """ + execlist = [] + separate = b'\r\r\n' + out, err = Popen(['wmic', 'process', 'get', 'CommandLine,ExecutablePath,Name,ProcessId', '/format:list'], + stdout=PIPE, stderr=PIPE).communicate() + for line in out.split(separate + separate): + execpid, exename, exepath, cmdline = None, None, None, None + for subline in line.split(separate): + if b'ProcessId=' in subline: + execpid = subline.split(b'=')[1].decode('utf-8') + if b'Name=' in subline: + exename = subline.split(b'=')[1].decode('utf-8') + if b'ExecutablePath=' in subline: + exepath = subline.split(b'=')[1].decode('utf-8') + if b'CommandLine=' in subline: + cmdline = subline.split(b'=')[1].decode('utf-8') + if execpid and exename: + execlist.append({'execpid': execpid, 'exename': exename, 'exepath': exepath, 'cmdline': cmdline}) + return execlist + + @classmethod + def _list_linux(cls) -> list: + """ + Find all running process with ps + :return: list of dictionaries with descriptions of found processes + """ + execlist = [] + out, err = Popen(['/bin/ps', '-eo', 'pid,args'], stdout=PIPE, stderr=PIPE).communicate() + for line in out.splitlines(): + execpid = line.split()[0].decode('utf-8') + exepath = line.split()[1].decode('utf-8') + exename = path.basename(exepath) + cmdline = line.split(None, 1)[1].decode('utf-8') + if execpid and exename: + execlist.append({'execpid': execpid, 'exename': exename, 'exepath': exepath, 'cmdline': cmdline}) + return execlist + + @classmethod + def list(cls) -> list: + """ + Find all running process + :return: list of dictionaries with descriptions of found processes + """ + if platform.startswith('linux') or platform.startswith('darwin'): + return cls._list_linux() + elif platform.startswith('win32'): + return cls._list_windows() + else: + return None + + @classmethod + def search(cls, find: str, exclude: str = None) -> list: + """ + Find specified processes + :param find: find process pid, name or arguments + :param exclude: exclude process pid, name or arguments + :return: list of dictionaries with descriptions of found processes + """ + proc_found = [] + try: + for proc in cls.list(): + if exclude and (exclude in proc['execpid'] or exclude in proc['exename'] or + exclude in proc['exepath'] or exclude in proc['cmdline']): + pass + elif find in proc['execpid'] or find in proc['exename'] or \ + find in proc['exepath'] or find in proc['cmdline']: + proc_found.append(proc) + except TypeError as ex: + print('ON', platform, 'PLATFORM', 'search ERROR:', ex) + finally: + if len(proc_found) == 0: + return None + else: + return proc_found + + @classmethod + def kill(cls, pid: int) -> None: + """ + Kill the process by means of the OS + :param pid: process ID + :return: None + """ + if platform.startswith('linux') or platform.startswith('darwin'): + Popen(['kill', '-s', 'SIGKILL', str(pid)]) + elif platform.startswith('win32'): + Popen(['taskkill', '/PID', str(pid), '/F']) + + +class FFmpeg: + """ + FFmpeg management from Python + """ + @classmethod + def run(cls, src: str, preset: str = None, fps: int = None, dst: str = None, + ffpath: str = None, watchdog: bool = False, sec: int = 5, mono: bool = False) -> None: + """ + Running the installed ffmpeg + :param src: sources urls (example: "rtsp://user:pass@host:554/Streaming/Channels/101, anull") + :param preset: 240p, 360p, 480p, 720p, 1080p, 1440p, 2160p + :param fps: frame per second encoding output + :param dst: destination url (example: rtp://239.0.0.1:5554) + :param ffpath: alternative path to bin (example: /usr/bin/ffmpeg) + :param watchdog: detect ffmpeg freeze and terminate + :param sec: seconds to wait before the watchdog terminates + :param mono: detect ffmpeg running copy and terminate + :return: None + """ + process = cls._bin(ffpath).split()+cls._src(src).split()+cls._preset(preset, fps).split()+cls._dst(dst).split() + if mono and Proc.search(' '.join(process)): + print('Process already exist, exit...') + else: + with Popen(process, stdout=PIPE, stderr=STDOUT) as proc: + que = None + if watchdog: + que = Queue() + Process(target=cls._watchdog, args=(proc.pid, sec, que,), daemon=True).start() + for line in proc.stdout: + if not que: + print(line, flush=True) + else: + que.put(line) + exit() + + @classmethod + def _bin(cls, path_ffmpeg: str) -> str: + """ + Returns the path to the ffmpeg depending on the OS + :param path_ffmpeg: alternative path to bin + :return: path to ffmpeg + """ + faq = ('\n' + 'Main download page: https://ffmpeg.org/download.html\n' + '\n' + 'Install on Linux (Debian):\n' + '\tsudo apt install -y ffmpeg\n' + '\tTarget: /usr/bin/ffmpeg\n' + '\n' + 'Install on Windows:\n' + '\tDownload and extract archive from: https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-full.7z\n' + '\tTarget: "%PROGRAMFILES%\\ffmpeg\\bin\\ffmpeg.exe"\n' + '\n' + 'Install on MacOS:\n' + '\tDownload and extract archive from: https://evermeet.cx/ffmpeg/\n' + '\tTarget: /usr/bin/ffmpeg\n') + if not path_ffmpeg: + if platform.startswith('linux') or platform.startswith('darwin'): + path_ffmpeg = '/usr/bin/ffmpeg' + elif platform.startswith('win32'): + path_ffmpeg = environ['PROGRAMFILES'] + "\\ffmpeg\\bin\\ffmpeg.exe" + if path.exists(path_ffmpeg): + return path_ffmpeg + else: + print('ON', platform, 'PLATFORM', 'not found ffmpeg', faq) + return None + + @classmethod + def _src(cls, sources: str) -> list: + """ + Parsing sources into ffmpeg format + :param sources: comma-separated list of sources in string format + :return: ffmpeg format list of sources + """ + list_sources = [] + for src in sources.split(','): + src = src.strip() + if 'null' in src: + src = ' '.join(['-f lavfi -i', src]) + elif 'rtsp' in src: + src = ' '.join(['-rtsp_transport tcp -i', src]) + else: + src = ' '.join(['-stream_loop -1 -re -i', src]) + list_sources.append(src) + return ' '.join(list_sources) + + @classmethod + def _preset(cls, choice: str, fps: int) -> str: + """ + Parsing preset into ffmpeg format + :param choice: preset selection + :param fps: frame per second encoding output + :return: ffmpeg format encoding parameters + """ + tune = '-tune zerolatency' + video = '-c:v copy' + audio = '-c:a aac -b:a 128k' + width, height, kbps = None, None, None + if choice: + if choice == '240p': + width, height, kbps = 426, 240, 480 + if choice == '360p': + width, height, kbps = 640, 360, 720 + if choice == '480p': + width, height, kbps = 854, 480, 1920 + if choice == '720p': + width, height, kbps = 1280, 720, 3960 + if choice == '1080p': + width, height, kbps = 1920, 1080, 5940 + if choice == '1440p': + width, height, kbps = 2560, 1440, 12960 + if choice == '2160p': + width, height, kbps = 3840, 2160, 32400 + if width and height and kbps: + video = ''.join(['-vf scale=', str(width), ':', str(height), ',setsar=1:1']) + video = ' '.join([video, '-c:v libx264 -pix_fmt yuv420p -preset ultrafast']) + if fps: + video = ' '.join([video, '-r', str(fps), '-g', str(fps * 2)]) + video = ' '.join([video, '-b:v', str(kbps) + 'k']) + return ' '.join([tune, video, audio]) + + @classmethod + def _dst(cls, destination: str) -> str: + """ + Parsing destination into ffmpeg format + :param destination: + :return: ffmpeg format destination + """ + container = '-f null' + stdout = '-v debug' # '-nostdin -nostats' # '-report' + if destination: + if 'rtmp' in destination: + container = '-f flv' + elif "rtp" in destination: + container = '-f rtp_mpegts' + else: + destination = '-' + return ' '.join([container, destination, stdout]) + + @classmethod + def _watchdog(cls, pid: int, sec: int = 5, que: Queue = None) -> None: + """ + If no data arrives in the queue, kill the process + :param pid: process ID + :param sec: seconds to wait for data + :param que: queue pointer + :return: None + """ + if que: + while True: + while not que.empty(): + print(que.get()) + sleep(sec) + if que.empty(): + Proc.kill(pid) + print('exit by watchdog') + break + exit() + + +if __name__ == "__main__": + from argparse import ArgumentParser + + args = ArgumentParser( + prog='streaming', + description='FFmpeg management from Python', + epilog='Dependencies: ' + 'Python 3 (tested version 3.9.5 on Debian GNU/Linux 11), ' + 'ffmpeg (tested version 4.3.4 on Debian GNU/Linux 11)' + ) + args.add_argument('-s', '--src', type=str, required=True, + help='sources urls (example: "rtsp://user:pass@host:554/Streaming/Channels/101, anull")') + args.add_argument('--preset', type=str, default=None, required=False, + help='240p, 360p, 480p, 720p, 1080p, 1440p, 2160p') + args.add_argument('--fps', type=int, default=None, required=False, + help='frame per second encoding output') + args.add_argument('--dst', type=str, default=None, required=False, + help='destination url (example: rtp://239.0.0.1:5554)') + args.add_argument('--ffpath', type=str, default=None, required=False, + help='alternative path to bin (example: /usr/bin/ffmpeg)') + args.add_argument('--watchdog', action='store_true', required=False, + help='detect ffmpeg freeze and terminate') + args.add_argument('--sec', type=int, default=15, required=False, + help='seconds to wait before the watchdog terminates') + args.add_argument('--mono', action='store_true', required=False, + help='detect ffmpeg running copy and terminate') + args = vars(args.parse_args()) + + FFmpeg.run(src=args['src'], preset=args['preset'], fps=args['fps'], dst=args['dst'], + ffpath=args['ffpath'], watchdog=args['watchdog'], sec=args['sec'], mono=args['mono']) diff --git a/cctv-scheduler.conf b/cctv-scheduler.conf index 36acf93..702868f 100644 --- a/cctv-scheduler.conf +++ b/cctv-scheduler.conf @@ -13,11 +13,47 @@ #log_level = DEBUG +[enable-broadcast] +# List the broadcast block names. Only blocks with the TRUE value will be used. +camera.test.local = true + + +[enable-sequences] +# List the sequence/camera block names. Only blocks with the TRUE value will be used. +camera.test.local = true + + [enable-sensors] # List the sensor block names. Only blocks with the TRUE value will be used. sensor.test.local = true +[broadcast-config:camera.test.local] +# Broadcast parameter description block always starts with "broadcast-config:". +src = rtsp://user:pass@192.168.254.253:554/Streaming/Channels/101,http://radio.fm:8000/stream.mp3 +dst = rtp://239.0.0.1:5554 +# Optionality you can change video stream framerate. +#fps = 25 +# +# Optionality you can set YouTube recommended preset: +# 240p, 360p, 480p, 720p, 1080p, 1440p, 2160p. +#preset = 1080p +# +# By default ffmpeg expected in /usr/bin/ffmpeg or C:\Program Files\ffmpeg\bin\ffmpeg.exe. +# If you need change it, uncomment the parameter and set the path you want. +#ffpath = /usr/bin/ffmpeg +# +# If you get program freezes because your network unstable, uncomment the parameter. +#watchdog = true +# +# By default, watchdog waits 5 seconds before terminating the program. +# If you need change it, uncomment the parameter and set the path you want. +#watchsec = 15 +# +# If you use crontab or other scheduler to run, uncomment the parameter to prevent process overlap. +#onlyonce = true + + [sensor-config:sensor.test.local] # Remote host's sensor parameter description block always starts with "sensor-config:". hostname = 192.168.254.252 @@ -30,11 +66,6 @@ nodetype = ds18b20 nodename = 28-1a2b3c4d5e6f -[enable-sequences] -# List the sequence/camera block names. Only blocks with the TRUE value will be used. -camera.test.local = true - - [camera-config:camera.test.local] # Camera parameter description block always starts with "camera-config:". hostname = 192.168.254.253 diff --git a/cctv-scheduler.py b/cctv-scheduler.py index e119e78..6463e41 100644 --- a/cctv-scheduler.py +++ b/cctv-scheduler.py @@ -6,7 +6,10 @@ import urllib.request from argparse import ArgumentParser from datetime import datetime from ftplib import FTP -from os import path, sep, makedirs, remove, replace +from multiprocessing import Process, Queue +from os import path, sep, makedirs, remove, replace, environ +from subprocess import Popen, PIPE, STDOUT +from sys import platform from time import sleep from paramiko import SSHClient, AutoAddPolicy @@ -1126,6 +1129,349 @@ class Sequence: logging.warning(msg='result:' + key + ' = ERROR') +class Proc: + """Find a running process from Python. + """ + @classmethod + def _list_windows(cls) -> list: + """Find all running process with wmi. + + Returns: + list: dictionaries with descriptions of found processes. + """ + execlist = [] + separate = b'\r\r\n' + out, err = Popen( + [ + 'wmic', 'process', 'get', + 'CommandLine,ExecutablePath,Name,ProcessId', + '/format:list' + ], + stdout=PIPE, + stderr=PIPE + ).communicate() + for line in out.split(separate + separate): + execpid, exename, exepath, cmdline = None, None, None, None + for subline in line.split(separate): + if b'ProcessId=' in subline: + execpid = subline.split(b'=')[1].decode('utf-8') + if b'Name=' in subline: + exename = subline.split(b'=')[1].decode('utf-8') + if b'ExecutablePath=' in subline: + exepath = subline.split(b'=')[1].decode('utf-8') + if b'CommandLine=' in subline: + cmdline = subline.split(b'=')[1].decode('utf-8') + if execpid and exename: + execlist.append( + { + 'execpid': execpid, + 'exename': exename, + 'exepath': exepath, + 'cmdline': cmdline + } + ) + return execlist + + @classmethod + def _list_linux(cls) -> list: + """Find all running process with ps. + + Returns: + list: dictionaries with descriptions of found processes. + """ + execlist = [] + out, err = Popen( + [ + '/bin/ps', '-eo', 'pid,args' + ], + stdout=PIPE, + stderr=PIPE + ).communicate() + for line in out.splitlines(): + execpid = line.split()[0].decode('utf-8') + exepath = line.split()[1].decode('utf-8') + exename = path.basename(exepath) + cmdline = line.split(None, 1)[1].decode('utf-8') + if execpid and exename: + execlist.append( + { + 'execpid': execpid, + 'exename': exename, + 'exepath': exepath, + 'cmdline': cmdline + } + ) + return execlist + + @classmethod + def list(cls) -> list: + """Find all running process. + + Returns: + list: dictionaries with descriptions of found processes. + """ + if platform.startswith('linux') or platform.startswith('darwin'): + return cls._list_linux() + elif platform.startswith('win32'): + return cls._list_windows() + else: + return None + + @classmethod + def search(cls, find: str, exclude: str = None) -> list: + """Find specified processes. + + Args: + find (str): find process pid, name or arguments. + exclude (str, optional): exclude process pid, name or arguments. Defaults to None. + + Returns: + list: dictionaries with descriptions of found processes. + """ + proc_found = [] + try: + for proc in cls.list(): + if exclude and ( + exclude in proc['execpid'] or + exclude in proc['exename'] or + exclude in proc['exepath'] or + exclude in proc['cmdline'] + ): + pass + elif ( + find in proc['execpid'] or + find in proc['exename'] or + find in proc['exepath'] or + find in proc['cmdline'] + ): + proc_found.append(proc) + except TypeError as ex: + print('ON', platform, 'PLATFORM', 'search ERROR:', ex) + finally: + if len(proc_found) == 0: + return None + else: + return proc_found + + @classmethod + def kill(cls, pid: int) -> None: + """Kill the process by means of the OS. + + Args: + pid (int): process ID. + """ + if platform.startswith('linux') or platform.startswith('darwin'): + Popen(['kill', '-s', 'SIGKILL', str(pid)]) + elif platform.startswith('win32'): + Popen(['taskkill', '/PID', str(pid), '/F']) + + +class FFmpeg: + """FFmpeg management from Python. + """ + @classmethod + def run( + cls, + src: str, + dst: str = None, + fps: int = None, + preset: str = None, + ffpath: str = None, + watchdog: bool = False, + watchsec: int = None, + onlyonce: bool = False + ) -> None: + """Running the installed ffmpeg + + Args: + src (str): sources urls (example: "rtsp://user:pass@host:554/Streaming/Channels/101, anull"). + dst (str, optional): destination url (example: rtp://239.0.0.1:5554). Defaults to None. + fps (int, optional): frame per second encoding output. Defaults to None. + preset (str, optional): 240p, 360p, 480p, 720p, 1080p, 1440p, 2160p. Defaults to None. + ffpath (str, optional): alternative path to bin (example: /usr/bin/ffmpeg). Defaults to None. + watchdog (bool, optional): detect ffmpeg freeze and terminate. Defaults to False. + watchsec (int, optional): seconds to wait before the watchdog terminates. Defaults to None. + onlyonce (bool, optional): detect ffmpeg running copy and terminate. Defaults to False. + """ + + process = ( + cls._bin(ffpath).split() + + cls._src(src).split() + + cls._preset(preset, fps).split() + + cls._dst(dst).split() + ) + if onlyonce and Proc.search(' '.join(process)): + print('Process already exist, exit...') + else: + logging.info(msg='Starting ' + ' '.join(process)) + with Popen(process, stdout=PIPE, stderr=STDOUT) as proc: + que = None + if watchdog: + que = Queue() + Process( + target=cls._watchdog, + args=(proc.pid, watchsec, que,), + daemon=True + ).start() + for line in proc.stdout: + if not que: + print(line, flush=True) + else: + que.put(line) + exit() + + @classmethod + def _bin(cls, path_ffmpeg: str) -> str: + """Returns the path to the ffmpeg depending on the OS. + + Args: + path_ffmpeg (str): alternative path to bin. + + Returns: + str: path to ffmpeg. + """ + faq = ( + '\n' + 'Main download page: https://ffmpeg.org/download.html\n' + '\n' + 'Install on Linux (Debian):\n' + '\tsudo apt install -y ffmpeg\n' + '\tTarget: /usr/bin/ffmpeg\n' + '\n' + 'Install on Windows:\n' + '\tDownload and extract archive from: https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-full.7z\n' + '\tTarget: "%PROGRAMFILES%\\ffmpeg\\bin\\ffmpeg.exe"\n' + '\n' + 'Install on MacOS:\n' + '\tDownload and extract archive from: https://evermeet.cx/ffmpeg/\n' + '\tTarget: /usr/bin/ffmpeg\n' + ) + if not path_ffmpeg: + if platform.startswith('linux') or platform.startswith('darwin'): + path_ffmpeg = '/usr/bin/ffmpeg' + elif platform.startswith('win32'): + path_ffmpeg = environ['PROGRAMFILES'] + "\\ffmpeg\\bin\\ffmpeg.exe" + if path.exists(path_ffmpeg): + return path_ffmpeg + else: + print('ON', platform, 'PLATFORM', 'not found ffmpeg', faq) + return None + + @classmethod + def _src(cls, sources: str) -> list: + """Parsing sources into ffmpeg format. + + Args: + sources (str): comma-separated list of sources in string format. + + Returns: + list: ffmpeg format list of sources. + """ + list_sources = [] + for src in sources.split(','): + src = src.strip() + if 'null' in src: + src = ' '.join(['-f lavfi -i', src]) + elif 'rtsp' in src: + src = ' '.join(['-rtsp_transport tcp -i', src]) + else: + src = ' '.join(['-stream_loop -1 -re -i', src]) + list_sources.append(src) + return ' '.join(list_sources) + + @classmethod + def _preset(cls, choice: str, fps: int) -> str: + """Parsing preset into ffmpeg format. + + Args: + choice (str): preset selection. + fps (int): frame per second encoding output. + + Returns: + str: ffmpeg format encoding parameters. + """ + tune = '-tune zerolatency' + video = '-c:v copy' + audio = '-c:a aac -b:a 128k' + width, height, kbps = None, None, None + if choice: + if choice == '240p': + width, height, kbps = 426, 240, 480 + if choice == '360p': + width, height, kbps = 640, 360, 720 + if choice == '480p': + width, height, kbps = 854, 480, 1920 + if choice == '720p': + width, height, kbps = 1280, 720, 3960 + if choice == '1080p': + width, height, kbps = 1920, 1080, 5940 + if choice == '1440p': + width, height, kbps = 2560, 1440, 12960 + if choice == '2160p': + width, height, kbps = 3840, 2160, 32400 + if width and height and kbps: + video = ''.join( + [ + '-vf scale=', + str(width), ':', str(height), + ',setsar=1:1' + ] + ) + video = ' '.join( + [ + video, + '-c:v libx264 -pix_fmt yuv420p -preset ultrafast' + ] + ) + if fps: + video = ' '.join([video, '-r', str(fps), '-g', str(fps * 2)]) + video = ' '.join([video, '-b:v', str(kbps) + 'k']) + return ' '.join([tune, video, audio]) + + @classmethod + def _dst(cls, destination: str) -> str: + """Parsing destination into ffmpeg format. + + Args: + destination (str): destination path or url. + + Returns: + str: ffmpeg format destination. + """ + container = '-f null' + stdout = '-v debug' # '-nostdin -nostats' # '-report' + if destination: + if 'rtmp' in destination: + container = '-f flv' + elif "rtp" in destination: + container = '-f rtp_mpegts' + else: + destination = '-' + return ' '.join([container, destination, stdout]) + + @classmethod + def _watchdog(cls, pid: int, sec: int, que: Queue = None) -> None: + """If no data arrives in the queue, kill the process. + + Args: + pid (int): process ID. + sec (int): seconds to wait for data. + que (Queue, optional): queue pointer. Defaults to None. + """ + if not sec: + sec = 5 + if que: + while True: + while not que.empty(): + print(que.get()) + sleep(sec) + if que.empty(): + Proc.kill(pid) + print('exit by watchdog') + break + exit() + + if __name__ == "__main__": time_start = datetime.now() @@ -1138,6 +1484,8 @@ if __name__ == "__main__": ) args.add_argument('--config', type=str, default=path.splitext(__file__)[0] + '.conf', required=False, help='custom configuration file path') + args.add_argument('-b', '--broadcast', action='store_true', required=False, + help='streaming media to destination') args.add_argument('-s', '--sequences', action='store_true', required=False, help='run sequences from config file') args.add_argument('-c', '--converter', action='store_true', required=False, @@ -1177,7 +1525,51 @@ if __name__ == "__main__": ) logging.getLogger("paramiko").setLevel(logging.WARNING) - if args['sequences']: + if args['broadcast']: + logging.info(msg='Starting streaming media to destination') + broadcasts = {} + conf = Parse(parameters=args['config'], block='enable-broadcast') + for key, value in conf.data.items(): + if value == 'true': + broadcast_config = Parse( + parameters=args['config'], + block='broadcast-config:' + key + ).data + src = None + if 'src' in broadcast_config: + src = broadcast_config['src'] + dst = None + if 'dst' in broadcast_config: + dst = broadcast_config['dst'] + fps = None + if 'fps' in broadcast_config: + fps = broadcast_config['fps'] + preset = None + if 'preset' in broadcast_config: + preset = broadcast_config['preset'] + ffpath = None + if 'ffpath' in broadcast_config: + ffpath = broadcast_config['ffpath'] + watchdog = None + if 'watchdog' in broadcast_config: + watchdog = broadcast_config['watchdog'] + watchsec = None + if 'watchsec' in broadcast_config: + watchsec = int(broadcast_config['watchsec']) + monopoly = None + if 'onlyonce' in broadcast_config: + onlyonce = broadcast_config['onlyonce'] + FFmpeg.run( + src=src, + dst=dst, + fps=fps, + preset=preset, + ffpath=ffpath, + watchdog=watchdog, + watchsec=watchsec, + onlyonce=onlyonce + ) + elif args['sequences']: logging.info(msg='Starting PTZ sequences from config file') sensors = {} conf = Parse(parameters=args['config'], block='enable-sensor') diff --git a/info/images/cctv-scheduler-0.3.png b/info/images/cctv-scheduler-0.3.png new file mode 100644 index 0000000000000000000000000000000000000000..14c91401024bb254b5d7f6a2829ea7622d1d4841 GIT binary patch literal 284467 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

SMLbOvNopUv>S_s@ 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

rMcXAo=; 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 literal 0 HcmV?d00001