async-rest 0.10.0 → 0.12.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a406ea0610d8c9f964d11b6c53881ef9e34b02a49dce5db69e35786f005c17e
4
- data.tar.gz: 9f993dccfca870612bb7a30ea84a8ad566606cf6cbbd951891cd4861820c12b9
3
+ metadata.gz: bc914b22fd6a8a19da71676f835e23a606b8c9e6ebd981f25b17b9452422a791
4
+ data.tar.gz: d639c6647805c99501b9849ee4ebdc3a1650279b93b5053f00af513cb75c2e6b
5
5
  SHA512:
6
- metadata.gz: 148b577baeb3606ad99ee9fe2211f91150e2d047e17b84f8c61f4ffc53642765375ef0cfc3048e173ca36f74542f6f511160e7ec9ac64abe62b8396c32faf28f
7
- data.tar.gz: 7cdf063ca9b4b228452e1502a552a74d7aabaff4ac625394498c75bc1bdfc3df7fef7414db19c050ff540000540432d4cf819d7a56c195ea5d0176920e5221dc
6
+ metadata.gz: 2fe066c918388cd94e92ba167f0910fd189991abb14565172946f74f9d8af3f24f66c18cef586a0b41a87d19c036af08da227404954f5619c313b1273fe64025
7
+ data.tar.gz: fe5226f20eb31178830ff77f37df8d03c0d3f66c0edc098ed700fcf7f394fee9ba4452cca6190e21c153390915227df23d7e29017e506f9c18f7e19000be33f5
data/lib/async/rest.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
4
  #
3
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
4
  #
3
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -23,7 +25,24 @@ module Async
23
25
  class Error < StandardError
24
26
  end
25
27
 
26
- class RequestFailure < Error
28
+ class RequestError < Error
29
+ end
30
+
31
+ class UnsupportedError < Error
32
+ end
33
+
34
+ class ResponseError < Error
35
+ def initialize(response)
36
+ super(response.read)
37
+
38
+ @response = response
39
+ end
40
+
41
+ def to_s
42
+ "#{@response}: #{super}"
43
+ end
44
+
45
+ attr :response
27
46
  end
28
47
  end
29
48
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
4
  #
3
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -28,15 +30,35 @@ module Async
28
30
  #
29
31
  # A representation consists of data, metadata describing the data, and, on occasion, metadata to describe the metadata (usually for the purpose of verifying message integrity). Metadata is in the form of name-value pairs, where the name corresponds to a standard that defines the value's structure and semantics. Response messages may include both representation metadata and resource metadata: information about the resource that is not specific to the supplied representation.
30
32
  class Representation
31
- def self.for(*args, **options)
32
- self.new(Resource.for(*args), **options)
33
+ def self.[] wrapper
34
+ klass = Class.new(self)
35
+
36
+ klass.const_set(:WRAPPER, wrapper)
37
+
38
+ return klass
39
+ end
40
+
41
+ def self.for(*arguments, **options)
42
+ representation = self.new(Resource.for(*arguments), **options)
43
+
44
+ return representation unless block_given?
45
+
46
+ Async do
47
+ begin
48
+ yield representation
49
+ ensure
50
+ representation.close
51
+ end
52
+ end
33
53
  end
34
54
 
55
+ WRAPPER = Wrapper::JSON
56
+
35
57
  # @param resource [Resource] the RESTful resource that this representation is of.
36
58
  # @param metadata [Hash | HTTP::Headers] the metadata associated wtih teh representation.
37
59
  # @param value [Object] the value of the representation.
38
60
  # @param wrapper [#prepare_request, #process_response] the wrapper for encoding/decoding the request/response body.
39
- def initialize(resource, metadata: {}, value: nil, wrapper: Wrapper::JSON.new)
61
+ def initialize(resource, metadata: {}, value: nil, wrapper: self.class::WRAPPER.new)
40
62
  @resource = resource
41
63
  @wrapper = wrapper
42
64
 
@@ -44,8 +66,12 @@ module Async
44
66
  @value = value
45
67
  end
46
68
 
47
- def with(klass = self.class, **options)
48
- klass.new(@resource.with(**options), wrapper: @wrapper)
69
+ def with(klass = nil, **options)
70
+ if klass
71
+ klass.new(@resource.with(**options), wrapper: klass::WRAPPER.new)
72
+ else
73
+ self.new(@resource.with(**options), wrapper: @wrapper)
74
+ end
49
75
  end
50
76
 
51
77
  def [] **parameters
@@ -63,6 +89,7 @@ module Async
63
89
  @resource.prepare_request(verb, payload, &@wrapper.method(:prepare_request))
64
90
  end
65
91
 
92
+ # If an exception propagates out of this method, the response will be closed.
66
93
  def process_response(request, response)
67
94
  @wrapper.process_response(request, response)
68
95
  end
@@ -75,7 +102,14 @@ module Async
75
102
 
76
103
  response = @resource.call(request)
77
104
 
78
- process_response(request, response)
105
+ # If we exit this block because of an exception, we close the response. This ensures we don't have any dangling connections.
106
+ begin
107
+ return process_response(request, response)
108
+ rescue
109
+ response.close
110
+
111
+ raise
112
+ end
79
113
  end
80
114
  end
81
115
 
@@ -88,7 +122,7 @@ module Async
88
122
  @metadata = response.headers
89
123
  @value = response.read
90
124
  else
91
-
125
+ raise ResponseError, response
92
126
  end
93
127
  end
94
128
 
@@ -39,13 +39,14 @@ module Async
39
39
  @headers = headers
40
40
  end
41
41
 
42
+ # @param endpoint [Async::HTTP::Endpoint] used to connect to the remote system and specify the base path.
42
43
  def self.connect(endpoint)
43
44
  reference = ::Protocol::HTTP::Reference.parse(endpoint.path)
44
45
 
45
46
  return ::Protocol::HTTP::AcceptEncoding.new(HTTP::Client.new(endpoint)), reference
46
47
  end
47
48
 
48
- def self.for(endpoint, *args)
49
+ def self.for(endpoint, *arguments)
49
50
  # TODO This behaviour is deprecated and will probably be removed.
50
51
  if endpoint.is_a? String
51
52
  endpoint = HTTP::Endpoint.parse(endpoint)
@@ -53,11 +54,11 @@ module Async
53
54
 
54
55
  client, reference = connect(endpoint)
55
56
 
56
- resource = self.new(client, reference, *args)
57
+ resource = self.new(client, reference, *arguments)
57
58
 
58
59
  return resource unless block_given?
59
60
 
60
- Async.run do
61
+ Async do
61
62
  begin
62
63
  yield resource
63
64
  ensure
@@ -69,14 +70,14 @@ module Async
69
70
  attr :reference
70
71
  attr :headers
71
72
 
72
- def self.with(parent, *args, headers: {}, **options)
73
+ def self.with(parent, *arguments, headers: {}, **options)
73
74
  reference = parent.reference.with(**options)
74
75
 
75
- self.new(*args, parent.delegate, reference, parent.headers.merge(headers))
76
+ self.new(*arguments, parent.delegate, reference, parent.headers.merge(headers))
76
77
  end
77
78
 
78
- def with(*args, **options)
79
- self.class.with(self, *args, **options)
79
+ def with(*arguments, **options)
80
+ self.class.with(self, *arguments, **options)
80
81
  end
81
82
 
82
83
  def get(klass = Representation, **parameters)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
4
  #
3
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -20,6 +22,6 @@
20
22
 
21
23
  module Async
22
24
  module REST
23
- VERSION = "0.10.0"
25
+ VERSION = "0.12.3"
24
26
  end
25
27
  end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require_relative 'json'
24
+ require_relative 'url_encoded'
25
+
26
+ module Async
27
+ module REST
28
+ module Wrapper
29
+ class Form < Generic
30
+ DEFAULT_CONTENT_TYPES = {
31
+ JSON::APPLICATION_JSON => JSON::Parser,
32
+ URLEncoded::APPLICATION_FORM_URLENCODED => URLEncoded::Parser,
33
+ }
34
+
35
+ def initialize(content_types = DEFAULT_CONTENT_TYPES)
36
+ @content_types = content_types
37
+ end
38
+
39
+ def prepare_request(payload, headers)
40
+ @content_types.each_key do |key|
41
+ headers.add('accept', key)
42
+ end
43
+
44
+ if payload
45
+ headers['content-type'] = URLEncoded::APPLICATION_FORM_URLENCODED
46
+
47
+ ::Protocol::HTTP::Body::Buffered.new([
48
+ ::Protocol::HTTP::URL.encode(payload)
49
+ ])
50
+ end
51
+ end
52
+
53
+ def parser_for(response)
54
+ if content_type = response.headers['content-type']
55
+ if parser = @content_types[content_type]
56
+ return parser
57
+ end
58
+ end
59
+
60
+ return super
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
4
  #
3
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -32,8 +34,28 @@ module Async
32
34
  # @param response [Protocol::HTTP::Response] the response that was received.
33
35
  # @return [Object] some application specific representation of the response.
34
36
  def process_response(request, response)
37
+ wrap_response(response)
38
+ end
39
+
40
+ def parser_for(response)
41
+ # It's not always clear why this error is being thrown.
42
+ return Unsupported
43
+ end
44
+
45
+ # Wrap the response body in the given klass.
46
+ def wrap_response(response)
47
+ if body = response.body
48
+ response.body = parser_for(response).new(body)
49
+ end
50
+
35
51
  return response
36
52
  end
53
+
54
+ class Unsupported < HTTP::Body::Wrapper
55
+ def join
56
+ raise UnsupportedError, super
57
+ end
58
+ end
37
59
  end
38
60
  end
39
61
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
4
  #
3
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -38,7 +40,7 @@ module Async
38
40
 
39
41
  attr :content_type
40
42
 
41
- def split(*args)
43
+ def split(*arguments)
42
44
  @content_type.split
43
45
  end
44
46
 
@@ -48,7 +50,6 @@ module Async
48
50
  if payload
49
51
  headers['content-type'] = @content_type
50
52
 
51
- # TODO dump incrementally to IO?
52
53
  HTTP::Body::Buffered.new([
53
54
  ::JSON.dump(payload)
54
55
  ])
@@ -61,22 +62,14 @@ module Async
61
62
  end
62
63
  end
63
64
 
64
- def wrap_response(response)
65
- if body = response.body
66
- response.body = Parser.new(body)
67
- end
68
- end
69
-
70
- def process_response(request, response)
65
+ def parser_for(response)
71
66
  if content_type = response.headers['content-type']
72
67
  if content_type.start_with? @content_type
73
- wrap_response(response)
74
- else
75
- raise Error, "Unknown content type: #{content_type}!"
68
+ return Parser
76
69
  end
77
70
  end
78
71
 
79
- return response
72
+ return super
80
73
  end
81
74
  end
82
75
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
4
  #
3
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -37,7 +39,7 @@ module Async
37
39
 
38
40
  attr :content_type
39
41
 
40
- def split(*args)
42
+ def split(*arguments)
41
43
  @content_type.split
42
44
  end
43
45
 
@@ -59,22 +61,14 @@ module Async
59
61
  end
60
62
  end
61
63
 
62
- def wrap_response(response)
63
- if body = response.body
64
- response.body = Parser.new(body)
65
- end
66
- end
67
-
68
- def process_response(request, response)
64
+ def parser_for(response)
69
65
  if content_type = response.headers['content-type']
70
66
  if content_type.start_with? @content_type
71
- wrap_response(response)
72
- else
73
- raise Error, "Unknown content type: #{content_type}!"
67
+ return Parser
74
68
  end
75
69
  end
76
70
 
77
- return response
71
+ return super
78
72
  end
79
73
  end
80
74
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-rest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.12.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-11 00:00:00.000000000 Z
11
+ date: 2021-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-http
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.1'
55
55
  - !ruby/object:Gem::Dependency
56
- name: covered
56
+ name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: bundler
70
+ name: covered
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -81,61 +81,53 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rspec
84
+ name: rake
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: '3.6'
89
+ version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: '3.6'
96
+ version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: rake
98
+ name: rspec
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ">="
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '0'
103
+ version: '3.6'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ">="
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
111
- description:
110
+ version: '3.6'
111
+ description:
112
112
  email:
113
- - samuel.williams@oriontransfer.co.nz
114
113
  executables: []
115
114
  extensions: []
116
115
  extra_rdoc_files: []
117
116
  files:
118
- - ".editorconfig"
119
- - ".gitignore"
120
- - ".rspec"
121
- - ".travis.yml"
122
- - Gemfile
123
- - README.md
124
- - Rakefile
125
- - async-rest.gemspec
126
- - examples/slack/clean.rb
127
117
  - lib/async/rest.rb
128
118
  - lib/async/rest/error.rb
129
119
  - lib/async/rest/representation.rb
130
120
  - lib/async/rest/resource.rb
131
121
  - lib/async/rest/version.rb
122
+ - lib/async/rest/wrapper/form.rb
132
123
  - lib/async/rest/wrapper/generic.rb
133
124
  - lib/async/rest/wrapper/json.rb
134
125
  - lib/async/rest/wrapper/url_encoded.rb
135
126
  homepage: https://github.com/socketry/async-rest
136
- licenses: []
127
+ licenses:
128
+ - MIT
137
129
  metadata: {}
138
- post_install_message:
130
+ post_install_message:
139
131
  rdoc_options: []
140
132
  require_paths:
141
133
  - lib
@@ -150,8 +142,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
142
  - !ruby/object:Gem::Version
151
143
  version: '0'
152
144
  requirements: []
153
- rubygems_version: 3.0.3
154
- signing_key:
145
+ rubygems_version: 3.3.0.dev
146
+ signing_key:
155
147
  specification_version: 4
156
148
  summary: A library for RESTful clients (and hopefully servers).
157
149
  test_files: []
data/.editorconfig DELETED
@@ -1,6 +0,0 @@
1
- root = true
2
-
3
- [*]
4
- indent_style = tab
5
- indent_size = 2
6
-
data/.gitignore DELETED
@@ -1,12 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
-
11
- # rspec failure tracking
12
- .rspec_status
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --warnings
3
- --require spec_helper
data/.travis.yml DELETED
@@ -1,19 +0,0 @@
1
- language: ruby
2
- dist: xenial
3
- cache: bundler
4
-
5
- matrix:
6
- include:
7
- - rvm: 2.4
8
- - rvm: 2.5
9
- - rvm: 2.6
10
- - rvm: jruby-head
11
- env: JRUBY_OPTS="--debug -X+O"
12
- - rvm: truffleruby
13
- - rvm: ruby-head
14
- - rvm: rbx-3
15
- allow_failures:
16
- - rvm: ruby-head
17
- - rvm: jruby-head
18
- - rvm: rbx-3
19
- - rvm: truffleruby
data/Gemfile DELETED
@@ -1,8 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in async-io.gemspec
4
- gemspec
5
-
6
- group :development do
7
- gem 'pry'
8
- end
data/README.md DELETED
@@ -1,106 +0,0 @@
1
- # Async::REST
2
-
3
- Roy Thomas Fielding's thesis [Architectural Styles and the Design of Network-based Software Architectures](https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm) describes [Representational State Transfer](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm) which comprises several core concepts:
4
-
5
- - `Resource`: A conceptual mapping to one or more entities.
6
- - `Representation`: An instance of a resource at a given point in time.
7
-
8
- This gem models these abstractions as closely and practically as possible and serves as a basis for building asynchronous web clients.
9
-
10
- [![Build Status](https://secure.travis-ci.org/socketry/async-rest.svg)](http://travis-ci.org/socketry/async-rest)
11
- [![Code Climate](https://codeclimate.com/github/socketry/async-rest.svg)](https://codeclimate.com/github/socketry/async-rest)
12
- [![Coverage Status](https://coveralls.io/repos/socketry/async-rest/badge.svg)](https://coveralls.io/r/socketry/async-rest)
13
-
14
- [async]: https://github.com/socketry/async
15
- [async-io]: https://github.com/socketry/async-io
16
- [falcon]: https://github.com/socketry/falcon
17
-
18
- ## Installation
19
-
20
- Add this line to your application's Gemfile:
21
-
22
- ```ruby
23
- gem 'async-rest'
24
- ```
25
-
26
- And then execute:
27
-
28
- $ bundle
29
-
30
- Or install it yourself as:
31
-
32
- $ gem install async-rest
33
-
34
- ## Usage
35
-
36
- Generally speaking, you want to create a representation class for each endpoint. This class is responsible for negotiating content type and processing the response, and traversing related endpoints.
37
-
38
- ### DNS over HTTP
39
-
40
- This simple example shows how to use a custom representation to access DNS over HTTP.
41
-
42
- ```ruby
43
- require 'async/http/server'
44
- require 'async/http/endpoint'
45
-
46
- require 'async/rest/resource'
47
- require 'async/rest/representation'
48
-
49
- module DNS
50
- class Query < Async::REST::Representation
51
- def initialize(*args)
52
- # This is the old/weird content-type used by Google's DNS resolver. It's obsolete.
53
- super(*args, wrapper: Async::REST::Wrapper::JSON.new("application/x-javascript"))
54
- end
55
-
56
- def question
57
- value[:Question]
58
- end
59
-
60
- def answer
61
- value[:Answer]
62
- end
63
- end
64
- end
65
-
66
- URL = 'https://dns.google.com/resolve'
67
- Async::REST::Resource.for(URL) do |resource|
68
- # Specify the representation class as the first argument (client side negotiation):
69
- query = resource.get(DNS::Query, name: 'example.com', type: 'AAAA')
70
-
71
- pp query.metadata
72
- pp query.value
73
- end
74
- ```
75
-
76
- ## Contributing
77
-
78
- 1. Fork it
79
- 2. Create your feature branch (`git checkout -b my-new-feature`)
80
- 3. Commit your changes (`git commit -am 'Add some feature'`)
81
- 4. Push to the branch (`git push origin my-new-feature`)
82
- 5. Create new Pull Request
83
-
84
- ## License
85
-
86
- Released under the MIT license.
87
-
88
- Copyright, 2015, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
89
-
90
- Permission is hereby granted, free of charge, to any person obtaining a copy
91
- of this software and associated documentation files (the "Software"), to deal
92
- in the Software without restriction, including without limitation the rights
93
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
94
- copies of the Software, and to permit persons to whom the Software is
95
- furnished to do so, subject to the following conditions:
96
-
97
- The above copyright notice and this permission notice shall be included in
98
- all copies or substantial portions of the Software.
99
-
100
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
101
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
102
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
103
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
104
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
105
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
106
- THE SOFTWARE.
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:test)
5
-
6
- task :default => :test
data/async-rest.gemspec DELETED
@@ -1,28 +0,0 @@
1
- # coding: utf-8
2
- require_relative 'lib/async/rest/version'
3
-
4
- Gem::Specification.new do |spec|
5
- spec.name = "async-rest"
6
- spec.version = Async::REST::VERSION
7
- spec.authors = ["Samuel Williams"]
8
- spec.email = ["samuel.williams@oriontransfer.co.nz"]
9
-
10
- spec.summary = "A library for RESTful clients (and hopefully servers)."
11
- spec.homepage = "https://github.com/socketry/async-rest"
12
-
13
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
14
- f.match(%r{^(test|spec|features)/})
15
- end
16
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
- spec.require_paths = ["lib"]
18
-
19
- spec.add_dependency "async-http", "~> 0.42"
20
- spec.add_dependency "protocol-http", "~> 0.7"
21
-
22
- spec.add_development_dependency "async-rspec", "~> 1.1"
23
-
24
- spec.add_development_dependency "covered"
25
- spec.add_development_dependency "bundler"
26
- spec.add_development_dependency "rspec", "~> 3.6"
27
- spec.add_development_dependency "rake"
28
- end
@@ -1,56 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'pry'
4
- require 'set'
5
-
6
- def rate_limited?(response)
7
- pp response
8
-
9
- response[:error] == "ratelimited"
10
- end
11
-
12
- require 'async/rest'
13
-
14
- URL = "https://slack.com/api"
15
- TOKEN = "xoxp-your-api-token"
16
-
17
- Async::REST::Resource.for(URL) do |resource|
18
- authenticated = resource.with(parameters: {token: TOKEN})
19
- delete = authenticated.with(path: "chat.delete")
20
-
21
- page = 1
22
- while true
23
- search = authenticated.with(path: "search.messages", parameters: {page: page, count: 100, query: "from:@username before:2019-02-15"})
24
- representation = search.get
25
-
26
- messages = representation.value[:messages]
27
- matches = messages[:matches]
28
-
29
- puts "Found #{matches.size} messages on page #{page} out of #{messages[:total]}..."
30
-
31
- break if matches.empty?
32
-
33
- matches.each do |message|
34
- text = message[:text]
35
- channel_id = message[:channel][:id]
36
- channel_name = message[:channel][:name]
37
- timestamp = message[:ts]
38
-
39
- pp [timestamp, channel_name, text]
40
-
41
- message_delete = Async::REST::Representation.new(
42
- delete.with(parameters: {channel: channel_id, ts: timestamp})
43
- )
44
-
45
- response = message_delete.post
46
- if rate_limited?(response.read)
47
- puts "Rate limiting..."
48
- Async::Task.current.sleep 10
49
- end
50
- end
51
-
52
- page += 1
53
- end
54
- end
55
-
56
- puts "Done"