Last active
November 27, 2020 22:09
-
-
Save neufeldtech/83109c0fef045212d552933d3ccf311f to your computer and use it in GitHub Desktop.
yolo.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"encoding/json" | |
"flag" | |
"fmt" | |
"log" | |
"net" | |
"net/http" | |
"reflect" | |
"sort" | |
"strings" | |
"time" | |
) | |
var flagIP = flag.String("ip", "127.0.0.1", "IP address to listen on") | |
var flagPort = flag.String("port", "7300", "Port to listen on") | |
type client struct { | |
Conn net.Conn | |
CallSign string | |
Message chan string | |
} | |
var ( | |
connections map[string]*client | |
stations RadioStations | |
maxSpotID int | |
) | |
func blast(msg string) { | |
for _, c := range connections { | |
writeFormattedMsg(c.Conn, msg) | |
} | |
} | |
func main() { | |
flag.Parse() | |
connections = make(map[string]*client, 0) | |
go func() { | |
for { | |
fmt.Println("fetching stations") | |
err := getStations(&stations) | |
if err != nil { | |
fmt.Println(err) | |
} | |
sort.SliceStable(stations, func(i, j int) bool { | |
return stations[i].SpotID > stations[j].SpotID | |
}) | |
if stations[0].SpotID > maxSpotID { | |
for _, s := range stations { | |
if s.SpotID > maxSpotID { | |
msg := fmt.Sprintf("found new station: %v", s.SpotID) | |
blast(msg) | |
} | |
} | |
} | |
maxSpotID = stations[0].SpotID | |
time.Sleep(3 * time.Second) | |
} | |
}() | |
//start listener | |
listener, err := net.Listen("tcp", *flagIP+":"+*flagPort) | |
if err != nil { | |
log.Fatalf("could not listen on interface %v:%v error: %v ", *flagIP, *flagPort, err) | |
} | |
defer listener.Close() | |
log.Println("listening on: ", listener.Addr()) | |
//main listen accept loop | |
for { | |
conn, err := listener.Accept() | |
if err != nil { | |
log.Fatalf("could not accept connection %v ", err) | |
} | |
//create new client on connection | |
go createclient(conn) | |
for _, c := range connections { | |
c.Message <- "someone has joined!" | |
} | |
time.Sleep(time.Millisecond) | |
} | |
} | |
func (c *client) close() { | |
c.Conn.Close() | |
c.Message <- "\\quit" | |
delete(connections, c.CallSign) | |
} | |
func (c *client) recieve() { | |
for { | |
msg := <-c.Message | |
log.Printf("recieve: client(%v|%v) recvd msg: %s ", c.Conn.RemoteAddr(), c.CallSign, msg) | |
writeFormattedMsg(c.Conn, msg) | |
time.Sleep(time.Millisecond) | |
} | |
} | |
func getStations(target interface{}) error { | |
var myClient = &http.Client{Timeout: 10 * time.Second} | |
r, err := myClient.Get("https://api.pota.us/spot/activator") | |
if err != nil { | |
return err | |
} | |
defer r.Body.Close() | |
return json.NewDecoder(r.Body).Decode(target) | |
} | |
func createclient(conn net.Conn) { | |
log.Printf("createclient: remote connection from: %v", conn.RemoteAddr()) | |
callSign, err := readInput(conn, "Login: ") | |
if err != nil { | |
panic(err) | |
} | |
writeFormattedMsg(conn, "Welcome "+callSign) | |
writeFormattedMsg(conn, fmt.Sprintf("I currently know about %v stations\n", len(stations))) | |
writeFormattedMsg(conn, fmt.Sprintf("Latest SpotID I know of is: %v\n", stations[0].SpotID)) | |
//init client struct | |
client := &client{ | |
Message: make(chan string), | |
Conn: conn, | |
CallSign: callSign, | |
} | |
log.Printf("new client created: %v %v", client.Conn.RemoteAddr(), client.CallSign) | |
connections[client.CallSign] = client | |
//spin off seperate send, recieve | |
go client.recieve() | |
} | |
func writeFormattedMsg(conn net.Conn, msg interface{}) error { | |
_, err := conn.Write([]byte("---------------------------\n")) | |
t := reflect.ValueOf(msg) | |
switch t.Kind() { | |
case reflect.Map: | |
for k, v := range msg.(map[string]string) { | |
_, err = conn.Write([]byte(k + " : " + v)) | |
} | |
break | |
case reflect.String: | |
v := reflect.ValueOf(msg).String() | |
_, err = conn.Write([]byte(v + "\n")) | |
break | |
} //switch | |
conn.Write([]byte("---------------------------\n")) | |
if err != nil { | |
return err | |
} | |
return nil //todo | |
} | |
func readInput(conn net.Conn, qst string) (string, error) { | |
conn.Write([]byte(qst)) | |
s, err := bufio.NewReader(conn).ReadString('\n') | |
if err != nil { | |
log.Printf("readinput: could not read input from stdin: %v from client %v", err, conn.RemoteAddr().String()) | |
return "", err | |
} | |
s = strings.Trim(s, "\r\n") | |
return s, nil | |
} | |
type RadioStations []RadioStation | |
type RadioStation struct { | |
SpotID int `json:"spotId"` | |
Activator string `json:"activator"` | |
Frequency string `json:"frequency"` | |
Mode string `json:"mode"` | |
Reference string `json:"reference"` | |
ParkName string `json:"parkName"` | |
SpotTime string `json:"spotTime"` | |
Spotter string `json:"spotter"` | |
Comments string `json:"comments"` | |
Source string `json:"source"` | |
Invalid interface{} `json:"invalid"` | |
Name string `json:"name"` | |
LocationDesc string `json:"locationDesc"` | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment