def get_bot_profile(): global bot_profile url = create_url(bot_info_method) response = requests.get(url) data = response.json() if data["ok"]: bot_profile = DictObject.objectify(data["result"])
def _add_message(self, text): """ Appends a message to the message queue. :type text: builtins.str :return: """ try: logger.debug("Received Message: \"{str}\"".format(str=text)) json_dict = json.loads(text) message = DictObject.objectify(json_dict) message = fix_message(message) except ValueError as e: for check in fix_plain_output.all: m = check[0].match(text) if m: message = DictObject(manual_result=m.groupdict(), type=check[1]) logger.warn( "Manually parsed output! This should be json!\nMessage:>{}<" .format(text)) break else: logger.warn( "Received message could not be parsed.\nMessage:>{}<". format(text), exc_info=True) return if self.append_json: message.merge_dict({u("json"): text}) with self._queue_access: self._queue.append(message) self._new_messages.release()
def _add_message(self, text): """ Appends a message to the message queue. :type text: builtins.str :return: """ try: logger.debug("Received Message: \"{str}\"".format(str=text)) json_dict = json.loads(text) message = DictObject.objectify(json_dict) message = self.parse_message(message) except ValueError as e: logger.warn( "Received message could not be parsed.\nMessage:>{}<".format( text), exc_info=True) return if isinstance(message, InitMessage): self.init_queue.append_message(message) elif isinstance(message, ProposeMessage): self.propose_queue.append_message(message) elif isinstance(message, PrevoteMessage): self.prevote_queue.append_message(message) elif isinstance(message, VoteMessage): self.vote_queue.append_message(message) else: logger.warning( "Discarded unknown message type: {msg_type}, {msg}".format( msg_type=type(message), msg=message))
def __init__(self, e): if isinstance(e, str): try: e = xml.fromstring(e) except xml.ParseError: logger.warn("Skipping malformed line: {line}".format(line=e), exc_info=True) return if isinstance(e, xml.Element): e = etree_to_dict(e) if isinstance(e, dict): e = DictObject.objectify(e) assert isinstance(e, DictObject) assert hasattr(e.item, "type") self.type = ascii_integers_to_string(e.item.type) self.code = ascii_integers_to_string(e.item.code) self.length = int(e.item.length) if "data" in e.item: assert self.length > 0 # length is zero if data is undefined. self.data = encoded_to_str(e.item.data["#text"], e.item.data["@encoding"], as_bytes=True) if e.item.data["@encoding"] == "base64": self._data_base64 = to_unicode(e.item.data["#text"]) else: self._data_base64 = None else: assert self.length == 0 # length is zero if data is undefined. self.data = to_binary("") self._data_base64 = None
def init(): path = "bot/" + API_KEY + "/income" hostname = HOSTNAME if not hostname: info = DictObject.objectify(requests.get('http://ipinfo.io').json()) logger.info("PATH: {}".format(info)) hostname = str(info.ip) # end if webhook_url = "https://" + hostname + "/" + URL_PATH + "/" + path logger.success("URL: {}".format(webhook_url)) # In case sending a custom public key # from pytgbot.api_types.sendable import InputFile # response = bot.set_webhook(webhook_url, certificate=InputFile("/certs/ YOUR FILE")) # In case of a valid HTTPS host, you can go with: response = bot.set_webhook(webhook_url) logger.success(response) import json return json.dumps({ "status": "ok", "webhook": webhook_url, "response": repr(response) })
def do(self, command, files=None, use_long_polling=False, request_timeout=None, **query): """ Returns the input as dict so that the result of any method is the do arguments. :param command: :param files: :param use_long_polling: :param request_timeout: :param query: :return: """ if command in self.fake_responses: return self._postprocess_data(self.fake_responses[command]) # end if url, params = self._prepare_request(command, query) data = { "call": { 'command': command, 'files': files, 'use_long_polling': use_long_polling, 'request_timeout': request_timeout, '**query': query }, "url": url, "json": params, "is_python_object": self.return_python_objects } return DictObject.objectify(data)
def __init__(self, e): if isinstance(e, str): try: e = xml.fromstring(e) except Exception: LOGGER.exception("Skipping malformed line") return if isinstance(e, xml.Element): e = etree_to_dict(e) if isinstance(e, dict): e = DictObject.objectify(e) assert isinstance(e, DictObject) assert hasattr(e.item, "type") self.type = ascii_integers_to_string(e.item.type) self.code = ascii_integers_to_string(e.item.code) self.length = int(e.item.length) if "data" in e.item: assert self.length > 0 # length is zero if data is undefined. self.data = encoded_to_str(e.item.data["#text"], e.item.data["@encoding"], as_bytes=True) if e.item.data["@encoding"] == "base64": self._data_base64 = try_decode(e.item.data["#text"]) else: self._data_base64 = None else: assert self.length == 0 # length is zero if data is undefined. self.data = try_encode("") self._data_base64 = None
def _do_request(self, url, params=None, files=None, use_long_polling=None, request_timeout=None): """ :param url: The complete url to send to :type url: str :keyword params: Parameter for that connection :keyword files: Optional files parameters :keyword use_long_polling: if it should use long polling. (see http://docs.python-requests.org/en/latest/api/#requests.Response.iter_content) :type use_long_polling: bool :keyword request_timeout: When the request should time out. :type request_timeout: int :return: json data received :rtype: DictObject.DictObject """ import requests r = requests.post(url, params=params, files=files, stream=use_long_polling, verify=True, timeout=request_timeout) # No self signed certificates. Telegram should be trustworthy anyway... from DictObject import DictObject try: logger.debug("Response: {}".format(r.json())) json_data = DictObject.objectify(r.json()) except Exception: logger.exception("Parsing answer failed.\nRequest: {r!s}\nContent: {r.content}".format(r=r)) raise # end if json_data["response"] = r # TODO: does this failes on json lists? Does TG does that? return json_data
def _add_message(self, text): """ Appends a message to the message queue. :type text: builtins.str :return: """ try: logger.debug("Received Message: \"{str}\"".format(str=text)) json_dict = json.loads(text) message = DictObject.objectify(json_dict) message = fix_message(message) except ValueError as e: for check in fix_plain_output.all: m = check[0].match(text) if m: message = DictObject(manual_result=m.groupdict(), type=check[1]) logger.warn("Manually parsed output! This should be json!\nMessage:>{}<".format(text)) break else: logger.warn("Received message could not be parsed.\nMessage:>{}<".format(text), exc_info=True) return if self.append_json: message.merge_dict({u("json"): text}) with self._queue_access: self._queue.append(message) self._new_messages.release()
def create_formatter(self): return DictObject.objectify( dict( color_black=self.prepare_color(self.BLACK), color_red=self.prepare_color(self.RED), color_green=self.prepare_color(self.GREEN), color_yellow=self.prepare_color(self.YELLOW), color_blue=self.prepare_color(self.BLUE), color_lightblue=self.prepare_color(self.LIGHT_BLUE), color_magenta=self.prepare_color(self.MAGENTA), color_cyan=self.prepare_color(self.CYAN), color_white=self.prepare_color(self.WHITE), color_grey=self.prepare_color(self.GREY), color_off=self.prepare_color( self.DEFAULT), # Default foreground color background_red=self.prepare_color(self.BG_RED), background_grey=self.prepare_color(self.BG_GREY), background_default=self.prepare_color( self.BG_DEFAULT), # turn of background background_off=self.prepare_color( self.BG_DEFAULT), # Default background color inverse_on=self.prepare_color( 7 ), # Reverse (invert the foreground and background colors) inverse_off=self.prepare_color(27), # Reset reverse all_off=self.prepare_color(self.RESET), ))
def process_received_message(message): global pending_hide_keyboard logger.info(message) message = DictObject.objectify(message) username = message['from'].username if hasattr(message['from'], 'username') else None processed_event = process_chat_event(message)#text or location if not processed_event: is_text = hasattr(message, 'text') if not is_text: #if it's not text it will not be processed for commands or direct message process_no_text_message(message, username) return processed_command = process_command(message, username) if not processed_command: processed_reply = commands.process_expected_reply(message.chat.id,\ message['from']['id'],\ username,\ message.text) if processed_reply: # Processed as reply, won't continue pending_hide_keyboard = True return (direct_msg, clean_text) = direct_message(message) direct_conversation = is_direct_conversation(message) if direct_msg: process_chat_message(message, clean_text) if not direct_msg or direct_conversation: process_message_trigger(message, clean_text, username)
def process_received_message(message): global pending_hide_keyboard logger.info(message) message = DictObject.objectify(message) username = message['from'].username if hasattr(message['from'], 'username') else None processed_event = process_chat_event(message) #text or location if not processed_event: is_text = hasattr(message, 'text') if not is_text: #if it's not text it will not be processed for commands or direct message process_no_text_message(message, username) return processed_command = process_command(message, username) if not processed_command: processed_reply = commands.process_expected_reply(message.chat.id,\ message['from']['id'],\ username,\ message.text) if processed_reply: # Processed as reply, won't continue pending_hide_keyboard = True return (direct_msg, clean_text) = direct_message(message) direct_conversation = is_direct_conversation(message) if direct_msg: process_chat_message(message, clean_text) if not direct_msg or direct_conversation: process_message_trigger(message, clean_text, username)
def load_message_triggers(): global message_triggers global configuration triggers_file = configuration.get('Message triggers', 'file_path') with open(triggers_file) as data_file: message_triggers = json.load(data_file) message_triggers = DictObject.objectify(message_triggers) logger.info("Loading message triggers...")
def get_json(url, objectify=True, **kwargs): kwargs.setdefault("headers", HEADERS) json = requests.get(url, **kwargs).json() if objectify: return DictObject.objectify(json) return json # end def
def get_bot_profile(): global bot_profile url = create_url(bot_info_method) response = requests.get(url) if response.status_code >= 400: logger.error('url: %s', url) logger.error('response: %s - %s', response.status_code, response.text) data = response.json() if data["ok"]: bot_profile = DictObject.objectify(data["result"])
def get_bot_profile(): global bot_profile url = create_url(bot_info_method) response = requests.get(url) if response.status_code>= 400: logger.error('url: %s', url) logger.error('response: %s - %s', response.status_code, response.text) data = response.json() if data["ok"]: bot_profile = DictObject.objectify(data["result"])
def do(self, command, files=None, **query): """ Send a request to the api. :param action: :param data: :param query: :return: """ url = self._base_url.format(api_key=n(self.api_key), command=n(command)) r = requests.post(url, params=query, files=files, verify=True) # No self signed certificates. Telegram should be trustworthy anyway... return DictObject.objectify(r.json())
def load_message_triggers(): global message_triggers global configuration logger.info("Loading message triggers...") triggers_file = configuration.get('Message triggers', 'file_path') if os.path.isfile(triggers_file): with open(triggers_file) as data_file: message_triggers = json.load(data_file) message_triggers = DictObject.objectify(message_triggers) else: logger.info("Creating triggers file: " + triggers_file) message_triggers = [] json.dump(message_triggers, open(triggers_file, 'w'))
def load_permissions(): permissions = None permissions_file = configuration.get('Privileges', 'permissions_file') logger.info("Loading permissions...") if os.path.isfile(permissions_file): with open(permissions_file) as data_file: permissions = json.load(data_file) permissions = DictObject.objectify(permissions) else: logger.info("Creating permissions file: " + permissions_file) permissions = {"root": "", "admins": [], "privileged_users": []} json.dump(permissions, open(permissions_file, 'w')) return permissions
def process_received_message(message): logger.info(message) message = DictObject.objectify(message) processed_event = process_chat_event(message) if not processed_event: processed_command = process_command(message) if not processed_command: (direct_msg, clean_text) = direct_message(message) direct_conversation = is_direct_conversation(message) if direct_msg: process_chat_message(message, clean_text) if not direct_msg or direct_conversation: process_message_trigger(message, clean_text)
def containers(self, exclude_self=False): """ Gets metadata for all containers in this scale grouping. :return: """ filters = [ '{0}={1}'.format(self.LABEL_COMPOSE_PROJECT, self.project), '{0}={1}'.format(self.LABEL_COMPOSE_SERVICE, self.service), # '{0}={1}'.format(LABEL_ONE_OFF, "True" if one_off else "False") ] return DictObject.objectify([ c for c in self.cli.containers(filters={'label': filters}) if not (exclude_self and c['Id'][:12] == self.hostname_env[:12]) ])
def __init__(self, text, receiver=None, reply_id=DEFAULT_MESSAGE_ID, parse_mode=DEFAULT_MARKDOWN_IS_NONE, reply_markup=None, disable_notification=False, disable_web_page_preview=True, call=None): super().__init__(receiver=receiver, reply_id=reply_id, reply_markup=reply_markup, disable_notification=disable_notification) if parse_mode is TextMessage.DEFAULT_MARKDOWN_IS_NONE: if call: call = DictObject.objectify(call) logger.warning("No parse mode was set, do you need the old default 'markdown'?\n" "Called from function {caller.name} at file {caller.file}:{caller.line}\n" "The line is:\n" "{caller.code}".format(**call) ) else: logger.warning("No parse mode was set, do you need the old default 'markdown'?\nCaller unknown.") # end if parse_mode = "text" # end if if parse_mode == "text": parse_mode = None # because "text" does not exist on TG Api. # end if texts = text_split(text, MAX_TEXT_LENGTH, max_parts=2) if len(texts) == 0: raise ValueError("Text was empty") if len(texts) == 1: logger.debug("Message has length {all} ({all_bytes} bytes). Not split.".format( all=len(text), all_bytes=len(escape(text).encode("utf-8")) )) else: logger.debug( "Message of length {all} ({all_bytes} bytes) split into {part} ({part_bytes} bytes) + {rest} more.".format( all=len(text), all_bytes=len(escape(text).encode("utf-8")), part=len(texts[0]), part_bytes=len(escape(texts[0]).encode("utf-8")), rest=len(texts) - 1 ) ) # end if self.disable_web_page_preview = disable_web_page_preview self.parse_mode = parse_mode self.text = texts[0] if len(texts) > 1: self.receiver = receiver self._next_msg = TextMessage( texts[1], receiver=receiver, parse_mode=self.parse_mode, reply_markup=reply_markup, disable_notification=disable_notification ) # end if if not text: raise ValueError("No text provided.")
def load_permissions(): permissions = None permissions_file = configuration.get('Privileges', 'permissions_file') logger.info("Loading permissions...") if os.path.isfile(permissions_file): with open(permissions_file) as data_file: permissions = json.load(data_file) permissions = DictObject.objectify(permissions) else: logger.info("Creating permissions file: " + permissions_file) permissions = { "root": "", "admins": [], "privileged_users": [] } json.dump(permissions, open(permissions_file, 'w')) return permissions
def _postprocess_request(self, request, response, json): """ This converts the response to either the response or a parsed :class:`pytgbot.api_types.receivable.Receivable`. :param request: the request :type request: request.Request|httpx.Request :param response: the request response :type response: requests.Response|httpx.Response :param json: the parsed json array :type json: dict :return: The json response from the server, or, if `self.return_python_objects` is `True`, a parsed return type. :rtype: DictObject.DictObject | pytgbot.api_types.receivable.Receivable """ from DictObject import DictObject try: logger.debug(json) res = DictObject.objectify(json) except Exception as e: raise TgApiResponseException('Parsing answer as json failed.', response, e) # end if res["_response"] = response # TODO: does this failes on json lists? Does TG does that? # TG should always return an dict, with at least a status or something. if self.return_python_objects: if res.ok is not True: raise TgApiServerException( error_code=res.error_code if "error_code" in res else None, response=res.response if "response" in res else None, description=res.description if "description" in res else None, request=request) # end if not ok if "result" not in res: raise TgApiParseException('Key "result" is missing.') # end if no result return res.result # end if return_python_objects return res
def _add_message(self, text): """ Appends a message to the message queue. :type text: builtins.str :return: """ try: logger.debug("Received Message: \"{str}\"".format(str=text)) json_dict = json.loads(text) message = DictObject.objectify(json_dict) message = self.parse_message(message) except ValueError as e: logger.warn( "Received message could not be parsed.\nMessage:>{}<".format( text), exc_info=True) return with self._queue_access: self._queue.append(message) self._new_messages.release()
def get_pokemon_config(): args_dict = None config_path = os.path.join(get_pokemon_directory(), pokesearch_config_file) with open(config_path) as file: args_dict = json.load(file) # args_dict = { # 'auth_service': 'google', # 'username': '******', # 'password': '******', # 'location': '20.6704923,-103.3713086', # 'step-limit': 10, # 'ignore': False, # 'only': '13', # 'display-pokestop': False, # 'display-gym': False, # 'locale': 'en', # 'onlylure': False, # 'ampm_clock': False, # 'debug': False # } return DictObject.objectify(args_dict)
def do(self, command, files=None, use_long_polling=False, request_timeout=None, **query): """ Returns the input as dict so that the result of any method is the do arguments. :param command: :param files: :param use_long_polling: :param request_timeout: :param query: :return: """ if command in self.fake_responses: return self._postprocess_data(self.fake_responses[command]) # end if url, params = self._prepare_request(command, query) data = { "call": {'command': command, 'files': files, 'use_long_polling': use_long_polling, 'request_timeout': request_timeout, '**query': query}, "url": url, "json": params, "is_python_object": self.return_python_objects } return DictObject.objectify(data)
def _do_request(self, url, params=None, files=None, use_long_polling=None, request_timeout=None): """ :param url: The complete url to send to :type url: str :keyword params: Parameter for that connection :keyword files: Optional files parameters :keyword use_long_polling: if it should use long polling. (see http://docs.python-requests.org/en/latest/api/#requests.Response.iter_content) :type use_long_polling: bool :keyword request_timeout: When the request should time out. :type request_timeout: int :return: json data received :rtype: DictObject.DictObject """ import requests r = requests.post( url, params=params, files=files, stream=use_long_polling, verify=True, timeout=request_timeout ) # No self signed certificates. Telegram should be trustworthy anyway... from DictObject import DictObject try: logger.debug("Response: {}".format(r.json())) json_data = DictObject.objectify(r.json()) except Exception: logger.exception("Parsing answer failed.\nRequest: {r!s}\nContent: {r.content}".format(r=r)) raise # end if json_data["response"] = r # TODO: does this failes on json lists? Does TG does that? return json_data
def execute_function(self, function_name, *arguments, **kwargs): """ Execute a function. Will check a bit, if the parameters looks fitting. If you specify retry_connect=int keyword. This is wrapped by .execute_function() to support both py3 and py2 syntax. :param function_name: The function name. :type function_name: str Now you may apply your arguments for that command. :keyword reply_id: The message id which this command is a reply to. (will be ignored on non-sending commands) :type reply_id: int or None :keyword enable_preview: If the URL found in a message should have a preview. Defaults to False. (Will be ignored by the CLI with non-sending commands) :type enable_preview: bool :keyword retry_connect: How often it should try to reconnect (-1 = infinite times) or fail if it can't establish the first connection. (default is 2) :type retry_connect: int :return: parsed result/exception :rtype: Object or IllegalResponseException :raises pytg.exceptions.NoResponse: If the CLI answer command timed out. """ command_name, new_args = self._validate_input(function_name, arguments) reply_id=None # python 2 fix if "reply_id" in kwargs: reply_id = kwargs["reply_id"] enable_preview=None if "enable_preview" in kwargs: enable_preview = kwargs["enable_preview"] retry_connect=2 if "retry_connect" in kwargs: retry_connect = kwargs["retry_connect"] if self._do_quit and not "quit" in command_name: raise AssertionError("Socket already terminated.") result_parser = functions[function_name][FUNC_RES] result_timeout = functions[function_name][FUNC_TIME] try: if result_timeout: result = self._do_command(command_name, new_args, answer_timeout=result_timeout, retry_connect=retry_connect, enable_preview=enable_preview, reply_id=reply_id) else: result = self._do_command(command_name, new_args, answer_timeout=self.default_answer_timeout, retry_connect=retry_connect, enable_preview=enable_preview, reply_id=reply_id) except ConnectionError as err: raise except NoResponse as err: args_ = inspect.getargspec(result_parser)[0] if not "exception" in args_: logger.exception("Result parser does not allow exceptions, but we got one: ") raise IllegalResponseException("Result parser does not allow exceptions.") try: return_result = result_parser(exception=err) return return_result except TypeError: logger.error("Result parser did not allow exceptions.") raise if result_parser != res.raw: # skip json'ing stuff marked as raw output. try: json_dict = json.loads(result) message = DictObject.objectify(json_dict) message = fix_message(message) except: logger.exception("Parsing of answer failed, maybe not valid json?\nMessage: >{}<".format(result)) #result_parser todo return IllegalResponseException("Parsing of answer failed, maybe not valid json?\nMessage: >{}<".format(result)) #TODO: This is *very* bad code. return result_parser(message) return result_parser(result) # raw()
def execute_function(self, function_name, *arguments, **kwargs): """ Execute a function. Will check a bit, if the parameters looks fitting. If you specify retry_connect=int keyword. This is wrapped by .execute_function() to support both py3 and py2 syntax. :param function_name: The function name. :type function_name: str Now you may apply your arguments for that command. :keyword reply_id: The message id which this command is a reply to. (will be ignored on non-sending commands) :type reply_id: int or None :keyword enable_preview: If the URL found in a message should have a preview. Defaults to False. (Will be ignored by the CLI with non-sending commands) :type enable_preview: bool :keyword retry_connect: How often it should try to reconnect (-1 = infinite times) or fail if it can't establish the first connection. (default is 2) :type retry_connect: int :keyword result_timeout: How long, in seconds, we wait for the cli to answer the send command. Set to None to use the global default timeout (`Sender.default_answer_timeout`) instead of the default timeout for the given command. To use the default timeout for that command omit this parameter. :type result_timeout: int or None :return: parsed result or raises an exception :rtype: Object or IllegalResponseException :raises pytg.exceptions.NoResponse: If the CLI answer command timed out. """ command_name, new_args = self._validate_input(function_name, arguments) reply_id = None # python 2 fix if "reply_id" in kwargs: reply_id = kwargs["reply_id"] enable_preview = None if "enable_preview" in kwargs: enable_preview = kwargs["enable_preview"] retry_connect = 2 if "retry_connect" in kwargs: retry_connect = kwargs["retry_connect"] if self._do_quit and "quit" not in command_name: raise AssertionError("Socket already terminated.") result_parser = functions[function_name][FUNC_RES] result_timeout = functions[function_name][FUNC_TIME] if "result_timeout" in kwargs: result_timeout = kwargs["result_timeout"] modifier = [] # reply id modifier if reply_id: if not isinstance(reply_id, int): # reply id modifier workaround if function_name in reply_functions: alternative_command = reply_functions[function_name] logger.warn("Trying to substitute command \"{cmd}\" to \"{alt}\" to provide backwards compatibiltity for the reply parameter.\n" "Please note this is *very* hacky and should NOT be trusted or used!!\n" "See https://github.com/luckydonald/pytg/issues/65 for details.".format(cmd=function_name, alt=alternative_command)) arguments = list(arguments) # because it is a tuple. arguments[0] = reply_id # should - in theory - replace the peer with the reply id. del kwargs["reply_id"] # so we don't try to substitute again. # This is at least the syntax of msg -> reply return self.execute_function(alternative_command, *arguments, **kwargs) else: raise AttributeError("reply_id keyword argument is not integer. " "Please use the reply methods with the permantent-msg-ids instead!") else: modifier.append("[reply =%i]" % reply_id) # preview modifier modifier.append("[enable_preview]" if enable_preview else "[disable_preview]") modifier_str = " ".join(modifier) try: request = self._build_request(command_name, new_args, modifier=modifier_str) if result_timeout: result = self._do_send(request, answer_timeout=result_timeout, retry_connect=retry_connect) else: result = self._do_send(request, answer_timeout=self.default_answer_timeout, retry_connect=retry_connect) except ConnectionError: raise except NoResponse: raise except Exception as err: args_ = inspect.getargspec(result_parser)[0] if "exception" not in args_: logger.exception("Result parser does not allow exceptions, but we got one: ") raise IllegalResponseException("Result parser does not allow exceptions.") try: return_result = result_parser(exception=err) return return_result except TypeError: logger.error("Result parser did not allow exceptions.") raise # end try _do_command if inspect.isclass(result_parser): assert issubclass(result_parser, ResultParser) # if it is a class it should subclass ResultParser. result_parser = result_parser() # get an instance # end if if result_parser != res.raw: # skip json'ing stuff marked as raw output. try: json_dict = json.loads(result) message = DictObject.objectify(json_dict) message = fix_message(message) result = message except: logger.exception("Parsing of answer failed, maybe not valid json?\nMessage:\n{}".format(result)) return IllegalResponseException("Parsing of answer failed, maybe not valid json?\nMessage: >{}<".format(result)) # TODO: This is *very* bad code. try: return result_parser(message) except FailException as e: e.command = request raise e # else (raw only) return result_parser(result) # raw() only
def main(): global logger global scheduler global chatbot global chat_events global message_triggers global configuration parser = argparse.ArgumentParser(description="Telegram bot program") parser.add_argument("-l", "--log", help="File to write log", default=None, metavar="FILE") parser.add_argument("-a", "--authorization-token", metavar="AUTHORIZATION_TOKEN", help="Set new Telegram authorization token", default=None) parser.add_argument("-v", "--verbose", help="Enable verbose mode", action='store_true', default=None) parser.add_argument("-t", "--train", help="Train chat bot based on the english corpus", action='store_true', default=None) parser.add_argument("-c", "--config-file", metavar="CONFIG_FILE", help="Set configuration file", type=argparse.FileType('r')) args = parser.parse_args() #Logger configuration logging_level = None if args.verbose: logging_level = logging.INFO logger = tglog.config_logger(name = LOGGER_NAME, log_file = args.log, replace_stdout=True, logLevel=logging_level) #Configuration file config_file = args.config_file config = configparser.RawConfigParser() if not config_file is None: config.readfp(config_file) else: config_path = config_file_path() logger.info("Loading configuration file: {file}".format(file=config_path)) if config_path is None or not os.path.isfile(config_path): logger.error("Config file:{config_file} doesn't exist.".format(config_file=config_path)) logger.error("Please provide a configuration file via -c argument or setting up {var_name} environment variable.".format(var_name=CONFIG_ENV_VAR)) return 1 config.read(config_path) configuration = config logger.info("Configuration file loaded sucessfully") # Set new token if necessary if args.authorization_token: config.set('Telegram', 'bot_token', args.authorization_token) with open(config_path, 'w') as configfile: config.write(configfile) logger.info('New authorization token saved.') # Get Telegram API properties create_url.url_format = config.get('Telegram','url_format') create_url.bot_token = config.get('Telegram', 'bot_token') if create_url.bot_token == 'TOKEN_BOT': logger.error("bot_token is missing, please add a token to tgbot.cgf") logger.error("Full config path: " + config_file_path()) return 1 # Load chat events events_file = config.get('Chat events', 'file_path') with open(events_file) as data_file: chat_events = json.load(data_file) chat_events = DictObject.objectify(chat_events) logger.info("Loading chat events...") # Load message events load_message_triggers() # Load permissions load_permissions() # Chat bot configuration chatbot_db = config.get('Chatterbot', 'db_path') try: chatbot = init_chatbot(chatbot_db) except MissingCorpusError: logger.warning("Corpora needs to be downloaded in order to use Chatterbot... downloading") textblob.download_corpora.download_all() chatbot = init_chatbot(chatbot_db) if args.train: logger.info("Bot is being trained...") chatbot.set_trainer(ChatterBotCorpusTrainer) chatbot.train("chatterbot.corpus.english") logger.info("Chatterbot initialized...") logger.info("Bot token: " + create_url.bot_token) # Load message commands sender = TelegramSender() commands.load_commands(sender, logger) # Telegram listener try: logger.info("Retrieving bot profile...") get_bot_profile() logger.info("Listening for incoming messages...") while True: get_updates() except GeneratorExit: clean_program() except KeyboardInterrupt: clean_program() else: clean_program() #Finish logger.info("Telegram bot terminated")
def me(self): return [ DictObject.objectify(c) for c in self.cli.containers() if c['Id'][:12] == self.hostname_env[:12] ][0]
def main(): global logger global scheduler global chatbot global chat_events global message_triggers global configuration parser = argparse.ArgumentParser(description="Telegram bot program") parser.add_argument("-l", "--log", help="File to write log", default=None, metavar="FILE") parser.add_argument("-v", "--verbose", help="Enable verbose mode", default=None) parser.add_argument("-c", "--config_file", help="Set configuration file", type=argparse.FileType('r')) args = parser.parse_args() #Logger configuration logging_level = None if args.verbose: logging_level = logging.INFO logger = tglog.config_logger(name = LOGGER_NAME, log_file = args.log, replace_stdout=True, logLevel=logging_level) #Configuration file config_file = args.config_file config = configparser.RawConfigParser() if not config_file is None: config.readfp(config_file) else: config_path = config_file_path() logger.info("Loading configuration file: {file}".format(file=config_path)) if config_path is None or not os.path.isfile(config_path): logger.error("Config file:{config_file} doesn't exist.".format(config_file=config_path)) logger.error("Please provide a configuration file via -c argument or setting up {var_name} environment variable.".format(var_name=CONFIG_ENV_VAR)) return 1 config.read(config_path) configuration = config logger.info("Configuration file loaded sucessfully") # Load chat events events_file = config.get('Chat events', 'file_path') with open(events_file) as data_file: chat_events = json.load(data_file) chat_events = DictObject.objectify(chat_events) logger.info("Loading chat events...") # Load message events load_message_triggers() #Chat bot configuration chatbot_db = config.get('Chatterbot', 'db_path') chatbot = ChatBot("Terminal", storage_adapter="chatterbot.adapters.storage.JsonDatabaseAdapter", logic_adapter="chatterbot.adapters.logic.EngramAdapter", io_adapter="chatterbot.adapters.io.TerminalAdapter", database=chatbot_db, logging=True) logger.info("Chatterbot initialized...") # Load message commands sender = TelegramSender() commands.load_commands(sender, logger) #Telegram listener create_url.url_format = config.get('Telegram','url_format') create_url.bot_token = config.get('Telegram', 'bot_token') if create_url.bot_token == '': logger.error("bot_token is missing, please add a token to tgbot.cgf") return 1 try: logger.info("Retrieving bot profile...") get_bot_profile() logger.info("Listening for incoming messages...") while True: get_updates() except GeneratorExit: pass except KeyboardInterrupt: pass else: pass #Finish logger.info("Telegram bot terminated")
def get_timeline(): node_list = set() event_list = list() date_min = None date_max = None node_events = DBMessage.select_by_sql(""" SELECT * FROM DBmessage WHERE date >= NOW() - '60 seconds'::INTERVAL """) for node_event in node_events: event_dict = DictObject.objectify({ "id": {}, # for deduplication in the GUI "action": None, # "send" or "acknowledge" "type": None, "nodes": {}, "timestamps": {}, "data": {} }) node_list.add(node_event.node) # update node list if date_min is None or node_event.date < date_min: date_min = node_event.date # end if if date_max is None or node_event.date > date_max: date_max = node_event.date # end if if isinstance(node_event, DBAcknowledge): received_msg = Message.from_dict(node_event.raw) event_dict.id["receive"] = node_event.id event_dict.action = "acknowledge" event_dict.nodes["send"] = received_msg.node event_dict.nodes["receive"] = node_event.node event_dict.timestamps["receive"] = generate_date_data( node_event.date) event_dict.type = JSON_TYPES[received_msg.type] event_dict.data = generate_msg_data(received_msg) node_list.add(received_msg.node) # update node list # additional DB query, to get sender DBClazz = MSG_TYPE_CLASS_MAP[received_msg.type] try: db_received_msg = DBClazz.get( sequence_no=received_msg.sequence_no, node=received_msg.node) event_dict.id["send"] = db_received_msg.id event_dict.timestamps["send"] = generate_date_data( db_received_msg.date) if date_min is None or db_received_msg.date < date_min: date_min = node_event.date # end if if date_max is None or db_received_msg.date > date_max: date_max = node_event.date # end if except orm.DatabaseError: event_dict.id["send"] = None event_dict.timestamps["send"] = generate_date_data(None) # end try else: event_dict.action = "send" event_dict.id["send"] = node_event.id event_dict.nodes["send"] = node_event.node event_dict.timestamps["send"] = generate_date_data(node_event.date) event_dict.type = JSON_TYPES[node_event.type] event_dict.data = generate_msg_data(node_event) # end if event_list.append(event_dict) # end for result = DictObject.objectify({ "nodes": node_list, "timestamps": { "min": generate_date_data(date_min), "max": generate_date_data(date_max) }, "events": event_list, }) return jsonify(result, allow_all_origin=True)
def main(): global logger global scheduler global chatbot global chat_events global message_triggers global configuration parser = argparse.ArgumentParser(description="Telegram bot program") parser.add_argument("-l", "--log", help="File to write log", default=None, metavar="FILE") parser.add_argument("-a", "--authorization-token", metavar="AUTHORIZATION_TOKEN", help="Set new Telegram authorization token", default=None) parser.add_argument("-v", "--verbose", help="Enable verbose mode", action='store_true', default=None) parser.add_argument("-t", "--train", help="Train chat bot based on the english corpus", action='store_true', default=None) parser.add_argument("-c", "--config-file", metavar="CONFIG_FILE", help="Set configuration file", type=argparse.FileType('r')) args = parser.parse_args() #Logger configuration logging_level = None if args.verbose: logging_level = logging.INFO logger = tglog.config_logger(name=LOGGER_NAME, log_file=args.log, replace_stdout=True, logLevel=logging_level) #Configuration file config_file = args.config_file config = configparser.RawConfigParser() if not config_file is None: config.readfp(config_file) else: config_path = config_file_path() logger.info( "Loading configuration file: {file}".format(file=config_path)) if config_path is None or not os.path.isfile(config_path): logger.error("Config file:{config_file} doesn't exist.".format( config_file=config_path)) logger.error( "Please provide a configuration file via -c argument or setting up {var_name} environment variable." .format(var_name=CONFIG_ENV_VAR)) return 1 config.read(config_path) configuration = config logger.info("Configuration file loaded sucessfully") # Get Telegram API properties create_url.url_format = config.get('Telegram', 'url_format') create_url.bot_token = config.get('Telegram', 'bot_token') if create_url.bot_token == 'TOKEN_BOT': logger.error("bot_token is missing, please add a token to tgbot.cgf") logger.error("Full config path: " + config_file_path()) return 1 # Load chat events events_file = config.get('Chat events', 'file_path') with open(events_file) as data_file: chat_events = json.load(data_file) chat_events = DictObject.objectify(chat_events) logger.info("Loading chat events...") # Load message events load_message_triggers() # Load permissions load_permissions() # Chat bot configuration chatbot_db = config.get('Chatterbot', 'db_path') try: chatbot = init_chatbot(chatbot_db) except MissingCorpusError: logger.warning( "Corpora needs to be downloaded in order to use Chatterbot... downloading" ) textblob.download_corpora.download_all() chatbot = init_chatbot(chatbot_db) if args.train: logger.info("Bot is being trained...") chatbot.set_trainer(ChatterBotCorpusTrainer) chatbot.train("chatterbot.corpus.english") logger.info("Chatterbot initialized...") # Set new token if necessary if args.authorization_token: config.set('Telegram', 'bot_token', args.authorization_token) with open(config_path, 'w') as configfile: config.write(configfile) logger.info('New authorization token saved.') logger.info("Bot token: " + create_url.bot_token) # Load message commands sender = TelegramSender() commands.load_commands(sender, logger) # Telegram listener try: logger.info("Retrieving bot profile...") get_bot_profile() logger.info("Listening for incoming messages...") while True: get_updates() except GeneratorExit: clean_program() except KeyboardInterrupt: clean_program() else: clean_program() #Finish logger.info("Telegram bot terminated")
class BotTestable(Bot): def __init__(self, api_key, return_python_objects=False): """ To enable the result of :meth:`self.do` to return data directly. :param api_key: Ignored. :param return_python_objects: Ignored? """ self.__api_key = "4458:FAKE_API_KEY_FOR_TESTING" self.return_python_objects = return_python_objects # super().__init__(API_KEY, return_python_objects=False) # end def fake_responses = DictObject.objectify({ "getMe": { "ok": True, "result": { "id": 1, "first_name": "FAKE BOT FOR TESTING", "username": "******" } }, "getWebhookInfo": { "ok": True, "result": { "url": "https://example.com/income/" + API_KEY, "has_custom_certificate": False, "pending_update_count": 0, "max_connections": 40 } }, }) def do(self, command, files=None, use_long_polling=False, request_timeout=None, **query): """ Returns the input as dict so that the result of any method is the do arguments. :param command: :param files: :param use_long_polling: :param request_timeout: :param query: :return: """ if command in self.fake_responses: return self._postprocess_data(self.fake_responses[command]) # end if url, params = self._prepare_request(command, query) data = { "call": { 'command': command, 'files': files, 'use_long_polling': use_long_polling, 'request_timeout': request_timeout, '**query': query }, "url": url, "json": params, "is_python_object": self.return_python_objects } return DictObject.objectify(data)
def execute_function(self, function_name, *arguments, **kwargs): """ Execute a function. Will check a bit, if the parameters looks fitting. If you specify retry_connect=int keyword. This is wrapped by .execute_function() to support both py3 and py2 syntax. :param function_name: The function name. :type function_name: str Now you may apply your arguments for that command. :keyword reply_id: The message id which this command is a reply to. (will be ignored on non-sending commands) :type reply_id: int or None :keyword enable_preview: If the URL found in a message should have a preview. Defaults to False. (Will be ignored by the CLI with non-sending commands) :type enable_preview: bool :keyword retry_connect: How often it should try to reconnect (-1 = infinite times) or fail if it can't establish the first connection. (default is 2) :type retry_connect: int :return: parsed result/exception :rtype: Object or IllegalResponseException :raises pytg.exceptions.NoResponse: If the CLI answer command timed out. """ command_name, new_args = self._validate_input(function_name, arguments) reply_id = None # python 2 fix if "reply_id" in kwargs: reply_id = kwargs["reply_id"] enable_preview = None if "enable_preview" in kwargs: enable_preview = kwargs["enable_preview"] retry_connect = 2 if "retry_connect" in kwargs: retry_connect = kwargs["retry_connect"] if self._do_quit and not "quit" in command_name: raise AssertionError("Socket already terminated.") result_parser = functions[function_name][FUNC_RES] result_timeout = functions[function_name][FUNC_TIME] try: if result_timeout: result = self._do_command(command_name, new_args, answer_timeout=result_timeout, retry_connect=retry_connect, enable_preview=enable_preview, reply_id=reply_id) else: result = self._do_command( command_name, new_args, answer_timeout=self.default_answer_timeout, retry_connect=retry_connect, enable_preview=enable_preview, reply_id=reply_id) except ConnectionError as err: raise except NoResponse as err: args_ = inspect.getargspec(result_parser)[0] if not "exception" in args_: logger.exception( "Result parser does not allow exceptions, but we got one: " ) raise IllegalResponseException( "Result parser does not allow exceptions.") try: return_result = result_parser(exception=err) return return_result except TypeError: logger.error("Result parser did not allow exceptions.") raise if result_parser != res.raw: # skip json'ing stuff marked as raw output. try: json_dict = json.loads(result) message = DictObject.objectify(json_dict) message = fix_message(message) except: logger.exception( "Parsing of answer failed, maybe not valid json?\nMessage: >{}<" .format(result)) #result_parser todo return IllegalResponseException( "Parsing of answer failed, maybe not valid json?\nMessage: >{}<" .format(result)) #TODO: This is *very* bad code. return result_parser(message) return result_parser(result) # raw()
def get_json(url, objectify=True, **kwargs): kwargs.setdefault("headers", HEADERS) json = requests.get(url, **kwargs).json() if objectify: return DictObject.objectify(json) return json