reddit_bot 1.7.1 → 1.7.6
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 +4 -4
- data/README.md +1 -1
- data/Rakefile +2 -2
- data/examples/cptflairbot3/main.rb +1 -1
- data/examples/devflairbot/main.rb +1 -1
- data/examples/dut/Gemfile +3 -0
- data/examples/dut/Gemfile.lock +21 -0
- data/examples/dut/main.rb +39 -0
- data/examples/largeimages/Gemfile +4 -5
- data/examples/largeimages/Gemfile.lock +25 -31
- data/examples/largeimages/main.rb +18 -9
- data/examples/realtimeww2/Gemfile.lock +5 -5
- data/examples/realtimeww2/main.rb +6 -6
- data/examples/unisa/Gemfile +5 -0
- data/examples/unisa/Gemfile.lock +23 -0
- data/examples/unisa/main.rb +39 -0
- data/examples/wallpaper/Gemfile +1 -1
- data/examples/wallpaper/Gemfile.lock +16 -15
- data/lib/reddit_bot.rb +68 -20
- data/reddit_bot.gemspec +2 -4
- metadata +11 -6
- data/lib/reddit_bot/version.rb +0 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 52b34b7ffbd747f455238139479414c4c73575e3
|
|
4
|
+
data.tar.gz: 7b08991727037d0f91bcecfb7bca40caa5e33b81
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7ee3c17c7ce2683ca7bfce42f50bdde6af718de47a1b1093f37e9efcc6a49181574dd7d9d6222f58a76348235f5b4da58f416c4888e78e51c3f2067cc3745199
|
|
7
|
+
data.tar.gz: 5fb5186be0faeda8b551cac5354c2d558d2972cfb41631f48feca0bd0c975bfb8626305d1bed292805ae8a128864679b531b474f3151f0019a31645604cc2e8c
|
data/README.md
CHANGED
|
@@ -79,7 +79,7 @@ You obviously can't run these examples as is, because they use local configs tha
|
|
|
79
79
|
:login: MyBotUsername
|
|
80
80
|
# :user_agent: optional_custom_useragent_to_bypass_reddit_spam_protection
|
|
81
81
|
|
|
82
|
-
To change
|
|
82
|
+
To change log level:
|
|
83
83
|
|
|
84
84
|
```ruby
|
|
85
85
|
RedditBot.logger.level = Logger::ERROR
|
data/Rakefile
CHANGED
|
@@ -10,7 +10,7 @@ loop do
|
|
|
10
10
|
next logger.info "bad destination: #{msg["data"]["dest"]}" unless msg["data"]["dest"] == "CPTFlairBot3"
|
|
11
11
|
case msg["data"]["subject"]
|
|
12
12
|
when "casualpokemontrades"
|
|
13
|
-
unless /^(?<name>\S+( \S+)*) ?\n(?<id>\d\d\d\d-\d\d\d\d-\d\d\d\d)\n(?<css_class
|
|
13
|
+
unless /^(?<name>\S+( \S+)*) ?\n(?<id>\d\d\d\d-\d\d\d\d-\d\d\d\d)\n(?<css_class>[a-z2-]+)$/ =~ msg["data"]["body"]
|
|
14
14
|
logger.info "invalid message for #{msg["data"]["subject"]}: %p" % msg["data"]["body"] unless Google::Cloud.env.compute_engine?
|
|
15
15
|
# puts "marking invalid message as read: %p" % msg["data"]["body"]
|
|
16
16
|
# BOT.json :post, "/api/read_message", {id: msg["data"]["name"]} unless Gem::Platform.local.os == "darwin"
|
|
@@ -34,7 +34,7 @@ loop do
|
|
|
34
34
|
JSON.parse( begin
|
|
35
35
|
NetHTTPUtils.request_data "https://www.reddit.com/r/#{subreddit}/comments.json", header: ["User-Agent", "ajsdjasdasd"]
|
|
36
36
|
rescue NetHTTPUtils::Error => e
|
|
37
|
-
raise unless [503, 504
|
|
37
|
+
raise unless [500, 502, 503, 504].include? e.code
|
|
38
38
|
sleep 60
|
|
39
39
|
retry
|
|
40
40
|
end )["data"]["children"].each do |comment|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
GEM
|
|
2
|
+
remote: https://rubygems.org/
|
|
3
|
+
specs:
|
|
4
|
+
addressable (2.7.0)
|
|
5
|
+
public_suffix (>= 2.0.2, < 5.0)
|
|
6
|
+
json (2.3.0)
|
|
7
|
+
nethttputils (0.4.0.0)
|
|
8
|
+
addressable
|
|
9
|
+
public_suffix (4.0.5)
|
|
10
|
+
reddit_bot (1.7.5)
|
|
11
|
+
json
|
|
12
|
+
nethttputils (~> 0.4.0.0)
|
|
13
|
+
|
|
14
|
+
PLATFORMS
|
|
15
|
+
ruby
|
|
16
|
+
|
|
17
|
+
DEPENDENCIES
|
|
18
|
+
reddit_bot
|
|
19
|
+
|
|
20
|
+
BUNDLED WITH
|
|
21
|
+
2.0.2
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require "reddit_bot"
|
|
2
|
+
subreddit = "dut".freeze
|
|
3
|
+
bot = RedditBot::Bot.new YAML.load(File.read "secrets.yaml"), subreddit: subreddit
|
|
4
|
+
twitter = RedditBot::Twitter.init_twitter "DUT_Tweets"
|
|
5
|
+
|
|
6
|
+
loop do
|
|
7
|
+
id = bot.new_posts.find do |post|
|
|
8
|
+
/\(https:\/\/twitter\.com\/#{RedditBot::Twitter::TWITTER_ACCOUNT}\/status\/(\d{18,})\)/i =~ post["selftext"] and break $1
|
|
9
|
+
end.to_i
|
|
10
|
+
fail "no tweets found in subreddit" if id.zero? unless ENV["FIRST_RUN"]
|
|
11
|
+
|
|
12
|
+
fail unless flair = bot.json(:get, "/r/#{subreddit}/api/link_flair").find do |flair|
|
|
13
|
+
flair["text"] == "Twitter"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
timeline = RedditBot::Twitter.user_timeline
|
|
17
|
+
timeline.replace timeline.take 2 if ENV["FIRST_RUN"] # against 200 posts long flood
|
|
18
|
+
timeline.reverse_each do |tweet|
|
|
19
|
+
next if tweet["id"] <= id
|
|
20
|
+
title, text, _ = RedditBot::Twitter.tweet2titleNtext tweet
|
|
21
|
+
result = bot.json :post, "/api/submit", {
|
|
22
|
+
sr: subreddit,
|
|
23
|
+
kind: "self",
|
|
24
|
+
title: title,
|
|
25
|
+
text: text,
|
|
26
|
+
flair_id: flair["id"],
|
|
27
|
+
}
|
|
28
|
+
p result
|
|
29
|
+
if result["json"]["errors"].empty?
|
|
30
|
+
abort "OK" if ENV["ONCE"]
|
|
31
|
+
next
|
|
32
|
+
end
|
|
33
|
+
fail unless result["json"]["errors"].map(&:first) == ["ALREADY_SUB"]
|
|
34
|
+
puts "ALREADY_SUB error for #{tweet["id"]}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
puts "END LOOP #{Time.now}"
|
|
38
|
+
sleep 300
|
|
39
|
+
end
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
gem "json"
|
|
4
4
|
|
|
5
|
-
gem "
|
|
6
|
-
gem "nokogiri"
|
|
5
|
+
gem "nokogiri", "~>1.10.8"
|
|
7
6
|
|
|
8
|
-
gem "
|
|
9
|
-
gem "directlink",
|
|
7
|
+
gem "nethttputils", git: "git@github.com:nakilon/nethttputils.git"
|
|
8
|
+
gem "directlink", "~>0.0.8.5"
|
|
10
9
|
|
|
11
|
-
gem "gcplogger", git: "git@github.com:
|
|
10
|
+
gem "gcplogger", git: "git@github.com:nakilon/gcplogger.git", tag: "v0.1.1.0"
|
|
12
11
|
gem "google-cloud-error_reporting"
|
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
GIT
|
|
2
|
-
remote: git@github.com:
|
|
3
|
-
revision: 8c829c76ede9734a51e7e416d9cd309dc28dc9d8
|
|
4
|
-
specs:
|
|
5
|
-
directlink (0.0.4.4)
|
|
6
|
-
addressable
|
|
7
|
-
fastimage (~> 2.1.3)
|
|
8
|
-
kramdown
|
|
9
|
-
nokogiri
|
|
10
|
-
reddit_bot (~> 1.6.7)
|
|
11
|
-
|
|
12
|
-
GIT
|
|
13
|
-
remote: git@github.com:Nakilon/gcplogger.git
|
|
2
|
+
remote: git@github.com:nakilon/gcplogger.git
|
|
14
3
|
revision: 7c1451fac49bd0d242c6de43315ae6e9a70d8f7f
|
|
15
4
|
tag: v0.1.1.0
|
|
16
5
|
specs:
|
|
@@ -19,19 +8,26 @@ GIT
|
|
|
19
8
|
public_suffix (~> 2.0)
|
|
20
9
|
|
|
21
10
|
GIT
|
|
22
|
-
remote: git@github.com:
|
|
23
|
-
revision:
|
|
24
|
-
ref: 15bc4111c4c4e1af580b63c62e08decf2d5527d5
|
|
11
|
+
remote: git@github.com:nakilon/nethttputils.git
|
|
12
|
+
revision: 1eea987604cf592a62a6732eae864959f7a9fdc4
|
|
25
13
|
specs:
|
|
26
|
-
|
|
14
|
+
nethttputils (0.3.3.0)
|
|
27
15
|
|
|
28
16
|
GEM
|
|
29
17
|
remote: https://rubygems.org/
|
|
30
18
|
specs:
|
|
31
|
-
addressable (2.
|
|
32
|
-
public_suffix (>= 2.0.2, <
|
|
19
|
+
addressable (2.7.0)
|
|
20
|
+
public_suffix (>= 2.0.2, < 5.0)
|
|
21
|
+
directlink (0.0.8.5)
|
|
22
|
+
addressable
|
|
23
|
+
fastimage (~> 2.1.3)
|
|
24
|
+
kramdown
|
|
25
|
+
nethttputils (~> 0.3.3.0)
|
|
26
|
+
nokogiri
|
|
27
|
+
reddit_bot (~> 1.7.0)
|
|
33
28
|
faraday (0.14.0)
|
|
34
29
|
multipart-post (>= 1.2, < 3)
|
|
30
|
+
fastimage (2.1.7)
|
|
35
31
|
google-cloud-core (1.2.0)
|
|
36
32
|
google-cloud-env (~> 1.0)
|
|
37
33
|
google-cloud-env (1.0.1)
|
|
@@ -69,25 +65,24 @@ GEM
|
|
|
69
65
|
google-protobuf (~> 3.1)
|
|
70
66
|
googleapis-common-protos-types (~> 1.0.0)
|
|
71
67
|
googleauth (>= 0.5.1, < 0.7)
|
|
72
|
-
json (2.
|
|
68
|
+
json (2.2.0)
|
|
73
69
|
jwt (2.1.0)
|
|
74
|
-
kramdown (1.
|
|
70
|
+
kramdown (2.1.0)
|
|
75
71
|
little-plugger (1.1.4)
|
|
76
72
|
logging (2.2.2)
|
|
77
73
|
little-plugger (~> 1.1)
|
|
78
74
|
multi_json (~> 1.10)
|
|
79
75
|
memoist (0.16.0)
|
|
80
|
-
mini_portile2 (2.
|
|
76
|
+
mini_portile2 (2.4.0)
|
|
81
77
|
multi_json (1.13.1)
|
|
82
78
|
multipart-post (2.0.0)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
mini_portile2 (~> 2.3.0)
|
|
79
|
+
nokogiri (1.10.8)
|
|
80
|
+
mini_portile2 (~> 2.4.0)
|
|
86
81
|
os (0.9.6)
|
|
87
82
|
public_suffix (2.0.5)
|
|
88
|
-
reddit_bot (1.
|
|
83
|
+
reddit_bot (1.7.3)
|
|
89
84
|
json
|
|
90
|
-
nethttputils (~> 0.
|
|
85
|
+
nethttputils (~> 0.3.3.0)
|
|
91
86
|
rly (0.2.3)
|
|
92
87
|
signet (0.8.1)
|
|
93
88
|
addressable (~> 2.3)
|
|
@@ -101,13 +96,12 @@ PLATFORMS
|
|
|
101
96
|
ruby
|
|
102
97
|
|
|
103
98
|
DEPENDENCIES
|
|
104
|
-
directlink
|
|
105
|
-
fastimage!
|
|
99
|
+
directlink (~> 0.0.8.5)
|
|
106
100
|
gcplogger!
|
|
107
101
|
google-cloud-error_reporting
|
|
108
102
|
json
|
|
109
|
-
|
|
110
|
-
|
|
103
|
+
nethttputils!
|
|
104
|
+
nokogiri (~> 1.10.8)
|
|
111
105
|
|
|
112
106
|
BUNDLED WITH
|
|
113
|
-
|
|
107
|
+
2.0.2
|
|
@@ -22,15 +22,15 @@ INCLUDE = %w{
|
|
|
22
22
|
user/kjoneslol/m/sfwpornnetwork
|
|
23
23
|
|
|
24
24
|
r/woahdude
|
|
25
|
+
r/pic
|
|
25
26
|
|
|
26
27
|
r/highres
|
|
27
28
|
r/wallpapers
|
|
28
29
|
r/wallpaper
|
|
29
30
|
r/WQHD_Wallpaper
|
|
30
31
|
|
|
31
|
-
r/pic
|
|
32
|
-
|
|
33
32
|
r/oldmaps
|
|
33
|
+
r/telephotolandscapes
|
|
34
34
|
}
|
|
35
35
|
EXCLUDE = %w{ foodporn powerwashingporn }
|
|
36
36
|
|
|
@@ -40,7 +40,7 @@ search_url = lambda do |url|
|
|
|
40
40
|
JSON.load( begin
|
|
41
41
|
NetHTTPUtils.request_data "https://www.reddit.com/r/largeimages/search.json", form: {q: "url:#{url}", restrict_sr: "on"}, header: ["User-Agent", "ajsdjasdasd"]
|
|
42
42
|
rescue NetHTTPUtils::Error => e
|
|
43
|
-
raise unless [503].include? e.code
|
|
43
|
+
raise unless [500, 503].include? e.code
|
|
44
44
|
sleep 60
|
|
45
45
|
retry
|
|
46
46
|
end )["data"]["children"]
|
|
@@ -85,13 +85,22 @@ loop do
|
|
|
85
85
|
].each do |source, min_resolution, entries|
|
|
86
86
|
logger.warn "#{source}.size: #{entries.size}"
|
|
87
87
|
entries.each do |id, url, title, subreddit, author, permalink|
|
|
88
|
+
author.downcase!
|
|
88
89
|
next if checked.include? id
|
|
89
90
|
checked << id
|
|
90
91
|
# next if Gem::Platform.local.os == "darwin" # prevent concurrent posting
|
|
91
|
-
logger.
|
|
92
|
-
next logger.warn "skipped a post by /u/sjhill"
|
|
93
|
-
next logger.warn "skipped a post by /u/redisforever"
|
|
94
|
-
next logger.warn "skipped a post by /u/bekalaki"
|
|
92
|
+
logger.info "image url for #{id}: #{url}"
|
|
93
|
+
next logger.warn "skipped a post by /u/sjhill" if author == "sjhill" # opt-out
|
|
94
|
+
next logger.warn "skipped a post by /u/redisforever" if author == "redisforever" # opt-out
|
|
95
|
+
next logger.warn "skipped a post by /u/bekalaki" if author == "bekalaki" # 9 ways to divide a karmawhore
|
|
96
|
+
next logger.warn "skipped a post by /u/cherryblackeyes" if author == "cherryblackeyes" # he's not nice
|
|
97
|
+
next logger.warn "skipped a post by /u/abel_a_kay" if author == "abel_a_kay" # posting very similar images of the same thing for the history
|
|
98
|
+
next logger.warn "skipped gifv" if ( begin
|
|
99
|
+
URI url
|
|
100
|
+
rescue URI::InvalidURIError
|
|
101
|
+
require "addressable"
|
|
102
|
+
URI Addressable::URI.escape url
|
|
103
|
+
end ).host.split(?.) == %w{ v redd it }
|
|
95
104
|
|
|
96
105
|
t = begin
|
|
97
106
|
DirectLink url, 60
|
|
@@ -105,11 +114,11 @@ loop do
|
|
|
105
114
|
DirectLink::ErrorBadLink => e
|
|
106
115
|
next logger.error "skipped (#{e}) #{url} from http://redd.it/#{id}"
|
|
107
116
|
end
|
|
108
|
-
logger.
|
|
117
|
+
logger.debug "DirectLink: #{t.inspect}"
|
|
109
118
|
tt = t.is_a?(Array) ? t : [t]
|
|
110
119
|
next logger.error "probably crosspost of a self post: http://redd.it/#{id}" if tt.empty?
|
|
111
120
|
unless min_resolution <= tt.first.width * tt.first.height
|
|
112
|
-
next logger.
|
|
121
|
+
next logger.info "skipped low resolution #{source}"
|
|
113
122
|
end
|
|
114
123
|
# puts "https://www.reddit.com/r/LargeImages/search.json?q=url%3A#{CGI.escape url}&restrict_sr=on"
|
|
115
124
|
resolution = "[#{tt.first.width}x#{tt.first.height}]"
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
GEM
|
|
2
2
|
remote: https://rubygems.org/
|
|
3
3
|
specs:
|
|
4
|
-
json (2.
|
|
5
|
-
nethttputils (0.2.
|
|
6
|
-
reddit_bot (1.
|
|
4
|
+
json (2.2.0)
|
|
5
|
+
nethttputils (0.3.2.6)
|
|
6
|
+
reddit_bot (1.7.1)
|
|
7
7
|
json
|
|
8
|
-
nethttputils (~> 0.2.
|
|
8
|
+
nethttputils (~> 0.3.2.0)
|
|
9
9
|
|
|
10
10
|
PLATFORMS
|
|
11
11
|
ruby
|
|
@@ -14,4 +14,4 @@ DEPENDENCIES
|
|
|
14
14
|
reddit_bot
|
|
15
15
|
|
|
16
16
|
BUNDLED WITH
|
|
17
|
-
|
|
17
|
+
2.0.1
|
|
@@ -37,11 +37,11 @@ tweet2titleNtext = lambda do |tweet|
|
|
|
37
37
|
[CGI::unescapeHTML(tweet["full_text"]).sub(/( https:\/\/t\.co\/[0-9a-zA-Z]{10})*\z/, ""), text, contains_media]
|
|
38
38
|
end
|
|
39
39
|
[
|
|
40
|
-
[905764294687633408, true, "The Polish government & military high command is now evacuating Warsaw for Brest, 120 miles east: German armies are too close to the capital", "* [Image 1](https://pbs.twimg.com/media/DJHq71BXYAA6KJ0.jpg)\n\n" "^- ^WW2 ^Tweets ^from ^
|
|
41
|
-
[915534673471733760, true, "In east Poland (now Soviet Ukraine) industry & farms to be collectivised, political parties banned, aristocrats & capitalists \"re-educated\".", "* [Image 1](https://pbs.twimg.com/media/DLSh2J9W4AACcOG.jpg)\n\n* [Image 2](https://pbs.twimg.com/media/DLSh4sKX0AEBaXq.jpg)\n\n^- ^WW2 ^Tweets ^from ^
|
|
42
|
-
[915208866408824832, true, "For 1st time, RAF planes dropping propaganda leaflets on Berlin itself, entitled \"Germans: these are your leaders!\"", "* [Image 1](https://pbs.twimg.com/media/DLN5jJ-XkAEUz9M.jpg)\n\n* [Link 1](https://www.psywar.org/product_1939EH158.php)\n\n" "^- ^WW2 ^Tweets ^from ^
|
|
43
|
-
[914577848891006978, true, "\"In Poland, Russia pursued a cold policy of selfinterest. But clearly necessary for Russia… against Nazi menace.\"", "* [Link 1](https://www.youtube.com/watch?v=ygmP5A3n2JA)\n\n" "^- ^WW2 ^Tweets ^from ^
|
|
44
|
-
[926581977372942336, false, "Finland rejects Soviet demand to surrender land near Leningrad & give Red Navy base in Hanko; Soviets now claim Finns' manner \"warlike\".", "^- ^WW2 ^Tweets ^from ^
|
|
40
|
+
[905764294687633408, true, "The Polish government & military high command is now evacuating Warsaw for Brest, 120 miles east: German armies are too close to the capital", "* [Image 1](https://pbs.twimg.com/media/DJHq71BXYAA6KJ0.jpg)\n\n" "^- ^WW2 ^Tweets ^from ^1942 [^\\(@#{TWITTER}\\)](https://twitter.com/#{TWITTER}) ^| [^""September ^7, ^2017](https://twitter.com/#{TWITTER}/status/905764294687633408)"],
|
|
41
|
+
[915534673471733760, true, "In east Poland (now Soviet Ukraine) industry & farms to be collectivised, political parties banned, aristocrats & capitalists \"re-educated\".", "* [Image 1](https://pbs.twimg.com/media/DLSh2J9W4AACcOG.jpg)\n\n* [Image 2](https://pbs.twimg.com/media/DLSh4sKX0AEBaXq.jpg)\n\n^- ^WW2 ^Tweets ^from ^1942 [^\\(@#{TWITTER}\\)](https://twitter.com/#{TWITTER}) ^| [^" "October ^4, ^2017](https://twitter.com/#{TWITTER}/status/915534673471733760)"],
|
|
42
|
+
[915208866408824832, true, "For 1st time, RAF planes dropping propaganda leaflets on Berlin itself, entitled \"Germans: these are your leaders!\"", "* [Image 1](https://pbs.twimg.com/media/DLN5jJ-XkAEUz9M.jpg)\n\n* [Link 1](https://www.psywar.org/product_1939EH158.php)\n\n" "^- ^WW2 ^Tweets ^from ^1942 [^\\(@#{TWITTER}\\)](https://twitter.com/#{TWITTER}) ^| [^" "October ^3, ^2017](https://twitter.com/#{TWITTER}/status/915208866408824832)"],
|
|
43
|
+
[914577848891006978, true, "\"In Poland, Russia pursued a cold policy of selfinterest. But clearly necessary for Russia… against Nazi menace.\"", "* [Link 1](https://www.youtube.com/watch?v=ygmP5A3n2JA)\n\n" "^- ^WW2 ^Tweets ^from ^1942 [^\\(@#{TWITTER}\\)](https://twitter.com/#{TWITTER}) ^| [^" "October ^1, ^2017](https://twitter.com/#{TWITTER}/status/914577848891006978)"],
|
|
44
|
+
[926581977372942336, false, "Finland rejects Soviet demand to surrender land near Leningrad & give Red Navy base in Hanko; Soviets now claim Finns' manner \"warlike\".", "^- ^WW2 ^Tweets ^from ^1942 [^\\(@#{TWITTER}\\)](https://twitter.com/#{TWITTER}) ^| [^" "November ^3, ^2017](https://twitter.com/#{TWITTER}/status/926581977372942336)"],
|
|
45
45
|
].each do |id, contains_media_, title_, text_|
|
|
46
46
|
title, text, contains_media = tweet2titleNtext[ JSON.load NetHTTPUtils.request_data(
|
|
47
47
|
"https://api.twitter.com/1.1/statuses/show.json",
|
|
@@ -101,7 +101,7 @@ loop do
|
|
|
101
101
|
sleep t
|
|
102
102
|
end
|
|
103
103
|
rescue NetHTTPUtils::Error => e
|
|
104
|
-
fail
|
|
104
|
+
fail unless [500, 503].include? e.code
|
|
105
105
|
sleep timeout
|
|
106
106
|
timeout *= 2
|
|
107
107
|
retry
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
GEM
|
|
2
|
+
remote: https://rubygems.org/
|
|
3
|
+
specs:
|
|
4
|
+
addressable (2.7.0)
|
|
5
|
+
public_suffix (>= 2.0.2, < 5.0)
|
|
6
|
+
byebug (11.0.1)
|
|
7
|
+
json (2.3.0)
|
|
8
|
+
nethttputils (0.4.0.0)
|
|
9
|
+
addressable
|
|
10
|
+
public_suffix (4.0.5)
|
|
11
|
+
reddit_bot (1.7.5)
|
|
12
|
+
json
|
|
13
|
+
nethttputils (~> 0.4.0.0)
|
|
14
|
+
|
|
15
|
+
PLATFORMS
|
|
16
|
+
ruby
|
|
17
|
+
|
|
18
|
+
DEPENDENCIES
|
|
19
|
+
byebug
|
|
20
|
+
reddit_bot
|
|
21
|
+
|
|
22
|
+
BUNDLED WITH
|
|
23
|
+
2.0.2
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require "reddit_bot"
|
|
2
|
+
subreddit = "unisa".freeze
|
|
3
|
+
bot = RedditBot::Bot.new YAML.load(File.read "secrets.yaml"), subreddit: subreddit
|
|
4
|
+
twitter = RedditBot::Twitter.init_twitter "unisa"
|
|
5
|
+
|
|
6
|
+
loop do
|
|
7
|
+
id = bot.new_posts.find do |post|
|
|
8
|
+
/\(https:\/\/twitter\.com\/#{RedditBot::Twitter::TWITTER_ACCOUNT}\/status\/(\d{18,})\)/i =~ post["selftext"] and break $1
|
|
9
|
+
end.to_i
|
|
10
|
+
fail "no tweets found in subreddit" if id.zero? unless ENV["FIRST_RUN"]
|
|
11
|
+
|
|
12
|
+
fail unless flair = bot.json(:get, "/r/#{subreddit}/api/link_flair").find do |flair|
|
|
13
|
+
flair["text"] == "Twitter"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
timeline = RedditBot::Twitter.user_timeline
|
|
17
|
+
timeline.replace timeline.take 2 if ENV["FIRST_RUN"] # against 200 posts long flood
|
|
18
|
+
timeline.reverse_each do |tweet|
|
|
19
|
+
next if tweet["id"] <= id
|
|
20
|
+
title, text, _ = RedditBot::Twitter.tweet2titleNtext tweet
|
|
21
|
+
result = bot.json :post, "/api/submit", {
|
|
22
|
+
sr: subreddit,
|
|
23
|
+
kind: "self",
|
|
24
|
+
title: title,
|
|
25
|
+
text: text,
|
|
26
|
+
flair_id: flair["id"],
|
|
27
|
+
}
|
|
28
|
+
p result
|
|
29
|
+
if result["json"]["errors"].empty?
|
|
30
|
+
abort "OK" if ENV["ONCE"]
|
|
31
|
+
next
|
|
32
|
+
end
|
|
33
|
+
fail unless result["json"]["errors"].map(&:first) == ["ALREADY_SUB"]
|
|
34
|
+
puts "ALREADY_SUB error for #{tweet["id"]}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
puts "END LOOP #{Time.now}"
|
|
38
|
+
sleep 300
|
|
39
|
+
end
|
data/examples/wallpaper/Gemfile
CHANGED
|
@@ -1,33 +1,34 @@
|
|
|
1
1
|
GEM
|
|
2
2
|
remote: https://rubygems.org/
|
|
3
3
|
specs:
|
|
4
|
-
addressable (2.
|
|
5
|
-
public_suffix (>= 2.0.2, <
|
|
6
|
-
directlink (0.0.
|
|
4
|
+
addressable (2.7.0)
|
|
5
|
+
public_suffix (>= 2.0.2, < 5.0)
|
|
6
|
+
directlink (0.0.8.7)
|
|
7
7
|
addressable
|
|
8
8
|
fastimage (~> 2.1.3)
|
|
9
9
|
kramdown
|
|
10
|
+
nethttputils (~> 0.3.3.0)
|
|
10
11
|
nokogiri
|
|
11
|
-
reddit_bot (~> 1.
|
|
12
|
-
fastimage (2.1.
|
|
13
|
-
json (2.
|
|
14
|
-
kramdown (1.
|
|
15
|
-
mini_portile2 (2.
|
|
16
|
-
nethttputils (0.
|
|
17
|
-
nokogiri (1.
|
|
18
|
-
mini_portile2 (~> 2.
|
|
12
|
+
reddit_bot (~> 1.7.0)
|
|
13
|
+
fastimage (2.1.7)
|
|
14
|
+
json (2.3.0)
|
|
15
|
+
kramdown (2.1.0)
|
|
16
|
+
mini_portile2 (2.4.0)
|
|
17
|
+
nethttputils (0.3.3.0)
|
|
18
|
+
nokogiri (1.10.4)
|
|
19
|
+
mini_portile2 (~> 2.4.0)
|
|
19
20
|
public_suffix (2.0.5)
|
|
20
|
-
reddit_bot (1.
|
|
21
|
+
reddit_bot (1.7.3)
|
|
21
22
|
json
|
|
22
|
-
nethttputils (~> 0.
|
|
23
|
+
nethttputils (~> 0.3.3.0)
|
|
23
24
|
|
|
24
25
|
PLATFORMS
|
|
25
26
|
ruby
|
|
26
27
|
|
|
27
28
|
DEPENDENCIES
|
|
28
29
|
directlink
|
|
29
|
-
nokogiri (~> 1.
|
|
30
|
+
nokogiri (~> 1.10.4)
|
|
30
31
|
public_suffix (< 3.0)
|
|
31
32
|
|
|
32
33
|
BUNDLED WITH
|
|
33
|
-
|
|
34
|
+
2.0.2
|
data/lib/reddit_bot.rb
CHANGED
|
@@ -3,11 +3,10 @@ STDOUT.sync = true
|
|
|
3
3
|
|
|
4
4
|
require "openssl"
|
|
5
5
|
require "json"
|
|
6
|
+
require "yaml"
|
|
6
7
|
|
|
7
8
|
require "nethttputils"
|
|
8
9
|
|
|
9
|
-
require_relative "reddit_bot/version" # TODO: deprecate this
|
|
10
|
-
|
|
11
10
|
module RedditBot
|
|
12
11
|
require "logger"
|
|
13
12
|
class << self
|
|
@@ -204,7 +203,7 @@ module RedditBot
|
|
|
204
203
|
username: @name,
|
|
205
204
|
password: @secret_password,
|
|
206
205
|
}, {
|
|
207
|
-
"User-Agent" => "bot/#{@user_agent || @name}/#{
|
|
206
|
+
"User-Agent" => "bot/#{@user_agent || @name}/#{Gem::Specification::load("#{__dir__}/../reddit_bot.gemspec").version} by /u/nakilon",
|
|
208
207
|
}, @secret_auth
|
|
209
208
|
unless @token_cached = response["access_token"]
|
|
210
209
|
fail "bot #{@name} isn't a 'developer' of app at https://www.reddit.com/prefs/apps/" if response == {"error"=>"invalid_grant"}
|
|
@@ -231,13 +230,13 @@ module RedditBot
|
|
|
231
230
|
begin
|
|
232
231
|
reddit_resp mtd, "https://oauth.reddit.com" + path, form, {
|
|
233
232
|
"Authorization" => "bearer #{token}",
|
|
234
|
-
"User-Agent" => "bot/#{@user_agent || @name}/#{
|
|
233
|
+
"User-Agent" => "bot/#{@user_agent || @name}/#{Gem::Specification::load("#{__dir__}/../reddit_bot.gemspec").version} by /u/nakilon",
|
|
235
234
|
}
|
|
236
235
|
rescue NetHTTPUtils::Error => e
|
|
236
|
+
raise unless e.code == 401
|
|
237
237
|
sleep timeout
|
|
238
238
|
Module.nesting[1].logger.info "sleeping #{timeout} seconds because of #{e.code}"
|
|
239
239
|
timeout *= 2
|
|
240
|
-
raise unless e.code == 401
|
|
241
240
|
@token_cached = nil
|
|
242
241
|
retry
|
|
243
242
|
end
|
|
@@ -245,22 +244,9 @@ module RedditBot
|
|
|
245
244
|
|
|
246
245
|
def reddit_resp *args
|
|
247
246
|
mtd, url, form, headers, basic_auth = *args
|
|
247
|
+
headers["Cookie:"] = "over18=1"
|
|
248
248
|
begin
|
|
249
|
-
NetHTTPUtils.request_data
|
|
250
|
-
next unless remaining = response.to_hash["x-ratelimit-remaining"]
|
|
251
|
-
if Gem::Platform.local.os == "darwin"
|
|
252
|
-
Module.nesting[1].logger.debug %w{
|
|
253
|
-
x-ratelimit-remaining
|
|
254
|
-
x-ratelimit-used
|
|
255
|
-
x-ratelimit-reset
|
|
256
|
-
}.map{ |key| "#{key}=#{response.to_hash[key]}" }.join ", "
|
|
257
|
-
end
|
|
258
|
-
fail remaining[0] if remaining[0].size < 4
|
|
259
|
-
next if remaining[0].size > 4
|
|
260
|
-
t = (response.to_hash["x-ratelimit-reset"][0].to_f + 1) / [remaining[0].to_f - 10, 1].max + 1
|
|
261
|
-
Module.nesting[1].logger.info "sleeping #{t} seconds because of x-ratelimit"
|
|
262
|
-
sleep t
|
|
263
|
-
end
|
|
249
|
+
NetHTTPUtils.request_data url, mtd, form: form, header: headers, auth: basic_auth
|
|
264
250
|
rescue NetHTTPUtils::Error => e
|
|
265
251
|
sleep 5
|
|
266
252
|
raise unless e.code.to_s.start_with? "50"
|
|
@@ -270,4 +256,66 @@ module RedditBot
|
|
|
270
256
|
end
|
|
271
257
|
|
|
272
258
|
end
|
|
259
|
+
|
|
260
|
+
module Twitter
|
|
261
|
+
require "json"
|
|
262
|
+
|
|
263
|
+
def self.init_twitter twitter
|
|
264
|
+
const_set :TWITTER_ACCOUNT, twitter
|
|
265
|
+
const_set :TWITTER_ACCESS_TOKEN, JSON.load(
|
|
266
|
+
NetHTTPUtils.request_data "https://api.twitter.com/oauth2/token", :post,
|
|
267
|
+
auth: File.read("twitter.token").split,
|
|
268
|
+
form: {grant_type: :client_credentials}
|
|
269
|
+
)["access_token"]
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
require "cgi"
|
|
273
|
+
def self.tweet2titleNtext tweet
|
|
274
|
+
text = ""
|
|
275
|
+
contains_media = false
|
|
276
|
+
up = ->s{ s.split.map{ |w| "^#{w}" }.join " " }
|
|
277
|
+
if tweet["extended_entities"] && !tweet["extended_entities"]["media"].empty?
|
|
278
|
+
contains_media = true
|
|
279
|
+
tweet["extended_entities"]["media"].each_with_index do |media, i|
|
|
280
|
+
text.concat "* [Image #{i + 1}](#{media["media_url_https"]})\n\n"
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
if !tweet["entities"]["urls"].empty?
|
|
284
|
+
contains_media = true
|
|
285
|
+
tweet["entities"]["urls"].each_with_index do |url, i|
|
|
286
|
+
text.concat "* [Link #{i + 1}](#{url["expanded_url"]})\n\n"
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
text.concat "^- #{
|
|
290
|
+
up[tweet["user"]["name"]]
|
|
291
|
+
} [^\\(@#{TWITTER_ACCOUNT}\\)](https://twitter.com/#{TWITTER_ACCOUNT}) ^| [#{
|
|
292
|
+
up[Date.parse(tweet["created_at"]).strftime "%B %-d, %Y"]
|
|
293
|
+
}](https://twitter.com/#{TWITTER_ACCOUNT}/status/#{tweet["id"]})"
|
|
294
|
+
[CGI::unescapeHTML(tweet["full_text"]).sub(/( https:\/\/t\.co\/[0-9a-zA-Z]{10})*\z/, ""), text, contains_media]
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def self.user_timeline
|
|
298
|
+
timeout = 1
|
|
299
|
+
JSON.load begin
|
|
300
|
+
NetHTTPUtils.request_data(
|
|
301
|
+
"https://api.twitter.com/1.1/statuses/user_timeline.json",
|
|
302
|
+
form: { screen_name: TWITTER_ACCOUNT, count: 200, tweet_mode: "extended" },
|
|
303
|
+
header: { Authorization: "Bearer #{TWITTER_ACCESS_TOKEN}" }
|
|
304
|
+
) do |res|
|
|
305
|
+
next unless res.key? "x-rate-limit-remaining"
|
|
306
|
+
remaining = res.fetch("x-rate-limit-remaining").to_i
|
|
307
|
+
next if 100 < remaining
|
|
308
|
+
t = (res.fetch("x-rate-limit-reset").to_i - Time.now.to_i + 1).fdiv remaining
|
|
309
|
+
puts "sleep #{t}"
|
|
310
|
+
sleep t
|
|
311
|
+
end
|
|
312
|
+
rescue NetHTTPUtils::Error => e
|
|
313
|
+
fail unless [500, 503].include? e.code
|
|
314
|
+
sleep timeout
|
|
315
|
+
timeout *= 2
|
|
316
|
+
retry
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
273
321
|
end
|
data/reddit_bot.gemspec
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
require_relative "lib/reddit_bot/version"
|
|
2
|
-
|
|
3
1
|
Gem::Specification.new do |spec|
|
|
4
2
|
spec.name = "reddit_bot"
|
|
5
|
-
spec.version =
|
|
3
|
+
spec.version = "1.7.6"
|
|
6
4
|
spec.authors = ["Victor Maslov"]
|
|
7
5
|
spec.email = ["nakilon@gmail.com"]
|
|
8
6
|
|
|
@@ -15,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
|
15
13
|
# spec.require_paths = ["lib"]
|
|
16
14
|
|
|
17
15
|
spec.add_runtime_dependency "json"
|
|
18
|
-
spec.add_runtime_dependency "nethttputils", "~>0.
|
|
16
|
+
spec.add_runtime_dependency "nethttputils", "~>0.4.0.0"
|
|
19
17
|
# spec.add_development_dependency "bundler", "~> 1.11"
|
|
20
18
|
# spec.add_development_dependency "rake", "~> 10.0"
|
|
21
19
|
# spec.add_development_dependency "rspec", "~> 3.0"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: reddit_bot
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.7.
|
|
4
|
+
version: 1.7.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Victor Maslov
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2020-06-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: json
|
|
@@ -30,14 +30,14 @@ dependencies:
|
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 0.
|
|
33
|
+
version: 0.4.0.0
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 0.
|
|
40
|
+
version: 0.4.0.0
|
|
41
41
|
description: better than PRAW
|
|
42
42
|
email:
|
|
43
43
|
- nakilon@gmail.com
|
|
@@ -72,6 +72,9 @@ files:
|
|
|
72
72
|
- examples/devflairbot/Gemfile
|
|
73
73
|
- examples/devflairbot/Gemfile.lock
|
|
74
74
|
- examples/devflairbot/main.rb
|
|
75
|
+
- examples/dut/Gemfile
|
|
76
|
+
- examples/dut/Gemfile.lock
|
|
77
|
+
- examples/dut/main.rb
|
|
75
78
|
- examples/get_dimensions.rb
|
|
76
79
|
- examples/iostroubleshooting/Gemfile
|
|
77
80
|
- examples/iostroubleshooting/Gemfile.lock
|
|
@@ -101,6 +104,9 @@ files:
|
|
|
101
104
|
- examples/sexypizza/Gemfile
|
|
102
105
|
- examples/sexypizza/Gemfile.lock
|
|
103
106
|
- examples/sexypizza/main.rb
|
|
107
|
+
- examples/unisa/Gemfile
|
|
108
|
+
- examples/unisa/Gemfile.lock
|
|
109
|
+
- examples/unisa/main.rb
|
|
104
110
|
- examples/wallpaper/Gemfile
|
|
105
111
|
- examples/wallpaper/Gemfile.lock
|
|
106
112
|
- examples/wallpaper/main.rb
|
|
@@ -108,7 +114,6 @@ files:
|
|
|
108
114
|
- examples/yayornay/Gemfile.lock
|
|
109
115
|
- examples/yayornay/main.rb
|
|
110
116
|
- lib/reddit_bot.rb
|
|
111
|
-
- lib/reddit_bot/version.rb
|
|
112
117
|
- reddit_bot.gemspec
|
|
113
118
|
homepage: https://github.com/Nakilon/reddit_bot
|
|
114
119
|
licenses:
|
|
@@ -130,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
130
135
|
version: '0'
|
|
131
136
|
requirements: []
|
|
132
137
|
rubyforge_project:
|
|
133
|
-
rubygems_version: 2.5.2
|
|
138
|
+
rubygems_version: 2.5.2.3
|
|
134
139
|
signing_key:
|
|
135
140
|
specification_version: 4
|
|
136
141
|
summary: Library for Reddit bots
|
data/lib/reddit_bot/version.rb
DELETED