diff --git a/Makefile b/Makefile index cc24462f..90e2a591 100644 --- a/Makefile +++ b/Makefile @@ -3,13 +3,13 @@ PROTOC_VERSION := 3.17.2 PROTOC_RELEASE := https://github.com/protocolbuffers/protobuf/releases PROTOC_URL := $(PROTOC_RELEASE)/download/v$(PROTOC_VERSION)/ -PROTO_FILES := $(shell find . -name "*.proto" -type f) +PROTO_FILES := $(shell find server -name "*.proto" -type f) +PROTO_THIRDPARTY_FILES := $(shell find thirdparty -name "*.proto" -type f) UNAME := $(shell uname) PROTOC_ZIP_MACOS := protoc-$(PROTOC_VERSION)-osx-x86_64.zip PROTOC_ZIP_LINUX := protoc-$(PROTOC_VERSION)-linux-x86_64.zip PROTOC_ZIP_WINDOWS := protoc-$(PROTOC_VERSION)-win64.zip - ifeq ($(UNAME),Darwin) PROTOC_FULL_URL := $(PROTOC_URL)/$(PROTOC_ZIP_MACOS) PROTOC_FILE := $(PROTOC_ZIP_MACOS) @@ -21,6 +21,8 @@ else ifeq ($(UNAME), Windows) PROTOC_FILE := $(PROTOC_ZIP_WINDOWS) endif +DART_MOCK_FILES := $(shell find client -name "*.mocks.dart" -type f) + .PHONY: install install: curl -OL $(PROTOC_FULL_URL) @@ -38,6 +40,7 @@ gen.go: mkdir -p ./server/pkg/protos/ protoc \ --proto_path=server \ + --proto_path=thirdparty \ --go_out=server \ --go_opt=paths=source_relative \ --go-grpc_out=server \ @@ -46,18 +49,22 @@ gen.go: .PHONY: gen.dart gen.dart: - mkdir -p ./client/lib/protos/ && \ - protoc \ - --proto_path=server \ - --dart_out=grpc:./client/lib/protos \ - $(PROTO_FILES) + mkdir -p ./client/lib/protos/ + protoc \ + --proto_path=server \ + --proto_path=thirdparty \ + --dart_out=grpc:./client/lib/protos \ + $(PROTO_FILES) $(PROTO_THIRDPARTY_FILES) .PHONY: test test: test.go test.dart .PHONY: test.dart -test.dart: - cd client && flutter pub run build_runner build && flutter analyze && flutter test +test.dart: $(DART_MOCK_FILES) + cd client && flutter analyze && flutter test + +$(DART_MOCK_FILES): $(DART_MOCK_FILES:.mocks.dart=.dart) + cd client && flutter pub run build_runner build .PHONY: test.dart-e2e test.dart-e2e: diff --git a/client/lib/protos/google/protobuf/timestamp.pb.dart b/client/lib/protos/google/protobuf/timestamp.pb.dart new file mode 100644 index 00000000..e5ed493f --- /dev/null +++ b/client/lib/protos/google/protobuf/timestamp.pb.dart @@ -0,0 +1,83 @@ +/// +// Generated code. Do not modify. +// source: google/protobuf/timestamp.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields + +import 'dart:core' as $core; + +import 'package:fixnum/fixnum.dart' as $fixnum; +import 'package:protobuf/protobuf.dart' as $pb; + +import 'package:protobuf/src/protobuf/mixins/well_known.dart' as $mixin; + +class Timestamp extends $pb.GeneratedMessage with $mixin.TimestampMixin { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Timestamp', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'google.protobuf'), createEmptyInstance: create, toProto3Json: $mixin.TimestampMixin.toProto3JsonHelper, fromProto3Json: $mixin.TimestampMixin.fromProto3JsonHelper) + ..aInt64(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'seconds') + ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'nanos', $pb.PbFieldType.O3) + ..hasRequiredFields = false + ; + + Timestamp._() : super(); + factory Timestamp({ + $fixnum.Int64? seconds, + $core.int? nanos, + }) { + final _result = create(); + if (seconds != null) { + _result.seconds = seconds; + } + if (nanos != null) { + _result.nanos = nanos; + } + return _result; + } + factory Timestamp.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory Timestamp.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + Timestamp clone() => Timestamp()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + Timestamp copyWith(void Function(Timestamp) updates) => super.copyWith((message) => updates(message as Timestamp)) as Timestamp; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static Timestamp create() => Timestamp._(); + Timestamp createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static Timestamp getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Timestamp? _defaultInstance; + + @$pb.TagNumber(1) + $fixnum.Int64 get seconds => $_getI64(0); + @$pb.TagNumber(1) + set seconds($fixnum.Int64 v) { $_setInt64(0, v); } + @$pb.TagNumber(1) + $core.bool hasSeconds() => $_has(0); + @$pb.TagNumber(1) + void clearSeconds() => clearField(1); + + @$pb.TagNumber(2) + $core.int get nanos => $_getIZ(1); + @$pb.TagNumber(2) + set nanos($core.int v) { $_setSignedInt32(1, v); } + @$pb.TagNumber(2) + $core.bool hasNanos() => $_has(1); + @$pb.TagNumber(2) + void clearNanos() => clearField(2); + /// Creates a new instance from [dateTime]. + /// + /// Time zone information will not be preserved. + static Timestamp fromDateTime($core.DateTime dateTime) { + final result = create(); + $mixin.TimestampMixin.setFromDateTime(result, dateTime); + return result; + } +} + diff --git a/client/lib/protos/google/protobuf/timestamp.pbenum.dart b/client/lib/protos/google/protobuf/timestamp.pbenum.dart new file mode 100644 index 00000000..72b1ec68 --- /dev/null +++ b/client/lib/protos/google/protobuf/timestamp.pbenum.dart @@ -0,0 +1,7 @@ +/// +// Generated code. Do not modify. +// source: google/protobuf/timestamp.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields + diff --git a/client/lib/protos/google/protobuf/timestamp.pbjson.dart b/client/lib/protos/google/protobuf/timestamp.pbjson.dart new file mode 100644 index 00000000..d031fbfc --- /dev/null +++ b/client/lib/protos/google/protobuf/timestamp.pbjson.dart @@ -0,0 +1,21 @@ +/// +// Generated code. Do not modify. +// source: google/protobuf/timestamp.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package + +import 'dart:core' as $core; +import 'dart:convert' as $convert; +import 'dart:typed_data' as $typed_data; +@$core.Deprecated('Use timestampDescriptor instead') +const Timestamp$json = const { + '1': 'Timestamp', + '2': const [ + const {'1': 'seconds', '3': 1, '4': 1, '5': 3, '10': 'seconds'}, + const {'1': 'nanos', '3': 2, '4': 1, '5': 5, '10': 'nanos'}, + ], +}; + +/// Descriptor for `Timestamp`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List timestampDescriptor = $convert.base64Decode('CglUaW1lc3RhbXASGAoHc2Vjb25kcxgBIAEoA1IHc2Vjb25kcxIUCgVuYW5vcxgCIAEoBVIFbmFub3M='); diff --git a/client/lib/protos/pkg/pr12er/messages.pb.dart b/client/lib/protos/pkg/pr12er/messages.pb.dart index dd6719f5..462b0eed 100644 --- a/client/lib/protos/pkg/pr12er/messages.pb.dart +++ b/client/lib/protos/pkg/pr12er/messages.pb.dart @@ -9,6 +9,8 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; +import '../../google/protobuf/timestamp.pb.dart' as $1; + import 'messages.pbenum.dart'; export 'messages.pbenum.dart'; @@ -23,7 +25,7 @@ class Video extends $pb.GeneratedMessage { ..a<$core.int>(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'numberOfLike', $pb.PbFieldType.O3) ..pPS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'keywords') ..a<$core.int>(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'numberOfViews', $pb.PbFieldType.O3) - ..aOS(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'publishedDate') + ..aOM<$1.Timestamp>(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'publishedDate', subBuilder: $1.Timestamp.create) ..hasRequiredFields = false ; @@ -37,7 +39,7 @@ class Video extends $pb.GeneratedMessage { $core.int? numberOfLike, $core.Iterable<$core.String>? keywords, $core.int? numberOfViews, - $core.String? publishedDate, + $1.Timestamp? publishedDate, }) { final _result = create(); if (id != null) { @@ -157,13 +159,15 @@ class Video extends $pb.GeneratedMessage { void clearNumberOfViews() => clearField(8); @$pb.TagNumber(9) - $core.String get publishedDate => $_getSZ(8); + $1.Timestamp get publishedDate => $_getN(8); @$pb.TagNumber(9) - set publishedDate($core.String v) { $_setString(8, v); } + set publishedDate($1.Timestamp v) { setField(9, v); } @$pb.TagNumber(9) $core.bool hasPublishedDate() => $_has(8); @$pb.TagNumber(9) void clearPublishedDate() => clearField(9); + @$pb.TagNumber(9) + $1.Timestamp ensurePublishedDate() => $_ensure(8); } class Detail extends $pb.GeneratedMessage { diff --git a/client/lib/protos/pkg/pr12er/messages.pbjson.dart b/client/lib/protos/pkg/pr12er/messages.pbjson.dart index 27559156..3a300774 100644 --- a/client/lib/protos/pkg/pr12er/messages.pbjson.dart +++ b/client/lib/protos/pkg/pr12er/messages.pbjson.dart @@ -48,12 +48,12 @@ const Video$json = const { const {'1': 'number_of_like', '3': 6, '4': 1, '5': 5, '10': 'numberOfLike'}, const {'1': 'keywords', '3': 7, '4': 3, '5': 9, '10': 'keywords'}, const {'1': 'number_of_views', '3': 8, '4': 1, '5': 5, '10': 'numberOfViews'}, - const {'1': 'published_date', '3': 9, '4': 1, '5': 9, '10': 'publishedDate'}, + const {'1': 'published_date', '3': 9, '4': 1, '5': 11, '6': '.google.protobuf.Timestamp', '10': 'publishedDate'}, ], }; /// Descriptor for `Video`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List videoDescriptor = $convert.base64Decode('CgVWaWRlbxIOCgJpZBgBIAEoBVICaWQSFAoFdGl0bGUYAiABKAlSBXRpdGxlEhIKBGxpbmsYAyABKAlSBGxpbmsSHAoJcHJlc2VudGVyGAQgASgJUglwcmVzZW50ZXISMAoIY2F0ZWdvcnkYBSABKA4yFC5wa2cucHIxMmVyLkNhdGVnb3J5UghjYXRlZ29yeRIkCg5udW1iZXJfb2ZfbGlrZRgGIAEoBVIMbnVtYmVyT2ZMaWtlEhoKCGtleXdvcmRzGAcgAygJUghrZXl3b3JkcxImCg9udW1iZXJfb2Zfdmlld3MYCCABKAVSDW51bWJlck9mVmlld3MSJQoOcHVibGlzaGVkX2RhdGUYCSABKAlSDXB1Ymxpc2hlZERhdGU='); +final $typed_data.Uint8List videoDescriptor = $convert.base64Decode('CgVWaWRlbxIOCgJpZBgBIAEoBVICaWQSFAoFdGl0bGUYAiABKAlSBXRpdGxlEhIKBGxpbmsYAyABKAlSBGxpbmsSHAoJcHJlc2VudGVyGAQgASgJUglwcmVzZW50ZXISMAoIY2F0ZWdvcnkYBSABKA4yFC5wa2cucHIxMmVyLkNhdGVnb3J5UghjYXRlZ29yeRIkCg5udW1iZXJfb2ZfbGlrZRgGIAEoBVIMbnVtYmVyT2ZMaWtlEhoKCGtleXdvcmRzGAcgAygJUghrZXl3b3JkcxImCg9udW1iZXJfb2Zfdmlld3MYCCABKAVSDW51bWJlck9mVmlld3MSQQoOcHVibGlzaGVkX2RhdGUYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wUg1wdWJsaXNoZWREYXRl'); @$core.Deprecated('Use detailDescriptor instead') const Detail$json = const { '1': 'Detail', diff --git a/client/lib/protos/pkg/pr12er/service.pb.dart b/client/lib/protos/pkg/pr12er/service.pb.dart index 9480044a..082b5407 100644 --- a/client/lib/protos/pkg/pr12er/service.pb.dart +++ b/client/lib/protos/pkg/pr12er/service.pb.dart @@ -9,7 +9,7 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; -import 'messages.pb.dart' as $1; +import 'messages.pb.dart' as $2; class HelloRequest extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'HelloRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'pkg.pr12er'), createEmptyInstance: create) @@ -107,13 +107,13 @@ class HelloResponse extends $pb.GeneratedMessage { class GetVideosResponse extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GetVideosResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'pkg.pr12er'), createEmptyInstance: create) - ..pc<$1.Video>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'videos', $pb.PbFieldType.PM, subBuilder: $1.Video.create) + ..pc<$2.Video>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'videos', $pb.PbFieldType.PM, subBuilder: $2.Video.create) ..hasRequiredFields = false ; GetVideosResponse._() : super(); factory GetVideosResponse({ - $core.Iterable<$1.Video>? videos, + $core.Iterable<$2.Video>? videos, }) { final _result = create(); if (videos != null) { @@ -143,7 +143,7 @@ class GetVideosResponse extends $pb.GeneratedMessage { static GetVideosResponse? _defaultInstance; @$pb.TagNumber(1) - $core.List<$1.Video> get videos => $_getList(0); + $core.List<$2.Video> get videos => $_getList(0); } class GetVideosRequest extends $pb.GeneratedMessage { @@ -177,13 +177,13 @@ class GetVideosRequest extends $pb.GeneratedMessage { class GetDetailsResponse extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GetDetailsResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'pkg.pr12er'), createEmptyInstance: create) - ..aOM<$1.Detail>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'detail', subBuilder: $1.Detail.create) + ..aOM<$2.Detail>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'detail', subBuilder: $2.Detail.create) ..hasRequiredFields = false ; GetDetailsResponse._() : super(); factory GetDetailsResponse({ - $1.Detail? detail, + $2.Detail? detail, }) { final _result = create(); if (detail != null) { @@ -213,15 +213,15 @@ class GetDetailsResponse extends $pb.GeneratedMessage { static GetDetailsResponse? _defaultInstance; @$pb.TagNumber(1) - $1.Detail get detail => $_getN(0); + $2.Detail get detail => $_getN(0); @$pb.TagNumber(1) - set detail($1.Detail v) { setField(1, v); } + set detail($2.Detail v) { setField(1, v); } @$pb.TagNumber(1) $core.bool hasDetail() => $_has(0); @$pb.TagNumber(1) void clearDetail() => clearField(1); @$pb.TagNumber(1) - $1.Detail ensureDetail() => $_ensure(0); + $2.Detail ensureDetail() => $_ensure(0); } class GetDetailsRequest extends $pb.GeneratedMessage { diff --git a/client/lib/widgets/detail/header.dart b/client/lib/widgets/detail/header.dart index 321e35a0..18e2b96a 100644 --- a/client/lib/widgets/detail/header.dart +++ b/client/lib/widgets/detail/header.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; import 'package:pr12er/protos/pkg/pr12er/messages.pb.dart'; // ignore: must_be_immutable @@ -62,7 +63,8 @@ class HeaderWidget extends StatelessWidget { return [ const Icon(Icons.today), const SizedBox(width: 8), - Text(video.publishedDate, style: const TextStyle(fontSize: 18)) + Text(DateFormat.yMd().format(video.publishedDate.toDateTime()), + style: const TextStyle(fontSize: 18)) ]; } } diff --git a/client/pubspec.lock b/client/pubspec.lock index b5c9ad1a..69c81d24 100644 --- a/client/pubspec.lock +++ b/client/pubspec.lock @@ -301,6 +301,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.0" + intl: + dependency: "direct main" + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.17.0" io: dependency: transitive description: diff --git a/client/pubspec.yaml b/client/pubspec.yaml index 5ec2fbf8..34e406b0 100644 --- a/client/pubspec.yaml +++ b/client/pubspec.yaml @@ -26,6 +26,7 @@ dependencies: flutter: sdk: flutter grpc: ^3.0.0 + intl: ^0.17.0 protobuf: ^2.0.0 provider: ^5.0.0 youtube_player_flutter: ^8.0.0 diff --git a/server/pkg/pr12er/messages.pb.go b/server/pkg/pr12er/messages.pb.go index 4544f4aa..bbbe5e41 100644 --- a/server/pkg/pr12er/messages.pb.go +++ b/server/pkg/pr12er/messages.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.17.0 +// protoc v3.17.1 // source: pkg/pr12er/messages.proto package pr12er @@ -9,6 +9,7 @@ package pr12er import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" ) @@ -135,15 +136,15 @@ type Video struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` - Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` - Link string `protobuf:"bytes,3,opt,name=link,proto3" json:"link,omitempty"` - Presenter string `protobuf:"bytes,4,opt,name=presenter,proto3" json:"presenter,omitempty"` - Category Category `protobuf:"varint,5,opt,name=category,proto3,enum=pkg.pr12er.Category" json:"category,omitempty"` - NumberOfLike int32 `protobuf:"varint,6,opt,name=number_of_like,json=numberOfLike,proto3" json:"number_of_like,omitempty"` - Keywords []string `protobuf:"bytes,7,rep,name=keywords,proto3" json:"keywords,omitempty"` - NumberOfViews int32 `protobuf:"varint,8,opt,name=number_of_views,json=numberOfViews,proto3" json:"number_of_views,omitempty"` - PublishedDate string `protobuf:"bytes,9,opt,name=published_date,json=publishedDate,proto3" json:"published_date,omitempty"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` + Link string `protobuf:"bytes,3,opt,name=link,proto3" json:"link,omitempty"` + Presenter string `protobuf:"bytes,4,opt,name=presenter,proto3" json:"presenter,omitempty"` + Category Category `protobuf:"varint,5,opt,name=category,proto3,enum=pkg.pr12er.Category" json:"category,omitempty"` + NumberOfLike int32 `protobuf:"varint,6,opt,name=number_of_like,json=numberOfLike,proto3" json:"number_of_like,omitempty"` + Keywords []string `protobuf:"bytes,7,rep,name=keywords,proto3" json:"keywords,omitempty"` + NumberOfViews int32 `protobuf:"varint,8,opt,name=number_of_views,json=numberOfViews,proto3" json:"number_of_views,omitempty"` + PublishedDate *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=published_date,json=publishedDate,proto3" json:"published_date,omitempty"` } func (x *Video) Reset() { @@ -234,11 +235,11 @@ func (x *Video) GetNumberOfViews() int32 { return 0 } -func (x *Video) GetPublishedDate() string { +func (x *Video) GetPublishedDate() *timestamppb.Timestamp { if x != nil { return x.PublishedDate } - return "" + return nil } type Detail struct { @@ -562,91 +563,95 @@ var File_pkg_pr12er_messages_proto protoreflect.FileDescriptor var file_pkg_pr12er_messages_proto_rawDesc = []byte{ 0x0a, 0x19, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x70, 0x6b, 0x67, - 0x2e, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, 0x22, 0xa2, 0x02, 0x0a, 0x05, 0x56, 0x69, 0x64, 0x65, - 0x6f, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x70, - 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x30, 0x0a, 0x08, 0x63, 0x61, 0x74, - 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x70, 0x6b, - 0x67, 0x2e, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, 0x2e, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, - 0x79, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x24, 0x0a, 0x0e, 0x6e, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x6c, 0x69, 0x6b, 0x65, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x66, 0x4c, 0x69, 0x6b, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x07, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x26, 0x0a, - 0x0f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x73, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x66, - 0x56, 0x69, 0x65, 0x77, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, - 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, 0x22, 0xc3, 0x01, 0x0a, - 0x06, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x13, 0x0a, 0x05, 0x70, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x72, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x05, - 0x70, 0x61, 0x70, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6b, - 0x67, 0x2e, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x70, 0x65, 0x72, 0x52, 0x05, - 0x70, 0x61, 0x70, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, - 0x74, 0x5f, 0x70, 0x61, 0x70, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, - 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x70, 0x65, - 0x72, 0x52, 0x0e, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x50, 0x61, 0x70, 0x65, 0x72, - 0x73, 0x12, 0x3f, 0x0a, 0x12, 0x73, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x5f, 0x70, 0x61, 0x70, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, - 0x70, 0x6b, 0x67, 0x2e, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x70, 0x65, 0x72, - 0x52, 0x10, 0x73, 0x61, 0x6d, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x50, 0x61, 0x70, 0x65, - 0x72, 0x73, 0x22, 0xf6, 0x01, 0x0a, 0x05, 0x50, 0x61, 0x70, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, - 0x70, 0x61, 0x70, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x70, 0x61, 0x70, 0x65, 0x72, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x72, 0x78, 0x69, 0x76, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x72, 0x78, 0x69, 0x76, - 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x62, 0x73, 0x72, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x62, 0x73, 0x72, 0x61, 0x63, 0x74, 0x12, 0x19, 0x0a, 0x08, - 0x70, 0x75, 0x62, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x70, 0x75, 0x62, 0x44, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x73, 0x12, 0x3a, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, - 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x70, 0x72, - 0x31, 0x32, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, - 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2c, 0x0a, - 0x07, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x22, 0xd4, 0x01, 0x0a, 0x0a, - 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, - 0x5f, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x69, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0a, 0x69, 0x73, 0x4f, 0x66, 0x66, 0x69, 0x63, 0x69, 0x61, 0x6c, 0x12, 0x10, 0x0a, 0x03, 0x75, - 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x14, 0x0a, - 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x77, - 0x6e, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x70, 0x72, 0x31, - 0x32, 0x65, 0x72, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x09, 0x66, - 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x0d, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x66, 0x53, 0x74, 0x61, 0x72, 0x73, - 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x5b, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x75, 0x6c, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, - 0x82, 0x01, 0x0a, 0x08, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x14, - 0x43, 0x41, 0x54, 0x45, 0x47, 0x4f, 0x52, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x41, 0x54, 0x45, 0x47, 0x4f, - 0x52, 0x59, 0x5f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x43, - 0x41, 0x54, 0x45, 0x47, 0x4f, 0x52, 0x59, 0x5f, 0x4e, 0x4c, 0x50, 0x10, 0x02, 0x12, 0x10, 0x0a, - 0x0c, 0x43, 0x41, 0x54, 0x45, 0x47, 0x4f, 0x52, 0x59, 0x5f, 0x4f, 0x43, 0x52, 0x10, 0x03, 0x12, - 0x12, 0x0a, 0x0e, 0x43, 0x41, 0x54, 0x45, 0x47, 0x4f, 0x52, 0x59, 0x5f, 0x41, 0x55, 0x44, 0x49, - 0x4f, 0x10, 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x41, 0x54, 0x45, 0x47, 0x4f, 0x52, 0x59, 0x5f, - 0x52, 0x53, 0x10, 0x05, 0x2a, 0x6d, 0x0a, 0x09, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, - 0x6b, 0x12, 0x19, 0x0a, 0x15, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x57, 0x4f, 0x52, 0x4b, 0x5f, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, - 0x46, 0x52, 0x41, 0x4d, 0x45, 0x57, 0x4f, 0x52, 0x4b, 0x5f, 0x54, 0x45, 0x4e, 0x53, 0x4f, 0x52, - 0x46, 0x4c, 0x4f, 0x57, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x57, - 0x4f, 0x52, 0x4b, 0x5f, 0x50, 0x59, 0x54, 0x4f, 0x52, 0x43, 0x48, 0x10, 0x02, 0x12, 0x14, 0x0a, - 0x10, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x57, 0x4f, 0x52, 0x4b, 0x5f, 0x4f, 0x54, 0x48, 0x45, 0x52, - 0x53, 0x10, 0x03, 0x42, 0x28, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x70, 0x6f, 0x74, 0x2f, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbe, 0x02, 0x0a, 0x05, 0x56, 0x69, 0x64, + 0x65, 0x6f, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x1c, 0x0a, 0x09, + 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x30, 0x0a, 0x08, 0x63, 0x61, + 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x70, + 0x6b, 0x67, 0x2e, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, 0x2e, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, + 0x72, 0x79, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x24, 0x0a, 0x0e, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x6c, 0x69, 0x6b, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x66, 0x4c, 0x69, + 0x6b, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x26, + 0x0a, 0x0f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x76, 0x69, 0x65, 0x77, + 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4f, + 0x66, 0x56, 0x69, 0x65, 0x77, 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, + 0x68, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x73, 0x68, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, 0x22, 0xc3, 0x01, 0x0a, 0x06, 0x44, 0x65, + 0x74, 0x61, 0x69, 0x6c, 0x12, 0x13, 0x0a, 0x05, 0x70, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x72, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x05, 0x70, 0x61, 0x70, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x70, + 0x72, 0x31, 0x32, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x70, 0x65, 0x72, 0x52, 0x05, 0x70, 0x61, 0x70, + 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x5f, 0x70, + 0x61, 0x70, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6b, + 0x67, 0x2e, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x70, 0x65, 0x72, 0x52, 0x0e, + 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x50, 0x61, 0x70, 0x65, 0x72, 0x73, 0x12, 0x3f, + 0x0a, 0x12, 0x73, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x70, 0x61, + 0x70, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6b, 0x67, + 0x2e, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x70, 0x65, 0x72, 0x52, 0x10, 0x73, + 0x61, 0x6d, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x50, 0x61, 0x70, 0x65, 0x72, 0x73, 0x22, + 0xf6, 0x01, 0x0a, 0x05, 0x50, 0x61, 0x70, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x61, 0x70, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x70, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x72, 0x78, 0x69, 0x76, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x72, 0x78, 0x69, 0x76, 0x49, 0x64, 0x12, + 0x18, 0x0a, 0x07, 0x61, 0x62, 0x73, 0x72, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x61, 0x62, 0x73, 0x72, 0x61, 0x63, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x75, 0x62, + 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x75, 0x62, + 0x44, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x73, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x73, 0x12, 0x3a, + 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x70, 0x72, 0x31, 0x32, 0x65, + 0x72, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x0c, 0x72, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x07, 0x6d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x6b, + 0x67, 0x2e, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, + 0x07, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x22, 0xd4, 0x01, 0x0a, 0x0a, 0x52, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x6f, 0x66, + 0x66, 0x69, 0x63, 0x69, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, + 0x4f, 0x66, 0x66, 0x69, 0x63, 0x69, 0x61, 0x6c, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x12, 0x33, 0x0a, 0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, + 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x09, 0x66, 0x72, 0x61, 0x6d, + 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, + 0x6f, 0x66, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x66, 0x53, 0x74, 0x61, 0x72, 0x73, 0x12, 0x20, 0x0a, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, + 0x5b, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, + 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x66, 0x75, 0x6c, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x82, 0x01, 0x0a, + 0x08, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x41, 0x54, + 0x45, 0x47, 0x4f, 0x52, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x41, 0x54, 0x45, 0x47, 0x4f, 0x52, 0x59, 0x5f, + 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x41, 0x54, 0x45, + 0x47, 0x4f, 0x52, 0x59, 0x5f, 0x4e, 0x4c, 0x50, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x41, + 0x54, 0x45, 0x47, 0x4f, 0x52, 0x59, 0x5f, 0x4f, 0x43, 0x52, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, + 0x43, 0x41, 0x54, 0x45, 0x47, 0x4f, 0x52, 0x59, 0x5f, 0x41, 0x55, 0x44, 0x49, 0x4f, 0x10, 0x04, + 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x41, 0x54, 0x45, 0x47, 0x4f, 0x52, 0x59, 0x5f, 0x52, 0x53, 0x10, + 0x05, 0x2a, 0x6d, 0x0a, 0x09, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x19, + 0x0a, 0x15, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x57, 0x4f, 0x52, 0x4b, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x46, 0x52, 0x41, + 0x4d, 0x45, 0x57, 0x4f, 0x52, 0x4b, 0x5f, 0x54, 0x45, 0x4e, 0x53, 0x4f, 0x52, 0x46, 0x4c, 0x4f, + 0x57, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x57, 0x4f, 0x52, 0x4b, + 0x5f, 0x50, 0x59, 0x54, 0x4f, 0x52, 0x43, 0x48, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x46, 0x52, + 0x41, 0x4d, 0x45, 0x57, 0x4f, 0x52, 0x4b, 0x5f, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x53, 0x10, 0x03, + 0x42, 0x28, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, + 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x70, 0x6f, 0x74, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, + 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x31, 0x32, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -664,27 +669,29 @@ func file_pkg_pr12er_messages_proto_rawDescGZIP() []byte { var file_pkg_pr12er_messages_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_pkg_pr12er_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_pkg_pr12er_messages_proto_goTypes = []interface{}{ - (Category)(0), // 0: pkg.pr12er.Category - (Framework)(0), // 1: pkg.pr12er.Framework - (*Video)(nil), // 2: pkg.pr12er.Video - (*Detail)(nil), // 3: pkg.pr12er.Detail - (*Paper)(nil), // 4: pkg.pr12er.Paper - (*Repository)(nil), // 5: pkg.pr12er.Repository - (*Method)(nil), // 6: pkg.pr12er.Method + (Category)(0), // 0: pkg.pr12er.Category + (Framework)(0), // 1: pkg.pr12er.Framework + (*Video)(nil), // 2: pkg.pr12er.Video + (*Detail)(nil), // 3: pkg.pr12er.Detail + (*Paper)(nil), // 4: pkg.pr12er.Paper + (*Repository)(nil), // 5: pkg.pr12er.Repository + (*Method)(nil), // 6: pkg.pr12er.Method + (*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp } var file_pkg_pr12er_messages_proto_depIdxs = []int32{ 0, // 0: pkg.pr12er.Video.category:type_name -> pkg.pr12er.Category - 4, // 1: pkg.pr12er.Detail.paper:type_name -> pkg.pr12er.Paper - 4, // 2: pkg.pr12er.Detail.relevant_papers:type_name -> pkg.pr12er.Paper - 4, // 3: pkg.pr12er.Detail.same_author_papers:type_name -> pkg.pr12er.Paper - 5, // 4: pkg.pr12er.Paper.repositories:type_name -> pkg.pr12er.Repository - 6, // 5: pkg.pr12er.Paper.methods:type_name -> pkg.pr12er.Method - 1, // 6: pkg.pr12er.Repository.framework:type_name -> pkg.pr12er.Framework - 7, // [7:7] is the sub-list for method output_type - 7, // [7:7] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 7, // 1: pkg.pr12er.Video.published_date:type_name -> google.protobuf.Timestamp + 4, // 2: pkg.pr12er.Detail.paper:type_name -> pkg.pr12er.Paper + 4, // 3: pkg.pr12er.Detail.relevant_papers:type_name -> pkg.pr12er.Paper + 4, // 4: pkg.pr12er.Detail.same_author_papers:type_name -> pkg.pr12er.Paper + 5, // 5: pkg.pr12er.Paper.repositories:type_name -> pkg.pr12er.Repository + 6, // 6: pkg.pr12er.Paper.methods:type_name -> pkg.pr12er.Method + 1, // 7: pkg.pr12er.Repository.framework:type_name -> pkg.pr12er.Framework + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_pkg_pr12er_messages_proto_init() } diff --git a/server/pkg/pr12er/messages.proto b/server/pkg/pr12er/messages.proto index 72bdba7b..a87f1bbd 100644 --- a/server/pkg/pr12er/messages.proto +++ b/server/pkg/pr12er/messages.proto @@ -1,6 +1,8 @@ syntax = "proto3"; package pkg.pr12er; +import "google/protobuf/timestamp.proto"; + option go_package = "github.com/codingpot/server/pkg/pr12er"; enum Category { @@ -28,7 +30,7 @@ message Video { int32 number_of_like = 6; repeated string keywords = 7; int32 number_of_views = 8; - string published_date = 9; + google.protobuf.Timestamp published_date = 9; } message Detail { @@ -45,7 +47,7 @@ message Paper { string pub_date = 4; repeated string authors = 5; repeated Repository repositories = 6; - repeated Method methods = 7; + repeated Method methods = 7; } message Repository { @@ -61,4 +63,4 @@ message Method { string name = 1; string full_name = 2; string description = 3; -} +} \ No newline at end of file diff --git a/server/pkg/pr12er/metadata.pb.go b/server/pkg/pr12er/metadata.pb.go index e643f456..72f3a4be 100644 --- a/server/pkg/pr12er/metadata.pb.go +++ b/server/pkg/pr12er/metadata.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.17.0 +// protoc v3.17.1 // source: pkg/pr12er/metadata.proto package pr12er diff --git a/server/pkg/pr12er/service.pb.go b/server/pkg/pr12er/service.pb.go index 64715936..d54a3d88 100644 --- a/server/pkg/pr12er/service.pb.go +++ b/server/pkg/pr12er/service.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.17.0 +// protoc v3.17.1 // source: pkg/pr12er/service.proto package pr12er diff --git a/thirdparty/google/protobuf/timestamp.proto b/thirdparty/google/protobuf/timestamp.proto new file mode 100644 index 00000000..9c4c75cc --- /dev/null +++ b/thirdparty/google/protobuf/timestamp.proto @@ -0,0 +1,147 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "google.golang.org/protobuf/types/known/timestamppb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "TimestampProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// A Timestamp represents a point in time independent of any time zone or local +// calendar, encoded as a count of seconds and fractions of seconds at +// nanosecond resolution. The count is relative to an epoch at UTC midnight on +// January 1, 1970, in the proleptic Gregorian calendar which extends the +// Gregorian calendar backwards to year one. +// +// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap +// second table is needed for interpretation, using a [24-hour linear +// smear](https://developers.google.com/time/smear). +// +// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By +// restricting to that range, we ensure that we can convert to and from [RFC +// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. +// +// # Examples +// +// Example 1: Compute Timestamp from POSIX `time()`. +// +// Timestamp timestamp; +// timestamp.set_seconds(time(NULL)); +// timestamp.set_nanos(0); +// +// Example 2: Compute Timestamp from POSIX `gettimeofday()`. +// +// struct timeval tv; +// gettimeofday(&tv, NULL); +// +// Timestamp timestamp; +// timestamp.set_seconds(tv.tv_sec); +// timestamp.set_nanos(tv.tv_usec * 1000); +// +// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. +// +// FILETIME ft; +// GetSystemTimeAsFileTime(&ft); +// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; +// +// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z +// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. +// Timestamp timestamp; +// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); +// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); +// +// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. +// +// long millis = System.currentTimeMillis(); +// +// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) +// .setNanos((int) ((millis % 1000) * 1000000)).build(); +// +// +// Example 5: Compute Timestamp from Java `Instant.now()`. +// +// Instant now = Instant.now(); +// +// Timestamp timestamp = +// Timestamp.newBuilder().setSeconds(now.getEpochSecond()) +// .setNanos(now.getNano()).build(); +// +// +// Example 6: Compute Timestamp from current time in Python. +// +// timestamp = Timestamp() +// timestamp.GetCurrentTime() +// +// # JSON Mapping +// +// In JSON format, the Timestamp type is encoded as a string in the +// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the +// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" +// where {year} is always expressed using four digits while {month}, {day}, +// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional +// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), +// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone +// is required. A proto3 JSON serializer should always use UTC (as indicated by +// "Z") when printing the Timestamp type and a proto3 JSON parser should be +// able to accept both UTC and other timezones (as indicated by an offset). +// +// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past +// 01:30 UTC on January 15, 2017. +// +// In JavaScript, one can convert a Date object to this format using the +// standard +// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) +// method. In Python, a standard `datetime.datetime` object can be converted +// to this format using +// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with +// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use +// the Joda Time's [`ISODateTimeFormat.dateTime()`]( +// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D +// ) to obtain a formatter capable of generating timestamps in this format. +// +// +message Timestamp { + // Represents seconds of UTC time since Unix epoch + // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + // 9999-12-31T23:59:59Z inclusive. + int64 seconds = 1; + + // Non-negative fractions of a second at nanosecond resolution. Negative + // second values with fractions must still have non-negative nanos values + // that count forward in time. Must be from 0 to 999,999,999 + // inclusive. + int32 nanos = 2; +} \ No newline at end of file