brutalismbot 0.1.1 → 0.2.0

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: 7dbe0c2ce29ee2c8169e733c62706340465aaa1307e608f2e84888c4181e1b6b
4
- data.tar.gz: a756eafc6077d900bde350dea0782b14ec988aacd0421f6b871d0c7ddedf83fb
3
+ metadata.gz: b1836d2eecd6d94c8d170223f7c8da3bbfe87909154d82492716d3ac1b3b411e
4
+ data.tar.gz: 825519ee45d36652e631310c38c0ce246c9e08e0f86987c4bfa42cc6345daa8a
5
5
  SHA512:
6
- metadata.gz: 427d8332a5df819072e2932227836aa8a1c62163261f711d070ca89cf745e4ab2dc8510326d2d15e82a6bc8c802fd350630b3614f4e8943a46fcdf75cfbce608
7
- data.tar.gz: e0ffb4aa085e92b6a6fafa2a0930992fd0ab9938ff7df3b36bb77dfce10766be0c78faefc2bee37fce66734f5ee7b6be2788e4f1b894f4c59ab83c083ae63707
6
+ metadata.gz: baed1a146152eb80401cbd75fd2e5265cd99fae63fb588db1ca66e233e52de8c06c6460abd099b6f046b4436923496d94bb7867b645382c81ec8857f9fb1a9f7
7
+ data.tar.gz: dde3ca496744cdf5e45c41be689c36587570c3cb4b79d7998a82d3ad002bc79e5e601aa09f21e246bc40bef00d46b2ec4b8affdc8595135f2ccac4cd5bd11617
data/README.md CHANGED
@@ -1,39 +1,50 @@
1
- # Brutalismbot
1
+ <img alt="brutalismbot" src="https://brutalismbot.com/banner.png"/>
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/brutalismbot`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ [![Gem Version](https://badge.fury.io/rb/brutalismbot.svg)](http://badge.fury.io/rb/brutalismbot)
4
+ [![Build Status](https://travis-ci.com/brutalismbot/gem.svg)](https://travis-ci.com/brutalismbot/gem)
5
+ [![codecov](https://codecov.io/gh/brutalismbot/gem/branch/master/graph/badge.svg)](https://codecov.io/gh/brutalismbot/gem)
4
6
 
5
- TODO: Delete this and the text above, and describe your gem
7
+ Brutalismbot RubyGem
6
8
 
7
9
  ## Installation
8
10
 
9
- Add this line to your application's Gemfile:
10
-
11
11
  ```ruby
12
- gem 'brutalismbot'
12
+ gem install brutalismbot
13
13
  ```
14
14
 
15
- And then execute:
16
-
17
- $ bundle
15
+ ## Usage
18
16
 
19
- Or install it yourself as:
17
+ ```ruby
18
+ require "aws-sdk-s3"
19
+ require "brutalismbot"
20
20
 
21
- $ gem install brutalismbot
21
+ bucket = Aws::S3::Bucket.new name: "my-bucket"
22
+ brutbot = Brutalismbot::S3::Client.new bucket: bucket,
23
+ prefix: "my/prefix/"
22
24
 
23
- ## Usage
25
+ # Get new posts after a given time
26
+ brutbot.subreddit.new_posts.after Time.parse("2019-06-01 12:00:00Z")
24
27
 
25
- TODO: Write usage instructions here
28
+ # Get current top post
29
+ brutbot.subreddit.top_post
26
30
 
27
- ## Development
31
+ # Get latest cached post
32
+ brutbot.posts.latest
28
33
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
-
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
34
+ # Get max key in posts
35
+ brutbot.posts.max_key
36
+ ```
32
37
 
33
38
  ## Contributing
34
39
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/brutalismbot.
40
+ Bug reports and pull requests are welcome on [GitHub](https://github.com/brutalismbot/gem).
36
41
 
37
42
  ## License
38
43
 
39
44
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
45
+
46
+ ### See Also
47
+
48
+ - [Brutalismbot API](https://github.com/brutalismbot/api)
49
+ - [Brutalismbot App](https://github.com/brutalismbot/brutalismbot)
50
+ - [Brutalismbot Monitoring](https://github.com/brutalismbot/monitoring)
@@ -1,112 +1,53 @@
1
- module R
2
- class Subreddit
3
- def initialize(endpoint:nil, user_agent:nil)
4
- @endpoint = endpoint
5
- @user_agent = user_agent
6
- end
7
-
8
- def new_posts(**params)
9
- url = File.join @endpoint, "new.json"
10
- qry = URI.encode_www_form params
11
- uri = URI.parse "#{url}?#{qry}"
12
- PostCollection.new uri: uri, user_agent: @user_agent
13
- end
1
+ module Brutalismbot
2
+ module R
3
+ class Subreddit
4
+ attr_reader :endpoint, :user_agent
14
5
 
15
- def top_post(**params)
16
- url = File.join @endpoint, "top.json"
17
- qry = URI.encode_www_form params
18
- uri = URI.parse "#{url}?#{qry}"
19
- PostCollection.new(uri: uri, user_agent: @user_agent).each do |post|
20
- break post unless post.url.nil?
6
+ def initialize(endpoint:nil, user_agent:nil)
7
+ @endpoint = endpoint
8
+ @user_agent = user_agent
21
9
  end
22
- end
23
- end
24
-
25
- class PostCollection
26
- include Enumerable
27
-
28
- def initialize(uri:, user_agent:, min_time:nil)
29
- @uri = uri
30
- @ssl = uri.scheme == "https"
31
- @user_agent = user_agent
32
- @min_time = min_time.to_i
33
- end
34
-
35
- def after(time)
36
- PostCollection.new uri: @uri, user_agent: @user_agent, min_time: time
37
- end
38
10
 
39
- def each
40
- puts "GET #{@uri}"
41
- Net::HTTP.start(@uri.host, @uri.port, use_ssl: @ssl) do |http|
42
- request = Net::HTTP::Get.new @uri, "user-agent" => @user_agent
43
- response = JSON.parse http.request(request).body
44
- children = response.dig("data", "children") || []
45
- children.reverse.each do |child|
46
- post = R::Brutalism::Post[child]
47
- yield post if post.created_after @min_time
48
- end
11
+ def posts(resource, **params)
12
+ url = File.join @endpoint, "#{resource}.json"
13
+ qry = URI.encode_www_form params
14
+ uri = URI.parse "#{url}?#{qry}"
15
+ PostCollection.new uri: uri, user_agent: @user_agent
49
16
  end
50
17
  end
51
- end
52
-
53
- class Brutalism < Subreddit
54
- def initialize(endpoint:nil, user_agent:nil)
55
- super endpoint: endpoint || "https://www.reddit.com/r/brutalism",
56
- user_agent: user_agent || "Brutalismbot #{Brutalismbot::VERSION}"
57
- end
58
-
59
- class Post < Hash
60
- def created_after(time)
61
- created_utc.to_i > time.to_i
62
- end
63
18
 
64
- def created_utc
65
- Time.at(dig("data", "created_utc").to_i).utc
66
- end
19
+ class PostCollection
20
+ include Enumerable
67
21
 
68
- def permalink
69
- dig "data", "permalink"
22
+ def initialize(uri:, user_agent:, min_time:nil)
23
+ @uri = uri
24
+ @ssl = uri.scheme == "https"
25
+ @user_agent = user_agent
26
+ @min_time = min_time.to_i
70
27
  end
71
28
 
72
- def title
73
- dig "data", "title"
29
+ def each
30
+ Brutalismbot.logger.info "GET #{@uri}"
31
+ Net::HTTP.start(@uri.host, @uri.port, use_ssl: @ssl) do |http|
32
+ request = Net::HTTP::Get.new @uri, "user-agent" => @user_agent
33
+ response = JSON.parse http.request(request).body
34
+ children = response.dig("data", "children") || []
35
+ children.reverse.each do |child|
36
+ post = Brutalismbot::Post[child]
37
+ yield post if post.created_after time: @min_time
38
+ end
39
+ end
74
40
  end
75
41
 
76
- def to_slack
77
- {
78
- blocks: [
79
- {
80
- type: "image",
81
- title: {
82
- type: "plain_text",
83
- text: "/r/brutalism",
84
- emoji: true,
85
- },
86
- image_url: url,
87
- alt_text: title,
88
- },
89
- {
90
- type: "context",
91
- elements: [
92
- {
93
- type: "mrkdwn",
94
- text: "<https://reddit.com#{permalink}|#{title}>",
95
- },
96
- ],
97
- },
98
- ],
99
- }
42
+ def since(time:)
43
+ PostCollection.new uri: @uri, user_agent: @user_agent, min_time: time
100
44
  end
45
+ end
101
46
 
102
- def url
103
- images = dig "data", "preview", "images"
104
- source = images.map{|x| x["source"] }.compact.max do |a,b|
105
- a.slice("width", "height").values <=> b.slice("width", "height").values
106
- end
107
- CGI.unescapeHTML source.dig("url")
108
- rescue NoMethodError
109
- dig("data", "media_metadata")&.values&.first&.dig("s", "u")
47
+ class Brutalism < Subreddit
48
+ def initialize(endpoint:nil, user_agent:nil)
49
+ super endpoint: endpoint || "https://www.reddit.com/r/brutalism",
50
+ user_agent: user_agent || "Brutalismbot #{Brutalismbot::VERSION}"
110
51
  end
111
52
  end
112
53
  end
@@ -1,39 +1,17 @@
1
1
  module Brutalismbot
2
2
  module S3
3
- class Client
4
- VERSION = "v1"
5
-
6
- def initialize(bucket:, prefix:nil)
7
- @bucket = bucket
8
- @prefix = prefix
9
- end
10
-
11
- def subreddit(endpoint:nil, user_agent:nil)
12
- R::Brutalism.new endpoint: endpoint,
13
- user_agent: user_agent
14
- end
15
-
16
- def auths
17
- AuthCollection.new bucket: @bucket,
18
- prefix: "#{@prefix}oauth/#{VERSION}/"
19
- end
20
-
21
- def posts
22
- PostCollection.new bucket: @bucket,
23
- prefix: "#{@prefix}posts/#{VERSION}/"
24
- end
25
- end
26
-
27
3
  class Collection
28
4
  include Enumerable
29
5
 
30
- def initialize(bucket:, prefix:)
6
+ attr_reader :bucket, :prefix
7
+
8
+ def initialize(bucket:, prefix:nil)
31
9
  @bucket = bucket
32
10
  @prefix = prefix
33
11
  end
34
12
 
35
13
  def each
36
- puts "GET s3://#{@bucket.name}/#{@prefix}*"
14
+ Brutalismbot.logger.info "GET s3://#{@bucket.name}/#{@prefix}*"
37
15
  @bucket.objects(prefix: @prefix).each do |object|
38
16
  yield object
39
17
  end
@@ -41,37 +19,52 @@ module Brutalismbot
41
19
 
42
20
  def put(body:, key:, dryrun:nil)
43
21
  if dryrun
44
- puts "PUT DRYRUN s3://#{@bucket.name}/#{key}"
22
+ Brutalismbot.logger.info "PUT DRYRUN s3://#{@bucket.name}/#{key}"
45
23
  else
46
- puts "PUT s3://#{@bucket.name}/#{key}"
24
+ Brutalismbot.logger.info "PUT s3://#{@bucket.name}/#{key}"
47
25
  @bucket.put_object key: key, body: body
48
26
  end
27
+ end
28
+ end
49
29
 
50
- {bucket: @bucket.name, key: key}
30
+ class Client < Collection
31
+ def subreddit(endpoint:nil, user_agent:nil)
32
+ Brutalismbot::R::Brutalism.new endpoint:endpoint, user_agent: user_agent
33
+ end
34
+
35
+ def auths
36
+ AuthCollection.new bucket: @bucket, prefix: "#{@prefix}auths/"
37
+ end
38
+
39
+ def posts
40
+ PostCollection.new bucket: @bucket, prefix: "#{@prefix}posts/"
51
41
  end
52
42
  end
53
43
 
54
44
  class AuthCollection < Collection
55
45
  def each
56
46
  super do |object|
57
- yield Brutalismbot::OAuth[JSON.parse object.get.body.read]
47
+ yield Brutalismbot::Auth[JSON.parse object.get.body.read]
58
48
  end
59
49
  end
60
50
 
61
- def delete(team_id:, dryrun:nil)
62
- prefix = "#{@prefix}team=#{team_id}/"
63
- puts "GET s3://#{@bucket.name}/#{prefix}*"
51
+ def remove(team:, dryrun:nil)
52
+ prefix = "#{@prefix}team=#{team}/"
53
+ Brutalismbot.logger.info "GET s3://#{@bucket.name}/#{prefix}*"
64
54
  @bucket.objects(prefix: prefix).map do |object|
65
55
  if dryrun
66
- puts "DELETE DRYRUN s3://#{@bucket.name}/#{object.key}"
67
- {bucket: @bucket.name, key: object.key}
56
+ Brutalismbot.logger.info "DELETE DRYRUN s3://#{@bucket.name}/#{object.key}"
68
57
  else
69
- puts "DELETE s3://#{@bucket.name}/#{object.key}"
58
+ Brutalismbot.logger.info "DELETE s3://#{@bucket.name}/#{object.key}"
70
59
  object.delete
71
60
  end
72
61
  end
73
62
  end
74
63
 
64
+ def mirror(body:, dryrun:nil)
65
+ map{|auth| auth.post body: body, dryrun: dryrun }
66
+ end
67
+
75
68
  def put(auth:, dryrun:nil)
76
69
  key = "#{@prefix}team=#{auth.team_id}/channel=#{auth.channel_id}/oauth.json"
77
70
  super key: key, body: auth.to_json, dryrun: dryrun
@@ -81,23 +74,23 @@ module Brutalismbot
81
74
  class PostCollection < Collection
82
75
  def each
83
76
  super do |object|
84
- yield R::Brutalism::Post[JSON.parse object.get.body.read]
77
+ yield Brutalismbot::Post[JSON.parse object.get.body.read]
85
78
  end
86
79
  end
87
80
 
88
81
  def latest
89
- R::Brutalism::Post[JSON.parse max_key.get.body.read]
82
+ Brutalismbot::Post[JSON.parse max_key.get.body.read]
90
83
  end
91
84
 
92
85
  def max_key
93
86
  # Dig for max key
94
- prefix = prefix_for Time.now.utc
95
- puts "GET s3://#{@bucket.name}/#{prefix}*"
87
+ prefix = prefix_for time: Time.now.utc
88
+ Brutalismbot.logger.info "GET s3://#{@bucket.name}/#{prefix}*"
96
89
 
97
90
  # Go up a level in prefix if no keys found
98
91
  until (keys = @bucket.objects(prefix: prefix)).any?
99
92
  prefix = prefix.split(/[^\/]+\/\z/).first
100
- puts "GET s3://#{@bucket.name}/#{prefix}*"
93
+ Brutalismbot.logger.info "GET s3://#{@bucket.name}/#{prefix}*"
101
94
  end
102
95
 
103
96
  # Return max by key
@@ -108,7 +101,7 @@ module Brutalismbot
108
101
  max_key.key.match(/(\d+).json\z/).to_a.last.to_i
109
102
  end
110
103
 
111
- def prefix_for(time)
104
+ def prefix_for(time:)
112
105
  time = Time.at(time.to_i).utc
113
106
  year = time.strftime '%Y'
114
107
  month = time.strftime '%Y-%m'
@@ -117,9 +110,13 @@ module Brutalismbot
117
110
  end
118
111
 
119
112
  def put(post:, dryrun:nil)
120
- key = "#{prefix_for post.created_utc}#{post.created_utc.to_i}.json"
113
+ key = "#{prefix_for time: post.created_utc}#{post.created_utc.to_i}.json"
121
114
  super key: key, body: post.to_json, dryrun: dryrun
122
115
  end
116
+
117
+ def update(posts:, dryrun:nil)
118
+ posts.map{|post| put post: post, dryrun: dryrun }
119
+ end
123
120
  end
124
121
  end
125
122
  end
@@ -1,3 +1,3 @@
1
1
  module Brutalismbot
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/brutalismbot.rb CHANGED
@@ -1,10 +1,114 @@
1
- require "brutalismbot/event"
2
- require "brutalismbot/oauth"
3
1
  require "brutalismbot/r"
4
2
  require "brutalismbot/s3"
5
3
  require "brutalismbot/version"
4
+ require "logger"
5
+ require "net/https"
6
6
 
7
7
  module Brutalismbot
8
+ class << self
9
+ @@config = {}
10
+ @@logger = Logger.new File::NULL
11
+
12
+ def config
13
+ @@config
14
+ end
15
+
16
+ def config=(config)
17
+ @@config = config || {}
18
+ end
19
+
20
+ def logger
21
+ config[:logger] || @@logger
22
+ end
23
+
24
+ def logger=(logger)
25
+ config[:logger] = logger
26
+ end
27
+ end
28
+
8
29
  class Error < StandardError
9
30
  end
31
+
32
+ class Auth < Hash
33
+ def channel_id
34
+ dig "incoming_webhook", "channel_id"
35
+ end
36
+
37
+ def post(body:, dryrun:nil)
38
+ uri = URI.parse webhook_url
39
+ ssl = uri.scheme == "https"
40
+ Net::HTTP.start(uri.host, uri.port, use_ssl: ssl) do |http|
41
+ if dryrun
42
+ Brutalismbot.logger&.info "POST DRYRUN #{uri}"
43
+ else
44
+ Brutalismbot.logger&.info "POST #{uri}"
45
+ req = Net::HTTP::Post.new uri, "content-type" => "application/json"
46
+ req.body = body
47
+ http.request req
48
+ end
49
+ end
50
+ end
51
+
52
+ def team_id
53
+ dig "team_id"
54
+ end
55
+
56
+ def webhook_url
57
+ dig "incoming_webhook", "url"
58
+ end
59
+ end
60
+
61
+ class Post < Hash
62
+ def created_after(time:)
63
+ created_utc.to_i > time.to_i
64
+ end
65
+
66
+ def created_utc
67
+ Time.at(dig("data", "created_utc").to_i).utc
68
+ end
69
+
70
+ def permalink
71
+ dig "data", "permalink"
72
+ end
73
+
74
+ def title
75
+ dig "data", "title"
76
+ end
77
+
78
+ def to_slack
79
+ {
80
+ blocks: [
81
+ {
82
+ type: "image",
83
+ title: {
84
+ type: "plain_text",
85
+ text: "/r/brutalism",
86
+ emoji: true,
87
+ },
88
+ image_url: url,
89
+ alt_text: title,
90
+ },
91
+ {
92
+ type: "context",
93
+ elements: [
94
+ {
95
+ type: "mrkdwn",
96
+ text: "<https://reddit.com#{permalink}|#{title}>",
97
+ },
98
+ ],
99
+ },
100
+ ],
101
+ }
102
+ end
103
+
104
+ def url
105
+ images = dig "data", "preview", "images"
106
+ source = images.map{|x| x["source"] }.compact.max do |a,b|
107
+ a.slice("width", "height").values <=> b.slice("width", "height").values
108
+ end
109
+ CGI.unescapeHTML source.dig("url")
110
+ rescue NoMethodError
111
+ dig("data", "media_metadata")&.values&.first&.dig("s", "u")
112
+ end
113
+ end
10
114
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brutalismbot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Mancevice
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-06 00:00:00.000000000 Z
11
+ date: 2019-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-s3
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: codecov
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.1'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +94,20 @@ dependencies:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
96
  version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.16'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.16'
83
111
  description: 'A Slack app that mirrors posts from /r/brutalism to a #channel of your
84
112
  choosing using incoming webhooks.'
85
113
  email:
@@ -92,8 +120,6 @@ files:
92
120
  - README.md
93
121
  - Rakefile
94
122
  - lib/brutalismbot.rb
95
- - lib/brutalismbot/event.rb
96
- - lib/brutalismbot/oauth.rb
97
123
  - lib/brutalismbot/r.rb
98
124
  - lib/brutalismbot/s3.rb
99
125
  - lib/brutalismbot/version.rb
@@ -1,30 +0,0 @@
1
- module Brutalismbot
2
- module Event
3
- class RecordCollection < Hash
4
- include Enumerable
5
-
6
- def each
7
- puts "EVENT #{to_json}"
8
- dig("Records").each{|x| yield x }
9
- end
10
- end
11
-
12
- class SNS < RecordCollection
13
- def each
14
- super do |record|
15
- yield JSON.parse record.dig("Sns", "Message")
16
- end
17
- end
18
- end
19
-
20
- class S3 < RecordCollection
21
- def each
22
- super do |record|
23
- bucket = URI.unescape record.dig("s3", "bucket", "name")
24
- key = URI.unescape record.dig("s3", "object", "key")
25
- yield bucket: bucket, key: key
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,32 +0,0 @@
1
- module Brutalismbot
2
- class OAuth < Hash
3
- def channel_id
4
- dig "incoming_webhook", "channel_id"
5
- end
6
-
7
- def post(body:, dryrun:nil)
8
- uri = URI.parse webhook_url
9
- ssl = uri.scheme == "https"
10
- res = Net::HTTP.start(uri.host, uri.port, use_ssl: ssl) do |http|
11
- if dryrun
12
- puts "POST DRYRUN #{uri}"
13
- OpenStruct.new code: 200, body: JSON.parse(body)
14
- else
15
- puts "POST #{uri}"
16
- req = Net::HTTP::Post.new uri, "content-type" => "application/json"
17
- req.body = body
18
- http.request req
19
- end
20
- end
21
- {statusCode: res.code, body: res.body}
22
- end
23
-
24
- def team_id
25
- dig "team_id"
26
- end
27
-
28
- def webhook_url
29
- dig "incoming_webhook", "url"
30
- end
31
- end
32
- end