Exemplo n.º 1
0
class bindings(object):
    def __init__(self, bot):
        self.bot = bot
        self.receiver = Receiver(host="localhost", port=self.bot.config.bindings_token)
        self.sender = Sender(host="localhost", port=self.bot.config.bindings_token)
        logging.getLogger("pytg").setLevel(logging.WARNING)

    def get_me(self):
        msg = self.sender.get_self()
        return User(msg.peer_id, msg.first_name, None, msg.username)

    def convert_message(self, msg):
        id = msg['id']
        if msg.receiver.type == 'user':
            conversation = Conversation(msg.sender.peer_id)
            conversation.title = msg.sender.first_name
        else:
            if msg.receiver.type == 'channel':
                conversation = Conversation(- int('100' + str(msg.receiver.peer_id)))
            else:
                conversation = Conversation(- int(msg.receiver.peer_id))
            conversation.title = msg.receiver.title

        if msg.sender.type == 'user':
            sender = User(int(msg.sender.peer_id))
            if 'first_name' in msg.sender:
                sender.first_name = msg.sender.first_name
            if 'last_name' in msg.sender:
                sender.last_name = msg.sender.last_name
            if 'username' in msg.sender:
                sender.username = msg.sender.username
        else:
            if msg.sender.type == 'channel':
                sender = Conversation(- int('100' + str(msg.sender.peer_id)))
            else:
                sender = Conversation(- int(msg.sender.peer_id))
            sender.first_name = msg.sender.title

        date = msg.date

        # Gets the type of the message
        if 'text' in msg:
            type = 'text'
            content = msg.text
            extra = None
        elif 'media' in msg:
            type = msg.media.type
            content = msg.id
            if 'caption' in msg.media:
                extra = msg.media.caption
            else:
                extra = None
        elif msg.event == 'service':
            type = 'service'
            if msg.action.type == 'chat_del_user':
                content = 'left_user'
                extra = msg.action.user.peer_id
            elif msg.action.type == 'chat_add_user':
                content = 'join_user'
                extra = msg.action.user.peer_id
            elif msg.action.type == 'chat_add_user_link':
                content = 'join_user'
                extra = msg.sender.peer_id
            else:
                type = None
                content = None
                extra = None
        else:
            type = None
            content = None
            extra = None

        # Generates another message object for the original message if the reply.
        if 'reply_id' in msg:
            reply_msg = self.sender.message_get(msg.reply_id)
            reply = self.convert_message(reply_msg)

        else:
            reply = None

        return Message(id, conversation, sender, content, type, date, reply, extra)

    def receiver_worker(self):
        try:
            logging.debug('Starting receiver worker...')
            while self.bot.started:
                self.receiver.start()
                self.receiver.message(self.main_loop())
        except KeyboardInterrupt:
            pass

    def send_message(self, message):
        if not message.extra:
            message.extra = {}

        if message.type != 'text' and message.content.startswith('http'):
            message.content = download(message.content)
        elif message.type != 'text' and not message.content.startswith('/'):
            message.content = self.sender.load_file(message.content)

        if not message.extra or not 'caption' in message.extra:
            message.extra['caption'] = None

        if message.type == 'text':
            self.sender.send_typing(self.peer(message.conversation.id), 1)

            if 'format' in message.extra and message.extra['format'] == 'Markdown':
                message.content = remove_markdown(message.content)
            elif 'format' in message.extra and message.extra['format'] == 'HTML':
                message.content = self.convert_links(message.content)

            try:
                if 'format' in message.extra and message.extra['format'] == 'HTML':
                    self.sender.raw('[html] msg %s %s' % (self.peer(message.conversation.id), self.escape(message.content)), enable_preview=False)
                else:
                    self.sender.send_msg(self.peer(message.conversation.id), message.content, enable_preview=False)
            except Exception as e:
                logging.exception(e)

        elif message.type == 'photo':
            self.sender.send_typing(self.peer(message.conversation.id), 1)  # 7
            try:
                if message.reply:
                    self.sender.reply_photo(message.reply, message.content, message.extra['caption'])
                else:
                    self.sender.send_photo(self.peer(message.conversation.id), message.content, message.extra['caption'])
            except Exception as e:
                logging.exception(e)

        elif message.type == 'audio':
            self.sender.send_typing(self.peer(message.conversation.id), 1)  # 6
            try:
                if message.reply:
                    self.sender.reply_audio(message.reply, message.content)
                else:
                    self.sender.send_audio(self.peer(message.conversation.id), message.content)
            except Exception as e:
                logging.exception(e)

        elif message.type == 'document':
            self.sender.send_typing(self.peer(message.conversation.id), 1)  # 8
            try:
                if message.reply:
                    self.sender.reply_document(message.reply, message.content, message.extra['caption'])
                else:
                    self.sender.send_document(self.peer(message.conversation.id), message.content, message.extra['caption'])
            except Exception as e:
                logging.exception(e)

        elif message.type == 'sticker':
            if message.reply:
                self.sender.reply_file(message.reply, message.content)
            else:
                self.sender.send_file(self.peer(message.conversation.id), message.content)

        elif message.type == 'video':
            self.sender.send_typing(self.peer(message.conversation.id), 1)  # 4
            try:
                if message.reply:
                    self.sender.reply_video(message.reply, message.content, message.extra['caption'])
                else:
                    self.sender.send_video(self.peer(message.conversation.id), message.content, message.extra['caption'])
            except Exception as e:
                logging.exception(e)

        elif message.type == 'voice':
            self.sender.send_typing(self.peer(message.conversation.id), 5)
            try:
                if message.reply:
                    self.sender.reply_audio(message.reply, message.content)
                else:
                    self.sender.send_audio(self.peer(message.conversation.id), message.content)
            except Exception as e:
                logging.exception(e)

        elif message.type == 'location':
            self.sender.send_typing(self.peer(message.conversation.id), 1)  # 9
            if message.reply:
                self.sender.reply_location(message.reply, message.content['latitude'], message.content['longitude'])
            else:
                self.sender.send_location(self.peer(message.conversation.id), message.content['latitude'], message.content['longitude'])

        else:
            print('UNKNOWN MESSAGE TYPE: ' + message.type)
            logging.debug("UNKNOWN MESSAGE TYPE")


    @coroutine
    def main_loop(self):
        while self.bot.started:
            msg = (yield)
            if (msg.event == 'message' and msg.own == False) or msg.event == 'service':
                message = self.convert_message(msg)
                self.bot.inbox.put(message)

                try:
                    if message.conversation.id > 0:
                        self.sender.mark_read(self.peer(message.sender.id))
                    else:
                        self.sender.mark_read(self.peer(message.conversation.id))
                except Exception as e:
                    logging.error(e)


    def peer(self, chat_id):
        if chat_id > 0:
            peer = 'user#id' + str(chat_id)
        else:
            if str(chat_id)[1:].startswith('100'):
                peer = 'channel#id' + str(chat_id)[4:]
            else:
                peer = 'chat#id' + str(chat_id)[1:]
        return peer


    def user_id(self, username):
        if username.startswith('@'):
            command = 'resolve_username ' + username[1:]
            resolve = self.sender.raw(command)
            dict = DictObject(json.loads(resolve))
        else:
            dict = self.sender.user_info(username)

        if 'peer_id' in dict:
            return dict.peer_id
        else:
            return False


    def get_id(self, user):
        if isinstance(user, int):
            return user

        if user.isdigit():
            id = int(user)
        else:
            id = int(self.user_id(user))

        return id


    def escape(self, string):
        if string is None:
            return None

        CHARS_UNESCAPED = ["\\", "\n", "\r", "\t", "\b", "\a", "'"]
        CHARS_ESCAPED = ["\\\\", "\\n", "\\r", "\\t", "\\b", "\\a", "\\'"]

        for i in range(0, 7):
            string = string.replace(CHARS_UNESCAPED[i], CHARS_ESCAPED[i])
        return string.join(["'", "'"])  # wrap with single quotes.


    def convert_links(self, string):
        for link in BeautifulSoup(string, 'lxml').findAll("a"):
            string = string.replace(str(link), link.get("href"))
        return string


    # THESE METHODS DO DIRECT ACTIONS #
    def get_file(self, file_id):
        pass


    def invite_conversation_member(self, conversation_id, user_id):
        self.sender.chat_add_user(self.peer(conversation_id), self.peer(user_id))


    def kick_conversation_member(self, conversation_id, user_id):
        self.sender.chat_del_user(self.peer(conversation_id), self.peer(user_id))


    def unban_conversation_member(self, conversation_id, user_id):
        pass


    def conversation_info(self, conversation_id):
        self.api_request('sendContact', params)
Exemplo n.º 2
0
class bindings(object):
    def __init__(self, bot):
        self.bot = bot
        self.receiver = Receiver(host="localhost",
                                 port=self.bot.config.bindings_token)
        self.sender = Sender(host="localhost",
                             port=self.bot.config.bindings_token)
        logging.getLogger("pytg").setLevel(logging.WARNING)

    def get_me(self):
        try:
            msg = self.sender.get_self()
            return User(msg.peer_id, msg.first_name, None, msg.username)
        except:
            return None

    def convert_message(self, msg):
        id = msg['id']
        if msg.receiver.type == 'user':
            conversation = Conversation(msg.sender.peer_id)
            conversation.title = msg.sender.first_name
        else:
            if msg.receiver.type == 'channel':
                conversation = Conversation(-int('100' +
                                                 str(msg.receiver.peer_id)))
            else:
                conversation = Conversation(-int(msg.receiver.peer_id))
            conversation.title = msg.receiver.title

        if msg.sender.type == 'user':
            sender = User(int(msg.sender.peer_id))
            if 'first_name' in msg.sender:
                sender.first_name = msg.sender.first_name
            if 'last_name' in msg.sender:
                sender.last_name = msg.sender.last_name
            if 'username' in msg.sender:
                sender.username = msg.sender.username
        else:
            if msg.sender.type == 'channel':
                sender = Conversation(-int('100' + str(msg.sender.peer_id)))
            else:
                sender = Conversation(-int(msg.sender.peer_id))
            sender.first_name = msg.sender.title

        date = msg.date

        # Gets the type of the message
        if 'text' in msg:
            type = 'text'
            content = msg.text
            extra = None
        elif 'media' in msg:
            type = msg.media.type
            content = msg.id
            if 'caption' in msg.media:
                extra = msg.media.caption
            else:
                extra = None
        elif msg.event == 'service':
            type = 'notification'
            if msg.action.type == 'chat_del_user':
                content = 'left_chat_member'
                extra = msg.action.user.peer_id
            elif msg.action.type == 'chat_add_user':
                content = 'new_chat_member'
                extra = msg.action.user.peer_id
            elif msg.action.type == 'chat_add_user_link':
                content = 'new_chat_member'
                extra = msg.sender.peer_id
            else:
                type = None
                content = None
                extra = None
        else:
            type = None
            content = None
            extra = None

        # Generates another message object for the original message if the reply.
        if 'reply_id' in msg:
            reply_msg = self.sender.message_get(msg.reply_id)
            reply = self.convert_message(reply_msg)

        else:
            reply = None

        return Message(id, conversation, sender, content, type, date, reply,
                       extra)

    def receiver_worker(self):
        try:
            logging.debug('Starting receiver worker...')
            while self.bot.started:
                self.receiver.start()
                self.receiver.message(self.main_loop())
        except KeyboardInterrupt:
            pass

    def send_message(self, message):
        if not message.extra:
            message.extra = {}

        if message.type != 'text' and message.content.startswith('http'):
            message.content = download(message.content)
        elif message.type != 'text' and not message.content.startswith('/'):
            message.content = self.sender.load_file(message.content)

        if not message.extra or not 'caption' in message.extra:
            message.extra['caption'] = None

        if message.type == 'text':
            self.sender.send_typing(self.peer(message.conversation.id), 1)

            if 'format' in message.extra and message.extra[
                    'format'] == 'Markdown':
                message.content = remove_markdown(message.content)
            elif 'format' in message.extra and message.extra[
                    'format'] == 'HTML':
                message.content = self.convert_links(message.content)

            try:
                if 'format' in message.extra and message.extra[
                        'format'] == 'HTML':
                    self.sender.raw('[html] msg %s %s' %
                                    (self.peer(message.conversation.id),
                                     self.escape(message.content)),
                                    enable_preview=False)
                else:
                    self.sender.send_msg(self.peer(message.conversation.id),
                                         message.content,
                                         enable_preview=False)
            except Exception as e:
                logging.exception(e)

        elif message.type == 'photo':
            self.sender.send_typing(self.peer(message.conversation.id), 1)  # 7
            try:
                if message.reply:
                    self.sender.reply_photo(message.reply, message.content,
                                            message.extra['caption'])
                else:
                    self.sender.send_photo(self.peer(message.conversation.id),
                                           message.content,
                                           message.extra['caption'])
            except Exception as e:
                logging.exception(e)

        elif message.type == 'audio':
            self.sender.send_typing(self.peer(message.conversation.id), 1)  # 6
            try:
                if message.reply:
                    self.sender.reply_audio(message.reply, message.content)
                else:
                    self.sender.send_audio(self.peer(message.conversation.id),
                                           message.content)
            except Exception as e:
                logging.exception(e)

        elif message.type == 'document':
            self.sender.send_typing(self.peer(message.conversation.id), 1)  # 8
            try:
                if message.reply:
                    self.sender.reply_document(message.reply, message.content,
                                               message.extra['caption'])
                else:
                    self.sender.send_document(
                        self.peer(message.conversation.id), message.content,
                        message.extra['caption'])
            except Exception as e:
                logging.exception(e)

        elif message.type == 'sticker':
            if message.reply:
                self.sender.reply_file(message.reply, message.content)
            else:
                self.sender.send_file(self.peer(message.conversation.id),
                                      message.content)

        elif message.type == 'video':
            self.sender.send_typing(self.peer(message.conversation.id), 1)  # 4
            try:
                if message.reply:
                    self.sender.reply_video(message.reply, message.content,
                                            message.extra['caption'])
                else:
                    self.sender.send_video(self.peer(message.conversation.id),
                                           message.content,
                                           message.extra['caption'])
            except Exception as e:
                logging.exception(e)

        elif message.type == 'voice':
            self.sender.send_typing(self.peer(message.conversation.id), 5)
            try:
                if message.reply:
                    self.sender.reply_audio(message.reply, message.content)
                else:
                    self.sender.send_audio(self.peer(message.conversation.id),
                                           message.content)
            except Exception as e:
                logging.exception(e)

        elif message.type == 'location':
            self.sender.send_typing(self.peer(message.conversation.id), 1)  # 9
            if message.reply:
                self.sender.reply_location(message.reply,
                                           message.content['latitude'],
                                           message.content['longitude'])
            else:
                self.sender.send_location(self.peer(message.conversation.id),
                                          message.content['latitude'],
                                          message.content['longitude'])

        else:
            print('UNKNOWN MESSAGE TYPE: ' + message.type)
            logging.debug("UNKNOWN MESSAGE TYPE")

    @coroutine
    def main_loop(self):
        while self.bot.started:
            msg = (yield)
            if (msg.event == 'message'
                    and msg.own == False) or msg.event == 'service':
                message = self.convert_message(msg)
                self.bot.inbox.put(message)

                try:
                    if message.conversation.id > 0:
                        self.sender.mark_read(self.peer(message.sender.id))
                    else:
                        self.sender.mark_read(
                            self.peer(message.conversation.id))
                except Exception as e:
                    logging.error(e)

    def peer(self, chat_id):
        if chat_id > 0:
            peer = 'user#id' + str(chat_id)
        else:
            if str(chat_id)[1:].startswith('100'):
                peer = 'channel#id' + str(chat_id)[4:]
            else:
                peer = 'chat#id' + str(chat_id)[1:]
        return peer

    def user_id(self, username):
        if username.startswith('@'):
            command = 'resolve_username ' + username[1:]
            resolve = self.sender.raw(command)
            dict = DictObject(json.loads(resolve))
        else:
            dict = self.sender.user_info(username)

        if 'peer_id' in dict:
            return dict.peer_id
        else:
            return False

    def get_id(self, user):
        if isinstance(user, int):
            return user

        if user.isdigit():
            id = int(user)
        else:
            id = int(self.user_id(user))

        return id

    def escape(self, string):
        if string is None:
            return None

        CHARS_UNESCAPED = ["\\", "\n", "\r", "\t", "\b", "\a", "'"]
        CHARS_ESCAPED = ["\\\\", "\\n", "\\r", "\\t", "\\b", "\\a", "\\'"]

        for i in range(0, 7):
            string = string.replace(CHARS_UNESCAPED[i], CHARS_ESCAPED[i])
        return string.join(["'", "'"])  # wrap with single quotes.

    def convert_links(self, string):
        for link in BeautifulSoup(string, 'lxml').findAll("a"):
            string = string.replace(str(link), link.get("href"))
        return string

    # THESE METHODS DO DIRECT ACTIONS #
    def get_file(self, file_id):
        pass

    def invite_conversation_member(self, conversation_id, user_id):
        self.sender.chat_add_user(self.peer(conversation_id),
                                  self.peer(user_id))

    def kick_conversation_member(self, conversation_id, user_id):
        self.sender.chat_del_user(self.peer(conversation_id),
                                  self.peer(user_id))

    def unban_conversation_member(self, conversation_id, user_id):
        pass

    def conversation_info(self, conversation_id):
        self.api_request('sendContact', params)
Exemplo n.º 3
0
class PyTelegram(object):
    def __init__(self):
        tgcli_port = 4458
        self.setlog()
        if not self.start(tgcli_port):
            sys.exit(1)

        self.receiver = Receiver(host="localhost", port=tgcli_port)
        self.sender = Sender(host="localhost", port=tgcli_port)

    def setlog(self):
        basepath = os.path.dirname(os.path.realpath(__file__))
        logdir = os.path.join(basepath, "./log")
        if not os.path.exists(logdir):
            os.mkdir(logdir)
        self.logname = os.path.join(basepath,
                                    "./log/%s.log" % time.strftime("%Y%m%d%H"))
        LOG_FORMAT = '[%(asctime)s] : %(levelname)s %(filename)s - %(funcName)s(%(lineno)d) - %(message)s'
        logging.basicConfig(
            format=LOG_FORMAT,
            level=0,
            handlers=[logging.FileHandler(self.logname, 'a', 'utf-8')])

    def need_proxy(self):
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.connect(('8.8.8.8', 1))
            selfip = s.getsockname()[0]
        except Exception as e:
            logging.error(e)
            return False

        if selfip.startswith("192.168.") or selfip.startswith("10.")\
                or selfip.startswith("172.1") or selfip.startswith("10.64."):
            logging.debug("need proxy")
            return True
        else:
            logging.debug("no need proxy")
            return False

    def start(self, tgcli_port):
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            check = s.connect_ex(('127.0.0.1', tgcli_port))
            s.close()
        except Exception as e:
            logging.error(e)
            check = 1

        if check == 0:
            return True

        if self.need_proxy():
            cmd = """nohup proxychains telegram-cli --json --tcp-port %d >> %s 2>&1 &"""\
                % (tgcli_port, self.logname)
        else:
            cmd = """nohup telegram-cli --json --tcp-port %d >> %s 2>&1 &"""\
                % (tgcli_port, self.logname)

        logging.debug(cmd)
        ret = subprocess.Popen(cmd,
                               shell=True,
                               stderr=subprocess.PIPE,
                               stdout=subprocess.PIPE)
        ret.wait()
        logging.debug("ret wait")
        reterr = ret.stderr.read()
        logging.debug("ret err")
        retout = ret.stdout.read()
        logging.debug("ret out")
        if reterr:
            logging.error(reterr.decode("utf8"))
            return False
        logging.info(retout)
        return True

    def parse_recive(self, msg_dict):
        logging.debug(msg_dict)

    def receive_loop(self):
        @coroutine
        def receive_coroutine_loop():
            while 1:
                msg = (yield)
                self.parse_recive(msg)

        self.receiver.start()
        self.receiver.message(receive_coroutine_loop())

    def get_channel_list(self, limit=0, offset=0):
        if limit == 0 and offset == 0:
            channels = self.sender.channel_list()
        else:
            channels = self.sender.channel_list(limit, offset)
        return channels

    def get_dialog_list(self, limit=0, offset=0):
        if limit == 0 and offset == 0:
            dialogs = self.sender.dialog_list()
        else:
            dialogs = self.sender.dialog_list(limit, offset)
        return dialogs

    def channel_get_members(self, name):
        members = self.sender.channel_get_members(name)
        return members

    def chat_get_members(self, name):
        chat_info_dict = self.sender.chat_info(name)
        meminfo_list = chat_info_dict["members"]
        return meminfo_list

    def get_history(self, peer, limit=0, offset=0):
        if limit == 0:
            ret = self.sender.history(peer,
                                      retry_connect=10,
                                      result_timeout=100)
        elif offset == 0:
            ret = self.sender.history(peer, limit, retry_connect=10)
        else:
            ret = self.sender.history(peer, limit, offset, retry_connect=10)
        #logging.debug(ret)
        ret.reverse()
        history_dict = collections.OrderedDict()
        for chat_info in ret:
            try:
                if chat_info["event"] != "message":
                    continue
                chatid = chat_info["id"]
                history_dict[chatid] = chat_info
                logging.debug(chat_info)
            except Exception as e:
                logging.error(e)
        return history_dict

    def create_group(self, groupname, userlist):
        try:
            ret = self.sender.create_group_chat(groupname, userlist[0])
            logging.debug(ret)
        except Exception as e:
            logging.error(e)
            return False

        if len(userlist) == 1:
            return True

        for username in userlist[1:]:
            try:
                ret = self.sender.chat_add_user(groupname, username, 0)
                logging.debug(ret)
            except Exception as e:
                logging.error(e)
        return True