diff --git a/server/api/tumdev/campus_backend.pb.gw.go b/server/api/tumdev/campus_backend.pb.gw.go index 2490593c..16c03ce3 100644 --- a/server/api/tumdev/campus_backend.pb.gw.go +++ b/server/api/tumdev/campus_backend.pb.gw.go @@ -50,6 +50,76 @@ func local_request_Campus_GetTopNewsAlert_0(ctx context.Context, marshaler runti } +func request_Campus_GetNewsAlert_0(ctx context.Context, marshaler runtime.Marshaler, client CampusClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetNewsAlertRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.Int32(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := client.GetNewsAlert(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Campus_GetNewsAlert_0(ctx context.Context, marshaler runtime.Marshaler, server CampusServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetNewsAlertRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.Int32(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := server.GetNewsAlert(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Campus_GetNewsAlerts_0(ctx context.Context, marshaler runtime.Marshaler, client CampusClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq emptypb.Empty + var metadata runtime.ServerMetadata + + msg, err := client.GetNewsAlerts(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Campus_GetNewsAlerts_0(ctx context.Context, marshaler runtime.Marshaler, server CampusServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq emptypb.Empty + var metadata runtime.ServerMetadata + + msg, err := server.GetNewsAlerts(ctx, &protoReq) + return msg, metadata, err + +} + func request_Campus_GetNewsSources_0(ctx context.Context, marshaler runtime.Marshaler, client CampusClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq emptypb.Empty var metadata runtime.ServerMetadata @@ -1337,6 +1407,56 @@ func RegisterCampusHandlerServer(ctx context.Context, mux *runtime.ServeMux, ser }) + mux.Handle("GET", pattern_Campus_GetNewsAlert_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/api.Campus/GetNewsAlert", runtime.WithHTTPPathPattern("/news/alerts/{id}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Campus_GetNewsAlert_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_Campus_GetNewsAlert_0(annotatedContext, mux, outboundMarshaler, w, req, response_Campus_GetNewsAlert_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Campus_GetNewsAlerts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/api.Campus/GetNewsAlerts", runtime.WithHTTPPathPattern("/news/alerts")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Campus_GetNewsAlerts_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_Campus_GetNewsAlerts_0(annotatedContext, mux, outboundMarshaler, w, req, response_Campus_GetNewsAlerts_0{resp}, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Campus_GetNewsSources_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -2275,6 +2395,50 @@ func RegisterCampusHandlerClient(ctx context.Context, mux *runtime.ServeMux, cli }) + mux.Handle("GET", pattern_Campus_GetNewsAlert_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/api.Campus/GetNewsAlert", runtime.WithHTTPPathPattern("/news/alerts/{id}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Campus_GetNewsAlert_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_Campus_GetNewsAlert_0(annotatedContext, mux, outboundMarshaler, w, req, response_Campus_GetNewsAlert_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Campus_GetNewsAlerts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/api.Campus/GetNewsAlerts", runtime.WithHTTPPathPattern("/news/alerts")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Campus_GetNewsAlerts_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_Campus_GetNewsAlerts_0(annotatedContext, mux, outboundMarshaler, w, req, response_Campus_GetNewsAlerts_0{resp}, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Campus_GetNewsSources_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -3057,6 +3221,24 @@ func (m response_Campus_GetTopNewsAlert_0) XXX_ResponseBody() interface{} { return response.Alert } +type response_Campus_GetNewsAlert_0 struct { + proto.Message +} + +func (m response_Campus_GetNewsAlert_0) XXX_ResponseBody() interface{} { + response := m.Message.(*GetNewsAlertReply) + return response.Alert +} + +type response_Campus_GetNewsAlerts_0 struct { + proto.Message +} + +func (m response_Campus_GetNewsAlerts_0) XXX_ResponseBody() interface{} { + response := m.Message.(*GetNewsAlertsReply) + return response.Alerts +} + type response_Campus_GetNewsSources_0 struct { proto.Message } @@ -3150,6 +3332,10 @@ func (m response_Campus_GetDishes_0) XXX_ResponseBody() interface{} { var ( pattern_Campus_GetTopNewsAlert_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"news", "alerts", "top"}, "")) + pattern_Campus_GetNewsAlert_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"news", "alerts", "id"}, "")) + + pattern_Campus_GetNewsAlerts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"news", "alerts"}, "")) + pattern_Campus_GetNewsSources_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"news", "sources"}, "")) pattern_Campus_SearchRooms_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"roomfinder", "room", "search"}, "")) @@ -3224,6 +3410,10 @@ var ( var ( forward_Campus_GetTopNewsAlert_0 = runtime.ForwardResponseMessage + forward_Campus_GetNewsAlert_0 = runtime.ForwardResponseMessage + + forward_Campus_GetNewsAlerts_0 = runtime.ForwardResponseMessage + forward_Campus_GetNewsSources_0 = runtime.ForwardResponseMessage forward_Campus_SearchRooms_0 = runtime.ForwardResponseMessage diff --git a/server/api/tumdev/campus_backend.proto b/server/api/tumdev/campus_backend.proto index 0d59602e..88e2a8fd 100644 --- a/server/api/tumdev/campus_backend.proto +++ b/server/api/tumdev/campus_backend.proto @@ -19,6 +19,18 @@ service Campus { response_body: "alert" }; } + rpc GetNewsAlert (GetNewsAlertRequest) returns (GetNewsAlertReply) { + option (google.api.http) = { + get: "/news/alerts/{id}" + response_body: "alert" + }; + } + rpc GetNewsAlerts (google.protobuf.Empty) returns (GetNewsAlertsReply) { + option (google.api.http) = { + get: "/news/alerts" + response_body: "alerts" + }; + } rpc GetNewsSources (google.protobuf.Empty) returns (NewsSourceReply) { option (google.api.http) = { @@ -387,6 +399,17 @@ message NewsSource { string icon = 3; } +message GetNewsAlertRequest { + int32 id = 1; +} + +message GetNewsAlertReply { + NewsAlert alert = 1; +} + +message GetNewsAlertsReply { + repeated NewsAlert alerts = 1; +} message GetTopNewsAlertReply { NewsAlert alert = 1; } diff --git a/server/api/tumdev/campus_backend.swagger.json b/server/api/tumdev/campus_backend.swagger.json index ebc58afb..1539e0ac 100644 --- a/server/api/tumdev/campus_backend.swagger.json +++ b/server/api/tumdev/campus_backend.swagger.json @@ -835,6 +835,32 @@ ] } }, + "/news/alerts": { + "get": { + "operationId": "Campus_GetNewsAlerts", + "responses": { + "200": { + "description": "", + "schema": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/apiNewsAlert" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "tags": [ + "Campus" + ] + } + }, "/news/alerts/top": { "get": { "operationId": "Campus_GetTopNewsAlert", @@ -857,6 +883,37 @@ ] } }, + "/news/alerts/{id}": { + "get": { + "operationId": "Campus_GetNewsAlert", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/apiNewsAlert" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "tags": [ + "Campus" + ] + } + }, "/news/sources": { "get": { "operationId": "Campus_GetNewsSources", @@ -1555,6 +1612,26 @@ } } }, + "apiGetNewsAlertReply": { + "type": "object", + "properties": { + "alert": { + "$ref": "#/definitions/apiNewsAlert" + } + } + }, + "apiGetNewsAlertsReply": { + "type": "object", + "properties": { + "alerts": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/apiNewsAlert" + } + } + } + }, "apiGetNotificationsConfirmReply": { "type": "object", "properties": { diff --git a/server/api/tumdev/campus_backend_grpc.pb.go b/server/api/tumdev/campus_backend_grpc.pb.go index 4c8cee17..56e68fac 100644 --- a/server/api/tumdev/campus_backend_grpc.pb.go +++ b/server/api/tumdev/campus_backend_grpc.pb.go @@ -21,6 +21,8 @@ const _ = grpc.SupportPackageIsVersion7 const ( Campus_GetTopNewsAlert_FullMethodName = "/api.Campus/GetTopNewsAlert" + Campus_GetNewsAlert_FullMethodName = "/api.Campus/GetNewsAlert" + Campus_GetNewsAlerts_FullMethodName = "/api.Campus/GetNewsAlerts" Campus_GetNewsSources_FullMethodName = "/api.Campus/GetNewsSources" Campus_SearchRooms_FullMethodName = "/api.Campus/SearchRooms" Campus_GetLocations_FullMethodName = "/api.Campus/GetLocations" @@ -63,6 +65,8 @@ const ( // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type CampusClient interface { GetTopNewsAlert(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetTopNewsAlertReply, error) + GetNewsAlert(ctx context.Context, in *GetNewsAlertRequest, opts ...grpc.CallOption) (*GetNewsAlertReply, error) + GetNewsAlerts(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetNewsAlertsReply, error) GetNewsSources(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*NewsSourceReply, error) SearchRooms(ctx context.Context, in *SearchRoomsRequest, opts ...grpc.CallOption) (*SearchRoomsReply, error) // a location is a campus location/building, e.g. "Garching Forschungszentrum" @@ -122,6 +126,24 @@ func (c *campusClient) GetTopNewsAlert(ctx context.Context, in *emptypb.Empty, o return out, nil } +func (c *campusClient) GetNewsAlert(ctx context.Context, in *GetNewsAlertRequest, opts ...grpc.CallOption) (*GetNewsAlertReply, error) { + out := new(GetNewsAlertReply) + err := c.cc.Invoke(ctx, Campus_GetNewsAlert_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *campusClient) GetNewsAlerts(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetNewsAlertsReply, error) { + out := new(GetNewsAlertsReply) + err := c.cc.Invoke(ctx, Campus_GetNewsAlerts_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *campusClient) GetNewsSources(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*NewsSourceReply, error) { out := new(NewsSourceReply) err := c.cc.Invoke(ctx, Campus_GetNewsSources_FullMethodName, in, out, opts...) @@ -442,6 +464,8 @@ func (c *campusClient) RemoveDevice(ctx context.Context, in *RemoveDeviceRequest // for forward compatibility type CampusServer interface { GetTopNewsAlert(context.Context, *emptypb.Empty) (*GetTopNewsAlertReply, error) + GetNewsAlert(context.Context, *GetNewsAlertRequest) (*GetNewsAlertReply, error) + GetNewsAlerts(context.Context, *emptypb.Empty) (*GetNewsAlertsReply, error) GetNewsSources(context.Context, *emptypb.Empty) (*NewsSourceReply, error) SearchRooms(context.Context, *SearchRoomsRequest) (*SearchRoomsReply, error) // a location is a campus location/building, e.g. "Garching Forschungszentrum" @@ -492,6 +516,12 @@ type UnimplementedCampusServer struct { func (UnimplementedCampusServer) GetTopNewsAlert(context.Context, *emptypb.Empty) (*GetTopNewsAlertReply, error) { return nil, status.Errorf(codes.Unimplemented, "method GetTopNewsAlert not implemented") } +func (UnimplementedCampusServer) GetNewsAlert(context.Context, *GetNewsAlertRequest) (*GetNewsAlertReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetNewsAlert not implemented") +} +func (UnimplementedCampusServer) GetNewsAlerts(context.Context, *emptypb.Empty) (*GetNewsAlertsReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetNewsAlerts not implemented") +} func (UnimplementedCampusServer) GetNewsSources(context.Context, *emptypb.Empty) (*NewsSourceReply, error) { return nil, status.Errorf(codes.Unimplemented, "method GetNewsSources not implemented") } @@ -628,6 +658,42 @@ func _Campus_GetTopNewsAlert_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _Campus_GetNewsAlert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetNewsAlertRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CampusServer).GetNewsAlert(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Campus_GetNewsAlert_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CampusServer).GetNewsAlert(ctx, req.(*GetNewsAlertRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Campus_GetNewsAlerts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CampusServer).GetNewsAlerts(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Campus_GetNewsAlerts_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CampusServer).GetNewsAlerts(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + func _Campus_GetNewsSources_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(emptypb.Empty) if err := dec(in); err != nil { @@ -1269,6 +1335,14 @@ var Campus_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetTopNewsAlert", Handler: _Campus_GetTopNewsAlert_Handler, }, + { + MethodName: "GetNewsAlert", + Handler: _Campus_GetNewsAlert_Handler, + }, + { + MethodName: "GetNewsAlerts", + Handler: _Campus_GetNewsAlerts_Handler, + }, { MethodName: "GetNewsSources", Handler: _Campus_GetNewsSources_Handler, diff --git a/server/backend/news.go b/server/backend/news.go index 1e59df59..8b5360a1 100644 --- a/server/backend/news.go +++ b/server/backend/news.go @@ -60,25 +60,53 @@ func (s *CampusServer) GetTopNewsAlert(ctx context.Context, _ *emptypb.Empty) (* }}, nil } -func (s *CampusServer) GetNewsAlerts(ctx context.Context, _ *pb.GetNewsAlertsRequest) (*pb.GetNewsAlertsReply, error) { +func (s *CampusServer) GetNewsAlert(ctx context.Context, req *pb.GetNewsAlertRequest) (*pb.GetNewsAlertReply, error) { if err := s.checkDevice(ctx); err != nil { return nil, err } var res *model.NewsAlert - err := s.db.Joins("Files").Where("NOW() between `from` and `to`").First(&res).Error + err := s.db.Joins("Files").Where("news_alert = ?", req.Id).First(&res).Error if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, status.Error(codes.NotFound, "no currenty active top news") + return nil, status.Error(codes.NotFound, "no news alerts") } else if err != nil { - log.WithError(err).Error("could not GetTopNews") - return nil, status.Error(codes.Internal, "could not GetTopNews") + log.WithError(err).Error("could not GetNewsAlert") + return nil, status.Error(codes.Internal, "could not GetNewsAlert") } - return &pb.GetTopNewsReply{ + return &pb.GetNewsAlertReply{Alert: &pb.NewsAlert{ ImageUrl: res.Files.URL.String, Link: res.Link.String, Created: timestamppb.New(res.Created), From: timestamppb.New(res.From), To: timestamppb.New(res.To), - }, nil + }}, nil +} + +func (s *CampusServer) GetNewsAlerts(ctx context.Context, _ *emptypb.Empty) (*pb.GetNewsAlertsReply, error) { + if err := s.checkDevice(ctx); err != nil { + return nil, err + } + + var res []*model.NewsAlert + err := s.db.Joins("Files").Scan(&res).Error + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, status.Error(codes.NotFound, "no news alerts") + } else if err != nil { + log.WithError(err).Error("could not GetNewsAlerts") + return nil, status.Error(codes.Internal, "could not GetNewsAlerts") + } + + var alerts []*pb.NewsAlert + for _, alert := range res { + alerts = append(alerts, &pb.NewsAlert{ + ImageUrl: alert.Files.URL.String, + Link: alert.Link.String, + Created: timestamppb.New(alert.Created), + From: timestamppb.New(alert.From), + To: timestamppb.New(alert.To), + }) + } + + return &pb.GetNewsAlertsReply{Alerts: alerts}, nil }