github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/chat/maps/srv.go (about) 1 package maps 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "net/http" 8 "strconv" 9 10 "github.com/keybase/client/go/avatars" 11 "github.com/keybase/client/go/chat/globals" 12 "github.com/keybase/client/go/protocol/keybase1" 13 14 "github.com/keybase/client/go/kbhttp/manager" 15 ) 16 17 type Srv struct { 18 globals.Contextified 19 httpSrv *manager.Srv 20 } 21 22 func NewSrv(g *globals.Context, httpSrv *manager.Srv) *Srv { 23 s := &Srv{ 24 Contextified: globals.NewContextified(g), 25 httpSrv: httpSrv, 26 } 27 s.httpSrv.HandleFunc("map", manager.SrvTokenModeDefault, s.serve) 28 return s 29 } 30 31 func (s *Srv) debug(msg string, args ...interface{}) { 32 s.G().GetLog().Debug("Maps.Srv: %s", fmt.Sprintf(msg, args...)) 33 } 34 35 func (s *Srv) makeError(w http.ResponseWriter, code int, msg string, args ...interface{}) { 36 s.debug("serve: error code: %d msg %s", code, fmt.Sprintf(msg, args...)) 37 w.WriteHeader(code) 38 } 39 40 func (s *Srv) serve(w http.ResponseWriter, req *http.Request) { 41 ctx := globals.ChatCtx(context.Background(), s.G(), keybase1.TLFIdentifyBehavior_CHAT_GUI, nil, nil) 42 strlat := req.URL.Query().Get("lat") 43 strlon := req.URL.Query().Get("lon") 44 strwidth := req.URL.Query().Get("width") 45 strheight := req.URL.Query().Get("height") 46 username := req.URL.Query().Get("username") 47 lat, err := strconv.ParseFloat(strlat, 64) 48 if err != nil { 49 s.makeError(w, http.StatusBadRequest, "invalid lat: %s", err) 50 return 51 } 52 lon, err := strconv.ParseFloat(strlon, 64) 53 if err != nil { 54 s.makeError(w, http.StatusBadRequest, "invalid lon: %s", err) 55 return 56 } 57 width, err := strconv.ParseInt(strwidth, 0, 0) 58 if err != nil { 59 s.makeError(w, http.StatusBadRequest, "invalid width: %s", err) 60 return 61 } 62 height, err := strconv.ParseInt(strheight, 0, 0) 63 if err != nil { 64 s.makeError(w, http.StatusBadRequest, "invalid height: %s", err) 65 return 66 } 67 mapURL, err := GetCustomMapURL(ctx, s.G().ExternalAPIKeySource, lat, lon, int(width)*scale, 68 int(height)*scale) 69 if err != nil { 70 s.makeError(w, http.StatusInternalServerError, "unable to get map url: %s", err) 71 return 72 } 73 mapReader, _, err := MapReaderFromURL(ctx, s.G(), mapURL) 74 if err != nil { 75 s.makeError(w, http.StatusInternalServerError, "unable to get map reader: %s", err) 76 return 77 } 78 79 defer mapReader.Close() 80 81 var reader io.ReadCloser 82 if username != "" { 83 avatarReader, _, err := avatars.GetBorderedCircleAvatar(ctx, s.G(), username, 48, 8, 8) 84 if err != nil { 85 s.makeError(w, http.StatusInternalServerError, "unable to get avatar: %s", err) 86 return 87 } 88 89 fancyReader, _, err := DecorateMap(ctx, avatarReader, mapReader) 90 if err != nil { 91 s.makeError(w, http.StatusInternalServerError, "unable to decorate map: %s", err) 92 return 93 } 94 reader = fancyReader 95 } else { 96 reader = mapReader 97 } 98 99 if _, err := io.Copy(w, reader); err != nil { 100 s.makeError(w, http.StatusInternalServerError, "unable to read map: %s", err) 101 return 102 } 103 } 104 105 func ServiceInit(g *globals.Context, httpSrv *manager.Srv) { 106 NewSrv(g, httpSrv) 107 }