ayadn 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/ayadn/post.rb ADDED
@@ -0,0 +1,212 @@
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
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ %w{rubygems pstore date open-uri net/http json io/console fileutils yaml pinboard base64}.each do |r|
5
+ require "#{r}"
6
+ end
7
+
8
+ winPlatforms = ['mswin', 'mingw', 'mingw_18', 'mingw_19', 'mingw_20', 'mingw32']
9
+ case Gem::Platform.local.os
10
+ when *winPlatforms
11
+ require 'win32console'
12
+ end
data/lib/ayadn/skip.rb ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+ class AyaDN
4
+ def ayadn_skip_add(kind, target) #kind: sources,hashtags,mentions
5
+ puts "Current skipped #{kind}: ".green + $tools.config['skipped']["#{kind}"].join(", ").red + "\n\n"
6
+ puts "Adding ".green + target.red + " to the skipped #{kind}.".green + "\n\n"
7
+ $tools.config['skipped']["#{kind}"].each do |in_config|
8
+ if in_config == target
9
+ puts target.red + " is already skipped.\n\n".green
10
+ exit
11
+ end
12
+ end
13
+ $tools.config['skipped']["#{kind}"].push(target)
14
+ puts "New skipped #{kind}: ".green + $tools.config['skipped']["#{kind}"].join(", ").red + "\n\n"
15
+ $tools.saveConfig
16
+ end
17
+ def ayadn_skip_remove(kind, target)
18
+ puts "Removing ".green + target.red + " from the skipped #{kind}.".green + "\n\n"
19
+ $tools.config['skipped']["#{kind}"].each do |in_config|
20
+ if in_config == target
21
+ $tools.config['skipped']["#{kind}"].delete(in_config)
22
+ end
23
+ end
24
+ puts "New skipped #{kind}: ".green + $tools.config['skipped']["#{kind}"].join(", ").red + "\n\n"
25
+ $tools.saveConfig
26
+ end
27
+ end
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+ class AyaDN
4
+ class ClientStatus
5
+ def canceled
6
+ "\nCanceled.\n\n".red
7
+ end
8
+ def showList(list, name)
9
+ if list == "muted"
10
+ "Your list of muted users:\n".green
11
+ elsif list == "followings"
12
+ "List of users ".green + "#{name} ".brown + "is following:\n".green
13
+ elsif list == "followers"
14
+ "List of ".green + "#{name}".brown + "'s followers:\n".green
15
+ end
16
+ end
17
+ def getInteractions
18
+ "\nLoading the ".green + "interactions ".brown + "informations.\n".green
19
+ end
20
+ def launchAuthorization(os)
21
+ if os == "osx"
22
+ "\nAyaDN opened a browser to authorize via App.net very easily. Just login with your App.net account, then copy the code it will give you, paste it here then press [ENTER].".pink + " Paste authorization code: \n\n".brown
23
+ else
24
+ s = "\nPlease open a browser and paste this URL: \n\n".brown
25
+ s += "https://account.app.net/oauth/authenticate?client_id=hFsCGArAjgJkYBHTHbZnUvzTmL4vaLHL&response_type=token&redirect_uri=http://aya.io/ayadn/auth.html&scope=basic stream write_post follow public_messages messages&include_marker=1"
26
+ s += "\n\nOn this page, login with your App.net account, then copy the code it will give you, paste it here then press [ENTER].".pink + " Paste authorization code: \n\n".brown
27
+ end
28
+ end
29
+ def authorized
30
+ "\nThank you for authorizing AyaDN. You won't need to do this anymore.\n\n".green
31
+ end
32
+ def noNewPosts
33
+ "\nNo new posts since your last visit.\n\n".red
34
+ end
35
+ def errorEmptyList
36
+ "\nThe list is empty.\n\n".red
37
+ end
38
+ def errorSyntax
39
+ "\nSyntax error.\n\n".red
40
+ end
41
+ def errorNotAuthorized
42
+ "\nYou haven't authorized AyaDN yet.\n\n".red
43
+ end
44
+ def errorNobodyReposted
45
+ "\nThis post hasn't been reposted by anyone.\n\n".red
46
+ end
47
+ def errorNobodyStarred
48
+ "\nThis post hasn't been starred by anyone.\n\n".red
49
+ end
50
+ def errorNoID
51
+ "\nError -> you must give a post ID to reply to.\n\n".red
52
+ end
53
+ def emptyPost
54
+ "\nError -> there was no text to post.\n\n".red
55
+ end
56
+ def errorInfos(arg)
57
+ "\nError -> ".red + "#{arg}".brown + " isn't a @username or a Post ID\n\n".red
58
+ end
59
+ def errorUserID(arg)
60
+ "\nError -> ".red + "#{arg}".brown + " is not a @username\n\n".red
61
+ end
62
+ def errorPostID(arg)
63
+ "\nError -> ".red + "#{arg}".brown + " is not a Post ID\n\n".red
64
+ end
65
+ def errorMessageNotSent
66
+ "\n\nCanceled. Your message hasn't been sent.\n\n".red
67
+ end
68
+ def errorMessageTooLong(realLength, to_remove)
69
+ "\nError: your message is ".red + "#{realLength} ".brown + "characters long, please remove ".red + "#{to_remove} ".brown + "characters.\n\n".red
70
+ end
71
+ def errorPostTooLong(realLength, to_remove)
72
+ "\nError: your post is ".red + "#{realLength} ".brown + " characters long, please remove ".red + "#{to_remove} ".brown + "characters.\n\n".red
73
+ end
74
+ def errorPostNotSent
75
+ "\n\nCanceled. Your post hasn't been sent.\n\n".red
76
+ end
77
+ def errorIsRepost(postID)
78
+ "\n#{postID} ".brown + " is a repost.\n".red
79
+ end
80
+ def errorAlreadyDeleted
81
+ "\nPost already deleted.\n\n".red
82
+ end
83
+ def redirectingToOriginal(postID)
84
+ "Redirecting to the original post: ".cyan + "#{postID}\n".brown
85
+ end
86
+ def fetchingList(list)
87
+ "\nFetching the \'#{list}\' list. Please wait\n".green
88
+ end
89
+ def getUnified
90
+ "\nLoading the ".green + "unified ".brown + "Stream".green
91
+ end
92
+ def getExplore(explore)
93
+ "\nLoading the ".green + "#{explore}".brown + " Stream".green
94
+ end
95
+ def getGlobal
96
+ "\nLoading the ".green + "global ".brown + "Stream".green
97
+ end
98
+ def whoReposted(arg)
99
+ s = "\nLoading informations on post ".green + "#{arg}".brown + "\n "
100
+ s += "\nReposted by: \n".cyan
101
+ end
102
+ def whoStarred(arg)
103
+ s = "\nLoading informations on post ".green + "#{arg}".brown + "\n"
104
+ s += "\nStarred by: \n".cyan
105
+ end
106
+ def infosUser(arg)
107
+ "\nLoading informations on ".green + "#{arg}".brown + "\n"
108
+ end
109
+ def infosPost(arg)
110
+ "\nLoading informations on post ".green + "#{arg}".brown + "\n"
111
+ end
112
+ def postsUser(arg)
113
+ "\nLoading posts of ".green + "#{arg}".brown + "\n"
114
+ end
115
+ def mentionsUser(arg)
116
+ "\nLoading posts mentionning ".green + "#{arg}".brown + "\n"
117
+ end
118
+ def starsUser(arg)
119
+ "\nLoading ".green + "#{arg}".reddish + "'s favorite posts\n".green
120
+ end
121
+ def starsPost(arg)
122
+ "\nLoading users who starred post ".green + "#{arg}".reddish + "\n"
123
+ end
124
+ def getHashtags(arg)
125
+ "\nLoading posts containing ".green + "##{arg}".pink + "\n".green
126
+ end
127
+ def sendPost
128
+ "\nSending post\n".green
129
+ end
130
+ def sendMessage
131
+ "\nSending private Message\n".green
132
+ end
133
+ def postSent
134
+ "Successfully posted\n".green
135
+ end
136
+ def postDeleted
137
+ "\nPost successfully deleted\n".green
138
+ end
139
+ def replyingToPost(postID)
140
+ "\nReplying to post ".cyan + "#{postID}\n".brown
141
+ end
142
+ def deletePost(postID)
143
+ "\nDeleting post ".green + "#{postID}".brown + "\n"
144
+ end
145
+ def getPostReplies(arg)
146
+ "\nLoading the conversation around post ".green + "#{arg}".brown + "\n"
147
+ end
148
+ def writePost
149
+ s = "\n#{$tools.ayadn_configuration[:post_max_length]} characters max, validate with [Enter] or cancel with [CTRL+C].\n".green
150
+ s += "\nType your text: ".cyan
151
+ end
152
+ def writeMessage
153
+ s = "\n#{$tools.ayadn_configuration[:message_max_length]} characters max, validate with [Enter] or cancel with [CTRL+C].\n".green
154
+ s += "\nType your text: ".cyan + "\n\n"
155
+ end
156
+ def writeReply(arg)
157
+ "\nLoading informations of post " + "#{arg}".brown + "\n"
158
+ end
159
+ def savingFile(name, path, file)
160
+ "\nSaving ".green + "#{name} ".brown + "in ".green + "#{path}#{file}".magenta
161
+ end
162
+ def stopped
163
+ "\n\nStopped.\n\n".red
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,204 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+ require 'yaml'
4
+ require 'rubygems'
5
+ require 'pinboard'
6
+
7
+ class AyaDN
8
+ class Tools
9
+ def initialize
10
+ @default_ayadn_data_path = Dir.home + "/ayadn/data"
11
+ @installed_config_path = "#{@default_ayadn_data_path}/config.yml"
12
+ @configFileContents = loadConfig
13
+ identityPrefix = @configFileContents['identity']['prefix']
14
+ ayadn_data_path = Dir.home + @configFileContents['files']['ayadnfiles']
15
+ @ayadn_configuration = {
16
+ data_path: ayadn_data_path,
17
+ posts_path: ayadn_data_path + "/#{identityPrefix}/posts",
18
+ lists_path: ayadn_data_path + "/#{identityPrefix}/lists",
19
+ files_path: ayadn_data_path + "/#{identityPrefix}/files",
20
+ db_path: ayadn_data_path + "/#{identityPrefix}/db",
21
+ last_page_id_path: ayadn_data_path + "/#{identityPrefix}/.pagination",
22
+ messages_path: ayadn_data_path + "/#{identityPrefix}/messages",
23
+ authorization_path: ayadn_data_path + "/#{identityPrefix}/.auth",
24
+ api_config_path: ayadn_data_path + "/#{identityPrefix}/.api",
25
+ progress_indicator: false,
26
+ platform: RbConfig::CONFIG['host_os']
27
+ }
28
+ end
29
+ def loadConfig
30
+ if File.exists?(@installed_config_path)
31
+ YAML::load_file(@installed_config_path)
32
+ elsif File.exists?('./config.yml')
33
+ YAML::load_file('./config.yml')
34
+ else
35
+ {
36
+ "counts" => {
37
+ "global" => 100,
38
+ "unified" => 100,
39
+ "checkins" => 100,
40
+ "explore" => 100,
41
+ "mentions" => 100,
42
+ "starred" => 100,
43
+ "posts" => 100,
44
+ "search" => 200
45
+ },
46
+ "timeline" => {
47
+ "downside" => true,
48
+ "directed" => true,
49
+ "streamback" => 30,
50
+ "countdown_1" => 5,
51
+ "countdown_2" => 15,
52
+ "show_client" => false,
53
+ "show_symbols" => true,
54
+ "show_reposters" => false
55
+ },
56
+ "files" => {
57
+ "ayadnfiles" => "/ayadn/data",
58
+ "auto_save_sent_messages" => false,
59
+ "auto_save_sent_posts" => false
60
+ },
61
+ "identity" => { "prefix" => "me" },
62
+ "skipped" => {
63
+ "sources" => [],
64
+ "hashtags" => [],
65
+ "mentions" => []
66
+ },
67
+ "pinboard" => {
68
+ "username" => "",
69
+ "password" => ""
70
+ }
71
+ }
72
+ end
73
+ end
74
+ def saveConfig
75
+ if File.exists?(@installed_config_path)
76
+ File.open(@installed_config_path, 'w') {|f| f.write config.to_yaml }
77
+ puts "\nDone!\n\n".green
78
+ else
79
+ File.open('./config.yml', 'w') {|f| f.write config.to_yaml }
80
+ puts "\nDone!\n\n".green
81
+ end
82
+ end
83
+ def installConfig
84
+ if File.exists?(@installed_config_path)
85
+ puts "\nInstalled config file already exists. Replace with the new one? (N/y) ".red
86
+ if STDIN.getch == ("y" || "Y")
87
+ copyConfigFromMaster
88
+ else
89
+ abort("\nCanceled.\n\n".red)
90
+ end
91
+ else
92
+ copyConfigFromMaster
93
+ end
94
+ end
95
+ def copyConfigFromMaster
96
+ FileUtils.cp('./config.yml', @installed_config_path)
97
+ puts "\nDone.\n\n".green
98
+ end
99
+ def config
100
+ @configFileContents
101
+ end
102
+ def ayadn_configuration
103
+ @ayadn_configuration
104
+ end
105
+ def winplatforms
106
+ /mswin|mingw|mingw32|cygwin/
107
+ end
108
+ def colorize(contentText)
109
+ content = Array.new
110
+ for word in contentText.split(" ") do
111
+ if word =~ /#\w+/
112
+ content.push(word.gsub(/#([A-Za-z0-9_]{1,255})(?![\w+])/, '#\1'.pink))
113
+ #content.push(removeEndCharIfSpecial(word, "pink"))
114
+ elsif word =~ /@\w+/
115
+ content.push(word.gsub(/@([A-Za-z0-9_]{1,20})(?![\w+])/, '@\1'.red))
116
+ #content.push(removeEndCharIfSpecial(word, "red"))
117
+ #elsif word =~ /^http/ or word =~ /^photos.app.net/ or word =~ /^files.app.net/ or word =~ /^chimp.li/ or word =~ /^bli.ms/
118
+ #content.push(word.magenta)
119
+ else
120
+ content.push(word)
121
+ end
122
+ end
123
+ content.join(" ")
124
+ end
125
+ def removeEndCharIfSpecial(word, color)
126
+ word_array = word.chars.to_a
127
+ last_char = word_array.last
128
+ if last_char =~ /[.,:;?!-'`&"()\/]/
129
+ word_array.pop
130
+ if color == "red"
131
+ word_colored = word_array.join("").red
132
+ elsif color == "pink"
133
+ word_colored = word_array.join("").pink
134
+ end
135
+ word_colored.chars.to_a.push(last_char).join("")
136
+ else
137
+ if color == "red"
138
+ word.red
139
+ elsif color == "pink"
140
+ word.pink
141
+ end
142
+ end
143
+ end
144
+
145
+ def getMarkdownText(str)
146
+ str.gsub %r{
147
+ \[ # Literal opening bracket
148
+ ( # Capture what we find in here
149
+ [^\]]+ # One or more characters other than close bracket
150
+ ) # Stop capturing
151
+ \] # Literal closing bracket
152
+ \( # Literal opening parenthesis
153
+ ( # Capture what we find in here
154
+ [^)]+ # One or more characters other than close parenthesis
155
+ ) # Stop capturing
156
+ \) # Literal closing parenthesis
157
+ }x, '\1'
158
+ end
159
+ def withoutSquareBraces(str)
160
+ str.gsub %r{
161
+ \[ # Literal opening bracket
162
+ ( # Capture what we find in here
163
+ [^\]]+ # One or more characters other than close bracket
164
+ ) # Stop capturing
165
+ \] # Literal closing bracket
166
+ }x, ''
167
+ end
168
+ def countdown(value)
169
+ value.downto(1) do |i|
170
+ print "\r#{sprintf("%02d", i)} sec... QUIT WITH [CTRL+C]".cyan
171
+ sleep 1
172
+ end
173
+ end
174
+ def startBrowser(url)
175
+ Process.detach(Process.spawn("sleep 1; open '#{url}'"))
176
+ end
177
+ def meta(meta)
178
+ case meta['code']
179
+ when 200
180
+ puts "\nDone!\n".green
181
+ when 301,302
182
+ puts "\nRedirected.\n\n".red
183
+ puts "#{meta.inspect}\n".red
184
+ when 404
185
+ puts "Does not exist (or has been deleted).\n\n".red
186
+ exit
187
+ else
188
+ abort("\nERROR: #{meta.to_s}\n".red)
189
+ end
190
+ end
191
+ def checkHTTPResp(resp)
192
+ case resp.code
193
+ when !200
194
+ abort("\nERROR: does not exist (or has been deleted) => #{resp.code} #{resp.body}\n".red)
195
+ end
196
+ end
197
+ def saveToPinboard(post_id, pin_username, pin_password, link, tags, post_text, user_name)
198
+ tags += ",ADN"
199
+ post_text += " http://alpha.app.net/#{user_name}/post/#{post_id}"
200
+ pinboard = Pinboard::Client.new(:username => pin_username, :password => pin_password)
201
+ pinboard.add(:url => link, :tags => tags, :extended => post_text, :description => link)
202
+ end
203
+ end
204
+ end