Пример #1
0
 def _NH_SIPAccountGotSelfPresenceState(self, notification):
     pidf_doc = notification.data.pidf
     services = [service for service in pidf_doc.services if service.status.extended is not None]
     if not services:
         return
     blink_settings = BlinkSettings()
     services.sort(key=lambda obj: obj.timestamp.value if obj.timestamp else epoch, reverse=True)
     service = services[0]
     if service.id in ('SID-%s' % uuid.UUID(SIPSimpleSettings().instance_id), 'SID-%s' % hashlib.md5(notification.sender.id).hexdigest()):
         # Our current state is the winning one
         return
     status = str(service.status.extended).title()
     note = None if not service.notes else str(list(service.notes)[0])
     if status == 'Offline':
         status = 'Invisible'
         note = None
     new_state = PresenceState(status, note)
     blink_settings.presence.current_state = new_state
     if new_state.note:
         try:
             next(state for state in blink_settings.presence.state_history if state == new_state)
         except StopIteration:
             blink_settings.presence.state_history = [new_state] + blink_settings.presence.state_history
         else:
             blink_settings.presence.state_history = [new_state] + [state for state in blink_settings.presence.state_history if state != new_state]
     blink_settings.save()
Пример #2
0
 def _NH_SIPAccountGotSelfPresenceState(self, notification):
     pidf_doc = notification.data.pidf
     services = [service for service in pidf_doc.services if service.status.extended is not None]
     if not services:
         return
     blink_settings = BlinkSettings()
     services.sort(key=lambda obj: obj.timestamp.value if obj.timestamp else epoch, reverse=True)
     service = services[0]
     if service.id in ('SID-%s' % uuid.UUID(SIPSimpleSettings().instance_id), 'SID-%s' % hashlib.md5(notification.sender.id).hexdigest()):
         # Our current state is the winning one
         return
     status = unicode(service.status.extended).title()
     note = None if not service.notes else unicode(list(service.notes)[0])
     if status == 'Offline':
         status = 'Invisible'
         note = None
     new_state = PresenceState(status, note)
     blink_settings.presence.current_state = new_state
     if new_state.note:
         try:
             next(state for state in blink_settings.presence.state_history if state==new_state)
         except StopIteration:
             blink_settings.presence.state_history = [new_state] + blink_settings.presence.state_history
         else:
             blink_settings.presence.state_history = [new_state] + [state for state in blink_settings.presence.state_history if state!=new_state]
     blink_settings.save()
Пример #3
0
 def _SH_AccountStateChanged(self):
     self.activity_note.setText(self.account_state.note)
     if self.account_state.state is AccountState.Invisible:
         self.activity_note.inactiveText = '(invisible)'
         self.activity_note.setEnabled(False)
     else:
         if not self.activity_note.isEnabled():
             self.activity_note.inactiveText = 'Add an activity note here'
             self.activity_note.setEnabled(True)
     if not self.account_state.state.internal:
         self.saved_account_state = None
     blink_settings = BlinkSettings()
     blink_settings.presence.current_state = PresenceState(self.account_state.state, self.account_state.note)
     blink_settings.presence.state_history = [PresenceState(state, note) for state, note in self.account_state.history]
     blink_settings.save()
Пример #4
0
 def _SH_AccountStateChanged(self):
     self.activity_note.setText(self.account_state.note)
     if self.account_state.state is AccountState.Invisible:
         self.activity_note.inactiveText = u'(invisible)'
         self.activity_note.setEnabled(False)
     else:
         if not self.activity_note.isEnabled():
             self.activity_note.inactiveText = u'Add an activity note here'
             self.activity_note.setEnabled(True)
     if not self.account_state.state.internal:
         self.saved_account_state = None
     blink_settings = BlinkSettings()
     blink_settings.presence.current_state = PresenceState(self.account_state.state, self.account_state.note)
     blink_settings.presence.state_history = [PresenceState(state, note) for state, note in self.account_state.history]
     blink_settings.save()
Пример #5
0
 def _NH_CFGSettingsObjectDidChange(self, notification):
     if notification.sender is BlinkSettings():
         account_manager = AccountManager()
         if 'presence.offline_note' in notification.data.modified:
             for account in (account for account in account_manager.get_accounts() if account.xcap.discovered):
                 state = BlinkPresenceState(account).offline_state
                 account.xcap_manager.set_offline_status(OfflineStatus(state) if state is not None else None)
         if 'presence.icon' in notification.data.modified:
             icon = IconManager().get('avatar')
             status_icon = Icon(icon.content, icon.content_type) if icon is not None else None
             for account in (account for account in account_manager.get_accounts() if account.xcap.discovered):
                 account.xcap_manager.set_status_icon(status_icon)
         if 'presence.current_state' in notification.data.modified:
             for account in (account for account in account_manager.get_accounts() if account.enabled and account.presence.enabled):
                 account.presence_state = BlinkPresenceState(account).online_state
     else:
         account = notification.sender
         if {'xcap.enabled', 'xcap.xcap_root'}.intersection(notification.data.modified):
             account.xcap.icon = None
             account.save()
         elif {'presence.enabled', 'display_name', 'xcap.icon'}.intersection(notification.data.modified) and account.presence.enabled:
             account.presence_state = BlinkPresenceState(account).online_state
             if account.xcap.discovered and (set(notification.data.modified) != {'xcap.icon'} or account.id in self._should_set_offline_status):
                 state = BlinkPresenceState(account).offline_state
                 account.xcap_manager.set_offline_status(OfflineStatus(state) if state is not None else None)
             if account.id in self._should_set_offline_status:  # do not use set.discard() here to avoid race conditions. it should only be removed if present.
                 self._should_set_offline_status.remove(account.id)
Пример #6
0
 def stop(self):
     notification_center = NotificationCenter()
     notification_center.remove_observer(self, name='SIPAccountWillActivate')
     notification_center.remove_observer(self, name='SIPAccountWillDeactivate')
     notification_center.remove_observer(self, name='SIPAccountDidDiscoverXCAPSupport')
     notification_center.remove_observer(self, name='XCAPManagerDidReloadData')
     notification_center.remove_observer(self, sender=BlinkSettings(), name='CFGSettingsObjectDidChange')
Пример #7
0
    def text(self):
        result = str(self.name or self.uri)
        blink_settings = BlinkSettings()
        if blink_settings.interface.show_history_name_and_uri:
            result = f'{str(self.name)} ({str(self.uri)})'

        if self.call_time:
            call_time = self.call_time.astimezone(tzlocal())
            call_date = call_time.date()
            today = date.today()
            days = (today - call_date).days
            if call_date == today:
                result += call_time.strftime(" at %H:%M")
            elif days == 1:
                result += call_time.strftime(" Yesterday at %H:%M")
            elif days < 7:
                result += call_time.strftime(" on %A")
            elif call_date.year == today.year:
                result += call_time.strftime(" on %B %d")
            else:
                result += call_time.strftime(" on %Y-%m-%d")
        if self.duration:
            seconds = int(self.duration.total_seconds())
            if seconds >= 3600:
                result += """ (%dh%02d'%02d")""" % (seconds / 3600,
                                                    (seconds % 3600) / 60,
                                                    seconds % 60)
            else:
                result += """ (%d'%02d")""" % (seconds / 60, seconds % 60)
        elif self.reason:
            result += ' (%s)' % self.reason.title()
        return result
Пример #8
0
    def offline_state(self):
        if self.account is BonjourAccount():
            return None

        blink_settings = BlinkSettings()

        account_id = hashlib.md5(self.account.id.encode()).hexdigest()
        timestamp = ISOTimestamp.now()

        doc = pidf.PIDF(str(self.account.uri))

        person = pidf.Person('PID-%s' % account_id)
        person.timestamp = timestamp
        person.activities = rpid.Activities()
        person.activities.add('offline')
        doc.add(person)

        service = pidf.Service('SID-%s' % account_id)
        service.status = 'closed'
        service.status.extended = 'offline'
        service.contact = str(self.account.uri)
        service.timestamp = timestamp
        service.capabilities = caps.ServiceCapabilities()
        service.display_name = self.account.display_name or None
        service.icon = "%s#blink-icon%s" % (
            self.account.xcap.icon.url, self.account.xcap.icon.etag
        ) if self.account.xcap.icon is not None else None
        if blink_settings.presence.offline_note:
            service.notes.add(blink_settings.presence.offline_note)
        doc.add(service)

        return doc
Пример #9
0
 def show(self, activate=True):
     settings = BlinkSettings()
     makedirs(settings.transfers_directory.normalized)
     self.setAttribute(Qt.WA_ShowWithoutActivating, not activate)
     super(FileTransferWindow, self).show()
     self.raise_()
     if activate:
         self.activateWindow()
Пример #10
0
 def filename_generator(cls):
     settings = BlinkSettings()
     name = os.path.join(
         settings.screenshots_directory.normalized,
         'ScreenSharing-{:%Y%m%d-%H.%M.%S}'.format(datetime.now()))
     yield '%s.png' % name
     for x in count(1):
         yield "%s-%d.png" % (name, x)
Пример #11
0
 def _NH_CFGSettingsObjectDidChange(self, notification):
     settings = SIPSimpleSettings()
     blink_settings = BlinkSettings()
     icon_manager = IconManager()
     if notification.sender is settings:
         if 'audio.muted' in notification.data.modified:
             self.mute_action.setChecked(settings.audio.muted)
             self.mute_button.setChecked(settings.audio.muted)
         if 'audio.silent' in notification.data.modified:
             self.silent_action.setChecked(settings.audio.silent)
             self.silent_button.setChecked(settings.audio.silent)
         if 'audio.output_device' in notification.data.modified:
             action = (action for action in self.output_devices_group.actions() if action.data() == settings.audio.output_device).next()
             action.setChecked(True)
         if 'audio.input_device' in notification.data.modified:
             action = (action for action in self.input_devices_group.actions() if action.data() == settings.audio.input_device).next()
             action.setChecked(True)
         if 'audio.alert_device' in notification.data.modified:
             action = (action for action in self.alert_devices_group.actions() if action.data() == settings.audio.alert_device).next()
             action.setChecked(True)
         if 'video.device' in notification.data.modified:
             action = (action for action in self.video_devices_group.actions() if action.data() == settings.video.device).next()
             action.setChecked(True)
         if 'answering_machine.enabled' in notification.data.modified:
             self.answering_machine_action.setChecked(settings.answering_machine.enabled)
         if 'chat.auto_accept' in notification.data.modified:
             self.auto_accept_chat_action.setChecked(settings.chat.auto_accept)
         if 'sounds.play_message_alerts' in notification.data.modified:
             self.received_messages_sound_action.setChecked(settings.sounds.play_message_alerts)
         if 'google_contacts.authorization_token' in notification.data.modified:
             authorization_token = notification.sender.google_contacts.authorization_token
             if authorization_token is None:
                 self.google_contacts_action.setText(u'Enable &Google Contacts...')
             else:
                 self.google_contacts_action.setText(u'Disable &Google Contacts')
             if authorization_token is InvalidToken:
                 self.google_contacts_dialog.open_for_incorrect_password()
     elif notification.sender is blink_settings:
         if 'presence.current_state' in notification.data.modified:
             state = getattr(AccountState, blink_settings.presence.current_state.state, AccountState.Available)
             self.account_state.setState(state, blink_settings.presence.current_state.note)
         if 'presence.icon' in notification.data.modified:
             self.set_user_icon(icon_manager.get('avatar'))
         if 'presence.offline_note' in notification.data.modified:
             # TODO: set offline note -Saul
             pass
     elif isinstance(notification.sender, (Account, BonjourAccount)):
         account_manager = AccountManager()
         account = notification.sender
         if 'enabled' in notification.data.modified:
             action = (action for action in self.accounts_menu.actions() if action.data() is account).next()
             action.setChecked(account.enabled)
         if 'display_name' in notification.data.modified and account is account_manager.default_account:
             self.display_name.setText(account.display_name or u'')
         if set(['enabled', 'message_summary.enabled', 'message_summary.voicemail_uri']).intersection(notification.data.modified):
             action = (action for action in self.voicemail_menu.actions() if action.data() is account).next()
             action.setVisible(False if account is BonjourAccount() else account.enabled and account.message_summary.enabled)
             action.setEnabled(False if account is BonjourAccount() else account.voicemail_uri is not None)
Пример #12
0
    def _NH_XCAPManagerDidReloadData(self, notification):
        account = notification.sender.account
        blink_settings = BlinkSettings()
        icon_manager = IconManager()

        offline_status = notification.data.offline_status
        status_icon = notification.data.status_icon

        try:
            offline_note = next(note for service in offline_status.pidf.services for note in service.notes)
        except (AttributeError, StopIteration):
            offline_note = None

        blink_settings.presence.offline_note = offline_note
        blink_settings.save()

        if status_icon:
            icon_hash = hashlib.sha1(status_icon.data).hexdigest()
            icon_desc = IconDescriptor(status_icon.url, icon_hash)
            if not blink_settings.presence.icon or blink_settings.presence.icon.etag != icon_hash:
                icon = icon_manager.store_data('avatar', status_icon.data)
                blink_settings.presence.icon = IconDescriptor(FileURL(icon.filename), icon_hash) if icon is not None else None
                blink_settings.save()
        else:
            icon_desc = None
            icon_manager.remove('avatar')
            blink_settings.presence.icon = None
            blink_settings.save()

        account.xcap.icon = icon_desc
        account.save()
Пример #13
0
 def _SH_AccountStateClicked(self, checked):
     filename = QFileDialog.getOpenFileName(self, u'Select Icon', self.last_icon_directory, u"Images (*.png *.tiff *.jpg *.xmp *.svg)")
     if filename:
         self.last_icon_directory = os.path.dirname(filename)
         filename = filename if os.path.realpath(filename) != os.path.realpath(self.default_icon_path) else None
         blink_settings = BlinkSettings()
         icon_manager = IconManager()
         if filename is not None:
             icon = icon_manager.store_file('avatar', filename)
             if icon is not None:
                 blink_settings.presence.icon = IconDescriptor(FileURL(icon.filename), hashlib.sha1(icon.content).hexdigest())
             else:
                 icon_manager.remove('avatar')
                 blink_settings.presence.icon = None
         else:
             icon_manager.remove('avatar')
             blink_settings.presence.icon = None
         blink_settings.save()
Пример #14
0
 def _SH_AccountStateClicked(self, checked):
     filename = QFileDialog.getOpenFileName(self, 'Select Icon', self.last_icon_directory, "Images (*.png *.tiff *.jpg *.xmp *.svg)")[0]
     if filename:
         self.last_icon_directory = os.path.dirname(filename)
         filename = filename if os.path.realpath(filename) != os.path.realpath(self.default_icon_path) else None
         blink_settings = BlinkSettings()
         icon_manager = IconManager()
         if filename is not None:
             icon = icon_manager.store_file('avatar', filename)
             if icon is not None:
                 blink_settings.presence.icon = IconDescriptor(FileURL(icon.filename), hashlib.sha1(icon.content).hexdigest())
             else:
                 icon_manager.remove('avatar')
                 blink_settings.presence.icon = None
         else:
             icon_manager.remove('avatar')
             blink_settings.presence.icon = None
         blink_settings.save()
Пример #15
0
 def _NH_SIPApplicationDidStart(self, notification):
     self.load_audio_devices()
     self.load_video_devices()
     notification.center.add_observer(self, name='CFGSettingsObjectDidChange')
     notification.center.add_observer(self, name='AudioDevicesDidChange')
     blink_settings = BlinkSettings()
     self.account_state.history = [(item.state, item.note) for item in blink_settings.presence.state_history]
     state = getattr(AccountState, blink_settings.presence.current_state.state, AccountState.Available)
     self.account_state.setState(state, blink_settings.presence.current_state.note)
Пример #16
0
    def _NH_XCAPManagerDidReloadData(self, notification):
        account = notification.sender.account
        blink_settings = BlinkSettings()
        icon_manager = IconManager()

        offline_status = notification.data.offline_status
        status_icon = notification.data.status_icon

        try:
            offline_note = next(note
                                for service in offline_status.pidf.services
                                for note in service.notes)
        except (AttributeError, StopIteration):
            offline_note = None

        blink_settings.presence.offline_note = offline_note
        blink_settings.save()

        try:
            offline_icon = next(service.icon
                                for service in offline_status.pidf.services)
        except (AttributeError, StopIteration):
            offline_icon_hash = None
        else:
            offline_icon_hash = str(offline_icon).partition(
                '#blink-icon')[2] or None

        if status_icon:
            icon_hash = hashlib.sha1(status_icon.data).hexdigest()
            icon_desc = IconDescriptor(status_icon.url, icon_hash)
            if not blink_settings.presence.icon or blink_settings.presence.icon.etag != icon_hash:
                icon = icon_manager.store_data('avatar', status_icon.data)
                blink_settings.presence.icon = IconDescriptor(
                    FileURL(icon.filename),
                    icon_hash) if icon is not None else None
                blink_settings.save()
            elif account.xcap.icon != icon_desc and icon_hash != offline_icon_hash:
                self._should_set_offline_status.add(account.id)
        else:
            if blink_settings.presence.icon is None is not account.xcap.icon:
                self._should_set_offline_status.add(account.id)
            elif blink_settings.presence.icon is account.xcap.icon is offline_status is None and account.xcap_manager.pidf_manipulation.supported:
                state = BlinkPresenceState(account).offline_state
                account.xcap_manager.set_offline_status(
                    OfflineStatus(state) if state is not None else None)
            icon_desc = None
            icon_manager.remove('avatar')
            blink_settings.presence.icon = None
            blink_settings.save()

        account.xcap.icon = icon_desc
        account.save()
Пример #17
0
    def _NH_XCAPManagerDidReloadData(self, notification):
        account = notification.sender.account
        blink_settings = BlinkSettings()
        icon_manager = IconManager()

        offline_status = notification.data.offline_status
        status_icon = notification.data.status_icon

        try:
            offline_note = next(note for service in offline_status.pidf.services for note in service.notes)
        except (AttributeError, StopIteration):
            offline_note = None

        blink_settings.presence.offline_note = offline_note
        blink_settings.save()

        try:
            offline_icon = next(service.icon for service in offline_status.pidf.services)
        except (AttributeError, StopIteration):
            offline_icon_hash = None
        else:
            offline_icon_hash = str(offline_icon).partition('#blink-icon')[2] or None

        if status_icon:
            icon_hash = hashlib.sha1(status_icon.data).hexdigest()
            icon_desc = IconDescriptor(status_icon.url, icon_hash)
            if not blink_settings.presence.icon or blink_settings.presence.icon.etag != icon_hash:
                icon = icon_manager.store_data('avatar', status_icon.data)
                blink_settings.presence.icon = IconDescriptor(FileURL(icon.filename), icon_hash) if icon is not None else None
                blink_settings.save()
            elif account.xcap.icon != icon_desc and icon_hash != offline_icon_hash:
                self._should_set_offline_status.add(account.id)
        else:
            if blink_settings.presence.icon is None is not account.xcap.icon:
                self._should_set_offline_status.add(account.id)
            elif blink_settings.presence.icon is account.xcap.icon is offline_status is None and account.xcap_manager.pidf_manipulation.supported:
                state = BlinkPresenceState(account).offline_state
                account.xcap_manager.set_offline_status(OfflineStatus(state) if state is not None else None)
            icon_desc = None
            icon_manager.remove('avatar')
            blink_settings.presence.icon = None
            blink_settings.save()

        account.xcap.icon = icon_desc
        account.save()
Пример #18
0
 def _AH_OpenTransfersFolder(self):
     settings = BlinkSettings()
     QDesktopServices.openUrl(
         QUrl.fromLocalFile(settings.transfers_directory.normalized))
Пример #19
0
 def _SH_ScreenshotsFolderActionTriggered(self):
     settings = BlinkSettings()
     QDesktopServices.openUrl(
         QUrl.fromLocalFile(settings.screenshots_directory.normalized))
Пример #20
0
    def online_state(self):
        blink_settings = BlinkSettings()

        state = blink_settings.presence.current_state.state
        note = blink_settings.presence.current_state.note

        state = 'offline' if state == 'Invisible' else state.lower()

        if self.account is BonjourAccount():
            return BonjourPresenceState(state, note)

        try:
            hostname = socket.gethostname()
        except Exception:
            hostname = 'localhost'
        account_id = hashlib.md5(self.account.id.encode()).hexdigest()
        timestamp = ISOTimestamp.now()

        doc = pidf.PIDF(str(self.account.uri))

        person = pidf.Person('PID-%s' % account_id)
        person.timestamp = timestamp
        person.activities = rpid.Activities()
        person.activities.add(state)
        doc.add(person)

        if state == 'offline':
            service = pidf.Service('SID-%s' % account_id)
            service.status = 'closed'
            service.status.extended = state
            service.contact = str(self.account.uri)
            service.timestamp = timestamp
            service.capabilities = caps.ServiceCapabilities()
            service.display_name = self.account.display_name or None
            service.icon = "%s#blink-icon%s" % (
                self.account.xcap.icon.url, self.account.xcap.icon.etag
            ) if self.account.xcap.icon is not None else None
            doc.add(service)
        else:
            settings = SIPSimpleSettings()
            instance_id = str(uuid.UUID(settings.instance_id))
            service = pidf.Service('SID-%s' % instance_id)
            service.status = 'open'
            service.status.extended = state
            service.contact = str(self.account.contact.public_gruu
                                  or self.account.uri)
            service.timestamp = timestamp
            service.capabilities = caps.ServiceCapabilities()
            service.capabilities.audio = True
            service.capabilities.text = False
            service.capabilities.message = True
            service.capabilities.file_transfer = True
            service.capabilities.screen_sharing_server = True
            service.capabilities.screen_sharing_client = True
            service.display_name = self.account.display_name or None
            service.icon = "%s#blink-icon%s" % (
                self.account.xcap.icon.url, self.account.xcap.icon.etag
            ) if self.account.xcap.icon is not None else None
            service.device_info = pidf.DeviceInfo(
                instance_id,
                description=hostname,
                user_agent=settings.user_agent)
            service.device_info.time_offset = pidf.TimeOffset()
            # TODO: Add real user input data -Saul
            service.user_input = rpid.UserInput()
            service.user_input.idle_threshold = 600
            service.add(pidf.DeviceID(instance_id))
            if note:
                service.notes.add(note)
            doc.add(service)

            device = pidf.Device('DID-%s' % instance_id,
                                 device_id=pidf.DeviceID(instance_id))
            device.timestamp = timestamp
            device.notes.add('%s at %s' % (settings.user_agent, hostname))
            doc.add(device)

        return doc
Пример #21
0
 def _AH_ReceivedFilesWindowActionTriggered(self, checked):
     settings = BlinkSettings()
     directory = settings.transfers_directory.normalized
     makedirs(directory)
     QDesktopServices.openUrl(QUrl.fromLocalFile(directory))
Пример #22
0
 def _AH_ScreenshotsWindowActionTriggered(self, checked):
     settings = BlinkSettings()
     directory = settings.screenshots_directory.normalized
     makedirs(directory)
     QDesktopServices.openUrl(QUrl.fromLocalFile(directory))
Пример #23
0
 def _NH_SIPApplicationDidStart(self, notification):
     notification.center.add_observer(self, name='CFGSettingsObjectDidChange', sender=BlinkSettings())