Пример #1
0
    def _add_entrance_message(self, input, command):
        match = re.search(r'^@?([^ ]+) (.+)$', input)

        if not match:
            self.print(f'Usage: {command.usage}')
            return

        login = match.group(1)
        message = match.group(2)
        if message.lower() == 'none':
            message = None

        broadcaster = get_broadcaster()
        api = broadcaster.twitch_api
        user_info = api.get_user(login)

        if not user_info:
            self.print(f'User not found: {login}')
            return

        if user_info['id'] not in self._sound_data['user_sounds']:
            self._sound_data['user_sounds'][user_info['id']] = {}

        self._sound_data['user_sounds'][user_info['id']]['message'] = message
        self._sound_data['user_sounds'][
            user_info['id']]['display_name'] = user_info['display_name']
        self._sound_data['user_sounds'][
            user_info['id']]['login'] = user_info['login']

        self.save_module_data(self._sound_data)

        display_name = user_info['display_name']
        self.print(f'Message added for {display_name}')
Пример #2
0
    def _set_volume(self, input, command):
        match = re.search(r'^([^ ]+) (\d+)$', input)
        if not match:
            self.print(f'Usage: {command.usage}')
            return

        login = match.group(1)
        volume = int(match.group(2))

        broadcaster = get_broadcaster()
        api = broadcaster.twitch_api
        user_info = api.get_user(login)

        if not user_info:
            self.print(f'User not found: {login}')
            return

        if user_info['id'] not in self._sound_data['user_sounds']:
            self.print(
                f'Welcome not configured for: {user_info["display_name"]}')
            return

        self._sound_data['user_sounds'][user_info['id']]['volume'] = volume
        self.save_module_data(self._sound_data)
        self.print(f"Volume for {user_info['display_name']} set to {volume}%")
Пример #3
0
    def _list_rewards(self, input, command):
        if not self._channel_point_data['attachments']:
            self.print('No channel point redemptions configured')
            return

        b = get_broadcaster()
        rewards = b.twitch_api.get_rewards(b.twitch_user_id)

        reward_map = {x['id']: x['title'] for x in rewards}

        self.print('Attached channel point redemptions:')

        for reward_id in self._channel_point_data['attachments']:
            if self._channel_point_data['attachments'][reward_id].get(
                    'command'):
                command_name = "!" + self._channel_point_data['attachments'][
                    reward_id].get('command')
            else:
                command_name = 'Not Set'

            self.print(
                f"  {reward_map.get(reward_id, '<deleted>')} - {command_name}")
            for message in self._channel_point_data['attachments'][
                    reward_id].get('message_command', {}):
                self.print(
                    f"    {message}: !{self._channel_point_data['attachments'][reward_id]['message_command'][message]}"
                )
Пример #4
0
	def run(self):
		while self._keep_listening:
			if (time.time() - self.last_check > 30) and (time.time() - self.last_changed > 180):
				broadcaster = get_broadcaster()
				if broadcaster:
					api = TwitchAPIHelper(broadcaster.oauth_tokens)
					stream = api.get_stream(broadcaster.twitch_user_id)
					if stream:
						if not self.broadcast_id or self.last_check == 0:
							self.event_queue.put(StreamStatusEvent(
								stream_id = stream['id'],
								title = stream['title'],
								started_at = stream['started_at'],
								viewer_count = stream['viewer_count']
							))
							self.last_changed = time.time()
							self.buffer_queue.put(('STATUS', 'Stream is now live!'))
							self.buffer_queue.put(('DEBUG', f"Stream ID: {stream['id']}"))

						self.broadcast_id = stream['id']

					else:
						if self.broadcast_id or self.last_check == 0:
							self.event_queue.put(StreamStatusEvent())
							self.last_changed = time.time()
							self.buffer_queue.put(('STATUS', 'Stream is offline.'))

						self.broadcast_id = None

				self.last_check = time.time()

			time.sleep(1)
Пример #5
0
    def user_id(self):
        if self._user_id is not None:
            return self._user_id

        broadcaster = get_broadcaster()
        user_info = broadcaster.twitch_api.get_user(self.display_name.lower())

        self._user_id = user_info['id']
        return self._user_id
Пример #6
0
    def _set_title(self, event):
        if not event.message:
            return
        broadcaster = get_broadcaster()

        res = self.twitch_api.set_stream_title(broadcaster.twitch_user_id,
                                               event.message)
        if res:
            self.send_chat_message('Stream title set to:')
            self.send_chat_message(res['title'])
        else:
            self.send_chat_message('Error updating stream title')
Пример #7
0
    def _set_game(self, event):
        if not event.message:
            return

        broadcaster = get_broadcaster()

        stream_info = self.twitch_api.set_stream_game(
            broadcaster.twitch_user_id, event.message)
        if stream_info:
            game_name = stream_info['game_name']
            self.send_chat_message(f'Game set to "{game_name}"')
        else:
            self.send_chat_message('Error setting game.')
Пример #8
0
    def __init__(self, event_loop, voltron):
        self.admin_commands = {}
        self.voltron = voltron
        self.event_loop = event_loop

        broadcaster = get_broadcaster()
        self.twitch_api = None
        if broadcaster:
            self.twitch_api = broadcaster.twitch_api

        self.setup()

        self.voltron.register_module(self)
Пример #9
0
    def first_message(self, event, run_by_command=False, testing=False):
        handled = False
        if not self._stream_online and not testing:
            return False

        sound_played = False
        if event.user_id in self._sound_data['user_sounds']:
            data = self._sound_data['user_sounds'][event.user_id]

            if data.get('sound_file', None):
                sound_path = f"{self.media_directory}\\{data['sound_file']}"
                volume = data.get('volume', 100)
                if not os.path.isfile(sound_path):
                    self.buffer_print('ERR', f'{sound_path} does not exist')

                else:
                    self.play_audio(sound_path,
                                    device=self.entrance_sound_device,
                                    volume=volume)
                    sound_played = True
                    handled = True

            if data.get('message', None):
                self.send_chat_message(data['message'], event=event)
                handled = True

        since_alert = time.time() - self._last_alert
        if not sound_played and self.alert_sound_device is not None and self.alert_sound and not run_by_command and since_alert > 30:
            alert_path = f"{self.media_directory}\\{self.alert_sound}"
            if not os.path.isfile(alert_path):
                self.buffer_print('ERR', f'{alert_path} does not exist')
            else:
                self.play_audio(alert_path, device=self.alert_sound_device)
                self._last_alert = time.time()

        if not run_by_command:
            broadcaster = get_broadcaster()
            follow_str = "Not Following"
            follow_time = broadcaster.twitch_api.get_follow_time(
                broadcaster.twitch_user_id, event.user_id)
            if follow_time is not None:
                follow_str = f"Followed {humanize.naturaltime(follow_time)}"
            self.print(f'First message: {event.display_name} ({follow_str})')

        return handled
Пример #10
0
        def save(prompt):
            action = prompt.lower().strip()
            if action == 'c':
                self.print('No account added')
                return True
            elif action == 'y':
                is_broadcaster = True
            elif action == 'n':
                is_broadcaster = False
            else:
                return False

            def confirm(prompt):
                action = prompt.lower().strip()
                if action == 'n':
                    return True
                elif action != 'y':
                    return False

                account = save_oauth(
                    login_info[0],  # oauth token
                    login_info[1],  # refresh_token
                    login_info[2],  # expires in
                    is_broadcaster  # is broadcaster
                )

                self.print(
                    'Authorization successful for {user} (broadcaster={broadcaster})'
                    .format(user=account.display_name,
                            broadcaster=is_broadcaster))
                self.update_status_text()
                self.get_prompt()
                self.voltron.reset()
                self.voltron.start()
                return True

            broadcaster = get_broadcaster()
            if broadcaster and is_broadcaster:
                self.update_status_text(
                    f'Replace current broadcaster account ({broadcaster.display_name})'
                )
                self.terminate_prompt(self.prompt_ident)
                self.prompt_ident = self.get_prompt('[Y]es/[N]o> ', confirm)
            else:
                return confirm('y')
Пример #11
0
    def _test_welcome(self, input, command):
        match = re.search(r'^([^ ]+)$', input)

        if not match:
            self.print(f'Usage: {command.usage}')
            return

        login = match.group(1)

        broadcaster = get_broadcaster()
        api = broadcaster.twitch_api
        user_info = api.get_user(login)

        if not user_info:
            self.print(f'User not found: {login}')
            return

        event = ChatMessageEvent('', user_info['display_name'],
                                 user_info['id'], False, False, False)

        self.first_message(event, testing=True, run_by_command=True)
Пример #12
0
    def _remove_entrance_sound(self, input, command):
        match = re.search(r'^([^ ]+)$', input)

        if not match:
            self.print(f'Usage: {command.usage}')
            return

        login = match.group(1)

        user_info = get_broadcaster().twitch_api.get_user(login)
        if not user_info:
            self.print(f'User not found: {login}')
            return

        if not user_info['id'] in self._sound_data['user_sounds'].keys():
            self.print(
                f"No sound exists for user: {user_info['display_name']}")
            return

        del self._sound_data['user_sounds'][user_info['id']]
        self.save_module_data(self._sound_data)
        self.print(f"Sound for {user_info['display_name']} removed.")
Пример #13
0
    def handle_bits(self, data):
        message = None
        m = data.get('message', None)
        if m:
            m = json.loads(m)
            message = m['data']
        if not message:
            return

        display_name = None
        if not message['is_anonymous']:
            broadcaster = get_broadcaster()
            user_info = broadcaster.twitch_api.get_user(message['user_name'])
            if user_info:
                display_name = user_info['display_name']

        event = BitsEvent(message.get('user_id'), message.get('user_name'),
                          display_name, message['bits_used'],
                          message.get('chat_message',
                                      ''), message['is_anonymous'],
                          message.get('total_bits_used', 0))

        self.event_queue.put(event)
Пример #14
0
    def _attach_reward(self, input, command):
        b = get_broadcaster()
        rewards = b.twitch_api.get_rewards(b.twitch_user_id)
        if not rewards:
            self.print('No rewards set up or unable to retrive from Twitch')
            return

        rewards_list = [(x['id'], x['title']) for x in rewards]
        index = 1
        for r in rewards_list:
            self.print(f"{index}. {r[1]}")
            index += 1

        def select_reward(prompt):
            if prompt == 'c':
                self.update_status_text()
                return True

            elif not prompt.isdigit():
                return False

            index = int(prompt)
            if len(rewards_list) < index or index < 0:
                self.print('Invalid Selection')
                return False

            selected_reward = rewards_list[index - 1]

            def message_selected(prompt):
                required_message = prompt.lower()
                if required_message == '':
                    required_message = None

                def command_selected(prompt):
                    if prompt == 'c':
                        self.update_status_text()
                        return True
                    match = re.search(r'^!([^ ]+ ?.*)$', prompt)
                    if not match:
                        self.print(
                            'Please type a valid command beginning with !')
                        return False

                    command = match.group(1).strip()

                    reward_data = self._channel_point_data['attachments'].get(
                        selected_reward[0], {})
                    if required_message is None:
                        reward_data['command'] = command
                    else:
                        message_map = reward_data.get('message_command', {})
                        message_map[required_message] = command
                        reward_data['message_command'] = message_map

                    self._channel_point_data['attachments'][
                        selected_reward[0]] = reward_data
                    self.save_module_data(self._channel_point_data)

                    self.print(
                        f"{selected_reward[1]} is now attached to !{command}, message: {required_message}"
                    )
                    self.update_status_text()
                    return True

                self.update_status_text(
                    f'Type !<command> to attach to {selected_reward[1]}. c to cancel.'
                )
                self.get_prompt('Command > ', command_selected)
                return True

            self.update_status_text(
                f'Type message to attach to {selected_reward[1]}. Leave blank for none.'
            )
            self.get_prompt('message > ', message_selected)
            return True

        self.update_status_text('Select reward to attach. c to cancel.')
        self.prompt_ident = self.get_prompt('Reward #> ', select_reward)
Пример #15
0
    def _delete_reward(self, input, command):
        if not self._channel_point_data['attachments']:
            self.print('No channel point redemptions configured')
            return

        b = get_broadcaster()
        rewards = b.twitch_api.get_rewards(b.twitch_user_id)

        reward_map = {x['id']: x['title'] for x in rewards}

        self.print('Select reward to delete:')
        selection_map = {}
        count = 1
        for reward_id in self._channel_point_data['attachments']:
            if self._channel_point_data['attachments'][reward_id].get(
                    'command'):
                command_name = "!" + self._channel_point_data['attachments'][
                    reward_id].get('command')
            else:
                command_name = 'Not Set'
            command = self._channel_point_data['attachments'][reward_id].get(
                'command')
            self.print(
                f"{count}. {reward_map.get(reward_id, '<deleted>')} - {command_name}"
            )
            for message in self._channel_point_data['attachments'][
                    reward_id].get('message_command', {}):
                self.print(
                    f"    {message}: !{self._channel_point_data['attachments'][reward_id]['message_command'][message]}"
                )

            selection_map[count] = reward_id
            count += 1

        def select_reward(input):
            if input.lower() == 'c':
                self.update_status_text()
                return True

            if not input.isdigit():
                return False

            selection = int(input)
            reward_id = selection_map.get(selection)
            if not reward_id:
                self.print(f'Invalid Selection: {input}')
                return False

            def select_message(input):
                if input == '':
                    selected_message = None
                else:
                    selected_message = input
                    if not selected_message in self._channel_point_data[
                            'attachments'][reward_id].get(
                                'message_command', {}):
                        self.print(f'No message set: {selected_message}')
                        return False

                def confirm(input):
                    command = input.lower().strip()
                    if command == 'n':
                        self.update_status_text()
                        return True
                    if command == 'y':
                        if selected_message:
                            del self._channel_point_data['attachments'][
                                reward_id]['message_command'][selected_message]
                            self.save_module_data(self._channel_point_data)
                            self.print(
                                f"{reward_map.get(reward_id, '<deleted>')} successfully deleted for message {selected_message}"
                            )
                            self.update_status_text()
                        else:
                            self._channel_point_data['attachments'][reward_id][
                                'command'] = None
                            self.save_module_data(self._channel_point_data)
                            self.print(
                                f"{reward_map.get(reward_id, '<deleted>')} successfully deleted"
                            )
                            self.update_status_text()

                        if not self._channel_point_data['attachments'][
                                reward_id].get(
                                    'command'
                                ) and not self._channel_point_data[
                                    'attachments'][reward_id].get(
                                        'message_command'):
                            del self._channel_point_data['attachments'][
                                reward_id]
                            self.save_module_data(self._channel_point_data)
                        return True

                self.update_status_text(
                    f"Delete {reward_map.get(reward_id, '<deleted>')}?")
                self.terminate_prompt(self.prompt_ident)
                self.prompt_ident = self.get_prompt('[Y]es/[N]o > ', confirm)

            self.update_status_text(
                'Message attachment to remove. (leave blank for none)')
            self.terminate_prompt(self.prompt_ident)
            self.prompt_ident = self.get_prompt('Message > ', select_message)

        self.update_status_text(
            'Select channel point redemption to delete. c to cancel')
        self.prompt_ident = self.get_prompt('Reward #> ', select_reward)
Пример #16
0
 def broadcaster(self):
     if not self._broadcaster:
         self._broadcaster = get_broadcaster()
     return self._broadcaster