poster.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "log"
  6. "net/http"
  7. "strings"
  8. "github.com/beego/x2j"
  9. )
  10. // https://zetcode.com/golang/getpostrequest/ post_req_form.go
  11. func Post(where string) *http.Response {
  12. resp, err := http.PostForm(where, nil)
  13. if err != nil {
  14. log.Printf("POST got non 200 code, %v", err)
  15. // Catch what error it is, if it's a no access to device try a etherwake
  16. return nil
  17. }
  18. return resp
  19. }
  20. /*func ListenToRequests(ln *net.UDPConn, data *string) {
  21. done := false
  22. do_send := true
  23. for !done {
  24. buffer := make([]byte, 1024) // 1k
  25. ln.SetReadDeadline(time.Now().Add(3 * time.Second))
  26. for !done {
  27. b, _, err := ln.ReadFromUDP(buffer)
  28. if b > 0 {
  29. str := string(buffer[0:])
  30. *data += str
  31. }
  32. if err != nil {
  33. if _, ok := err.(net.Error); !ok {
  34. log.Print(err)
  35. done = true
  36. }
  37. }
  38. if do_send {
  39. err = PostFind()
  40. if err != nil {
  41. log.Printf("POST Find returned %v", err)
  42. }
  43. do_send = false
  44. }
  45. }
  46. }
  47. }*/
  48. /*
  49. func PostFind() {
  50. file, err := os.ReadFile("finder.txt")
  51. if err != nil {
  52. log.Print(err)
  53. }
  54. addr, err := net.ResolveUDPAddr("udp", "239.255.255.250:1900")
  55. if err != nil {
  56. log.Print(err)
  57. }
  58. conn, err := net.DialUDP("udp", nil, addr)
  59. if err != nil {
  60. log.Print(err)
  61. }
  62. defer conn.Close()
  63. conn.Write(file)
  64. log.Println("Posted Request for devices")
  65. }
  66. func GetFind(data *[]string) {
  67. addr, err := net.ResolveUDPAddr("udp", ":1900")
  68. if err != nil {
  69. log.Printf("GET Find failed getting port 1900, %v", err)
  70. return
  71. }
  72. fmt.Printf("Listening on %s\r\n", addr.String())
  73. ln, err := net.ListenUDP("udp", addr)
  74. if err != nil {
  75. log.Printf("GET Find started listener for 1900, %v", err)
  76. return
  77. }
  78. var list []string
  79. buffer := make([]byte, 1024) // 1k
  80. defer ln.Close()
  81. ln.SetReadDeadline(time.Now().Add(3 * time.Second))
  82. for {
  83. n, adr, err := ln.ReadFromUDP(buffer)
  84. str := string(buffer[0:n])
  85. fmt.Printf("Got '%s' from %s\r\n", str, adr.String())
  86. if err != nil {
  87. log.Println(err)
  88. break
  89. }
  90. list = append(list, adr.String())
  91. }
  92. *data = list
  93. }
  94. */
  95. func Get(where string) *http.Response {
  96. resp, err := http.Get(where)
  97. if err != nil {
  98. log.Printf("GET got non 200 code, %v", err)
  99. return nil
  100. } else {
  101. return resp
  102. }
  103. }
  104. // https://developer.roku.com/docs/developer-program/debugging/external-control-api.md#keypress-key-values codes
  105. func KeyPress(ip, command string) string {
  106. return fmt.Sprintf("http://%s:8060/keypress/%s", ip, command)
  107. }
  108. // https://developer.roku.com/docs/developer-program/debugging/external-control-api.md#general-ecp-commands
  109. func Query(ip, what string) string {
  110. return fmt.Sprintf("http://%s:8060/query/%s", ip, what)
  111. }
  112. func PerformKey(ip, command string) bool {
  113. r := Post(KeyPress(ip, command))
  114. if r == nil {
  115. return false
  116. }
  117. defer r.Body.Close()
  118. return true
  119. }
  120. func GetQuery(ip, command string) []byte {
  121. var resp *http.Response = Get(Query(ip, command))
  122. if resp == nil {
  123. return nil
  124. }
  125. var body []byte
  126. var err error
  127. body, err = io.ReadAll(resp.Body)
  128. if err != nil {
  129. log.Printf("Reading from body got error, %v", err)
  130. }
  131. defer resp.Body.Close()
  132. return body
  133. }
  134. func GetCurrentPlay(ip string) *MediaPlayer {
  135. var resp []byte = GetQuery(ip, "media-player")
  136. var mp MediaPlayer
  137. var err error = x2j.Unmarshal(resp, &mp)
  138. if err != nil {
  139. log.Printf("Error occurred processing XML, %v", err)
  140. }
  141. return &mp
  142. }
  143. func ObtainDeviceInfo(ip string) *DeviceInfo {
  144. var resp []byte = GetQuery(ip, "device-info")
  145. var di DeviceInfo
  146. var err error = x2j.Unmarshal(resp, &di)
  147. if err != nil {
  148. log.Printf("Error occurred processing XML, %v", err)
  149. }
  150. return &di
  151. }
  152. // Returns a map of device-infos
  153. func GetDeviceInfo(ip string) *DeviceInfo {
  154. var di *DeviceInfo = ObtainDeviceInfo(ip)
  155. /*keys := glom.GetPossible(dev)
  156. for _, key := range keys {
  157. log.Printf("%s = %v", key, dev[key])
  158. }*/
  159. return di
  160. }
  161. func GetDevices(wake_on_lan map[string]string) (*[]string, map[string]string) {
  162. var str []string
  163. resp := strings.Split(PostFind(), "\n")
  164. //fmt.Printf("Processing %d lines\n", len(resp))
  165. ip := ""
  166. for _, line := range resp {
  167. if strings.Contains(line, "LOCATION") {
  168. st := strings.ReplaceAll(line, "LOCATION: http://", "")
  169. st = strings.ReplaceAll(st, ":8060/", "")
  170. st = strings.ReplaceAll(st, "\r", "")
  171. //fmt.Printf("IP='%s'", st)
  172. str = append(str, st)
  173. ip = st
  174. } else if strings.Contains(line, "WAKEUP") {
  175. st := strings.ReplaceAll(line, "WAKEUP: MAC=", "")
  176. st = strings.ReplaceAll(st, ";Timeout=10", "")
  177. st = strings.ReplaceAll(st, "\r", "")
  178. //fmt.Printf("IP='%s' MAC='%s'", ip, st)
  179. wake_on_lan[ip] = st
  180. }
  181. }
  182. return &str, wake_on_lan
  183. }
  184. func DebugInfo(ip string) string {
  185. // Query the current playing thing, and get the tv channels
  186. var mp *MediaPlayer = GetCurrentPlay(ip)
  187. var name string
  188. var id string
  189. /*r1 := GetQuery(ip, "tv-channels")
  190. chan_name, _ := glom.Glom(r1, "tv-channels.channel.name")
  191. chan_phy_id, _ := glom.Glom(r1, "tv-channels.channel.physical-channel")
  192. chan_number, _ := glom.Glom(r1, "tv-channels.channel.number")*/
  193. if mp.Plugin.Name == "" && mp.Plugin.Id == 0 {
  194. name = "TV"
  195. id = "No Connection"
  196. } else {
  197. name = mp.Plugin.Name
  198. id = fmt.Sprintf("%d", mp.Plugin.Id)
  199. }
  200. // Debug print
  201. fmt.Printf("Name: %v (%v)\r\n", name, id)
  202. //fmt.Printf("Channel: %v (%v / %v)\r\n", chan_name, chan_phy_id, chan_number)
  203. return fmt.Sprintf("%v (%v)", name, id)
  204. }