summaryrefslogtreecommitdiff
path: root/localkannel-dispatch
blob: bbfe891c7a08bae770e3588c6155b201bb2b3d1c (plain)
  1. #!/bin/sh
  2. set -e
  3. vardir=/var/lib/kannel/hello
  4. sbindir=/usr/local/sbin
  5. exit0() {
  6. [ -n "$1" ] && echo "$1"
  7. exit 0
  8. }
  9. exit1() {
  10. response="${1:+Error: }${1:-Internal error!}"
  11. # FIXME: pass error messages via stderr (not stdout)
  12. # echo >&2 "$response"
  13. echo "$response"
  14. [ -z "$SMS_SMSC$SMS_URL" ] || $sbindir/localsendsms "$to" "$response"
  15. exit 1
  16. }
  17. simpleword() {
  18. echo "$1" | perl -ne '/([a-zæøåÆØÅ!@\/][a-zæøåÆØÅ0-9-]+)/i and print lc($1)'
  19. }
  20. uriunescape() {
  21. if [ 0 = "$urldecode" ]; then
  22. echo "$@"
  23. else
  24. echo "$@" | perl -e 'use URI::Escape; print lc(uri_unescape(<STDIN>));'
  25. fi
  26. }
  27. # Resolve var from "variable = value" pair in file below /etc/local
  28. getfilevar() {
  29. file="/etc/local/$1"
  30. var="$2"
  31. grep -m1 "^$var" "$file" | awk -F '(= )' '{print $2}'
  32. }
  33. lastservicephone() {
  34. logfile=/var/log/kannel/smsbox.log
  35. tac $logfile $logfile.1 \
  36. | perl -ne "/INFO: Starting to service <.*> from <$1> to <([^<>]*)>/ and print \$1 and exit 0"
  37. }
  38. #from=`uriunescape "$1" | sed -e 's/\+/ /g'`; shift
  39. from=`uriunescape "$1"`; shift
  40. #to=`uriunescape "$1" | sed -e 's/\+/ /g'`; shift
  41. to=`uriunescape "$1"`; shift
  42. # FIXME: avoid stripping ALL plusses
  43. set -- `uriunescape "$@" | sed -e 's/\+/ /g'`
  44. #set -- `uriunescape "$@"`
  45. app_raw="$1"
  46. app=`simpleword "$1"`; shift
  47. export debug
  48. SMS_PHONE="$from"
  49. urldecode=0
  50. export SMS_PHONE urldecode
  51. case "$SMS_REALM" in
  52. test)
  53. provider="dummy"
  54. mdpath="/home/hearth/public_webdata/hearth/content/sms"
  55. export mdpath
  56. ;;
  57. hello)
  58. provider="local"
  59. # provider="coolsms"
  60. # provider="clickatell"
  61. mdpath="/home/hearth/public_webdata/hearth/content/sms"
  62. export mdpath
  63. ;;
  64. hellobudapest)
  65. provider="clickatell"
  66. addtestphones="+36307418279" # Jonas
  67. addphones=""
  68. gotestphones="+36307418279" # Jonas
  69. gophones=""
  70. SMS_ERRFROM="+36307418279" # Jonas
  71. SMS_ERRTO1="+36307418279" # Jonas
  72. # SMS_ERRTO2="+36307418241" # Emma
  73. SMS_ERRTO2="+36703782127" # Emma
  74. mdpath="/home/www-hearth/public_webdata/hellobudapest/content/sms"
  75. export SMS_ERRFROM SMS_ERRTO1 SMS_ERRTO2 mdpath
  76. ;;
  77. hellotorino)
  78. provider="clickatell"
  79. gotestphones="+393453915741 +393453805531 +393453801457" # Jonas, Jacob, Vera
  80. gophones="+393407574815 +393407574813 +393381467977 +393478617029" # Alessandra, Vela, Marco, Silvia
  81. SMS_ERRFROM="+393453915741" # Jonas
  82. SMS_ERRTO1="+393453801457" # Vera
  83. SMS_ERRTO2="+393483281187" # Rescue
  84. mdpath="/home/www-hearth/public_webdata/hellotorino/content/sms"
  85. export SMS_ERRFROM SMS_ERRTO1 SMS_ERRTO2 mdpath
  86. ;;
  87. cyber)
  88. provider="local"
  89. mdpath="/home/cyberhus/public_webdata/mdsms/content/sms"
  90. export mdpath
  91. ;;
  92. *)
  93. exit1 "unknown realm \"$SMS_REALM\"!"
  94. ;;
  95. esac
  96. case "$provider" in
  97. dummy)
  98. dummy=1
  99. ADMIN_OK=1
  100. export ADMIN_OK dummy
  101. ;;
  102. local)
  103. export SMS_SMSC
  104. ;;
  105. coolsms)
  106. unset SMS_SMSC
  107. SMS_URL="https://sms.coolsmsc.dk:8081/"
  108. SMS_USER=$(getfilevar coolsms user)
  109. SMS_PW=$(getfilevar coolsms pw)
  110. SMS_CP="cp1252"
  111. SMS_MSGTAG="message"
  112. export SMS_URL SMS_USER SMS_PW SMS_CP SMS_MSGTAG
  113. ;;
  114. # supports concatenation and req_feat (e.g 48: sender ID)
  115. # does not support DLR, and only concatenates max. 3 smses
  116. clickatell)
  117. unset SMS_SMSC
  118. SMS_URL="https://api.clickatell.com/http/sendmsg"
  119. SMS_USER=$(getfilevar clickatell user)
  120. SMS_PW=$(getfilevar clickatell pw)
  121. SMS_CP="iso8859-1"
  122. SMS_USERTAG="user"
  123. SMS_API=$(getfilevar clickatell api)
  124. SMS_CALLBACK="3"
  125. SMS_CONCAT="3"
  126. SMS_ESCALATE="1"
  127. SMS_VALIDITY="1"
  128. SMS_REQ_FEAT="24611" # 1+2+32+8192+16384 = text+8bit+numeric_src+dlr+concat
  129. stripprefix="1"
  130. export SMS_URL SMS_USER SMS_PW SMS_CP SMS_USERTAG SMS_API SMS_CALLBACK SMS_CONCAT SMS_ESCALATE SMS_VALIDITY SMS_REQ_FEAT stripprefix
  131. ;;
  132. # supports DLR
  133. # Kannel clickatell profile supports concatenation but not req_feat
  134. # Kannel generic profile supports req_feat but not concatenation
  135. clickatell_via_kannel)
  136. SMS_SMSC="X"
  137. SMS_CONCATENATION="1"
  138. SMS_DLR_MASK="7"
  139. SMS_DLR_URL="http://helloearth.jones.dk/test.cgi?type=dlr&msgid=XXX&smsid=%I&from=%p&to=%P&time=%t&unixtime=%T&dlr=%d&dlrmsg=%A"
  140. SMS_CP="iso8859-1"
  141. SMS_VALIDITY="1"
  142. SMS_BINFO="req_feat=24611&concat=3&escalate=1%validity=1" # 1+2+32+8192+16384 = text+8bit+numeric_src+dlr+concat
  143. stripprefix="1"
  144. export SMS_SMSC SMS_CONCATENATION SMS_DLR_MASK SMS_DLR_URL SMS_CP SMS_VALIDITY SMS_BINFO stripprefix
  145. ;;
  146. routo_via_kannel)
  147. SMS_SMSC="Y"
  148. export SMS_SMSC
  149. ;;
  150. *)
  151. exit1 "unknown provider \"$provider\"!"
  152. ;;
  153. esac
  154. # FIXME: some safety net against abusing this imposter feature
  155. #if [ -n "$REDIRECT_OK" ]; then
  156. case "$app" in
  157. @*)
  158. # FIXME: Avoid hardcoding national prefix
  159. targetphone="$(echo "$app" | perl -pe 's/^@//;' -e 's/^([^+])/+36\1/')"
  160. # TODO: silence errors - or better: bounce those back to original sender
  161. targetfrom=$(lastservicephone "$targetphone")
  162. [ -n "$targetfrom" ] || exit1 "refusing to redirect: unknown target phone number \"$targetphone\"."
  163. SMS_PHONE="$targetfrom" $sbindir/localmarkdown2sms "$targetphone" "$@"
  164. exit 0
  165. ;;
  166. esac
  167. #fi
  168. if [ -n "$GROUP_OK" ]; then
  169. case "$app" in
  170. !*)
  171. group="$(echo "$app" | perl -pe 's/^!//;')"
  172. members=$(cd "$vardir/user" && grep -lF "$group" */group | perl -pe "s,/group$,,") || members=
  173. [ -n "$members" ] || exit1 "Message redirected for none: no members resolved in group \"$group\"!"
  174. for member in $members; do
  175. phone=$(head -n 1 "$vardir/user/$member/phone") || nophone="${nophone+$nophone }$member"
  176. [ -z "$phone" ] || $sbindir/localmarkdown2sms "$phone" "$@"
  177. done
  178. [ -n "$members" ] || exit1 "Message redirected for none: no members resolved in group \"$group\"!"
  179. membercount=$(echo "$members" | wc --word)
  180. [ -z "$nophone" ] || nophonecount=$(echo "$nophone" | wc --word)
  181. [ -z "$nophone" ] || exit1 "Message redirected for $membercount members of group \"$group\", but failed for $nophonecount of them (could not resolve phone number)!"
  182. exit0 "Message redirected for $membercount members of group \"$group\"."
  183. ;;
  184. esac
  185. fi
  186. case "$app" in
  187. /*)
  188. cmd="$(echo "$app" | perl -pe 's/^\///;')"
  189. case "$cmd" in
  190. ping)
  191. if [ "help" = "$1" ]; then
  192. $sbindir/localsendsms "$to" "Usage:
  193. /ping [...]
  194. Respond \"pong\" and echo back any addition input."
  195. exit 0
  196. fi
  197. $sbindir/localsendsms "$to" pong "$@"
  198. exit 0
  199. ;;
  200. add|addtest)
  201. if [ "help" = "$1" ]; then
  202. $sbindir/localsendsms "$to" "Usage:
  203. /add ID PHONE [MSG]...]
  204. Register PHONE as ID,
  205. and (if included) send MSG to subscribers."
  206. exit 0
  207. fi
  208. id="$(echo "$1" | perl -ne '/^(\d\d)$/ and print $1;')"
  209. [ -n "$id" ] || exit1 "wrong or missing id: must be 2 digits."
  210. shift
  211. # FIXME: avoid juggling with leading plus here when no longer stripped from input
  212. # phone="$(echo "$1" | perl -ne 's/^(?=[^+])/+36/;' -e '/^(\+\d\d\d+)$/ and print $1;')"
  213. phone="$(echo "$1" | perl -ne '/^(\d\d\d+)$/ and print $1;')"
  214. [ -n "$phone" ] || exit1 "wrong or missing phone number: must be only digits with leading + and at least 3 digits."
  215. targetfrom=$(lastservicephone "\+$phone")
  216. [ -n "$targetfrom" ] || exit1 "unknown phone +$phone: it must have been used with the system recently."
  217. phone="+$phone"
  218. shift
  219. case "$cmd" in
  220. addtest)
  221. msgphones="$addtestphones"
  222. ;;
  223. add)
  224. msgphones="$addphones"
  225. ;;
  226. esac
  227. str=$($sbindir/localsmsadmin add user "$id" "$phone")
  228. $sbindir/localsendsms "$to" "[info] \"$cmd\": $str."
  229. if [ -n "$*" ]; then
  230. for msgphone in $msgphones; do
  231. $sbindir/localsendsms "$msgphone" "[info] $id $phone $@"
  232. done
  233. $sbindir/localsendsms "$to" "[info] $id $phone added/updated. trailing message forwarded to subscribers."
  234. else
  235. $sbindir/localsendsms "$to" "[info] $id $phone added/updated. (no trailing message passed to subscribers)."
  236. fi
  237. exit 0
  238. ;;
  239. # FIXME: generalize this ugly hacks somehow, and secure against random use
  240. go|gotest|so|sotest)
  241. case "$cmd" in
  242. go*)
  243. basecmd="go"
  244. realcmd="hello"
  245. ;;
  246. so*)
  247. basecmd="so"
  248. realcmd="szia"
  249. ;;
  250. esac
  251. if [ "help" = "$1" ]; then
  252. $sbindir/localsendsms "$to" "Usage:
  253. /$basecmd PHONE... [MSG...]
  254. /${basecmd}test PHONE... [MSG...]
  255. /$basecmd help
  256. Start thread \"$realcmd\" on behalf of each PHONE,
  257. and (if included) send MSG to subscribers."
  258. exit 0
  259. fi
  260. [ -n "$1" ] || exit1 "target phone number missing (try \"/$cmd help\" for usage)"
  261. case "$cmd" in
  262. gotest|sotest)
  263. phones="$gotestphones"
  264. ;;
  265. go|so)
  266. phones="$gophones"
  267. ;;
  268. esac
  269. # FIXME: avoid juggling with leading plus here when no longer stripped from input
  270. # FIXME: make country code optional again when plus no longer stripped from input
  271. # FIXME: Avoid hardcoding national prefix
  272. while [ -n "$1" ]; do
  273. # targetphone="$(echo "$1" | perl -ne 's/^(?=[^+])/+36/;' -e '/^(\+\d\d\d+)$/ and print $1;')"
  274. targetphone="$(echo "$1" | perl -ne '/^(\d\d\d+)$/ and print $1;')"
  275. [ -n "$targetphone" ] || continue
  276. # Sanity check
  277. targetfrom=$(lastservicephone "\+$targetphone")
  278. [ -n "$targetfrom" ] || exit1 "refusing to redirect: unknown target phone number +$targetphone."
  279. targetphones="${targetphones:+$targetphones }\+$targetphone"
  280. shift
  281. done
  282. # send responses (threaded one last, to work in debug mode)
  283. if [ -n "$*" ]; then
  284. for phone in $phones; do
  285. $sbindir/localsendsms "$phone" "[$cmd] $@"
  286. done
  287. $sbindir/localsendsms "$to" "[info] \"$cmd\" thread started for $targetphones and trailing message forwarded to subscribers."
  288. else
  289. $sbindir/localsendsms "$to" "[info] \"$cmd\" thread started for $targetphones (no trailing message passed to subscribers)."
  290. fi
  291. for phone in $targetphones; do
  292. SMS_PHONE=$(lastservicephone "$phone") $sbindir/localmarkdown2sms "$phone" "$realcmd"
  293. done
  294. exit 0
  295. ;;
  296. esac
  297. candidates=$(cd "$vardir/user" && grep -lF "$to" */phone | perl -pe "s,/phone$,,") || candidates=
  298. [ -z "$candidates" ] || $(grep -vqF "$candidates" "$vardir/group/admin/user") || admin=true
  299. if [ -n "$ADMIN_OK" ] && [ -n "$admin" ]; then
  300. str="$($sbindir/localsmsadmin "$cmd" "$@" 2>&1)" || exit1 "$str"
  301. $sbindir/localsendsms "$to" $str
  302. exit 0
  303. elif [ "help" = "$cmd" ]; then
  304. $sbindir/localsendsms "$to" "Commands:
  305. /ping [...]
  306. /COMMAND help
  307. /help
  308. try e.g. \"/del help\"."
  309. exit 0
  310. fi
  311. ;;
  312. esac
  313. #FIXME: if sender has a mission, check for "done": process missionpending and report result to mission members
  314. # yb)
  315. # s="$(links -dump "http://www.yubnub.org/parser/parse?command=$@")"
  316. # $sbindir/localsendsms "$to" "$s"
  317. # exit 0
  318. # ;;
  319. # Bail out if another thread already active targeted same user
  320. # FIXME: avoid juggling with leading plus here when no longer stripped from input
  321. if pgrep -f "$to"; then
  322. for errorto in $SMS_ERRTO1 $SMS_ERRTO2; do
  323. SMS_PHONE="$SMS_ERRFROM" $sbindir/localsendsms "$errorto" "[warning] silently suppressed \"$app_raw\" for $to busy already"
  324. done
  325. exit 0
  326. fi
  327. $sbindir/localmarkdown2sms "$to" "$app_raw" "$@"