kentaroi-okayu 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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'