kentaroi-okayu 0.0.1

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.
Files changed (56) hide show
  1. data/.document +5 -0
  2. data/.gitignore +6 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +18 -0
  5. data/Rakefile +63 -0
  6. data/VERSION +1 -0
  7. data/bin/okayu +6 -0
  8. data/lib/app.rb +25 -0
  9. data/lib/app_dir.rb +29 -0
  10. data/lib/client.rb +210 -0
  11. data/lib/controllers/listeners_controller.rb +18 -0
  12. data/lib/controllers/live_controller.rb +82 -0
  13. data/lib/controllers/visitors_controller.rb +19 -0
  14. data/lib/controllers.rb +3 -0
  15. data/lib/cookie_thief.rb +172 -0
  16. data/lib/db/migrate/000_create_lives.rb +14 -0
  17. data/lib/db/migrate/001_create_comments.rb +22 -0
  18. data/lib/db/migrate/002_create_visitors.rb +15 -0
  19. data/lib/db/migrate/003_create_listeners.rb +15 -0
  20. data/lib/db/migrate/004_create_communities.rb +13 -0
  21. data/lib/db/migrate/005_create_listeners_lives.rb +12 -0
  22. data/lib/db/migrate/006_create_lives_visitors.rb +13 -0
  23. data/lib/factory.rb +16 -0
  24. data/lib/models/comment.rb +22 -0
  25. data/lib/models/community.rb +3 -0
  26. data/lib/models/listener.rb +5 -0
  27. data/lib/models/live.rb +6 -0
  28. data/lib/models/visitor.rb +5 -0
  29. data/lib/models.rb +23 -0
  30. data/lib/okayu.rb +10 -0
  31. data/lib/player_status.rb +16 -0
  32. data/lib/sample_msg +2 -0
  33. data/lib/thread_info.rb +32 -0
  34. data/lib/user_info.rb +49 -0
  35. data/lib/views/app_frame.rb +89 -0
  36. data/lib/views/color_dialog.rb +56 -0
  37. data/lib/views/colors.rb +168 -0
  38. data/lib/views/live_panel.rb +335 -0
  39. data/lib/views/login_dialog.rb +80 -0
  40. data/lib/views/main_panel.rb +50 -0
  41. data/lib/views.rb +11 -0
  42. data/logged_in_page +893 -0
  43. data/login_error_page +83 -0
  44. data/okayu.gemspec +126 -0
  45. data/tcp_log +0 -0
  46. data/test/client_test.rb +61 -0
  47. data/test/cookie_thief_test.rb +36 -0
  48. data/test/ie_cookie.txt +63 -0
  49. data/test/okayu_test.rb +8 -0
  50. data/test/player_status_test.rb +61 -0
  51. data/test/raw_player_status +2 -0
  52. data/test/raw_player_status_community_only +3 -0
  53. data/test/raw_player_status_notlogged_in +2 -0
  54. data/test/test_helper.rb +11 -0
  55. data/test/thread_info_test.rb +11 -0
  56. metadata +193 -0
@@ -0,0 +1,335 @@
1
+ module Okayu
2
+ COLORIZE = 300
3
+ NAME = 301
4
+
5
+ class LiveListCtrl < Wx::ListCtrl
6
+ COLUMNS = { :no => 0,
7
+ :message => 1,
8
+ :mail => 2,
9
+ :time => 3,
10
+ :name => 4,
11
+ :id => 5,
12
+ :premium => 6,
13
+ :ngword => 7 }
14
+ attr_accessor :base_time
15
+
16
+ def initialize(parent)
17
+ super(parent, :id => Wx::ID_ANY, :style => Wx::LC_REPORT)
18
+ insert_column COLUMNS[:no], "No", Wx::LIST_FORMAT_LEFT, -1
19
+ insert_column COLUMNS[:message], "Message", Wx::LIST_FORMAT_LEFT, -1
20
+ insert_column COLUMNS[:mail], "Command", Wx::LIST_FORMAT_LEFT, -1
21
+ insert_column COLUMNS[:time], "Time", Wx::LIST_FORMAT_LEFT, -1
22
+ insert_column COLUMNS[:name], "Name", Wx::LIST_FORMAT_LEFT, -1
23
+ insert_column COLUMNS[:id], "Id", Wx::LIST_FORMAT_LEFT, -1
24
+ insert_column COLUMNS[:premium], "Premium", Wx::LIST_FORMAT_LEFT, -1
25
+ insert_column COLUMNS[:ngword], "NG word", Wx::LIST_FORMAT_LEFT, -1
26
+ load_column_width
27
+
28
+ evt_list_col_end_drag(Wx::ID_ANY){|event| on_column_resized(event)}
29
+
30
+ evt_list_item_right_click(get_id) {|event| on_list_item_right_click(event)}
31
+ evt_list_item_activated(Wx::ID_ANY) {|event| on_activated(event)}
32
+ evt_key_down(){|event| get_parent.on_key_down(event)}
33
+
34
+ evt_menu(COLORIZE){show_color_dialog}
35
+ evt_menu(NAME){show_name_dialog}
36
+ end
37
+
38
+ def load_column_width
39
+ return unless UserInfo.column_width
40
+ set_column_width COLUMNS[:no], UserInfo.column_width[:no]
41
+ set_column_width COLUMNS[:message], UserInfo.column_width[:message]
42
+ set_column_width COLUMNS[:mail], UserInfo.column_width[:mail]
43
+ set_column_width COLUMNS[:time], UserInfo.column_width[:time]
44
+ set_column_width COLUMNS[:name], UserInfo.column_width[:name]
45
+ set_column_width COLUMNS[:id], UserInfo.column_width[:id]
46
+ set_column_width COLUMNS[:premium], UserInfo.column_width[:premium]
47
+ set_column_width COLUMNS[:ngword], UserInfo.column_width[:ngword]
48
+ end
49
+
50
+ def insert_comment comment
51
+ item = Wx::ListItem.new
52
+ item.set_data({:id => comment.id,
53
+ :visitor_id => comment.visitor_id,
54
+ :listener_id => comment.listener_id})
55
+ item.set_id 0
56
+ item.set_column COLUMNS[:no]
57
+ item.set_text comment.number.to_s
58
+ # item.set_text_colour Wx::GREEN
59
+ insert_item(item)
60
+
61
+ item.set_column COLUMNS[:message]
62
+ item.set_text comment.message
63
+ set_item(item)
64
+
65
+ item.set_column COLUMNS[:mail]
66
+ item.set_text comment.mail
67
+ set_item(item)
68
+
69
+ item.set_column COLUMNS[:time]
70
+ item.set_text Time.at(comment.commented_at - @base_time).strftime("%M:%S")
71
+ set_item(item)
72
+
73
+ if comment.listener
74
+ item.set_column COLUMNS[:name]
75
+ item.set_text comment.listener.name
76
+ set_item(item)
77
+ end
78
+
79
+ item.set_column COLUMNS[:id]
80
+ item.set_text comment.user_id || comment.visitor.user_id
81
+ set_item(item)
82
+
83
+ item.set_column COLUMNS[:premium]
84
+ if comment.owner
85
+ item.set_text '主'
86
+ elsif comment.premium
87
+ item.set_text 'P'
88
+ elsif comment.command
89
+ item.set_text 'System'
90
+ else
91
+ item.set_text ''
92
+ end
93
+ set_item(item)
94
+
95
+ if comment.listener
96
+ if color_index = comment.listener.color_index
97
+ set_color_to_an_item(0, COLORS[color_index])
98
+ end
99
+ elsif comment.visitor
100
+ if color_index = comment.visitor.color_index
101
+ set_color_to_an_item(0, COLORS[color_index])
102
+ end
103
+ end
104
+
105
+ end
106
+
107
+ def on_column_resized event
108
+ column = event.get_column
109
+ if UserInfo[:column_width]
110
+ UserInfo[:column_width][COLUMNS.index(column)] = get_column_width(column)
111
+ else
112
+ UserInfo[:column_width] = {
113
+ :no => get_column_width(COLUMNS[:no]),
114
+ :message => get_column_width(COLUMNS[:message]),
115
+ :mail => get_column_width(COLUMNS[:mail]),
116
+ :time => get_column_width(COLUMNS[:time]),
117
+ :name => get_column_width(COLUMNS[:name]),
118
+ :id => get_column_width(COLUMNS[:id]),
119
+ :premium => get_column_width(COLUMNS[:premium]),
120
+ :ngword => get_column_width(COLUMNS[:ngword])
121
+ }
122
+ end
123
+ end
124
+
125
+ def on_list_item_right_click event
126
+ menu = Wx::Menu.new
127
+ menu.append(COLORIZE, "色をつける(&C)", "")
128
+ menu.append(NAME, "名前をつける(&M)", "")
129
+ popup_menu(menu, event.get_point)
130
+ end
131
+
132
+ def show_color_dialog
133
+ dialog = ColorDialog.new(self)
134
+ color_index = dialog.show_modal
135
+ item_index = get_selections.first
136
+ if color_index >= 0 && color_index < COLORS.length
137
+ on_color_set item_index, color_index
138
+ end
139
+ end
140
+
141
+ def show_name_dialog
142
+ dialog = Wx::TextEntryDialog.new(self, "名前を入力してください")
143
+ dialog.show_modal
144
+ item_index = get_selections.first
145
+
146
+ item = get_item(item_index)
147
+ item.set_text_colour(COLORS[WHITE][:color])
148
+ item.set_column COLUMNS[:name]
149
+ item.set_text(dialog.get_value)
150
+ set_item(item)
151
+ end
152
+
153
+ def is_colored? index
154
+ get_item_background_colour(index) != Wx::NULL_COLOUR &&
155
+ get_item_background_colour(index) != COLORS[WHITE][:color]
156
+ end
157
+
158
+ def on_activated event
159
+ item_index = event.get_index
160
+ if is_colored?(item_index)
161
+ on_color_unset item_index
162
+ else
163
+ on_color_set item_index
164
+ end
165
+ end
166
+
167
+ def on_color_set index, color_index=nil
168
+ color_index = rand(COLORS.length) unless color_index
169
+ data = get_item_data(index)
170
+ return unless data
171
+
172
+ if data[:listener_id]
173
+ set_color({:listener_id => data[:listener_id]}, COLORS[color_index])
174
+ unless ListenersController.set_color_index :id => data[:listener_id],
175
+ :color_index => color_index
176
+ Wx::message_box('色設定の保存に失敗しました')
177
+ end
178
+ else
179
+ set_color({:visitor_id => data[:visitor_id]}, COLORS[color_index])
180
+ unless VisitorsController.set_color_index :id => data[:visitor_id],
181
+ :color_index => color_index
182
+ Wx::message_box('色設定の保存に失敗しました')
183
+ end
184
+ end
185
+ end
186
+
187
+ def on_color_unset index
188
+ data = get_item_data(index)
189
+ return unless data
190
+
191
+ if data[:listener_id]
192
+ set_color({:listener_id => data[:listener_id]}, COLORS[WHITE])
193
+ unless ListenersController.unset_color_index :id => data[:listener_id]
194
+ Wx::message_box('色設定の消去に失敗しました')
195
+ end
196
+ else
197
+ set_color({:visitor_id => data[:visitor_id]}, COLORS[WHITE])
198
+ unless VisitorsController.unset_color_index :id => data[:visitor_id]
199
+ Wx::message_box('色設定の消去に失敗しました')
200
+ end
201
+ end
202
+ end
203
+
204
+ def set_color target, color
205
+ if target[:listener_id]
206
+ self.each do |index|
207
+ if get_item_data(index)[:listener_id] == target[:listener_id]
208
+ set_color_to_an_item(index, color)
209
+ end
210
+ end
211
+ elsif target[:visitor_id]
212
+ self.each do |index|
213
+ if get_item_data(index)[:visitor_id] == target[:visitor_id]
214
+ set_color_to_an_item(index, color)
215
+ end
216
+ end
217
+ end
218
+ end
219
+
220
+ def set_color_to_an_item index, color
221
+ set_item_background_colour(index, color[:color])
222
+ if color[:white_text]
223
+ get_item(index).set_text_colour(COLORS[WHITE][:color])
224
+ end
225
+ end
226
+
227
+ def on_name_set index, name
228
+ end
229
+ def on_name_unset index, name
230
+ end
231
+ def set_name target, name
232
+ end
233
+ def set_name_to_an_item index, name
234
+ end
235
+ end
236
+
237
+ class LivePanel < Wx::Panel
238
+ attr_reader :title
239
+ def initialize parent
240
+ super
241
+ @title = 'live'
242
+ @ready = false
243
+
244
+ @live_url = Wx::TextCtrl.new(self,
245
+ :id => Wx::ID_ANY,
246
+ :style => Wx::TE_PROCESS_ENTER)
247
+ @list = LiveListCtrl.new(self)
248
+
249
+ sizer = Wx::BoxSizer.new(Wx::VERTICAL)
250
+ sizer.add(@live_url, 0, Wx::ALL|Wx::EXPAND, 10)
251
+ sizer.add(@list, 1, Wx::ALL|Wx::EXPAND, 10)
252
+ set_sizer(sizer)
253
+ sizer.set_size_hints(self)
254
+
255
+ @live_url.set_focus
256
+
257
+ #@live_url.evt_key_down(){|event| on_key_down(event)}
258
+ evt_key_down(){|event| on_key_down(event)}
259
+
260
+
261
+ @live_url.evt_text_enter(@live_url.get_id) {|event| on_live_url_enter(event)}
262
+ end
263
+
264
+ def set_index index
265
+ @index = index
266
+ end
267
+
268
+ def on_new_url
269
+ @live_url.set_focus
270
+ @live_url.set_selection(-1, -1)
271
+ end
272
+
273
+ def on_live_url_enter event
274
+ close
275
+
276
+ if live_id = live_id_from_url(@live_url.get_value)
277
+ @ready = false
278
+ @live_controller = LiveController.new(live_id)
279
+ if @live_controller.valid?
280
+ @list.base_time = @live_controller.base_time
281
+ get_parent.set_page_text(@index, live_id)
282
+
283
+ @list.delete_all_items
284
+ @live_controller.comments.each do |comment|
285
+ @list.insert_comment(comment)
286
+ end
287
+
288
+ @ready = true
289
+ end
290
+ end
291
+ end
292
+
293
+ def live_id_from_url url
294
+ if /^\d+$/ =~ url
295
+ "lv#{url}"
296
+ elsif /lv\d+/ =~ url
297
+ $&
298
+ else
299
+ nil
300
+ end
301
+ end
302
+
303
+ def on_key_down event
304
+ case event.get_key_code
305
+ when 0x16E # Ctrl+PageUp
306
+ if event.control_down
307
+ get_parent.advance_selection false
308
+ end
309
+ when 0x16F # Ctrl+PageDown
310
+ if event.control_down
311
+ get_parent.advance_selection true
312
+ end
313
+ end
314
+ end
315
+
316
+ def close
317
+ if @live_controller
318
+ @live_controller.close
319
+ end
320
+ end
321
+
322
+
323
+ def on_update
324
+ if @ready && @live_controller.live_now?
325
+ comments = @live_controller.new_comments
326
+ comments.each do |comment|
327
+ @list.insert_comment(comment)
328
+ end
329
+ end
330
+ end
331
+
332
+ end
333
+ end
334
+
335
+
@@ -0,0 +1,80 @@
1
+ module Okayu
2
+ IE_BTN = 250
3
+ FIREFOX_BTN = 251
4
+ CHROME_BTN = 252
5
+
6
+ ID_PASS_BTN = 255
7
+ class LoginDialog < Wx::Dialog
8
+ def initialize parent
9
+ super(parent, Wx::ID_ANY, "ログイン")
10
+ @ie_btn = Wx::RadioButton.new(self, :id => IE_BTN, :label => 'Internet Explorer')
11
+ @firefox_btn = Wx::RadioButton.new(self, :id => FIREFOX_BTN, :label => 'Firefox / Iceweasel')
12
+ @chrome_btn = Wx::RadioButton.new(self, :id => CHROME_BTN, :label => 'Google Chrome')
13
+ @id_pass_btn = Wx::RadioButton.new(self, :id => ID_PASS_BTN, :label => 'Id && Password')
14
+ @mail = Wx::TextCtrl.new self,
15
+ :id => Wx::ID_ANY,
16
+ :value => UserInfo.mail || '',
17
+ :style => Wx::TE_PROCESS_ENTER
18
+ @password = Wx::TextCtrl.new self,
19
+ :id => Wx::ID_ANY,
20
+ :value => UserInfo.password || '',
21
+ :style => Wx::TE_PROCESS_ENTER | Wx::TE_PASSWORD
22
+ @ok_btn = Wx::Button.new(self, :id => Wx::ID_OK, :label => 'OK')
23
+ sizer = Wx::BoxSizer.new Wx::VERTICAL
24
+ sizer.add(@ie_btn, 0, Wx::ALL | Wx::EXPAND, 10)
25
+ sizer.add(@firefox_btn, 0, Wx::ALL | Wx::EXPAND, 10)
26
+ sizer.add(@chrome_btn, 0, Wx::ALL | Wx::EXPAND, 10)
27
+ sizer.add(@id_pass_btn, 0, Wx::ALL | Wx::EXPAND, 10)
28
+ sizer.add(@mail, 0, Wx::ALL | Wx::EXPAND, 10)
29
+ sizer.add(@password, 0, Wx::ALL | Wx::EXPAND, 10)
30
+ sizer.add(@ok_btn, 0, Wx::ALL | Wx::EXPAND, 10)
31
+ set_sizer(sizer)
32
+ sizer.set_size_hints(self)
33
+ sizer.fit(self)
34
+
35
+ case UserInfo.login
36
+ when :ie
37
+ @ie_btn.set_value true
38
+ when :firefox
39
+ @firefox_btn.set_value true
40
+ when :chrome
41
+ @chrome_btn.set_value true
42
+ when :id_pass
43
+ @id_pass_btn.set_value true
44
+ end
45
+ @ok_btn.set_focus
46
+
47
+ @mail.evt_text_enter(@mail.get_id){ on_enter }
48
+ @password.evt_text_enter(@password.get_id){ on_enter}
49
+
50
+ @ok_btn.evt_button(Wx::ID_OK){|event| on_ok(event)}
51
+ end
52
+
53
+ def on_enter
54
+ UserInfo.login = :id_pass
55
+ UserInfo.mail = @mail.get_value
56
+ UserInfo.password = @password.get_value
57
+ Client.connect :mail => @mail.get_value, :password => @password.get_value
58
+ end_modal 1
59
+ end
60
+
61
+ def on_ok event
62
+ if @ie_btn.get_value
63
+ UserInfo.login = :ie
64
+ Client.connect :cookie => IECookieThief.get(:host => '.nicovideo.jp', :name => 'user_session')
65
+ end_modal 1
66
+ elsif @firefox_btn.get_value
67
+ UserInfo.login = :firefox
68
+ Client.connect :cookie => FirefoxCookieThief.get(:host => '.nicovideo.jp', :name => 'user_session')
69
+ end_modal 1
70
+ elsif @firefox_btn.get_value
71
+ UserInfo.login = :chrome
72
+ Client.connect :cookie => ChromeCookieThief.get(:host => '.nicovideo.jp', :name => 'user_session')
73
+ end_modal 1
74
+ else
75
+ on_enter
76
+ end
77
+ end
78
+ end
79
+ end
80
+
@@ -0,0 +1,50 @@
1
+ module Okayu
2
+ class MainPanel < Wx::Panel
3
+ attr_reader :timer
4
+ def initialize(frame, x, y, w, h)
5
+ super(frame, -1, Wx::Point.new(x, y), Wx::Size.new(w, h))
6
+ @notebook = Wx::Notebook.new self,
7
+ :id =>ID_NOTEBOOK,
8
+ :pos => Wx::Point.new(x, y),
9
+ :size => Wx::Size.new(w, h)
10
+ # panel = LivePanel.new(@notebook)
11
+ # @notebook.add_page(panel, panel.title, TRUE)
12
+ create_tab
13
+
14
+ @timer = Wx::Timer.new(self, Wx::ID_ANY)
15
+ @timer.start
16
+ evt_timer(@timer.get_id) {|event| on_update}
17
+
18
+ evt_size{|event| on_size(event)}
19
+ end
20
+
21
+ def on_update
22
+ @notebook.each_page do |page|
23
+ page.on_update
24
+ end
25
+ end
26
+
27
+ def on_size event
28
+ if @notebook
29
+ size = get_client_size
30
+ @notebook.set_dimensions(2, 2, (size.get_width - 4), (size.get_height - 4))
31
+ end
32
+ end
33
+
34
+ def create_tab
35
+ panel = LivePanel.new(@notebook)
36
+ @notebook.add_page(panel, panel.title, TRUE)
37
+ @notebook.get_current_page.set_index(@notebook.get_selection)
38
+ end
39
+
40
+ def close_tab
41
+ @notebook.get_current_page.close
42
+ @notebook.delete_page(@notebook.get_selection)
43
+ end
44
+
45
+ def get_current_page
46
+ @notebook.get_current_page
47
+ end
48
+ end
49
+
50
+ end
data/lib/views.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'wx'
3
+
4
+ require 'views/colors.rb'
5
+
6
+ require 'views/login_dialog.rb'
7
+ require 'views/color_dialog.rb'
8
+
9
+ require 'views/live_panel.rb'
10
+ require 'views/main_panel.rb'
11
+ require 'views/app_frame.rb'