stream-ruby 2.11.0 → 4.0.1
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.
- checksums.yaml +5 -5
- data/README.md +46 -49
- data/lib/stream/activities.rb +110 -46
- data/lib/stream/batch.rb +20 -23
- data/lib/stream/client.rb +61 -32
- data/lib/stream/collections.rb +34 -9
- data/lib/stream/errors.rb +2 -0
- data/lib/stream/feed.rb +44 -42
- data/lib/stream/reactions.rb +80 -0
- data/lib/stream/signer.rb +4 -19
- data/lib/stream/url.rb +4 -2
- data/lib/stream/users.rb +45 -0
- data/lib/stream/version.rb +1 -1
- metadata +19 -46
- data/lib/stream/signedrequest.rb +0 -43
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 1e0b02058c12522318ebd603cf9df70336a10c24676e76ba58c52f7cb76557f3
|
|
4
|
+
data.tar.gz: 52a4c6385266cfd6db60ea487872f563af1b6f5efd9cc6470f01ee654efb8a75
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5d96047a3327bff2d71c72e9e19b9c0ee76caaa6bbd55342b6758c81c1df1059069ffd2e0f01ac04282f02231aebc12f5d217376a567446ae542f16dc006c73c
|
|
7
|
+
data.tar.gz: c94076dddbe29e81f7635222dcfc0b001bc9d289e10f1fc244ce1f3d17bdcf78a5805d384c5f363163af9e8ac743b22152a9171cd9ffe433f21cace83e56d4e5
|
data/README.md
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
stream-ruby
|
|
2
|
-
===========
|
|
1
|
+
# stream-ruby
|
|
3
2
|
|
|
4
3
|
[](https://travis-ci.org/GetStream/stream-ruby) [](http://badge.fury.io/rb/stream-ruby)
|
|
5
4
|
|
|
@@ -11,19 +10,14 @@ You can sign up for a Stream account at https://getstream.io/get_started.
|
|
|
11
10
|
|
|
12
11
|
#### Ruby version requirements and support
|
|
13
12
|
|
|
14
|
-
This API Client project requires Ruby 2.
|
|
15
|
-
- 2.2.8
|
|
16
|
-
- 2.3.1
|
|
17
|
-
- 2.3.5
|
|
18
|
-
- 2.4.2
|
|
19
|
-
- 2.5.1
|
|
13
|
+
This API Client project requires Ruby 2.5.x at a minimum.
|
|
20
14
|
|
|
21
15
|
See the [Travis configuration](.travis.yml) for details of how it is built and tested.
|
|
22
16
|
|
|
23
17
|
### Installation
|
|
24
18
|
|
|
25
19
|
```bash
|
|
26
|
-
gem install
|
|
20
|
+
gem install 'stream-ruby'
|
|
27
21
|
```
|
|
28
22
|
|
|
29
23
|
### Full documentation
|
|
@@ -35,30 +29,43 @@ Documentation for this Ruby client are available at the [Stream website](https:/
|
|
|
35
29
|
```ruby
|
|
36
30
|
# Instantiate a new client to connect to us east API endpoint
|
|
37
31
|
require 'stream'
|
|
38
|
-
client = Stream::Client.new('YOUR_API_KEY', 'API_KEY_SECRET', 'APP_ID', :
|
|
32
|
+
client = Stream::Client.new('YOUR_API_KEY', 'API_KEY_SECRET', 'APP_ID', location: 'us-east')
|
|
33
|
+
|
|
39
34
|
# Find your API keys here https://getstream.io/dashboard/
|
|
40
35
|
|
|
41
36
|
# Instantiate a feed object
|
|
42
37
|
user_feed_1 = client.feed('user', '1')
|
|
43
38
|
|
|
44
39
|
# Get activities from 5 to 10 (slow pagination)
|
|
45
|
-
result = user_feed_1.get(:
|
|
40
|
+
result = user_feed_1.get(limit: 5, offset: 5)
|
|
46
41
|
# (Recommended & faster) Filter on an id less than the given UUID
|
|
47
|
-
result =
|
|
42
|
+
result =
|
|
43
|
+
user_feed_1.get(limit: 5, id_lt: 'e561de8f-00f1-11e4-b400-0cc47a024be0')
|
|
48
44
|
|
|
49
45
|
# Create a new activity
|
|
50
|
-
activity_data = {:
|
|
46
|
+
activity_data = { actor: 1, verb: 'tweet', object: 1, foreign_id: 'tweet:1' }
|
|
51
47
|
activity_response = user_feed_1.add_activity(activity_data)
|
|
52
48
|
# Create a bit more complex activity
|
|
53
|
-
activity_data = {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
activity_data = {
|
|
50
|
+
actor: 1,
|
|
51
|
+
verb: 'tweet',
|
|
52
|
+
object: 1,
|
|
53
|
+
foreign_id: 'tweet:1',
|
|
54
|
+
course: { name: 'Golden Gate park', distance: 10 },
|
|
55
|
+
participants: %w[Thierry Tommaso],
|
|
56
|
+
started_at: DateTime.now
|
|
57
57
|
}
|
|
58
58
|
activity_response = user_feed_1.add_activity(activity_data)
|
|
59
59
|
|
|
60
60
|
# Update an existing activity (requires both :foreign_id and :time fields)
|
|
61
|
-
activity_data = {
|
|
61
|
+
activity_data = {
|
|
62
|
+
actor: 1,
|
|
63
|
+
verb: 'tweet',
|
|
64
|
+
object: 1,
|
|
65
|
+
foreign_id: 'tweet:1',
|
|
66
|
+
popularity: 100,
|
|
67
|
+
time: '2016-05-13T16:12:30'
|
|
68
|
+
}
|
|
62
69
|
client.update_activity(activity_data)
|
|
63
70
|
|
|
64
71
|
# Update activities
|
|
@@ -68,7 +75,7 @@ client.update_activities([activity_data])
|
|
|
68
75
|
user_feed_1.remove_activity('e561de8f-00f1-11e4-b400-0cc47a024be0')
|
|
69
76
|
|
|
70
77
|
# Remove activities by their foreign_id
|
|
71
|
-
user_feed_1.remove_activity('tweet:1', foreign_id
|
|
78
|
+
user_feed_1.remove_activity('tweet:1', foreign_id: true)
|
|
72
79
|
|
|
73
80
|
# Follow another feed
|
|
74
81
|
user_feed_1.follow('flat', '42')
|
|
@@ -78,60 +85,45 @@ user_feed_1.unfollow('flat', '42')
|
|
|
78
85
|
|
|
79
86
|
# Batch adding activities
|
|
80
87
|
activities = [
|
|
81
|
-
|
|
82
|
-
|
|
88
|
+
[actor: '1', verb: 'tweet', object: '1'],
|
|
89
|
+
[actor: '2', verb: 'like', object: '3']
|
|
83
90
|
]
|
|
84
91
|
user_feed_1.add_activities(activities)
|
|
85
92
|
|
|
86
93
|
# Batch following many feeds (requires ruby 2.1 or later)
|
|
87
94
|
follows = [
|
|
88
|
-
{:
|
|
89
|
-
{:
|
|
90
|
-
{:
|
|
95
|
+
{ source: 'flat:1', target: 'user:1' },
|
|
96
|
+
{ source: 'flat:1', target: 'user:2' },
|
|
97
|
+
{ source: 'flat:1', target: 'user:3' }
|
|
91
98
|
]
|
|
92
99
|
client.follow_many(follows)
|
|
93
100
|
|
|
94
101
|
# Add an activity and push it to other feeds too using the `to` field
|
|
95
|
-
data = [
|
|
96
|
-
:actor_id => '1',
|
|
97
|
-
:verb => 'like',
|
|
98
|
-
:object_id => '3',
|
|
99
|
-
:to => %w(user:44 user:45)
|
|
100
|
-
]
|
|
102
|
+
data = [actor_id: '1', verb: 'like', object_id: '3', to: %w[user:44 user:45]]
|
|
101
103
|
user_feed_1.add_activity(data)
|
|
102
104
|
|
|
103
|
-
|
|
104
105
|
# Updating parts of an activity
|
|
105
106
|
set = {
|
|
106
|
-
'product.price': 19.99,
|
|
107
|
-
'shares': {
|
|
108
|
-
'facebook': '...',
|
|
109
|
-
'twitter': '...'
|
|
110
|
-
},
|
|
107
|
+
'product.price': 19.99, 'shares': { 'facebook': '...', 'twitter': '...' }
|
|
111
108
|
}
|
|
112
|
-
unset = [
|
|
113
|
-
'daily_likes',
|
|
114
|
-
'popularity'
|
|
115
|
-
]
|
|
109
|
+
unset = %w[daily_likes popularity]
|
|
116
110
|
# ...by ID
|
|
117
111
|
client.activity_partial_update(
|
|
118
|
-
id: '54a60c1e-4ee3-494b-a1e3-50c06acb5ed4',
|
|
119
|
-
set: set,
|
|
120
|
-
unset: unset,
|
|
112
|
+
id: '54a60c1e-4ee3-494b-a1e3-50c06acb5ed4', set: set, unset: unset
|
|
121
113
|
)
|
|
122
114
|
# ...or by combination of foreign ID and time
|
|
123
115
|
client.activity_partial_update(
|
|
124
116
|
foreign_id: 'product:123',
|
|
125
117
|
time: '2016-11-10T13:20:00.000000',
|
|
126
118
|
set: set,
|
|
127
|
-
unset: unset
|
|
119
|
+
unset: unset
|
|
128
120
|
)
|
|
129
121
|
|
|
130
122
|
# Generating tokens for client side usage
|
|
131
123
|
token = user_feed_1.readonly_token
|
|
132
124
|
|
|
133
125
|
# Javascript client side feed initialization
|
|
134
|
-
user1 = client.feed('user', '1', '{{ token }}')
|
|
126
|
+
user1 = client.feed('user', '1', '{{ token }}')
|
|
135
127
|
|
|
136
128
|
# Retrieve first 10 followers of a feed
|
|
137
129
|
user_feed_1.followers(0, 10)
|
|
@@ -146,16 +138,21 @@ user_feed_1.following(10)
|
|
|
146
138
|
user_feed_1.following(10, 10)
|
|
147
139
|
|
|
148
140
|
# Check if user_feed_1 follows specific feeds
|
|
149
|
-
user_feed_1.following(0, 2, filter=[
|
|
141
|
+
user_feed_1.following(0, 2, filter = %w[user:42 user:43])
|
|
150
142
|
|
|
151
143
|
# Add one activity to many feeds in one request
|
|
152
|
-
feeds = %w
|
|
153
|
-
activity = {
|
|
144
|
+
feeds = %w[flat:1 flat:2 flat:3 flat:4]
|
|
145
|
+
activity = {
|
|
146
|
+
actor: 'User:2', verb: 'pin', object: 'Place:42', target: 'Board:1'
|
|
147
|
+
}
|
|
154
148
|
client.add_to_many(activity, feeds)
|
|
149
|
+
|
|
150
|
+
# Retrive open graph information
|
|
151
|
+
client.og('https://google.com')
|
|
155
152
|
```
|
|
156
153
|
|
|
157
154
|
### Copyright and License Information
|
|
158
155
|
|
|
159
|
-
Copyright (c) 2014-
|
|
156
|
+
Copyright (c) 2014-2020 Stream.io Inc, and individual contributors. All rights reserved.
|
|
160
157
|
|
|
161
158
|
See the file "LICENSE" for information on the history of this software, terms & conditions for usage, and a DISCLAIMER OF ALL WARRANTIES.
|
data/lib/stream/activities.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
module Stream
|
|
2
2
|
module Activities
|
|
3
|
-
|
|
4
3
|
#
|
|
5
4
|
# Get activities directly, via ID or Foreign ID + timestamp
|
|
6
5
|
#
|
|
@@ -8,34 +7,33 @@ module Stream
|
|
|
8
7
|
#
|
|
9
8
|
# @return the found activities, if any.
|
|
10
9
|
#
|
|
11
|
-
# @example
|
|
12
|
-
#
|
|
10
|
+
# @example Retrieve by activity IDs
|
|
11
|
+
# @client.get_activities(
|
|
12
|
+
# ids: [
|
|
13
|
+
# '4b39fda2-d6e2-42c9-9abf-5301ef071b12',
|
|
14
|
+
# '89b910d3-1ef5-44f8-914e-e7735d79e817'
|
|
15
|
+
# ]
|
|
16
|
+
# )
|
|
13
17
|
#
|
|
14
|
-
# @
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
# @client.get_activities(
|
|
22
|
-
# foreign_id_times: [
|
|
23
|
-
# { foreign_id: 'post:1000', time: '2016-11-10T13:20:00.000000' },
|
|
24
|
-
# { foreign_id: 'like:2000', time: '2018-01-07T09:15:59.123456' }
|
|
25
|
-
# ]
|
|
26
|
-
# )
|
|
18
|
+
# @example Retrieve by Foreign IDs + timestamps
|
|
19
|
+
# @client.get_activities(
|
|
20
|
+
# foreign_id_times: [
|
|
21
|
+
# { foreign_id: 'post:1000', time: '2016-11-10T13:20:00.000000' },
|
|
22
|
+
# { foreign_id: 'like:2000', time: '2018-01-07T09:15:59.123456' }
|
|
23
|
+
# ]
|
|
24
|
+
# )
|
|
27
25
|
#
|
|
28
26
|
def get_activities(params = {})
|
|
29
27
|
if params[:foreign_id_times]
|
|
30
28
|
foreign_ids = []
|
|
31
29
|
timestamps = []
|
|
32
|
-
params[:foreign_id_times].each
|
|
30
|
+
params[:foreign_id_times].each do |e|
|
|
33
31
|
foreign_ids << e[:foreign_id]
|
|
34
32
|
timestamps << e[:time]
|
|
35
|
-
|
|
33
|
+
end
|
|
36
34
|
params = {
|
|
37
35
|
foreign_ids: foreign_ids,
|
|
38
|
-
timestamps: timestamps
|
|
36
|
+
timestamps: timestamps
|
|
39
37
|
}
|
|
40
38
|
end
|
|
41
39
|
signature = Stream::Signer.create_jwt_token('activities', '*', @api_secret, '*')
|
|
@@ -43,42 +41,108 @@ module Stream
|
|
|
43
41
|
end
|
|
44
42
|
|
|
45
43
|
#
|
|
46
|
-
# Partial update activity, via
|
|
44
|
+
# Partial update activity, via activity ID or Foreign ID + timestamp
|
|
47
45
|
#
|
|
48
46
|
# @param [Hash<:id, :foreign_id, :time, :set, :unset>] data the request params (id and foreign_id+timestamp mutually exclusive)
|
|
49
47
|
#
|
|
50
48
|
# @return the updated activity.
|
|
51
49
|
#
|
|
52
|
-
# @example
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
#
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
#
|
|
74
|
-
#
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
#
|
|
50
|
+
# @example Identify using activity ID
|
|
51
|
+
# @client.activity_partial_update(
|
|
52
|
+
# id: "4b39fda2-d6e2-42c9-9abf-5301ef071b12",
|
|
53
|
+
# set: {
|
|
54
|
+
# "product.price.eur": 12.99,
|
|
55
|
+
# "colors": {
|
|
56
|
+
# "blue": "#0000ff",
|
|
57
|
+
# "green": "#00ff00",
|
|
58
|
+
# }
|
|
59
|
+
# },
|
|
60
|
+
# unset: [ "popularity", "size.xl" ]
|
|
61
|
+
# )
|
|
62
|
+
#
|
|
63
|
+
# @example Identify using Foreign ID + timestamp
|
|
64
|
+
# @client.activity_partial_update(
|
|
65
|
+
# foreign_id: 'product:123',
|
|
66
|
+
# time: '2016-11-10T13:20:00.000000',
|
|
67
|
+
# set: {
|
|
68
|
+
# "product.price.eur": 12.99,
|
|
69
|
+
# "colors": {
|
|
70
|
+
# "blue": "#0000ff",
|
|
71
|
+
# "green": "#00ff00",
|
|
72
|
+
# }
|
|
73
|
+
# },
|
|
74
|
+
# unset: [ "popularity", "size.xl" ]
|
|
75
|
+
# )
|
|
76
|
+
#
|
|
78
77
|
def activity_partial_update(data = {})
|
|
79
78
|
signature = Stream::Signer.create_jwt_token('activities', '*', @api_secret, '*')
|
|
80
79
|
make_request(:post, '/activity/', signature, {}, data)
|
|
81
80
|
end
|
|
82
81
|
|
|
82
|
+
#
|
|
83
|
+
# Batch partial activity update
|
|
84
|
+
#
|
|
85
|
+
# @param [Array< Hash<:id, :foreign_id, :time, :set, :unset> >] changes the list of changes to be applied
|
|
86
|
+
#
|
|
87
|
+
# @return the updated activities
|
|
88
|
+
#
|
|
89
|
+
# @example Identify using activity IDs
|
|
90
|
+
# @client.batch_activity_partial_update([
|
|
91
|
+
# {
|
|
92
|
+
# id: "4b39fda2-d6e2-42c9-9abf-5301ef071b12",
|
|
93
|
+
# set: {
|
|
94
|
+
# "product.price.eur": 12.99,
|
|
95
|
+
# "colors": {
|
|
96
|
+
# "blue": "#0000ff",
|
|
97
|
+
# "green": "#00ff00",
|
|
98
|
+
# }
|
|
99
|
+
# },
|
|
100
|
+
# unset: [ "popularity", "size.x2" ]
|
|
101
|
+
# },
|
|
102
|
+
# {
|
|
103
|
+
# id: "8d2dcad8-1e34-11e9-8b10-9cb6d0925edd",
|
|
104
|
+
# set: {
|
|
105
|
+
# "product.price.eur": 17.99,
|
|
106
|
+
# "colors": {
|
|
107
|
+
# "red": "#ff0000",
|
|
108
|
+
# "green": "#00ff00",
|
|
109
|
+
# }
|
|
110
|
+
# },
|
|
111
|
+
# unset: [ "rating" ]
|
|
112
|
+
# }
|
|
113
|
+
# ])
|
|
114
|
+
#
|
|
115
|
+
# @example Identify using Foreign IDs + timestamps
|
|
116
|
+
# @client.batch_activity_partial_update([
|
|
117
|
+
# {
|
|
118
|
+
# foreign_id: "product:123",
|
|
119
|
+
# time: '2016-11-10T13:20:00.000000',
|
|
120
|
+
# set: {
|
|
121
|
+
# "product.price.eur": 22.99,
|
|
122
|
+
# "colors": {
|
|
123
|
+
# "blue": "#0000ff",
|
|
124
|
+
# "green": "#00ff00",
|
|
125
|
+
# }
|
|
126
|
+
# },
|
|
127
|
+
# unset: [ "popularity", "size.x2" ]
|
|
128
|
+
# },
|
|
129
|
+
# {
|
|
130
|
+
# foreign_id: "product:1234",
|
|
131
|
+
# time: '2017-11-10T13:20:00.000000',
|
|
132
|
+
# set: {
|
|
133
|
+
# "product.price.eur": 37.99,
|
|
134
|
+
# "colors": {
|
|
135
|
+
# "black": "#000000",
|
|
136
|
+
# "white": "#ffffff",
|
|
137
|
+
# }
|
|
138
|
+
# },
|
|
139
|
+
# unset: [ "rating" ]
|
|
140
|
+
# }
|
|
141
|
+
# ])
|
|
142
|
+
#
|
|
143
|
+
def batch_activity_partial_update(changes = [])
|
|
144
|
+
signature = Stream::Signer.create_jwt_token('activities', '*', @api_secret, '*')
|
|
145
|
+
make_request(:post, '/activity/', signature, {}, { changes: changes })
|
|
146
|
+
end
|
|
83
147
|
end
|
|
84
148
|
end
|
data/lib/stream/batch.rb
CHANGED
|
@@ -8,20 +8,17 @@ module Stream
|
|
|
8
8
|
# @return [nil]
|
|
9
9
|
#
|
|
10
10
|
# @example
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# ]
|
|
17
|
-
# @client.follow_many(follows)
|
|
11
|
+
# follows = [
|
|
12
|
+
# {:source => 'flat:1', :target => 'user:1'},
|
|
13
|
+
# {:source => 'flat:1', :target => 'user:3'}
|
|
14
|
+
# ]
|
|
15
|
+
# @client.follow_many(follows)
|
|
18
16
|
#
|
|
19
17
|
def follow_many(follows, activity_copy_limit = nil)
|
|
20
18
|
query_params = {}
|
|
21
|
-
unless activity_copy_limit.nil?
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
make_signed_request(:post, '/follow_many/', query_params, follows)
|
|
19
|
+
query_params['activity_copy_limit'] = activity_copy_limit unless activity_copy_limit.nil?
|
|
20
|
+
signature = Stream::Signer.create_jwt_token('follower', '*', @api_secret, '*')
|
|
21
|
+
make_request(:post, '/follow_many/', signature, query_params, follows)
|
|
25
22
|
end
|
|
26
23
|
|
|
27
24
|
#
|
|
@@ -32,18 +29,17 @@ module Stream
|
|
|
32
29
|
# return [nil]
|
|
33
30
|
#
|
|
34
31
|
# @example
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
# ]
|
|
41
|
-
# @client.unfollow_many(unfollows)
|
|
32
|
+
# unfollows = [
|
|
33
|
+
# {source: 'user:1', target: 'timeline:1'},
|
|
34
|
+
# {source: 'user:2', target: 'timeline:2', keep_history: false}
|
|
35
|
+
# ]
|
|
36
|
+
# @client.unfollow_many(unfollows)
|
|
42
37
|
#
|
|
43
38
|
def unfollow_many(unfollows)
|
|
44
|
-
|
|
39
|
+
signature = Stream::Signer.create_jwt_token('follower', '*', @api_secret, '*')
|
|
40
|
+
make_request(:post, '/unfollow_many/', signature, {}, unfollows)
|
|
45
41
|
end
|
|
46
|
-
|
|
42
|
+
|
|
47
43
|
#
|
|
48
44
|
# Adds an activity to many feeds in one single request
|
|
49
45
|
#
|
|
@@ -54,10 +50,11 @@ module Stream
|
|
|
54
50
|
#
|
|
55
51
|
def add_to_many(activity_data, feeds)
|
|
56
52
|
data = {
|
|
57
|
-
:
|
|
58
|
-
:
|
|
53
|
+
feeds: feeds,
|
|
54
|
+
activity: activity_data
|
|
59
55
|
}
|
|
60
|
-
|
|
56
|
+
signature = Stream::Signer.create_jwt_token('feed', '*', @api_secret, '*')
|
|
57
|
+
make_request(:post, '/feed/add_to_many/', signature, {}, data)
|
|
61
58
|
end
|
|
62
59
|
end
|
|
63
60
|
end
|
data/lib/stream/client.rb
CHANGED
|
@@ -5,8 +5,8 @@ require 'stream/signer'
|
|
|
5
5
|
require 'stream/url'
|
|
6
6
|
|
|
7
7
|
module Stream
|
|
8
|
-
STREAM_URL_COM_RE = %r{https
|
|
9
|
-
STREAM_URL_IO_RE = %r{https
|
|
8
|
+
STREAM_URL_COM_RE = %r{https://(?<key>\w+):(?<secret>\w+)@((api\.)|((?<location>[-\w]+)\.))?(?<api_hostname>stream-io-api\.com)/[\w=-?%&]+app_id=(?<app_id>\d+)}i.freeze
|
|
9
|
+
STREAM_URL_IO_RE = %r{https://(?<key>\w+):(?<secret>\w+)@((api\.)|((?<location>[-\w]+)\.))?(?<api_hostname>getstream\.io)/[\w=-?%&]+app_id=(?<app_id>\d+)}i.freeze
|
|
10
10
|
|
|
11
11
|
class Client
|
|
12
12
|
attr_reader :api_key
|
|
@@ -14,17 +14,15 @@ module Stream
|
|
|
14
14
|
attr_reader :app_id
|
|
15
15
|
attr_reader :client_options
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
require 'stream/batch'
|
|
18
|
+
require 'stream/personalization'
|
|
19
|
+
require 'stream/collections'
|
|
20
|
+
require 'stream/activities'
|
|
21
|
+
require 'stream/reactions'
|
|
22
|
+
require 'stream/users'
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
include Stream::Activities
|
|
27
|
-
end
|
|
24
|
+
include Stream::Batch
|
|
25
|
+
include Stream::Activities
|
|
28
26
|
|
|
29
27
|
#
|
|
30
28
|
# initializes a Stream API Client
|
|
@@ -46,7 +44,7 @@ module Stream
|
|
|
46
44
|
re = Stream::STREAM_URL_IO_RE
|
|
47
45
|
end
|
|
48
46
|
raise ArgumentError, 'empty api_key parameter and missing or invalid STREAM_URL env variable' unless re
|
|
49
|
-
|
|
47
|
+
|
|
50
48
|
matches = re.match(ENV['STREAM_URL'])
|
|
51
49
|
api_key = matches['key']
|
|
52
50
|
api_secret = matches['secret']
|
|
@@ -77,12 +75,31 @@ module Stream
|
|
|
77
75
|
# @return [Stream::Feed]
|
|
78
76
|
#
|
|
79
77
|
def feed(feed_slug, user_id)
|
|
80
|
-
|
|
81
|
-
Stream::Feed.new(self, feed_slug, user_id, token)
|
|
78
|
+
Stream::Feed.new(self, feed_slug, user_id)
|
|
82
79
|
end
|
|
83
80
|
|
|
81
|
+
# Creates a user token
|
|
82
|
+
#
|
|
83
|
+
# @deprecated Use Client#create_user_token instead
|
|
84
|
+
#
|
|
85
|
+
# @param [string] user_id the user_if of this token (e.g. User42)
|
|
86
|
+
# @param [hash] extra_data additional token data
|
|
87
|
+
#
|
|
88
|
+
# @return [string]
|
|
89
|
+
#
|
|
84
90
|
def create_user_session_token(user_id, extra_data = {})
|
|
85
|
-
|
|
91
|
+
create_user_token(user_id, extra_data)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Creates a user token
|
|
95
|
+
#
|
|
96
|
+
# @param [string] user_id the user_if of this token (e.g. User42)
|
|
97
|
+
# @param [hash] extra_data additional token data
|
|
98
|
+
#
|
|
99
|
+
# @return [string]
|
|
100
|
+
#
|
|
101
|
+
def create_user_token(user_id, extra_data = {})
|
|
102
|
+
Stream::Signer.create_user_token(user_id, extra_data, api_secret)
|
|
86
103
|
end
|
|
87
104
|
|
|
88
105
|
def personalization
|
|
@@ -93,6 +110,14 @@ module Stream
|
|
|
93
110
|
CollectionsClient.new(api_key, api_secret, app_id, client_options)
|
|
94
111
|
end
|
|
95
112
|
|
|
113
|
+
def reactions
|
|
114
|
+
ReactionsClient.new(api_key, api_secret, app_id, client_options)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def users
|
|
118
|
+
UsersClient.new(api_key, api_secret, app_id, client_options)
|
|
119
|
+
end
|
|
120
|
+
|
|
96
121
|
def update_activity(activity)
|
|
97
122
|
update_activities([activity])
|
|
98
123
|
end
|
|
@@ -102,22 +127,26 @@ module Stream
|
|
|
102
127
|
make_request(:post, '/activities/', auth_token, {}, 'activities' => activities)
|
|
103
128
|
end
|
|
104
129
|
|
|
130
|
+
def og(uri)
|
|
131
|
+
auth_token = Stream::Signer.create_jwt_token('*', '*', @api_secret, '*')
|
|
132
|
+
make_request(:get, '/og', auth_token, { url: uri })
|
|
133
|
+
end
|
|
134
|
+
|
|
105
135
|
def get_default_params
|
|
106
|
-
{:
|
|
136
|
+
{ api_key: @api_key }
|
|
107
137
|
end
|
|
108
138
|
|
|
109
139
|
def get_http_client
|
|
110
|
-
@
|
|
140
|
+
@get_http_client ||= StreamHTTPClient.new(url_generator)
|
|
111
141
|
end
|
|
112
142
|
|
|
113
143
|
def make_query_params(params)
|
|
114
|
-
Hash[get_default_params.merge(params).sort_by {|k,
|
|
144
|
+
Hash[get_default_params.merge(params).sort_by { |k, _v| k.to_s }]
|
|
115
145
|
end
|
|
116
146
|
|
|
117
147
|
def make_request(method, relative_url, signature, params = {}, data = {}, headers = {})
|
|
118
148
|
headers['Authorization'] = signature
|
|
119
149
|
headers['stream-auth-type'] = 'jwt'
|
|
120
|
-
|
|
121
150
|
get_http_client.make_http_request(method, relative_url, make_query_params(params), data, headers)
|
|
122
151
|
end
|
|
123
152
|
|
|
@@ -162,7 +191,7 @@ module Stream
|
|
|
162
191
|
|
|
163
192
|
case response[:status].to_i
|
|
164
193
|
when 200..203
|
|
165
|
-
|
|
194
|
+
::JSON.parse(response[:body])
|
|
166
195
|
end
|
|
167
196
|
end
|
|
168
197
|
end
|
|
@@ -171,16 +200,16 @@ module Stream
|
|
|
171
200
|
def call(env)
|
|
172
201
|
@app.call(env).on_complete do |response|
|
|
173
202
|
case response[:status].to_i
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
203
|
+
when 200..203
|
|
204
|
+
return response
|
|
205
|
+
when 401
|
|
206
|
+
raise StreamApiResponseException, error_message(response, 'Bad feed')
|
|
207
|
+
when 403
|
|
208
|
+
raise StreamApiResponseException, error_message(response, 'Bad auth/headers')
|
|
209
|
+
when 404
|
|
210
|
+
raise StreamApiResponseException, error_message(response, 'url not found')
|
|
211
|
+
when 204...600
|
|
212
|
+
raise StreamApiResponseException, error_message(response, _build_error_message(response.body))
|
|
184
213
|
end
|
|
185
214
|
end
|
|
186
215
|
end
|
|
@@ -204,7 +233,7 @@ module Stream
|
|
|
204
233
|
end
|
|
205
234
|
|
|
206
235
|
def error_message(response, body = nil)
|
|
207
|
-
"#{response[:method].to_s.upcase} #{response[:url]}: #{[response[:status]
|
|
236
|
+
"#{response[:method].to_s.upcase} #{response[:url]}: #{["#{response[:status]}:", body].compact.join(' ')}"
|
|
208
237
|
end
|
|
209
238
|
end
|
|
210
239
|
end
|
data/lib/stream/collections.rb
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
module Stream
|
|
2
2
|
class CollectionsClient < Client
|
|
3
|
+
def add(collection_name, collection_data, id: nil, user_id: nil)
|
|
4
|
+
data = {
|
|
5
|
+
id: id,
|
|
6
|
+
user_id: user_id,
|
|
7
|
+
data: collection_data
|
|
8
|
+
}
|
|
9
|
+
uri = "/collections/#{collection_name}/"
|
|
10
|
+
make_collection_request(:post, {}, data, endpoint: uri)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def get(collection_name, id)
|
|
14
|
+
uri = "collections/#{collection_name}/#{id}/"
|
|
15
|
+
make_collection_request(:get, {}, {}, endpoint: uri)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def update(collection_name, id, data: nil)
|
|
19
|
+
data = {
|
|
20
|
+
data: data
|
|
21
|
+
}
|
|
22
|
+
uri = "collections/#{collection_name}/#{id}/"
|
|
23
|
+
make_collection_request(:put, {}, data, endpoint: uri)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def delete(collection_name, id)
|
|
27
|
+
uri = "collections/#{collection_name}/#{id}/"
|
|
28
|
+
make_collection_request(:delete, {}, {}, endpoint: uri)
|
|
29
|
+
end
|
|
30
|
+
|
|
3
31
|
def upsert(collection, objects = [])
|
|
4
32
|
data = {
|
|
5
33
|
data: {
|
|
@@ -9,14 +37,14 @@ module Stream
|
|
|
9
37
|
make_collection_request(:post, {}, data)
|
|
10
38
|
end
|
|
11
39
|
|
|
12
|
-
def
|
|
40
|
+
def select(collection, ids = [])
|
|
13
41
|
params = {
|
|
14
42
|
foreign_ids: ids.map { |id| "#{collection}:#{id}" }.join(',')
|
|
15
43
|
}
|
|
16
44
|
make_collection_request(:get, params, {})
|
|
17
45
|
end
|
|
18
46
|
|
|
19
|
-
def
|
|
47
|
+
def delete_many(collection, ids = [])
|
|
20
48
|
params = {
|
|
21
49
|
collection_name: collection,
|
|
22
50
|
ids: ids.join(',')
|
|
@@ -25,17 +53,14 @@ module Stream
|
|
|
25
53
|
end
|
|
26
54
|
|
|
27
55
|
def create_reference(collection, id)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def create_user_reference(id)
|
|
32
|
-
create_reference('user', id)
|
|
56
|
+
k = id
|
|
57
|
+
k = id['id'] if id.respond_to?(:keys) && !id['id'].nil?
|
|
58
|
+
"SO:#{collection}:#{k}"
|
|
33
59
|
end
|
|
34
60
|
|
|
35
61
|
private
|
|
36
62
|
|
|
37
|
-
def make_collection_request(method, params, data)
|
|
38
|
-
endpoint = '/meta/'
|
|
63
|
+
def make_collection_request(method, params, data, endpoint: '/collections/')
|
|
39
64
|
auth_token = Stream::Signer.create_jwt_token('collections', '*', @api_secret, '*', '*')
|
|
40
65
|
make_request(method, endpoint, auth_token, params, data)
|
|
41
66
|
end
|
data/lib/stream/errors.rb
CHANGED
data/lib/stream/feed.rb
CHANGED
|
@@ -6,16 +6,11 @@ module Stream
|
|
|
6
6
|
attr_reader :id
|
|
7
7
|
attr_reader :slug
|
|
8
8
|
attr_reader :user_id
|
|
9
|
-
attr_reader :token
|
|
10
9
|
|
|
11
|
-
def initialize(client, feed_slug, user_id
|
|
12
|
-
unless valid_feed_slug feed_slug
|
|
13
|
-
raise StreamInputData, 'feed_slug can only contain alphanumeric characters plus underscores'
|
|
14
|
-
end
|
|
10
|
+
def initialize(client, feed_slug, user_id)
|
|
11
|
+
raise StreamInputData, 'feed_slug can only contain alphanumeric characters plus underscores' unless valid_feed_slug feed_slug
|
|
15
12
|
|
|
16
|
-
unless valid_user_id user_id
|
|
17
|
-
raise StreamInputData, 'user_id can only contain alphanumeric characters plus underscores and dashes'
|
|
18
|
-
end
|
|
13
|
+
raise StreamInputData, 'user_id can only contain alphanumeric characters plus underscores and dashes' unless valid_user_id user_id
|
|
19
14
|
|
|
20
15
|
@id = "#{feed_slug}:#{user_id}"
|
|
21
16
|
@client = client
|
|
@@ -23,7 +18,6 @@ module Stream
|
|
|
23
18
|
@slug = feed_slug
|
|
24
19
|
@feed_name = "#{feed_slug}#{user_id}"
|
|
25
20
|
@feed_url = "#{feed_slug}/#{user_id}"
|
|
26
|
-
@token = token
|
|
27
21
|
end
|
|
28
22
|
|
|
29
23
|
def readonly_token
|
|
@@ -39,30 +33,27 @@ module Stream
|
|
|
39
33
|
end
|
|
40
34
|
|
|
41
35
|
def get(params = {})
|
|
42
|
-
uri =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
36
|
+
uri = if params[:enrich] || params[:reactions]
|
|
37
|
+
"/enrich/feed/#{@feed_url}/"
|
|
38
|
+
else
|
|
39
|
+
"/feed/#{@feed_url}/"
|
|
40
|
+
end
|
|
41
|
+
params[:mark_read] = params[:mark_read].join(',') if params[:mark_read]&.is_a?(Array)
|
|
42
|
+
params[:mark_seen] = params[:mark_seen].join(',') if params[:mark_seen]&.is_a?(Array)
|
|
43
|
+
if params[:reactions].respond_to?(:keys)
|
|
44
|
+
params[:withOwnReactions] = true if params[:reactions][:own]
|
|
45
|
+
params[:withRecentReactions] = true if params[:reactions][:recent]
|
|
46
|
+
params[:withReactionCounts] = true if params[:reactions][:counts]
|
|
48
47
|
end
|
|
49
|
-
|
|
48
|
+
%i[enrich reactions].each { |k| params.delete(k) }
|
|
50
49
|
|
|
50
|
+
auth_token = create_jwt_token('feed', 'read')
|
|
51
51
|
@client.make_request(:get, uri, auth_token, params)
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
def sign_to_field(to)
|
|
55
|
-
to.map do |feed_id|
|
|
56
|
-
feed_slug, user_id = feed_id.split(':')
|
|
57
|
-
feed = @client.feed(feed_slug, user_id)
|
|
58
|
-
"#{feed.id} #{feed.token}"
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
54
|
def add_activity(activity_data)
|
|
63
55
|
uri = "/feed/#{@feed_url}/"
|
|
64
56
|
data = activity_data.clone
|
|
65
|
-
data[:to] &&= sign_to_field(data[:to])
|
|
66
57
|
auth_token = create_jwt_token('feed', 'write')
|
|
67
58
|
|
|
68
59
|
@client.make_request(:post, uri, auth_token, {}, data)
|
|
@@ -70,23 +61,20 @@ module Stream
|
|
|
70
61
|
|
|
71
62
|
def add_activities(activities)
|
|
72
63
|
uri = "/feed/#{@feed_url}/"
|
|
73
|
-
activities
|
|
74
|
-
activity[:to] &&= sign_to_field(activity[:to])
|
|
75
|
-
end
|
|
76
|
-
data = {:activities => activities}
|
|
64
|
+
data = { activities: activities }
|
|
77
65
|
auth_token = create_jwt_token('feed', 'write')
|
|
78
66
|
|
|
79
67
|
@client.make_request(:post, uri, auth_token, {}, data)
|
|
80
68
|
end
|
|
81
69
|
|
|
82
|
-
def remove(activity_id, foreign_id
|
|
70
|
+
def remove(activity_id, foreign_id: false)
|
|
83
71
|
remove_activity(activity_id, foreign_id)
|
|
84
72
|
end
|
|
85
73
|
|
|
86
|
-
def remove_activity(activity_id, foreign_id
|
|
74
|
+
def remove_activity(activity_id, foreign_id: false)
|
|
87
75
|
uri = "/feed/#{@feed_url}/#{activity_id}/"
|
|
88
76
|
params = {}
|
|
89
|
-
params = {foreign_id: 1} if foreign_id
|
|
77
|
+
params = { foreign_id: 1 } if foreign_id
|
|
90
78
|
auth_token = create_jwt_token('feed', 'delete')
|
|
91
79
|
|
|
92
80
|
@client.make_request(:delete, uri, auth_token, params)
|
|
@@ -102,15 +90,29 @@ module Stream
|
|
|
102
90
|
@client.make_request(:post, '/activities/', auth_token, {}, 'activities' => activities)
|
|
103
91
|
end
|
|
104
92
|
|
|
93
|
+
def update_activity_to_targets(foreign_id, time, new_targets: nil, added_targets: nil, removed_targets: nil)
|
|
94
|
+
uri = "/feed_targets/#{@feed_url}/activity_to_targets/"
|
|
95
|
+
data = {
|
|
96
|
+
'foreign_id': foreign_id,
|
|
97
|
+
'time': time
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
data['new_targets'] = new_targets unless new_targets.nil?
|
|
101
|
+
data['added_targets'] = added_targets unless added_targets.nil?
|
|
102
|
+
data['removed_targets'] = removed_targets unless removed_targets.nil?
|
|
103
|
+
auth_token = create_jwt_token('feed_targets', 'write')
|
|
104
|
+
|
|
105
|
+
@client.make_request(:post, uri, auth_token, {}, data)
|
|
106
|
+
end
|
|
107
|
+
|
|
105
108
|
def follow(target_feed_slug, target_user_id, activity_copy_limit = 300)
|
|
106
109
|
uri = "/feed/#{@feed_url}/follows/"
|
|
107
|
-
activity_copy_limit = 0 if activity_copy_limit
|
|
110
|
+
activity_copy_limit = 0 if activity_copy_limit.negative?
|
|
108
111
|
activity_copy_limit = 1000 if activity_copy_limit > 1000
|
|
109
112
|
|
|
110
113
|
follow_data = {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
activity_copy_limit: activity_copy_limit
|
|
114
|
+
target: "#{target_feed_slug}:#{target_user_id}",
|
|
115
|
+
activity_copy_limit: activity_copy_limit
|
|
114
116
|
}
|
|
115
117
|
auth_token = create_jwt_token('follower', 'write')
|
|
116
118
|
|
|
@@ -120,8 +122,8 @@ module Stream
|
|
|
120
122
|
def followers(offset = 0, limit = 25)
|
|
121
123
|
uri = "/feed/#{@feed_url}/followers/"
|
|
122
124
|
params = {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
+
offset: offset,
|
|
126
|
+
limit: limit
|
|
125
127
|
}
|
|
126
128
|
auth_token = create_jwt_token('follower', 'read')
|
|
127
129
|
|
|
@@ -131,16 +133,16 @@ module Stream
|
|
|
131
133
|
def following(offset = 0, limit = 25, filter = [])
|
|
132
134
|
uri = "/feed/#{@feed_url}/follows/"
|
|
133
135
|
params = {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
136
|
+
offset: offset,
|
|
137
|
+
limit: limit,
|
|
138
|
+
filter: filter.join(',')
|
|
137
139
|
}
|
|
138
140
|
auth_token = create_jwt_token('follower', 'read')
|
|
139
141
|
|
|
140
142
|
@client.make_request(:get, uri, auth_token, params)
|
|
141
143
|
end
|
|
142
144
|
|
|
143
|
-
def unfollow(target_feed_slug, target_user_id, keep_history
|
|
145
|
+
def unfollow(target_feed_slug, target_user_id, keep_history: false)
|
|
144
146
|
uri = "/feed/#{@feed_url}/follows/#{target_feed_slug}:#{target_user_id}/"
|
|
145
147
|
auth_token = create_jwt_token('follower', 'delete')
|
|
146
148
|
params = {}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
module Stream
|
|
2
|
+
class ReactionsClient < Client
|
|
3
|
+
def add(kind, activity_id, user_id, data: nil, target_feeds: nil)
|
|
4
|
+
data = {
|
|
5
|
+
kind: kind,
|
|
6
|
+
activity_id: activity_id,
|
|
7
|
+
user_id: user_id,
|
|
8
|
+
data: data,
|
|
9
|
+
target_feeds: target_feeds
|
|
10
|
+
}
|
|
11
|
+
make_reaction_request(:post, {}, data)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def get(reaction_id)
|
|
15
|
+
uri = "/reaction/#{reaction_id}/"
|
|
16
|
+
make_reaction_request(:get, {}, {}, endpoint: uri)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def update(reaction_id, data: nil, target_feeds: nil)
|
|
20
|
+
data = {
|
|
21
|
+
data: data,
|
|
22
|
+
target_feeds: target_feeds
|
|
23
|
+
}
|
|
24
|
+
uri = "/reaction/#{reaction_id}/"
|
|
25
|
+
make_reaction_request(:put, {}, data, endpoint: uri)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def delete(reaction_id)
|
|
29
|
+
uri = "/reaction/#{reaction_id}/"
|
|
30
|
+
make_reaction_request(:delete, {}, {}, endpoint: uri)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def add_child(kind, parent_id, user_id, data: nil, target_feeds: nil)
|
|
34
|
+
data = {
|
|
35
|
+
kind: kind,
|
|
36
|
+
parent: parent_id,
|
|
37
|
+
user_id: user_id,
|
|
38
|
+
data: data,
|
|
39
|
+
target_feeds: target_feeds
|
|
40
|
+
}
|
|
41
|
+
make_reaction_request(:post, {}, data)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def filter(params = {})
|
|
45
|
+
field = ''
|
|
46
|
+
value = ''
|
|
47
|
+
kind = params.fetch(:kind, '')
|
|
48
|
+
if params[:reaction_id]
|
|
49
|
+
field = 'reaction_id'
|
|
50
|
+
value = params[:reaction_id]
|
|
51
|
+
elsif params[:activity_id]
|
|
52
|
+
field = 'activity_id'
|
|
53
|
+
value = params[:activity_id]
|
|
54
|
+
elsif params[:user_id]
|
|
55
|
+
field = 'user_id'
|
|
56
|
+
value = params[:user_id]
|
|
57
|
+
end
|
|
58
|
+
params.delete(field.to_sym) unless field.empty?
|
|
59
|
+
uri = if kind.nil? || kind.empty?
|
|
60
|
+
"/reaction/#{field}/#{value}/"
|
|
61
|
+
else
|
|
62
|
+
"/reaction/#{field}/#{value}/#{kind}/"
|
|
63
|
+
end
|
|
64
|
+
make_reaction_request(:get, params, {}, endpoint: uri)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def create_reference(id)
|
|
68
|
+
k = id
|
|
69
|
+
k = id['id'] if id.respond_to?(:keys) && !id['id'].nil?
|
|
70
|
+
"SR:#{k}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def make_reaction_request(method, params, data, endpoint: '/reaction/')
|
|
76
|
+
auth_token = Stream::Signer.create_jwt_token('reactions', '*', @api_secret, '*', '*')
|
|
77
|
+
make_request(method, endpoint, auth_token, params, data)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
data/lib/stream/signer.rb
CHANGED
|
@@ -7,32 +7,17 @@ module Stream
|
|
|
7
7
|
|
|
8
8
|
def initialize(key)
|
|
9
9
|
@key = key.to_s
|
|
10
|
-
@sha1 = OpenSSL::Digest.new('sha1')
|
|
11
10
|
end
|
|
12
11
|
|
|
13
|
-
def
|
|
14
|
-
value.tr('+', '-').tr('/', '_').gsub(/^=+/, '').gsub(/=+$/, '')
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def sign_message(message)
|
|
18
|
-
key = Digest::SHA1.digest @key.to_s
|
|
19
|
-
token = Base64.strict_encode64(OpenSSL::HMAC.digest(@sha1, key, message))
|
|
20
|
-
urlsafe_encodeb64(token)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def sign(feed_slug, user_id)
|
|
24
|
-
sign_message("#{feed_slug}#{user_id}")
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def self.create_user_session_token(user_id, payload = {}, api_secret)
|
|
12
|
+
def self.create_user_token(user_id, payload = {}, api_secret)
|
|
28
13
|
payload['user_id'] = user_id
|
|
29
|
-
|
|
14
|
+
JWT.encode(payload, api_secret, 'HS256')
|
|
30
15
|
end
|
|
31
16
|
|
|
32
17
|
def self.create_jwt_token(resource, action, api_secret, feed_id = nil, user_id = nil)
|
|
33
18
|
payload = {
|
|
34
|
-
|
|
35
|
-
|
|
19
|
+
resource: resource,
|
|
20
|
+
action: action
|
|
36
21
|
}
|
|
37
22
|
payload['feed_id'] = feed_id if feed_id
|
|
38
23
|
payload['user_id'] = user_id if user_id
|
data/lib/stream/url.rb
CHANGED
|
@@ -7,10 +7,11 @@ module Stream
|
|
|
7
7
|
|
|
8
8
|
class APIURLGenerator < URLGenerator
|
|
9
9
|
def initialize(options)
|
|
10
|
+
super()
|
|
10
11
|
@options = options
|
|
11
12
|
location = make_location(options[:location])
|
|
12
|
-
location ||=
|
|
13
|
-
api_version = options[:api_version]
|
|
13
|
+
location ||= 'api'
|
|
14
|
+
api_version = options[:api_version] || 'v1.0'
|
|
14
15
|
if ENV['STREAM_URL']
|
|
15
16
|
uri = URI.parse(ENV['STREAM_URL'])
|
|
16
17
|
scheme = uri.scheme
|
|
@@ -48,6 +49,7 @@ module Stream
|
|
|
48
49
|
|
|
49
50
|
class PersonalizationURLGenerator < URLGenerator
|
|
50
51
|
def initialize(options)
|
|
52
|
+
super()
|
|
51
53
|
@options = options
|
|
52
54
|
host = 'personalization.stream-io-api.com'
|
|
53
55
|
@base_path = '/personalization/v1.0'
|
data/lib/stream/users.rb
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Stream
|
|
2
|
+
class UsersClient < Client
|
|
3
|
+
def add(user_id, data: nil, get_or_create: false)
|
|
4
|
+
data = {
|
|
5
|
+
id: user_id,
|
|
6
|
+
data: data
|
|
7
|
+
}
|
|
8
|
+
params = {
|
|
9
|
+
get_or_create: get_or_create
|
|
10
|
+
}
|
|
11
|
+
make_user_request(:post, params, data)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def get(user_id)
|
|
15
|
+
uri = "/user/#{user_id}/"
|
|
16
|
+
make_user_request(:get, {}, {}, endpoint: uri)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def update(user_id, data: nil)
|
|
20
|
+
data = {
|
|
21
|
+
data: data
|
|
22
|
+
}
|
|
23
|
+
uri = "/user/#{user_id}/"
|
|
24
|
+
make_user_request(:put, {}, data, endpoint: uri)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def delete(user_id)
|
|
28
|
+
uri = "/user/#{user_id}/"
|
|
29
|
+
make_user_request(:delete, {}, {}, endpoint: uri)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def create_reference(id)
|
|
33
|
+
k = id
|
|
34
|
+
k = id['id'] if id.respond_to?(:keys) && !id['id'].nil?
|
|
35
|
+
"SU:#{k}"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def make_user_request(method, params, data, endpoint: '/user/')
|
|
41
|
+
auth_token = Stream::Signer.create_jwt_token('users', '*', @api_secret, '*', '*')
|
|
42
|
+
make_request(method, endpoint, auth_token, params, data)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
data/lib/stream/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stream-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 4.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tommaso Barbugli
|
|
@@ -10,40 +10,20 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date:
|
|
13
|
+
date: 2021-01-05 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: faraday
|
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
|
18
18
|
requirements:
|
|
19
19
|
- - ">="
|
|
20
|
-
- !ruby/object:Gem::Version
|
|
21
|
-
version: 0.10.0
|
|
22
|
-
- - "<"
|
|
23
|
-
- !ruby/object:Gem::Version
|
|
24
|
-
version: '1.0'
|
|
25
|
-
type: :runtime
|
|
26
|
-
prerelease: false
|
|
27
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
28
|
-
requirements:
|
|
29
|
-
- - ">="
|
|
30
|
-
- !ruby/object:Gem::Version
|
|
31
|
-
version: 0.10.0
|
|
32
|
-
- - "<"
|
|
33
|
-
- !ruby/object:Gem::Version
|
|
34
|
-
version: '1.0'
|
|
35
|
-
- !ruby/object:Gem::Dependency
|
|
36
|
-
name: http_signatures
|
|
37
|
-
requirement: !ruby/object:Gem::Requirement
|
|
38
|
-
requirements:
|
|
39
|
-
- - "~>"
|
|
40
20
|
- !ruby/object:Gem::Version
|
|
41
21
|
version: '0'
|
|
42
22
|
type: :runtime
|
|
43
23
|
prerelease: false
|
|
44
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
45
25
|
requirements:
|
|
46
|
-
- - "
|
|
26
|
+
- - ">="
|
|
47
27
|
- !ruby/object:Gem::Version
|
|
48
28
|
version: '0'
|
|
49
29
|
- !ruby/object:Gem::Dependency
|
|
@@ -52,62 +32,56 @@ dependencies:
|
|
|
52
32
|
requirements:
|
|
53
33
|
- - ">="
|
|
54
34
|
- !ruby/object:Gem::Version
|
|
55
|
-
version:
|
|
56
|
-
- - "~>"
|
|
57
|
-
- !ruby/object:Gem::Version
|
|
58
|
-
version: '2.1'
|
|
35
|
+
version: '0'
|
|
59
36
|
type: :runtime
|
|
60
37
|
prerelease: false
|
|
61
38
|
version_requirements: !ruby/object:Gem::Requirement
|
|
62
39
|
requirements:
|
|
63
40
|
- - ">="
|
|
64
41
|
- !ruby/object:Gem::Version
|
|
65
|
-
version:
|
|
66
|
-
- - "~>"
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '2.1'
|
|
42
|
+
version: '0'
|
|
69
43
|
- !ruby/object:Gem::Dependency
|
|
70
44
|
name: rake
|
|
71
45
|
requirement: !ruby/object:Gem::Requirement
|
|
72
46
|
requirements:
|
|
73
|
-
- - "
|
|
47
|
+
- - ">="
|
|
74
48
|
- !ruby/object:Gem::Version
|
|
75
49
|
version: '0'
|
|
76
50
|
type: :development
|
|
77
51
|
prerelease: false
|
|
78
52
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
53
|
requirements:
|
|
80
|
-
- - "
|
|
54
|
+
- - ">="
|
|
81
55
|
- !ruby/object:Gem::Version
|
|
82
56
|
version: '0'
|
|
83
57
|
- !ruby/object:Gem::Dependency
|
|
84
58
|
name: rspec
|
|
85
59
|
requirement: !ruby/object:Gem::Requirement
|
|
86
60
|
requirements:
|
|
87
|
-
- - "
|
|
61
|
+
- - ">="
|
|
88
62
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '
|
|
63
|
+
version: '0'
|
|
90
64
|
type: :development
|
|
91
65
|
prerelease: false
|
|
92
66
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
67
|
requirements:
|
|
94
|
-
- - "
|
|
68
|
+
- - ">="
|
|
95
69
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '
|
|
70
|
+
version: '0'
|
|
97
71
|
- !ruby/object:Gem::Dependency
|
|
98
72
|
name: simplecov
|
|
99
73
|
requirement: !ruby/object:Gem::Requirement
|
|
100
74
|
requirements:
|
|
101
|
-
- - "
|
|
75
|
+
- - ">="
|
|
102
76
|
- !ruby/object:Gem::Version
|
|
103
|
-
version: '0
|
|
77
|
+
version: '0'
|
|
104
78
|
type: :development
|
|
105
79
|
prerelease: false
|
|
106
80
|
version_requirements: !ruby/object:Gem::Requirement
|
|
107
81
|
requirements:
|
|
108
|
-
- - "
|
|
82
|
+
- - ">="
|
|
109
83
|
- !ruby/object:Gem::Version
|
|
110
|
-
version: '0
|
|
84
|
+
version: '0'
|
|
111
85
|
description: Ruby client for getstream.io service
|
|
112
86
|
email: support@getstream.io
|
|
113
87
|
executables: []
|
|
@@ -128,9 +102,10 @@ files:
|
|
|
128
102
|
- lib/stream/exceptions.rb
|
|
129
103
|
- lib/stream/feed.rb
|
|
130
104
|
- lib/stream/personalization.rb
|
|
131
|
-
- lib/stream/
|
|
105
|
+
- lib/stream/reactions.rb
|
|
132
106
|
- lib/stream/signer.rb
|
|
133
107
|
- lib/stream/url.rb
|
|
108
|
+
- lib/stream/users.rb
|
|
134
109
|
- lib/stream/version.rb
|
|
135
110
|
homepage: http://github.com/GetStream/stream-ruby
|
|
136
111
|
licenses:
|
|
@@ -144,17 +119,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
144
119
|
requirements:
|
|
145
120
|
- - ">="
|
|
146
121
|
- !ruby/object:Gem::Version
|
|
147
|
-
version:
|
|
122
|
+
version: 2.5.0
|
|
148
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
124
|
requirements:
|
|
150
125
|
- - ">="
|
|
151
126
|
- !ruby/object:Gem::Version
|
|
152
127
|
version: '0'
|
|
153
128
|
requirements: []
|
|
154
|
-
|
|
155
|
-
rubygems_version: 2.4.7
|
|
129
|
+
rubygems_version: 3.1.2
|
|
156
130
|
signing_key:
|
|
157
131
|
specification_version: 4
|
|
158
132
|
summary: A gem that provides a client interface for getstream.io
|
|
159
133
|
test_files: []
|
|
160
|
-
has_rdoc: true
|
data/lib/stream/signedrequest.rb
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
require 'http_signatures'
|
|
2
|
-
require 'net/http'
|
|
3
|
-
require 'time'
|
|
4
|
-
|
|
5
|
-
module Stream
|
|
6
|
-
module SignedRequest
|
|
7
|
-
module ClassMethods
|
|
8
|
-
def supports_signed_requests;
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def self.included(klass)
|
|
13
|
-
klass.extend ClassMethods
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def make_signed_request(method, relative_url, params = {}, data = {})
|
|
17
|
-
query_params = make_query_params(params)
|
|
18
|
-
context = HttpSignatures::Context.new(
|
|
19
|
-
keys: {@api_key => @api_secret},
|
|
20
|
-
algorithm: 'hmac-sha256',
|
|
21
|
-
headers: %w(date)
|
|
22
|
-
)
|
|
23
|
-
method_map = {
|
|
24
|
-
:get => Net::HTTP::Get,
|
|
25
|
-
:delete => Net::HTTP::Delete,
|
|
26
|
-
:put => Net::HTTP::Put,
|
|
27
|
-
:post => Net::HTTP::Post
|
|
28
|
-
}
|
|
29
|
-
request_date = Time.now.rfc822
|
|
30
|
-
message = method_map[method].new(
|
|
31
|
-
"#{get_http_client.base_path}#{relative_url}?#{URI.encode_www_form(query_params)}",
|
|
32
|
-
'date' => request_date
|
|
33
|
-
)
|
|
34
|
-
context.signer.sign(message)
|
|
35
|
-
headers = {
|
|
36
|
-
Authorization: message['Signature'],
|
|
37
|
-
Date: request_date,
|
|
38
|
-
'X-Api-Key' => api_key
|
|
39
|
-
}
|
|
40
|
-
get_http_client.make_http_request(method, relative_url, query_params, data, headers)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|