reddit-to-telegram 0.1.0
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 +7 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +14 -0
- data/.tool-versions +1 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +65 -0
- data/README.md +9 -0
- data/lib/reddit-to-telegram.rb +34 -0
- data/lib/reddit_to_telegram/reddit/auth.rb +27 -0
- data/lib/reddit_to_telegram/reddit/fetch.rb +47 -0
- data/lib/reddit_to_telegram/reddit/output.rb +81 -0
- data/lib/reddit_to_telegram/store/aws_simple_db.rb +111 -0
- data/lib/reddit_to_telegram/store/memory.rb +31 -0
- data/lib/reddit_to_telegram/store/temp_file.rb +65 -0
- data/lib/reddit_to_telegram/store.rb +52 -0
- data/lib/reddit_to_telegram/telegram/post.rb +47 -0
- data/lib/reddit_to_telegram/telegram/prepare_request.rb +40 -0
- data/lib/reddit_to_telegram/telegram/video.rb +25 -0
- data/lib/reddit_to_telegram/vars.rb +68 -0
- data/lib/reddit_to_telegram/version.rb +5 -0
- data/reddit-to-telegram.gemspec +21 -0
- data/tmp/.keep +0 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: def346e1939d931f21e0f24d1630cb4bd9a6d08d0ef7ebd5abbe825c1550a938
|
4
|
+
data.tar.gz: 2f82277c614573fe1fd857a6fb6ea61f9c9e05c0f988469ad058dc2e69b1c98d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f11773282239a115f8e1609f7cd96af138057b8ca14aaaad938da783888efa50c25ead86cbc7a04af2095b642c481f297d07b2ae972e34dc6f2c4f2a80cb1dce
|
7
|
+
data.tar.gz: 107f58634675023a1c0ac98a6be862dd5101169f76296bedc09c280bd21e8cb737ef6610557d5932f3034dc25f1aa4e66ef43af6b1d115a614405b1fdf6512f3
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 3.2.2
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
reddit-to-telegram (0.0.0)
|
5
|
+
aws-sdk-simpledb
|
6
|
+
httparty
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
ast (2.4.2)
|
12
|
+
aws-eventstream (1.3.0)
|
13
|
+
aws-partitions (1.883.0)
|
14
|
+
aws-sdk-core (3.190.3)
|
15
|
+
aws-eventstream (~> 1, >= 1.3.0)
|
16
|
+
aws-partitions (~> 1, >= 1.651.0)
|
17
|
+
aws-sigv4 (~> 1.8)
|
18
|
+
jmespath (~> 1, >= 1.6.1)
|
19
|
+
aws-sdk-simpledb (1.42.0)
|
20
|
+
aws-sdk-core (~> 3, >= 3.188.0)
|
21
|
+
aws-sigv2 (~> 1.0)
|
22
|
+
aws-sigv2 (1.2.0)
|
23
|
+
aws-sigv4 (1.8.0)
|
24
|
+
aws-eventstream (~> 1, >= 1.0.2)
|
25
|
+
httparty (0.21.0)
|
26
|
+
mini_mime (>= 1.0.0)
|
27
|
+
multi_xml (>= 0.5.2)
|
28
|
+
jmespath (1.6.2)
|
29
|
+
json (2.7.1)
|
30
|
+
language_server-protocol (3.17.0.3)
|
31
|
+
mini_mime (1.1.5)
|
32
|
+
multi_xml (0.6.0)
|
33
|
+
parallel (1.24.0)
|
34
|
+
parser (3.3.0.5)
|
35
|
+
ast (~> 2.4.1)
|
36
|
+
racc
|
37
|
+
racc (1.7.3)
|
38
|
+
rainbow (3.1.1)
|
39
|
+
regexp_parser (2.9.0)
|
40
|
+
rexml (3.2.6)
|
41
|
+
rubocop (1.60.2)
|
42
|
+
json (~> 2.3)
|
43
|
+
language_server-protocol (>= 3.17.0)
|
44
|
+
parallel (~> 1.10)
|
45
|
+
parser (>= 3.3.0.2)
|
46
|
+
rainbow (>= 2.2.2, < 4.0)
|
47
|
+
regexp_parser (>= 1.8, < 3.0)
|
48
|
+
rexml (>= 3.2.5, < 4.0)
|
49
|
+
rubocop-ast (>= 1.30.0, < 2.0)
|
50
|
+
ruby-progressbar (~> 1.7)
|
51
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
52
|
+
rubocop-ast (1.30.0)
|
53
|
+
parser (>= 3.2.1.0)
|
54
|
+
ruby-progressbar (1.13.0)
|
55
|
+
unicode-display_width (2.5.0)
|
56
|
+
|
57
|
+
PLATFORMS
|
58
|
+
x86_64-linux
|
59
|
+
|
60
|
+
DEPENDENCIES
|
61
|
+
reddit-to-telegram!
|
62
|
+
rubocop
|
63
|
+
|
64
|
+
BUNDLED WITH
|
65
|
+
2.4.10
|
data/README.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "reddit_to_telegram/reddit/fetch"
|
4
|
+
require_relative "reddit_to_telegram/store"
|
5
|
+
require_relative "reddit_to_telegram/telegram/post"
|
6
|
+
|
7
|
+
module RedditToTelegram
|
8
|
+
class << self
|
9
|
+
def post(sources)
|
10
|
+
return if sources.empty?
|
11
|
+
|
12
|
+
Store.setup
|
13
|
+
|
14
|
+
sources.each do |subreddit, telegram_chat_id|
|
15
|
+
res = Reddit::Fetch.hot(subreddit)
|
16
|
+
handle_res(res, subreddit, telegram_chat_id)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def handle_res(res, subreddit, telegram_chat_id)
|
21
|
+
return if res.nil?
|
22
|
+
|
23
|
+
post = find_new_post(subreddit, res)
|
24
|
+
return if post.nil?
|
25
|
+
|
26
|
+
Telegram::Post.push(post, telegram_chat_id)
|
27
|
+
Store::Posts.add(subreddit, post[:id])
|
28
|
+
end
|
29
|
+
|
30
|
+
def find_new_post(subreddit, posts)
|
31
|
+
posts.find { |post| !Store::Posts.dup?(subreddit, post[:id]) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "httparty"
|
4
|
+
require_relative "../vars"
|
5
|
+
|
6
|
+
module RedditToTelegram
|
7
|
+
module Reddit
|
8
|
+
class Auth
|
9
|
+
include HTTParty
|
10
|
+
|
11
|
+
URI = "https://www.reddit.com/api/v1/access_token"
|
12
|
+
PARAMS = { grant_type: "client_credentials" }.freeze
|
13
|
+
HEADERS = { "Content-Type" => "application/x-www-form-urlencoded" }.freeze
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def token
|
17
|
+
HTTParty.post(
|
18
|
+
URI,
|
19
|
+
body: PARAMS,
|
20
|
+
headers: HEADERS,
|
21
|
+
basic_auth: { username: Vars::Reddit.client_id, password: Vars::Reddit.client_secret }
|
22
|
+
)["access_token"]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "httparty"
|
4
|
+
require_relative "auth"
|
5
|
+
require_relative "output"
|
6
|
+
require_relative "../store"
|
7
|
+
require_relative "../vars"
|
8
|
+
|
9
|
+
module RedditToTelegram
|
10
|
+
module Reddit
|
11
|
+
class Fetch
|
12
|
+
include HTTParty
|
13
|
+
|
14
|
+
BASE_URI = "https://oauth.reddit.com/r"
|
15
|
+
QUERY = { g: "GLOBAL", limit: Vars.max_stored_posts }.freeze
|
16
|
+
BASE_HEADERS = {
|
17
|
+
"Content-Type" => "application/json",
|
18
|
+
"Accept" => "application/json"
|
19
|
+
}.freeze
|
20
|
+
|
21
|
+
class << self
|
22
|
+
def hot(subreddit, retries_left = 5)
|
23
|
+
headers = BASE_HEADERS.merge("Authorization" => "Bearer #{Store::Reddit.token}")
|
24
|
+
res = HTTParty.get(
|
25
|
+
"#{BASE_URI}/#{subreddit}/hot.json",
|
26
|
+
query: QUERY,
|
27
|
+
headers:
|
28
|
+
)
|
29
|
+
handle_response(res, subreddit, retries_left)
|
30
|
+
end
|
31
|
+
|
32
|
+
def handle_response(res, subreddit, retries_left)
|
33
|
+
case res.code
|
34
|
+
when 401
|
35
|
+
Store::Reddit.token = Auth.token
|
36
|
+
hot(subreddit, retries_left) if retries_left > 0
|
37
|
+
when 429
|
38
|
+
sleep(10 / retries_left) if retries_left > 0
|
39
|
+
hot(subreddit, retries_left - 1) if retries_left > 0
|
40
|
+
when 200
|
41
|
+
Output.format_response(res)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RedditToTelegram
|
4
|
+
module Reddit
|
5
|
+
class Output
|
6
|
+
class << self
|
7
|
+
def format_response(res)
|
8
|
+
posts = res["data"]["children"]
|
9
|
+
posts.reject! { |post| post["data"]["stickied"] == true }
|
10
|
+
posts.map { |post| format_post(post) }.compact
|
11
|
+
end
|
12
|
+
|
13
|
+
def format_post(post)
|
14
|
+
data = post["data"]
|
15
|
+
if data["post_hint"] == "image"
|
16
|
+
format_image_post(data)
|
17
|
+
elsif data["post_hint"] == "link"
|
18
|
+
format_link_post(data)
|
19
|
+
elsif data["is_gallery"]
|
20
|
+
format_gallery_post(data)
|
21
|
+
elsif data["is_video"]
|
22
|
+
format_video_post(data)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def format_image_post(data)
|
27
|
+
base_post_format_attrs(data).merge(
|
28
|
+
{ type: :image,
|
29
|
+
media: data["url"] }
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def format_link_post(data)
|
34
|
+
base_post_format_attrs(data).merge(
|
35
|
+
{ type: :text,
|
36
|
+
text: "#{data['title']}\n\n#{data['url']}" }
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def format_gallery_post(data)
|
41
|
+
base_post_format_attrs(data).merge(
|
42
|
+
{ type: :gallery,
|
43
|
+
media: prepare_gallery_links(data) }
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
def format_video_post(data)
|
48
|
+
video_data = data["secure_media"]["reddit_video"]
|
49
|
+
video_url = video_data["fallback_url"]
|
50
|
+
if video_data["has_audio"]
|
51
|
+
audio_url = "#{video_url.split('_')[0]}_AUDIO_128.mp4"
|
52
|
+
video_url = "https://sd.rapidsave.com/download.php"\
|
53
|
+
"?permalink=https://reddit.com#{data['permalink']}"\
|
54
|
+
"&video_url=#{video_url}&audio_url=#{audio_url}"
|
55
|
+
end
|
56
|
+
|
57
|
+
base_post_format_attrs(data).merge(
|
58
|
+
{
|
59
|
+
type: :video,
|
60
|
+
media: video_url,
|
61
|
+
misc: {
|
62
|
+
binary: video_data["has_audio"] || false
|
63
|
+
}
|
64
|
+
}
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
68
|
+
def base_post_format_attrs(data)
|
69
|
+
{ id: data["name"],
|
70
|
+
text: data["title"] }
|
71
|
+
end
|
72
|
+
|
73
|
+
def prepare_gallery_links(data)
|
74
|
+
data["media_metadata"].map do |image|
|
75
|
+
image[1]["p"][0]["u"].split("?").first.gsub("preview", "i")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "aws-sdk-simpledb"
|
4
|
+
require "json"
|
5
|
+
require_relative "../vars"
|
6
|
+
|
7
|
+
module RedditToTelegram
|
8
|
+
module Store
|
9
|
+
class AWSSimpleDB
|
10
|
+
DOMAIN_NAME = "reddit_to_telegram"
|
11
|
+
ITEM_NAME = "cached_data"
|
12
|
+
|
13
|
+
class << self
|
14
|
+
attr_reader :reddit_token
|
15
|
+
|
16
|
+
def setup
|
17
|
+
create_domain unless client.list_domains.domain_names.include?(DOMAIN_NAME)
|
18
|
+
read_db
|
19
|
+
end
|
20
|
+
|
21
|
+
def reddit_token=(val)
|
22
|
+
@reddit_token = val
|
23
|
+
write_db
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_post(subreddit, id)
|
27
|
+
@posts[subreddit] = [] if @posts[subreddit].nil?
|
28
|
+
@posts[subreddit] << id
|
29
|
+
@posts[subreddit].shift if @posts[subreddit].count > Store::MAX_STORED_POSTS
|
30
|
+
write_db
|
31
|
+
end
|
32
|
+
|
33
|
+
def dup_post?(subreddit, id)
|
34
|
+
return false if @posts[subreddit].nil?
|
35
|
+
|
36
|
+
@posts[subreddit].include?(id)
|
37
|
+
end
|
38
|
+
|
39
|
+
def client
|
40
|
+
@client ||= Aws::SimpleDB::Client.new(
|
41
|
+
access_key_id: Vars::AWS.access_key_id,
|
42
|
+
secret_access_key: Vars::AWS.secret_access_key,
|
43
|
+
region: Vars::AWS.region
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
def read_db
|
48
|
+
res = client.get_attributes(
|
49
|
+
{
|
50
|
+
domain_name: "reddit_to_telegram",
|
51
|
+
item_name: "cached_data",
|
52
|
+
consistent_read: true
|
53
|
+
}
|
54
|
+
)
|
55
|
+
|
56
|
+
return assign_default_values if res.attributes.empty?
|
57
|
+
|
58
|
+
assign_values_from_db(res)
|
59
|
+
end
|
60
|
+
|
61
|
+
def assign_values_from_db(data)
|
62
|
+
@reddit_token = data.attributes.find { |a| a.name == "reddit_token" }.value || ""
|
63
|
+
@posts = {}
|
64
|
+
data.attributes.each do |attr|
|
65
|
+
@posts[attr.name.split("_").last.to_sym] = JSON.parse(attr.value) if attr.name.match?(/posts_.+/)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def write_db
|
70
|
+
client.put_attributes(
|
71
|
+
{
|
72
|
+
domain_name: DOMAIN_NAME,
|
73
|
+
item_name: ITEM_NAME,
|
74
|
+
attributes: prepare_db_attrs
|
75
|
+
}
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
def prepare_db_attrs
|
80
|
+
attrs = [
|
81
|
+
{
|
82
|
+
name: "reddit_token",
|
83
|
+
value: @reddit_token,
|
84
|
+
replace: true
|
85
|
+
}
|
86
|
+
]
|
87
|
+
|
88
|
+
@posts.each do |subreddit, values|
|
89
|
+
attrs << { name: "posts_#{subreddit}", value: values.to_json, replace: true }
|
90
|
+
end
|
91
|
+
|
92
|
+
attrs
|
93
|
+
end
|
94
|
+
|
95
|
+
def assign_default_values
|
96
|
+
@reddit_token = ""
|
97
|
+
@posts = {}
|
98
|
+
end
|
99
|
+
|
100
|
+
def create_domain
|
101
|
+
res = client.list_domains
|
102
|
+
return unless res.successful?
|
103
|
+
|
104
|
+
return if res.domain_names.include?(DOMAIN_NAME)
|
105
|
+
|
106
|
+
client.create_domain({ domain_name: DOMAIN_NAME })
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RedditToTelegram
|
4
|
+
module Store
|
5
|
+
class Memory
|
6
|
+
class << self
|
7
|
+
attr_accessor :reddit_token
|
8
|
+
|
9
|
+
@posts = {}
|
10
|
+
|
11
|
+
def setup; end
|
12
|
+
|
13
|
+
def add_post(subreddit, id)
|
14
|
+
@posts[subreddit] = [] if @posts[subreddit].nil?
|
15
|
+
@posts[subreddit] << id
|
16
|
+
@posts[subreddit].shift if @posts[subreddit].count > Store::MAX_STORED_POSTS
|
17
|
+
end
|
18
|
+
|
19
|
+
def dup_post?(subreddit, id)
|
20
|
+
return false if posts[subreddit].nil?
|
21
|
+
|
22
|
+
posts[subreddit].include?(id)
|
23
|
+
end
|
24
|
+
|
25
|
+
def posts
|
26
|
+
@posts ||= {}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
module RedditToTelegram
|
6
|
+
module Store
|
7
|
+
class TempFile
|
8
|
+
STORE_FILE_DIR = "#{Dir.pwd}/tmp/store.json".freeze
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_reader :reddit_token, :posts
|
12
|
+
|
13
|
+
@reddit_token = nil
|
14
|
+
@posts = {}
|
15
|
+
|
16
|
+
def setup
|
17
|
+
read_file
|
18
|
+
end
|
19
|
+
|
20
|
+
def reddit_token=(val)
|
21
|
+
@reddit_token = val
|
22
|
+
write_file
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_post(subreddit, id)
|
26
|
+
@posts[subreddit] = [] if @posts[subreddit].nil?
|
27
|
+
@posts[subreddit] << id
|
28
|
+
@posts[subreddit].shift if @posts[subreddit].count > Store::MAX_STORED_POSTS
|
29
|
+
write_file
|
30
|
+
end
|
31
|
+
|
32
|
+
def dup_post?(subreddit, id)
|
33
|
+
return false if posts[subreddit].nil?
|
34
|
+
|
35
|
+
posts[subreddit].include?(id)
|
36
|
+
end
|
37
|
+
|
38
|
+
def read_file
|
39
|
+
return assign_default_values unless File.exist?(STORE_FILE_DIR)
|
40
|
+
|
41
|
+
file = File.read(STORE_FILE_DIR)
|
42
|
+
data = JSON.parse(file)
|
43
|
+
@reddit_token = data["reddit_token"]
|
44
|
+
@posts = {}
|
45
|
+
data.each do |key, value|
|
46
|
+
@posts[key.split("_").last.to_sym] = value if key.match?(/posts_.+/)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def write_file
|
51
|
+
data = { reddit_token: @reddit_token }
|
52
|
+
@posts.each do |subreddit, values|
|
53
|
+
data["posts_#{subreddit}".to_sym] = values
|
54
|
+
end
|
55
|
+
File.open(STORE_FILE_DIR, "w") { |f| f.write(data.to_json) }
|
56
|
+
end
|
57
|
+
|
58
|
+
def assign_default_values
|
59
|
+
@reddit_token = nil
|
60
|
+
@posts = {}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "store/aws_simple_db"
|
4
|
+
require_relative "store/memory"
|
5
|
+
require_relative "store/temp_file"
|
6
|
+
|
7
|
+
module RedditToTelegram
|
8
|
+
module Store
|
9
|
+
MAX_STORED_POSTS = Vars.max_stored_posts ? Vars.max_stored_posts - 1 : 24
|
10
|
+
STORE_MAP = {
|
11
|
+
aws_simple_db: "RedditToTelegram::Store::AWSSimpleDB",
|
12
|
+
memory: "RedditToTelegram::Store::Memory",
|
13
|
+
temp_file: "RedditToTelegram::Store::TempFile"
|
14
|
+
}.freeze
|
15
|
+
DEFAULT_STORE = :aws_simple_db
|
16
|
+
|
17
|
+
STORE = Object.const_get("RedditToTelegram::Store::AWSSimpleDB")
|
18
|
+
|
19
|
+
class << self
|
20
|
+
attr_accessor :active
|
21
|
+
|
22
|
+
def setup(selected_store = DEFAULT_STORE)
|
23
|
+
self.active = Object.const_get(STORE_MAP[selected_store.to_sym])
|
24
|
+
active.send(:setup)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Reddit
|
29
|
+
class << self
|
30
|
+
def token
|
31
|
+
Store.active.send(:reddit_token)
|
32
|
+
end
|
33
|
+
|
34
|
+
def token=(val)
|
35
|
+
Store.active.send(:reddit_token=, val)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Posts
|
41
|
+
class << self
|
42
|
+
def add(subreddit, id)
|
43
|
+
Store.active.send(:add_post, subreddit, id)
|
44
|
+
end
|
45
|
+
|
46
|
+
def dup?(subreddit, id)
|
47
|
+
Store.active.send(:dup_post?, subreddit, id)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "httparty"
|
4
|
+
require_relative "prepare_request"
|
5
|
+
require_relative "video"
|
6
|
+
|
7
|
+
module RedditToTelegram
|
8
|
+
module Telegram
|
9
|
+
class Post
|
10
|
+
include HTTParty
|
11
|
+
|
12
|
+
BASE_URI = "https://api.telegram.org/bot"
|
13
|
+
JSON_HEADERS = { "Content-Type" => "application/json", "Accept" => "application/json" }.freeze
|
14
|
+
FORM_HEADERS = { "Content-Type" => "multipart/form-data", "Accept" => "application/json" }.freeze
|
15
|
+
METHOD_MAP = {
|
16
|
+
image: :photo,
|
17
|
+
gallery: :mediagroup,
|
18
|
+
text: :message,
|
19
|
+
video: :video
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
class << self
|
23
|
+
def push(post, channel)
|
24
|
+
HTTParty.post(
|
25
|
+
"#{BASE_URI}#{Vars::Telegram.bot_token}/send#{METHOD_MAP[post[:type]]}",
|
26
|
+
**params(post, channel)
|
27
|
+
)
|
28
|
+
|
29
|
+
push({ type: :text, text: body[:caption] }, channel) if post[:type] == :gallery
|
30
|
+
Video.delete_file if post[:type] == :video
|
31
|
+
end
|
32
|
+
|
33
|
+
def params(post, channel)
|
34
|
+
binary = post.dig(:misc)&.dig(:binary)
|
35
|
+
body = PrepareRequest.body(post, channel)
|
36
|
+
|
37
|
+
pars = {
|
38
|
+
body: binary ? body : body.to_json,
|
39
|
+
headers: binary ? FORM_HEADERS : JSON_HEADERS
|
40
|
+
}
|
41
|
+
pars[:multipart] = true if binary
|
42
|
+
pars
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "video"
|
4
|
+
|
5
|
+
module RedditToTelegram
|
6
|
+
module Telegram
|
7
|
+
class PrepareRequest
|
8
|
+
class << self
|
9
|
+
def body(post, chat_id)
|
10
|
+
case post[:type]
|
11
|
+
when :image
|
12
|
+
{ chat_id: "@#{chat_id}", photo: post[:media], caption: prepare_text(post, chat_id) }
|
13
|
+
when :gallery
|
14
|
+
{ chat_id: "@#{chat_id}", media: prepare_gallery_media(post), caption: prepare_text(post, chat_id) }
|
15
|
+
when :text
|
16
|
+
{ chat_id: "@#{chat_id}", text: prepare_text(post, chat_id) }
|
17
|
+
when :video
|
18
|
+
{ chat_id: "@#{chat_id}", video: prepare_video(post), caption: prepare_text(post, chat_id) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def prepare_text(post, chat_id)
|
23
|
+
id = post[:id].split("_")[1]
|
24
|
+
"#{post[:text]}\n\nhttps://redd.it/#{id}\n@#{chat_id}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def prepare_gallery_media(post)
|
28
|
+
Array(post[:media]).map { |link| { type: "photo", media: link } }
|
29
|
+
end
|
30
|
+
|
31
|
+
def prepare_video(post)
|
32
|
+
return post[:media] unless post[:misc][:binary]
|
33
|
+
|
34
|
+
Video.from_link(post[:media])
|
35
|
+
File.open(Video::TEMP_VIDEO_PATH)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "open-uri"
|
4
|
+
|
5
|
+
module RedditToTelegram
|
6
|
+
module Telegram
|
7
|
+
class Video
|
8
|
+
TEMP_VIDEO_PATH = "#{Dir.pwd}/tmp/video.mp4".freeze
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def from_link(link)
|
12
|
+
download = URI.parse(link).open
|
13
|
+
IO.copy_stream(download, TEMP_VIDEO_PATH)
|
14
|
+
end
|
15
|
+
|
16
|
+
def delete_file
|
17
|
+
f = File.open(TEMP_VIDEO_PATH, "r")
|
18
|
+
ensure
|
19
|
+
f.close unless f.nil? || f.closed?
|
20
|
+
File.delete(TEMP_VIDEO_PATH) if File.exist?(TEMP_VIDEO_PATH)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RedditToTelegram
|
4
|
+
module Vars
|
5
|
+
class << self
|
6
|
+
# rubocop:disable Metrics/ParameterLists
|
7
|
+
def assign_values(
|
8
|
+
max_stored_posts:,
|
9
|
+
aws_access_key_id:,
|
10
|
+
aws_secret_access_key:,
|
11
|
+
aws_region:,
|
12
|
+
reddit_client_id:,
|
13
|
+
reddit_client_secret:,
|
14
|
+
telegram_bot_token:
|
15
|
+
)
|
16
|
+
|
17
|
+
@max_stored_posts = max_stored_posts
|
18
|
+
AWS.instance_variable_set(:@access_key_id, aws_access_key_id)
|
19
|
+
AWS.instance_variable_set(:@secret_access_key, aws_secret_access_key)
|
20
|
+
AWS.instance_variable_set(:@region, aws_region)
|
21
|
+
Reddit.instance_variable_set(:@client_id, reddit_client_id)
|
22
|
+
Reddit.instance_variable_set(:@client_secret, reddit_client_secret)
|
23
|
+
Telegram.instance_variable_set(:@bot_token, telegram_bot_token)
|
24
|
+
end
|
25
|
+
# rubocop:enable Metrics/ParameterLists
|
26
|
+
|
27
|
+
def max_stored_posts
|
28
|
+
@max_stored_posts ||= ENV["RTT_MAX_STORED_POSTS"].to_i || 25
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class AWS
|
33
|
+
class << self
|
34
|
+
def access_key_id
|
35
|
+
@access_key_id ||= ENV["RTT_AWS_ACCESS_KEY_ID"]
|
36
|
+
end
|
37
|
+
|
38
|
+
def secret_access_key
|
39
|
+
@secret_access_key ||= ENV["RTT_AWS_SECRET_ACCESS_KEY"]
|
40
|
+
end
|
41
|
+
|
42
|
+
def region
|
43
|
+
@region ||= ENV["RTT_AWS_REGION"]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Reddit
|
49
|
+
class << self
|
50
|
+
def client_id
|
51
|
+
@client_id ||= ENV["RTT_REDDIT_CLIENT_ID"]
|
52
|
+
end
|
53
|
+
|
54
|
+
def client_secret
|
55
|
+
@client_secret ||= ENV["RTT_REDDIT_CLIENT_SECRET"]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class Telegram
|
61
|
+
class << self
|
62
|
+
def bot_token
|
63
|
+
@bot_token ||= ENV["RTT_TELEGRAM_BOT_TOKEN"]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$:.push File.expand_path("../lib", __FILE__)
|
4
|
+
require "reddit_to_telegram/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "reddit-to-telegram"
|
8
|
+
s.version = RedditToTelegram::VERSION
|
9
|
+
s.summary = "Fetches hot posts from reddit and pushes them to telegram"
|
10
|
+
s.description = "This gem makes simple reddit-to-telegram ruby bots easy to create"
|
11
|
+
s.authors = ["Mark Tityuk"]
|
12
|
+
s.email = "mark.tityuk@gmail.com"
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.homepage = "https://github.com/dersnek/reddit-to-telegram"
|
15
|
+
s.license = "MIT"
|
16
|
+
|
17
|
+
s.add_dependency "aws-sdk-simpledb"
|
18
|
+
s.add_dependency "httparty"
|
19
|
+
|
20
|
+
s.add_development_dependency "rubocop"
|
21
|
+
end
|
data/tmp/.keep
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: reddit-to-telegram
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mark Tityuk
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-01-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aws-sdk-simpledb
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: httparty
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: This gem makes simple reddit-to-telegram ruby bots easy to create
|
56
|
+
email: mark.tityuk@gmail.com
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- ".gitignore"
|
62
|
+
- ".rubocop.yml"
|
63
|
+
- ".tool-versions"
|
64
|
+
- Gemfile
|
65
|
+
- Gemfile.lock
|
66
|
+
- README.md
|
67
|
+
- lib/reddit-to-telegram.rb
|
68
|
+
- lib/reddit_to_telegram/reddit/auth.rb
|
69
|
+
- lib/reddit_to_telegram/reddit/fetch.rb
|
70
|
+
- lib/reddit_to_telegram/reddit/output.rb
|
71
|
+
- lib/reddit_to_telegram/store.rb
|
72
|
+
- lib/reddit_to_telegram/store/aws_simple_db.rb
|
73
|
+
- lib/reddit_to_telegram/store/memory.rb
|
74
|
+
- lib/reddit_to_telegram/store/temp_file.rb
|
75
|
+
- lib/reddit_to_telegram/telegram/post.rb
|
76
|
+
- lib/reddit_to_telegram/telegram/prepare_request.rb
|
77
|
+
- lib/reddit_to_telegram/telegram/video.rb
|
78
|
+
- lib/reddit_to_telegram/vars.rb
|
79
|
+
- lib/reddit_to_telegram/version.rb
|
80
|
+
- reddit-to-telegram.gemspec
|
81
|
+
- tmp/.keep
|
82
|
+
homepage: https://github.com/dersnek/reddit-to-telegram
|
83
|
+
licenses:
|
84
|
+
- MIT
|
85
|
+
metadata: {}
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubygems_version: 3.4.10
|
102
|
+
signing_key:
|
103
|
+
specification_version: 4
|
104
|
+
summary: Fetches hot posts from reddit and pushes them to telegram
|
105
|
+
test_files: []
|