예제 #1
0
    def _handle_do_rm_choice_cmd(self, text):
        # /do-rm-choice-{choice_id}
        try:
            choice_id = int(text[14:])
        except Exception:
            Log.e(f"Failed while parsing choice id: {text}")
            raise

        with model.open_session(self._Session) as s:
            poll_ms = _query_active_polls(s, self._chat_id)
            if not poll_ms:
                raise _ResponseException(self.RESPONSE_ERROR_POLL_NOT_EXIST)

            poll_m = poll_ms[0]
            if poll_m.creator_user_id != self._user["id"]:
                raise _ResponseException(self.RESPONSE_ERROR_NOT_CREATOR)
            if len(poll_m.choices) == 1:
                raise _ResponseException(self.RESPONSE_ERROR_RM_LAST_CHOICE)
            choice_m = next(
                filter(lambda c_m: c_m.poll_choice_id == choice_id,
                       poll_m.choices))
            choice = choice_m.text
            s.delete(choice_m)

        self._edit_message_text(self.RESPONSE_RM_CHOICE_PERSISTED_F % choice,
                                parse_mode="Markdown")
예제 #2
0
    def _handle_do_unvote_cmd(self, text):
        # /do-unvote-{choice_id}
        try:
            vote = int(text[11:])
        except Exception:
            Log.e(f"Failed while parsing choice id: {text}")
            raise

        with model.open_session(self._Session) as s:
            poll_ms = _query_active_user_votes(s, self._chat_id,
                                               self._user["id"])
            if not poll_ms:
                raise _ResponseException(
                    self.RESPONSE_ERROR_NOT_VOTED %
                    f"[{self._user['first_name']}](tg://user?id={self._user['id']})"
                )

            poll_m = poll_ms[0]
            for c_m in poll_m.choices:
                if c_m.poll_choice_id == vote:
                    for v_m in c_m.votes:
                        if v_m.user_id == self._user["id"]:
                            vote_m = v_m
                            break
            try:
                choice_text = vote_m.choice.text
                s.delete(vote_m)
            except NameError:
                # User hasn't voted this option?
                raise _ResponseException(
                    self.RESPONSE_ERROR_NOT_VOTED %
                    f"[{self._user['first_name']}](tg://user?id={self._user['id']})"
                )

            text = self.RESPONSE_UNVOTED % (
                f"[{self._user['first_name']}](tg://user?id={self._user['id']})"
            )
            announce_text = self.RESPONSE_UNVOTE_ANNOUNCE % (
                f"[{self._user['first_name']}](tg://user?id={self._user['id']})",
                choice_text)
        self._edit_message_text(text, parse_mode="Markdown")
        self._send_message(announce_text, parse_mode="Markdown")

        # Start a new session to make the delete effective
        with model.open_session(self._Session) as s:
            poll_ms = _query_active_polls(s, self._chat_id)
            if not poll_ms:
                # ???
                raise _ResponseException(self.RESPONSE_ERROR_POLL_NOT_EXIST)

            poll_m = poll_ms[0]
            poll_text = _repr_poll(poll_m)
            poll_keyboard = _make_poll_inline_keyboard(
                poll_m.creator_user_id == self._user["id"])
        self._send_message(
            poll_text,
            parse_mode="Markdown",
            reply_markup=InlineKeyboardMarkup(inline_keyboard=poll_keyboard))
예제 #3
0
    def _handle_do_vote_cmd(self, text):
        # /do-vote-{choice_id}
        try:
            vote = int(text[9:])
        except Exception:
            Log.e(f"Failed while parsing choice id: {text}")
            raise

        with model.open_session(self._Session) as s:
            poll_ms = _query_active_polls(s, self._chat_id)
            if not poll_ms:
                raise _ResponseException(self.RESPONSE_ERROR_POLL_NOT_EXIST)

            poll_m = poll_ms[0]
            user_id = self._user["id"]
            for c_m in poll_m.choices:
                if c_m.poll_choice_id == vote:
                    choice_m = c_m
                    break
            # We don't need a fallback val for choice_m -- it'll raise when we
            # access it anyway

            if not poll_m.is_multiple_vote:
                # Make sure user hasn't voted yet
                for c_m in poll_m.choices:
                    if any(user_id == v_m.user_id for v_m in c_m.votes):
                        raise _ResponseException(
                            self.RESPONSE_ERROR_MULTIPLE_VOTE %
                            f"[{self._user['first_name']}](tg://user?id={self._user['id']})"
                        )
            else:
                # Make sure user hasn't voted for this choice yet
                if any(user_id == v_m.user_id for v_m in choice_m.votes):
                    raise _ResponseException(
                        self.RESPONSE_ERROR_IDENTICAL_VOTE %
                        f"[{self._user['first_name']}](tg://user?id={self._user['id']})"
                    )

            vote_m = model.PollVote(user_id=user_id,
                                    user_name=self._user["first_name"],
                                    choice=choice_m)
            s.add(vote_m)

            text = self.RESPONSE_VOTED % (
                f"[{self._user['first_name']}](tg://user?id={self._user['id']})"
            )
            announce_text = self.RESPONSE_VOTE_ANNOUNCE % (
                f"[{self._user['first_name']}](tg://user?id={self._user['id']})",
                choice_m.text)
            poll_text = _repr_poll(poll_m)
            poll_keyboard = _make_poll_inline_keyboard(
                poll_m.creator_user_id == self._user["id"])
        self._edit_message_text(text, parse_mode="Markdown")
        self._send_message(announce_text, parse_mode="Markdown")
        self._send_message(
            poll_text,
            parse_mode="Markdown",
            reply_markup=InlineKeyboardMarkup(inline_keyboard=poll_keyboard))
예제 #4
0
 def handle(self):
     try:
         self._do_handle()
     except _ResponseException as e:
         Log.e("Failed while handle", e)
         self._bot.sendMessage(self._glance["chat_id"], e.response)
     except Exception as e:
         Log.e("Failed while handle", e)
         self._bot.sendMessage(self._glance["chat_id"],
                               self.RESPONSE_EXCEPTION)
예제 #5
0
		def _callback():
			try:
				self._ensure_allowed_users()
				return self._do_handle()
			except _WhitelistException as e:
				Log.i("Disallowed user (%s) is chating with us"
						% self._msg["from"]["first_name"])
				return self.RESPONSE_DISALLOWED_USER
			except Exception as e:
				Log.e("Failed while _do_handle", e)
				return self.RESPONSE_EXCEPTION
예제 #6
0
 def handle(self):
     try:
         self._do_handle()
     except _ResponseException as e:
         Log.e("Failed while handle", e)
         self._send_message(e.response, parse_mode="Markdown")
     except Exception as e:
         Log.e("Failed while handle", e)
         self._send_message(self.RESPONSE_EXCEPTION)
     finally:
         # After the user presses a callback button, Telegram clients will
         # display a progress bar until you call answerCallbackQuery. It is,
         # therefore, necessary to react by calling answerCallbackQuery even
         # if no notification to the user is needed
         self._bot.answerCallbackQuery(self._glance["query_id"])
예제 #7
0
	def handle(self):
		try:
			self._ensure_supported_chat()
			self._ensure_allowed_users()
			self._do_handle()
		except _ChanelException as e:
			pass
		except _WhitelistException as e:
			Log.i("Disallowed user (%s) is chating with us"
					% self._msg["from"]["first_name"])
			self._bot.sendMessage(self._glance["chat_id"],
					self.RESPONSE_MD_DISALLOWED_USER, parse_mode = "Markdown")
		except Exception as e:
			Log.e("Failed while _do_handle", e)
			self._bot.sendMessage(self._glance["chat_id"],
					self.RESPONSE_EXCEPTION)
예제 #8
0
	def _build_response(self, text):
		query = _QueryHandler(text)
		if query.is_empty:
			return self._TextResponse(self.RESPONSE_NO_RESULTS)
		try:
			response = CustomSearchApi().list(**query.request_args)
		except CustomSearchApi.NetworkError as e:
			Log.e("Failed while list %d: %s" % (e.status_code, e.message))
			if e.status_code == 404:
				return self._TextResponse(self.RESPONSE_NO_MORE_QUOTA)
			else:
				raise e
		if not response or "items" not in response:
			return self._TextResponse(self.RESPONSE_NO_RESULTS)

		if query.is_image:
			return self._build_image_response(response)
		else:
			return self._build_text_response(response)
예제 #9
0
	def _do_handle(self):
		Log.v(self._msg)
		query = _QueryHandler(self._glance["query_string"])
		if query.is_empty:
			return []
		try:
			response = CustomSearchApi().list(**query.request_args)
		except CustomSearchApi.NetworkError as e:
			Log.e("Failed while list %d: %s" % (e.status_code, e.message))
			if e.status_code == 403:
				return self.RESPONSE_NO_MORE_QUOTA
			else:
				raise e
		if not response or "items" not in response:
			return self.RESPONSE_NO_RESULTS

		if query.is_image:
			return self._build_image_response(response)
		else:
			return self._build_text_response(response)
예제 #10
0
	def handle(self):
		try:
			self._ensure_allowed_users()
			response = self._do_handle()
		except _WhitelistException as e:
			Log.i("Disallowed user (%s) is chating with us"
					% self._msg["from"]["first_name"])
			response = self.RESPONSE_DISALLOWED_USER
		except Exception as e:
			Log.e("Failed while _do_handle", e)
			response = self.RESPONSE_EXCEPTION

		if isinstance(response, list):
			self._bot.answerInlineQuery(self._glance["query_id"], response)
		elif isinstance(response, tuple):
			self._bot.answerInlineQuery(self._glance["query_id"], *response)
		elif isinstance(response, dict):
			self._bot.answerInlineQuery(self._glance["query_id"], **response)
		else:
			raise ValueError("Invalid response format")
예제 #11
0
 def list(self, q, **kwargs):
     Log.d("Searching: %s" % q)
     if not q:
         return {}
     args = dict(kwargs)
     args.update({
         "key": self.API_KEY,
         "cx": self.SEARCH_ENGINE_ID,
         "safe": "medium",
         "q": q,
     })
     with http_request("GET", self.URL, params=args) as response:
         if response.status_code != 200:
             Log.e("Failed while list: %d" % response.status_code)
             if response.text:
                 raise self.NetworkError(url=self.URL,
                                         status_code=response.status_code,
                                         message=response.text)
             else:
                 raise self.NetworkError(url=self.URL,
                                         status_code=response.status_code)
         else:
             return response.json()