fbcrawl-colly 0.2.6 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,46 @@
1
+ module FbcrawlColly
2
+ class Client
3
+
4
+ def initialize(host_and_port)
5
+ @host_and_port = host_and_port
6
+ @client = new_grpc_client
7
+ @colly = @client.init(FbcrawlColly::Empty.new)
8
+
9
+ ObjectSpace.define_finalizer(self) do
10
+ new_grpc_client.free_colly(@colly)
11
+ end
12
+ end
13
+
14
+ def login(email, password, totp_secret = "")
15
+ s = @client.login(FbcrawlColly::LoginRequest.new(pointer: @colly, email: email, password: password, totp_secret: totp_secret)).cookies
16
+ end
17
+
18
+ def login_with_cookies(cookies)
19
+ s = @client.login_with_cookies(FbcrawlColly::LoginWithCookiesRequest.new(pointer: @colly, cookies: cookies))
20
+ end
21
+
22
+ def fetch_group_info(group_id_or_username)
23
+ s = @client.fetch_group_info(FbcrawlColly::FetchGroupInfoRequest.new(pointer: @colly, group_username: group_id_or_username))
24
+ end
25
+
26
+ def fetch_group_feed(group_id, next_cursor = nil)
27
+ s = @client.fetch_group_feed(FbcrawlColly::FetchGroupFeedRequest.new(pointer: @colly, group_id: group_id, next_cursor: next_cursor))
28
+ end
29
+
30
+ def fetch_post(group_id, post_id, comment_next_cursor = nil)
31
+ s = @client.fetch_post(FbcrawlColly::FetchPostRequest.new(pointer: @colly, group_id: group_id, post_id: post_id, comment_next_cursor: comment_next_cursor))
32
+ end
33
+
34
+ def fetch_content_images(post_id, next_cursor = nil)
35
+ s = @client.fetch_content_images(FbcrawlColly::FetchContentImagesRequest.new(pointer: @colly, post_id: post_id, next_cursor: next_cursor))
36
+ end
37
+
38
+ def fetch_image_url(image_id)
39
+ s = @client.fetch_image_url(FbcrawlColly::FetchImageUrlRequest.new(pointer: @colly, image_id: image_id))
40
+ end
41
+ private
42
+ def new_grpc_client
43
+ FbcrawlColly::Grpc::Stub.new(@host_and_port, :this_channel_is_insecure)
44
+ end
45
+ end
46
+ end
@@ -1,3 +1,3 @@
1
1
  module FbcrawlColly
2
- VERSION = "0.2.6"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -0,0 +1,117 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: fbcrawl.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_file("fbcrawl.proto", :syntax => :proto3) do
8
+ add_message "fbcrawl_colly.Empty" do
9
+ end
10
+ add_message "fbcrawl_colly.Pointer" do
11
+ optional :address, :int64, 1
12
+ end
13
+ add_message "fbcrawl_colly.LoginRequest" do
14
+ optional :pointer, :message, 1, "fbcrawl_colly.Pointer"
15
+ optional :email, :string, 2
16
+ optional :password, :string, 3
17
+ optional :totp_secret, :string, 4
18
+ end
19
+ add_message "fbcrawl_colly.LoginResponse" do
20
+ optional :cookies, :string, 1
21
+ end
22
+ add_message "fbcrawl_colly.LoginWithCookiesRequest" do
23
+ optional :pointer, :message, 1, "fbcrawl_colly.Pointer"
24
+ optional :cookies, :string, 2
25
+ end
26
+ add_message "fbcrawl_colly.FetchGroupInfoRequest" do
27
+ optional :pointer, :message, 1, "fbcrawl_colly.Pointer"
28
+ optional :group_username, :string, 2
29
+ end
30
+ add_message "fbcrawl_colly.FetchGroupFeedRequest" do
31
+ optional :pointer, :message, 1, "fbcrawl_colly.Pointer"
32
+ optional :group_id, :int64, 2
33
+ optional :next_cursor, :string, 3
34
+ end
35
+ add_message "fbcrawl_colly.FetchPostRequest" do
36
+ optional :pointer, :message, 1, "fbcrawl_colly.Pointer"
37
+ optional :group_id, :int64, 2
38
+ optional :post_id, :int64, 3
39
+ optional :comment_next_cursor, :string, 4
40
+ end
41
+ add_message "fbcrawl_colly.FetchContentImagesRequest" do
42
+ optional :pointer, :message, 1, "fbcrawl_colly.Pointer"
43
+ optional :post_id, :int64, 2
44
+ optional :next_cursor, :string, 3
45
+ end
46
+ add_message "fbcrawl_colly.FetchImageUrlRequest" do
47
+ optional :pointer, :message, 1, "fbcrawl_colly.Pointer"
48
+ optional :image_id, :int64, 2
49
+ end
50
+ add_message "fbcrawl_colly.FacebookGroup" do
51
+ optional :id, :int64, 1
52
+ optional :name, :string, 2
53
+ optional :member_count, :int64, 3
54
+ end
55
+ add_message "fbcrawl_colly.FacebookUser" do
56
+ optional :id, :int64, 1
57
+ optional :name, :string, 2
58
+ end
59
+ add_message "fbcrawl_colly.FacebookPost" do
60
+ optional :id, :int64, 1
61
+ optional :group, :message, 2, "fbcrawl_colly.FacebookGroup"
62
+ optional :user, :message, 3, "fbcrawl_colly.FacebookUser"
63
+ optional :content, :string, 4
64
+ optional :comments, :message, 5, "fbcrawl_colly.CommentList"
65
+ optional :content_link, :string, 6
66
+ repeated :content_images, :message, 7, "fbcrawl_colly.FacebookImage"
67
+ optional :content_image, :message, 8, "fbcrawl_colly.FacebookImage"
68
+ optional :created_at, :int64, 9
69
+ optional :reaction_count, :int64, 10
70
+ optional :comment_count, :int64, 11
71
+ end
72
+ add_message "fbcrawl_colly.CommentList" do
73
+ repeated :comments, :message, 5, "fbcrawl_colly.FacebookComment"
74
+ optional :next_cursor, :string, 12
75
+ end
76
+ add_message "fbcrawl_colly.FacebookImage" do
77
+ optional :id, :int64, 1
78
+ optional :url, :string, 2
79
+ end
80
+ add_message "fbcrawl_colly.FacebookComment" do
81
+ optional :id, :int64, 1
82
+ optional :post, :message, 2, "fbcrawl_colly.FacebookPost"
83
+ optional :user, :message, 3, "fbcrawl_colly.FacebookUser"
84
+ optional :content, :string, 4
85
+ optional :created_at, :int64, 5
86
+ end
87
+ add_message "fbcrawl_colly.FacebookPostList" do
88
+ repeated :posts, :message, 1, "fbcrawl_colly.FacebookPost"
89
+ optional :next_cursor, :string, 2
90
+ end
91
+ add_message "fbcrawl_colly.FacebookImageList" do
92
+ repeated :images, :message, 1, "fbcrawl_colly.FacebookImage"
93
+ optional :next_cursor, :string, 2
94
+ end
95
+ end
96
+ end
97
+
98
+ module FbcrawlColly
99
+ Empty = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.Empty").msgclass
100
+ Pointer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.Pointer").msgclass
101
+ LoginRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.LoginRequest").msgclass
102
+ LoginResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.LoginResponse").msgclass
103
+ LoginWithCookiesRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.LoginWithCookiesRequest").msgclass
104
+ FetchGroupInfoRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.FetchGroupInfoRequest").msgclass
105
+ FetchGroupFeedRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.FetchGroupFeedRequest").msgclass
106
+ FetchPostRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.FetchPostRequest").msgclass
107
+ FetchContentImagesRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.FetchContentImagesRequest").msgclass
108
+ FetchImageUrlRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.FetchImageUrlRequest").msgclass
109
+ FacebookGroup = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.FacebookGroup").msgclass
110
+ FacebookUser = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.FacebookUser").msgclass
111
+ FacebookPost = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.FacebookPost").msgclass
112
+ CommentList = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.CommentList").msgclass
113
+ FacebookImage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.FacebookImage").msgclass
114
+ FacebookComment = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.FacebookComment").msgclass
115
+ FacebookPostList = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.FacebookPostList").msgclass
116
+ FacebookImageList = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fbcrawl_colly.FacebookImageList").msgclass
117
+ end
@@ -0,0 +1,31 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # Source: fbcrawl.proto for package 'fbcrawl_colly'
3
+
4
+ require 'grpc'
5
+ require 'fbcrawl_pb'
6
+
7
+ module FbcrawlColly
8
+ module Grpc
9
+ class Service
10
+
11
+ include GRPC::GenericService
12
+
13
+ self.marshal_class_method = :encode
14
+ self.unmarshal_class_method = :decode
15
+ self.service_name = 'fbcrawl_colly.Grpc'
16
+
17
+ # Sends a greeting
18
+ rpc :Init, FbcrawlColly::Empty, FbcrawlColly::Pointer
19
+ rpc :FreeColly, FbcrawlColly::Pointer, FbcrawlColly::Empty
20
+ rpc :Login, FbcrawlColly::LoginRequest, FbcrawlColly::LoginResponse
21
+ rpc :LoginWithCookies, FbcrawlColly::LoginWithCookiesRequest, FbcrawlColly::Empty
22
+ rpc :FetchGroupInfo, FbcrawlColly::FetchGroupInfoRequest, FbcrawlColly::FacebookGroup
23
+ rpc :FetchGroupFeed, FbcrawlColly::FetchGroupFeedRequest, FbcrawlColly::FacebookPostList
24
+ rpc :FetchPost, FbcrawlColly::FetchPostRequest, FbcrawlColly::FacebookPost
25
+ rpc :FetchContentImages, FbcrawlColly::FetchContentImagesRequest, FbcrawlColly::FacebookImageList
26
+ rpc :FetchImageUrl, FbcrawlColly::FetchImageUrlRequest, FbcrawlColly::FacebookImage
27
+ end
28
+
29
+ Stub = Service.rpc_stub_class
30
+ end
31
+ end
data/main.go CHANGED
@@ -1,21 +1,17 @@
1
1
  package main
2
2
 
3
- /*
4
- #include <stdio.h>
5
- #include <stdlib.h>
6
-
7
- static void myprint(char* s) {
8
- printf("%s\n", s);
9
- }
10
-
11
-
12
- */
13
3
  import "C"
14
-
15
4
  import (
5
+ context "context"
16
6
  "flag"
17
- "github.com/golang/protobuf/proto"
18
- "qnetwork.net/fbcrawl/fbcolly"
7
+ "github.com/google/logger"
8
+ lru "github.com/hashicorp/golang-lru"
9
+ "google.golang.org/grpc"
10
+ "log"
11
+ "net"
12
+ "os"
13
+ "qnetwork.net/fbcrawl/fbcrawl"
14
+ "qnetwork.net/fbcrawl/fbcrawl/pb"
19
15
  "unsafe"
20
16
  )
21
17
 
@@ -27,92 +23,93 @@ var password = flag.String("password", "change_me", "facebook password")
27
23
  var otp = flag.String("otp", "123456", "facebook otp")
28
24
  var groupId = flag.String("groupId", "334294967318328", "facebook group id, default is 334294967318328")
29
25
 
30
- var allInstances = map[uintptr]*fbcolly.Fbcolly{}
26
+ var allInstances, _ = lru.New(20)
27
+
28
+ func getColly(pointer *pb.Pointer) *fbcolly.Fbcolly {
29
+ c, ok := allInstances.Get(pointer.Address)
30
+ if ok {
31
+ return c.(*fbcolly.Fbcolly)
32
+ }
33
+ return nil
34
+ }
35
+
36
+ // server is used to implement helloworld.GreeterServer.
37
+ type server struct {
38
+ pb.GrpcServer
39
+ }
31
40
 
32
- //export Init
33
- func Init() uintptr {
41
+ func (s server) Init(ctx context.Context, empty *pb.Empty) (*pb.Pointer, error) {
34
42
  instance := fbcolly.New()
35
43
  ptr := (uintptr)(unsafe.Pointer(instance))
36
- allInstances[ptr] = instance
37
- return ptr
44
+ allInstances.Add(int64(ptr), instance)
45
+ return &pb.Pointer{Address: int64(ptr)}, nil
38
46
  }
39
47
 
40
- //export FreeColly
41
- func FreeColly(pointer unsafe.Pointer) {
42
- delete(allInstances, uintptr(pointer))
48
+ func (s server) FreeColly(ctx context.Context, pointer *pb.Pointer) (*pb.Empty, error) {
49
+ logger.Info("FreeColly")
50
+ allInstances.Remove(pointer.Address)
51
+ return &pb.Empty{}, nil
43
52
  }
44
53
 
45
- //export Login
46
- func Login(pointer unsafe.Pointer, email *C.char, password *C.char) *C.char {
47
- p := (*fbcolly.Fbcolly)(pointer)
48
- cookies, err := p.Login(C.GoString(email), C.GoString(password), "")
54
+ func (s server) Login(ctx context.Context, request *pb.LoginRequest) (*pb.LoginResponse, error) {
55
+ p := getColly(request.Pointer)
56
+
57
+ cookies, err := p.Login(request.Email, request.Password, request.TotpSecret)
49
58
  if err == nil {
50
- return C.CString(cookies)
59
+ return &pb.LoginResponse{Cookies: cookies}, err
51
60
  }
52
- return nil
61
+ return nil, err
53
62
  }
54
63
 
55
- //export LoginWithCookies
56
- func LoginWithCookies(pointer unsafe.Pointer, cookies *C.char) {
57
- p := (*fbcolly.Fbcolly)(pointer)
58
- p.LoginWithCookies(C.GoString(cookies))
64
+ func (s server) LoginWithCookies(ctx context.Context, request *pb.LoginWithCookiesRequest) (*pb.Empty, error) {
65
+ p := getColly(request.Pointer)
66
+ err := p.LoginWithCookies(request.Cookies)
67
+ return &pb.Empty{}, err
59
68
  }
60
69
 
61
- //export FetchGroupInfo
62
- func FetchGroupInfo(pointer unsafe.Pointer, groupIdOrUsername *C.char) unsafe.Pointer {
63
- p := (*fbcolly.Fbcolly)(pointer)
64
- _, groupInfo := p.FetchGroupInfo(C.GoString(groupIdOrUsername))
65
- marshaled, _ := proto.Marshal(groupInfo)
66
- return C.CBytes(append(marshaled, 0))
70
+ func (s server) FetchGroupInfo(ctx context.Context, request *pb.FetchGroupInfoRequest) (*pb.FacebookGroup, error) {
71
+ p := getColly(request.Pointer)
72
+ err, groupInfo := p.FetchGroupInfo(request.GroupUsername)
73
+ return groupInfo, err
67
74
  }
68
75
 
69
- //export FetchGroupFeed
70
- func FetchGroupFeed(pointer unsafe.Pointer, groupId int64) unsafe.Pointer {
71
- p := (*fbcolly.Fbcolly)(pointer)
72
- _, postsList := p.FetchGroupFeed(groupId)
73
- marshaledPostsList, _ := proto.Marshal(postsList)
74
- return C.CBytes(append(marshaledPostsList, 0))
76
+ func (s server) FetchGroupFeed(ctx context.Context, request *pb.FetchGroupFeedRequest) (*pb.FacebookPostList, error) {
77
+ p := getColly(request.Pointer)
78
+ err, postsList := p.FetchGroupFeed(request.GroupId, request.NextCursor)
79
+ return postsList, err
75
80
  }
76
81
 
77
- //export FetchPost
78
- func FetchPost(pointer unsafe.Pointer, groupId int64, postId int64) unsafe.Pointer {
79
- p := (*fbcolly.Fbcolly)(pointer)
80
- _, post := p.FetchPost(groupId, postId)
81
- marshaledPost, _ := proto.Marshal(post)
82
- return C.CBytes(append(marshaledPost, 0))
82
+ func (s server) FetchPost(ctx context.Context, request *pb.FetchPostRequest) (*pb.FacebookPost, error) {
83
+ p := getColly(request.Pointer)
84
+ err, post := p.FetchPost(request.GroupId, request.PostId, request.CommentNextCursor)
85
+ return post, err
83
86
  }
84
87
 
85
- //export FetchContentImages
86
- func FetchContentImages(pointer unsafe.Pointer, postId int64) unsafe.Pointer {
87
- p := (*fbcolly.Fbcolly)(pointer)
88
- _, imageList := p.FetchContentImages(postId)
89
- marshaled, _ := proto.Marshal(imageList)
90
- return C.CBytes(append(marshaled, 0))
88
+ func (s server) FetchContentImages(ctx context.Context, request *pb.FetchContentImagesRequest) (*pb.FacebookImageList, error) {
89
+ p := getColly(request.Pointer)
90
+ err, imageList := p.FetchContentImages(request.PostId, request.NextCursor)
91
+ return imageList, err
91
92
  }
92
93
 
93
- //export FetchImageUrl
94
- func FetchImageUrl(pointer unsafe.Pointer, imageId int64) unsafe.Pointer {
95
- p := (*fbcolly.Fbcolly)(pointer)
96
- _, image := p.FetchImageUrl(imageId)
97
- marshaled, _ := proto.Marshal(image)
98
- return C.CBytes(append(marshaled, 0))
94
+ func (s server) FetchImageUrl(ctx context.Context, request *pb.FetchImageUrlRequest) (*pb.FacebookImage, error) {
95
+ p := getColly(request.Pointer)
96
+ err, image := p.FetchImageUrl(request.ImageId)
97
+ return image, err
99
98
  }
100
99
 
101
100
  func main() {
102
- //r := regexp.MustCompile("/([\\d\\w.]+)").FindStringSubmatch()[1]
103
- //print(r.FindStringSubmatch("/liem.phamthanh.161?refid=18&__tn__=R")[1])
104
- //flag.Parse()
105
- //
106
- ////post := fbcrawl.FacebookPost{}
107
- ////bPost, err := proto.Marshal(&post)
108
- //
109
- //lf, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660)
110
- //if err != nil {
111
- // logger.Fatalf("Failed to open log file: %v", err)
112
- //}
113
- //defer lf.Close()
114
- //defer logger.Init("fb-colly", *verbose, false, lf).Close()
115
- //f := fbcolly.New()
116
- //err = f.Login(*email, *password, *otp)
117
- //f.FetchGroupFeed(*groupId)
101
+ port := os.Getenv("PORT")
102
+ if len(port) == 0 {
103
+ port = "50051"
104
+ }
105
+ lis, err := net.Listen("tcp", ":"+port)
106
+ logger.Info("Port listened at", port)
107
+ if err != nil {
108
+ log.Fatalf("failed to listen: %v", err)
109
+ }
110
+ s := grpc.NewServer()
111
+ pb.RegisterGrpcServer(s, &server{})
112
+ if err := s.Serve(lis); err != nil {
113
+ log.Fatalf("failed to serve: %v", err)
114
+ }
118
115
  }
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fbcrawl-colly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Duy Le
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-15 00:00:00.000000000 Z
11
+ date: 2020-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: ffi
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: google-protobuf
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -39,13 +25,13 @@ dependencies:
39
25
  - !ruby/object:Gem::Version
40
26
  version: '0'
41
27
  - !ruby/object:Gem::Dependency
42
- name: rake-compiler
28
+ name: grpc
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
31
  - - ">="
46
32
  - !ruby/object:Gem::Version
47
33
  version: '0'
48
- type: :development
34
+ type: :runtime
49
35
  prerelease: false
50
36
  version_requirements: !ruby/object:Gem::Requirement
51
37
  requirements:
@@ -56,12 +42,12 @@ description: Crawl mbasic.facebook.com using GO Colly
56
42
  email:
57
43
  - duyleekun@gmail.com
58
44
  executables: []
59
- extensions:
60
- - ext/fbcrawl_colly/extconf.rb
45
+ extensions: []
61
46
  extra_rdoc_files: []
62
47
  files:
63
48
  - ".gitignore"
64
49
  - CODE_OF_CONDUCT.md
50
+ - Dockerfile
65
51
  - Gemfile
66
52
  - Gemfile.lock
67
53
  - LICENSE.txt
@@ -69,18 +55,19 @@ files:
69
55
  - Rakefile
70
56
  - bin/console
71
57
  - bin/setup
72
- - ext/fbcrawl_colly/.gitignore
73
- - ext/fbcrawl_colly/Makefile
74
- - ext/fbcrawl_colly/extconf.rb
75
- - fbcolly/fbcolly.go
76
58
  - fbcrawl-colly.gemspec
77
59
  - fbcrawl.proto
60
+ - fbcrawl/fbcolly.go
61
+ - fbcrawl/pb/fbcrawl.pb.go
62
+ - fbcrawl/pb/fbcrawl_grpc.pb.go
78
63
  - go.mod
79
64
  - go.sum
80
65
  - lib/fbcrawl-colly.rb
81
- - lib/fbcrawl_colly/colly.rb
82
- - lib/fbcrawl_colly/ffi.rb
66
+ - lib/fbcrawl_colly.rb
67
+ - lib/fbcrawl_colly/client.rb
83
68
  - lib/fbcrawl_colly/version.rb
69
+ - lib/pb/fbcrawl_pb.rb
70
+ - lib/pb/fbcrawl_services_pb.rb
84
71
  - main.go
85
72
  homepage: http://github.com/duyleekun/fbcrawl-colly
86
73
  licenses:
@@ -93,6 +80,7 @@ post_install_message:
93
80
  rdoc_options: []
94
81
  require_paths:
95
82
  - lib
83
+ - lib/pb
96
84
  required_ruby_version: !ruby/object:Gem::Requirement
97
85
  requirements:
98
86
  - - ">="