add route

This commit is contained in:
Владимир Фёдоров 2026-03-26 02:23:36 +07:00
parent 9f9ffaa55f
commit 0a6294a62f
12 changed files with 864 additions and 22 deletions

View File

@ -12,8 +12,38 @@ service pinnedMessage {
get: "/ping"
};
}
rpc GetDays(GetDaysReq) returns (GetDaysRsp) {
option (google.api.http) = {
get: "/schedule"
};
}
}
message PingReq {}
message PingRsp {}
message GetDaysReq {}
message GetDaysRsp {
repeated Day days = 1;
}
message Day {
string date = 1;
repeated Performance performances = 2;
}
message Performance {
string time_collection = 1;
string time_start = 2;
string place = 3;
string name = 4;
repeated Number numbers = 5;
string costumes = 6;
}
message Number {
string name = 1;
}

Binary file not shown.

View File

@ -9,6 +9,7 @@ import (
"pinned_message/internal/config"
"pinned_message/internal/modules/data_parser"
"pinned_message/internal/modules/date_parser"
"pinned_message/internal/services"
"pinned_message/internal/services/schedule_parser"
"pinned_message/internal/services/schedule_storage"
proto "pinned_message/proto"
@ -29,17 +30,25 @@ func main() {
s := grpc.NewServer()
ctx := context.Background()
scheduleStorage := schedule_storage.NewScheduleStorage(config.GetScheduleFilepath())
scheduleParser := schedule_parser.NewScheduleParser(
data_parser.NewGoogleTableScheduleParser(),
date_parser.NewDateParser(),
*schedule_storage.NewScheduleStorage(config.GetScheduleFilepath()),
scheduleStorage,
)
go func() {
scheduleParser.Run(ctx)
}()
// Attach the Greeter service to the server
proto.RegisterPinnedMessageServer(s, app.NewServer())
proto.RegisterPinnedMessageServer(
s,
app.NewServer(
services.NewServices(
scheduleStorage,
),
),
)
// Serve gRPC server
log.Println("Serving gRPC on 0.0.0.0:8080")
go func() {

View File

@ -2,17 +2,27 @@ package app
import (
"context"
"pinned_message/internal/services"
proto "pinned_message/proto"
)
type Server struct {
proto.UnimplementedPinnedMessageServer
services *services.Services
}
func NewServer() *Server {
return &Server{}
func NewServer(
services *services.Services,
) *Server {
return &Server{
services: services,
}
}
func (s *Server) Ping(_ context.Context, _ *proto.PingReq) (*proto.PingRsp, error) {
return &proto.PingRsp{}, nil
}
func (s *Server) GetDays(ctx context.Context, req *proto.GetDaysReq) (*proto.GetDaysRsp, error) {
return s.services.GetDays(ctx, req)
}

View File

@ -25,13 +25,13 @@ type performance struct {
type ScheduleParser struct {
dataParser data_parser.IDataParser
dateParser date_parser.IDateParser
scheduleStorage schedule_storage.ScheduleStorage
scheduleStorage *schedule_storage.ScheduleStorage
}
func NewScheduleParser(
dataParser data_parser.IDataParser,
dateParser date_parser.IDateParser,
scheduleStorage schedule_storage.ScheduleStorage,
scheduleStorage *schedule_storage.ScheduleStorage,
) *ScheduleParser {
return &ScheduleParser{
dataParser: dataParser,

View File

@ -2,6 +2,7 @@ package schedule_storage
import (
"encoding/json"
"fmt"
"log"
"os"
"pinned_message/internal/models"
@ -30,3 +31,16 @@ func (s *ScheduleStorage) SaveSchedule(days []*models.Day) error {
log.Printf("save story to: %s", s.filepath)
return nil
}
func (s *ScheduleStorage) GetSchedule() ([]*models.Day, error) {
data, err := os.ReadFile(s.filepath)
if err != nil {
return nil, fmt.Errorf("story file %s not found", s.filepath)
}
log.Printf("load story from: %s", s.filepath)
days := []*models.Day{}
if err := json.Unmarshal(data, &days); err != nil {
return nil, err
}
return days, nil
}

View File

@ -0,0 +1,66 @@
package services
import (
"context"
"pinned_message/internal/services/schedule_storage"
"pinned_message/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type Services struct {
scheduleStorage *schedule_storage.ScheduleStorage
}
func NewServices(
scheduleStorage *schedule_storage.ScheduleStorage,
) *Services {
return &Services{
scheduleStorage: scheduleStorage,
}
}
func (s *Services) GetDays(context.Context, *proto.GetDaysReq) (*proto.GetDaysRsp, error) {
days, err := s.scheduleStorage.GetSchedule()
if err != nil {
return nil, status.Errorf(codes.Internal, err.Error())
}
res := &proto.GetDaysRsp{}
for _, day := range days {
resPerformances := make([]*proto.Performance, 0, len(day.Performances))
for _, performance := range day.Performances {
resNumbers := make([]*proto.Number, 0, len(performance.Numbers))
for _, number := range performance.Numbers {
resNumbers = append(
resNumbers,
&proto.Number{
Name: number.Name,
},
)
}
resPerformances = append(
resPerformances,
&proto.Performance{
TimeCollection: performance.TimeCollection,
TimeStart: performance.TimeStart,
Place: performance.Place,
Name: performance.Name,
Numbers: resNumbers,
Costumes: performance.Costumes,
},
)
}
res.Days = append(
res.Days,
&proto.Day{
Date: day.Date.String(),
Performances: resPerformances,
},
)
}
return res, nil
}

View File

@ -94,6 +94,266 @@ func (*PingRsp) Descriptor() ([]byte, []int) {
return file_main_proto_rawDescGZIP(), []int{1}
}
type GetDaysReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetDaysReq) Reset() {
*x = GetDaysReq{}
mi := &file_main_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetDaysReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetDaysReq) ProtoMessage() {}
func (x *GetDaysReq) ProtoReflect() protoreflect.Message {
mi := &file_main_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetDaysReq.ProtoReflect.Descriptor instead.
func (*GetDaysReq) Descriptor() ([]byte, []int) {
return file_main_proto_rawDescGZIP(), []int{2}
}
type GetDaysRsp struct {
state protoimpl.MessageState `protogen:"open.v1"`
Days []*Day `protobuf:"bytes,1,rep,name=days,proto3" json:"days,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetDaysRsp) Reset() {
*x = GetDaysRsp{}
mi := &file_main_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetDaysRsp) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetDaysRsp) ProtoMessage() {}
func (x *GetDaysRsp) ProtoReflect() protoreflect.Message {
mi := &file_main_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetDaysRsp.ProtoReflect.Descriptor instead.
func (*GetDaysRsp) Descriptor() ([]byte, []int) {
return file_main_proto_rawDescGZIP(), []int{3}
}
func (x *GetDaysRsp) GetDays() []*Day {
if x != nil {
return x.Days
}
return nil
}
type Day struct {
state protoimpl.MessageState `protogen:"open.v1"`
Date string `protobuf:"bytes,1,opt,name=date,proto3" json:"date,omitempty"`
Performances []*Performance `protobuf:"bytes,2,rep,name=performances,proto3" json:"performances,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Day) Reset() {
*x = Day{}
mi := &file_main_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Day) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Day) ProtoMessage() {}
func (x *Day) ProtoReflect() protoreflect.Message {
mi := &file_main_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Day.ProtoReflect.Descriptor instead.
func (*Day) Descriptor() ([]byte, []int) {
return file_main_proto_rawDescGZIP(), []int{4}
}
func (x *Day) GetDate() string {
if x != nil {
return x.Date
}
return ""
}
func (x *Day) GetPerformances() []*Performance {
if x != nil {
return x.Performances
}
return nil
}
type Performance struct {
state protoimpl.MessageState `protogen:"open.v1"`
TimeCollection string `protobuf:"bytes,1,opt,name=time_collection,json=timeCollection,proto3" json:"time_collection,omitempty"`
TimeStart string `protobuf:"bytes,2,opt,name=time_start,json=timeStart,proto3" json:"time_start,omitempty"`
Place string `protobuf:"bytes,3,opt,name=place,proto3" json:"place,omitempty"`
Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"`
Numbers []*Number `protobuf:"bytes,5,rep,name=numbers,proto3" json:"numbers,omitempty"`
Costumes string `protobuf:"bytes,6,opt,name=costumes,proto3" json:"costumes,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Performance) Reset() {
*x = Performance{}
mi := &file_main_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Performance) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Performance) ProtoMessage() {}
func (x *Performance) ProtoReflect() protoreflect.Message {
mi := &file_main_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Performance.ProtoReflect.Descriptor instead.
func (*Performance) Descriptor() ([]byte, []int) {
return file_main_proto_rawDescGZIP(), []int{5}
}
func (x *Performance) GetTimeCollection() string {
if x != nil {
return x.TimeCollection
}
return ""
}
func (x *Performance) GetTimeStart() string {
if x != nil {
return x.TimeStart
}
return ""
}
func (x *Performance) GetPlace() string {
if x != nil {
return x.Place
}
return ""
}
func (x *Performance) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *Performance) GetNumbers() []*Number {
if x != nil {
return x.Numbers
}
return nil
}
func (x *Performance) GetCostumes() string {
if x != nil {
return x.Costumes
}
return ""
}
type Number struct {
state protoimpl.MessageState `protogen:"open.v1"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Number) Reset() {
*x = Number{}
mi := &file_main_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Number) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Number) ProtoMessage() {}
func (x *Number) ProtoReflect() protoreflect.Message {
mi := &file_main_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Number.ProtoReflect.Descriptor instead.
func (*Number) Descriptor() ([]byte, []int) {
return file_main_proto_rawDescGZIP(), []int{6}
}
func (x *Number) GetName() string {
if x != nil {
return x.Name
}
return ""
}
var File_main_proto protoreflect.FileDescriptor
const file_main_proto_rawDesc = "" +
@ -101,9 +361,28 @@ const file_main_proto_rawDesc = "" +
"\n" +
"main.proto\x12\x14crabs.pinned_message\x1a\x1cgoogle/api/annotations.proto\"\t\n" +
"\aPingReq\"\t\n" +
"\aPingRsp2d\n" +
"\aPingRsp\"\f\n" +
"\n" +
"GetDaysReq\";\n" +
"\n" +
"GetDaysRsp\x12-\n" +
"\x04days\x18\x01 \x03(\v2\x19.crabs.pinned_message.DayR\x04days\"`\n" +
"\x03Day\x12\x12\n" +
"\x04date\x18\x01 \x01(\tR\x04date\x12E\n" +
"\fperformances\x18\x02 \x03(\v2!.crabs.pinned_message.PerformanceR\fperformances\"\xd3\x01\n" +
"\vPerformance\x12'\n" +
"\x0ftime_collection\x18\x01 \x01(\tR\x0etimeCollection\x12\x1d\n" +
"\n" +
"time_start\x18\x02 \x01(\tR\ttimeStart\x12\x14\n" +
"\x05place\x18\x03 \x01(\tR\x05place\x12\x12\n" +
"\x04name\x18\x04 \x01(\tR\x04name\x126\n" +
"\anumbers\x18\x05 \x03(\v2\x1c.crabs.pinned_message.NumberR\anumbers\x12\x1a\n" +
"\bcostumes\x18\x06 \x01(\tR\bcostumes\"\x1c\n" +
"\x06Number\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name2\xc6\x01\n" +
"\rpinnedMessage\x12S\n" +
"\x04Ping\x12\x1d.crabs.pinned_message.PingReq\x1a\x1d.crabs.pinned_message.PingRsp\"\r\x82\xd3\xe4\x93\x02\a\x12\x05/pingB\vZ\tpkg/protob\x06proto3"
"\x04Ping\x12\x1d.crabs.pinned_message.PingReq\x1a\x1d.crabs.pinned_message.PingRsp\"\r\x82\xd3\xe4\x93\x02\a\x12\x05/ping\x12`\n" +
"\aGetDays\x12 .crabs.pinned_message.GetDaysReq\x1a .crabs.pinned_message.GetDaysRsp\"\x11\x82\xd3\xe4\x93\x02\v\x12\t/scheduleB\vZ\tpkg/protob\x06proto3"
var (
file_main_proto_rawDescOnce sync.Once
@ -117,19 +396,29 @@ func file_main_proto_rawDescGZIP() []byte {
return file_main_proto_rawDescData
}
var file_main_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_main_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_main_proto_goTypes = []any{
(*PingReq)(nil), // 0: crabs.pinned_message.PingReq
(*PingRsp)(nil), // 1: crabs.pinned_message.PingRsp
(*PingReq)(nil), // 0: crabs.pinned_message.PingReq
(*PingRsp)(nil), // 1: crabs.pinned_message.PingRsp
(*GetDaysReq)(nil), // 2: crabs.pinned_message.GetDaysReq
(*GetDaysRsp)(nil), // 3: crabs.pinned_message.GetDaysRsp
(*Day)(nil), // 4: crabs.pinned_message.Day
(*Performance)(nil), // 5: crabs.pinned_message.Performance
(*Number)(nil), // 6: crabs.pinned_message.Number
}
var file_main_proto_depIdxs = []int32{
0, // 0: crabs.pinned_message.pinnedMessage.Ping:input_type -> crabs.pinned_message.PingReq
1, // 1: crabs.pinned_message.pinnedMessage.Ping:output_type -> crabs.pinned_message.PingRsp
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
4, // 0: crabs.pinned_message.GetDaysRsp.days:type_name -> crabs.pinned_message.Day
5, // 1: crabs.pinned_message.Day.performances:type_name -> crabs.pinned_message.Performance
6, // 2: crabs.pinned_message.Performance.numbers:type_name -> crabs.pinned_message.Number
0, // 3: crabs.pinned_message.pinnedMessage.Ping:input_type -> crabs.pinned_message.PingReq
2, // 4: crabs.pinned_message.pinnedMessage.GetDays:input_type -> crabs.pinned_message.GetDaysReq
1, // 5: crabs.pinned_message.pinnedMessage.Ping:output_type -> crabs.pinned_message.PingRsp
3, // 6: crabs.pinned_message.pinnedMessage.GetDays:output_type -> crabs.pinned_message.GetDaysRsp
5, // [5:7] is the sub-list for method output_type
3, // [3:5] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
}
func init() { file_main_proto_init() }
@ -143,7 +432,7 @@ func file_main_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_main_proto_rawDesc), len(file_main_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumMessages: 7,
NumExtensions: 0,
NumServices: 1,
},

View File

@ -56,6 +56,27 @@ func local_request_PinnedMessage_Ping_0(ctx context.Context, marshaler runtime.M
return msg, metadata, err
}
func request_PinnedMessage_GetDays_0(ctx context.Context, marshaler runtime.Marshaler, client PinnedMessageClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq GetDaysReq
metadata runtime.ServerMetadata
)
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.GetDays(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_PinnedMessage_GetDays_0(ctx context.Context, marshaler runtime.Marshaler, server PinnedMessageServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq GetDaysReq
metadata runtime.ServerMetadata
)
msg, err := server.GetDays(ctx, &protoReq)
return msg, metadata, err
}
// RegisterPinnedMessageHandlerServer registers the http handlers for service PinnedMessage to "mux".
// UnaryRPC :call PinnedMessageServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
@ -82,6 +103,26 @@ func RegisterPinnedMessageHandlerServer(ctx context.Context, mux *runtime.ServeM
}
forward_PinnedMessage_Ping_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_PinnedMessage_GetDays_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)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/crabs.pinned_message.PinnedMessage/GetDays", runtime.WithHTTPPathPattern("/schedule"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_PinnedMessage_GetDays_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_PinnedMessage_GetDays_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@ -139,13 +180,32 @@ func RegisterPinnedMessageHandlerClient(ctx context.Context, mux *runtime.ServeM
}
forward_PinnedMessage_Ping_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_PinnedMessage_GetDays_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)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/crabs.pinned_message.PinnedMessage/GetDays", runtime.WithHTTPPathPattern("/schedule"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_PinnedMessage_GetDays_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_PinnedMessage_GetDays_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
var (
pattern_PinnedMessage_Ping_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"ping"}, ""))
pattern_PinnedMessage_Ping_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"ping"}, ""))
pattern_PinnedMessage_GetDays_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"schedule"}, ""))
)
var (
forward_PinnedMessage_Ping_0 = runtime.ForwardResponseMessage
forward_PinnedMessage_Ping_0 = runtime.ForwardResponseMessage
forward_PinnedMessage_GetDays_0 = runtime.ForwardResponseMessage
)

View File

@ -32,9 +32,90 @@
"pinnedMessage"
]
}
},
"/schedule": {
"get": {
"operationId": "pinnedMessage_GetDays",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/pinned_messageGetDaysRsp"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
},
"tags": [
"pinnedMessage"
]
}
}
},
"definitions": {
"pinned_messageDay": {
"type": "object",
"properties": {
"date": {
"type": "string"
},
"performances": {
"type": "array",
"items": {
"$ref": "#/definitions/pinned_messagePerformance"
}
}
}
},
"pinned_messageGetDaysRsp": {
"type": "object",
"properties": {
"days": {
"type": "array",
"items": {
"$ref": "#/definitions/pinned_messageDay"
}
}
}
},
"pinned_messageNumber": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
},
"pinned_messagePerformance": {
"type": "object",
"properties": {
"time_collection": {
"type": "string"
},
"time_start": {
"type": "string"
},
"place": {
"type": "string"
},
"name": {
"type": "string"
},
"numbers": {
"type": "array",
"items": {
"$ref": "#/definitions/pinned_messageNumber"
}
},
"costumes": {
"type": "string"
}
}
},
"pinned_messagePingRsp": {
"type": "object"
},

View File

@ -19,7 +19,8 @@ import (
const _ = grpc.SupportPackageIsVersion9
const (
PinnedMessage_Ping_FullMethodName = "/crabs.pinned_message.pinnedMessage/Ping"
PinnedMessage_Ping_FullMethodName = "/crabs.pinned_message.pinnedMessage/Ping"
PinnedMessage_GetDays_FullMethodName = "/crabs.pinned_message.pinnedMessage/GetDays"
)
// PinnedMessageClient is the client API for PinnedMessage service.
@ -27,6 +28,7 @@ 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 PinnedMessageClient interface {
Ping(ctx context.Context, in *PingReq, opts ...grpc.CallOption) (*PingRsp, error)
GetDays(ctx context.Context, in *GetDaysReq, opts ...grpc.CallOption) (*GetDaysRsp, error)
}
type pinnedMessageClient struct {
@ -47,11 +49,22 @@ func (c *pinnedMessageClient) Ping(ctx context.Context, in *PingReq, opts ...grp
return out, nil
}
func (c *pinnedMessageClient) GetDays(ctx context.Context, in *GetDaysReq, opts ...grpc.CallOption) (*GetDaysRsp, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetDaysRsp)
err := c.cc.Invoke(ctx, PinnedMessage_GetDays_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// PinnedMessageServer is the server API for PinnedMessage service.
// All implementations must embed UnimplementedPinnedMessageServer
// for forward compatibility.
type PinnedMessageServer interface {
Ping(context.Context, *PingReq) (*PingRsp, error)
GetDays(context.Context, *GetDaysReq) (*GetDaysRsp, error)
mustEmbedUnimplementedPinnedMessageServer()
}
@ -65,6 +78,9 @@ type UnimplementedPinnedMessageServer struct{}
func (UnimplementedPinnedMessageServer) Ping(context.Context, *PingReq) (*PingRsp, error) {
return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented")
}
func (UnimplementedPinnedMessageServer) GetDays(context.Context, *GetDaysReq) (*GetDaysRsp, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetDays not implemented")
}
func (UnimplementedPinnedMessageServer) mustEmbedUnimplementedPinnedMessageServer() {}
func (UnimplementedPinnedMessageServer) testEmbeddedByValue() {}
@ -104,6 +120,24 @@ func _PinnedMessage_Ping_Handler(srv interface{}, ctx context.Context, dec func(
return interceptor(ctx, in, info, handler)
}
func _PinnedMessage_GetDays_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetDaysReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PinnedMessageServer).GetDays(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PinnedMessage_GetDays_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PinnedMessageServer).GetDays(ctx, req.(*GetDaysReq))
}
return interceptor(ctx, in, info, handler)
}
// PinnedMessage_ServiceDesc is the grpc.ServiceDesc for PinnedMessage service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@ -115,6 +149,10 @@ var PinnedMessage_ServiceDesc = grpc.ServiceDesc{
MethodName: "Ping",
Handler: _PinnedMessage_Ping_Handler,
},
{
MethodName: "GetDays",
Handler: _PinnedMessage_GetDays_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "main.proto",

245
test.json Normal file
View File

@ -0,0 +1,245 @@
{
"days": [
{
"date": "2026-03-24 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "-",
"timeStart": "18:00 - 20:00",
"place": "танцкласс",
"name": "репетиция",
"numbers": [{ "name": "все" }],
"costumes": "-"
}
]
},
{
"date": "2026-03-26 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "-",
"timeStart": "18:00 - 20:00",
"place": "танцкласс",
"name": "репетиция",
"numbers": [{ "name": "все" }],
"costumes": "-"
}
]
},
{
"date": "2026-03-27 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "13:00",
"timeStart": "15:00 - 17:00",
"place": "КДМ (Юрина 204в)",
"name": "Закрытие регионального этапа Всероссийского проекта-фестиваля «Российская школьная весна» Алтайского края и Открытие Краевого фестиваля студенческого творчества \"Студенческая весна на Алтае. Феста - 2026\"",
"numbers": [{ "name": "Гавря" }],
"costumes": ""
}
]
},
{
"date": "2026-03-28 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "",
"timeStart": "17:30 - 21:00",
"place": "актовый зал С",
"name": "репетиция КП",
"numbers": [{ "name": "Еще люблю" }],
"costumes": "реп форма"
}
]
},
{
"date": "2026-03-29 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "12.15",
"timeStart": "13:00-14:00",
"place": "концертный зал Д",
"name": "День открытых дверей АлтГУ",
"numbers": [{ "name": "Русская душа" }],
"costumes": ""
}
]
},
{
"date": "2026-03-30 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "",
"timeStart": "11:30-15:00",
"place": "аграрка на красноармейском",
"name": "ФЕСТА. Оригинальный жанр",
"numbers": [{ "name": "Песня цыганки" }],
"costumes": ""
}
]
},
{
"date": "2026-03-31 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "",
"timeStart": "17:30 - 21:00",
"place": "актовый зал С",
"name": "репетиция КП",
"numbers": [{ "name": "Еще люблю" }],
"costumes": "реп форма"
}
]
},
{
"date": "2026-04-01 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "",
"timeStart": "17:30 - 21:00",
"place": "актовый зал С",
"name": "репетиция КП",
"numbers": [{ "name": "Еще люблю" }],
"costumes": "костюм свой"
}
]
},
{
"date": "2026-04-02 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "",
"timeStart": "17:30 - 21:00",
"place": "актовый зал С",
"name": "репетиция КП",
"numbers": [{ "name": "Еще люблю" }],
"costumes": "костюм свой"
}
]
},
{
"date": "2026-04-03 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "",
"timeStart": "10:00-11:00",
"place": "актовый зал С",
"name": "ФЕСТА. КП",
"numbers": [{ "name": "Еще люблю" }],
"costumes": "костюм свой"
},
{
"timeCollection": "",
"timeStart": "15:00-16:00",
"place": "актовый зал С",
"name": "репетиция танцевального направления",
"numbers": [
{ "name": "Русская душа" },
{ "name": " Гавря" },
{ "name": " Полька" }
],
"costumes": ""
}
]
},
{
"date": "2026-04-04 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "",
"timeStart": "",
"place": "актовый зал С",
"name": "ФЕСТА. Танцевальное направление",
"numbers": [
{ "name": "Русская душа" },
{ "name": " Гавря" },
{ "name": " Полька" }
],
"costumes": ""
}
]
},
{
"date": "2026-04-05 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "",
"timeStart": "",
"place": "актовый зал С",
"name": "ФЕСТА. Танцевальное направление",
"numbers": [
{ "name": "Русская душа" },
{ "name": " Гавря" },
{ "name": " Полька" }
],
"costumes": ""
}
]
},
{
"date": "2026-04-06 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "",
"timeStart": "",
"place": "концертный зал Д",
"name": "ЕММО. открытие",
"numbers": [{ "name": "Китайский" }, { "name": " Полька" }],
"costumes": ""
}
]
},
{
"date": "2026-04-08 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "",
"timeStart": "",
"place": "концертный зал Д",
"name": "ЕММО. закрытие",
"numbers": [{ "name": "Гавря" }, { "name": " Русская душа" }],
"costumes": ""
}
]
},
{
"date": "2026-04-17 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "",
"timeStart": "Вечер",
"place": "актовый зал С",
"name": "Мисс ИББ",
"numbers": [{ "name": "Китайский" }],
"costumes": ""
}
]
},
{
"date": "2026-04-24 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "",
"timeStart": "",
"place": "актовый зал С",
"name": "Отчетник",
"numbers": [{ "name": "мы сдохнем" }],
"costumes": ""
}
]
},
{
"date": "2026-05-01 00:00:00 +0700 +07",
"performances": [
{
"timeCollection": "",
"timeStart": "",
"place": "отъезд от гаража С",
"name": "Маральник",
"numbers": [{ "name": "" }],
"costumes": ""
}
]
}
]
}