├── .version ├── .gitignore ├── configure ├── AUTHORS ├── info ├── main.py ├── LICENSE ├── Makefile ├── README.org └── main.sh /.version: -------------------------------------------------------------------------------- 1 | 1.2 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.deb 2 | *.html 3 | *.pdf 4 | *.png 5 | *.sch 6 | *.txt 7 | batti.sch 8 | batti.sh 9 | deb/ 10 | droid/ 11 | path.config -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | echo "Checking: dependencies" 6 | list="wget sed pdftotext python" 7 | for item in $list; do 8 | echo -ne "\t" 9 | which $item 10 | done 11 | 12 | if [ -d .git ]; then 13 | git describe --tags > .version 14 | cat .version 15 | fi 16 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # Creator 2 | zerOnepal 3 | 4 | # Maintainer 5 | no one do you want to? 6 | 7 | # Contributors 8 | Avinash Kundaliya 9 | Batsal Awaley 10 | Manish Munikar 11 | Samundra Shrestha 12 | Sujit Maharjan 13 | krazedkrish 14 | rho 15 | -------------------------------------------------------------------------------- /info: -------------------------------------------------------------------------------- 1 | Package: batti 2 | Version: 0.1 3 | Architecture: all 4 | Maintainer: Sujit Maharjan 5 | Installed-Size: 1 6 | Depends: bash, sed, poppler-utils 7 | Section: testing 8 | Priority: optional 9 | Homepage: https://github.com/foss-np/batti/ 10 | Description: Load-shedding information written in bash 11 | batti is a bash script that can automatically download the load-shedding schedule from the NEA website and display in the terminal. 12 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from __future__ import print_function 3 | 4 | import sys 5 | 6 | data = open(sys.argv[1]).read() 7 | 8 | row = [ [], [], [], [], [], [], [] ] 9 | for line in data.splitlines()[1:]: 10 | b = 16 11 | for i in range(7): 12 | a = b 13 | b = a + 12 14 | guess = line[a:b].strip() 15 | l = len(guess) 16 | if l == 0: continue 17 | elif l < 11: 18 | b = b + (12 - l) 19 | guess = line[a:b].strip() 20 | 21 | row[i].append(guess) 22 | 23 | 24 | n = max(len(l) for l in row) 25 | flag = False 26 | 27 | for i in range(n): 28 | if flag: break 29 | for j, col in enumerate(row): 30 | try: 31 | val = col[i] 32 | except: 33 | val = "--:-----:--" 34 | 35 | if i > 0: 36 | if row[j-1][0] == val: 37 | val = "--:-----:--" 38 | flag = True 39 | 40 | print(val, end="\t") 41 | print() 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2013 The batti Authors 2 | This project "batti" is licensed under a Creative Commons Attribution 3.0 Unported License. 3 | 4 | You are free: 5 | to Share — to copy, distribute and transmit the work 6 | to Remix — to adapt the work 7 | to make commercial use of the work 8 | 9 | Under the following conditions: 10 | Attribution — You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work). 11 | 12 | With the understanding that: 13 | Waiver — Any of the above conditions can be waived if you get permission from the copyright holder. 14 | Public Domain — Where the work or any of its elements is in the public domain under applicable law, that status is in no way affected by the license. 15 | Other Rights — In no way are any of the following rights affected by the license: 16 | Your fair dealing or fair use rights, or other applicable copyright exceptions and limitations; 17 | The author's moral rights; 18 | Rights other persons may have either in the work itself or in how the work is used, such as publicity or privacy rights. 19 | Notice — For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to this web page. 20 | 21 | Based on a work at https://github.com/foss-np/batti. 22 | To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/deed.en_US. 23 | Permissions beyond the scope of this license may be available at info@fossnepal.org. 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SOURCES = main.sh main.py 2 | SUPPORT = README.org AUTHORS LICENSE .version 3 | PKG_NAME = batti 4 | FILE_CONFIG="${HOME}/.cache/batti.sch" 5 | 6 | default: 7 | ./main.sh 8 | @echo "This was the DEMO, use make install" 9 | 10 | all: 11 | @echo "# Not implemented" 12 | @echo "build programs lib, doc." 13 | 14 | unlink: 15 | rm -f /usr/local/bin/${PKG_NAME} 16 | 17 | uninstall: unlink 18 | rm -rf /opt/${PKG_NAME} 19 | 20 | link: unlink 21 | ln -s "$(PWD)/main.sh" /usr/local/bin/${PKG_NAME} 22 | 23 | alias: 24 | @echo "add alias in to '.bashrc'" 25 | @echo "alias ${PKG_NAME}='$PWD/main.sh'" 26 | 27 | install: unlink uninstall 28 | mkdir -p /opt/${PKG_NAME} 29 | install -m 755 ${SOURCES} -t /opt/${PKG_NAME}/ 30 | cp ${SUPPORT} /opt/${PKG_NAME}/ 31 | ln -s /opt/${PKG_NAME}/main.sh /usr/local/bin/${PKG_NAME} 32 | 33 | installcheck: 34 | @echo "# Not implemented" 35 | @echo ${SOURCES} 36 | 37 | clean: deb-clean droid-clean 38 | @echo "erase what has been buit (opposite of make all)" 39 | 40 | dist: 41 | @echo "# Not implemented" 42 | @echo "create PACKAGE-VERSION.tar.gz" 43 | 44 | droid: 45 | @echo "# Compacting for Android" 46 | mkdir droid 47 | sed 's|HOME/.cache|WD|' main.sh > droid/batti.sh 48 | chmod +x droid/batti.sh 49 | ./main.sh -d > droid/batti.sch 50 | [ -e .version ] && cp .version droid/ 51 | 52 | droid-clean: 53 | rm -rf droid 54 | 55 | distclean: clean droid-clean deb-clean 56 | @echo "# Not implemented" 57 | @echo "erase what ever done by make all, then clean what ever done by ./configure" 58 | 59 | distcheck: 60 | @echo "# Not implemented" 61 | @echo "do sanity check" 62 | 63 | check: 64 | @echo "# Not implemented" 65 | @echo "run the test suite if any" 66 | 67 | deb: deb-clean 68 | @echo "creates debain package" 69 | mkdir -p deb/DEBIAN 70 | mkdir -p deb/usr/local/bin 71 | cp main.sh deb/usr/local/bin/batti 72 | cp info deb/DEBIAN/control 73 | dpkg-deb --build deb . 74 | 75 | deb-clean: 76 | rm -rf deb 77 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | #+TITLE: batti 2 | #+DATE: Monday, Mar 14 2016 3 | #+OPTIONS: num:t 4 | #+STARTUP: showall 5 | 6 | *NOTE FROM MAINTAINER: I have stop working on this, anyone is most welcome to Pick it up* 7 | 8 | Load-shedding information used to be completely written in *bash* 9 | until the blockade started. It downloads and extract schedule form [[http://www.nea.org.np/loadshedding.html][nea]] 10 | as and processes your query. 11 | 12 | Hoping you will never need these kinda thing. 13 | 14 | [[https://raw.github.com/foss-np/batti/gh-pages/images/screenshot.png]] 15 | 16 | [[Creative Commons Attribution 3.0 Unported License][file:http://i.creativecommons.org/l/by/3.0/88x31.png]] 17 | 18 | batti Copyright © 2016 to the batti authors. 19 | 20 | * Installation 21 | ** Arch 22 | #+BEGIN_SRC bash 23 | yaourt batti-git 24 | #+END_SRC 25 | 26 | ** Ubuntu 27 | add repo into `/etc/apt/sources.list` 28 | #+BEGIN_SRC bash 29 | $ echo deb http://foss-np.github.io/deb-packages >> /etc/apt/sources.list 30 | $ sudo apt-get update 31 | $ sudo apt-get install batti 32 | #+END_SRC 33 | 34 | *** Building deb 35 | #+BEGIN_SRC bash 36 | $ make deb 37 | #+END_SRC 38 | 39 | :TIP: see make recipies 40 | 41 | ** Windows 42 | Currently there is no automated method, please follow *Manual* 43 | section. 44 | ** OS/X 45 | 46 | BSD sed will might work 47 | 48 | ** Manual 49 | *** Requirement 50 | | | linux | OS/X | ms-windows | 51 | |------------+---------------+------+---------------| 52 | | bash | bash | | git-bash/migw | 53 | | GNU sed* | sed | | gnu32 | 54 | | wget | wget | | wget | 55 | | pdftotext | poppler-utils | | poppler-utils | 56 | | python 2/3 | python | | python 3 | 57 | 58 | * BSD sed might not work 59 | 60 | =configure= will check the dependencies 61 | 62 | **** Optional Dependencies 63 | 64 | - [[https://github.com/foss-np/2utf8][2utf8]] old dependencies 65 | *** Download 66 | Download the latest verion from [[https://github.com/foss-np/batti/archive/master.zip][zip]] or [[https://github.com/foss-np/batti/archive/master.tar.gz][tar]], clone the repo. 67 | 68 | #+begin_src bash 69 | $ cd path-to-batti 70 | $ ./configure 71 | $ sudo make install 72 | #+end_src 73 | 74 | * Usage 75 | #+BEGIN_SRC bash 76 | $ batti -h 77 | Usage: batti [OPTIONS] [GROUP_NO] 78 | -a | --all Show All [default] 79 | -w | --week Show weeks schedule 80 | -t | --today Show todays schedule 81 | -g | --group Group number 1-7 82 | -u | --update Check for update 83 | -p | --previous Show previous schedule 84 | -d | --dump Dump raw schedule data 85 | -x | --xml Dump shedule to xml 86 | -c | --credits Display the Credits 87 | -h | --help Display this information 88 | -v | --version Version information 89 | 90 | #+END_SRC 91 | 92 | * Beyond Terminal 93 | ** [[http://conky.sourceforge.net/][conky]] 94 | batti is written to be use in terminal, but using conky you can 95 | easily make the desktop widget showing information. 96 | 97 | ** android 98 | Yes, android is linux and supports bash. 99 | 100 | : NOTE: we got frustrated from so call that app… 101 | 102 | *CURRENTLY THERE IS NO APK, you should run it from terminal* 103 | 104 | #+BEGIN_SRC bash 105 | $ ./configure 106 | $ make droid 107 | $ git branch droid 108 | #+END_SRC 109 | 110 | * Others 111 | - [[https://github.com/haude/charge-khattam][charge-khattam]] :: Python tkinter GUI wrapper. 112 | - [[https://github.com/samundra/Nep_Loadshedding_Py3][Nepal-Loadshedding-Indicator]] :: The applet for unity 113 | 114 | ** Similar works on github we found! 115 | - [[https://github.com/xtranophilist/nls][nls]] 116 | - [[https://github.com/hardfire/losh][losh]] 117 | - [[https://github.com/leosabbir/nepalloadshedding][nepalloadshedding]] 118 | - [[https://github.com/bibekdahal/mainbatti-talika][mainbatti-talika]] 119 | - [[https://github.com/blacpythoz/Nepal-Loadshedding-Schedule][Nepal-Loadshedding-Schedule]] 120 | -------------------------------------------------------------------------------- /main.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | WD="$(dirname $(readlink $0 || echo $0))" 6 | SCHEDULE="${HOME}/.cache/batti.sch" 7 | TEMP='/tmp' 8 | days=(Sunday Monday Tuesday Wednesday Thursday Friday Saturday) 9 | today=(`date +%w`) 10 | 11 | function download { 12 | wget -c http://nea.org.np/loadshedding.html -O $TEMP/nea.html 13 | links=($(sed -n '/supportive_docs/p' $TEMP/nea.html |\ 14 | tr '<' '\n' | sed -n 's/.*\(http.*pdf\)">.*/\1/p')) 15 | first_one=$(echo $links | sed -n '1p') 16 | wget -c "${first_one}" -O $TEMP/nea.pdf 17 | } 18 | 19 | function extract { 20 | [[ -e $SCHEDULE ]] && hash_old=$(md5sum $SCHEDULE | cut -b 1-32) 21 | 22 | pdftotext -f 1 -layout $TEMP/nea.pdf $TEMP/raw.txt 23 | sed -n '/;d"x÷af/,/;d"x–@/p' $TEMP/raw.txt | sed '2,${/;d"x÷af/q}' > $TEMP/part.txt 24 | 25 | # NOTE: 2utf8 is not-really required but for fail and debug situations 26 | # 2utf8 -i $TEMP/part.txt > $TEMP/uni2.txt 27 | 28 | # 29 | ## BEGIN: 2utf8 30 | sed -i 's/)/0/g; s/!/1/g; s/@/2/g; s/#/3/g; 31 | s/%/5/g; s/\^/6/g; s/\&/7/g; 32 | s/\*/8/g; s/(/9/g; s/–/-/g; s/M/:/g' $TEMP/part.txt 33 | cat $TEMP/part.txt | tr '$' '4' > $TEMP/uni.txt # FIX: its hard to replace $ 34 | ## END: 2utf8 35 | 36 | ## screw it, you are drunk nea 37 | $WD/main.py $TEMP/uni.txt | sed -n '/[0-9]/p' > $TEMP/batti.sch 38 | 39 | hash_new=$(md5sum $TEMP/batti.sch | cut -b 1-32) 40 | if [[ "$hash_new" == "$hash_old" ]]; then 41 | >&2 echo "> Schedule Unchanged" 42 | else 43 | >&2 echo "> New Schedule" 44 | mkdir -p $(dirname $SCHEDULE) 45 | mv $SCHEDULE ${SCHEDULE/.sch/.bak} 46 | cp $TEMP/batti.sch $SCHEDULE 47 | fi 48 | } 49 | 50 | function get_color { # arg($1:color_code) 51 | # NOTE: cdef is always same 52 | [[ -z "$SGR" ]] && echo "\033[$1;$2m" 53 | } 54 | 55 | function rotate_field { # arg($1:day, $2:group) 56 | f=$(($1-$2)) 57 | [[ $f -le 0 ]] && f=$((7+$f)) 58 | echo $f 59 | } 60 | 61 | function range_check { # arg($1:check_value) 62 | if [[ -z $1 ]]; then 63 | echo -n 64 | elif [[ $1 -gt 0 ]] && [[ $1 -le 7 ]]; then 65 | echo -n $(($grp-2)) # subtract for rotation because of data 66 | else 67 | >&2 echo "group number out of range" 68 | exit 1 69 | fi 70 | } 71 | 72 | function view_today { # arg($1:group) 73 | field=$(rotate_field $today $1) 74 | f0=$((field-1)) 75 | f1=$((f0+7)) 76 | f2=$((f0+14)) 77 | echo -n "${data[f0]}, ${data[f1]}" 78 | [[ -z "${data[f2]}" ]] || echo -n ", ${data[f2]}" && echo 79 | } 80 | 81 | function view_week { # arg($1:group) 82 | for((i=0; i<7; i++)) { 83 | field=$(rotate_field $i $1) 84 | f0=$((field-1)) 85 | f1=$((f0+7)) 86 | f2=$((f0+14)) 87 | 88 | if [[ $today == $i ]]; then 89 | color=$(get_color 1 32) 90 | cdef=$(get_color 0 0) 91 | else 92 | color="" 93 | cdef="" 94 | fi 95 | 96 | echo -e "${color}${days[$i]:0:3}" # $field 97 | echo -e "\t${data[f0]}" 98 | echo -e "\t${data[f1]}\n"; 99 | [[ -z "${data[f2]}" ]] || echo -ne "\n\t${data[f2]}$cdef" && echo -e "$cdef" 100 | } 101 | } 102 | 103 | function view_all { # arg($1:group) 104 | # is loaded by default so data must be loaded 105 | data=($(sed 's/://g' $SCHEDULE)) 106 | 107 | h1=$(get_color 1 32) 108 | c1=$(get_color 1 34) 109 | cdef=$(get_color 0 0) 110 | 111 | echo -en " $h1" 112 | 113 | for day in ${days[@]}; do 114 | printf " %-7s" ${day:0:3} 115 | done 116 | echo -e "$cdef" 117 | 118 | for((g=1; g<=7; g++)) { 119 | echo -en "$h1 Group $g: $cdef" 120 | grp=$(($g-2)) 121 | line2="" 122 | line3="" 123 | if [[ "$1" != $grp ]]; then c2="" 124 | else c2=$(get_color 0 34); fi 125 | 126 | for((i=0; i<7; i++)) { 127 | field=$(rotate_field $i $grp) 128 | f0=$((field-1)) 129 | f1=$((f0+7)) 130 | f2=$((f0+14)) 131 | if [[ $today == $i ]]; then 132 | echo -en "$c1${data[f0]}$cdef " 133 | line2+=$(echo -en "$c1${data[f1]}$cdef ") 134 | line3+=$(echo -en "$c1${data[f2]}$cdef ") 135 | else 136 | echo -en "$c2${data[f0]} " 137 | line2+=$(echo -en "$c2${data[f1]} ") 138 | line3+=$(echo -en "$c2${data[f2]} ") 139 | fi 140 | } 141 | 142 | if [[ -z "${data[f2]}" ]]; then 143 | echo -e "$cdef\n $line2" 144 | else 145 | echo -ne "$cdef\n $line2" 146 | echo -e "$cdef\n $line3" 147 | fi 148 | } 149 | } 150 | 151 | function xml_dump { 152 | data=($(cat $SCHEDULE)) 153 | echo -e "\n" 154 | for((g=1; g<=7; g++)) { 155 | echo -e " " 156 | grp=$((g-2)) 157 | for((i=0; i<7; i++)) { 158 | field=$(rotate_field $i $grp) 159 | f0=$((field-1)) 160 | f1=$((f0+7)) 161 | f2=$((f0+14)) 162 | 163 | echo " " 164 | echo " ${data[f0]}" 165 | echo " ${data[f1]}" 166 | [[ -z "${data[f2]}" ]] || echo " ${data[f2]}" 167 | echo " " 168 | } 169 | echo " " 170 | } 171 | echo "" 172 | } 173 | 174 | function update { 175 | local FILE="$TEMP/nea.pdf" 176 | [[ -e $FILE ]] || download 177 | if [[ -e $FILE ]]; then 178 | file $FILE | grep PDF && extract || { 179 | rm $FILE 180 | >&2 echo "Error in PDF, run the update again" 181 | } 182 | fi 183 | } 184 | 185 | function credits { 186 | h1=$(get_color 1 32) 187 | cdef=$(get_color 0 0) 188 | sed 's/^#.*/'`echo -e $h1`'&'`echo -e $cdef`'/' $WD/AUTHORS 189 | echo 190 | } 191 | 192 | function usage { 193 | echo -e "Usage: batti [OPTIONS] [GROUP_NO]"; 194 | echo -e "\t-a | --all\tShow All [default]" 195 | echo -e "\t-w | --week\tShow weeks schedule" 196 | echo -e "\t-t | --today\tShow todays schedule" 197 | echo -e "\t-g | --group\tGroup number [1-7]" 198 | echo -e "\t-u | --update\tCheck for update" 199 | echo -e "\t-p | --previous\tShow previous schedule" 200 | echo -e "\t-d | --dump\tDump raw schedule data" 201 | echo -e "\t-x | --xml\tDump to xml" 202 | echo -e "\t-c | --credits\tDisplay credits" 203 | echo -e "\t-h | --help\tDisplay this information" 204 | echo -e "\t-v | --version\tVersion information" 205 | } 206 | 207 | GETOPT=$(getopt -o g:awtupdxchv\ 208 | -l all,group:,week,today,update,previous,dump,xml,credits,help,version\ 209 | -n "batti"\ 210 | -- "$@") 211 | 212 | eval set -- "$GETOPT" 213 | 214 | view_mode=0 215 | while true; do 216 | case $1 in 217 | -a|--all) view_mode=0; shift;; 218 | -w|--week) view_mode=1; shift;; 219 | -t|--today) view_mode=2; shift;; 220 | -g|--group) grp=$2; shift 2;; 221 | -u|--update) update; exit;; 222 | -p|--previous) SCHEDULE=${SCHEDULE/.sch/.bak}; shift;; 223 | -d|--dump) cat $SCHEDULE; exit;; 224 | -x|--xml) xml_dump; exit;; 225 | -c|--credits) credits; exit;; 226 | -h|--help) usage; exit;; 227 | -v|--version) cat $WD/.version; echo; exit;; 228 | --) shift; break;; 229 | esac 230 | done 231 | 232 | # extra argument 233 | for arg do 234 | grp=$arg 235 | break 236 | done 237 | 238 | grp=$(range_check "$grp") 239 | 240 | [[ -e $SCHEDULE ]] || update 241 | data=($(cat $SCHEDULE)) 242 | 243 | if [[ $view_mode != "0" ]] && [[ "$grp" == "" ]]; then 244 | >&2 echo "group not defined" 245 | exit 1 246 | fi 247 | 248 | if (( "$view_mode" == 2 )); then view_today $grp 249 | elif (( "$view_mode" == 1 )); then view_week $grp 250 | else view_all $grp; fi 251 | --------------------------------------------------------------------------------