anonbot 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #!/usr/bin/env bash
  2. # This file defines anonbot, an irc bot used on irc.sdf.org.
  3. # Copyright (C) 2015-2021 mlaine@sdfeu.org
  4. # Permission is hereby granted, free of charge, to any person obtaining
  5. # a copy of this software and associated documentation files (the
  6. # "Software"), to deal in the Software without restriction, including
  7. # without limitation the rights to use, copy, modify, merge, publish,
  8. # distribute, sublicense, and/or sell copies of the Software, and to
  9. # permit persons to whom the Software is furnished to do so, subject to
  10. # the following conditions:
  11. # The above copyright notice and this permission notice shall be
  12. # included in all copies or substantial portions of the Software.
  13. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  15. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  16. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  17. # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  18. # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  19. # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. #-----------------------------------------------------------------------
  21. host='irc.sdf.org'
  22. port=6667
  23. user='bot'
  24. nick='anonbot'
  25. real='Anonradio Bot'
  26. chan='#anonradio'
  27. stat='http://anonradio.net:8000/status-json.xsl'
  28. sched='https://anonradio.net/schedule/'
  29. function init {
  30. exec 3<&-
  31. kill "$pid" 2>'/dev/null'
  32. exec 3<>"/dev/tcp/$host/$port" || return 1
  33. printf 'USER %s 0 * :%s\n' "$user" "$real" >&3
  34. printf 'NICK %s\n' "$nick" >&3
  35. update &
  36. pid="$!"
  37. }
  38. function status {
  39. raw="$(curl --connect-timeout 5 -fs "$stat")"
  40. for str in 'server_name' 'title' 'listeners'; do
  41. declare -g $str="$(awk -F "$str\":" '
  42. {
  43. split($2,s,",\"")
  44. gsub(/"/,"",s[1])
  45. gsub(/ *$/,"",s[1])
  46. print s[1]
  47. }
  48. ' <<< "$raw")"
  49. done
  50. if [[ -z "$server_name" || -z "$listeners" ]]; then
  51. return 1
  52. fi
  53. }
  54. function schedule {
  55. raw="$(curl --connect-timeout 5 -Lkfs "$sched")"
  56. if [[ -z "$raw" ]]; then
  57. send 'Could not fetch the schedule.'
  58. return
  59. fi
  60. if [[ "$1" == 'cur' ]]; then
  61. host="$(printf "$raw" | awk 'NR==5{print $3}')"
  62. show="$(printf "$raw" | awk 'NR==5{$1=$2=$3="";print}' | awk '{$1=$1};1')"
  63. send "Current show, hosted by $host: $show"
  64. return
  65. elif [[ "$1" == 'next' ]]; then
  66. time="$(printf "$raw" | awk 'NR==6{print $2}')"
  67. host="$(printf "$raw" | awk 'NR==6{print $3}')"
  68. show="$(printf "$raw" | awk 'NR==6{$1=$2=$3="";print}' | awk '{$1=$1};1')"
  69. send "Next show, hosted by $host at $time: $show"
  70. else
  71. send 'Anonradio schedule for the next 10 shows:'
  72. readarray -t foo <<< "$(printf "$raw" | awk 'NR>5&&NR<16')"
  73. for str in "${foo[@]}"; do
  74. send "$str"
  75. done
  76. fi
  77. send "The time is now $(date -u '+%R (all times in %Z)')."
  78. }
  79. function send {
  80. if [[ "${FUNCNAME[1]}" = 'push' ]]; then
  81. colour="\x0303"
  82. else
  83. colour="\x0307"
  84. fi
  85. printf 'PRIVMSG %b\n' "$chan :$colour$1\x03" >&3
  86. }
  87. function push {
  88. send "$server_name ${title:+: $title }($listeners listeners)"
  89. }
  90. function update {
  91. sleep 10
  92. current=''
  93. while true; do
  94. if status; then
  95. if [[ "$title" != "$current" ]]; then
  96. current="$title"
  97. push && sleep 120
  98. fi
  99. else
  100. sleep 60 && continue
  101. fi
  102. sleep 20
  103. done
  104. }
  105. function priv {
  106. case "$1" in
  107. 'np')
  108. if status; then
  109. push
  110. else
  111. send 'No program at the moment.'
  112. fi ;;
  113. 'help')
  114. send "Type 'np' for now playing, 'current' for the current show, 'next' for the next show, 'schedule' for the next ten shows and 'source' for my source." ;;
  115. 'source')
  116. send 'You can view my source at https://notabug.org/mlaine/anonbot.' ;;
  117. 'current')
  118. schedule 'cur' ;;
  119. 'next')
  120. schedule 'next' ;;
  121. 'schedule')
  122. schedule ;;
  123. esac
  124. }
  125. function main {
  126. init
  127. while true; do
  128. if IFS=$' \t\r' read -ru3 -a data -t 300; then
  129. if [[ "${data[0]}" = 'PING' ]]; then
  130. printf 'PONG %s\n' "${data[1]}" >&3
  131. elif [[ "${data[1]}" = '001' ]]; then
  132. printf 'JOIN %s\n' "$chan" >&3
  133. elif [[ "${data[1]}${data[3]}" = "PRIVMSG:$nick:" ]]; then
  134. priv "${data[4],,}"
  135. fi
  136. else
  137. sleep 300
  138. init
  139. fi
  140. done
  141. }
  142. main