├── .env ├── .gitattributes ├── .gitignore ├── .npmignore ├── COPYING ├── INSTALL.md ├── INSTALL ├── .gitignore ├── README.md ├── autoinstall-ubuntu-latest.sh ├── autoinstall-ubuntu-stable.sh ├── centos.sh ├── cuda9-part1.sh ├── cuda9-part2-after-reboot.sh ├── ffmpeg.sh ├── freebsd.sh ├── installDatabase.js ├── macos-part2.sh ├── macos.sh ├── now.sh ├── openalpr-gpu-easy.sh ├── opencv-cuda.sh ├── shinobi.service ├── start.sh ├── ubuntu-easyinstall.sh └── ubuntu.sh ├── LICENSE ├── README.md ├── UPDATE.sh ├── camera.js ├── conf.sample.json ├── cron.js ├── definitions └── en_CA.json ├── index.html ├── languages ├── ar.json ├── bn.json ├── de.json ├── en_CA.json ├── fr.json ├── ja.json ├── pt_BR.json ├── ru.json └── zh.json ├── package.json ├── plugins ├── .gitignore ├── child │ ├── .gitignore │ ├── child.js │ ├── conf.child.sample.json │ └── conf.json.default ├── microsoft │ ├── conf.sample.json │ └── shinobi-ms-vision.js ├── motion │ ├── .gitignore │ ├── INSTALL.sh │ ├── README.md │ ├── conf.sample.json │ ├── libs │ │ └── clusterPoints.js │ ├── shinobi-motion-pixel.js │ └── shinobi-motion.js ├── openalpr │ ├── .gitignore │ ├── README.md │ ├── conf.sample.json │ ├── package.json │ └── shinobi-openalpr.js └── opencv │ ├── .gitignore │ ├── conf.sample.json │ ├── shinobi-opencv-no-motion.js │ └── shinobi-opencv.js ├── sql ├── .gitignore ├── database.sql ├── default_data.sql ├── docker │ └── 01-framework.sql ├── framework.sql ├── mssql │ ├── default_data.sql │ ├── framework.sql │ └── user.sql ├── postgresql │ ├── default_data.sql │ ├── framework.sql │ └── user.sql ├── shinobi.sample.sqlite ├── sqlite3 │ └── framework.sql ├── sqllog.txt ├── tables.sql ├── update-1-1-2017.sql ├── update-13-7-2017.sql ├── update-17-5-2017.sql ├── update-2-2-2017.sql ├── update-26-08-2017.sql ├── update-5-6-2017.sql └── user.sql ├── super.sample.json ├── tools ├── addVideos.js.disabled └── translateLanguageFile.js └── web ├── libs ├── .gitignore ├── css │ ├── bootstrap-table.min.css │ ├── bootstrap-theme.css │ ├── bootstrap-theme.css.map │ ├── bootstrap-theme.min.css │ ├── bootstrap-theme.min.css.map │ ├── bootstrap.css │ ├── bootstrap.css.map │ ├── bootstrap.min.css │ ├── bootstrap.min.css.map │ ├── c3.css │ ├── circles.css │ ├── daterangepicker.css │ ├── daterangepicker.scss │ ├── font-awesome.css │ ├── font-awesome.min.css │ ├── fullcalendar.min.css │ ├── fullcalendar.print.css │ ├── login.css │ ├── main.dash2.css │ ├── material.min.css │ ├── material.min.css.map │ ├── material.style.css │ ├── pnotify.custom.min.css │ ├── poseidon.css │ └── vbox.css ├── fonts │ ├── FontAwesome.otf │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.svg │ ├── fontawesome-webfont.ttf │ ├── fontawesome-webfont.woff │ └── fontawesome-webfont.woff2 ├── img │ ├── bg.jpg │ ├── demo.jpg │ └── icon │ │ ├── README.md │ │ ├── apple-touch-icon-114x114.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-144x144.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-57x57.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-72x72.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── circle-text.png │ │ ├── favicon-128.png │ │ ├── favicon-16x16.png │ │ ├── favicon-196x196.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── favicon.ico │ │ ├── mstile-144x144.png │ │ ├── mstile-150x150.png │ │ ├── mstile-310x150.png │ │ ├── mstile-310x310-circle.png │ │ ├── mstile-310x310.png │ │ └── mstile-70x70.png ├── js │ ├── Chart.js │ ├── bootstrap-table-locale-all.min.js │ ├── bootstrap-table.min.js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── c3.js │ ├── clock.js │ ├── clusterPoints.js │ ├── d3.v3.min.js │ ├── dash.mediaplayer.min.js │ ├── daterangepicker.js │ ├── flv.min.js │ ├── flv.min.js.map │ ├── flv.shinobi.js │ ├── fullcalendar.min.js │ ├── gcal.js │ ├── hls.min.js │ ├── jquery-ui.min.js │ ├── jquery.canvasAreaDraw.js │ ├── jquery.min.js │ ├── jquery.serialize.js │ ├── livestamp.min.js │ ├── locale-all.js │ ├── main.dash2.js │ ├── material.min.js │ ├── material.min.js.map │ ├── menu.js │ ├── moment.js │ ├── morris.min.js │ ├── npm.js │ ├── placeholder.js │ ├── pnotify.custom.min.js │ ├── poseidon.js │ └── socket.io.js ├── less │ ├── animated.less │ ├── bordered-pulled.less │ ├── core.less │ ├── fixed-width.less │ ├── font-awesome.less │ ├── icons.less │ ├── larger.less │ ├── list.less │ ├── mixins.less │ ├── path.less │ ├── rotated-flipped.less │ ├── screen-reader.less │ ├── stacked.less │ └── variables.less ├── scss │ ├── _animated.scss │ ├── _bordered-pulled.scss │ ├── _core.scss │ ├── _fixed-width.scss │ ├── _icons.scss │ ├── _larger.scss │ ├── _list.scss │ ├── _mixins.scss │ ├── _path.scss │ ├── _rotated-flipped.scss │ ├── _screen-reader.scss │ ├── _stacked.scss │ ├── _variables.scss │ └── font-awesome.scss └── themes │ └── Enterprise Blue │ └── style.css └── pages ├── admin.ejs ├── blocks ├── api.ejs ├── confirm.ejs ├── filters.ejs ├── github.ejs ├── header.ejs ├── help.ejs ├── logs.ejs ├── mainpermissions.ejs ├── monitoredit.ejs ├── multimon.ejs ├── powervideo.ejs ├── probe.ejs ├── region.ejs ├── settings.ejs ├── subpermissions.ejs ├── timelapse.ejs └── videoview.ejs ├── dashcam.ejs ├── embed.ejs ├── factor.ejs ├── home.ejs ├── index.ejs ├── mjpeg.ejs ├── script.ejs ├── streamer.ejs └── super.ejs /.env: -------------------------------------------------------------------------------- 1 | MYSQL_HOST=db 2 | MYSQL_DATABASE=ccio 3 | MYSQL_USER=ccio 4 | MYSQL_PASSWORD=shinobi 5 | MYSQL_ROOT_PASSWORD=shinobiroot 6 | MYSQL_VOLUME_DIR="./dbdata" 7 | ADMIN_PASSWORD=admin 8 | TIMEZONE_OFFSET='-0800' 9 | VIDEOS_VOLUME_DIR="./videos" 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | docker-entrypoint.sh text eol=lf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | videos 3 | events 4 | frames 5 | web.old 6 | .DS_Store 7 | .vagrant 8 | conf.json 9 | super.json 10 | dbdata 11 | npm-debug.log 12 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | conf.json -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | This software is licensed under the GPLv3 and AGPLv3 2 | 3 | GPLv3 : https://www.gnu.org/licenses/gpl-3.0.en.html 4 | AGPLv3 : https://www.gnu.org/licenses/agpl-3.0.en.html -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | **Detailed Instructions for multiple Operating Systems can now be found in the docs.** 2 | 3 | https://shinobi.video/docs/start -------------------------------------------------------------------------------- /INSTALL/.gitignore: -------------------------------------------------------------------------------- 1 | installed.txt -------------------------------------------------------------------------------- /INSTALL/README.md: -------------------------------------------------------------------------------- 1 | #### Fast Install (The Ninja Way) 2 | 3 | 1. Become `root` to use the installer and run Shinobi. Use one of the following to do so. 4 | 5 | - Ubuntu 17.04, 17.10 6 | - `sudo su` 7 | - CentOS 7 8 | - `su` 9 | - MacOS 10.7(+) 10 | - `su` 11 | 2. Download and run the installer. 12 | 13 | ``` 14 | bash <(curl -s https://raw.githubusercontent.com/ShinobiCCTV/Shinobi-Installer/master/shinobi-install.sh) 15 | ``` 16 | 17 | More info can be found here. https://shinobi.video/docs/start -------------------------------------------------------------------------------- /INSTALL/autoinstall-ubuntu-latest.sh: -------------------------------------------------------------------------------- 1 | apt install git -y 2 | git clone https://github.com/ShinobiCCTV/Shinobi.git -b dev Shinobi-dev 3 | cd Shinobi-dev 4 | chmod +x INSTALL/ubuntu-easyinstall.sh && INSTALL/ubuntu-easyinstall.sh 5 | bash INSTALL/ubuntu-easyinstall.sh -------------------------------------------------------------------------------- /INSTALL/autoinstall-ubuntu-stable.sh: -------------------------------------------------------------------------------- 1 | apt install git -y 2 | git clone https://github.com/ShinobiCCTV/Shinobi.git Shinobi 3 | cd Shinobi 4 | chmod +x INSTALL/ubuntu-easyinstall.sh && INSTALL/ubuntu-easyinstall.sh 5 | bash INSTALL/ubuntu-easyinstall.sh -------------------------------------------------------------------------------- /INSTALL/cuda9-part1.sh: -------------------------------------------------------------------------------- 1 | sudo add-apt-repository ppa:graphics-drivers/ppa -y 2 | sudo apt update -y 3 | sudo apt install g++ freeglut3-dev build-essential libx11-dev libxmu-dev libxi-dev libglu1-mesa libglu1-mesa-dev -y 4 | sudo apt install gcc-6 -y 5 | sudo apt install g++-6 -y 6 | wget https://cdn.shinobi.video/installers/cuda9-part2-after-reboot.sh -O cuda9-part2-after-reboot.sh 7 | sudo chmod +x ./cuda9-part2-after-reboot.sh 8 | wget https://developer.nvidia.com/compute/cuda/9.0/Prod/local_installers/cuda_9.0.176_384.81_linux-run -O cuda_9.run 9 | sudo chmod +x cuda_9.run 10 | sudo echo "blacklist amd76x_edac" >> /etc/modprobe.d/blacklist.conf 11 | sudo echo "blacklist vga16fb" >> /etc/modprobe.d/blacklist.conf 12 | sudo echo "blacklist nouveau" >> /etc/modprobe.d/blacklist.conf 13 | sudo echo "blacklist rivafb" >> /etc/modprobe.d/blacklist.conf 14 | sudo echo "blacklist nvidiafb" >> /etc/modprobe.d/blacklist.conf 15 | sudo echo "blacklist rivatv" >> /etc/modprobe.d/blacklist.conf 16 | sudo update-initramfs -u 17 | echo "Now you need to reboot and run the next part." 18 | echo "Do after the reboot inside this directory : ./cuda9-part2-after-reboot.sh" -------------------------------------------------------------------------------- /INSTALL/cuda9-part2-after-reboot.sh: -------------------------------------------------------------------------------- 1 | sudo service lightdm stop 2 | sudo init 3 3 | sudo ./cuda_9.run -- override 4 | sudo ln -s /usr/bin/gcc-6 /usr/local/cuda/bin/gcc 5 | sudo ln -s /usr/bin/g++-6 /usr/local/cuda/bin/g++ 6 | nvidia-smi -------------------------------------------------------------------------------- /INSTALL/ffmpeg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "=============" 3 | echo "Install FFMPEG" 4 | echo "What build of FFMPEG do you require?" 5 | echo "If you don't know check your CPU specs for a hint." 6 | echo "- 32bit" 7 | echo "- 64bit" 8 | echo "- armel-32bit" 9 | echo "- armhf-32bit" 10 | read ffmpegbuild 11 | wget "https://s3.amazonaws.com/cloudcamio/ffmpeg-release-$ffmpegbuild-static.tar.xz" 12 | tar xf "ffmpeg-release-$ffmpegbuild-static.tar.xz" 13 | mv "ffmpeg-3.3-$ffmpegbuild-static/ffmpeg" "/usr/bin/ffmpeg" 14 | mv "ffmpeg-3.3-$ffmpegbuild-static/ffmpeg-10bit" "/usr/bin/ffmpeg-10bit" 15 | mv "ffmpeg-3.3-$ffmpegbuild-static/ffprobe" "/usr/bin/ffprobe" 16 | mv "ffmpeg-3.3-$ffmpegbuild-static/ffserver" "/usr/bin/ffserver" 17 | chmod +x /usr/bin/ffmpeg 18 | chmod +x /usr/bin/ffmpeg-10bit 19 | chmod +x /usr/bin/ffprobe 20 | chmod +x /usr/bin/ffserver 21 | rm -rf "ffmpeg-3.3-$ffmpegbuild-static" 22 | rm -rf "ffmpeg-release-$ffmpegbuild-static.tar.xz" 23 | -------------------------------------------------------------------------------- /INSTALL/freebsd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/tcsh 2 | echo "=========================================================" 3 | echo "==== Shinobi : The Open Source CCTV and NVR Solution ====" 4 | echo "=========================================================" 5 | echo "This script should run as root inside your jail from the root" 6 | echo "of the cloned git repository." 7 | echo "To answer yes type the letter (y) in lowercase and press ENTER." 8 | echo "Default is no (N). Skip any components you already have or don't need." 9 | echo "=============" 10 | echo "Shinobi - Do you want to Install Node.js?" 11 | echo "(y)es or (N)o" 12 | set nodejsinstall = $< 13 | if ( $nodejsinstall == "y" ) then 14 | pkg install -y node8 npm-node8 15 | endif 16 | echo "=============" 17 | echo "Shinobi - Do you want to Install FFMPEG?" 18 | echo "(y)es or (N)o" 19 | set ffmpeginstall = $< 20 | if ( $ffmpeginstall == "y" ) then 21 | pkg install -y ffmpeg libav x264 x265 22 | endif 23 | echo "=============" 24 | echo "Shinobi - Database Installation" 25 | echo "WARNING - This requires an existing and running mariadb service." 26 | echo "(y)es or (N)o" 27 | set mysqlagreeData = $< 28 | if ( $mysqlagreeData == "y" ) then 29 | echo "What is your SQL Username?" 30 | set sqluser = $< 31 | echo "What is your SQL Password?" 32 | set sqlpass = $< 33 | echo "What is your SQL Host?" 34 | set sqlhost = $< 35 | echo "Installing mariadb client..." 36 | pkg install -y mariadb102-client 37 | echo "Installing database schema..." 38 | mysql -h $sqlhost -u $sqluser -p$sqlpass -e "source sql/user.sql" || true 39 | mysql -h $sqlhost -u $sqluser -p$sqlpass -e "source sql/framework.sql" || true 40 | echo "Shinobi - Use the /super endpoint to create your super user." 41 | endif 42 | echo "=============" 43 | echo "Shinobi - Install NPM Libraries" 44 | npm install 45 | echo "=============" 46 | echo "Shinobi - Install PM2" 47 | npm install pm2 -g 48 | if (! -e "./conf.json" ) then 49 | cp conf.sample.json conf.json 50 | endif 51 | if (! -e "./super.json" ) then 52 | echo "Default Superuser : admin@shinobi.video" 53 | echo "Default Password : admin" 54 | cp super.sample.json super.json 55 | endif 56 | echo "Shinobi - Start Shinobi?" 57 | echo "(y)es or (N)o" 58 | set startShinobi = $< 59 | if ( $startShinobi == "y" ) then 60 | set PM2BIN="$PWD/node_modules/pm2/bin" 61 | $PM2BIN/pm2 start camera.js 62 | $PM2BIN/pm2 start cron.js 63 | $PM2BIN/pm2 save 64 | $PM2BIN/pm2 list 65 | endif 66 | echo "Shinobi - Start on boot?" 67 | echo "(y)es or (N)o" 68 | set startupShinobi = $< 69 | if ( $startupShinobi == "y" ) then 70 | set PM2BIN="$PWD/node_modules/pm2/bin" 71 | $PM2BIN/pm2 startup rcd 72 | endif 73 | echo "Shinobi - Finished" 74 | -------------------------------------------------------------------------------- /INSTALL/installDatabase.js: -------------------------------------------------------------------------------- 1 | var knex = require('knex'); 2 | if(config.databaseType===undefined){config.databaseType='mysql'} 3 | 4 | var databaseOptions = { 5 | client: config.databaseType, 6 | connection: config.db, 7 | } 8 | if(databaseOptions.client.indexOf('sqlite')>-1){ 9 | databaseOptions.client = 'sqlite3'; 10 | databaseOptions.useNullAsDefault = true; 11 | } 12 | if(databaseOptions.client === 'sqlite3' && databaseOptions.connection.filename === undefined){ 13 | databaseOptions.connection.filename = __dirname+"/shinobi.sqlite" 14 | } 15 | s.databaseEngine = knex(databaseOptions) 16 | s.sqlQuery = function(query,values,onMoveOn,hideLog){ 17 | if(!values){values=[]} 18 | if(typeof values === 'function'){ 19 | var onMoveOn = values; 20 | var values = []; 21 | } 22 | if(!onMoveOn){onMoveOn=function(){}} 23 | return s.databaseEngine.raw(query,values) 24 | .asCallback(function(err,r){ 25 | if(err&&config.databaseLogs){ 26 | s.systemLog('s.sqlQuery QUERY',query) 27 | s.systemLog('s.sqlQuery ERROR',err) 28 | } 29 | if(onMoveOn) 30 | if(typeof onMoveOn === 'function'){ 31 | if(!r)r=[] 32 | onMoveOn(err,r) 33 | }else{ 34 | console.log(onMoveOn) 35 | } 36 | }) 37 | } -------------------------------------------------------------------------------- /INSTALL/macos-part2.sh: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | echo "=========================================================" 4 | echo "==!! Shinobi : The Open Source CCTV and NVR Solution !!==" 5 | echo "=================== Mac OS Install Part 2 ===============" 6 | echo "=========================================================" 7 | echo "Shinobi - Database Installation" 8 | echo "(y)es or (N)o" 9 | read mysqlagreeData 10 | if [ "$mysqlagreeData" = "y" ]; then 11 | echo "Shinobi - Use root for database installation?" 12 | echo "(y)es or (N)o" 13 | echo "What is your SQL Username?" 14 | read sqluser 15 | echo "What is your SQL Password?" 16 | read sqlpass 17 | echo "You may now be asked for your Administator (root for Mac OS, not MySQL) password" 18 | sudo mysql -u $sqluser -p$sqlpass -e "source sql/user.sql" || true 19 | sudo mysql -u $sqluser -p$sqlpass -e "source sql/framework.sql" || true 20 | echo "Shinobi - Do you want to create a new user for viewing and managing cameras in Shinobi? You can do this later in the Superuser panel." 21 | echo "(y)es or (N)o" 22 | read mysqlDefaultData 23 | if [ "$mysqlDefaultData" = "y" ]; then 24 | escapeReplaceQuote='\\"' 25 | groupKey=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 7 | head -n 1) 26 | userID=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 6 | head -n 1) 27 | userEmail=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 6 | head -n 1)"@"$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 6 | head -n 1)".com" 28 | userPasswordPlain=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 6 | head -n 1) 29 | userPasswordMD5=$(echo -n "$userPasswordPlain" | md5sum | awk '{print $1}') 30 | userDetails='{"days":"10"}' 31 | userDetails=$(echo "$userDetails" | sed -e 's/"/'$escapeReplaceQuote'/g') 32 | echo $userDetailsNew 33 | apiIP='0.0.0.0' 34 | apiKey=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) 35 | apiDetails='{"auth_socket":"1","get_monitors":"1","control_monitors":"1","get_logs":"1","watch_stream":"1","watch_snapshot":"1","watch_videos":"1","delete_videos":"1"}' 36 | apiDetails=$(echo "$apiDetails" | sed -e 's/"/'$escapeReplaceQuote'/g') 37 | rm sql/default_user.sql || true 38 | echo "USE ccio;INSERT INTO Users (\`ke\`,\`uid\`,\`auth\`,\`mail\`,\`pass\`,\`details\`) VALUES (\"$groupKey\",\"$userID\",\"$apiKey\",\"$userEmail\",\"$userPasswordMD5\",\"$userDetails\");INSERT INTO API (\`code\`,\`ke\`,\`uid\`,\`ip\`,\`details\`) VALUES (\"$apiKey\",\"$groupKey\",\"$userID\",\"$apiIP\",\"$apiDetails\");" > "sql/default_user.sql" 39 | sudo mysql -u $sqluser -p$sqlpass --database ccio -e "source sql/default_user.sql" > "INSTALL/log.txt" 40 | echo "The following details will be shown again at the end of the installation." 41 | echo "=====================================" 42 | echo "======= Login Credentials =======" 43 | echo "|| Username : $userEmail" 44 | echo "|| Password : $userPasswordPlain" 45 | echo "|| API Key : $apiKey" 46 | echo "=====================================" 47 | echo "=====================================" 48 | echo "** To change these settings login to either to the Superuser panel or login to the dashboard as the user that was just created and open the Settings window. **" 49 | fi 50 | fi 51 | echo "=============" 52 | echo "Shinobi - Install NPM Libraries" 53 | sudo npm install 54 | echo "=============" 55 | echo "Shinobi - Install PM2" 56 | sudo npm install pm2 -g 57 | if [ ! -e "./conf.json" ]; then 58 | sudo cp conf.sample.json conf.json 59 | fi 60 | if [ ! -e "./super.json" ]; then 61 | echo "Default Superuser : admin@shinobi.video" 62 | echo "Default Password : admin" 63 | sudo cp super.sample.json super.json 64 | fi 65 | echo "Shinobi - Finished" 66 | touch INSTALL/installed.txt 67 | sudo chmod -R 755 . 68 | echo "=====================================" > INSTALL/installed.txt 69 | echo "======= Login Credentials =======" >> INSTALL/installed.txt 70 | echo "|| Username : $userEmail" >> INSTALL/installed.txt 71 | echo "|| Password : $userPasswordPlain" >> INSTALL/installed.txt 72 | echo "|| API Key : $apiKey" >> INSTALL/installed.txt 73 | echo "=====================================" >> INSTALL/installed.txt 74 | echo "=====================================" >> INSTALL/installed.txt 75 | echo "Shinobi - Start Shinobi and set to start on boot?" 76 | echo "(y)es or (N)o" 77 | read startShinobi 78 | if [ "$startShinobi" = "y" ]; then 79 | sudo pm2 start camera.js 80 | sudo pm2 start cron.js 81 | sudo pm2 startup 82 | sudo pm2 save 83 | sudo pm2 list 84 | fi 85 | echo "details written to INSTALL/installed.txt" 86 | echo "=====================================" 87 | echo "======= Login Credentials =======" 88 | echo "|| Username : $userEmail" 89 | echo "|| Password : $userPasswordPlain" 90 | echo "|| API Key : $apiKey" 91 | echo "=====================================" 92 | echo "=====================================" -------------------------------------------------------------------------------- /INSTALL/macos.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "=========================================================" 3 | echo "==!! Shinobi : The Open Source CCTV and NVR Solution !!==" 4 | echo "=================== Mac OS Install Part 1 ===============" 5 | echo "=========================================================" 6 | echo "To answer yes type the letter (y) in lowercase and press ENTER." 7 | echo "Default is no (N). Skip any components you already have or don't need." 8 | echo "=============" 9 | echo "Shinobi - Do you want to Install Node.js?" 10 | echo "(y)es or (N)o" 11 | read nodejsinstall 12 | if [ "$nodejsinstall" = "y" ]; then 13 | curl -o node-v8.9.3.pkg https://nodejs.org/dist/v8.9.3/node-v8.9.3.pkg 14 | sudo installer -pkg node-v8.9.3.pkg -target / 15 | rm node-v8.9.3.pkg 16 | sudo ln -s /usr/local/bin/node /usr/bin/nodejs 17 | fi 18 | echo "=============" 19 | echo "Shinobi - Do you want to Install FFmpeg?" 20 | echo "(y)es or (N)o" 21 | read ffmpeginstall 22 | if [ "$ffmpeginstall" = "y" ]; then 23 | echo "Shinobi - Installing FFmpeg" 24 | curl -o ffmpeg.zip https://cdn.shinobi.video/installers/ffmpeg-3.4.1-macos.zip 25 | sudo unzip ffmpeg.zip 26 | sudo rm ffmpeg.zip 27 | sudo mv ffmpeg-3.4.1-macos/ffmpeg /usr/bin/ffmpeg 28 | sudo mv ffmpeg-3.4.1-macos/ffplay /usr/bin/ffplay 29 | sudo mv ffmpeg-3.4.1-macos/ffprobe /usr/bin/ffprobe 30 | sudo mv ffmpeg-3.4.1-macos/ffserver /usr/bin/ffserver 31 | sudo chmod +x /usr/bin/ffmpeg 32 | sudo chmod +x /usr/bin/ffplay 33 | sudo chmod +x /usr/bin/ffprobe 34 | sudo chmod +x /usr/bin/ffserver 35 | fi 36 | echo "=============" 37 | echo "Shinobi - Do you want to Install MySQL? Choose No if you have MySQL or MySQL already." 38 | echo "(y)es or (N)o" 39 | read mysqlagree 40 | if [ "$mysqlagree" = "y" ]; then 41 | echo "Shinobi - Installing MySQL" 42 | bash <(curl -Ls http://git.io/eUx7rg) 43 | fi 44 | echo "=============" 45 | echo "=============" 46 | echo "You must now close this terminal window and reopen it." 47 | echo "Reopen the Shinobi folder and run" 48 | echo "chmod +x INSTALL/macos-part2.sh && INSTALL/macos-part2.sh" 49 | echo "=============" 50 | echo "=============" -------------------------------------------------------------------------------- /INSTALL/now.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Shinobi Installer" 3 | echo "========" 4 | echo "Select your OS" 5 | echo "If your OS is not on the list please refer to the docs." 6 | echo "========" 7 | echo "1. Ubuntu" 8 | echo "2. CentOS" 9 | echo "3. MacOS" 10 | echo "========" 11 | read oschoicee 12 | case $oschoicee in 13 | "1") 14 | chmod +x INSTALL/ubuntu.sh 15 | sh INSTALL/ubuntu.sh 16 | ;; 17 | "2") 18 | chmod +x INSTALL/centos.sh 19 | INSTALL/centos.sh 20 | ;; 21 | "3") 22 | chmod +x INSTALL/macos.sh 23 | INSTALL/macos.sh 24 | ;; 25 | *) 26 | echo "Choice not found." 27 | ;; 28 | esac -------------------------------------------------------------------------------- /INSTALL/openalpr-gpu-easy.sh: -------------------------------------------------------------------------------- 1 | # Install prerequisites 2 | # this includes all the ones missing from OpenALPR's guide. 3 | sudo apt install libopencv-dev libtesseract-dev git cmake build-essential libleptonica-dev -y 4 | sudo apt install liblog4cplus-dev libcurl3-dev -y 5 | sudo apt install libleptonica-dev -y 6 | sudo apt install libcurl4-openssl-dev -y 7 | sudo apt install liblog4cplus-dev -y 8 | sudo apt install beanstalkd -y 9 | sudo apt install openjdk-8-jdk -y 10 | 11 | # Clone the latest code from GitHub 12 | git clone https://github.com/openalpr/openalpr.git 13 | 14 | # Setup the build directory 15 | cd openalpr/src 16 | mkdir build 17 | cd build 18 | 19 | # setup the compile environment 20 | cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_INSTALL_SYSCONFDIR:PATH=/etc –DCOMPILE_GPU=1 .. 21 | 22 | # compile the library 23 | make 24 | 25 | # Install the binaries/libraries to your local system (prefix is /usr) 26 | sudo make install 27 | 28 | # Test the library 29 | wget http://plates.openalpr.com/h786poj.jpg -O lp.jpg 30 | alpr lp.jpg -------------------------------------------------------------------------------- /INSTALL/opencv-cuda.sh: -------------------------------------------------------------------------------- 1 | # OpenCV CUDA 2 | 3 | wget -O opencv.zip https://github.com/opencv/opencv/archive/3.4.0.zip 4 | wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/3.4.0.zip 5 | sudo apt-get install unzip -y 6 | 7 | sudo unzip opencv.zip -d tempOpenCV 8 | sudo unzip opencv_contrib.zip -d tempOpenCVContrib 9 | 10 | sudo mv tempOpenCV/opencv-3.4.0 opencv 11 | sudo mv tempOpenCVContrib/opencv_contrib-3.4.0 opencv_contrib 12 | sudo rm -rf tempOpenCV 13 | sudo rm -rf tempOpenCVContrib 14 | 15 | sudo apt install build-essential cmake git pkg-config unzip ffmpeg qtbase5-dev python-dev python3-dev python-numpy python3-numpy libhdf5-dev libgtk-3-dev libdc1394-22 libdc1394-22-dev libjpeg-dev libtiff5-dev libtesseract-dev -y 16 | 17 | sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu zesty-security main" 18 | sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main" 19 | sudo apt update 20 | sudo apt install libjasper1 libjasper-dev libavcodec-dev libavformat-dev libswscale-dev libxine2-dev libgstreamer-plugins-base1.0-0 libgstreamer-plugins-base1.0-dev libpng16-16 libpng-dev libv4l-dev libtbb-dev libfaac-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev v4l-utils -y 21 | 22 | cd opencv 23 | mkdir release 24 | cd release 25 | 26 | cmake -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_NVCUVID=ON -D FORCE_VTK=ON -D BUILD_DOCS=ON -D WITH_XINE=ON -D WITH_CUDA=ON -D WITH_OPENGL=ON -D WITH_TBB=ON -D BUILD_EXAMPLES=ON -D WITH_OPENCL=ON -D CMAKE_BUILD_TYPE=RELEASE -D CUDA_NVCC_FLAGS="-D_FORCE_INLINES --expt-relaxed-constexpr" -D WITH_GDAL=ON -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules/ -D ENABLE_FAST_MATH=1 -D CUDA_FAST_MATH=1 -D WITH_CUBLAS=1 .. 27 | 28 | make -j4 29 | sudo make install -------------------------------------------------------------------------------- /INSTALL/shinobi.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=ShinobiCCTV 3 | 4 | [Service] 5 | WorkingDirectory=/home/Shinobi 6 | Type=forking 7 | ExecStart=/bin/bash INSTALL/start.sh 8 | KillMode=process 9 | 10 | [Install] 11 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /INSTALL/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ -e "INSTALL/installed.txt" ]; then 3 | echo "Starting Shinobi" 4 | pm2 start camera.js 5 | pm2 start cron.js 6 | fi 7 | if [ ! -e "INSTALL/installed.txt" ]; then 8 | chmod +x INSTALL/now.sh&&INSTALL/now.sh 9 | fi -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This software is licensed under the GPLv3 and AGPLv3 2 | 3 | GPLv3 : https://www.gnu.org/licenses/gpl-3.0.en.html 4 | AGPLv3 : https://www.gnu.org/licenses/agpl-3.0.en.html -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # We moved to GitLab! 2 | ## https://gitlab.com/Shinobi-Systems/Shinobi 3 | -------------------------------------------------------------------------------- /UPDATE.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | distro=$1 3 | if [ -z ${distro+x} ]; then 4 | distro='master' 5 | fi 6 | rm -rf $distro master_temp 7 | wget https://github.com/ShinobiCCTV/Shinobi/tarball/$distro 8 | mkdir master_temp 9 | tar -xzf $distro -C master_temp --strip-components=1 10 | rm -rf camera.js web UPDATE.sh package.json cron.js languages LICENSE COPYING 11 | pm2 stop camera.js 12 | pm2 stop cron.js 13 | pm2 kill 14 | mv master_temp/UPDATE.sh UPDATE.sh 15 | chmod +x UPDATE.sh 16 | sed -i 's/\r//' UPDATE.sh 17 | mv master_temp/languages languages 18 | mv master_temp/definitions definitions 19 | mv master_temp/web web 20 | mv master_temp/LICENSE LICENSE 21 | mv master_temp/COPYING COPYING 22 | mv master_temp/package.json package.json 23 | mv master_temp/camera.js camera.js 24 | mv master_temp/cron.js cron.js 25 | mv master_temp/plugins/motion/shinobi-motion.js plugins/motion/shinobi-motion.js 26 | mv master_temp/plugins/opencv/shinobi-opencv.js plugins/motion/shinobi-opencv.js 27 | npm install 28 | rm -rf $distro master_temp 29 | pm2 start camera.js 30 | pm2 start cron.js 31 | if [ ! -f plugins/motion/conf.json ]; then 32 | pm2 start plugins/motion/shinobi-motion.js 33 | fi -------------------------------------------------------------------------------- /conf.sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "port": 8080, 3 | "addStorage": [ 4 | {"name":"second","path":"__DIR__/videos2"} 5 | ], 6 | "db": { 7 | "host": "127.0.0.1", 8 | "user": "majesticflame", 9 | "password": "", 10 | "database": "ccio", 11 | "port":3306 12 | }, 13 | "mail":{ 14 | "service": "gmail", 15 | "auth": { 16 | "user": "your_email@gmail.com", 17 | "pass": "your_password_or_app_specific_password" 18 | } 19 | }, 20 | "cron":{ 21 | "key":"change_this_to_something_very_random__just_anything_other_than_this" 22 | }, 23 | "pluginKeys":{ 24 | "Motion":"change_this_to_something_very_random____make_sure_to_match__/plugins/motion/conf.json", 25 | "OpenCV":"change_this_to_something_very_random____make_sure_to_match__/plugins/opencv/conf.json", 26 | "OpenALPR":"SomeOpenALPRkeySoPeopleDontMessWithYourShinobi" 27 | } 28 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shinobi", 3 | "version": "1.0.37", 4 | "description": "CCTV and NVR in Node.js, Version : daf882caf6053a7c2c8f4e69427620356f8a440c", 5 | "main": "camera.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "chmod +x INSTALL/start.sh && INSTALL/start.sh" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/moeiscool/Shinobi.git" 13 | }, 14 | "author": "Moe Alam", 15 | "license": "GPLv3", 16 | "bugs": { 17 | "url": "https://github.com/ShinobiCCTV/Shinobi/issues" 18 | }, 19 | "homepage": "https://github.com/moeiscool/Shinobi#readme", 20 | "dependencies": { 21 | "body-parser": "^1.15.2", 22 | "circular-json": "0.3.1", 23 | "connection-tester": "^0.1.1", 24 | "crypto": "^0.0.3", 25 | "mp4frag": "^0.0.15", 26 | "ejs": "^2.5.5", 27 | "express": "^4.14.0", 28 | "jsonfile": "^3.0.1", 29 | "moment": "^2.17.0", 30 | "mysql": "^2.12.0", 31 | "sqlite3": "^3.1.13", 32 | "knex": "^0.14.2", 33 | "ffmpeg-static": "^2.1.0", 34 | "pam-diff": "0.10.2", 35 | "pipe2pam": "0.6.2", 36 | "nodemailer": "^4.0.1", 37 | "onvif": "^0.5.3", 38 | "path": "^0.12.7", 39 | "request": "^2.79.0", 40 | "socket.io": "^1.7.1", 41 | "socket.io-client": "^1.7.2", 42 | "webdav": "^0.3.1", 43 | "ldapauth-fork": "^4.0.2" 44 | }, 45 | "devDependencies": {} 46 | } 47 | -------------------------------------------------------------------------------- /plugins/.gitignore: -------------------------------------------------------------------------------- 1 | opencv-python 2 | ccv 3 | stemkoski 4 | variantai -------------------------------------------------------------------------------- /plugins/child/.gitignore: -------------------------------------------------------------------------------- 1 | conf.json 2 | events 3 | frames -------------------------------------------------------------------------------- /plugins/child/conf.child.sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"Macbook", 3 | "ws":"66.51.132.100", 4 | "key":"3123asdasdf1dtj1hjk23sdfaasd12asdasddfdbtnkkfgvesra3asdsd3123afdsfqw345", 5 | } -------------------------------------------------------------------------------- /plugins/child/conf.json.default: -------------------------------------------------------------------------------- 1 | {"host":"127.0.0.1","user":"root","password":"","database":"ccio"} -------------------------------------------------------------------------------- /plugins/microsoft/conf.sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "plug":"ComputerVision", 3 | "host":"localhost", 4 | "port":8080, 5 | "key":"UNIQUE KEY HERE", 6 | "computerVision":{ 7 | "apiKey":"YOUR_KEY", 8 | "endpoint":"http://YOUR_ENDPOINT/analyze", 9 | "params":{ 10 | "visualFeatures": "Categories,Description,Color", 11 | "details": "", 12 | "language": "en" 13 | } 14 | }, 15 | "EmotionAPI":{ 16 | "apiKey":"YOUR_KEY", 17 | "endpoint":"http://YOUR_ENDPOINT/recognize", 18 | "params":{} 19 | }, 20 | "FaceAPI":{ 21 | "apiKey":"YOUR_KEY", 22 | "endpoint":"http://YOUR_ENDPOINT/detect", 23 | "params":{ 24 | "returnFaceId": "true", 25 | "returnFaceLandmarks": "false", 26 | "returnFaceAttributes": "age,gender,headPose,smile,facialHair,glasses,emotion,hair,makeup,occlusion,accessories,blur,exposure,noise" 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /plugins/microsoft/shinobi-ms-vision.js: -------------------------------------------------------------------------------- 1 | // 2 | // Shinobi - Microsoft Computer Vision Plugin 3 | // Copyright (C) 2016-2025 Moe Alam, moeiscool 4 | // 5 | process.on('uncaughtException', function (err) { 6 | console.error('uncaughtException',err); 7 | }); 8 | var fs=require('fs'); 9 | var exec = require('child_process').exec; 10 | //var http = require('http'); 11 | var request = require('request'); 12 | var moment = require('moment'); 13 | var cognitive = require('cognitive-services'); 14 | var config=require('./conf.json'); 15 | if(config.systemLog===undefined){config.systemLog=true} 16 | s={ 17 | group:{}, 18 | dir:{ 19 | cascades:__dirname+'/cascades/' 20 | }, 21 | isWin:(process.platform==='win32') 22 | } 23 | //default stream folder check 24 | if(!config.streamDir){ 25 | if(s.isWin===false){ 26 | config.streamDir='/dev/shm' 27 | }else{ 28 | config.streamDir=config.windowsTempDir 29 | } 30 | if(!fs.existsSync(config.streamDir)){ 31 | config.streamDir=__dirname+'/streams/' 32 | }else{ 33 | config.streamDir+='/streams/' 34 | } 35 | } 36 | s.dir.streams=config.streamDir; 37 | //streams dir 38 | if(!fs.existsSync(s.dir.streams)){ 39 | fs.mkdirSync(s.dir.streams); 40 | } 41 | s.gid=function(x){ 42 | if(!x){x=10};var t = "";var p = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 43 | for( var i=0; i < x; i++ ) 44 | t += p.charAt(Math.floor(Math.random() * p.length)); 45 | return t; 46 | }; 47 | s.systemLog=function(q,w,e){ 48 | if(!w){w=''} 49 | if(!e){e=''} 50 | if(config.systemLog===true){ 51 | return console.log(moment().format(),q,w,e) 52 | } 53 | } 54 | s.objectToParameter = function(obj){ 55 | return Object.keys(obj).map(function(key) { 56 | return key + '=' + encodeURIComponent(obj[key]); 57 | }).join('&'); 58 | } 59 | s.sendImageToMS=function(sourceImageUrl,API,callback){ 60 | var URL = API.endpoint+'?'+s.objectToParameter(API.params) 61 | request(URL,{ 62 | method: 'POST', 63 | headers:{ 64 | "Ocp-Apim-Subscription-Key":API.apiKey 65 | }, 66 | json: { 67 | url:sourceImageUrl 68 | } 69 | }, callback) 70 | } 71 | s.detectObject=function(buffer,d){ 72 | var sourceImageUrl = 'http://184.105.6.43/'+s.api_key+'/jpeg/'+d.ke+'/'+d.id+'/s.jpg' 73 | // const client = new cognitive.computerVision({ 74 | // apiKey: config.computerVision.apiKey, 75 | // endpoint: config.computerVision.endpoint 76 | // }); 77 | // const parameters = { 78 | // "visualFeatures": "Categories,Tags,Description", 79 | // "details": "Celebrities,Landmarks" 80 | // }; 81 | // const headers = { 82 | // 'Content-type': 'application/json' 83 | // }; 84 | // const body = { 85 | // "url": sourceImageUrl 86 | // }; 87 | // 88 | // client.analyzeImage({ 89 | // parameters, 90 | // headers, 91 | // body 92 | // }).then((response) => { 93 | //// should(response).not.be.undefined(); 94 | //// should(response).have.properties(["categories", "metadata", "requestId"]); 95 | // console.log(response) 96 | // }).catch((err) => { 97 | // console.log('Error',err) 98 | // }); 99 | var responses = {} 100 | s.sendImageToMS(sourceImageUrl,config.computerVision,function(err,resp,body1){ 101 | responses.computerVisionURL = body1 102 | s.sendImageToMS(sourceImageUrl,config.FaceAPI,function(err,resp,body2){ 103 | responses.faceApiURL = body2 104 | s.sendImageToMS(sourceImageUrl,config.EmotionAPI,function(err,resp,body3){ 105 | responses.EmotionAPI = body3 106 | console.log('responses',JSON.stringify(responses,null,3)) 107 | }) 108 | }) 109 | }) 110 | } 111 | s.makeMonitorObject=function(d){ 112 | if(!s.group[d.ke]){ 113 | s.group[d.ke]={} 114 | } 115 | if(!s.group[d.ke][d.id]){ 116 | s.group[d.ke][d.id]={ 117 | port:null, 118 | countStarted:new Date() 119 | } 120 | } 121 | } 122 | io = require('socket.io-client')('ws://'+config.host+':'+config.port);//connect to master 123 | s.cx=function(x){x.pluginKey=config.key;x.plug=config.plug;return io.emit('ocv',x)} 124 | io.on('connect',function(d){ 125 | s.cx({f:'init',plug:config.plug}); 126 | }) 127 | io.on('disconnect',function(d){ 128 | io.connect() 129 | }) 130 | io.on('f',function(d){ 131 | switch(d.f){ 132 | case'api_key': 133 | s.api_key=d.key 134 | break; 135 | case'init_monitor': 136 | if(s.group[d.ke]&&s.group[d.ke][d.id]){ 137 | s.group[d.ke][d.id].buffer=null 138 | s.group[d.ke][d.id].countStarted=new Date() 139 | } 140 | s.makeMonitorObject(d) 141 | break; 142 | case'frame': 143 | d.details={} 144 | try{ 145 | s.makeMonitorObject(d) 146 | if(!s.group[d.ke][d.id].buffer){ 147 | s.group[d.ke][d.id].buffer=[d.frame]; 148 | }else{ 149 | s.group[d.ke][d.id].buffer.push(d.frame) 150 | } 151 | if(d.frame[d.frame.length-2] === 0xFF && d.frame[d.frame.length-1] === 0xD9){ 152 | if(d.mon.detector_frame_save==="1"){ 153 | d.base64=s.group[d.ke][d.id].buffer.toString('base64') 154 | } 155 | if(d.mon.detector_scale_x&&d.mon.detector_scale_x!==''&&d.mon.detector_scale_y&&d.mon.detector_scale_y!==''){ 156 | d.width=d.mon.detector_scale_x; 157 | d.height=d.mon.detector_scale_y; 158 | }else{ 159 | d.width=640 160 | d.height=480 161 | } 162 | s.detectObject(Buffer.concat(s.group[d.ke][d.id].buffer),d) 163 | s.group[d.ke][d.id].buffer=null; 164 | } 165 | } catch(err){ 166 | console.error(err) 167 | } 168 | break; 169 | } 170 | }) -------------------------------------------------------------------------------- /plugins/motion/.gitignore: -------------------------------------------------------------------------------- 1 | conf.json 2 | -------------------------------------------------------------------------------- /plugins/motion/INSTALL.sh: -------------------------------------------------------------------------------- 1 | apt-get install libcairo2-dev libjpeg-dev libpango1.0-dev libgif-dev build-essential g++ 2 | npm install canvas 3 | cd plugins/motion 4 | cp conf.sample.json conf.json 5 | pm2 start shinobi-motion.js -------------------------------------------------------------------------------- /plugins/motion/README.md: -------------------------------------------------------------------------------- 1 | # Shinobi Motion Detector 2 | 3 | Install required libraries. 4 | 5 | **Ubuntu and Debian only** 6 | 7 | ``` 8 | sudo apt-get install libcairo2-dev libjpeg-dev libpango1.0-dev libgif-dev build-essential g++ 9 | ``` 10 | 11 | **CentOS only** 12 | 13 | ``` 14 | su -c 'yum install cairo cairo-devel cairomm-devel libjpeg-turbo-devel pango pango-devel pangomm pangomm-devel giflib-devel' 15 | yum search arial 16 | yum install liberation-sans-fonts.noarch 17 | ``` 18 | 19 | **Install the Node.js Canvas engine** 20 | 21 | ``` 22 | sudo npm install canvas 23 | ``` 24 | 25 | Go to the Shinobi directory. **Below is an example.** 26 | 27 | ``` 28 | cd /home/Shinobi 29 | ``` 30 | 31 | Copy the config file. 32 | 33 | ``` 34 | cp plugins/motion/conf.sample.json plugins/motion/conf.json 35 | ``` 36 | 37 | Edit it the new file. Host should be `localhost` and port should match the `listening port for camera.js`. 38 | 39 | ``` 40 | nano plugins/motion/conf.json 41 | ``` 42 | 43 | Start the plugin. 44 | 45 | ``` 46 | node plugins/motion/shinobi-motion.js 47 | ``` 48 | 49 | Or to daemonize with PM2. 50 | 51 | ``` 52 | pm2 start plugins/motion/shinobi-motion.js 53 | ``` 54 | 55 | Doing this will reveal options in the monitor configuration. Shinobi does not need to be restarted when a plugin is initiated or stopped. 56 | 57 | -------------------------------------------------------------------------------- /plugins/motion/conf.sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "plug":"Motion", 3 | "host":"localhost", 4 | "port":8080, 5 | "key":"change_this_to_something_very_random____make_sure_to_match__/plugins/motion/conf.json", 6 | "notice":"Looks like you have the Motion plugin running. Don't forget to enable Send Frames to start pushing frames to be read." 7 | } -------------------------------------------------------------------------------- /plugins/motion/libs/clusterPoints.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = { 4 | 5 | data: getterSetter([], function(arrayOfArrays) { 6 | var n = arrayOfArrays[0].length; 7 | return (arrayOfArrays.map(function(array) { 8 | return array.length == n; 9 | }).reduce(function(boolA, boolB) { return (boolA & boolB) }, true)); 10 | }), 11 | 12 | clusters: function() { 13 | var pointsAndCentroids = kmeans(this.data(), {k: this.k(), iterations: this.iterations() }); 14 | var points = pointsAndCentroids.points; 15 | var centroids = pointsAndCentroids.centroids; 16 | 17 | return centroids.map(function(centroid) { 18 | return { 19 | centroid: centroid.location(), 20 | points: points.filter(function(point) { return point.label() == centroid.label() }).map(function(point) { return point.location() }), 21 | }; 22 | }); 23 | }, 24 | 25 | k: getterSetter(undefined, function(value) { return ((value % 1 == 0) & (value > 0)) }), 26 | 27 | iterations: getterSetter(Math.pow(10, 3), function(value) { return ((value % 1 == 0) & (value > 0)) }), 28 | 29 | }; 30 | 31 | function kmeans(data, config) { 32 | // default k 33 | var k = config.k || Math.round(Math.sqrt(data.length / 2)); 34 | var iterations = config.iterations; 35 | 36 | // initialize point objects with data 37 | var points = data.map(function(vector) { return new Point(vector) }); 38 | 39 | // intialize centroids randomly 40 | var centroids = []; 41 | for (var i = 0; i < k; i++) { 42 | centroids.push(new Centroid(points[i % points.length].location(), i)); 43 | }; 44 | 45 | // update labels and centroid locations until convergence 46 | for (var iter = 0; iter < iterations; iter++) { 47 | points.forEach(function(point) { point.updateLabel(centroids) }); 48 | centroids.forEach(function(centroid) { centroid.updateLocation(points) }); 49 | }; 50 | 51 | // return points and centroids 52 | return { 53 | points: points, 54 | centroids: centroids 55 | }; 56 | 57 | }; 58 | 59 | // objects 60 | function Point(location) { 61 | var self = this; 62 | this.location = getterSetter(location); 63 | this.label = getterSetter(); 64 | this.updateLabel = function(centroids) { 65 | var distancesSquared = centroids.map(function(centroid) { 66 | return sumOfSquareDiffs(self.location(), centroid.location()); 67 | }); 68 | self.label(mindex(distancesSquared)); 69 | }; 70 | }; 71 | 72 | function Centroid(initialLocation, label) { 73 | var self = this; 74 | this.location = getterSetter(initialLocation); 75 | this.label = getterSetter(label); 76 | this.updateLocation = function(points) { 77 | var pointsWithThisCentroid = points.filter(function(point) { return point.label() == self.label() }); 78 | if (pointsWithThisCentroid.length > 0) self.location(averageLocation(pointsWithThisCentroid)); 79 | }; 80 | }; 81 | 82 | // convenience functions 83 | function getterSetter(initialValue, validator) { 84 | var thingToGetSet = initialValue; 85 | var isValid = validator || function(val) { return true }; 86 | return function(newValue) { 87 | if (typeof newValue === 'undefined') return thingToGetSet; 88 | if (isValid(newValue)) thingToGetSet = newValue; 89 | }; 90 | }; 91 | 92 | function sumOfSquareDiffs(oneVector, anotherVector) { 93 | var squareDiffs = oneVector.map(function(component, i) { 94 | return Math.pow(component - anotherVector[i], 2); 95 | }); 96 | return squareDiffs.reduce(function(a, b) { return a + b }, 0); 97 | }; 98 | 99 | function mindex(array) { 100 | var min = array.reduce(function(a, b) { 101 | return Math.min(a, b); 102 | }); 103 | return array.indexOf(min); 104 | }; 105 | 106 | function sumVectors(a, b) { 107 | return a.map(function(val, i) { return val + b[i] }); 108 | }; 109 | 110 | function averageLocation(points) { 111 | var zeroVector = points[0].location().map(function() { return 0 }); 112 | var locations = points.map(function(point) { return point.location() }); 113 | var vectorSum = locations.reduce(function(a, b) { return sumVectors(a, b) }, zeroVector); 114 | return vectorSum.map(function(val) { return val / points.length }); 115 | }; 116 | -------------------------------------------------------------------------------- /plugins/openalpr/.gitignore: -------------------------------------------------------------------------------- 1 | conf.json 2 | cascades -------------------------------------------------------------------------------- /plugins/openalpr/README.md: -------------------------------------------------------------------------------- 1 | # OpenALPR and Motion Detector 2 | 3 | Install required libraries. 4 | 5 | **Ubuntu and Debian only** 6 | 7 | ``` 8 | sudo apt update && sudo apt install libcairo2-dev libjpeg-dev libpango1.0-dev libgif-dev build-essential g++ openalpr openalpr-daemon openalpr-utils libopenalpr-dev -y 9 | ``` 10 | 11 | **Install the Node.js Canvas engine** 12 | 13 | ``` 14 | sudo npm install canvas@1.6 15 | ``` 16 | Go to the Shinobi directory. **Below is an example.** 17 | 18 | ``` 19 | cd /home/Shinobi 20 | ``` 21 | 22 | Copy the config file. 23 | 24 | ``` 25 | cp plugins/openalpr/conf.sample.json plugins/openalpr/conf.json 26 | ``` 27 | 28 | Edit it the new file. Host should be `localhost` and port should match the `listening port for camera.js`. 29 | 30 | ``` 31 | nano plugins/openalpr/conf.json 32 | ``` 33 | 34 | Start the plugin. 35 | 36 | ``` 37 | node plugins/openalpr/shinobi-motion.js 38 | ``` 39 | 40 | Or to daemonize with PM2. 41 | 42 | ``` 43 | pm2 start plugins/openalpr/shinobi-motion.js 44 | ``` 45 | 46 | Doing this will reveal options in the monitor configuration. Shinobi does not need to be restarted when a plugin is initiated or stopped. 47 | 48 | ## Run the plugin as a Host 49 | > The main app (Shinobi) will be the client and the plugin will be the host. The purpose of allowing this method is so that you can use one plugin for multiple Shinobi instances. Allowing you to easily manage connections without starting multiple processes. 50 | 51 | Edit your plugins configuration file. Set the `hostPort` **to be different** than the `listening port for camera.js`. 52 | 53 | ``` 54 | nano plugins/openalpr/conf.json 55 | ``` 56 | 57 | Here is a sample of a Host configuration for the plugin. 58 | - `plug` is the name of the plugin corresponding in the main configuration file. 59 | - `https` choose if you want to use SSL or not. Default is `false`. 60 | - `hostPort` can be any available port number. **Don't make this the same port number as Shinobi.** Default is `8082`. 61 | - `type` tells the main application (Shinobi) what kind of plugin it is. In this case it is a detector. 62 | 63 | ``` 64 | { 65 | "plug":"OpenALPR", 66 | "hostPort":8082, 67 | "key":"SomeOpenALPRkeySoPeopleDontMessWithYourShinobi", 68 | "mode":"host", 69 | "type":"detector" 70 | } 71 | ``` 72 | 73 | Now modify the **main configuration file** located in the main directory of Shinobi. *Where you currently should be.* 74 | 75 | ``` 76 | nano conf.json 77 | ``` 78 | 79 | Add the `plugins` array if you don't already have it. Add the following *object inside the array*. 80 | 81 | ``` 82 | "plugins":[ 83 | { 84 | "id" : "OpenALPR", 85 | "https" : false, 86 | "host" : "localhost", 87 | "port" : 8082, 88 | "key" : "SomeOpenALPRkeySoPeopleDontMessWithYourShinobi", 89 | "mode" : "host", 90 | "type" : "detector" 91 | } 92 | ], 93 | ``` -------------------------------------------------------------------------------- /plugins/openalpr/conf.sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "plug":"OpenALPR", 3 | "host":"localhost", 4 | "port":8080, 5 | "hostPort":8082, 6 | "key":"SomeOpenALPRkeySoPeopleDontMessWithYourShinobi", 7 | "mode":"client", 8 | "type":"detector" 9 | } -------------------------------------------------------------------------------- /plugins/openalpr/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shinobi-openalpr", 3 | "version": "1.0.0", 4 | "description": "OpenALPR plugin for Shinobi", 5 | "main": "shinobi-openalpr.js", 6 | "dependencies": { 7 | "canvas": "^1.6.7", 8 | "express": "^4.16.2", 9 | "moment": "^2.19.2", 10 | "socket.io": "^2.0.4" 11 | }, 12 | "devDependencies": {}, 13 | "scripts": { 14 | "test": "echo \"Error: no test specified\" && exit 1" 15 | }, 16 | "author": "Moe Alam", 17 | "license": "ISC" 18 | } 19 | -------------------------------------------------------------------------------- /plugins/opencv/.gitignore: -------------------------------------------------------------------------------- 1 | conf.json 2 | cascades -------------------------------------------------------------------------------- /plugins/opencv/conf.sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "plug":"OpenCV", 3 | "host":"localhost", 4 | "port":8080, 5 | "key":"change_this_to_something_very_random____make_sure_to_match__/plugins/opencv/conf.json" 6 | } -------------------------------------------------------------------------------- /sql/.gitignore: -------------------------------------------------------------------------------- 1 | monitors.sql 2 | users.sql 3 | shinobi.sqlite -------------------------------------------------------------------------------- /sql/database.sql: -------------------------------------------------------------------------------- 1 | -- -------------------------------------------------------- 2 | -- Host: 192.168.88.58 3 | -- Server version: 5.7.17-0ubuntu0.16.04.1 - (Ubuntu) 4 | -- Server OS: Linux 5 | -- HeidiSQL Version: 9.3.0.4984 6 | -- -------------------------------------------------------- 7 | 8 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 9 | /*!40101 SET NAMES utf8mb4 */; 10 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 11 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 12 | 13 | -- Dumping database structure for ccio 14 | CREATE DATABASE IF NOT EXISTS `ccio` /*!40100 DEFAULT CHARACTER SET utf8 */; 15 | USE `ccio`; 16 | 17 | -- Data exporting was unselected. 18 | /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; 19 | /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; 20 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -------------------------------------------------------------------------------- /sql/default_data.sql: -------------------------------------------------------------------------------- 1 | -- -------------------------------------------------------- 2 | -- Host: 66.51.132.100 3 | -- Server version: 5.7.16-0ubuntu0.16.04.1 - (Ubuntu) 4 | -- Server OS: Linux 5 | -- HeidiSQL Version: 9.3.0.4984 6 | -- -------------------------------------------------------- 7 | 8 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 9 | /*!40101 SET NAMES utf8mb4 */; 10 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 11 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 12 | -- Dumping data for table ccio.Users: ~0 rows (approximately) 13 | /*!40000 ALTER TABLE `Users` DISABLE KEYS */; 14 | INSERT INTO `Users` (`ke`, `uid`, `auth`, `mail`, `pass`, `details`) VALUES 15 | ('2Df5hBE', 'XDf5hB3', 'ec49f05c1ddc7d818c61b3343c98cbc6', 'ccio@m03.ca', '5f4dcc3b5aa765d61d8327deb882cf99', '{"days":"10"}'); 16 | INSERT INTO `Monitors` (`mid`, `ke`, `name`, `shto`, `shfr`, `details`, `type`, `ext`, `protocol`, `host`, `path`, `port`, `fps`, `mode`, `width`, `height`) VALUES ('Demo', '2Df5hBE', 'Demo', '[]', '[]', '{"fatal_max":"","notes":"","dir":"","rtsp_transport":"tcp","muser":"","mpass":"","port_force":"0","sfps":"","aduration":"1000000","probesize":"1000000","accelerator":"0","hwaccel":null,"hwaccel_vcodec":"","hwaccel_device":"","stream_type":"hls","stream_mjpeg_clients":"","stream_vcodec":"copy","stream_acodec":"no","hls_time":"","preset_stream":"","hls_list_size":"","signal_check":"","signal_check_log":null,"stream_quality":"","stream_fps":"1","stream_scale_x":"","stream_scale_y":"","rotate_stream":null,"svf":"","stream_timestamp":"0","stream_timestamp_font":"","stream_timestamp_font_size":"","stream_timestamp_color":"","stream_timestamp_box_color":"","stream_timestamp_x":"","stream_timestamp_y":"","stream_watermark":"0","stream_watermark_location":"","stream_watermark_position":null,"snap":"1","snap_fps":"","snap_scale_x":"","snap_scale_y":"","snap_vf":"","vcodec":"copy","crf":"","preset_record":"","acodec":"libvorbis","dqf":null,"cutoff":"10","rotate_record":null,"vf":"","timestamp":"1","timestamp_font":"","timestamp_font_size":"","timestamp_color":"","timestamp_box_color":"","timestamp_x":"","timestamp_y":"","watermark":null,"watermark_location":"","watermark_position":null,"cust_input":"","cust_snap":"","cust_detect":"","cust_stream":"","cust_stream_server":"","cust_record":"","custom_output":"","detector":"0","detector_webhook":null,"detector_webhook_url":"","detector_command_enable":null,"detector_command":"","detector_command_timeout":"","detector_lock_timeout":"","detector_save":null,"detector_frame_save":null,"detector_mail":null,"detector_mail_timeout":"","detector_record_method":null,"detector_trigger":null,"detector_trigger_record_fps":"","detector_timeout":"","watchdog_reset":null,"detector_delete_motionless_videos":null,"detector_send_frames":null,"detector_fps":"","detector_scale_x":"","detector_scale_y":"","detector_use_motion":null,"detector_use_detect_object":null,"detector_frame":null,"detector_sensitivity":"","cords":"","detector_lisence_plate":null,"detector_lisence_plate_country":null,"detector_notrigger":null,"detector_notrigger_mail":null,"detector_notrigger_timeout":"","control":"0","control_base_url":"","control_stop":null,"control_url_stop_timeout":"","control_url_center":"","control_url_left":"","control_url_left_stop":"","control_url_right":"","control_url_right_stop":"","control_url_up":"","control_url_up_stop":"","control_url_down":"","control_url_down_stop":"","control_url_enable_nv":"","control_url_disable_nv":"","control_url_zoom_out":"","control_url_zoom_out_stop":"","control_url_zoom_in":"","control_url_zoom_in_stop":"","groups":"","loglevel":"warning","sqllog":"0","detector_cascades":""}', 'mjpeg', 'mp4', 'http', 'came3.nkansai.ne.jp', '/nphMotionJpeg?Resolution=640x480&Quality=Motion', 81, 15, 'start', 640, 480); 17 | /*!40000 ALTER TABLE `Users` ENABLE KEYS */; 18 | /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; 19 | /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; 20 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 21 | -------------------------------------------------------------------------------- /sql/docker/01-framework.sql: -------------------------------------------------------------------------------- 1 | -- -------------------------------------------------------- 2 | -- Host: 192.168.88.58 3 | -- Server version: 5.7.17-0ubuntu0.16.04.1 - (Ubuntu) 4 | -- Server OS: Linux 5 | -- HeidiSQL Version: 9.3.0.4984 6 | -- -------------------------------------------------------- 7 | 8 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 9 | /*!40101 SET NAMES utf8mb4 */; 10 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 11 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 12 | 13 | -- Dumping structure for table ccio.API 14 | CREATE TABLE IF NOT EXISTS `API` ( 15 | `ke` varchar(50) DEFAULT NULL, 16 | `uid` varchar(50) DEFAULT NULL, 17 | `ip` tinytext, 18 | `code` varchar(100) DEFAULT NULL, 19 | `details` text, 20 | `time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 21 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 22 | 23 | -- Data exporting was unselected. 24 | 25 | 26 | -- Dumping structure for table ccio.Events 27 | CREATE TABLE IF NOT EXISTS `Events` ( 28 | `ke` varchar(50) DEFAULT NULL, 29 | `mid` varchar(50) DEFAULT NULL, 30 | `details` text, 31 | `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 32 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; 33 | 34 | -- Data exporting was unselected. 35 | 36 | 37 | -- Dumping structure for table ccio.Logs 38 | CREATE TABLE IF NOT EXISTS `Logs` ( 39 | `ke` varchar(50) DEFAULT NULL, 40 | `mid` varchar(50) DEFAULT NULL, 41 | `info` text, 42 | `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 43 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 44 | 45 | -- Data exporting was unselected. 46 | 47 | 48 | -- Dumping structure for table ccio.Monitors 49 | CREATE TABLE IF NOT EXISTS `Monitors` ( 50 | `mid` varchar(50) DEFAULT NULL, 51 | `ke` varchar(50) DEFAULT NULL, 52 | `name` varchar(50) DEFAULT NULL, 53 | `shto` text, 54 | `shfr` text, 55 | `details` longtext, 56 | `type` varchar(50) DEFAULT 'jpeg', 57 | `ext` varchar(50) DEFAULT 'webm', 58 | `protocol` varchar(50) DEFAULT 'http', 59 | `host` varchar(100) DEFAULT '0.0.0.0', 60 | `path` varchar(100) DEFAULT '/', 61 | `port` int(8) DEFAULT '80', 62 | `fps` int(8) DEFAULT '1', 63 | `mode` varchar(15) DEFAULT NULL, 64 | `width` int(11) DEFAULT '640', 65 | `height` int(11) DEFAULT '360' 66 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 67 | 68 | -- Data exporting was unselected. 69 | 70 | 71 | -- Dumping structure for table ccio.Presets 72 | CREATE TABLE IF NOT EXISTS `Presets` ( 73 | `ke` varchar(50) DEFAULT NULL, 74 | `name` text, 75 | `details` text, 76 | `type` enum('monitor','event','user') DEFAULT NULL 77 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 78 | 79 | -- Data exporting was unselected. 80 | 81 | 82 | -- Dumping structure for table ccio.Users 83 | CREATE TABLE IF NOT EXISTS `Users` ( 84 | `ke` varchar(50) DEFAULT NULL, 85 | `uid` varchar(50) DEFAULT NULL, 86 | `auth` varchar(50) DEFAULT NULL, 87 | `mail` varchar(100) DEFAULT NULL, 88 | `pass` varchar(100) DEFAULT NULL, 89 | `details` longtext, 90 | UNIQUE KEY `mail` (`mail`) 91 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 92 | 93 | -- Data exporting was unselected. 94 | 95 | 96 | -- Dumping structure for table ccio.Videos 97 | CREATE TABLE IF NOT EXISTS `Videos` ( 98 | `mid` varchar(50) DEFAULT NULL, 99 | `ke` varchar(50) DEFAULT NULL, 100 | `ext` enum('webm','mp4') DEFAULT NULL, 101 | `time` timestamp NULL DEFAULT NULL, 102 | `duration` float DEFAULT NULL, 103 | `size` float DEFAULT NULL, 104 | `frames` int(11) DEFAULT NULL, 105 | `end` timestamp NULL DEFAULT NULL, 106 | `status` int(1) DEFAULT '0' COMMENT '0:Building,1:Complete,2:Read,3:Archive', 107 | `details` text 108 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 109 | 110 | -- Data exporting was unselected. 111 | /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; 112 | /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; 113 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 114 | -------------------------------------------------------------------------------- /sql/framework.sql: -------------------------------------------------------------------------------- 1 | -- -------------------------------------------------------- 2 | -- Host: 192.168.88.37 3 | -- Server version: 10.1.25-MariaDB- - Ubuntu 17.04 4 | -- Server OS: debian-linux-gnu 5 | -- HeidiSQL Version: 9.4.0.5125 6 | -- -------------------------------------------------------- 7 | 8 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 9 | /*!40101 SET NAMES utf8 */; 10 | /*!50503 SET NAMES utf8mb4 */; 11 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 12 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 13 | 14 | 15 | -- Dumping database structure for ccio 16 | CREATE DATABASE IF NOT EXISTS `ccio` /*!40100 DEFAULT CHARACTER SET utf8mb4 */; 17 | USE `ccio`; 18 | 19 | -- Dumping structure for table ccio.API 20 | CREATE TABLE IF NOT EXISTS `API` ( 21 | `ke` varchar(50) DEFAULT NULL, 22 | `uid` varchar(50) DEFAULT NULL, 23 | `ip` tinytext, 24 | `code` varchar(100) DEFAULT NULL, 25 | `details` text, 26 | `time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 27 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 28 | 29 | -- Data exporting was unselected. 30 | -- Dumping structure for table ccio.Events 31 | CREATE TABLE IF NOT EXISTS `Events` ( 32 | `ke` varchar(50) DEFAULT NULL, 33 | `mid` varchar(50) DEFAULT NULL, 34 | `details` text, 35 | `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 36 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; 37 | 38 | -- Data exporting was unselected. 39 | -- Dumping structure for table ccio.Logs 40 | CREATE TABLE IF NOT EXISTS `Logs` ( 41 | `ke` varchar(50) DEFAULT NULL, 42 | `mid` varchar(50) DEFAULT NULL, 43 | `info` text, 44 | `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 45 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 46 | 47 | -- Data exporting was unselected. 48 | -- Dumping structure for table ccio.Monitors 49 | CREATE TABLE IF NOT EXISTS `Monitors` ( 50 | `mid` varchar(50) DEFAULT NULL, 51 | `ke` varchar(50) DEFAULT NULL, 52 | `name` varchar(50) DEFAULT NULL, 53 | `shto` text, 54 | `shfr` text, 55 | `details` longtext, 56 | `type` varchar(50) DEFAULT 'jpeg', 57 | `ext` varchar(50) DEFAULT 'webm', 58 | `protocol` varchar(50) DEFAULT 'http', 59 | `host` varchar(100) DEFAULT '0.0.0.0', 60 | `path` varchar(100) DEFAULT '/', 61 | `port` int(8) DEFAULT '80', 62 | `fps` int(8) DEFAULT '1', 63 | `mode` varchar(15) DEFAULT NULL, 64 | `width` int(11) DEFAULT '640', 65 | `height` int(11) DEFAULT '360' 66 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 67 | 68 | -- Data exporting was unselected. 69 | -- Dumping structure for table ccio.Presets 70 | CREATE TABLE IF NOT EXISTS `Presets` ( 71 | `ke` varchar(50) DEFAULT NULL, 72 | `name` text, 73 | `details` text, 74 | `type` enum('monitor','event','user') DEFAULT NULL 75 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 76 | 77 | -- Data exporting was unselected. 78 | -- Dumping structure for table ccio.Users 79 | CREATE TABLE IF NOT EXISTS `Users` ( 80 | `ke` varchar(50) DEFAULT NULL, 81 | `uid` varchar(50) DEFAULT NULL, 82 | `auth` varchar(50) DEFAULT NULL, 83 | `mail` varchar(100) DEFAULT NULL, 84 | `pass` varchar(100) DEFAULT NULL, 85 | `details` longtext, 86 | UNIQUE KEY `mail` (`mail`) 87 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 88 | 89 | -- Data exporting was unselected. 90 | -- Dumping structure for table ccio.Videos 91 | CREATE TABLE IF NOT EXISTS `Videos` ( 92 | `mid` varchar(50) DEFAULT NULL, 93 | `ke` varchar(50) DEFAULT NULL, 94 | `ext` enum('webm','mp4') DEFAULT NULL, 95 | `time` timestamp NULL DEFAULT NULL, 96 | `duration` float DEFAULT NULL, 97 | `size` float DEFAULT NULL, 98 | `frames` int(11) DEFAULT NULL, 99 | `end` timestamp NULL DEFAULT NULL, 100 | `status` int(1) DEFAULT '0' COMMENT '0:Building,1:Complete,2:Read,3:Archive', 101 | `details` text 102 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 103 | 104 | -- Data exporting was unselected. 105 | /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; 106 | /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; 107 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 108 | -------------------------------------------------------------------------------- /sql/mssql/default_data.sql: -------------------------------------------------------------------------------- 1 | -- -------------------------------------------------------- 2 | -- Host: 66.51.132.100 3 | -- Server version: 5.7.16-0ubuntu0.16.04.1 - (Ubuntu) 4 | -- Server OS: Linux 5 | -- HeidiSQL Version: 9.3.0.4984 6 | -- -------------------------------------------------------- 7 | 8 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 9 | /*!40101 SET NAMES utf8mb4 */; 10 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 11 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 12 | -- Dumping data for table ccio.Users: ~0 rows (approximately) 13 | /*!40000 ALTER TABLE `Users` DISABLE KEYS */; 14 | INSERT INTO Users ([ke], [uid], [auth], [mail], [pass], [details]) VALUES 15 | ('2Df5hBE', 'XDf5hB3', 'ec49f05c1ddc7d818c61b3343c98cbc6', 'ccio@m03.ca', '5f4dcc3b5aa765d61d8327deb882cf99', '{"days":"10"}'); 16 | INSERT INTO Monitors ([mid], [ke], [name], [shto], [shfr], [details], [type], [ext], [protocol], [host], [path], [port], [fps], [mode], [width], [height]) VALUES ('bunny', '2Df5hBE', 'Bunny', '[]', '[]', '{"fatal_max":"","notes":"","dir":"","rtsp_transport":"tcp","muser":"","mpass":"","port_force":"0","sfps":"","aduration":"1000000","probesize":"1000000","accelerator":"0","hwaccel":null,"hwaccel_vcodec":"","hwaccel_device":"","stream_type":"hls","stream_mjpeg_clients":"","stream_vcodec":"copy","stream_acodec":"no","hls_time":"","preset_stream":"","hls_list_size":"","signal_check":"","signal_check_log":null,"stream_quality":"","stream_fps":"1","stream_scale_x":"","stream_scale_y":"","rotate_stream":null,"svf":"","stream_timestamp":"0","stream_timestamp_font":"","stream_timestamp_font_size":"","stream_timestamp_color":"","stream_timestamp_box_color":"","stream_timestamp_x":"","stream_timestamp_y":"","stream_watermark":"0","stream_watermark_location":"","stream_watermark_position":null,"snap":"1","snap_fps":"","snap_scale_x":"","snap_scale_y":"","snap_vf":"","vcodec":"copy","crf":"","preset_record":"","acodec":"libvorbis","dqf":null,"cutoff":"10","rotate_record":null,"vf":"","timestamp":"1","timestamp_font":"","timestamp_font_size":"","timestamp_color":"","timestamp_box_color":"","timestamp_x":"","timestamp_y":"","watermark":null,"watermark_location":"","watermark_position":null,"cust_input":"","cust_snap":"","cust_detect":"","cust_stream":"","cust_stream_server":"","cust_record":"","custom_output":"","detector":"0","detector_webhook":null,"detector_webhook_url":"","detector_command_enable":null,"detector_command":"","detector_command_timeout":"","detector_lock_timeout":"","detector_save":null,"detector_frame_save":null,"detector_mail":null,"detector_mail_timeout":"","detector_record_method":null,"detector_trigger":null,"detector_trigger_record_fps":"","detector_timeout":"","watchdog_reset":null,"detector_delete_motionless_videos":null,"detector_send_frames":null,"detector_fps":"","detector_scale_x":"","detector_scale_y":"","detector_use_motion":null,"detector_use_detect_object":null,"detector_frame":null,"detector_sensitivity":"","cords":"","detector_lisence_plate":null,"detector_lisence_plate_country":null,"detector_notrigger":null,"detector_notrigger_mail":null,"detector_notrigger_timeout":"","control":"0","control_base_url":"","control_stop":null,"control_url_stop_timeout":"","control_url_center":"","control_url_left":"","control_url_left_stop":"","control_url_right":"","control_url_right_stop":"","control_url_up":"","control_url_up_stop":"","control_url_down":"","control_url_down_stop":"","control_url_enable_nv":"","control_url_disable_nv":"","control_url_zoom_out":"","control_url_zoom_out_stop":"","control_url_zoom_in":"","control_url_zoom_in_stop":"","groups":"","loglevel":"warning","sqllog":"0","detector_cascades":""}', 'mjpeg', 'mp4', 'http', 'came3.nkansai.ne.jp', '/nphMotionJpeg?Resolution=640x480&Quality=Motion', 81, 15, 'start', 640, 480); 17 | /*!40000 ALTER TABLE `Users` ENABLE KEYS */; 18 | /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; 19 | /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; 20 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 21 | -------------------------------------------------------------------------------- /sql/mssql/framework.sql: -------------------------------------------------------------------------------- 1 | -- -------------------------------------------------------- 2 | -- Host: 192.168.88.37 3 | -- Server version: 10.1.25-MariaDB- - Ubuntu 17.04 4 | -- Server OS: debian-linux-gnu 5 | -- HeidiSQL Version: 9.4.0.5125 6 | -- -------------------------------------------------------- 7 | 8 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 9 | /*!40101 SET NAMES utf8 */; 10 | /*!50503 SET NAMES utf8mb4 */; 11 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 12 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 13 | 14 | 15 | -- Dumping database structure for ccio 16 | CREATE DATABASE `ccio` /*!40100 DEFAULT CHARACTER SET utf8mb4 */; 17 | USE ccio; 18 | 19 | -- Dumping structure for table ccio.API 20 | CREATE TABLE API ( 21 | ke varchar(50) DEFAULT NULL, 22 | uid varchar(50) DEFAULT NULL, 23 | ip varchar(255), 24 | code varchar(100) DEFAULT NULL, 25 | details varchar(max), 26 | time datetime2(0) NULL DEFAULT GETDATE() 27 | ) ; 28 | 29 | -- Data exporting was unselected. 30 | -- Dumping structure for table ccio.Events 31 | CREATE TABLE Events ( 32 | ke varchar(50) DEFAULT NULL, 33 | mid varchar(50) DEFAULT NULL, 34 | details varchar(max), 35 | time datetime2(0) NOT NULL DEFAULT GETDATE() 36 | ) ; 37 | 38 | -- Data exporting was unselected. 39 | -- Dumping structure for table ccio.Logs 40 | CREATE TABLE Logs ( 41 | ke varchar(50) DEFAULT NULL, 42 | mid varchar(50) DEFAULT NULL, 43 | info varchar(max), 44 | time datetime2(0) NOT NULL DEFAULT GETDATE() 45 | ) ; 46 | 47 | -- Data exporting was unselected. 48 | -- Dumping structure for table ccio.Monitors 49 | CREATE TABLE Monitors ( 50 | mid varchar(50) DEFAULT NULL, 51 | ke varchar(50) DEFAULT NULL, 52 | name varchar(50) DEFAULT NULL, 53 | shto varchar(max), 54 | shfr varchar(max), 55 | details varchar(max), 56 | type varchar(50) DEFAULT 'jpeg', 57 | ext varchar(50) DEFAULT 'webm', 58 | protocol varchar(50) DEFAULT 'http', 59 | host varchar(100) DEFAULT '0.0.0.0', 60 | path varchar(100) DEFAULT '/', 61 | port int DEFAULT '80', 62 | fps int DEFAULT '1', 63 | mode varchar(15) DEFAULT NULL, 64 | width int DEFAULT '640', 65 | height int DEFAULT '360' 66 | ) ; 67 | 68 | -- Data exporting was unselected. 69 | -- Dumping structure for table ccio.Presets 70 | CREATE TABLE Presets ( 71 | ke varchar(50) DEFAULT NULL, 72 | name varchar(max), 73 | details varchar(max), 74 | type enum('monitor','event','user') DEFAULT NULL 75 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 76 | 77 | -- Data exporting was unselected. 78 | -- Dumping structure for table ccio.Users 79 | CREATE TABLE Users ( 80 | ke varchar(50) DEFAULT NULL, 81 | uid varchar(50) DEFAULT NULL, 82 | auth varchar(50) DEFAULT NULL, 83 | mail varchar(100) DEFAULT NULL, 84 | pass varchar(100) DEFAULT NULL, 85 | details varchar(max), 86 | CONSTRAINT mail UNIQUE (mail) 87 | ) ; 88 | 89 | -- Data exporting was unselected. 90 | -- Dumping structure for table ccio.Videos 91 | CREATE TABLE Videos ( 92 | mid varchar(50) DEFAULT NULL, 93 | ke varchar(50) DEFAULT NULL, 94 | ext enum('webm','mp4') DEFAULT NULL, 95 | time datetime2(0) NULL DEFAULT NULL, 96 | duration float DEFAULT NULL, 97 | size float DEFAULT NULL, 98 | frames int DEFAULT NULL, 99 | end datetime2(0) NULL DEFAULT NULL, 100 | status int DEFAULT '0' , 101 | details varchar(max) 102 | ) ; 103 | 104 | -- Data exporting was unselected. 105 | /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; 106 | /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; 107 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 108 | -------------------------------------------------------------------------------- /sql/mssql/user.sql: -------------------------------------------------------------------------------- 1 | CREATE USER 'majesticflame'@'127.0.0.1' IDENTIFIED BY ''; 2 | GRANT ALL PRIVILEGES ON ccio.* TO 'majesticflame'@'127.0.0.1'; 3 | FLUSH PRIVILEGES; -------------------------------------------------------------------------------- /sql/postgresql/default_data.sql: -------------------------------------------------------------------------------- 1 | -- -------------------------------------------------------- 2 | -- Host: 66.51.132.100 3 | -- Server version: 5.7.16-0ubuntu0.16.04.1 - (Ubuntu) 4 | -- Server OS: Linux 5 | -- HeidiSQL Version: 9.3.0.4984 6 | -- -------------------------------------------------------- 7 | 8 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 9 | /*!40101 SET NAMES utf8mb4 */; 10 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 11 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 12 | -- Dumping data for table ccio.Users: ~0 rows (approximately) 13 | /*!40000 ALTER TABLE `Users` DISABLE KEYS */; 14 | INSERT INTO Users (ke, uid, auth, mail, pass, details) VALUES 15 | ('2Df5hBE', 'XDf5hB3', 'ec49f05c1ddc7d818c61b3343c98cbc6', 'ccio@m03.ca', '5f4dcc3b5aa765d61d8327deb882cf99', '{"days":"10"}'); 16 | INSERT INTO Monitors (mid, ke, name, shto, shfr, details, type, ext, protocol, host, path, port, fps, mode, width, height) VALUES ('bunny', '2Df5hBE', 'Bunny', '[]', '[]', '{"fatal_max":"","notes":"","dir":"","rtsp_transport":"tcp","muser":"","mpass":"","port_force":"0","sfps":"","aduration":"1000000","probesize":"1000000","accelerator":"0","hwaccel":null,"hwaccel_vcodec":"","hwaccel_device":"","stream_type":"hls","stream_mjpeg_clients":"","stream_vcodec":"copy","stream_acodec":"no","hls_time":"","preset_stream":"","hls_list_size":"","signal_check":"","signal_check_log":null,"stream_quality":"","stream_fps":"1","stream_scale_x":"","stream_scale_y":"","rotate_stream":null,"svf":"","stream_timestamp":"0","stream_timestamp_font":"","stream_timestamp_font_size":"","stream_timestamp_color":"","stream_timestamp_box_color":"","stream_timestamp_x":"","stream_timestamp_y":"","stream_watermark":"0","stream_watermark_location":"","stream_watermark_position":null,"snap":"1","snap_fps":"","snap_scale_x":"","snap_scale_y":"","snap_vf":"","vcodec":"copy","crf":"","preset_record":"","acodec":"libvorbis","dqf":null,"cutoff":"10","rotate_record":null,"vf":"","timestamp":"1","timestamp_font":"","timestamp_font_size":"","timestamp_color":"","timestamp_box_color":"","timestamp_x":"","timestamp_y":"","watermark":null,"watermark_location":"","watermark_position":null,"cust_input":"","cust_snap":"","cust_detect":"","cust_stream":"","cust_stream_server":"","cust_record":"","custom_output":"","detector":"0","detector_webhook":null,"detector_webhook_url":"","detector_command_enable":null,"detector_command":"","detector_command_timeout":"","detector_lock_timeout":"","detector_save":null,"detector_frame_save":null,"detector_mail":null,"detector_mail_timeout":"","detector_record_method":null,"detector_trigger":null,"detector_trigger_record_fps":"","detector_timeout":"","watchdog_reset":null,"detector_delete_motionless_videos":null,"detector_send_frames":null,"detector_fps":"","detector_scale_x":"","detector_scale_y":"","detector_use_motion":null,"detector_use_detect_object":null,"detector_frame":null,"detector_sensitivity":"","cords":"","detector_lisence_plate":null,"detector_lisence_plate_country":null,"detector_notrigger":null,"detector_notrigger_mail":null,"detector_notrigger_timeout":"","control":"0","control_base_url":"","control_stop":null,"control_url_stop_timeout":"","control_url_center":"","control_url_left":"","control_url_left_stop":"","control_url_right":"","control_url_right_stop":"","control_url_up":"","control_url_up_stop":"","control_url_down":"","control_url_down_stop":"","control_url_enable_nv":"","control_url_disable_nv":"","control_url_zoom_out":"","control_url_zoom_out_stop":"","control_url_zoom_in":"","control_url_zoom_in_stop":"","groups":"","loglevel":"warning","sqllog":"0","detector_cascades":""}', 'mjpeg', 'mp4', 'http', 'came3.nkansai.ne.jp', '/nphMotionJpeg?Resolution=640x480&Quality=Motion', 81, 15, 'start', 640, 480); 17 | /*!40000 ALTER TABLE `Users` ENABLE KEYS */; 18 | /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; 19 | /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; 20 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 21 | -------------------------------------------------------------------------------- /sql/postgresql/framework.sql: -------------------------------------------------------------------------------- 1 | -- -------------------------------------------------------- 2 | -- Host: 192.168.88.37 3 | -- Server version: 10.1.25-MariaDB- - Ubuntu 17.04 4 | -- Server OS: debian-linux-gnu 5 | -- HeidiSQL Version: 9.4.0.5125 6 | -- -------------------------------------------------------- 7 | 8 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 9 | /*!40101 SET NAMES utf8 */; 10 | /*!50503 SET NAMES utf8mb4 */; 11 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 12 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 13 | 14 | 15 | -- Dumping database structure for ccio 16 | CREATE DATABASE `ccio` /*!40100 DEFAULT CHARACTER SET utf8mb4 */; 17 | USE ccio; 18 | 19 | -- Dumping structure for table ccio.API 20 | CREATE TABLE IF NOT EXISTS API ( 21 | ke varchar(50) DEFAULT NULL, 22 | uid varchar(50) DEFAULT NULL, 23 | ip tinytext, 24 | code varchar(100) DEFAULT NULL, 25 | details text, 26 | time timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP 27 | ) ; 28 | 29 | -- Data exporting was unselected. 30 | -- Dumping structure for table ccio.Events 31 | CREATE TABLE IF NOT EXISTS Events ( 32 | ke varchar(50) DEFAULT NULL, 33 | mid varchar(50) DEFAULT NULL, 34 | details text, 35 | time timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP 36 | ) ; 37 | 38 | -- Data exporting was unselected. 39 | -- Dumping structure for table ccio.Logs 40 | CREATE TABLE IF NOT EXISTS Logs ( 41 | ke varchar(50) DEFAULT NULL, 42 | mid varchar(50) DEFAULT NULL, 43 | info text, 44 | time timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP 45 | ) ; 46 | 47 | -- Data exporting was unselected. 48 | -- Dumping structure for table ccio.Monitors 49 | CREATE TABLE IF NOT EXISTS Monitors ( 50 | mid varchar(50) DEFAULT NULL, 51 | ke varchar(50) DEFAULT NULL, 52 | name varchar(50) DEFAULT NULL, 53 | shto text, 54 | shfr text, 55 | details longtext, 56 | type varchar(50) DEFAULT 'jpeg', 57 | ext varchar(50) DEFAULT 'webm', 58 | protocol varchar(50) DEFAULT 'http', 59 | host varchar(100) DEFAULT '0.0.0.0', 60 | path varchar(100) DEFAULT '/', 61 | port int DEFAULT '80', 62 | fps int DEFAULT '1', 63 | mode varchar(15) DEFAULT NULL, 64 | width int DEFAULT '640', 65 | height int DEFAULT '360' 66 | ) ; 67 | 68 | -- Data exporting was unselected. 69 | -- Dumping structure for table ccio.Presets 70 | CREATE TABLE IF NOT EXISTS Presets ( 71 | ke varchar(50) DEFAULT NULL, 72 | name text, 73 | details text, 74 | type enum('monitor','event','user') DEFAULT NULL 75 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 76 | 77 | -- Data exporting was unselected. 78 | -- Dumping structure for table ccio.Users 79 | CREATE TABLE IF NOT EXISTS Users ( 80 | ke varchar(50) DEFAULT NULL, 81 | uid varchar(50) DEFAULT NULL, 82 | auth varchar(50) DEFAULT NULL, 83 | mail varchar(100) DEFAULT NULL, 84 | pass varchar(100) DEFAULT NULL, 85 | details longtext, 86 | CONSTRAINT mail UNIQUE (mail) 87 | ) ; 88 | 89 | -- Data exporting was unselected. 90 | -- Dumping structure for table ccio.Videos 91 | CREATE TABLE IF NOT EXISTS Videos ( 92 | mid varchar(50) DEFAULT NULL, 93 | ke varchar(50) DEFAULT NULL, 94 | ext enum('webm','mp4') DEFAULT NULL, 95 | time timestamp(0) NULL DEFAULT NULL, 96 | duration double precision DEFAULT NULL, 97 | size double precision DEFAULT NULL, 98 | frames int DEFAULT NULL, 99 | end timestamp(0) NULL DEFAULT NULL, 100 | status int DEFAULT '0' , 101 | details text 102 | ) ; 103 | 104 | -- Data exporting was unselected. 105 | /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; 106 | /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; 107 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 108 | -------------------------------------------------------------------------------- /sql/postgresql/user.sql: -------------------------------------------------------------------------------- 1 | CREATE USER 'majesticflame'@'127.0.0.1' IDENTIFIED BY ''; 2 | GRANT ALL PRIVILEGES ON ccio.* TO 'majesticflame'@'127.0.0.1'; 3 | FLUSH PRIVILEGES; -------------------------------------------------------------------------------- /sql/shinobi.sample.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/sql/shinobi.sample.sqlite -------------------------------------------------------------------------------- /sql/sqlite3/framework.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.16 Distrib 10.1.26-MariaDB, for debian-linux-gnu (x86_64) 2 | -- 3 | -- Host: localhost Database: db 4 | -- ------------------------------------------------------ 5 | -- Server version 10.1.26-MariaDB-0+deb9u1 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!40101 SET NAMES utf8mb4 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 18 | 19 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 20 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 21 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 22 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 23 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 24 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 25 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 26 | 27 | -- Dump completed on 2018-02-11 20:25:54 28 | -------------------------------------------------------------------------------- /sql/sqllog.txt: -------------------------------------------------------------------------------- 1 | update-5-6-2017.sql - allows Idle mode options and future proofs the mode field for other modes. -------------------------------------------------------------------------------- /sql/tables.sql: -------------------------------------------------------------------------------- 1 | -- -------------------------------------------------------- 2 | -- Host: 192.168.88.58 3 | -- Server version: 5.7.17-0ubuntu0.16.04.1 - (Ubuntu) 4 | -- Server OS: Linux 5 | -- HeidiSQL Version: 9.3.0.4984 6 | -- -------------------------------------------------------- 7 | 8 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 9 | /*!40101 SET NAMES utf8mb4 */; 10 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 11 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 12 | 13 | 14 | -- Dumping structure for table ccio.API 15 | CREATE TABLE IF NOT EXISTS `API` ( 16 | `ke` varchar(50) DEFAULT NULL, 17 | `uid` varchar(50) DEFAULT NULL, 18 | `ip` tinytext, 19 | `code` varchar(100) DEFAULT NULL, 20 | `details` text, 21 | `time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 22 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 23 | 24 | -- Data exporting was unselected. 25 | 26 | 27 | -- Dumping structure for table ccio.Events 28 | CREATE TABLE IF NOT EXISTS `Events` ( 29 | `ke` varchar(50) DEFAULT NULL, 30 | `mid` varchar(50) DEFAULT NULL, 31 | `details` text, 32 | `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 33 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; 34 | 35 | -- Data exporting was unselected. 36 | 37 | 38 | -- Dumping structure for table ccio.Logs 39 | CREATE TABLE IF NOT EXISTS `Logs` ( 40 | `ke` varchar(50) DEFAULT NULL, 41 | `mid` varchar(50) DEFAULT NULL, 42 | `info` text, 43 | `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 44 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 45 | 46 | -- Data exporting was unselected. 47 | 48 | 49 | -- Dumping structure for table ccio.Monitors 50 | CREATE TABLE IF NOT EXISTS `Monitors` ( 51 | `mid` varchar(50) DEFAULT NULL, 52 | `ke` varchar(50) DEFAULT NULL, 53 | `name` varchar(50) DEFAULT NULL, 54 | `shto` text, 55 | `shfr` text, 56 | `details` longtext, 57 | `type` varchar(50) DEFAULT 'jpeg', 58 | `ext` varchar(50) DEFAULT 'webm', 59 | `protocol` varchar(50) DEFAULT 'http', 60 | `host` varchar(100) DEFAULT '0.0.0.0', 61 | `path` varchar(100) DEFAULT '/', 62 | `port` int(8) DEFAULT '80', 63 | `fps` int(8) DEFAULT '1', 64 | `mode` varchar(15) DEFAULT NULL, 65 | `width` int(11) DEFAULT '640', 66 | `height` int(11) DEFAULT '360' 67 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 68 | 69 | -- Data exporting was unselected. 70 | 71 | 72 | -- Dumping structure for table ccio.Presets 73 | CREATE TABLE IF NOT EXISTS `Presets` ( 74 | `ke` varchar(50) DEFAULT NULL, 75 | `name` text, 76 | `details` text, 77 | `type` enum('monitor','event','user') DEFAULT NULL 78 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 79 | 80 | -- Data exporting was unselected. 81 | 82 | 83 | -- Dumping structure for table ccio.Users 84 | CREATE TABLE IF NOT EXISTS `Users` ( 85 | `ke` varchar(50) DEFAULT NULL, 86 | `uid` varchar(50) DEFAULT NULL, 87 | `auth` varchar(50) DEFAULT NULL, 88 | `mail` varchar(100) DEFAULT NULL, 89 | `pass` varchar(100) DEFAULT NULL, 90 | `details` longtext, 91 | UNIQUE KEY `mail` (`mail`) 92 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 93 | 94 | -- Data exporting was unselected. 95 | 96 | 97 | -- Dumping structure for table ccio.Videos 98 | CREATE TABLE IF NOT EXISTS `Videos` ( 99 | `mid` varchar(50) DEFAULT NULL, 100 | `ke` varchar(50) DEFAULT NULL, 101 | `ext` enum('webm','mp4') DEFAULT NULL, 102 | `time` timestamp NULL DEFAULT NULL, 103 | `duration` float DEFAULT NULL, 104 | `size` float DEFAULT NULL, 105 | `frames` int(11) DEFAULT NULL, 106 | `end` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 107 | `status` int(1) DEFAULT '0' COMMENT '0:Open,1:Complete,2:Error,3:Unknown' 108 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 109 | 110 | -- Data exporting was unselected. 111 | /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; 112 | /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; 113 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -------------------------------------------------------------------------------- /sql/update-1-1-2017.sql: -------------------------------------------------------------------------------- 1 | USE ccio; 2 | ALTER TABLE Monitors MODIFY ext VARCHAR(50); 3 | 4 | CREATE TABLE IF NOT EXISTS `API` ( 5 | `ke` varchar(50) DEFAULT NULL, 6 | `uid` varchar(50) DEFAULT NULL, 7 | `ip` tinytext, 8 | `code` varchar(100) DEFAULT NULL, 9 | `details` text, 10 | `time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 11 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -------------------------------------------------------------------------------- /sql/update-13-7-2017.sql: -------------------------------------------------------------------------------- 1 | USE `ccio`; 2 | ALTER TABLE Videos CHANGE end end TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP; -------------------------------------------------------------------------------- /sql/update-17-5-2017.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS `ccio`; 2 | USE `ccio`; 3 | 4 | CREATE TABLE IF NOT EXISTS `BackupVideos` ( 5 | `mid` varchar(50) DEFAULT NULL, 6 | `ke` varchar(50) DEFAULT NULL, 7 | `ext` varchar(15) DEFAULT NULL, 8 | `time` timestamp NULL DEFAULT NULL, 9 | `end` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 10 | `size` float DEFAULT NULL, 11 | `details` longtext 12 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 13 | 14 | ALTER TABLE Videos MODIFY COLUMN `ext` varchar(15); 15 | ALTER TABLE Videos ADD `details` longtext; 16 | ALTER TABLE Videos DROP COLUMN `frames`; 17 | ALTER TABLE Videos DROP COLUMN `duration`; -------------------------------------------------------------------------------- /sql/update-2-2-2017.sql: -------------------------------------------------------------------------------- 1 | -- -------------------------------------------------------- 2 | -- Host: 192.168.88.58 3 | -- Server version: 5.7.17-0ubuntu0.16.04.1 - (Ubuntu) 4 | -- Server OS: Linux 5 | -- HeidiSQL Version: 9.3.0.4984 6 | -- -------------------------------------------------------- 7 | 8 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 9 | /*!40101 SET NAMES utf8mb4 */; 10 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 11 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 12 | 13 | -- Dumping database structure for ccio 14 | USE ccio; 15 | ALTER TABLE `Monitors` CHANGE COLUMN `protocol` `protocol` VARCHAR(50) NULL DEFAULT 'http' AFTER `ext`; 16 | 17 | -- Dumping structure for table ccio.Events 18 | CREATE TABLE IF NOT EXISTS `Events` ( 19 | `ke` varchar(50) DEFAULT NULL, 20 | `mid` varchar(50) DEFAULT NULL, 21 | `details` text, 22 | `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 23 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; 24 | 25 | -- Data exporting was unselected. 26 | /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; 27 | /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; 28 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 29 | -------------------------------------------------------------------------------- /sql/update-26-08-2017.sql: -------------------------------------------------------------------------------- 1 | use ccio 2 | ALTER TABLE `Videos` ADD COLUMN `details` TEXT NULL DEFAULT NULL AFTER `status`; -------------------------------------------------------------------------------- /sql/update-5-6-2017.sql: -------------------------------------------------------------------------------- 1 | USE `ccio`; 2 | 3 | ALTER TABLE Monitors MODIFY COLUMN `mode` varchar(15); -------------------------------------------------------------------------------- /sql/user.sql: -------------------------------------------------------------------------------- 1 | CREATE USER 'majesticflame'@'127.0.0.1' IDENTIFIED BY ''; 2 | GRANT ALL PRIVILEGES ON ccio.* TO 'majesticflame'@'127.0.0.1'; 3 | FLUSH PRIVILEGES; -------------------------------------------------------------------------------- /super.sample.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "mail":"admin@shinobi.video", 4 | "pass":"21232f297a57a5a743894a0e4a801fc3" 5 | } 6 | ] -------------------------------------------------------------------------------- /tools/addVideos.js.disabled: -------------------------------------------------------------------------------- 1 | //add videos to SQL tables from filesystem 2 | var fs = require('fs'); 3 | var moment = require('moment'); 4 | var mysql = require('mysql'); 5 | var config = require('../conf.json'); 6 | s={} 7 | s.disc=function(){ 8 | sql = mysql.createConnection(config.db); 9 | sql.connect(function(err){if(err){console.log('Error Connecting : DB',err);setTimeout(s.disc, 2000);}}); 10 | sql.on('error',function(err) {console.log('DB Lost.. Retrying..');console.log(err);s.disc();return;}); 11 | } 12 | s.disc(); 13 | if(!config.videosDir){config.videosDir=__dirname+'/../videos/'} 14 | s.dir={videos:config.videosDir}; 15 | s.nameToTime=function(x){x=x.split('.')[0].split('T'),x[1]=x[1].replace(/-/g,':');x=x.join(' ');return x;} 16 | s.moment=function(e,x){ 17 | if(!e){e=new Date};if(!x){x='YYYY-MM-DDTHH-mm-ss'}; 18 | return moment(e).format(x); 19 | } 20 | fs.readdir(s.dir.videos,function(err,groups){ 21 | groups.forEach(function(group){ 22 | fs.readdir(s.dir.videos+group,function(err,cameras){ 23 | cameras.forEach(function(camera){ 24 | fs.readdir(s.dir.videos+group+'/'+camera,function(err,videos){ 25 | sql.query('SELECT * FROM Videos WHERE ke=? AND mid=?',[group,camera],function(err,r){ 26 | videos.forEach(function(filename){ 27 | fs.stat(s.dir.videos+group+'/'+camera+'/'+filename,function(err,file){ 28 | file.startTime=s.nameToTime(filename) 29 | file.endTime=s.moment(file.mtime,'YYYY-MM-DD HH:mm:ss') 30 | var save=[camera,group,filename.split('.')[1],file.size,file.startTime,file.endTime,1] 31 | var found=null 32 | r.forEach(function(v){ 33 | if(s.moment(v.time,'YYYY-MM-DD HH:mm:ss')===file.startTime){ 34 | found=v 35 | } 36 | }) 37 | if(!found){ 38 | console.log('!found',save) 39 | sql.query('INSERT INTO Videos (mid,ke,ext,size,time,end,status) VALUES (?,?,?,?,?,?,?)',save) 40 | } 41 | }) 42 | }) 43 | }) 44 | }) 45 | }) 46 | }) 47 | }) 48 | }) -------------------------------------------------------------------------------- /tools/translateLanguageFile.js: -------------------------------------------------------------------------------- 1 | console.log('This translation tool uses Yandex.') 2 | if(!process.argv[2]||!process.argv[3]||!process.argv[4]){ 3 | console.log('You must input arguments.') 4 | console.log('# node translateLanguageFile.js ') 5 | console.log('Example:') 6 | console.log('# node translateLanguageFile.js en_US en ar') 7 | return 8 | } 9 | var langDir='../languages/' 10 | var fs=require('fs'); 11 | var https = require('https'); 12 | var jsonfile=require('jsonfile'); 13 | var source=require(langDir+process.argv[2]+'.json') 14 | var list = Object.keys(source) 15 | console.log(list.length) 16 | var extra = '' 17 | if(process.argv[4]==='he'){process.argv[4]=='ar'} 18 | var current = 1 19 | var currentItem = list[0] 20 | var chosenFile = langDir+process.argv[4]+'.json' 21 | try{ 22 | newList=require(chosenFile) 23 | }catch(err){ 24 | console.log(chosenFile) 25 | var newList={} 26 | } 27 | var newListAlphabetical={} 28 | var goNext=function(){ 29 | ++current 30 | currentItem = list[current] 31 | if(list.length===current){ 32 | console.log('complete checking.. please wait') 33 | Object.keys(newList).sort().forEach(function(y,t){ 34 | newListAlphabetical[y]=newList[y] 35 | }) 36 | jsonfile.writeFile(chosenFile,newListAlphabetical,{spaces: 2},function(){ 37 | console.log('complete writing') 38 | }) 39 | }else{ 40 | next(currentItem) 41 | } 42 | } 43 | var next=function(v){ 44 | if(v===undefined){return false} 45 | //trnsl.1.1.20170718T033617Z.a9bbd3b739ca59df.7f89b7474ec69812afd0014b5e338328ebf3fc39 46 | if(newList[v]&&newList[v]!==source[v]){ 47 | goNext() 48 | return 49 | } 50 | if(/<[a-z][\s\S]*>/i.test(source[v])===true){ 51 | extra+='&format=html' 52 | } 53 | var url = 'https://translate.yandex.net/api/v1.5/tr.json/translate?key=trnsl.1.1.20160311T042953Z.341f2f63f38bdac6.c7e5c01fff7f57160141021ca61b60e36ff4d379'+extra+'&lang='+process.argv[3]+'-'+process.argv[4]+'&text='+source[v] 54 | https.request(url, function(data) { 55 | data.setEncoding('utf8'); 56 | var chunks=''; 57 | data.on('data', (chunk) => { 58 | chunks+=chunk; 59 | }); 60 | data.on('end', () => { 61 | try{ 62 | chunks=JSON.parse(chunks) 63 | if(chunks.html){ 64 | if(chunks.html[0]){ 65 | var translation=chunks.html[0] 66 | }else{ 67 | var translation=chunks.html 68 | } 69 | 70 | }else{ 71 | var translation=chunks.text[0] 72 | } 73 | }catch(err){ 74 | var translation=source[v] 75 | } 76 | newList[v]=translation; 77 | console.log(current+'/'+list.length+','+v+' ---> '+translation) 78 | goNext() 79 | }); 80 | }).on('error', function(e) { 81 | console.log('ERROR : 500 '+v) 82 | res.sendStatus(500); 83 | }).end(); 84 | } 85 | next(currentItem) -------------------------------------------------------------------------------- /web/libs/.gitignore: -------------------------------------------------------------------------------- 1 | demo -------------------------------------------------------------------------------- /web/libs/css/bootstrap-table.min.css: -------------------------------------------------------------------------------- 1 | .fixed-table-container .bs-checkbox,.fixed-table-container .no-records-found{text-align:center}.fixed-table-body thead th .th-inner,.table td,.table th{box-sizing:border-box}.bootstrap-table .table{margin-bottom:0!important;border-bottom:1px solid #ddd;border-collapse:collapse!important;border-radius:1px}.bootstrap-table .table:not(.table-condensed),.bootstrap-table .table:not(.table-condensed)>tbody>tr>td,.bootstrap-table .table:not(.table-condensed)>tbody>tr>th,.bootstrap-table .table:not(.table-condensed)>tfoot>tr>td,.bootstrap-table .table:not(.table-condensed)>tfoot>tr>th,.bootstrap-table .table:not(.table-condensed)>thead>tr>td{padding:8px}.bootstrap-table .table.table-no-bordered>tbody>tr>td,.bootstrap-table .table.table-no-bordered>thead>tr>th{border-right:2px solid transparent}.bootstrap-table .table.table-no-bordered>tbody>tr>td:last-child{border-right:none}.fixed-table-container{position:relative;clear:both;border:1px solid #ddd;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px}.fixed-table-container.table-no-bordered{border:1px solid transparent}.fixed-table-footer,.fixed-table-header{overflow:hidden}.fixed-table-footer{border-top:1px solid #ddd}.fixed-table-body{overflow-x:auto;overflow-y:auto;height:100%}.fixed-table-container table{width:100%}.fixed-table-container thead th{height:0;padding:0;margin:0;border-left:1px solid #ddd}.fixed-table-container thead th:focus{outline:transparent solid 0}.fixed-table-container thead th:first-child{border-left:none;border-top-left-radius:4px;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px}.fixed-table-container tbody td .th-inner,.fixed-table-container thead th .th-inner{padding:8px;line-height:24px;vertical-align:top;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fixed-table-container thead th .sortable{cursor:pointer;background-position:right;background-repeat:no-repeat;padding-right:30px}.fixed-table-container thead th .both{background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC')}.fixed-table-container thead th .asc{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg==)}.fixed-table-container thead th .desc{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII=)}.fixed-table-container th.detail{width:30px}.fixed-table-container tbody td{border-left:1px solid #ddd}.fixed-table-container tbody tr:first-child td{border-top:none}.fixed-table-container tbody td:first-child{border-left:none}.fixed-table-container tbody .selected td{background-color:#f5f5f5}.fixed-table-container .bs-checkbox .th-inner{padding:8px 0}.fixed-table-container input[type=radio],.fixed-table-container input[type=checkbox]{margin:0 auto!important}.fixed-table-pagination .pagination-detail,.fixed-table-pagination div.pagination{margin-top:10px;margin-bottom:10px}.fixed-table-pagination div.pagination .pagination{margin:0}.fixed-table-pagination .pagination a{padding:6px 12px;line-height:1.428571429}.fixed-table-pagination .pagination-info{line-height:34px;margin-right:5px}.fixed-table-pagination .btn-group{position:relative;display:inline-block;vertical-align:middle}.fixed-table-pagination .dropup .dropdown-menu{margin-bottom:0}.fixed-table-pagination .page-list{display:inline-block}.fixed-table-toolbar .columns-left{margin-right:5px}.fixed-table-toolbar .columns-right{margin-left:5px}.fixed-table-toolbar .columns label{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429}.fixed-table-toolbar .bs-bars,.fixed-table-toolbar .columns,.fixed-table-toolbar .search{position:relative;margin-top:10px;margin-bottom:10px;line-height:34px}.fixed-table-pagination li.disabled a{pointer-events:none;cursor:default}.fixed-table-loading{display:none;position:absolute;top:42px;right:0;bottom:0;left:0;z-index:99;background-color:#fff;text-align:center}.fixed-table-body .card-view .title{font-weight:700;display:inline-block;min-width:30%;text-align:left!important}.table td,.table th{vertical-align:middle}.fixed-table-toolbar .dropdown-menu{text-align:left;max-height:300px;overflow:auto}.fixed-table-toolbar .btn-group>.btn-group{display:inline-block;margin-left:-1px!important}.fixed-table-toolbar .btn-group>.btn-group>.btn{border-radius:0}.fixed-table-toolbar .btn-group>.btn-group:first-child>.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.fixed-table-toolbar .btn-group>.btn-group:last-child>.btn{border-top-right-radius:4px;border-bottom-right-radius:4px}.bootstrap-table .table>thead>tr>th{vertical-align:bottom;border-bottom:1px solid #ddd}.bootstrap-table .table thead>tr>th{padding:0;margin:0}.bootstrap-table .fixed-table-footer tbody>tr>td{padding:0!important}.bootstrap-table .fixed-table-footer .table{border-bottom:none;border-radius:0;padding:0!important}.pull-right .dropdown-menu{right:0;left:auto}p.fixed-table-scroll-inner{width:100%;height:200px}div.fixed-table-scroll-outer{top:0;left:0;visibility:hidden;width:200px;height:150px;overflow:hidden} -------------------------------------------------------------------------------- /web/libs/css/c3.css: -------------------------------------------------------------------------------- 1 | /*-- Chart --*/ 2 | .c3 svg { 3 | font: 10px sans-serif; 4 | -webkit-tap-highlight-color: transparent; } 5 | 6 | .c3 path, .c3 line { 7 | fill: none; 8 | stroke: #000; } 9 | 10 | .c3 text { 11 | -webkit-user-select: none; 12 | -moz-user-select: none; 13 | user-select: none; } 14 | 15 | .c3-legend-item-tile, 16 | .c3-xgrid-focus, 17 | .c3-ygrid, 18 | .c3-event-rect, 19 | .c3-bars path { 20 | shape-rendering: crispEdges; } 21 | 22 | .c3-chart-arc path { 23 | stroke: #fff; } 24 | 25 | .c3-chart-arc text { 26 | fill: #fff; 27 | font-size: 13px; } 28 | 29 | /*-- Axis --*/ 30 | /*-- Grid --*/ 31 | .c3-grid line { 32 | stroke: #aaa; } 33 | 34 | .c3-grid text { 35 | fill: #aaa; } 36 | 37 | .c3-xgrid, .c3-ygrid { 38 | stroke-dasharray: 3 3; } 39 | 40 | /*-- Text on Chart --*/ 41 | .c3-text.c3-empty { 42 | fill: #808080; 43 | font-size: 2em; } 44 | 45 | /*-- Line --*/ 46 | .c3-line { 47 | stroke-width: 1px; } 48 | 49 | /*-- Point --*/ 50 | .c3-circle._expanded_ { 51 | stroke-width: 1px; 52 | stroke: white; } 53 | 54 | .c3-selected-circle { 55 | fill: white; 56 | stroke-width: 2px; } 57 | 58 | /*-- Bar --*/ 59 | .c3-bar { 60 | stroke-width: 0; } 61 | 62 | .c3-bar._expanded_ { 63 | fill-opacity: 1; 64 | fill-opacity: 0.75; } 65 | 66 | /*-- Focus --*/ 67 | .c3-target.c3-focused { 68 | opacity: 1; } 69 | 70 | .c3-target.c3-focused path.c3-line, .c3-target.c3-focused path.c3-step { 71 | stroke-width: 2px; } 72 | 73 | .c3-target.c3-defocused { 74 | opacity: 0.3 !important; } 75 | 76 | /*-- Region --*/ 77 | .c3-region { 78 | fill: steelblue; 79 | fill-opacity: .1; } 80 | 81 | /*-- Brush --*/ 82 | .c3-brush .extent { 83 | fill-opacity: .1; } 84 | 85 | /*-- Select - Drag --*/ 86 | /*-- Legend --*/ 87 | .c3-legend-item { 88 | font-size: 12px; } 89 | 90 | .c3-legend-item-hidden { 91 | opacity: 0.15; } 92 | 93 | .c3-legend-background { 94 | opacity: 0.75; 95 | fill: white; 96 | stroke: lightgray; 97 | stroke-width: 1; } 98 | 99 | /*-- Title --*/ 100 | .c3-title { 101 | font: 14px sans-serif; } 102 | 103 | /*-- Tooltip --*/ 104 | .c3-tooltip-container { 105 | z-index: 10; } 106 | 107 | .c3-tooltip { 108 | border-collapse: collapse; 109 | border-spacing: 0; 110 | background-color: #fff; 111 | empty-cells: show; 112 | -webkit-box-shadow: 7px 7px 12px -9px #777777; 113 | -moz-box-shadow: 7px 7px 12px -9px #777777; 114 | box-shadow: 7px 7px 12px -9px #777777; 115 | opacity: 0.9; } 116 | 117 | .c3-tooltip tr { 118 | border: 1px solid #CCC; } 119 | 120 | .c3-tooltip th { 121 | background-color: #aaa; 122 | font-size: 14px; 123 | padding: 2px 5px; 124 | text-align: left; 125 | color: #FFF; } 126 | 127 | .c3-tooltip td { 128 | font-size: 13px; 129 | padding: 3px 6px; 130 | background-color: #fff; 131 | border-left: 1px dotted #999; } 132 | 133 | .c3-tooltip td > span { 134 | display: inline-block; 135 | width: 10px; 136 | height: 10px; 137 | margin-right: 6px; } 138 | 139 | .c3-tooltip td.value { 140 | text-align: right; } 141 | 142 | /*-- Area --*/ 143 | .c3-area { 144 | stroke-width: 0; 145 | opacity: 0.2; } 146 | 147 | /*-- Arc --*/ 148 | .c3-chart-arcs-title { 149 | dominant-baseline: middle; 150 | font-size: 1.3em; } 151 | 152 | .c3-chart-arcs .c3-chart-arcs-background { 153 | fill: #e0e0e0; 154 | stroke: none; } 155 | 156 | .c3-chart-arcs .c3-chart-arcs-gauge-unit { 157 | fill: #000; 158 | font-size: 16px; } 159 | 160 | .c3-chart-arcs .c3-chart-arcs-gauge-max { 161 | fill: #777; } 162 | 163 | .c3-chart-arcs .c3-chart-arcs-gauge-min { 164 | fill: #777; } 165 | 166 | .c3-chart-arc .c3-gauge-value { 167 | fill: #000; 168 | /* font-size: 28px !important;*/ } 169 | 170 | .c3-chart-arc.c3-target g path { 171 | opacity: 1; } 172 | 173 | .c3-chart-arc.c3-target.c3-focused g path { 174 | opacity: 1; } 175 | -------------------------------------------------------------------------------- /web/libs/css/fullcalendar.print.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * FullCalendar v3.0.1 Print Stylesheet 3 | * Docs & License: http://fullcalendar.io/ 4 | * (c) 2016 Adam Shaw 5 | */ 6 | 7 | /* 8 | * Include this stylesheet on your page to get a more printer-friendly calendar. 9 | * When including this stylesheet, use the media='print' attribute of the tag. 10 | * Make sure to include this stylesheet IN ADDITION to the regular fullcalendar.css. 11 | */ 12 | 13 | .fc { 14 | max-width: 100% !important; 15 | } 16 | 17 | 18 | /* Global Event Restyling 19 | --------------------------------------------------------------------------------------------------*/ 20 | 21 | .fc-event { 22 | background: #fff !important; 23 | color: #000 !important; 24 | page-break-inside: avoid; 25 | } 26 | 27 | .fc-event .fc-resizer { 28 | display: none; 29 | } 30 | 31 | 32 | /* Table & Day-Row Restyling 33 | --------------------------------------------------------------------------------------------------*/ 34 | 35 | .fc th, 36 | .fc td, 37 | .fc hr, 38 | .fc thead, 39 | .fc tbody, 40 | .fc-row { 41 | border-color: #ccc !important; 42 | background: #fff !important; 43 | } 44 | 45 | /* kill the overlaid, absolutely-positioned components */ 46 | /* common... */ 47 | .fc-bg, 48 | .fc-bgevent-skeleton, 49 | .fc-highlight-skeleton, 50 | .fc-helper-skeleton, 51 | /* for timegrid. within cells within table skeletons... */ 52 | .fc-bgevent-container, 53 | .fc-business-container, 54 | .fc-highlight-container, 55 | .fc-helper-container { 56 | display: none; 57 | } 58 | 59 | /* don't force a min-height on rows (for DayGrid) */ 60 | .fc tbody .fc-row { 61 | height: auto !important; /* undo height that JS set in distributeHeight */ 62 | min-height: 0 !important; /* undo the min-height from each view's specific stylesheet */ 63 | } 64 | 65 | .fc tbody .fc-row .fc-content-skeleton { 66 | position: static; /* undo .fc-rigid */ 67 | padding-bottom: 0 !important; /* use a more border-friendly method for this... */ 68 | } 69 | 70 | .fc tbody .fc-row .fc-content-skeleton tbody tr:last-child td { /* only works in newer browsers */ 71 | padding-bottom: 1em; /* ...gives space within the skeleton. also ensures min height in a way */ 72 | } 73 | 74 | .fc tbody .fc-row .fc-content-skeleton table { 75 | /* provides a min-height for the row, but only effective for IE, which exaggerates this value, 76 | making it look more like 3em. for other browers, it will already be this tall */ 77 | height: 1em; 78 | } 79 | 80 | 81 | /* Undo month-view event limiting. Display all events and hide the "more" links 82 | --------------------------------------------------------------------------------------------------*/ 83 | 84 | .fc-more-cell, 85 | .fc-more { 86 | display: none !important; 87 | } 88 | 89 | .fc tr.fc-limited { 90 | display: table-row !important; 91 | } 92 | 93 | .fc td.fc-limited { 94 | display: table-cell !important; 95 | } 96 | 97 | .fc-popover { 98 | display: none; /* never display the "more.." popover in print mode */ 99 | } 100 | 101 | 102 | /* TimeGrid Restyling 103 | --------------------------------------------------------------------------------------------------*/ 104 | 105 | /* undo the min-height 100% trick used to fill the container's height */ 106 | .fc-time-grid { 107 | min-height: 0 !important; 108 | } 109 | 110 | /* don't display the side axis at all ("all-day" and time cells) */ 111 | .fc-agenda-view .fc-axis { 112 | display: none; 113 | } 114 | 115 | /* don't display the horizontal lines */ 116 | .fc-slats, 117 | .fc-time-grid hr { /* this hr is used when height is underused and needs to be filled */ 118 | display: none !important; /* important overrides inline declaration */ 119 | } 120 | 121 | /* let the container that holds the events be naturally positioned and create real height */ 122 | .fc-time-grid .fc-content-skeleton { 123 | position: static; 124 | } 125 | 126 | /* in case there are no events, we still want some height */ 127 | .fc-time-grid .fc-content-skeleton table { 128 | height: 4em; 129 | } 130 | 131 | /* kill the horizontal spacing made by the event container. event margins will be done below */ 132 | .fc-time-grid .fc-event-container { 133 | margin: 0 !important; 134 | } 135 | 136 | 137 | /* TimeGrid *Event* Restyling 138 | --------------------------------------------------------------------------------------------------*/ 139 | 140 | /* naturally position events, vertically stacking them */ 141 | .fc-time-grid .fc-event { 142 | position: static !important; 143 | margin: 3px 2px !important; 144 | } 145 | 146 | /* for events that continue to a future day, give the bottom border back */ 147 | .fc-time-grid .fc-event.fc-not-end { 148 | border-bottom-width: 1px !important; 149 | } 150 | 151 | /* indicate the event continues via "..." text */ 152 | .fc-time-grid .fc-event.fc-not-end:after { 153 | content: "..."; 154 | } 155 | 156 | /* for events that are continuations from previous days, give the top border back */ 157 | .fc-time-grid .fc-event.fc-not-start { 158 | border-top-width: 1px !important; 159 | } 160 | 161 | /* indicate the event is a continuation via "..." text */ 162 | .fc-time-grid .fc-event.fc-not-start:before { 163 | content: "..."; 164 | } 165 | 166 | /* time */ 167 | 168 | /* undo a previous declaration and let the time text span to a second line */ 169 | .fc-time-grid .fc-event .fc-time { 170 | white-space: normal !important; 171 | } 172 | 173 | /* hide the the time that is normally displayed... */ 174 | .fc-time-grid .fc-event .fc-time span { 175 | display: none; 176 | } 177 | 178 | /* ...replace it with a more verbose version (includes AM/PM) stored in an html attribute */ 179 | .fc-time-grid .fc-event .fc-time:after { 180 | content: attr(data-full); 181 | } 182 | 183 | 184 | /* Vertical Scroller & Containers 185 | --------------------------------------------------------------------------------------------------*/ 186 | 187 | /* kill the scrollbars and allow natural height */ 188 | .fc-scroller, 189 | .fc-day-grid-container, /* these divs might be assigned height, which we need to cleared */ 190 | .fc-time-grid-container { /* */ 191 | overflow: visible !important; 192 | height: auto !important; 193 | } 194 | 195 | /* kill the horizontal border/padding used to compensate for scrollbars */ 196 | .fc-row { 197 | border: 0 !important; 198 | margin: 0 !important; 199 | } 200 | 201 | 202 | /* Button Controls 203 | --------------------------------------------------------------------------------------------------*/ 204 | 205 | .fc-button-group, 206 | .fc button { 207 | display: none; /* don't display any button-related controls */ 208 | } 209 | -------------------------------------------------------------------------------- /web/libs/css/login.css: -------------------------------------------------------------------------------- 1 | #register-msg:empty{display:none} 2 | .shinobi-bg{background:url(/libs/img/bg.jpg);background-size:cover;background-position:center;position:relative} 3 | .shinobi-bg{background:#333} 4 | .shinobi-bg-shade{position:absolute;height:100%;width:100%;background:rgba(0,0,0,0.5)} 5 | .panel-login { 6 | background:#343434; 7 | color:#ddd; 8 | margin-top:90px; 9 | border-color: #444; 10 | -webkit-box-shadow: 0px 2px 3px 0px rgba(0,0,0,0.2); 11 | -moz-box-shadow: 0px 2px 3px 0px rgba(0,0,0,0.2); 12 | box-shadow: 0px 2px 3px 0px rgba(0,0,0,0.2); 13 | } 14 | .panel-login>.panel-heading { 15 | color: #00415d; 16 | background-color: #333; 17 | color: #fff; 18 | border-color: #444; 19 | text-align:center; 20 | } 21 | .panel-login>.panel-heading a{ 22 | text-decoration: none; 23 | color: #666; 24 | font-weight: bold; 25 | font-size: 15px; 26 | -webkit-transition: all 0.1s linear; 27 | -moz-transition: all 0.1s linear; 28 | transition: all 0.1s linear; 29 | } 30 | .panel-login>.panel-heading a.active{ 31 | color: #3b75b4; 32 | } 33 | .panel-login>.panel-heading hr{ 34 | margin-top: 10px; 35 | margin-bottom: 0px; 36 | clear: both; 37 | border: 0; 38 | height: 1px; 39 | background-image: -webkit-linear-gradient(left,rgba(0, 0, 0, 0),rgba(0, 0, 0, 0.15),rgba(0, 0, 0, 0)); 40 | background-image: -moz-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.15),rgba(0,0,0,0)); 41 | background-image: -ms-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.15),rgba(0,0,0,0)); 42 | background-image: -o-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.15),rgba(0,0,0,0)); 43 | } 44 | .panel-login input[type="text"],.panel-login input[type="email"],.panel-login input[type="password"] { 45 | height: 45px; 46 | border: 1px solid #ddd; 47 | font-size: 16px; 48 | -webkit-transition: all 0.1s linear; 49 | -moz-transition: all 0.1s linear; 50 | transition: all 0.1s linear; 51 | } 52 | .panel-login input:hover, 53 | .panel-login input:focus { 54 | outline:none; 55 | -webkit-box-shadow: none; 56 | -moz-box-shadow: none; 57 | box-shadow: none; 58 | border-color: #ccc; 59 | } 60 | .btn-login { 61 | background-color: #59B2E0; 62 | outline: none; 63 | color: #fff; 64 | font-size: 14px; 65 | height: auto; 66 | font-weight: normal; 67 | padding: 14px 0; 68 | text-transform: uppercase; 69 | border-color: #59B2E6; 70 | } 71 | .btn-login:hover, 72 | .btn-login:focus { 73 | color: #fff; 74 | background-color: #53A3CD; 75 | border-color: #53A3CD; 76 | } 77 | .forgot-password { 78 | text-decoration: underline; 79 | color: #888; 80 | } 81 | .forgot-password:hover, 82 | .forgot-password:focus { 83 | text-decoration: underline; 84 | color: #666; 85 | } 86 | 87 | .btn-register { 88 | background-color: #1CB94E; 89 | outline: none; 90 | color: #fff; 91 | font-size: 14px; 92 | height: auto; 93 | font-weight: normal; 94 | padding: 14px 0; 95 | text-transform: uppercase; 96 | border-color: #1CB94A; 97 | } 98 | .btn-register:hover, 99 | .btn-register:focus { 100 | color: #fff; 101 | background-color: #1CA347; 102 | border-color: #1CA347; 103 | } 104 | 105 | .monospace{font-family: monospace;} -------------------------------------------------------------------------------- /web/libs/css/pnotify.custom.min.css: -------------------------------------------------------------------------------- 1 | .ui-pnotify{top:36px;right:36px;position:absolute;height:auto;z-index:2}body>.ui-pnotify{position:fixed;z-index:100040}.ui-pnotify-modal-overlay{background-color:rgba(0,0,0,.4);top:0;left:0;position:absolute;height:100%;width:100%;z-index:1}body>.ui-pnotify-modal-overlay{position:fixed;z-index:100039}.ui-pnotify.ui-pnotify-in{display:block!important}.ui-pnotify.ui-pnotify-move{transition:left .5s ease,top .5s ease,right .5s ease,bottom .5s ease}.ui-pnotify.ui-pnotify-fade-slow{transition:opacity .6s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-slow.ui-pnotify.ui-pnotify-move{transition:opacity .6s linear,left .5s ease,top .5s ease,right .5s ease,bottom .5s ease}.ui-pnotify.ui-pnotify-fade-normal{transition:opacity .4s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-normal.ui-pnotify.ui-pnotify-move{transition:opacity .4s linear,left .5s ease,top .5s ease,right .5s ease,bottom .5s ease}.ui-pnotify.ui-pnotify-fade-fast{transition:opacity .2s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-fast.ui-pnotify.ui-pnotify-move{transition:opacity .2s linear,left .5s ease,top .5s ease,right .5s ease,bottom .5s ease}.ui-pnotify.ui-pnotify-fade-in{opacity:1}.ui-pnotify .ui-pnotify-shadow{-webkit-box-shadow:0 6px 28px 0 rgba(0,0,0,.1);-moz-box-shadow:0 6px 28px 0 rgba(0,0,0,.1);box-shadow:0 6px 28px 0 rgba(0,0,0,.1)}.ui-pnotify-container{background-position:0 0;padding:.8em;height:100%;margin:0}.ui-pnotify-container:after{content:" ";visibility:hidden;display:block;height:0;clear:both}.ui-pnotify-container.ui-pnotify-sharp{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.ui-pnotify-title{display:block;margin-bottom:.4em;margin-top:0}.ui-pnotify-text{display:block}.ui-pnotify-icon,.ui-pnotify-icon span{display:block;float:left;margin-right:.2em}.ui-pnotify.stack-bottomleft,.ui-pnotify.stack-topleft{left:25px;right:auto}.ui-pnotify.stack-bottomleft,.ui-pnotify.stack-bottomright{bottom:25px;top:auto}.ui-pnotify.stack-modal{left:50%;right:auto;margin-left:-150px}.ui-pnotify-closer,.ui-pnotify-sticker{float:right;margin-left:.2em}.ui-pnotify-history-container{position:absolute;top:0;right:18px;width:70px;border-top:none;padding:0;-webkit-border-top-left-radius:0;-moz-border-top-left-radius:0;border-top-left-radius:0;-webkit-border-top-right-radius:0;-moz-border-top-right-radius:0;border-top-right-radius:0;z-index:10000}.ui-pnotify-history-container.ui-pnotify-history-fixed{position:fixed}.ui-pnotify-history-container .ui-pnotify-history-header{padding:2px;text-align:center}.ui-pnotify-history-container button{cursor:pointer;display:block;width:100%}.ui-pnotify-history-container .ui-pnotify-history-pulldown{display:block;margin:0 auto}.ui-pnotify-container{position:relative;left:0}@media (max-width:480px){.ui-pnotify-mobile-able.ui-pnotify{position:fixed;top:0;right:0;left:0;width:auto!important;font-size:1.2em;-webkit-font-smoothing:antialiased;-moz-font-smoothing:antialiased;-ms-font-smoothing:antialiased;font-smoothing:antialiased}.ui-pnotify-mobile-able.ui-pnotify .ui-pnotify-shadow{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;border-bottom-width:5px}.ui-pnotify-mobile-able .ui-pnotify-container{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.ui-pnotify-mobile-able.ui-pnotify.stack-bottomleft,.ui-pnotify-mobile-able.ui-pnotify.stack-topleft{left:0;right:0}.ui-pnotify-mobile-able.ui-pnotify.stack-bottomleft,.ui-pnotify-mobile-able.ui-pnotify.stack-bottomright{left:0;right:0;bottom:0;top:auto}.ui-pnotify-mobile-able.ui-pnotify.stack-bottomleft .ui-pnotify-shadow,.ui-pnotify-mobile-able.ui-pnotify.stack-bottomright .ui-pnotify-shadow{border-top-width:5px;border-bottom-width:1px}} -------------------------------------------------------------------------------- /web/libs/css/poseidon.css: -------------------------------------------------------------------------------- 1 | /* bug: pseudo selectors for :fullscreen, :-moz-full-screen, and :-webkit-full-screen cannot be grouped together */ 2 | 3 | /* styles for container div */ 4 | 5 | div.mse-container { 6 | position: relative; 7 | float: left; 8 | display: inline-block; 9 | background: linear-gradient(black, grey, black); 10 | border: 1px solid white; 11 | } 12 | 13 | div.mse-container:fullscreen { 14 | width: 100%; 15 | height: 100%; 16 | } 17 | 18 | div.mse-container:-ms-fullscreen { 19 | width: 100%; 20 | height: 100%; 21 | } 22 | 23 | div.mse-container:-moz-full-screen { 24 | width: 100%; 25 | height: 100%; 26 | } 27 | 28 | div.mse-container:-webkit-full-screen { 29 | width: 100%; 30 | height: 100%; 31 | } 32 | 33 | div.mse-container.disabled { 34 | pointer-events: none; 35 | opacity: 0.4; 36 | } 37 | 38 | /* styles for video */ 39 | 40 | video.mse-video { 41 | pointer-events: none; 42 | cursor: none; 43 | } 44 | 45 | div.mse-container:fullscreen video { 46 | width: 100%; 47 | height: 100%; 48 | } 49 | 50 | div.mse-container:-ms-fullscreen video { 51 | width: 100%; 52 | height: 100%; 53 | } 54 | 55 | div.mse-container:-moz-full-screen video { 56 | width: 100%; 57 | height: 100%; 58 | } 59 | 60 | div.mse-container:-webkit-full-screen video { 61 | width: 100%; 62 | height: 100%; 63 | } 64 | 65 | /* styles for controls div */ 66 | 67 | div.mse-controls { 68 | position: absolute; 69 | background: black; 70 | border: 1px solid white; 71 | left: 5px; 72 | right: 5px; 73 | bottom: 5px; 74 | padding: 3px; 75 | border-radius: 5px; 76 | opacity: 0; 77 | } 78 | 79 | div.mse-controls:hover { 80 | opacity: 0.8; 81 | } 82 | 83 | div.mse-container:fullscreen div { 84 | border: 2px solid white; 85 | left: 10px; 86 | right: 10px; 87 | bottom: 10px; 88 | padding: 6px; 89 | border-radius: 10px; 90 | } 91 | 92 | div.mse-container:-ms-fullscreen div { 93 | border: 2px solid white; 94 | left: 10px; 95 | right: 10px; 96 | bottom: 10px; 97 | padding: 6px; 98 | border-radius: 10px; 99 | } 100 | 101 | div.mse-container:-moz-full-screen div { 102 | border: 2px solid white; 103 | left: 10px; 104 | right: 10px; 105 | bottom: 10px; 106 | padding: 6px; 107 | border-radius: 10px; 108 | } 109 | 110 | div.mse-container:-webkit-full-screen div { 111 | border: 2px solid white; 112 | left: 10px; 113 | right: 10px; 114 | bottom: 10px; 115 | padding: 6px; 116 | border-radius: 10px; 117 | } 118 | 119 | /* styles for buttons */ 120 | 121 | div.mse-container button { 122 | background-color: transparent; 123 | border: none; 124 | outline: none; 125 | opacity: 0.8; 126 | cursor: pointer; 127 | color: white; 128 | font-size: 16px; 129 | margin: 1px; 130 | } 131 | 132 | div.mse-container button:hover { 133 | opacity: 1; 134 | } 135 | 136 | div.mse-container button:active { 137 | opacity: 0.6; 138 | } 139 | 140 | div.mse-container:fullscreen button { 141 | font-size: 32px; 142 | } 143 | 144 | div.mse-container:-ms-fullscreen button { 145 | font-size: 32px; 146 | } 147 | 148 | div.mse-container:-moz-full-screen button { 149 | font-size: 32px; 150 | } 151 | 152 | div.mse-container:-webkit-full-screen button { 153 | font-size: 32px; 154 | } 155 | 156 | button.mse-start, button.mse-stop, button.mse-snapshot { 157 | float: left; 158 | } 159 | 160 | button.mse-fullscreen, button.mse-cycle { 161 | float: right; 162 | } 163 | 164 | button.mse-start:before { 165 | font-family: FontAwesome; 166 | content: "\f04b"; 167 | } 168 | 169 | button.mse-stop:before { 170 | font-family: FontAwesome; 171 | content: "\f04d"; 172 | } 173 | 174 | button.mse-snapshot:before { 175 | font-family: FontAwesome; 176 | content: "\f030"; 177 | } 178 | 179 | button.mse-fullscreen:before { 180 | font-family: FontAwesome; 181 | content: "\f065"; 182 | } 183 | 184 | button.mse-stop.cycling { 185 | pointer-events: none; 186 | cursor: none; 187 | opacity: 0.2; 188 | } 189 | 190 | div.mse-container:fullscreen button.mse-fullscreen:before { 191 | font-family: FontAwesome; 192 | content: "\f066"; 193 | } 194 | 195 | div.mse-container:-ms-fullscreen button.mse-fullscreen:before { 196 | font-family: FontAwesome; 197 | content: "\f066"; 198 | } 199 | 200 | div.mse-container:-moz-full-screen button.mse-fullscreen:before { 201 | font-family: FontAwesome; 202 | content: "\f066"; 203 | } 204 | 205 | div.mse-container:-webkit-full-screen button.mse-fullscreen:before { 206 | font-family: FontAwesome; 207 | content: "\f066"; 208 | } 209 | 210 | button.mse-cycle:before { 211 | font-family: FontAwesome; 212 | content: "\f021";/* other cycle icon options : f021 f110 f01e f1ce */ 213 | } 214 | 215 | button.mse-cycle.animated { 216 | -webkit-animation: spin 5s linear infinite; 217 | animation: spin 5s linear infinite; 218 | } 219 | 220 | /* SPIN animation for cycle button */ 221 | 222 | @-webkit-keyframes spin { 223 | 0% { 224 | -webkit-transform: rotate(0deg); 225 | transform: rotate(0deg); 226 | } 227 | 228 | 100% { 229 | -webkit-transform: rotate(359deg); 230 | transform: rotate(359deg); 231 | } 232 | } 233 | 234 | @keyframes spin { 235 | 0% { 236 | -webkit-transform: rotate(0deg); 237 | -ms-transform: rotate(0deg); 238 | transform: rotate(0deg); 239 | } 240 | 241 | 100% { 242 | -webkit-transform: rotate(359deg); 243 | -ms-transform: rotate(359deg); 244 | transform: rotate(359deg); 245 | } 246 | } -------------------------------------------------------------------------------- /web/libs/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /web/libs/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /web/libs/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /web/libs/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /web/libs/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /web/libs/img/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/bg.jpg -------------------------------------------------------------------------------- /web/libs/img/demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/demo.jpg -------------------------------------------------------------------------------- /web/libs/img/icon/README.md: -------------------------------------------------------------------------------- 1 | # How do I make this Icon Set? 2 | 3 | Go to http://www.favicomatic.com/ , upload your image and let it do the magic. 4 | 5 | Remember! if you use favicomatic.com and it helps you, please consider donating to them. 6 | 7 | - Moe Alam -------------------------------------------------------------------------------- /web/libs/img/icon/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /web/libs/img/icon/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /web/libs/img/icon/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /web/libs/img/icon/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /web/libs/img/icon/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /web/libs/img/icon/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /web/libs/img/icon/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /web/libs/img/icon/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /web/libs/img/icon/circle-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/circle-text.png -------------------------------------------------------------------------------- /web/libs/img/icon/favicon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/favicon-128.png -------------------------------------------------------------------------------- /web/libs/img/icon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/favicon-16x16.png -------------------------------------------------------------------------------- /web/libs/img/icon/favicon-196x196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/favicon-196x196.png -------------------------------------------------------------------------------- /web/libs/img/icon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/favicon-32x32.png -------------------------------------------------------------------------------- /web/libs/img/icon/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/favicon-96x96.png -------------------------------------------------------------------------------- /web/libs/img/icon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/favicon.ico -------------------------------------------------------------------------------- /web/libs/img/icon/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/mstile-144x144.png -------------------------------------------------------------------------------- /web/libs/img/icon/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/mstile-150x150.png -------------------------------------------------------------------------------- /web/libs/img/icon/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/mstile-310x150.png -------------------------------------------------------------------------------- /web/libs/img/icon/mstile-310x310-circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/mstile-310x310-circle.png -------------------------------------------------------------------------------- /web/libs/img/icon/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/mstile-310x310.png -------------------------------------------------------------------------------- /web/libs/img/icon/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeiscool/Shinobi/2600e91ff79290f0e3203f154356018f4f1846d2/web/libs/img/icon/mstile-70x70.png -------------------------------------------------------------------------------- /web/libs/js/clock.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | var monthNames = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]; 3 | var dayNames= ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"] 4 | 5 | var newDate = new Date(); 6 | newDate.setDate(newDate.getDate()); 7 | $('#time-date').html(dayNames[newDate.getDay()] + " " + newDate.getDate() + ' ' + monthNames[newDate.getMonth()] + ' ' + newDate.getFullYear()); 8 | 9 | var second=function() { 10 | var seconds = new Date().getSeconds(); 11 | document.getElementById("time-sec").innerHTML=( seconds < 10 ? "0" : "" ) + seconds; 12 | } 13 | var minute=function() { 14 | var minutes = new Date().getMinutes(); 15 | document.getElementById("time-min").innerHTML=(( minutes < 10 ? "0" : "" ) + minutes); 16 | } 17 | var hour=function() { 18 | var hours = new Date().getHours(); 19 | var element=$("#time-hours"); 20 | hours = ( hours < 10 ? "0" : "" ) + hours; 21 | if(element.hasClass('twentyfour')&&hours>12){hours=hours-12} 22 | element.html(hours); 23 | } 24 | setInterval(function(){second(),minute(),hour();},1000); 25 | second(),minute(),hour(); 26 | }); -------------------------------------------------------------------------------- /web/libs/js/clusterPoints.js: -------------------------------------------------------------------------------- 1 | // Original is by Nathan Epstein and found at https://github.com/NathanEpstein/clusters/blob/master/clusters.js 2 | // Modified for browser 3 | 4 | var Cluster = { 5 | 6 | data: getterSetter([], function(arrayOfArrays) { 7 | if(!arrayOfArrays[0]){ 8 | arrayOfArrays[0]=[0,0] 9 | } 10 | var n = arrayOfArrays[0].length; 11 | return (arrayOfArrays.map(function(array) { 12 | return array.length == n; 13 | }).reduce(function(boolA, boolB) { return (boolA & boolB) }, true)); 14 | }), 15 | 16 | clusters: function() { 17 | var pointsAndCentroids = kmeans(this.data(), {k: this.k(), iterations: this.iterations() }); 18 | var points = pointsAndCentroids.points; 19 | var centroids = pointsAndCentroids.centroids; 20 | 21 | return centroids.map(function(centroid) { 22 | return { 23 | centroid: centroid.location(), 24 | points: points.filter(function(point) { return point.label() == centroid.label() }).map(function(point) { return point.location() }), 25 | }; 26 | }); 27 | }, 28 | 29 | k: getterSetter(undefined, function(value) { return ((value % 1 == 0) & (value > 0)) }), 30 | 31 | iterations: getterSetter(Math.pow(10, 3), function(value) { return ((value % 1 == 0) & (value > 0)) }), 32 | 33 | }; 34 | 35 | function kmeans(data, config) { 36 | // default k 37 | var k = config.k || Math.round(Math.sqrt(data.length / 2)); 38 | var iterations = config.iterations; 39 | 40 | // initialize point objects with data 41 | var points = data.map(function(vector) { return new Point(vector) }); 42 | 43 | // intialize centroids randomly 44 | var centroids = []; 45 | for (var i = 0; i < k; i++) { 46 | centroids.push(new Centroid(points[i % points.length].location(), i)); 47 | }; 48 | 49 | // update labels and centroid locations until convergence 50 | for (var iter = 0; iter < iterations; iter++) { 51 | points.forEach(function(point) { point.updateLabel(centroids) }); 52 | centroids.forEach(function(centroid) { centroid.updateLocation(points) }); 53 | }; 54 | 55 | // return points and centroids 56 | return { 57 | points: points, 58 | centroids: centroids 59 | }; 60 | 61 | }; 62 | 63 | // objects 64 | function Point(location) { 65 | var self = this; 66 | this.location = getterSetter(location); 67 | this.label = getterSetter(); 68 | this.updateLabel = function(centroids) { 69 | var distancesSquared = centroids.map(function(centroid) { 70 | return sumOfSquareDiffs(self.location(), centroid.location()); 71 | }); 72 | self.label(mindex(distancesSquared)); 73 | }; 74 | }; 75 | 76 | function Centroid(initialLocation, label) { 77 | var self = this; 78 | this.location = getterSetter(initialLocation); 79 | this.label = getterSetter(label); 80 | this.updateLocation = function(points) { 81 | var pointsWithThisCentroid = points.filter(function(point) { return point.label() == self.label() }); 82 | if (pointsWithThisCentroid.length > 0) self.location(averageLocation(pointsWithThisCentroid)); 83 | }; 84 | }; 85 | 86 | // convenience functions 87 | function getterSetter(initialValue, validator) { 88 | var thingToGetSet = initialValue; 89 | var isValid = validator || function(val) { return true }; 90 | return function(newValue) { 91 | if (typeof newValue === 'undefined') return thingToGetSet; 92 | if (isValid(newValue)) thingToGetSet = newValue; 93 | }; 94 | }; 95 | 96 | function sumOfSquareDiffs(oneVector, anotherVector) { 97 | var squareDiffs = oneVector.map(function(component, i) { 98 | return Math.pow(component - anotherVector[i], 2); 99 | }); 100 | return squareDiffs.reduce(function(a, b) { return a + b }, 0); 101 | }; 102 | 103 | function mindex(array) { 104 | var min = array.reduce(function(a, b) { 105 | return Math.min(a, b); 106 | }); 107 | return array.indexOf(min); 108 | }; 109 | 110 | function sumVectors(a, b) { 111 | return a.map(function(val, i) { return val + b[i] }); 112 | }; 113 | 114 | function averageLocation(points) { 115 | var zeroVector = points[0].location().map(function() { return 0 }); 116 | var locations = points.map(function(point) { return point.location() }); 117 | var vectorSum = locations.reduce(function(a, b) { return sumVectors(a, b) }, zeroVector); 118 | return vectorSum.map(function(val) { return val / points.length }); 119 | }; -------------------------------------------------------------------------------- /web/libs/js/gcal.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * FullCalendar v3.0.1 Google Calendar Plugin 3 | * Docs & License: http://fullcalendar.io/ 4 | * (c) 2016 Adam Shaw 5 | */ 6 | 7 | (function(factory) { 8 | if (typeof define === 'function' && define.amd) { 9 | define([ 'jquery' ], factory); 10 | } 11 | else if (typeof exports === 'object') { // Node/CommonJS 12 | module.exports = factory(require('jquery')); 13 | } 14 | else { 15 | factory(jQuery); 16 | } 17 | })(function($) { 18 | 19 | 20 | var API_BASE = 'https://www.googleapis.com/calendar/v3/calendars'; 21 | var FC = $.fullCalendar; 22 | var applyAll = FC.applyAll; 23 | 24 | 25 | FC.sourceNormalizers.push(function(sourceOptions) { 26 | var googleCalendarId = sourceOptions.googleCalendarId; 27 | var url = sourceOptions.url; 28 | var match; 29 | 30 | // if the Google Calendar ID hasn't been explicitly defined 31 | if (!googleCalendarId && url) { 32 | 33 | // detect if the ID was specified as a single string. 34 | // will match calendars like "asdf1234@calendar.google.com" in addition to person email calendars. 35 | if (/^[^\/]+@([^\/\.]+\.)*(google|googlemail|gmail)\.com$/.test(url)) { 36 | googleCalendarId = url; 37 | } 38 | // try to scrape it out of a V1 or V3 API feed URL 39 | else if ( 40 | (match = /^https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/([^\/]*)/.exec(url)) || 41 | (match = /^https?:\/\/www.google.com\/calendar\/feeds\/([^\/]*)/.exec(url)) 42 | ) { 43 | googleCalendarId = decodeURIComponent(match[1]); 44 | } 45 | 46 | if (googleCalendarId) { 47 | sourceOptions.googleCalendarId = googleCalendarId; 48 | } 49 | } 50 | 51 | 52 | if (googleCalendarId) { // is this a Google Calendar? 53 | 54 | // make each Google Calendar source uneditable by default 55 | if (sourceOptions.editable == null) { 56 | sourceOptions.editable = false; 57 | } 58 | 59 | // We want removeEventSource to work, but it won't know about the googleCalendarId primitive. 60 | // Shoehorn it into the url, which will function as the unique primitive. Won't cause side effects. 61 | // This hack is obsolete since 2.2.3, but keep it so this plugin file is compatible with old versions. 62 | sourceOptions.url = googleCalendarId; 63 | } 64 | }); 65 | 66 | 67 | FC.sourceFetchers.push(function(sourceOptions, start, end, timezone) { 68 | if (sourceOptions.googleCalendarId) { 69 | return transformOptions(sourceOptions, start, end, timezone, this); // `this` is the calendar 70 | } 71 | }); 72 | 73 | 74 | function transformOptions(sourceOptions, start, end, timezone, calendar) { 75 | var url = API_BASE + '/' + encodeURIComponent(sourceOptions.googleCalendarId) + '/events?callback=?'; // jsonp 76 | var apiKey = sourceOptions.googleCalendarApiKey || calendar.options.googleCalendarApiKey; 77 | var success = sourceOptions.success; 78 | var data; 79 | var timezoneArg; // populated when a specific timezone. escaped to Google's liking 80 | 81 | function reportError(message, apiErrorObjs) { 82 | var errorObjs = apiErrorObjs || [ { message: message } ]; // to be passed into error handlers 83 | 84 | // call error handlers 85 | (sourceOptions.googleCalendarError || $.noop).apply(calendar, errorObjs); 86 | (calendar.options.googleCalendarError || $.noop).apply(calendar, errorObjs); 87 | 88 | // print error to debug console 89 | FC.warn.apply(null, [ message ].concat(apiErrorObjs || [])); 90 | } 91 | 92 | if (!apiKey) { 93 | reportError("Specify a googleCalendarApiKey. See http://fullcalendar.io/docs/google_calendar/"); 94 | return {}; // an empty source to use instead. won't fetch anything. 95 | } 96 | 97 | // The API expects an ISO8601 datetime with a time and timezone part. 98 | // Since the calendar's timezone offset isn't always known, request the date in UTC and pad it by a day on each 99 | // side, guaranteeing we will receive all events in the desired range, albeit a superset. 100 | // .utc() will set a zone and give it a 00:00:00 time. 101 | if (!start.hasZone()) { 102 | start = start.clone().utc().add(-1, 'day'); 103 | } 104 | if (!end.hasZone()) { 105 | end = end.clone().utc().add(1, 'day'); 106 | } 107 | 108 | // when sending timezone names to Google, only accepts underscores, not spaces 109 | if (timezone && timezone != 'local') { 110 | timezoneArg = timezone.replace(' ', '_'); 111 | } 112 | 113 | data = $.extend({}, sourceOptions.data || {}, { 114 | key: apiKey, 115 | timeMin: start.format(), 116 | timeMax: end.format(), 117 | timeZone: timezoneArg, 118 | singleEvents: true, 119 | maxResults: 9999 120 | }); 121 | 122 | return $.extend({}, sourceOptions, { 123 | googleCalendarId: null, // prevents source-normalizing from happening again 124 | url: url, 125 | data: data, 126 | startParam: false, // `false` omits this parameter. we already included it above 127 | endParam: false, // same 128 | timezoneParam: false, // same 129 | success: function(data) { 130 | var events = []; 131 | var successArgs; 132 | var successRes; 133 | 134 | if (data.error) { 135 | reportError('Google Calendar API: ' + data.error.message, data.error.errors); 136 | } 137 | else if (data.items) { 138 | $.each(data.items, function(i, entry) { 139 | var url = entry.htmlLink || null; 140 | 141 | // make the URLs for each event show times in the correct timezone 142 | if (timezoneArg && url !== null) { 143 | url = injectQsComponent(url, 'ctz=' + timezoneArg); 144 | } 145 | 146 | events.push({ 147 | id: entry.id, 148 | title: entry.summary, 149 | start: entry.start.dateTime || entry.start.date, // try timed. will fall back to all-day 150 | end: entry.end.dateTime || entry.end.date, // same 151 | url: url, 152 | location: entry.location, 153 | description: entry.description 154 | }); 155 | }); 156 | 157 | // call the success handler(s) and allow it to return a new events array 158 | successArgs = [ events ].concat(Array.prototype.slice.call(arguments, 1)); // forward other jq args 159 | successRes = applyAll(success, this, successArgs); 160 | if ($.isArray(successRes)) { 161 | return successRes; 162 | } 163 | } 164 | 165 | return events; 166 | } 167 | }); 168 | } 169 | 170 | 171 | // Injects a string like "arg=value" into the querystring of a URL 172 | function injectQsComponent(url, component) { 173 | // inject it after the querystring but before the fragment 174 | return url.replace(/(\?.*?)?(#|$)/, function(whole, qs, hash) { 175 | return (qs ? qs + '&' : '?') + component + hash; 176 | }); 177 | } 178 | 179 | 180 | }); 181 | -------------------------------------------------------------------------------- /web/libs/js/jquery.serialize.js: -------------------------------------------------------------------------------- 1 | jQuery.fn.serializeObject=function (){"use strict";var result={};var extend=function (i, element){var node=result[element.name];if ('undefined' !==typeof node && node !==null){if (jQuery.isArray(node)){node.push(element.value);}else{result[element.name]=[node, element.value];}}else{result[element.name]=element.value;}};jQuery.each(this.serializeArray(), extend);return result;}; -------------------------------------------------------------------------------- /web/libs/js/livestamp.min.js: -------------------------------------------------------------------------------- 1 | // Livestamp.js / v1.1.2 / (c) 2012 Matt Bradley / MIT License 2 | (function(d,g){var h=1E3,i=!1,e=d([]),j=function(b,a){var c=b.data("livestampdata");"number"==typeof a&&(a*=1E3);b.removeAttr("data-livestamp").removeData("livestamp");a=g(a);g.isMoment(a)&&!isNaN(+a)&&(c=d.extend({},{original:b.contents()},c),c.moment=g(a),b.data("livestampdata",c).empty(),e.push(b[0]))},k=function(){i||(f.update(),setTimeout(k,h))},f={update:function(){d("[data-livestamp]").each(function(){var a=d(this);j(a,a.data("livestamp"))});var b=[];e.each(function(){var a=d(this),c=a.data("livestampdata"); 3 | if(void 0===c)b.push(this);else if(g.isMoment(c.moment)){var e=a.html(),c=c.moment.fromNow();if(e!=c){var f=d.Event("change.livestamp");a.trigger(f,[e,c]);f.isDefaultPrevented()||a.html(c)}}});e=e.not(b)},pause:function(){i=!0},resume:function(){i=!1;k()},interval:function(b){if(void 0===b)return h;h=b}},l={add:function(b,a){"number"==typeof a&&(a*=1E3);a=g(a);g.isMoment(a)&&!isNaN(+a)&&(b.each(function(){j(d(this),a)}),f.update());return b},destroy:function(b){e=e.not(b);b.each(function(){var a= 4 | d(this),c=a.data("livestampdata");if(void 0===c)return b;a.html(c.original?c.original:"").removeData("livestampdata")});return b},isLivestamp:function(b){return void 0!==b.data("livestampdata")}};d.livestamp=f;d(function(){f.resume()});d.fn.livestamp=function(b,a){l[b]||(a=b,b="add");return l[b](this,a)}})(jQuery,moment); 5 | -------------------------------------------------------------------------------- /web/libs/js/menu.js: -------------------------------------------------------------------------------- 1 | jQuery(document).ready(function($){ 2 | 3 | var navigationContainer = $('#cd-nav').addClass('is-fixed'), 4 | mainNavigation = navigationContainer.find('#cd-main-nav ul'); 5 | 6 | //open or close the menu clicking on the bottom "menu" link 7 | $('#cd-nav li a').on('click', function(){ 8 | $('.cd-nav-trigger').click(); 9 | }) 10 | $('.cd-nav-trigger').on('click', function(){ 11 | $(this).toggleClass('menu-is-open'); 12 | //we need to remove the transitionEnd event handler (we add it when scolling up with the menu open) 13 | mainNavigation.off('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend').toggleClass('is-visible'); 14 | 15 | }); 16 | 17 | }); -------------------------------------------------------------------------------- /web/libs/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /web/libs/js/placeholder.js: -------------------------------------------------------------------------------- 1 | (function($){!function(t,e){"object"==typeof module&&module.exports?module.exports=e(t):t.placeholder=e(t)}("undefined"!=typeof window?window:this,function(){function t(t){c&&u||(c=document.createElement("canvas"),u=c.getContext("2d"));var e=parseInt(t.a[0]),n=parseInt(t.a[1]);c.width=e,c.height=n,u.clearRect(0,0,e,n),u.fillStyle=t.c,u.fillRect(0,0,e,n),u.fillStyle=t.d,u.font=t.e+" normal "+t.f+" "+(t.g||100)+"px "+t.h;var r=1;if(""===t.g){var o=.7*e,l=.7*n,i=u.measureText(t.b).width,a=100;r=Math.min(o/i,l/a)}return u.translate(e/2,n/2),u.scale(r,r),u.textAlign="center",u.textBaseline="middle",u.fillText(t.b,0,0),c}function e(){return"#"+("00000"+(16777216*Math.random()<<0).toString(16)).slice(-6)}function n(t){t=t||{};var n=t.size||"128x128",r=t.text||n,o=t.bgcolor||e(),l=t.color||e(),i=t.fstyle||"normal",a=t.fweight||"bold",c=t.fsize||"",u=t.ffamily||"consolas",f={};return n=n.split("x"),2!==n.length&&(n=[128,128]),f.a=n,f.b=r,f.c=o,f.d=l,f.e=i,f.f=a,f.g=c,f.h=u,t=null,f}function r(e){return e=n(e),t(e)}function o(t){return r(t).toDataURL()}function l(t,e,n){return t.getAttribute(e)||n}function i(t){var e,n={},r=t.split("&");for(var o in r){e=r[o].split("=");try{n[e[0]]=decodeURIComponent(e[1])}catch(l){n[e[0]]=e[1]}}return n}function a(t){for(var e,n,r=document.querySelectorAll("img.placeholder"),a=0;a li { position: relative; } 9 | } 10 | .@{fa-css-prefix}-li { 11 | position: absolute; 12 | left: -@fa-li-width; 13 | width: @fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.@{fa-css-prefix}-lg { 17 | left: (-@fa-li-width + (4em / 14)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /web/libs/less/mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | .fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | 14 | .fa-icon-rotate(@degrees, @rotation) { 15 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation})"; 16 | -webkit-transform: rotate(@degrees); 17 | -ms-transform: rotate(@degrees); 18 | transform: rotate(@degrees); 19 | } 20 | 21 | .fa-icon-flip(@horiz, @vert, @rotation) { 22 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation}, mirror=1)"; 23 | -webkit-transform: scale(@horiz, @vert); 24 | -ms-transform: scale(@horiz, @vert); 25 | transform: scale(@horiz, @vert); 26 | } 27 | 28 | 29 | // Only display content to screen readers. A la Bootstrap 4. 30 | // 31 | // See: http://a11yproject.com/posts/how-to-hide-content/ 32 | 33 | .sr-only() { 34 | position: absolute; 35 | width: 1px; 36 | height: 1px; 37 | padding: 0; 38 | margin: -1px; 39 | overflow: hidden; 40 | clip: rect(0,0,0,0); 41 | border: 0; 42 | } 43 | 44 | // Use in conjunction with .sr-only to only display content when it's focused. 45 | // 46 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 47 | // 48 | // Credit: HTML5 Boilerplate 49 | 50 | .sr-only-focusable() { 51 | &:active, 52 | &:focus { 53 | position: static; 54 | width: auto; 55 | height: auto; 56 | margin: 0; 57 | overflow: visible; 58 | clip: auto; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /web/libs/less/path.less: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); 7 | src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), 8 | url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'), 9 | url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), 10 | url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), 11 | url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /web/libs/less/rotated-flipped.less: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } 5 | .@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } 6 | .@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } 7 | 8 | .@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } 9 | .@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .@{fa-css-prefix}-rotate-90, 15 | :root .@{fa-css-prefix}-rotate-180, 16 | :root .@{fa-css-prefix}-rotate-270, 17 | :root .@{fa-css-prefix}-flip-horizontal, 18 | :root .@{fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /web/libs/less/screen-reader.less: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { .sr-only(); } 5 | .sr-only-focusable { .sr-only-focusable(); } 6 | -------------------------------------------------------------------------------- /web/libs/less/stacked.less: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .@{fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .@{fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .@{fa-css-prefix}-inverse { color: @fa-inverse; } 21 | -------------------------------------------------------------------------------- /web/libs/scss/_animated.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .#{$fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /web/libs/scss/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em $fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .#{$fa-css-prefix}-pull-left { float: left; } 11 | .#{$fa-css-prefix}-pull-right { float: right; } 12 | 13 | .#{$fa-css-prefix} { 14 | &.#{$fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.#{$fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .#{$fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /web/libs/scss/_core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /web/libs/scss/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /web/libs/scss/_larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .#{$fa-css-prefix}-2x { font-size: 2em; } 11 | .#{$fa-css-prefix}-3x { font-size: 3em; } 12 | .#{$fa-css-prefix}-4x { font-size: 4em; } 13 | .#{$fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /web/libs/scss/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: $fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .#{$fa-css-prefix}-li { 11 | position: absolute; 12 | left: -$fa-li-width; 13 | width: $fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.#{$fa-css-prefix}-lg { 17 | left: -$fa-li-width + (4em / 14); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /web/libs/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | 14 | @mixin fa-icon-rotate($degrees, $rotation) { 15 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})"; 16 | -webkit-transform: rotate($degrees); 17 | -ms-transform: rotate($degrees); 18 | transform: rotate($degrees); 19 | } 20 | 21 | @mixin fa-icon-flip($horiz, $vert, $rotation) { 22 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)"; 23 | -webkit-transform: scale($horiz, $vert); 24 | -ms-transform: scale($horiz, $vert); 25 | transform: scale($horiz, $vert); 26 | } 27 | 28 | 29 | // Only display content to screen readers. A la Bootstrap 4. 30 | // 31 | // See: http://a11yproject.com/posts/how-to-hide-content/ 32 | 33 | @mixin sr-only { 34 | position: absolute; 35 | width: 1px; 36 | height: 1px; 37 | padding: 0; 38 | margin: -1px; 39 | overflow: hidden; 40 | clip: rect(0,0,0,0); 41 | border: 0; 42 | } 43 | 44 | // Use in conjunction with .sr-only to only display content when it's focused. 45 | // 46 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 47 | // 48 | // Credit: HTML5 Boilerplate 49 | 50 | @mixin sr-only-focusable { 51 | &:active, 52 | &:focus { 53 | position: static; 54 | width: auto; 55 | height: auto; 56 | margin: 0; 57 | overflow: visible; 58 | clip: auto; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /web/libs/scss/_path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); 7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), 8 | url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), 9 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), 10 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), 11 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /web/libs/scss/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .#{$fa-css-prefix}-rotate-90, 15 | :root .#{$fa-css-prefix}-rotate-180, 16 | :root .#{$fa-css-prefix}-rotate-270, 17 | :root .#{$fa-css-prefix}-flip-horizontal, 18 | :root .#{$fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /web/libs/scss/_screen-reader.scss: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { @include sr-only(); } 5 | .sr-only-focusable { @include sr-only-focusable(); } 6 | -------------------------------------------------------------------------------- /web/libs/scss/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; } 21 | -------------------------------------------------------------------------------- /web/libs/scss/font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables"; 7 | @import "mixins"; 8 | @import "path"; 9 | @import "core"; 10 | @import "larger"; 11 | @import "fixed-width"; 12 | @import "list"; 13 | @import "bordered-pulled"; 14 | @import "animated"; 15 | @import "rotated-flipped"; 16 | @import "stacked"; 17 | @import "icons"; 18 | @import "screen-reader"; 19 | -------------------------------------------------------------------------------- /web/libs/themes/Enterprise Blue/style.css: -------------------------------------------------------------------------------- 1 | #main_header { 2 | background: #122444; 3 | color: #fff; 4 | } 5 | .demo-drawer { 6 | background: #1b2d4c; 7 | color: #fff; 8 | } 9 | #main_canvas { 10 | background: #2b3a50; 11 | color: #333; 12 | } 13 | .monitor_item .mdl-card__media { 14 | background: #fbfbfb; 15 | } 16 | .monitor_item .stream-block { 17 | background: #000; 18 | } 19 | .monitor_item .mdl-card { 20 | border: 1px solid #b7b7b7; 21 | } 22 | .monitor_item .mdl-card__supporting-text { 23 | background: #122444; 24 | color: #fff!important; 25 | } 26 | .progress-bar-warning { 27 | background-color: #b59f00; 28 | } 29 | .monitor_item .side-menu { 30 | background: #1b2431; 31 | color: #fff; 32 | } 33 | .monitor_item .mdl-card { 34 | border: 1px solid #122444; 35 | } 36 | .dark.modal .modal-header,.dark.modal .modal-footer{background:#091222;border-color:#222;} 37 | .dark.modal .modal-body{background:#151d28;} 38 | .form-group-group.forestgreen {border-color: #091222;} 39 | .form-group-group.forestgreen h4 {background: #091222;} 40 | .dark .form-group-group {background: #18253e;} 41 | .dark .list-group-item {background: #091222;border-color: #18253e;} -------------------------------------------------------------------------------- /web/pages/blocks/api.ejs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/pages/blocks/confirm.ejs: -------------------------------------------------------------------------------- 1 | 2 | 19 | -------------------------------------------------------------------------------- /web/pages/blocks/filters.ejs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/pages/blocks/github.ejs: -------------------------------------------------------------------------------- 1 | 2 | 22 | 38 | -------------------------------------------------------------------------------- /web/pages/blocks/header.ejs: -------------------------------------------------------------------------------- 1 | 2 | <%-lang.Shinobi%> 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | <% cleanLang=function(string){ 34 | if(!string){string=''} 35 | return string.replace(/'/g,"\\'") 36 | } %> -------------------------------------------------------------------------------- /web/pages/blocks/help.ejs: -------------------------------------------------------------------------------- 1 | 2 | 46 | -------------------------------------------------------------------------------- /web/pages/blocks/logs.ejs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/pages/blocks/powervideo.ejs: -------------------------------------------------------------------------------- 1 | 2 | 87 | -------------------------------------------------------------------------------- /web/pages/blocks/probe.ejs: -------------------------------------------------------------------------------- 1 | 2 | 39 | 40 | -------------------------------------------------------------------------------- /web/pages/blocks/region.ejs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/pages/blocks/subpermissions.ejs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/pages/blocks/timelapse.ejs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/pages/blocks/videoview.ejs: -------------------------------------------------------------------------------- 1 | 2 | 48 | 49 | -------------------------------------------------------------------------------- /web/pages/factor.ejs: -------------------------------------------------------------------------------- 1 | <% include blocks/header %> 2 |
3 |
4 |
5 |
6 |
7 | 48 |
49 |
50 |
51 |
52 |
53 | 54 | 70 | -------------------------------------------------------------------------------- /web/pages/mjpeg.ejs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/pages/script.ejs: -------------------------------------------------------------------------------- 1 | <%- include('../libs/js/'+file) %> -------------------------------------------------------------------------------- /web/pages/streamer.ejs: -------------------------------------------------------------------------------- 1 | <% include blocks/header %> 2 | 3 | 4 |
5 | Stream 6 |
7 | 8 |
9 |
Monitor to Stream and Save under
10 | requires https or firefox 11 |
12 |
13 |
14 |
15 | Logout 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | 134 | 144 | --------------------------------------------------------------------------------