105
117
self.conf = Configuration(app_name)
106
118
self.xmlprocessor = XMLProcessor()
107
119
#create a regex to replace parts of a dent
108
self.regex_tag = re.compile("(^| )(#[A-z0-9_-]+)")
109
self.regex_group = re.compile("(^| )(![A-z0-9_-]+)")
110
self.regex_user=re.compile("(^| )(@[A-z0-9_]+)")
120
self.regex_tag = re.compile("(^| )(#[\w-]+)")
121
self.regex_group = re.compile("(^| )(![\w-]+)")
122
self.regex_user=re.compile("(^|[^A-z0-9])(@\w+)")
111
123
self.regex_url=re.compile("(http[s]?://.*?)(\s|$)",re.IGNORECASE)
113
self.regex_filter_tags = re.compile("#([A-z0-9_-]+)")
114
self.regex_filter_groups = re.compile("!([A-z0-9_-]+)")
115
124
#get the initial dents
116
125
self.initial_dents = self.conf.get('settings','initial_dents',default='20' )
211
216
#add the Grouppage
212
217
self.mainwindow.notebook.append_page(self.grouppage,gtk.Label(_("Group") ) )
214
#create the filters page
215
self.filterpage = FilterPage()
216
#add the groupage to the notebook
217
self.mainwindow.notebook.append_page(self.filterpage,gtk.Label(_("Filters") ) )
218
#connect the filter page signals
219
self.filterpage.connect('add-tag-filter', self.add_tag_filter )
220
self.filterpage.connect('remove-tag-filter', self.remove_tag_filter )
221
self.filterpage.connect('add-group-filter', self.add_group_filter )
222
self.filterpage.connect('remove-group-filter', self.remove_group_filter )
223
self.filterpage.connect('add-user-filter', self.add_user_filter )
224
self.filterpage.connect('remove-user-filter', self.remove_user_filter )
226
219
#create and add the account page
227
220
self.settingspage = SettingsPage(has_hildon,has_pynotify)
228
221
self.settingspage.set_initial_dents( self.initial_dents )
249
242
self.settingspage.connect('option-notify-replies',self.option_changed, 'notify_replies')
250
243
self.settingspage.connect('initial-dents',self.set_initial_dents)
251
244
self.settingspage.connect('link-color',self.set_link_color)
245
self.settingspage.connect('add-string-filter', self.add_string_filter )
246
self.settingspage.connect('remove-string-filter', self.remove_string_filter )
247
self.settingspage.connect('add-user-filter', self.add_user_filter )
248
self.settingspage.connect('remove-user-filter', self.remove_user_filter )
252
249
#add the settings to the mainwindow
253
250
self.mainwindow.add_notebook_page(self.settingspage,gtk.Label(_("Settings") ) )
254
251
#create and add the about page
350
348
self.mainwindow.set_notebook_page(DENT)
351
349
self.get_statuses()
353
def get_statuses(self):
354
self.increment_requests()
355
self.comm.get_statuses(highest_id[DENT])
357
def get_mentions(self):
358
self.increment_requests()
359
self.comm.get_mentions(highest_id[MENTION])
351
def get_statuses(self,count="20"):
352
#do some time handling for the good doctor
354
if self.last_get_statuses - now > 120:
355
count = self.initial_dents
357
self.last_get_statuses = now
358
self.increment_requests()
359
self.comm.get_statuses(count=count, since=highest_id['dent_previous'])
360
#clean up the garbage
363
def get_mentions(self,count="20"):
364
self.increment_requests()
365
self.comm.get_mentions(count=count,since=highest_id['mention_previous'])
361
367
def get_direct_messages(self):
362
368
now = time.time()
363
369
#has it been 3 minutes since the last request?
364
370
if now-(3*60) > self.last_direct_message_time:
365
371
self.increment_requests()
366
self.comm.get_direct_messages(highest_id[DIRECT])
372
self.comm.get_direct_messages(highest_id['direct_previous'])
367
373
self.last_direct_message_time=now
375
def run(self, enable_logging=False):
376
self.logging = enable_logging
370
377
#start the communicator
371
378
self.comm.start()
372
379
self.main_loop = gobject.MainLoop()
373
380
#add a function to the main loop
374
gobject.timeout_add(90*1000, self.update_statuses )
375
gobject.timeout_add(3*60*1000, self.update_mentions)
381
gobject.timeout_add(60*1000, self.update_statuses )
382
gobject.timeout_add(90*1000, self.update_mentions )
376
383
#we have to temporarily show the various pages or nothing works
377
384
''' why the fuck do I need to do this? '''
378
self.mainwindow.set_notebook_page(MainWindow.DIRECT)
379
self.mainwindow.set_notebook_page(MainWindow.MENTION)
380
self.mainwindow.set_notebook_page(MainWindow.DENT)
385
self.mainwindow.set_notebook_page(DIRECT)
386
self.mainwindow.set_notebook_page(MENTION)
387
self.mainwindow.set_notebook_page(DENT)
381
388
#did the conf read a name and password?
382
389
if( self.conf.name() !="" and self.conf.password()!=""):
383
390
self.comm.set_name_and_password( self.conf.name(),self.conf.password() )
385
392
self.settingspage.set_name(self.conf.name())
386
393
self.settingspage.set_password(self.conf.password())
387
394
#add a timout to get dents
388
gobject.timeout_add(500,self.get_statuses )
389
gobject.timeout_add(600,self.get_mentions )
395
gobject.timeout_add(500,self.get_statuses,self.initial_dents )
396
gobject.timeout_add(600,self.get_mentions,self.initial_dents )
390
397
#gobject.timeout_add(1000,self.get_direct_messages )
392
399
#set the focus on the account page; the last page
393
self.mainwindow.set_notebook_page(MainWindow.ACCOUNT)
400
self.mainwindow.set_notebook_page(ACCOUNT)
395
402
self.mainwindow.run()
396
403
self.main_loop.run()
399
404
#if we ever get here, we should quit
401
406
def update_statuses(self):
496
501
is_member = self.xmlprocessor.get_user_is_member(text)
497
502
self.mainwindow.display_user_is_member( is_member )
504
def process_new_directXML(self,comm,text):
505
#a update status was sent
506
self.decrement_requests()
507
#clear the textview thing
508
self.mainwindow.emit_update_textview_responsed()
499
510
def process_new_statusXML(self,comm,text):
500
#a update status was sent, get all new statuses
501
#self.update_statuses()
511
#a update status was sent
502
512
self.decrement_requests()
503
#there is one statusa and it is the DOM
513
#clear the textview thing
514
self.mainwindow.emit_update_textview_responsed()
515
#there is one status and it is the DOM
504
516
status = self.xmlprocessor.get_dom(text)
505
517
data = self.xmlprocessor.get_dent_data(status)
506
518
data['markup'] = self.markup_dent_text(data['text'])
508
520
dent = self.connect_dent(data,self.dentspage)
509
self.imagecache.add_image_to_widget(data['profile_image_url'],dent)
511
522
def process_conversationXML(self,object,text,conversation_id):
512
523
self.decrement_requests()
513
524
#is this the current conversation Id? if not, then do nothing
522
533
data['in_reply_to_screen_name']=None
523
534
#tell the mainWindow to add the dent
524
535
dent = self.connect_dent(data,self.contextpage,True, self.options['context_backwards'] )
525
self.imagecache.add_image_to_widget(data['profile_image_url'],dent)
526
536
if data['in_reply_to_id']!=None:
527
537
#recursively get in_reply_to_ids
528
538
self.get_conversation(id=data['in_reply_to_id'],conversation_id=conversation_id)
530
def connect_dent(self,data,target_page,is_conv=False,conv_backwards=False,is_direct_dent=False,prune=0):
540
def connect_dent(self,data,target_page,is_conv=False,conv_backwards=False,is_direct_dent=False):
532
542
dent = Dent(data,is_direct=is_direct_dent)
533
dent.connect('group-clicked', self.view_group)
534
dent.connect('reply-clicked', self.reply_clicked)
535
dent.connect('direct-clicked', self.direct_clicked)
536
dent.connect('view-conversation-clicked', self.view_conversation)
537
dent.connect('user-clicked', self.view_user)
538
dent.connect('text-label-clicked',self.dent_text_clicked)
539
dent.connect('redent-clicked',self.redent_clicked)
540
dent.connect('favorite-clicked',self.favorite_clicked)
541
dent.connect('unfavorite-clicked',self.unfavorite_clicked)
542
dent.connect('open-link',self.open_link)
543
target_page.dentScroller.add_dent( dent, is_conv, conv_backwards )
545
target_page.dentScroller.prune(prune)
543
if target_page.dentScroller.add_dent( dent, is_conv, conv_backwards ):
544
dent.connect('group-clicked', self.view_group)
545
dent.connect('reply-clicked', self.reply_clicked)
546
dent.connect('direct-clicked', self.direct_clicked)
547
dent.connect('view-conversation-clicked', self.view_conversation)
548
dent.connect('user-clicked', self.view_user)
549
dent.connect('text-label-clicked',self.dent_text_clicked)
550
dent.connect('redent-clicked',self.redent_clicked)
551
dent.connect('favorite-clicked',self.favorite_clicked)
552
dent.connect('unfavorite-clicked',self.unfavorite_clicked)
553
dent.connect('open-link',self.open_link)
554
if target_page!=self.userpage:
555
#get the image for this dent
556
self.imagecache.add_image_to_widget(data['profile_image_url'],dent)
548
563
def reply_clicked(self,dent,name):
549
self.respond_to_id=dent.id
550
564
#set the text buffer
551
565
self.mainwindow.update_textbuffer.set_text("@%s " % (name) )
552
566
self.mainwindow.update_textview.grab_focus()
567
#set the respond_to_id
568
self.respond_to_id=dent.id
554
571
def favorite_clicked(self,dent):
644
666
if not filtered_status:
646
668
data['markup'] = self.markup_dent_text(data['text'])
647
dent = self.connect_dent(data,target_page,is_direct_dent=is_direct,prune=self.initial_dents*3)
649
if target_page!=self.userpage:
650
#get the image for this dent
651
self.imagecache.add_image_to_widget(data['profile_image_url'],dent)
669
#did this dent connect
670
if not self.connect_dent(data,target_page,is_direct_dent=is_direct):
652
673
#if the target_page = 0 and not first_dents and not is_conf
653
674
if target_page==self.dentspage and not self.is_first_dents:
654
675
if "@"+self.conf.name() in data['markup']:
655
dent=self.connect_dent(data, self.mentionspage,prune=self.initial_dents*3 )
656
self.imagecache.add_image_to_widget(data['profile_image_url'],dent)
676
dent=self.connect_dent(data, self.mentionspage )
658
678
if self.options['notify_replies'] and has_pynotify:
659
679
self.notify.notify_reply(data['screen_name'], data['markup'] )
683
self.log("filter #%s %s" %(data['status_id'], filtered[1] ) )
663
685
self.is_first_dents=False
664
686
#get the related images
665
687
self.imagecache.get_images()
666
if (dent_count!=0 or reply_count!=0) and has_pynotify:
667
self.prepare_notifications(dent_count,reply_count)
669
Take in the statuses, check if user wants notifications
670
count the number of notifications, and call notify methods
672
def prepare_notifications(self,dents,replies):
673
#count = len(statuses)
674
if self.options['notifications']:
675
if not self.options['notify_replies']:
676
self.notify.notify(dents,replies)
679
self.notify.notify_updates(dents)
689
if (dent_count!=0 or reply_count!=0) and has_pynotify and target_page==self.dentspage:
691
if self.options['notifications']:
692
if not self.options['notify_replies']:
693
self.notify.notify(dent_count,reply_count)
696
self.notify.notify_updates(dent_count)
697
#prune off the extra dents
698
target_page.dentScroller.prune(self.initial_dents*2)
681
700
def process_widget_image(self,comm,data,name):
682
701
self.imagecache.widget_image_add(data,name)
684
def communication_exception(self,communicator,code):
703
def communication_exception(self,communicator,code,signal=None):
685
704
self.decrement_requests()
687
706
#bad authorization
690
709
MainWindow.ERROR_MESSAGE)
691
710
self.mainwindow.set_notebook_page(MainWindow.ACCOUNT)
692
711
elif code == '404':
694
714
elif code == '503':
695
print 'service unavailable'
716
#print 'service unavailable'
697
print 'unknown error: '+code
719
#print 'unknown error: '+code
720
#a signal may have been passed from the comm
721
if signal == "new-statusXML":
722
#a dent was sent but it failed
723
self.mainwindow.emit_update_textview_responsed(error=True)
699
725
#functions to handle the filtration system
700
def add_tag_filter(self,winder,tag):
701
if not tag in self.filters['tags']:
702
self.filters['tags'].append(tag)
703
self.filters['tags'].sort()
704
self.filterpage.set_tag_filters( self.filters['tags'] )
706
def remove_tag_filter(self,winder,tag):
707
if tag in self.filters['tags']:
708
self.filters['tags'].remove(tag)
709
self.filterpage.set_tag_filters( self.filters['tags'] )
711
def add_group_filter(self,winder,group):
712
if not group in self.filters['groups']:
713
self.filters['groups'].append(group)
714
self.filters['groups'].sort()
715
self.filterpage.set_group_filters( self.filters['groups'] )
717
def remove_group_filter(self,winder,group):
718
if group in self.filters['groups']:
719
self.filters['groups'].remove(group)
720
self.filterpage.set_group_filters( self.filters['groups'] )
726
def add_string_filter(self,winder,string):
727
if not string in self.filters['strings']:
728
self.filters['strings'].append(string)
729
self.filters['strings'].sort()
730
self.settingspage.set_string_filters( self.filters['strings'] )
732
def remove_string_filter(self,winder,string):
733
if string in self.filters['strings']:
734
self.filters['strings'].remove(string)
735
self.settingspage.set_string_filters( self.filters['strings'] )
722
737
def add_user_filter(self,winder,user):
723
738
if not user in self.filters['users']:
724
739
self.filters['users'].append(user)
725
740
self.filters['users'].sort()
726
self.filterpage.set_user_filters( self.filters['users'] )
741
self.settingspage.set_user_filters( self.filters['users'] )
728
743
def remove_user_filter(self,winder,user):
729
744
if user in self.filters['users']:
730
745
self.filters['users'].remove(user)
731
self.filterpage.set_user_filters( self.filters['users'] )
746
self.settingspage.set_user_filters( self.filters['users'] )
733
748
def check_filtered(self,data):
734
if len(self.filters['tags'])==0 and len(self.filters['users'])==0 and len(self.filters['groups'])==0:
738
#what are the tags in the dent?
739
dent_tags = self.regex_filter_tags.findall(text)
740
for tag in dent_tags:
741
for ftag in self.filters['tags']:
742
if tag.lower()==ftag.lower():
743
return (True, "tag: %s" % tag )
745
#what are the groups in the dent?
746
dent_groups = self.regex_filter_groups.findall(text)
747
for group in dent_groups:
748
for fgroup in self.filters['groups']:
749
if group.lower()==fgroup.lower():
750
return (True, "group: %s" % group )
753
for user in self.filters['users']:
754
if data['screen_name'].lower()==user.lower():
755
return (True, "user: %s" % data['screen_name'] )
749
if len(self.filters['users'])!=0 :
750
#filter against the user
751
for user in self.filters['users']:
752
if data['screen_name'].lower()==user.lower():
753
return (True, "user: %s" % data['screen_name'] )
755
if len(self.filters['strings'])!=0:
756
#filter against the strings
759
#loop through the filter strings
760
for string in self.filters['strings']:
761
if re.search(string,text, flags=re.IGNORECASE):
762
return (True, "string: %s" % string )
763
#if we get this far, just return
759
766
def status_clicked(self,widget):
760
767
if self.window_is_hidden==True:
875
883
gtk.rc_parse_string(style)
876
884
#fuck you GTK for not make this work, more than once!
878
##Commented out 9.4.10 x1101
879
886
#functions for blocking/unblocking
880
#def block_create(self,widget,user_id):
881
# self.comm.block_create(user_id)
887
def block_create(self,widget,user_id):
888
self.comm.block_create(user_id)
883
#def block_destroy(self,widget,user_id):
884
# self.comm.block_destroy(user_id)
890
def block_destroy(self,widget,user_id):
891
self.comm.block_destroy(user_id)
887
894
def set_is_direct_message_mode(self,mode,user=None):