class Response(AliceObject): """Response object""" text = attrib(type=str) tts = attrib(default=None, type=str) card = attrib(default=None, convert=ensure_cls(Card)) buttons = attrib(default=None, convert=ensure_cls(Button)) end_session = attrib(default=False, type=bool)
class Meta(AliceObject): """Meta object""" locale = attrib(type=str) timezone = attrib(type=str) client_id = attrib(type=str) interfaces = attrib(default=None, convert=ensure_cls(Interfaces)) flags = attrib(factory=list)
class Request(AliceObject): """Request object""" type = attrib(type=str) command = attrib(default='', type=str) # Can be none if payload passed original_utterance = attrib(default='', type=str) # Can be none if payload passed markup = attrib(default=None) payload = attrib(default=None) nlu = attrib(default=None, convert=ensure_cls(NaturalLanguageUnderstanding)) @type.validator def check(self, attribute, value): """ Type can be 'SimpleUtterance' or 'ButtonPressed' "SimpleUtterance" — голосовой ввод; "ButtonPressed" — нажатие кнопки. """ if value not in RequestType.all(): raise ValueError( f'Request type must be "SimpleUtterance" or "ButtonPressed", not "{value}"' ) def __attrs_post_init__(self): if self.markup is not None: self.markup = Markup(**self.markup)
class Game: state = attrib(default='', type=str) state_stack = attrib(factory=list) game_process = attrib(factory=GameProcess, convert=ensure_cls(GameProcess)) users = attrib(factory=list) def set_state(self, value): if self.state != value: self.state_stack.append(self.state) self.state = value def go_back(self): if len(self.state_stack) > 0: self.state = self.state_stack.pop() def start_game(self): self.game_process = GameProcess() self.game_process.players.append(Player.bot()) self.game_process.players.extend([Player(name=n) for n in self.users]) def users_clear_all(self): self.users.clear() def users_append_new(self, name): name = str(name).capitalize() self.users.append(name) def to_json(self): return asdict(self)
class GameProcess: words = attrib(factory=list) current_player_i = attrib(default=0, type=int) attempt_count = attrib(default=0, type=int) players = attrib(factory=list, convert=ensure_cls(Player)) losing_players = attrib(factory=list, convert=ensure_cls(Player)) vars = attrib(factory=dict) def _next_player_index(self): if self.current_player_i == len(self.players) - 1: return 0 else: return self.current_player_i + 1 def _previous_player_index(self): if self.current_player_i == 0: return len(self.players) - 1 else: return self.current_player_i - 1 def player_say(self, value): self.words.append(value) self.current_player_i = self._next_player_index() @property def next_player(self): return self.players[self._next_player_index()] @property def current_player(self): return self.players[self.current_player_i] def previous_player(self): return self.players[self._previous_player_index()] def current_player_do_lost(self): self.losing_players.append(self.players.pop(self.current_player_i)) if self.current_player_i == len(self.players): self.current_player_i = 0 def current_player_is_bot(self): return self.current_player().name == BOT_NAME
class Entity(AliceObject): """Entity object""" type = attrib(type=str) tokens = attrib(convert=ensure_cls(EntityTokens)) value = attrib(factory=dict) @type.validator def check(self, attribute, value): """Report unknown type""" if value not in EntityType.all(): log.error('Unknown Entity type! `%r`', value) def __attrs_post_init__(self): """If entity type not number, convert to EntityValue""" if self.value and self.type != EntityType.YANDEX_NUMBER: self.value = EntityValue(**self.value)
class AliceResponse(AliceObject): """AliceResponse is a response to Alice API""" response = attrib(converter=ensure_cls(Response)) session = attrib(converter=ensure_cls(BaseSession)) version = attrib(type=str)
class CardFooter(AliceObject): """This object represents a card's footer""" text = attrib(type=str) button = attrib(default=None, converter=ensure_cls(MediaButton))
class AliceRequest(AliceObject): """AliceRequest is a request from Alice API""" meta = attrib(convert=ensure_cls(Meta)) request = attrib(convert=ensure_cls(Request)) session = attrib(convert=ensure_cls(Session)) version = attrib(type=str) def _response(self, response): return AliceResponse(response=response, session=self.session.base, version=self.version) def response(self, responose_or_text, **kwargs): """ Generate response :param responose_or_text: Response or Response's text: if responose_or_text is not an instance of Response, it is passed to the Response initialisator with kwargs. Otherwise it is used as a Response :param kwargs: tts, card, buttons, end_session for Response NOTE: if you want to pass card, concider using one of these methods: response_big_image, response_items_list :return: AliceResponse """ if not isinstance(responose_or_text, Response): responose_or_text = Response(responose_or_text, **kwargs) return self._response(responose_or_text) def response_big_image(self, text, image_id, title, description, button=None, **kwargs): """ Generate response with Big Image card :param text: Response's text :param image_id: Image's id for BigImage Card :param title: Image's title for BigImage Card :param description: Image's description for BigImage Card :param button: Image's button for BigImage Card :param kwargs: tts, buttons, end_session for Response :return: AliceResponse """ return self._response( Response( text, **kwargs, card=Card.big_image(image_id, title, description, button), )) def response_items_list(self, text, header, items, footer=None, **kwargs): """ Generate response with Items List card :param text: Response's text :param header: Card's header :param items: Card's items - list of `Image` objects :param footer: Card's footer :param kwargs: tts, buttons, end_session for Response :return: AliceResponse """ return self._response( Response(text, **kwargs, card=Card.items_list(header, items, footer)))
class Card(AliceObject): """This object represents a Card either of type `BigImage` or `ItemsList`""" type = attrib(type=str) # for BigImage image_id = attrib(default=None, type=str) title = attrib(default=None, type=str) description = attrib(default=None, type=str) button = attrib(default=None, convert=ensure_cls(MediaButton)) # for ItemsList header = attrib(default=None, convert=ensure_cls(CardHeader)) items = attrib(default=None, convert=ensure_cls(Image)) # List of Image objects footer = attrib(default=None, convert=ensure_cls(CardFooter)) @type.validator def check(self, attribute, value): """ Type can be 'BigImage' or 'ItemsList' "BigImage" — с одним изображением "ItemsList" — с галереей из нескольких изображений """ if value not in CardType.all(): raise ValueError( f'Card type must be "BigImage" or "ItemsList", not "{value}"') @classmethod def big_image(cls, image_id, title, description, button=None): """ Generate Big Image card :param image_id: Image's id for BigImage Card :param title: Image's title for BigImage Card :param description: Image's description for BigImage Card :param button: Image's button for BigImage Card :return: Card """ return cls( CardType.BIG_IMAGE, image_id=image_id, title=title, description=description, button=button, ) @classmethod def items_list(cls, header, items, footer=None): """ Generate Items List card :param header: Card's header :param items: Card's items - list of `Image` objects :param footer: Card's footer :return: Card """ return cls( CardType.ITEMS_LIST, header=header, items=items, footer=footer, )
class Image(AliceObject): """Image object""" image_id = attrib(type=str) title = attrib(type=str) description = attrib(type=str) button = attrib(default=None, convert=ensure_cls(MediaButton))
class NaturalLanguageUnderstanding(AliceObject): """Natural Language Understanding object""" tokens = attrib(factory=list) entities = attrib(factory=list, convert=ensure_cls(Entity))