File: yo_update.rb

package info (click to toggle)
tdiary-contrib 5.0.2-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 2,576 kB
  • ctags: 1,957
  • sloc: ruby: 16,900; lisp: 514; xml: 451; php: 61; sql: 40; sh: 35; makefile: 33
file content (233 lines) | stat: -rw-r--r-- 6,890 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# -*- coding: utf-8 -*-
#
# yo_update.rb - Yo all when an entry or a comment is posted
#
# Copyright (C) 2014, zunda <zundan at gmail.com>
#
# Permission is granted for use, copying, modification,
# distribution, and distribution of modified versions of this
# work under the terms of GPL version 2 or later.
#

require 'uri'
require 'timeout'
require 'net/http'
require 'json'

YO_UPDATE_TIMEOUT = 10

class YoUpdateError < StandardError; end

def yo_update_url(date = nil, frag = nil)	# date: Time frag: e.g. 'p01'
	url = @conf.index.dup
	url[0, 0] = base_url unless %r|^https?://|i =~ url
	url.gsub!( %r|/\./|, '/' )
	if date
		ymd = date.strftime('%Y%m%d')
		anc = frag ? "#{ymd}##{frag}" : ymd
		url += anchor(anc)
	end
	url
end

def yo_update_api_key
	r = @conf['yo_update.api_key']
	if not r or r.empty?
		return nil
	end
	return r
end

def yo_update_access_api(req)
	if @conf['proxy']
		proxy_uri = URI("http://" + @conf['proxy'])
		proxy_addr = proxy_uri.host
		proxy_port = proxy_uri.port
	else
		proxy_addr = nil
		proxy_port = nil
	end
	begin
		Timeout.timeout(YO_UPDATE_TIMEOUT) do
			return Net::HTTP.start(req.uri.host, req.uri.port, proxy_addr, proxt_port){|http|
				http.request(req)
			}
		end
	rescue Timeout::Error
		raise YoUpdateError, "Timeout accessing Yo API"
	rescue SocketError => e
		raise YoUpdateError, e.message
	end
end

def yo_update_send_yo(username = nil, url = '')
	api_key = yo_update_api_key
	unless api_key
		raise YoUpdateError, "Yo API Key is not set"
	end
	data = {'api_token' => api_key}
	data['link'] = url unless url.empty?
	unless username
		req = Net::HTTP::Post.new(URI("http://api.justyo.co/yoall/"))
		req.set_form_data(data)
		expected = '{}'
	else
		req = Net::HTTP::Post.new(URI("http://api.justyo.co/yo/"))
		data['username'] = username
		req.set_form_data(data)
		expected = '{"result": "OK"}'
	end
	res = yo_update_access_api(req)
	data = res.body
	unless data == expected
		raise YoUpdateError, "error from Yo API: #{data}"
	end
	return data
end

def yo_update_send_yo_or_log(username = nil, url = '')
	return unless yo_update_api_key
	begin
		yo_update_send_yo(username, url)
	rescue YoUpdateError => e
		@logger.error "yo_update.rb: #{e.message}"
	end
end

def yo_update_subscribers_count
	api_key = yo_update_api_key
	unless api_key
		raise YoUpdateError, "Yo API Key is not set"
	end
	req = Net::HTTP::Get.new(
		URI("http://api.justyo.co/subscribers_count/?api_token=#{URI.escape(api_key)}")
	)
	res = yo_update_access_api(req)
	data = res.body
	begin
		r = JSON::parse(data)
		if r.has_key?('result')
			return r['result']
		else
			raise YoUpdateError, "Error from Yo API: #{data}"
		end
	rescue JSON::ParserError
		raise YoUpdateError, "Error from Yo API: #{data}"
	end
end

unless defined? yo_update_conf_label	# maybe defined in a language resource
	def yo_update_conf_label
		'Send Yo with updates'
	end
end

unless defined? yo_update_test_result_label	# maybe defined in a language resource
	def yo_update_test_result_label(username, result)
		"- Sent to <tt>#{h username}</tt> and got <tt>#{h result}</tt>"
	end
end

unless defined? yo_update_conf_html	# maybe defined in a language resource
	def yo_update_conf_html(conf, n_subscribers, test_result)
		action_label = {
			'send_on_update' => 'when an entry is added',
			'send_on_comment' => 'when a comment is posted',
		}
		<<-HTML
		<h3 class="subtitle">API key</h3>
		<p><input name="yo_update.api_key" value="#{h conf['yo_update.api_key']}" size="40"></p>
		<h3 class="subtitle">Username</h3>
		<p><input name="yo_update.username" value="#{h conf['yo_update.username']}" size="40"></p>
		<h3 class="subtitle">Send Yo</h3>
		<ul>
		#{%w(send_on_update send_on_comment).map{|action|
			checked = conf["yo_update.#{action}"] ? ' checked' : ''
			%Q|<li><label for="yo_update.#{action}"><input id="yo_update.#{action}" name="yo_update.#{action}" value="t" type="checkbox"#{checked}>#{action_label[action]}</label>|
		}.join("\n\t")}
		</ul>
		<p>Test sending Yo! to <input name="yo_update.test" value="" size="10"> with optional link <input name="yo_update.link" value="#{yo_update_url}" size="40">#{test_result}</p>
		<h3 class="subtitle">Current Subscribers</h3>
		<p>#{h n_subscribers}</p>
		<h3 class="subtitle">Yo button</h3>
		<p>Add the following to somewhere or your diary.</p>
		<pre>&lt;div id=&quot;yo-button&quot;&gt;&lt;/div&gt;</pre>
		<h3 class="subtitle">Howto</h3>
		<ol>
		<li>Sign in with your personal Yo account at <a href="http://dev.justyo.co/">http://dev.justyo.co/</a>
		<li>Follow the instructions to obtain new API account.
			Please leave the Callback URL blank.
		<li>Copy the API key and API username above.
		</ol>
		HTML
	end
end

add_conf_proc('yo_update', yo_update_conf_label) do
	test_result = ''
	if @mode == 'saveconf' then
		@conf['yo_update.api_key'] = @cgi.params['yo_update.api_key'][0]
		@conf['yo_update.username'] = @cgi.params['yo_update.username'][0]
		@conf['yo_update.send_on_update'] = (@cgi.params['yo_update.send_on_update'][0] == 't')
		@conf['yo_update.send_on_comment'] = (@cgi.params['yo_update.send_on_comment'][0] == 't')
		test_username = @cgi.params['yo_update.test'][0]
		test_link = @cgi.params['yo_update.link'][0]
		if test_username and not test_username.empty?
			begin
				result = yo_update_send_yo(test_username, test_link)
			rescue YoUpdateError => e
				result = e.message
			end
			test_result = yo_update_test_result_label(test_username, result)
		end
	end
	unless @conf.has_key?('yo_update.send_on_update')
		@conf['yo_update.send_on_update'] = true
	end
	begin
		n_subscribers = yo_update_subscribers_count
	rescue YoUpdateError => e
		n_subscribers = e.message
	end
	yo_update_conf_html(@conf, n_subscribers, test_result)
end

add_update_proc do
	if @mode == 'append' and @conf['yo_update.send_on_update']
		url = yo_update_url(@date)	# link to the date
		yo_update_send_yo_or_log(nil, url)
	elsif @mode == 'comment' and @comment and @comment.visible? and @conf['yo_update.send_on_comment']
		frag = "c%02d" % @diaries[@date.strftime("%Y%m%d")].count_comments(true)
		url = yo_update_url(@date, frag)
		yo_update_send_yo_or_log(nil, url)
	end
end

add_header_proc do
	if @conf['yo_update.api_key']
		triggers = []
		triggers << 'Entry' if @conf['yo_update.send_on_update']
		triggers << 'Tsukkomi' if @conf['yo_update.send_on_comment']
		trigger_str = "#{triggers.join(' or ')} is added"
		<<-HTML
	<script type="text/javascript"><!--
		var _yoData = {
			"username": "#{@conf['yo_update.username']}",
			"trigger": "#{trigger_str}"
		};
		var s = document.createElement("script");
		s.type = "text/javascript";
		s.src = "//yoapp.s3.amazonaws.com/js/yo-button.js";
		(document.head || document.getElementsByTagName("head")[0]).appendChild(s);
	--></script>
		HTML
	end
end

# Local Variables:
# mode: ruby
# indent-tabs-mode: t
# tab-width: 3
# ruby-indent-level: 3
# End:
# vim: ts=3 sw=3