async-rest 0.12.2 → 0.12.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/async/rest/representation.rb +9 -5
- data/lib/async/rest/resource.rb +6 -8
- data/lib/async/rest/version.rb +1 -1
- data/lib/async/rest/wrapper/json.rb +1 -1
- data/lib/async/rest/wrapper/url_encoded.rb +1 -1
- metadata +19 -31
- data/.editorconfig +0 -6
- data/.gitignore +0 -12
- data/.rspec +0 -3
- data/.travis.yml +0 -20
- data/Gemfile +0 -10
- data/README.md +0 -106
- data/Rakefile +0 -8
- data/async-rest.gemspec +0 -29
- data/examples/github/feed.rb +0 -112
- data/examples/slack/clean.rb +0 -57
- data/examples/xkcd/comic.rb +0 -65
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc914b22fd6a8a19da71676f835e23a606b8c9e6ebd981f25b17b9452422a791
|
4
|
+
data.tar.gz: d639c6647805c99501b9849ee4ebdc3a1650279b93b5053f00af513cb75c2e6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2fe066c918388cd94e92ba167f0910fd189991abb14565172946f74f9d8af3f24f66c18cef586a0b41a87d19c036af08da227404954f5619c313b1273fe64025
|
7
|
+
data.tar.gz: fe5226f20eb31178830ff77f37df8d03c0d3f66c0edc098ed700fcf7f394fee9ba4452cca6190e21c153390915227df23d7e29017e506f9c18f7e19000be33f5
|
@@ -31,15 +31,15 @@ module Async
|
|
31
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.
|
32
32
|
class Representation
|
33
33
|
def self.[] wrapper
|
34
|
-
klass = Class.new(
|
34
|
+
klass = Class.new(self)
|
35
35
|
|
36
36
|
klass.const_set(:WRAPPER, wrapper)
|
37
37
|
|
38
38
|
return klass
|
39
39
|
end
|
40
40
|
|
41
|
-
def self.for(*
|
42
|
-
representation = self.new(Resource.for(*
|
41
|
+
def self.for(*arguments, **options)
|
42
|
+
representation = self.new(Resource.for(*arguments), **options)
|
43
43
|
|
44
44
|
return representation unless block_given?
|
45
45
|
|
@@ -66,8 +66,12 @@ module Async
|
|
66
66
|
@value = value
|
67
67
|
end
|
68
68
|
|
69
|
-
def with(klass =
|
70
|
-
klass
|
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
|
71
75
|
end
|
72
76
|
|
73
77
|
def [] **parameters
|
data/lib/async/rest/resource.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
# Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
4
2
|
#
|
5
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
@@ -48,7 +46,7 @@ module Async
|
|
48
46
|
return ::Protocol::HTTP::AcceptEncoding.new(HTTP::Client.new(endpoint)), reference
|
49
47
|
end
|
50
48
|
|
51
|
-
def self.for(endpoint, *
|
49
|
+
def self.for(endpoint, *arguments)
|
52
50
|
# TODO This behaviour is deprecated and will probably be removed.
|
53
51
|
if endpoint.is_a? String
|
54
52
|
endpoint = HTTP::Endpoint.parse(endpoint)
|
@@ -56,7 +54,7 @@ module Async
|
|
56
54
|
|
57
55
|
client, reference = connect(endpoint)
|
58
56
|
|
59
|
-
resource = self.new(client, reference, *
|
57
|
+
resource = self.new(client, reference, *arguments)
|
60
58
|
|
61
59
|
return resource unless block_given?
|
62
60
|
|
@@ -72,14 +70,14 @@ module Async
|
|
72
70
|
attr :reference
|
73
71
|
attr :headers
|
74
72
|
|
75
|
-
def self.with(parent, *
|
73
|
+
def self.with(parent, *arguments, headers: {}, **options)
|
76
74
|
reference = parent.reference.with(**options)
|
77
75
|
|
78
|
-
self.new(*
|
76
|
+
self.new(*arguments, parent.delegate, reference, parent.headers.merge(headers))
|
79
77
|
end
|
80
78
|
|
81
|
-
def with(*
|
82
|
-
self.class.with(self, *
|
79
|
+
def with(*arguments, **options)
|
80
|
+
self.class.with(self, *arguments, **options)
|
83
81
|
end
|
84
82
|
|
85
83
|
def get(klass = Representation, **parameters)
|
data/lib/async/rest/version.rb
CHANGED
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.12.
|
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:
|
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:
|
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:
|
70
|
+
name: covered
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -81,51 +81,39 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rake
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
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: '
|
96
|
+
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: rspec
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
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: '
|
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/github/feed.rb
|
127
|
-
- examples/slack/clean.rb
|
128
|
-
- examples/xkcd/comic.rb
|
129
117
|
- lib/async/rest.rb
|
130
118
|
- lib/async/rest/error.rb
|
131
119
|
- lib/async/rest/representation.rb
|
@@ -139,7 +127,7 @@ homepage: https://github.com/socketry/async-rest
|
|
139
127
|
licenses:
|
140
128
|
- MIT
|
141
129
|
metadata: {}
|
142
|
-
post_install_message:
|
130
|
+
post_install_message:
|
143
131
|
rdoc_options: []
|
144
132
|
require_paths:
|
145
133
|
- lib
|
@@ -154,8 +142,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
142
|
- !ruby/object:Gem::Version
|
155
143
|
version: '0'
|
156
144
|
requirements: []
|
157
|
-
rubygems_version: 3.0.
|
158
|
-
signing_key:
|
145
|
+
rubygems_version: 3.3.0.dev
|
146
|
+
signing_key:
|
159
147
|
specification_version: 4
|
160
148
|
summary: A library for RESTful clients (and hopefully servers).
|
161
149
|
test_files: []
|
data/.editorconfig
DELETED
data/.gitignore
DELETED
data/.rspec
DELETED
data/.travis.yml
DELETED
@@ -1,20 +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: 2.7
|
11
|
-
- rvm: 2.6
|
12
|
-
env: COVERAGE=PartialSummary,Coveralls
|
13
|
-
- rvm: jruby-head
|
14
|
-
env: JRUBY_OPTS="--debug -X+O"
|
15
|
-
- rvm: truffleruby
|
16
|
-
- rvm: ruby-head
|
17
|
-
allow_failures:
|
18
|
-
- rvm: truffleruby
|
19
|
-
- rvm: ruby-head
|
20
|
-
- rvm: jruby-head
|
data/Gemfile
DELETED
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://travis-ci.com/socketry/async-rest.svg?branch=master)](https://travis-ci.com/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 remote resource. This class is responsible for negotiating content type and processing the response, and traversing related resources.
|
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
data/async-rest.gemspec
DELETED
@@ -1,29 +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.licenses = ["MIT"]
|
8
|
-
spec.authors = ["Samuel Williams"]
|
9
|
-
spec.email = ["samuel.williams@oriontransfer.co.nz"]
|
10
|
-
|
11
|
-
spec.summary = "A library for RESTful clients (and hopefully servers)."
|
12
|
-
spec.homepage = "https://github.com/socketry/async-rest"
|
13
|
-
|
14
|
-
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
15
|
-
f.match(%r{^(test|spec|features)/})
|
16
|
-
end
|
17
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
-
spec.require_paths = ["lib"]
|
19
|
-
|
20
|
-
spec.add_dependency "async-http", "~> 0.42"
|
21
|
-
spec.add_dependency "protocol-http", "~> 0.7"
|
22
|
-
|
23
|
-
spec.add_development_dependency "async-rspec", "~> 1.1"
|
24
|
-
|
25
|
-
spec.add_development_dependency "covered"
|
26
|
-
spec.add_development_dependency "bundler"
|
27
|
-
spec.add_development_dependency "rspec", "~> 3.6"
|
28
|
-
spec.add_development_dependency "rake"
|
29
|
-
end
|
data/examples/github/feed.rb
DELETED
@@ -1,112 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'async'
|
5
|
-
require 'async/rest'
|
6
|
-
require 'async/rest/wrapper/form'
|
7
|
-
|
8
|
-
require 'date'
|
9
|
-
|
10
|
-
URL = "https://api.github.com"
|
11
|
-
ENDPOINT = Async::HTTP::Endpoint.parse(URL)
|
12
|
-
|
13
|
-
module GitHub
|
14
|
-
class Wrapper < Async::REST::Wrapper::Form
|
15
|
-
DEFAULT_CONTENT_TYPES = {
|
16
|
-
"application/vnd.github.v3+json" => Async::REST::Wrapper::JSON::Parser
|
17
|
-
}
|
18
|
-
|
19
|
-
def initialize
|
20
|
-
super(DEFAULT_CONTENT_TYPES)
|
21
|
-
end
|
22
|
-
|
23
|
-
def parser_for(response)
|
24
|
-
if content_type = response.headers['content-type']
|
25
|
-
if content_type.start_with? "application/json"
|
26
|
-
return Async::REST::Wrapper::JSON::Parser
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
return super
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
class Representation < Async::REST::Representation[Wrapper]
|
35
|
-
end
|
36
|
-
|
37
|
-
class User < Representation
|
38
|
-
end
|
39
|
-
|
40
|
-
class Client < Representation
|
41
|
-
def user(name)
|
42
|
-
self.with(User, path: "users/#{name}")
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
module Paginate
|
47
|
-
include Enumerable
|
48
|
-
|
49
|
-
def represent(metadata, attributes)
|
50
|
-
resource = @resource.with(path: attributes[:id])
|
51
|
-
|
52
|
-
representation.new(resource, metadata: metadata, value: attributes)
|
53
|
-
end
|
54
|
-
|
55
|
-
def each(page: 1, per_page: 50, **parameters)
|
56
|
-
return to_enum(:each, page: page, per_page: per_page, **parameters) unless block_given?
|
57
|
-
|
58
|
-
while true
|
59
|
-
items = @resource.get(self.class, page: page, per_page: per_page, **parameters)
|
60
|
-
|
61
|
-
break if items.empty?
|
62
|
-
|
63
|
-
Array(items.value).each do |item|
|
64
|
-
yield represent(items.metadata, item)
|
65
|
-
end
|
66
|
-
|
67
|
-
page += 1
|
68
|
-
|
69
|
-
# Was this the last page?
|
70
|
-
break if items.value.size < per_page
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def empty?
|
75
|
-
self.value.empty?
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
class Event < Representation
|
80
|
-
def created_at
|
81
|
-
DateTime.parse(value[:created_at])
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
class Events < Representation
|
86
|
-
include Paginate
|
87
|
-
|
88
|
-
def representation
|
89
|
-
Event
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
class User < Representation
|
94
|
-
def public_events
|
95
|
-
self.with(Events, path: "events/public")
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
puts "Connecting..."
|
101
|
-
headers = Protocol::HTTP::Headers.new
|
102
|
-
headers['user-agent'] = "async-rest/GitHub v#{Async::REST::VERSION}"
|
103
|
-
|
104
|
-
GitHub::Client.for(ENDPOINT, headers) do |client|
|
105
|
-
user = client.user("ioquatix")
|
106
|
-
|
107
|
-
events = user.public_events.to_a
|
108
|
-
pp events.first.created_at
|
109
|
-
pp events.last.created_at
|
110
|
-
end
|
111
|
-
|
112
|
-
puts "done"
|
data/examples/slack/clean.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'pry'
|
5
|
-
require 'set'
|
6
|
-
|
7
|
-
def rate_limited?(response)
|
8
|
-
pp response
|
9
|
-
|
10
|
-
response[:error] == "ratelimited"
|
11
|
-
end
|
12
|
-
|
13
|
-
require 'async/rest'
|
14
|
-
|
15
|
-
URL = "https://slack.com/api"
|
16
|
-
TOKEN = "xoxp-your-api-token"
|
17
|
-
|
18
|
-
Async::REST::Resource.for(URL) do |resource|
|
19
|
-
authenticated = resource.with(parameters: {token: TOKEN})
|
20
|
-
delete = authenticated.with(path: "chat.delete")
|
21
|
-
|
22
|
-
page = 1
|
23
|
-
while true
|
24
|
-
search = authenticated.with(path: "search.messages", parameters: {page: page, count: 100, query: "from:@username before:2019-02-15"})
|
25
|
-
representation = search.get
|
26
|
-
|
27
|
-
messages = representation.value[:messages]
|
28
|
-
matches = messages[:matches]
|
29
|
-
|
30
|
-
puts "Found #{matches.size} messages on page #{page} out of #{messages[:total]}..."
|
31
|
-
|
32
|
-
break if matches.empty?
|
33
|
-
|
34
|
-
matches.each do |message|
|
35
|
-
text = message[:text]
|
36
|
-
channel_id = message[:channel][:id]
|
37
|
-
channel_name = message[:channel][:name]
|
38
|
-
timestamp = message[:ts]
|
39
|
-
|
40
|
-
pp [timestamp, channel_name, text]
|
41
|
-
|
42
|
-
message_delete = Async::REST::Representation.new(
|
43
|
-
delete.with(parameters: {channel: channel_id, ts: timestamp})
|
44
|
-
)
|
45
|
-
|
46
|
-
response = message_delete.post
|
47
|
-
if rate_limited?(response.read)
|
48
|
-
puts "Rate limiting..."
|
49
|
-
Async::Task.current.sleep 10
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
page += 1
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
puts "Done"
|
data/examples/xkcd/comic.rb
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require_relative '../../lib/async/rest'
|
5
|
-
require_relative '../../lib/async/rest/wrapper/url_encoded'
|
6
|
-
|
7
|
-
require 'nokogiri'
|
8
|
-
|
9
|
-
Async.logger.debug!
|
10
|
-
|
11
|
-
module XKCD
|
12
|
-
module Wrapper
|
13
|
-
# This defines how we interact with the XKCD service.
|
14
|
-
class HTML < Async::REST::Wrapper::URLEncoded
|
15
|
-
TEXT_HTML = "text/html"
|
16
|
-
|
17
|
-
# How to process the response body.
|
18
|
-
class Parser < ::Protocol::HTTP::Body::Wrapper
|
19
|
-
def join
|
20
|
-
Nokogiri::HTML(super)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# We wrap the response body with the parser (it could incrementally parse the body).
|
25
|
-
def wrap_response(response)
|
26
|
-
if body = response.body
|
27
|
-
response.body = Parser.new(body)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def process_response(request, response)
|
32
|
-
if content_type = response.headers['content-type']
|
33
|
-
if content_type.start_with? TEXT_HTML
|
34
|
-
wrap_response(response)
|
35
|
-
else
|
36
|
-
raise Error, "Unknown content type: #{content_type}!"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
return response
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# A comic representation.
|
46
|
-
class Comic < Async::REST::Representation[Wrapper::HTML]
|
47
|
-
def image_url
|
48
|
-
self.value.css("#comic img").attribute("src").text
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
Async do
|
54
|
-
URL = 'https://xkcd.com/'
|
55
|
-
|
56
|
-
Async::REST::Resource.for(URL) do |resource|
|
57
|
-
(2000..2010).each do |id|
|
58
|
-
Async do
|
59
|
-
representation = resource.with(path: "/#{id}/").get(XKCD::Comic)
|
60
|
-
|
61
|
-
p representation.image_url
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|