reddit-to-telegram 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|