ayadn 0.6.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +20 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +17 -0
  5. data/Gemfile +14 -0
  6. data/Guardfile +26 -0
  7. data/LICENSE.txt +22 -0
  8. data/MANUAL.md +946 -0
  9. data/README.md +26 -411
  10. data/Rakefile +6 -0
  11. data/ayadn.gemspec +39 -0
  12. data/bin/ayadn +3 -3
  13. data/lib/ayadn.rb +12 -25
  14. data/lib/ayadn/action.rb +1121 -0
  15. data/lib/ayadn/alias.rb +106 -0
  16. data/lib/ayadn/api.rb +312 -301
  17. data/lib/ayadn/app.rb +429 -365
  18. data/lib/ayadn/authorize.rb +127 -28
  19. data/lib/ayadn/blacklist.rb +116 -0
  20. data/lib/ayadn/cnx.rb +105 -0
  21. data/lib/ayadn/databases.rb +110 -0
  22. data/lib/ayadn/descriptions.rb +1043 -0
  23. data/lib/ayadn/endpoints.rb +220 -153
  24. data/lib/ayadn/errors.rb +37 -0
  25. data/lib/ayadn/extend.rb +4 -10
  26. data/lib/ayadn/fileops.rb +48 -0
  27. data/lib/ayadn/logs.rb +32 -0
  28. data/lib/ayadn/pinboard.rb +46 -35
  29. data/lib/ayadn/post.rb +229 -212
  30. data/lib/ayadn/scroll.rb +251 -0
  31. data/lib/ayadn/set.rb +377 -0
  32. data/lib/ayadn/settings.rb +195 -0
  33. data/lib/ayadn/status.rb +226 -165
  34. data/lib/ayadn/switch.rb +72 -0
  35. data/lib/ayadn/version.rb +4 -0
  36. data/lib/ayadn/view.rb +506 -269
  37. data/lib/ayadn/workers.rb +362 -0
  38. data/spec/helpers.rb +19 -0
  39. data/spec/mock/@ericd.json +160 -0
  40. data/spec/mock/@m.json +45 -0
  41. data/spec/mock/checkins.json +1856 -0
  42. data/spec/mock/fwr_@ayadn.json +1077 -0
  43. data/spec/mock/posted.json +1 -0
  44. data/spec/mock/stream.json +1 -0
  45. data/spec/spec_helper.rb +14 -0
  46. data/spec/unit/api_spec.rb +61 -0
  47. data/spec/unit/databases_spec.rb +5 -0
  48. data/spec/unit/descriptions_spec.rb +9 -0
  49. data/spec/unit/endpoints_spec.rb +35 -0
  50. data/spec/unit/post_spec.rb +136 -0
  51. data/spec/unit/status_spec.rb +9 -0
  52. data/spec/unit/view_spec.rb +119 -0
  53. data/spec/unit/workers_spec.rb +147 -0
  54. metadata +216 -40
  55. data/CHANGELOG.md +0 -250
  56. data/CONTRIBUTORS.md +0 -5
  57. data/LICENSE.md +0 -14
  58. data/lib/ayadn/adn_files.rb +0 -84
  59. data/lib/ayadn/client-http.rb +0 -226
  60. data/lib/ayadn/colors.rb +0 -62
  61. data/lib/ayadn/config.yml +0 -35
  62. data/lib/ayadn/debug.rb +0 -36
  63. data/lib/ayadn/files.rb +0 -184
  64. data/lib/ayadn/get-api.rb +0 -43
  65. data/lib/ayadn/help.rb +0 -152
  66. data/lib/ayadn/list.rb +0 -89
  67. data/lib/ayadn/main.rb +0 -542
  68. data/lib/ayadn/requires.rb +0 -12
  69. data/lib/ayadn/skip.rb +0 -27
  70. data/lib/ayadn/tools.rb +0 -208
  71. data/lib/ayadn/user-stream.rb +0 -91
  72. data/lib/ayadn/view-channels.rb +0 -120
  73. data/lib/ayadn/view-interactions.rb +0 -57
  74. data/lib/ayadn/view-object.rb +0 -195
  75. data/lib/experiments.rb +0 -109
data/lib/ayadn/logs.rb ADDED
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+ module Ayadn
3
+ class Logs
4
+ class << self
5
+ attr_accessor :rec
6
+ end
7
+ def self.create_logger
8
+ @rec = Logger.new(Settings.config[:paths][:log] + "/ayadn.log", 'monthly')
9
+ @rec.formatter = proc do |severity, datetime, progname, msg|
10
+ "#{datetime} (#{Settings.config[:version]}) #{severity} -- #{msg}\n"
11
+ end
12
+ end
13
+
14
+ # unused (experiment)
15
+ def self.send_log(from, args, content)
16
+ begin
17
+ log = {
18
+ "platform" => "#{Settings.config[:platform]}",
19
+ "date" => Time.now,
20
+ "version" => "#{Settings.config[:version]}",
21
+ "source" => from,
22
+ "args" => args,
23
+ "content" => content
24
+ }
25
+ Post.new.send_log(log)
26
+ rescue
27
+ @rec.warn("Unable to send log.")
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -1,37 +1,48 @@
1
- #!/usr/bin/env ruby
2
- require 'base64'
3
- require 'open-uri'
4
-
5
1
  # encoding: utf-8
6
- class AyaDN
7
- def ayadnBookmark(*args)
8
- post_id = args[0][1]
9
- tags = args[0][2]
10
- hash = @api.getSinglePost(post_id)
11
- data = hash['data']
12
- post_text = data['text']
13
- user_name = data['user']['username']
14
- link = data['entities']['links'][0]['url']
15
- if $tools.config['pinboard']['username'] != nil
16
- puts "\nSaving post ".green + post_id.brown + " to Pinboard...\n".green
17
- $tools.saveToPinboard(post_id, $tools.config['pinboard']['username'], URI.unescape(Base64::decode64($tools.config['pinboard']['password'])), link, tags, post_text, user_name)
18
- puts "Done!\n\n".green
19
- else
20
- puts "\nConfiguration does not include your Pinbard credentials.\n".red
21
- begin
22
- puts "Please enter your Pinboard username (CTRL+C to cancel): ".green
23
- pin_username = STDIN.gets.chomp()
24
- puts "\nPlease enter your Pinboard password (invisible, CTRL+C to cancel): ".green
25
- pin_password = STDIN.noecho(&:gets).chomp()
26
- rescue Exception
27
- abort($status.stopped)
28
- end
29
- $tools.config['pinboard']['username'] = pin_username
30
- $tools.config['pinboard']['password'] = URI.escape(Base64::encode64(pin_password))
31
- $tools.saveConfig
32
- puts "Saving post ".green + post_id.brown + " to Pinboard...\n".green
33
- $tools.saveToPinboard(post_id, pin_username, pin_password, link, tags, post_text, user_name)
34
- puts "Done!\n\n".green
35
- end
36
- end
2
+ module Ayadn
3
+ class PinBoard
4
+
5
+ def has_credentials_file?
6
+ File.exist?(Ayadn::Settings.config[:paths][:db] + '/ayadn_pinboard.db')
7
+ end
8
+
9
+ def ask_credentials
10
+ begin
11
+ puts "Please enter your Pinboard username (CTRL+C to cancel): ".color(:green)
12
+ pin_username = STDIN.gets.chomp()
13
+ puts "\nPlease enter your Pinboard password (invisible, CTRL+C to cancel): ".color(:green)
14
+ pin_password = STDIN.noecho(&:gets).chomp()
15
+ rescue Interrupt
16
+ abort(Status.canceled)
17
+ rescue => e
18
+ puts Status.wtf
19
+ Errors.global_error("pinboard/ask_credentials", pin_username, e)
20
+ end
21
+ save_credentials(encode(pin_username, pin_password))
22
+ end
23
+
24
+ def load_credentials
25
+ decode(File.read(Ayadn::Settings.config[:paths][:db] + '/ayadn_pinboard.db'))
26
+ end
27
+
28
+ def pin(data)
29
+ pinboard = Pinboard::Client.new(:username => data.username, :password => data.password)
30
+ pinboard.add(:url => data.url, :tags => data.tags, :extended => data.text, :description => data.description)
31
+ end
32
+
33
+ private
34
+
35
+ def decode(encoded_pinboard_credentials)
36
+ Base64.strict_decode64(encoded_pinboard_credentials[/AyadnPinboard (.*)/, 1]).split(":")
37
+ end
38
+
39
+ def save_credentials(encoded_pinboard_credentials)
40
+ File.write(Ayadn::Settings.config[:paths][:db] + '/ayadn_pinboard.db', encoded_pinboard_credentials)
41
+ end
42
+
43
+ def encode(username, password)
44
+ "AyadnPinboard #{Base64.strict_encode64([username, password].join(":"))}"
45
+ end
46
+
47
+ end
37
48
  end
data/lib/ayadn/post.rb CHANGED
@@ -1,212 +1,229 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
3
- class AyaDN
4
- def ayadn_compose_post
5
- puts $status.writePost + "\n"
6
- char_count = $tools.ayadn_configuration[:post_max_length]
7
- begin
8
- input_text = STDIN.gets.chomp
9
- rescue Exception
10
- abort($status.errorPostNotSent)
11
- end
12
- real_text_length = $tools.getMarkdownText(input_text.dup).length
13
- remaining_text_length = char_count - real_text_length
14
- if remaining_text_length >= 0
15
- ayadnSendPost(input_text, nil)
16
- else
17
- abort($status.errorPostTooLong(real_text_length, remaining_text_length.abs))
18
- end
19
- end
20
- def ayadnSendPost(text, reply_to = nil)
21
- abort($status.emptyPost) if (text == nil)
22
- puts $status.sendPost
23
- blob = JSON.parse(@api.httpSend(text, reply_to))
24
- @hash = blob['data']
25
- my_post_id = @hash['id']
26
- puts @view.new(nil).buildSimplePostInfo(@hash)
27
- puts $status.postSent
28
- if $tools.config['files']['auto_save_sent_posts']
29
- fileURL = $tools.ayadn_configuration[:posts_path] + "/#{my_post_id}.post"
30
- f = File.new(fileURL, "w")
31
- f.puts(@hash)
32
- f.close
33
- end
34
- if (reply_to == nil || reply_to.empty?)
35
- @hash = @api.getSimpleUnified
36
- stream, last_page_id = completeStream
37
- stream.sub!(/#{my_post_id}/, my_post_id.to_s.green.reverse_color)
38
- displayStream(stream)
39
- else
40
- @hash = @api.getPostReplies(reply_to)
41
- stream, last_page_id = completeStream
42
- stream.sub!(/#{reply_to}/, reply_to.to_s.red.reverse_color)
43
- stream.sub!(/#{my_post_id}/, my_post_id.to_s.green.reverse_color)
44
- displayStream(stream)
45
- end
46
- end
47
- def ayadn_quote(post_id)
48
- @progress_indicator = false
49
- post_to_quote = @api.getSinglePost(post_id)
50
- meta, data = post_to_quote['meta'], post_to_quote['data']
51
- puts "\n"
52
- if data['text'] != nil
53
- text_to_quote = $tools.withoutSquareBraces(data['text']).chomp(" ")
54
- else
55
- abort("\n\nError: no text to quote.\n\n".red)
56
- end
57
- @new_string = text_to_quote
58
- if data['entities']['links'] != nil
59
- data['entities']['links'].each do |obj|
60
- @new_string = text_to_quote.gsub("#{obj['text']}", "[#{obj['text']}](#{obj['url']})").chomp(" ")
61
- end
62
- end
63
- new_text = " >> @#{data['user']['username']}: " + (@new_string ||= text_to_quote)
64
- remaining = $tools.ayadn_configuration[:post_max_length] - $tools.getMarkdownText(new_text.dup).length - 1
65
- puts "AyaDN will automatically quote the original post like this after your comment. Markdown and embedded links will be preserved. (CTRL-C to cancel):\n".green
66
- puts '"' + $tools.getMarkdownText(new_text.dup) + '"' + "\n"
67
- abort("\nCANCELED: original text is too long, can't quote it.\n\n".red) if remaining <= 1
68
- puts "\n#{remaining}".magenta + " characters remaining. Write your comment: \n\n".brown
69
- begin
70
- input_text = STDIN.gets.chomp
71
- rescue Exception
72
- abort($status.errorPostNotSent)
73
- end
74
- new_text = input_text + new_text
75
- remaining = $tools.ayadn_configuration[:post_max_length] - $tools.getMarkdownText(new_text.dup).length
76
- abort("\n" + $status.errorPostTooLong(new_text.length, new_text.length - $tools.ayadn_configuration[:post_max_length])) if remaining <= 0
77
- ayadnSendPost(new_text)
78
- end
79
- def ayadn_reply(postID)
80
- @progress_indicator = false
81
- puts $status.replyingToPost(postID)
82
- post_mentions_array, replying_to_this_username, is_repost = @api.getPostMentions(postID)
83
- if is_repost != nil
84
- puts $status.errorIsRepost(postID)
85
- postID = is_repost['id']
86
- puts $status.redirectingToOriginal(postID)
87
- post_mentions_array, replying_to_this_username, is_repost = @api.getPostMentions(postID)
88
- end
89
- if $tools.config['identity']['prefix'] == "me"
90
- me_saved = $files.users_read("me")
91
- me_saved ? (my_username = me_saved) : (my_username = @api.getUserName("me"))
92
- else
93
- my_username = $tools.config['identity']['prefix']
94
- end
95
- #my_handle = "@" + my_username
96
- replying_to_handle = "@" + replying_to_this_username
97
- new_content = Array.new
98
- # if I'm not answering myself, add the @username of the "replyee"
99
- new_content.push(replying_to_handle) if replying_to_this_username != my_username
100
- post_mentions_array.each do |item|
101
- new_content.push("@" + item) if item != my_username
102
- end
103
- if new_content.length > 1
104
- all_mentions = new_content.dup
105
- leading_mention = all_mentions.first
106
- all_mentions.shift
107
- puts "\nThe leading mention (".green + leading_mention.red + ") has been put at the beginning of your post.\nThe rest of the mentions (".green + all_mentions.join(", ").red + ") will be added automatically at the end.".green
108
- end
109
- ayadn_compose_reply(postID, new_content)
110
- end
111
- def ayadn_compose_reply(reply_to, mentions_list = "")
112
- puts $status.writePost
113
- all_mentions = mentions_list.dup
114
- char_count = $tools.ayadn_configuration[:post_max_length]
115
- leading_mention = all_mentions.first
116
- mentions_list.shift
117
- mentions_list = mentions_list.join(" ")
118
- if leading_mention != nil
119
- text = leading_mention + " "
120
- char_count -= 1
121
- else
122
- text = ""
123
- end
124
- print "\n#{text}"
125
- begin
126
- input_text = STDIN.gets.chomp
127
- rescue Exception
128
- abort($status.errorPostNotSent)
129
- end
130
- if leading_mention != nil
131
- post_text = text + input_text + " " + mentions_list
132
- real_text_length = $tools.getMarkdownText(post_text.dup).length
133
- else
134
- post_text = input_text
135
- real_text_length = $tools.getMarkdownText(post_text.dup).length
136
- end
137
- remaining_text_length = char_count - real_text_length
138
- if remaining_text_length >= 0
139
- ayadnSendPost(post_text, reply_to)
140
- else
141
- abort($status.errorPostTooLong(real_text_length, real_text_length - $tools.ayadn_configuration[:post_max_length]))
142
- end
143
- end
144
-
145
-
146
- def ayadnComposeMessage(target)
147
- puts $status.writeMessage
148
- begin
149
- input_text = STDIN.gets.chomp
150
- rescue Exception
151
- abort($status.errorMessageNotSent)
152
- end
153
- real_length = $tools.getMarkdownText(input_text.dup).length
154
- if real_length < $tools.ayadn_configuration[:message_max_length]
155
- ayadnSendMessage(target, input_text)
156
- else
157
- abort($status.errorMessageTooLong(real_length, real_length - $tools.ayadn_configuration[:message_max_length]))
158
- end
159
- end
160
- def ayadnSendMessage(target, text)
161
- abort($status.emptyPost) if (text.empty? || text == nil)
162
- puts $status.sendMessage
163
- if target.is_integer?
164
- target = $files.load_channel_id(target)
165
- end
166
- blob = JSON.parse(@api.httpSendMessage(target, text))
167
- @hash = blob['data']
168
- private_message_channel_ID = @hash['channel_id']
169
- #private_message_thread_ID = @hash['thread_id']
170
- $files.makedir($tools.ayadn_configuration[:messages_path])
171
- puts "Channel ID: ".cyan + private_message_channel_ID.brown + " Message ID: ".cyan + @hash['id'].brown + "\n\n"
172
- puts $status.postSent
173
- $files.save_channel_id(private_message_channel_ID, target)
174
- # save message
175
- if $tools.config['files']['auto_save_sent_messages']
176
- fileURL = $tools.ayadn_configuration[:messages_path] + "/#{target}-#{@hash['id']}.post"
177
- f = File.new(fileURL, "w")
178
- f.puts(@hash)
179
- f.close
180
- end
181
- end
182
-
183
- def ayadnComposeMessageToChannel(target)
184
- puts $status.writeMessage
185
- begin
186
- input_text = STDIN.gets.chomp
187
- rescue Exception
188
- abort($status.errorMessageNotSent)
189
- end
190
- real_length = $tools.getMarkdownText(input_text.dup).length
191
- if real_length < $tools.ayadn_configuration[:message_max_length]
192
- ayadnSendMessageToChannel(target, input_text)
193
- else
194
- abort($status.errorMessageTooLong(real_length, real_length - $tools.ayadn_configuration[:message_max_length]))
195
- end
196
- end
197
- def ayadnSendMessageToChannel(target, text)
198
- abort($status.emptyPost) if (text.empty? || text == nil)
199
- puts $status.sendMessage
200
- if !target.is_integer?
201
- target = $files.load_channel_id(target)
202
- end
203
- blob = JSON.parse(@api.httpSendMessageToChannel(target, text))
204
- @hash = blob['data']
205
- private_channel_ID = @hash['channel_id']
206
- #private_thread_ID = @hash['thread_id']
207
- $files.makedir($tools.ayadn_configuration[:messages_path])
208
- puts "Channel ID: ".cyan + private_channel_ID.brown + " Message ID: ".cyan + @hash['id'].brown + "\n\n"
209
- puts $status.postSent
210
- $files.save_channel_id(private_channel_ID, target)
211
- end
212
- end
1
+ module Ayadn
2
+ class Post
3
+
4
+ def post(args)
5
+ unless text_is_empty?(args)
6
+ send_post(args.join(" "))
7
+ else
8
+ error_text_empty
9
+ end
10
+ end
11
+
12
+ def compose
13
+ case Settings.config[:platform]
14
+ when /mswin|mingw|cygwin/
15
+ post = classic
16
+ else
17
+ require "readline"
18
+ post = readline
19
+ end
20
+ post
21
+ end
22
+
23
+ def auto_classic
24
+ loop do
25
+ begin
26
+ print "#{Settings.config[:identity][:handle]} >> ".color(:red)
27
+ t = STDIN.gets.chomp
28
+ send_post(t)
29
+ puts Status.done
30
+ rescue Interrupt
31
+ abort(Status.canceled)
32
+ end
33
+ end
34
+ end
35
+
36
+ def auto_readline
37
+ loop do
38
+ begin
39
+ while buffer = Readline.readline("#{Settings.config[:identity][:handle]} >> ".color(:red))
40
+ send_post(buffer)
41
+ puts Status.done
42
+ end
43
+ rescue Interrupt
44
+ abort(Status.canceled)
45
+ end
46
+ end
47
+ end
48
+
49
+ def readline
50
+ puts Status.readline
51
+ post = []
52
+ begin
53
+ while buffer = Readline.readline("> ")
54
+ post << buffer
55
+ end
56
+ rescue Interrupt
57
+ #temp
58
+ Errors.info "Write post: canceled."
59
+ abort(Status.canceled)
60
+ end
61
+ post
62
+ end
63
+
64
+ def classic
65
+ puts Status.classic
66
+ input_text = STDIN.gets.chomp
67
+ [input_text]
68
+ end
69
+
70
+ def reply(new_post, replied_to)
71
+ replied_to = replied_to.values[0]
72
+ reply = replied_to[:handle].dup
73
+ reply << " #{new_post}"
74
+ replied_to[:mentions].uniq!
75
+ replied_to[:mentions].each do |m|
76
+ next if m == replied_to[:username]
77
+ next if m == Settings.config[:identity][:username]
78
+ reply << " @#{m}"
79
+ end
80
+ reply
81
+ end
82
+
83
+ def send_pm(username, text)
84
+ url = Endpoints.new.pm_url
85
+ url << "?include_annotations=1&access_token=#{Ayadn::Settings.user_token}"
86
+ send_content(url, payload_pm(username, text))
87
+ end
88
+
89
+ def send_message(channel_id, text)
90
+ url = Endpoints.new.messages(channel_id, {})
91
+ send_content(url, payload_basic(text))
92
+ end
93
+
94
+ def send_log(data)
95
+ url = Endpoints.new.ayadnlog
96
+ send_content(url, payload_log(data))
97
+ end
98
+
99
+ def send_post(text)
100
+ url = Endpoints.new.posts_url
101
+ send_content(url, payload_basic(text))
102
+ end
103
+
104
+ def send_reply(text, post_id)
105
+ url = Endpoints.new.posts_url
106
+ send_content(url, payload_reply(text, post_id))
107
+ end
108
+
109
+ def send_content(url, payload)
110
+ url << "?include_annotations=1&access_token=#{Ayadn::Settings.user_token}"
111
+ JSON.parse(CNX.post(url, payload))
112
+ end
113
+
114
+ def check_post_length(lines_array)
115
+ max_size = Settings.config[:post_max_length]
116
+ check_length(lines_array, max_size)
117
+ end
118
+
119
+ def check_message_length(lines_array)
120
+ max_size = Settings.config[:message_max_length]
121
+ check_length(lines_array, max_size)
122
+ end
123
+
124
+ def check_length(lines_array, max_size)
125
+ words_array = []
126
+ lines_array.each { |word| words_array << get_markdown_text(word) }
127
+ size = words_array.join.length
128
+ if size < 1
129
+ error_text_empty
130
+ exit
131
+ elsif size > max_size
132
+ Errors.warn "Canceled: too long (#{size - max_size}chars)"
133
+ abort("\n\nCanceled: too long. #{max_size} max, #{size - max_size} characters to remove.\n\n\n".color(:red))
134
+ end
135
+ end
136
+
137
+ def get_markdown_text(str)
138
+ str.gsub(/\[([^\]]+)\]\(([^)]+)\)/, '\1')
139
+ end
140
+
141
+ def markdown_extract(str)
142
+ result = str.gsub(/\[([^\]]+)\]\(([^)]+)\)/, '\1|||\2')
143
+ result.split('|||') #=> [text, link]
144
+ end
145
+
146
+ def text_is_empty?(args)
147
+ args.empty? || args[0] == ""
148
+ end
149
+
150
+ def error_text_empty
151
+ puts "\n\nYou should provide some text.\n\n".color(:red)
152
+ Errors.warn "-Post without text-"
153
+ end
154
+
155
+ def annotations
156
+ [
157
+ {
158
+ "type" => "com.ayadn.user",
159
+ "value" => {
160
+ "+net.app.core.user" => {
161
+ "user_id" => "#{Settings.config[:identity][:handle]}",
162
+ "format" => "basic"
163
+ }
164
+ }
165
+ },
166
+ {
167
+ "type" => "com.ayadn.client",
168
+ "value" => {
169
+ "url" => "http://ayadn-app.net",
170
+ "author" => {
171
+ "name" => "Eric Dejonckheere",
172
+ "username" => "ericd",
173
+ "id" => "69904",
174
+ "email" => "eric@aya.io"
175
+ },
176
+ "version" => "#{Settings.config[:version]}"
177
+ }
178
+ }
179
+ ]
180
+ end
181
+
182
+ def entities
183
+ {
184
+ "parse_markdown_links" => true,
185
+ "parse_links" => true
186
+ }
187
+ end
188
+
189
+ def payload_basic(text)
190
+ {
191
+ "text" => text,
192
+ "entities" => entities,
193
+ "annotations" => annotations
194
+ }
195
+ end
196
+
197
+ def payload_pm(username, text)
198
+ {
199
+ "text" => text,
200
+ "entities" => entities,
201
+ "destinations" => username,
202
+ "annotations" => annotations
203
+ }
204
+ end
205
+
206
+ def payload_reply(text, reply_to)
207
+ {
208
+ "text" => text,
209
+ "reply_to" => reply_to,
210
+ "entities" => entities,
211
+ "annotations" => annotations
212
+ }
213
+ end
214
+
215
+ def payload_log(data)
216
+ extended = annotations
217
+ extended << {
218
+ "type" => "com.ayadn.log",
219
+ "value" => data
220
+ }
221
+ return {
222
+ "text" => "#ayadnlog",
223
+ "entities" => entities,
224
+ "annotations" => extended
225
+ }
226
+ end
227
+
228
+ end
229
+ end