xasin-telegram 0.1.1.dev

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: '08a672d2bfc09cc9300f4079e89d575885db4d50'
4
+ data.tar.gz: c3cc7d5cc307f94739eb6d18ab6c8f69c7d088c6
5
+ SHA512:
6
+ metadata.gz: a5dc1b8a37e4b39036a1bdcfa36ce98c533c0db87944074aae5464364cecf62d8afe9e56c9db39ac67e56990dcd1f87bd612934a3e66c076f734bb791b3599ca
7
+ data.tar.gz: 62cd7a35febfa417839088c9f0806c4a66086f53b1d21b1ed1e75f6e6e7f7ce98de360127f63488cb44f14cfb2094a779be76c2fc26f56edec441ba1e97ca755
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+
2
+ # Xasin's simplifying Telegram gem
3
+ This gem is mainly meant for personal use.
4
+ Many of the existing Ruby gems for Telegram have all the functionality you want,
5
+ but also require a fairly complex setup, and good knowledge of the Telegram API.
6
+
7
+ My gem doesn't include all functionality, but aims to provide a somewhat simpler interface of
8
+ interaction with a small number (or just a single) of users.
9
+ I mainly use it for my own smart home system, to easily send and receive messages, but not much more.
10
+
11
+ ## Single-User mode
12
+ The main element of this gem is the single user mode.
13
+ It discards messages of all users except one, and provides a simple "send" and "on_message" interface:
14
+
15
+ ```Ruby
16
+ require 'xasin/telegram.rb'
17
+
18
+ # The HTTP "core" handles sending raw commands and getting updates, but not much more.
19
+ httpCore = Xasin::Telegram::HTTPCore.new(APIKEY);
20
+
21
+ # The SingleUser class handles the aforementioned sending/receiving of messages.
22
+ # Its first argument is the Chat-ID it should use, which is NOT the user ID
23
+ # To find it out you have to perform an update request to the Telegram API, send a message to your bot,
24
+ # and get the Chat_ID from there.
25
+ # I'm working on a better way >.>
26
+ singleUser = Xasin::Telegram::SingleUser.new(CHAT_ID, httpCore);
27
+
28
+
29
+ # From then, using the user is simple. Only text is required!
30
+ returned_id = singleUser.send_message(TEXT, **args);
31
+
32
+ # The ID that is returned can then be used to edit or delete the message:
33
+ singleUser.edit_message(returned_id, NEW_TEXT);
34
+ singleUser.delete_message(returned_id);
35
+
36
+ # And to receive messages:
37
+ singleUser.on_message do |message|
38
+ # Fetch the text from the message first!
39
+ text = message[:text];
40
+ end
41
+ ```
@@ -0,0 +1,66 @@
1
+
2
+ require 'net/http'
3
+ require 'json'
4
+
5
+ module Xasin
6
+ module Telegram
7
+ class HTTPCore
8
+ def initialize(apikey)
9
+ @apikey = apikey;
10
+
11
+ @lastUpdateID = 0;
12
+ Thread.new do
13
+ receive_loop();
14
+ end.abort_on_exception = true
15
+
16
+ @receptors = Array.new();
17
+ end
18
+
19
+ def perform_post(method, data = nil)
20
+ callAddress = URI "https://api.telegram.org/bot#{@apikey}/#{method}"
21
+
22
+ begin
23
+ if data
24
+ response = Net::HTTP.post_form(callAddress, data);
25
+ else
26
+ response = Net::HTTP.get callAddress
27
+ end
28
+
29
+ response = JSON.parse(response.body, symbolize_names: true);
30
+ rescue
31
+ sleep 0.5;
32
+ retry
33
+ end
34
+
35
+ return response;
36
+ end
37
+
38
+ def receive_loop()
39
+ loop do
40
+ begin
41
+ packet = perform_post("getUpdates", {timeout: 20, offset: @lastUpdateID + 1})
42
+
43
+ next unless packet[:ok];
44
+ next if packet[:result].length == 0;
45
+
46
+ packet[:result].each do |data|
47
+ hUpdateID = data[:update_id].to_i
48
+ @lastUpdateID = [hUpdateID, @lastUpdateID].max
49
+
50
+ @receptors.each do |r|
51
+ r.handle_packet(data);
52
+ end
53
+ end
54
+ rescue
55
+ sleep 1
56
+ retry
57
+ end
58
+ end
59
+ end
60
+
61
+ def attach_receptor(receptorClass)
62
+ @receptors << receptorClass;
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,145 @@
1
+
2
+ require 'mqtt/sub_handler'
3
+
4
+ module Xasin
5
+ module Telegram
6
+ module MQTT
7
+ class Server
8
+ attr_accessor :usernameList
9
+
10
+ def initialize(httpCore, mqtt)
11
+ if(httpCore.is_a? Telegram::HTTPCore)
12
+ @httpCore = httpCore;
13
+ else
14
+ @httpCore = Telegram::HTTPCore.new(httpCore);
15
+ end
16
+ @httpCore.attach_receptor(self);
17
+
18
+ @mqtt = mqtt;
19
+
20
+ # Hash {username => ChatID}
21
+ @usernameList = Hash.new();
22
+ # Hash {ChatID => {GroupID => MessageID}}
23
+ @groupIDList = Hash.new();
24
+
25
+ setup_mqtt();
26
+ end
27
+
28
+ # Processes messages received through MQTT
29
+ # It takes care of setting a few good defaults (like parse_mode),
30
+ # deletes any old messages of the same GroupID (if requested),
31
+ # and stores the new Message ID for later processing
32
+ # @param data [Hash] The raw "message" object received from the Telegram API
33
+ # @param uID [Integer,String] The user-id as received from the MQTT Wildcard.
34
+ # Can be a username defined in @usernameList
35
+ def _handle_send(data, uID)
36
+ # Resolve a saved Username to a User-ID
37
+ uID = @usernameList[uID] if(@usernameList.key? uID)
38
+ uID = uID.to_i;
39
+
40
+ begin
41
+ data = JSON.parse(data, symbolize_names: true);
42
+ rescue
43
+ # Allow for pure-text to be sent (easier on the ESPs)
44
+ data = {text: data}
45
+ end
46
+
47
+ data[:parse_mode] ||= "Markdown";
48
+ data[:chat_id] = uID;
49
+
50
+ reply = @httpCore.perform_post("sendMessage", data);
51
+
52
+ # Check if this message has a grouping ID
53
+ if(gID = data[:GID])
54
+ # If the message has the :single flag, delete the last one
55
+ if(data[:single])
56
+ _handle_delete(gID, uID);
57
+ end
58
+
59
+ # Save this grouping ID
60
+ @groupIDList[uID][gID] = reply[:result][:message_id];
61
+ end
62
+ end
63
+
64
+ def _handle_edit(data, uID)
65
+ # Resolve a saved Username to a User-ID
66
+ uID = @usernameList[uID] if(@usernameList.key? uID)
67
+ uID = uID.to_i;
68
+
69
+ begin
70
+ data = JSON.parse(data, symbolize_names: true);
71
+
72
+ return unless data[:text];
73
+ # Fetch the target Message ID
74
+ return unless mID = @groupIDList[uID][data[:GID]]
75
+
76
+ # Send the POST request editing the message text
77
+ @httpCore.perform_post("editMessageText",
78
+ { text: data[:text],
79
+ chat_id: uID,
80
+ message_id: mID});
81
+ rescue
82
+ end
83
+ end
84
+
85
+ def _handle_delete(data, uID)
86
+ # Resolve a saved Username to a User-ID
87
+ uID = @usernameList[uID] if(@usernameList.key? uID)
88
+ uID = uID.to_i;
89
+
90
+ # Fetch the real message ID held by a grouping ID
91
+ return unless mID = @groupIDList[uID][data]
92
+ @groupIDList[uID].delete(data);
93
+
94
+ @httpCore.perform_post("deleteMessage", {chat_id: uID, message_id: mID});
95
+ end
96
+
97
+ def setup_mqtt()
98
+ @mqtt.subscribe_to "Telegram/+/Send" do |data, tSplit|
99
+ _handle_send(data, tSplit[0]);
100
+ end
101
+
102
+ @mqtt.subscribe_to "Telegram/+/Edit" do |data, tSplit|
103
+ _handle_edit(data, tSplit[0])
104
+ end
105
+
106
+ @mqtt.subscribe_to "Telegram/+/Delete" do |data, tSplit|
107
+ _handle_delete(data, tSplit[0])
108
+ end
109
+
110
+ @mqtt.subscribe_to "Telegram/+/Release" do |data, tSplit|
111
+ # Resolve a saved Username to a User-ID
112
+ uID = tSplit[0];
113
+ uID = @usernameList[uID] if(@usernameList.key? uID)
114
+ uID = uID.to_i;
115
+
116
+ # Delete the stored GID key
117
+ @groupIDList[uID].delete(data);
118
+ end
119
+ end
120
+
121
+ def handle_packet(packet)
122
+ if(msg = packet[:message])
123
+ uID = msg[:chat][:id];
124
+ if(newUID = @usernameList.key(uID))
125
+ uID = newUID
126
+ end
127
+
128
+ data = Hash.new();
129
+ return unless(data[:text] = msg[:text])
130
+
131
+ if(replyMSG = msg[:reply_to_message])
132
+ data[:reply_GID] = @groupIDList[uID].key(replyMSG[:message_id]);
133
+ end
134
+
135
+ if(data[:reply_GID])
136
+ @mqtt.publish_to "Telegram/#{uID}/Reply", data;
137
+ else
138
+ @mqtt.publish_to "Telegram/#{uID}/Received", data;
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,73 @@
1
+
2
+ require_relative "HTTPCore.rb"
3
+
4
+ module Xasin
5
+ module Telegram
6
+ class SingleUser
7
+ attr_reader :httpCore
8
+
9
+ def initialize(userChat, httpCore)
10
+ @httpCore = httpCore.is_a?(Telegram::HTTPCore) ? httpCore : HTTPCore.new(httpCore);
11
+ @httpCore.attach_receptor(self);
12
+
13
+ @userID = userChat;
14
+
15
+ @message_procs = Array.new();
16
+ @inlinebutton_procs = Array.new();
17
+ end
18
+
19
+ def handle_packet(packet)
20
+ if(packet[:message]) then
21
+ return unless packet[:message][:chat][:id] == @userID;
22
+
23
+ @message_procs.each do |cb| cb.call(packet[:message]); end
24
+ packet[:has_been_handled] = true;
25
+ end
26
+
27
+ if(packet[:callback_query]) then
28
+ return unless packet[:callback_query][:message][:chat][:id] == @userID;
29
+
30
+ @inlinebutton_procs.each do |cb| cb.call(packet[:callback_query]); end
31
+ packet[:has_been_handled] = true;
32
+ end
33
+ end
34
+
35
+ def send_message(text, **args)
36
+ args ||= Hash.new();
37
+ args[:text] = text;
38
+
39
+ args[:chat_id] = @userID;
40
+ args[:parse_mode] ||= "Markdown";
41
+
42
+ sent_message = @httpCore.perform_post("sendMessage", args);
43
+
44
+ return sent_message[:result][:message_id];
45
+ end
46
+
47
+ def edit_message(mID, text=nil, **args)
48
+ args[:chat_id] = @userID;
49
+ args[:message_id] = mID;
50
+
51
+ args[:parse_mode] ||= "Markdown";
52
+
53
+ if(text) then
54
+ args[:text] = text;
55
+ @httpCore.perform_post("editMessageText", args);
56
+ else
57
+ @httpCore.perform_post("editMessageReplyMarkup", args);
58
+ end
59
+ end
60
+
61
+ def delete_message(mID)
62
+ @httpCore.perform_post("deleteMessage", {chat_id: @userID, message_id: mID});
63
+ end
64
+
65
+ def on_message(&block)
66
+ @message_procs << block;
67
+ end
68
+ def on_inlinebutton_press(&block)
69
+ @inlinebutton_procs << block;
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,3 @@
1
+
2
+ require_relative "Telegram/HTTPCore.rb"
3
+ require_relative "Telegram/SingleUser.rb"
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xasin-telegram
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1.dev
5
+ platform: ruby
6
+ authors:
7
+ - Xasin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-06-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mqtt-sub_handler
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
+ description: Multi-Purpose Telegram gem. Mainly for personal use, but also used as
28
+ a Telegram to MQTT Bridge for IoT devices
29
+ email:
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - README.md
35
+ - lib/xasin/telegram.rb
36
+ - lib/xasin/telegram/HTTPCore.rb
37
+ - lib/xasin/telegram/MQTT_Adapter.rb
38
+ - lib/xasin/telegram/SingleUser.rb
39
+ homepage: https://github.com/XasWorks/XasCode/tree/GEM_Telegram/Ruby/Telegram
40
+ licenses:
41
+ - GPL-3.0
42
+ metadata: {}
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">"
55
+ - !ruby/object:Gem::Version
56
+ version: 1.3.1
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 2.6.14.1
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: Xasin's Telegram gem
63
+ test_files: []