Example #1
0
class ViberPub:
    def __init__(self, appConfig, dbName = 'vb_db.json') -> None:
        self.db = TinyDB(dbName)
        self.usersDb = TinyDB('vb_users.json')
        self.app = Flask(__name__)
        self.config = appConfig
        self.viber = Api(BotConfiguration(
            name = self.config.getProperty('Publishers.Viber.Name'),
            avatar = '',
            auth_token = self.config.getProperty('Publishers.Viber.Token')
        ))
        self.query = Query()
        print("Viber publisher created.")
    
    def __del__(self):
        self.db.close()
        self.usersDb.close()
            
    def FormatMessage(self, rawMessages):
        res = 'Automatsko obaveštenje o najavljenim prekidima snabdevanja električnom energijom u Banatskom Velikom Selu i okolini\n\n'

        for rawMessage in rawMessages:
            common_desc = rawMessage['common_desc']
            common_desc = ' '.join(common_desc.split('\\t'))
            common_desc = ' '.join(common_desc.split('\n'))
            common_desc = ' '.join(common_desc.split('\t'))
            common_desc = ' '.join(common_desc.split())
            common_desc = common_desc.replace('\xa0', ' ')
            res = res + common_desc + '\n'
            for rawMessageDesc in rawMessage['desc']:
                pretty = ' '.join(rawMessageDesc.split('\\n')).replace('\xa0', ' ')
                pretty = ' '.join(pretty.split('\\t'))
                pretty = ' '.join(pretty.split('\n'))
                pretty = ' '.join(pretty.split('\t'))
                pretty = ' '.join(pretty.split('\\'))
                pretty = ' '.join(pretty.split())
                pretty = re.sub(r'\b[0-9]\\\.', '', pretty)
                pretty = re.sub(r'[0-9]\\\.', '', pretty)
                res = res + ' ' + pretty + '\n'
            res = res + '\n'
        return res

    def Publish(self, message) -> None:
        if len(message.message) > 0:
            print('Posting to Viber...' + self.FormatMessage(message.message))
            UserQ = Query()
            for user in self.usersDb.search(UserQ.active == '1'):
                messageCopy = copy.copy(message)
                messageCopy.userId = user['id']
                if len(self.db.search((self.query.hash == messageCopy.hash) & (self.query.userId == user['id']))) == 0:
                    try:
                        self.viber.send_messages(user['id'], [ TextMessage(text=self.FormatMessage(messageCopy.message)) ])
                        messageCopy.message = ''
                        self.db.insert(messageCopy.ToDict())
                        print('Message sent to Viber user: '******'name'])
                    except Exception as e:
                        print('Posting to Viber user {0} -> {1}'.format(user['name'], e))
                else:
                    print('User ' + user['name'] + ' already notified through Viber')
Example #2
0
def AdminStart(message):
    if not re.search("\/start (\d+)", message.text):
        markup = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True)
        buttons = [types.KeyboardButton('🎓 Персонал')]
        buttons.append(types.KeyboardButton('🔥 Сессии'))
        buttons.append(types.KeyboardButton('⚙️ Сменить имя'))
        markup.add(*buttons)
        bot.send_message(message.chat.id,
                         'Панель управления',
                         reply_markup=markup)
        return
    system_id = int(re.search("(\d+)", message.text).group(1))
    user = db_users.find_one({"_id": message.from_user.id})
    tolker = db_users.find_one({"system id": system_id})
    if tolker['operator']['active session'] is not None:
        bot.send_message(message.chat.id,
                         'Пользователь сейчас занят другим оператором')
        return
    tolker['operator']['active session'] = user['system id']
    if user['operator']["sessions"] is None:
        user['operator']["sessions"] = []
    if user['operator']['active session'] is None:
        user['operator']['active session'] = system_id
        if system_id in user['operator']["sessions"]:
            user['operator']["sessions"].remove(system_id)
        db_users.replace_one({"_id": message.from_user.id}, user, True)
        db_users.replace_one({"system id": system_id}, tolker, True)
        bot.send_message(message.chat.id, f'Диалог с {tolker["name"]} активен')
        if tolker["messenger"] == "viber":
            viber = Api(
                BotConfiguration(name=user['operator']['name'],
                                 avatar=cfg.v_avatar,
                                 auth_token=cfg.v_token))
            viber.send_messages(tolker["_id"],
                                [TextMessage(text='Оператор подключился')])
        elif tolker["messenger"] == "telegram":
            bot.send_message(
                tolker["_id"],
                f"{user['operator']['name']} Оператор подключился")
        return
    if system_id in user['operator']["sessions"]:
        user['operator']["sessions"].remove(system_id)
    if user['operator']['active session'] is not None:
        user['operator']["sessions"].append(user['operator']['active session'])
    user['operator']['active session'] = system_id
    db_users.replace_one({"_id": message.from_user.id}, user, True)
    db_users.replace_one({"system id": system_id}, tolker, True)
    bot.send_message(message.chat.id, f'Диалог с {tolker["name"]} активен')
    if tolker["messenger"] == "viber":
        viber = Api(
            BotConfiguration(name=user['operator']['name'],
                             avatar=cfg.v_avatar,
                             auth_token=cfg.v_token))
        viber.send_messages(tolker["_id"],
                            [TextMessage(text='Оператор подключился')])
    elif tolker["messenger"] == "telegram":
        bot.send_message(tolker["_id"],
                         f"{user['operator']['name']} Оператор подключился")
Example #3
0
def SessionClose(message):
    system_id = int(re.search("(\d+)", message.text).group(1))
    user = db_users.find_one({"_id": message.from_user.id})
    if not db_users.find_one({"system id": system_id}):
        bot.send_message(message.chat.id, 'Такого пользователя нет')
        return
    tolker = db_users.find_one({"system id": system_id})
    if user['operator']['active session'] == system_id:
        user['operator']['active session'] = None
        tolker['operator']['active session'] = None
        db_users.replace_one({"_id": message.from_user.id}, user, True)
        db_users.replace_one({"_id": tolker["_id"]}, tolker, True)
        bot.send_message(message.chat.id,
                         f'Активная сессия с {tolker["name"]} закрыта')
        if tolker["messenger"] == "viber":
            viber = Api(
                BotConfiguration(name=user['operator']['name'],
                                 avatar=cfg.v_avatar,
                                 auth_token=cfg.v_token))
            viber.send_messages(tolker["_id"],
                                [TextMessage(text='Оператор отключился')])
        elif tolker["messenger"] == "telegram":
            bot.send_message(tolker["_id"],
                             f"{user['operator']['name']}\nОтключился")
        return
    if system_id in user['operator']["sessions"]:
        user['operator']['sessions'].remove(system_id)
        tolker['operator']['active session'] = None
        if len(user['operator']["sessions"]) == 0:
            user['operator']["sessions"] = None
        db_users.replace_one({"_id": message.from_user.id}, user, True)
        db_users.replace_one({"_id": tolker["_id"]}, tolker, True)
        bot.send_message(message.chat.id, f'Сессия с {tolker["name"]} закрыта')
        if tolker["messenger"] == "viber":
            viber = Api(
                BotConfiguration(name=user['operator']['name'],
                                 avatar=cfg.v_avatar,
                                 auth_token=cfg.v_token))
            viber.send_messages(tolker["_id"],
                                [TextMessage(text='Оператор отключился')])
        elif tolker["messenger"] == "telegram":
            bot.send_message(tolker["_id"],
                             f"{user['operator']['name']}\nОтключился")
        return
Example #4
0
class Viber(BaseMessenger):
    """
    IM connector for Viber Bot API
    """

    # region Interface

    def __init__(self, token: str, **kwargs):
        super().__init__(token, **kwargs)

        self.bot = Api(
            BotConfiguration(
                auth_token=token,
                name=kwargs.get('name'),
                avatar=kwargs.get('avatar'),
            ))

    def enable_webhook(self, url: str, **kwargs):
        return self.bot.set_webhook(url=url)

    def disable_webhook(self):
        return self.bot.unset_webhook()

    def get_account_info(self) -> Dict[str, Any]:
        # data = {
        #    "status":0,
        #    "status_message":"ok",
        #    "id":"pa:75346594275468546724",
        #    "name":"account name",
        #    "uri":"accountUri",
        #    "icon":"http://example.com",
        #    "background":"http://example.com",
        #    "category":"category",
        #    "subcategory":"sub category",
        #    "location":{
        #       "lon":0.1,
        #       "lat":0.2
        #    },
        #    "country":"UK",
        #    "webhook":"https://my.site.com",
        #    "event_types":[
        #       "delivered",
        #       "seen"
        #    ],
        #    "subscribers_count":35,
        #    "members":[
        #       {
        #          "id":"01234567890A=",
        #          "name":"my name",
        #          "avatar":"http://example.com",
        #          "role":"admin"
        #       }
        #    ]
        # }
        try:
            data = self.bot.get_account_info()
        except Exception as err:
            raise MessengerException(err)

        return {
            'id': data.get('id'),
            'username': data.get('name'),
            'uri': data.get('uri'),  # check this
            'info': data
        }

    def get_user_info(self, user_id: str, **kwargs) -> Dict[str, Any]:
        # data = {
        #   "id":"01234567890A=",
        #   "name":"John McClane",
        #   "avatar":"http://avatar.example.com",
        #   "country":"UK",
        #   "language":"en",
        #   "primary_device_os":"android 7.1",
        #   "api_version":1,
        #   "viber_version":"6.5.0",
        #   "mcc":1,
        #   "mnc":1,
        #   "device_type":"iPhone9,4"
        # }
        try:
            data = self.bot.get_user_details(user_id)
        except Exception as err:
            if 'failed with status: 12' in str(err):
                raise RequestsLimitExceeded(err)
            raise MessengerException(err)

        return {
            'id': data.get('id'),
            'username': data.get('name'),
            'avatar': data.get('avatar'),
            'info': data,
        }

    def parse_message(self, request: HttpRequest) -> Message:
        # Verify signature
        sign = request.META.get('HTTP_X_VIBER_CONTENT_SIGNATURE')
        data = json.loads(request.body)
        if not self.bot.verify_signature(request.body, sign):
            raise MessengerException(f'Viber message not verified; '
                                     f'Data={data}; Sign={sign};')

        return self._from_viber_message(self.bot.create_request(data))

    def send_message(self, receiver: str,
                     messages: Union[Message, List[Message]]) -> List[str]:
        if isinstance(messages, MessageList):
            messages = messages.as_list()
        elif isinstance(messages, Message):
            messages = [messages]

        vb_messages = []
        for message in messages:
            vb_messages.append(self._to_viber_message(message))

        try:
            return self.bot.send_messages(receiver, vb_messages)
        except Exception as err:
            if 'failed with status: 6, message: notSubscribed' in str(err):
                raise NotSubscribed(err)
            raise MessengerException(err)

    def welcome_message(self, text: str) -> Union[str, Dict[str, Any], None]:
        return {
            "sender": {
                "name": self.name,
                "avatar": self.avatar_url
            },
            "type": "text",
            "text": text
        }

    # endregion

    # region Help methods

    @staticmethod
    def _from_viber_message(vb_request: ViberRequest) -> Message:
        if isinstance(vb_request, vbr.ViberMessageRequest):
            assert isinstance(vb_request.message, TypedMessage)

            vb_message = vb_request.message
            if isinstance(vb_message, vbm.TextMessage):
                if 'btn-' in vb_message.text:
                    return Button(id=vb_request.message_token,
                                  user_id=vb_request.sender.id,
                                  timestamp=vb_request.timestamp,
                                  command=vb_message.text)
                return Text(id=vb_request.message_token,
                            user_id=vb_request.sender.id,
                            timestamp=vb_request.timestamp,
                            text=vb_message.text)
            elif isinstance(vb_message, vbm.PictureMessage):
                return Picture(id=vb_request.message_token,
                               user_id=vb_request.sender.id,
                               timestamp=vb_request.timestamp,
                               file_url=vb_message.media)
            elif isinstance(vb_message, vbm.VideoMessage):
                return Video(id=vb_request.message_token,
                             user_id=vb_request.sender.id,
                             timestamp=vb_request.timestamp,
                             file_url=vb_message.media,
                             file_size=vb_message.size)
            elif isinstance(vb_message, vbm.FileMessage):
                return File(id=vb_request.message_token,
                            user_id=vb_request.sender.id,
                            timestamp=vb_request.timestamp,
                            file_url=vb_message.media,
                            file_size=vb_message.size)
            elif isinstance(vb_message, vbm.RichMediaMessage):
                return RichMedia(id=vb_request.message_token,
                                 user_id=vb_request.sender.id,
                                 timestamp=vb_request.timestamp,
                                 text=vb_message.alt_text,
                                 rich_media=vb_message.rich_media)
            elif isinstance(vb_message, vbm.ContactMessage):
                return Contact(id=vb_request.message_token,
                               user_id=vb_request.sender.id,
                               timestamp=vb_request.timestamp,
                               contact=vb_message.contact)
            elif isinstance(vb_message, vbm.LocationMessage):
                return Location(id=vb_request.message_token,
                                user_id=vb_request.sender.id,
                                timestamp=vb_request.timestamp,
                                location=vb_message.location)
            elif isinstance(vb_message, vbm.URLMessage):
                return Url(id=vb_request.message_token,
                           user_id=vb_request.sender.id,
                           timestamp=vb_request.timestamp,
                           url=vb_message.media)
            elif isinstance(vb_message, vbm.StickerMessage):
                return Sticker(id=vb_request.message_token,
                               user_id=vb_request.sender.id,
                               timestamp=vb_request.timestamp,
                               file_id=vb_message.sticker_id)
            return Text(id=vb_request.message_token,
                        user_id=vb_request.sender.id,
                        timestamp=vb_request.timestamp,
                        text=str(vb_message))
        elif isinstance(vb_request, vbr.ViberConversationStartedRequest):
            return Event(id=vb_request.message_token,
                         user_id=vb_request.user_id,
                         timestamp=vb_request.timestamp,
                         event_type=EType.START,
                         user_name=vb_request.user.name,
                         context=vb_request.context)
        elif isinstance(vb_request, vbr.ViberSubscribedRequest):
            return Event(id=vb_request.message_token,
                         user_id=vb_request.user_id,
                         timestamp=vb_request.timestamp,
                         event_type=EType.SUBSCRIBED,
                         user_name=vb_request.user.name)
        elif isinstance(vb_request, vbr.ViberUnsubscribedRequest):
            return Event(id=vb_request.message_token,
                         user_id=vb_request.user_id,
                         timestamp=vb_request.timestamp,
                         event_type=EType.UNSUBSCRIBED)
        elif isinstance(vb_request, vbr.ViberDeliveredRequest):
            return Event(id=vb_request.message_token,
                         user_id=vb_request.user_id,
                         timestamp=vb_request.timestamp,
                         event_type=EType.DELIVERED)
        elif isinstance(vb_request, vbr.ViberSeenRequest):
            return Event(id=vb_request.message_token,
                         user_id=vb_request.user_id,
                         timestamp=vb_request.timestamp,
                         event_type=EType.SEEN)
        elif isinstance(vb_request, vbr.ViberFailedRequest):
            log.warning(f'Client failed receiving message; Error={vb_request}')
            return Event(id=vb_request.message_token,
                         user_id=vb_request.user_id,
                         timestamp=vb_request.timestamp,
                         event_type=EType.START,
                         context=vb_request.desc)
        elif vb_request.event_type == 'webhook':
            return Event(timestamp=vb_request.timestamp)

        log.warning(f'ViberRequest type={type(vb_request)}; '
                    f'Object={vb_request};')
        return Text(timestamp=vb_request.timestamp, text=str(vb_request))

    def _to_viber_message(self, message: Message) -> VbMessage:
        kb = self._get_keyboard(message.buttons)

        if isinstance(message, Text):
            return vbm.TextMessage(text=message.text, keyboard=kb)
        if isinstance(message, Sticker):
            return vbm.StickerMessage(sticker_id=message.file_id, keyboard=kb)
        elif isinstance(message, Picture):
            return vbm.PictureMessage(media=message.file_url,
                                      text=message.text,
                                      keyboard=kb)
        elif isinstance(message, Video):
            return vbm.VideoMessage(media=message.file_url,
                                    size=message.file_size,
                                    text=message.text,
                                    keyboard=kb)
        elif isinstance(message, (File, Audio)):
            return vbm.FileMessage(media=message.file_url,
                                   size=message.file_size or 0,
                                   file_name=message.file_name or '',
                                   keyboard=kb)
        elif isinstance(message, Contact):
            contact = message.contact
            return vbm.ContactMessage(contact=contact, keyboard=kb)
        elif isinstance(message, Url):
            return vbm.URLMessage(media=message.url, keyboard=kb)
        elif isinstance(message, Location):
            location = message.location
            return vbm.LocationMessage(location=location, keyboard=kb)
        elif isinstance(message, RichMedia):
            rich_media = message.rich_media
            return vbm.RichMediaMessage(rich_media=rich_media,
                                        alt_text=message.text,
                                        keyboard=kb)

    @staticmethod
    def _get_keyboard(buttons: List[Button]) -> Optional[Dict[str, Any]]:
        # TODO do refactoring
        if not buttons:
            return None

        vb_buttons = []
        for button in buttons:
            # assert isinstance(button, Button), f'{button=} {type(button)}'
            vb_btn = {
                'Columns':
                2,  # TODO: how is it storage in Model?
                'Rows':
                1,
                'BgColor':
                '#aaaaaa',
                'ActionType':
                'reply',
                'ActionBody':
                button.command,
                'Text':
                '<font color="{clr}"><b>{text}'
                '</b></font>'.format(text=button.text, clr='#131313'),
                'TextVAlign':
                'middle',
                'TextHAlign':
                'center',
                'TextOpacity':
                60,
                'TextSize':
                'large',
                'TextPaddings': [12, 8, 8, 20],  # [up, left, right, bottom]
            }

            if hasattr(button, 'image'):
                domain = Site.objects.get_current().domain
                vb_btn.update({
                    'BgMedia': f'https://{domain}{button.image}',
                    'BgMediaScaleType': 'fill'
                })

            vb_buttons.append(vb_btn)

        return {
            'Type': 'keyboard',
            'BgColor': '#ffffff',
            'min_api_version': 6,
            'Buttons': vb_buttons,
        }
Example #5
0
class ViberChatBot(ChatBot):
    def __init__(self):
        name = 'Guide'
        avatar = 'https://st2.depositphotos.com/'\
            '3146979/9765/v/950/depositphotos_97658722'\
            '-stock-illustration-vector-round-icon-pile-of.jpg'
        auth_token = os.environ['VIBER_AUTH_TOKEN']
        viber_bot_config = BotConfiguration(name=name,
                                            avatar=avatar,
                                            auth_token=auth_token)
        self.viber_bot = Api(viber_bot_config)

    def get_message(self, request):
        signature = request.headers.get('X-Viber-Content-Signature')
        if not self.viber_bot.verify_signature(request.get_data(), signature):
            raise 'Invalid Signature!', signature

        viber_request = self.viber_bot.parse_request(request.get_data())

        if isinstance(viber_request, ViberMessageRequest):
            user_id = viber_request.sender.id
            text = viber_request.message.text
            return {'user_id': user_id, 'text': text}
        elif isinstance(viber_request, ViberSubscribedRequest):
            pass
        elif isinstance(viber_request, ViberSeenRequest):
            pass
        elif isinstance(viber_request, ViberDeliveredRequest):
            pass
        elif isinstance(viber_request, ViberFailedRequest):
            raise 'client failed receiving message. failure: {0}'.format(
                viber_request)
        else:
            pass

    def send_message(self, user_id, answer):
        viber_answer = []
        if 'text' in answer:
            text_message = TextMessage(text=answer['text'])
            viber_answer.append(text_message)
        if 'image' in answer:
            url_prefix = 'https://drive.google.com/uc?export=download&id='
            image_url = url_prefix + answer['image']
            picture_message = PictureMessage(media=image_url)
            viber_answer.append(picture_message)
        if 'options' in answer:
            keyboard = self.create_keyboard(answer['options'])
            keyboard_message = KeyboardMessage(tracking_data=None,
                                               keyboard=keyboard)
            viber_answer.append(keyboard_message)

        self.viber_bot.send_messages(user_id, viber_answer)

    def create_keyboard(self, connections):
        keyboard = {}
        keyboard['Type'] = 'keyboard'
        keyboard['Buttons'] = map(self.create_button, connections)
        return keyboard

    def create_button(self, connection):
        button = {}
        button['Columns'] = 6
        button['Rows'] = 1
        button['Text'] = '<font color="#000000"><b>' + \
            connection + '</b></font>'
        button['TextSize'] = 'large'
        button['TextHAlign'] = 'center'
        button['TextVAlign'] = 'middle'
        button['ActionType'] = 'reply'
        button['ActionBody'] = connection
        button['BgColor'] = '#b9e6f5'
        return button
Example #6
0
class ViberFlaskWrapper(Flask):

    # Stores session states
    sessionStorage = {}

    # Viber object for API interaction
    viber = None

    # Yandex Disk object for API interaction
    disk = None

    # List of users allowed to use bot
    allowedUsers = None

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.add_url_rule('/message', view_func=self.message, methods=['POST'])

        bot_configuration = BotConfiguration(
            name=os.environ['VIBERBOT_NAME'],
            avatar=os.environ['VIBERBOT_AVATAR'],
            auth_token=os.environ['VIBERBOT_TOKEN'])

        self.viber = Api(bot_configuration)
        self.allowedUsers = os.environ['VIBERBOT_ALLOWED_USERS']

        self.disk = YadiskWrapper(os.environ['YADISK_TOKEN'])

    def message(self):
        """Retrieves request body and generates response"""
        logging.debug("Processing new request")
        # verify message signature
        if not self.viber.verify_signature(
                request.get_data(),
                request.headers.get('X-Viber-Content-Signature')):
            logging.debug("User invalid signature: %s",
                          request.headers.get('X-Viber-Content-Signature'))
            return Response(status=403)

        # this library supplies a simple way to receive a request object
        viber_request = self.viber.parse_request(request.get_data())

        # process only message requests
        if not isinstance(viber_request, ViberMessageRequest):
            logging.debug("Message is not ViberMessageRequest")
            return Response(status=200)

        # check if user allowed to iteract with bot
        if not viber_request.sender.id in self.allowedUsers:
            logging.debug("Unknown user: %s", viber_request.sender.id)
            message = TextMessage(text="403")
            self.viber.send_messages(viber_request.sender.id, [message])
            return Response(status=200)

        # fix for duplicate message processing
        if viber_request.message_token not in self.sessionStorage:
            self.sessionStorage[viber_request.message_token] = 'processing'
        else:
            return Response(status=200)

        # Process Text message
        if isinstance(viber_request.message, TextMessage):
            logging.debug("Processing TextMessage")
            request_text = viber_request.message.text
            response_text = 'Saving...'
            message = TextMessage(text=response_text)
            self.viber.send_messages(viber_request.sender.id, [message])
            # Create saving thread
            logging.debug("Starting Saving Thread")
            self.thread_save_to_disk(viber_request.sender.id, request_text,
                                     None)
#			save_thread = threading.Thread(
#				target=self.thread_save_to_disk,
#				args=(
#					viber_request.sender.id,
#					request_text,
#					None))
#			save_thread.start()

# Process Picture, Video and File messages
        elif isinstance(viber_request.message, PictureMessage)	\
         or isinstance(viber_request.message, VideoMessage)		\
         or isinstance(viber_request.message, FileMessage):
            logging.debug("Processing FileMessage")
            url = viber_request.message.media  # URL of sent file
            response_text = 'Saving...'
            message = TextMessage(text=response_text)
            self.viber.send_messages(viber_request.sender.id, [message])
            # Create saving thread
            logging.debug("Starting Saving Thread")
            self.thread_save_to_disk(viber_request.sender.id, None, url)
#			save_thread = threading.Thread(
#				target=self.thread_save_to_disk,
#				args=(
#					viber_request.sender.id,
#					None,
#					url))
#			save_thread.start()

# Process Location message
        elif isinstance(viber_request.message, LocationMessage):
            logging.debug("Processing LocationMessage")
            request_text = str(viber_request.message.location)
            response_text = 'Saving...'
            message = TextMessage(text=response_text)
            self.viber.send_messages(viber_request.sender.id, [message])
            # Create saving thread
            logging.debug("Starting Saving Thread")
            self.thread_save_to_disk(viber_request.sender.id, request_text,
                                     None)


#			save_thread = threading.Thread(
#				target=self.thread_save_to_disk,
#				args=(
#					viber_request.sender.id,
#					request_text,
#					None))
#			save_thread.start()

# Process other messages
        else:
            logging.debug("Received unsupported message")
            response_text = 'Not supported yet'
            message = TextMessage(text=response_text)
            self.viber.send_messages(viber_request.sender.id, [message])

        # fix for duplicate message processing
        if viber_request.message_token in self.sessionStorage:
            del self.sessionStorage[viber_request.message_token]

        return Response(status=200)

    def thread_save_to_disk(self, user_id, note, file_url):
        """Saves data to Yandex Disk and sends report to user_id"""
        logging.debug("Saving Thread started")
        response_text = 'Saved'
        # if text note provided
        if note:
            logging.debug("Saving note")
            if not self.disk.save_note(note):
                response_text = 'Cannot save note.'
        # if file provided
        if file_url:
            logging.debug("Saving file")
            # extract filename from URL
            url_parsed = urlparse(file_url)
            filename = os.path.basename(url_parsed.path)
            # download file to temp directory
            with urllib.request.urlopen(file_url) as response:
                logging.debug("Downloading file from Viber server")
                data = response.read()
                logging.debug("Uploading file to Disk")
                # upload file to Disk
                if not self.disk.save_file(filename, data):
                    response_text = 'Cannot save file.'

        message = TextMessage(text=response_text)
        self.viber.send_messages(user_id, [message])
        return
Example #7
0
class ViberWebhook:
    def __init__(self, appConfig, dbUsers = 'vb_users.json') -> None:
        http_tunnel = ngrok.connect()
        self.public_url = http_tunnel.public_url.replace('http', 'https')
        print('Public URL acquired: ' + self.public_url)
        self.usersDb = TinyDB(dbUsers)
        self.app = Flask(__name__)
        self.config = appConfig
        self.viber = Api(BotConfiguration(
            name = self.config.getProperty('Publishers.Viber.Name'),
            avatar = self.config.getProperty('Publishers.Viber.Avatar'),
            auth_token = self.config.getProperty('Publishers.Viber.Token')
        ))
        self.query = Query()
        
        ## Delayed webhook setup
        scheduler = sched.scheduler(time.time, time.sleep)
        scheduler.enter(5, 1, self.set_webhook, (self.viber,))
        t = threading.Thread(target=scheduler.run)
        t.start()

        self.app.add_url_rule('/', 'incoming', self.incoming, methods=['POST'])
        self.app.add_url_rule('/ctrl', '', self.control, methods=['POST', 'GET'])
        self.t_webApp = threading.Thread(target=self.flaskThread)
        self.t_webApp.setDaemon(True)
        
        print("Viber worker created.")
    
    def __del__(self):
        self.usersDb.close()
        
    def flaskThread(self):
        self.app.run(host='0.0.0.0', port=80, debug=False)

    def Run(self):
        self.t_webApp.run()

    def GetAdmins(self):
        admins = self.usersDb.search(self.query.admin == '1')
        return admins

    def NotifyAdmins(self, admins, message):
        for admin in admins:
            self.viber.send_messages(admin['id'], [ TextMessage(text = message) ])   

    def IsAdmin(self, user_id, admins):
        return next((admin for admin in admins if admin['id'] == user_id), None) != None

    def Reboot():
        command = "/usr/bin/sudo /sbin/shutdown -r now"
        import subprocess
        process = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
        output = process.communicate()[0]
        print(output)

    def RestartViber():
        command = "service Viber restart"
        import subprocess
        process = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
        output = process.communicate()[0]
        print(output)

    def incoming(self):

        admins = self.GetAdmins()
        print(request.path)
        viber_request = self.viber.parse_request(request.get_data().decode('utf8'))

        if isinstance(viber_request, ViberMessageRequest):
            message = viber_request.message
            if isinstance(message, TextMessage):

                is_admin = self.IsAdmin(viber_request.sender.id, admins)
                if is_admin:
                    print("IsAdmin: True")
                
                ## HANDLE ADMIN REQUESTS
                usersListStr = ''
                if(message.text.strip() == "/ListUsers" and is_admin):
                    for user in self.usersDb.all():
                        usersListStr += user['name'] + '\n'
                    self.NotifyAdmins(admins, 'Korisnici: \n' + usersListStr)
                    return Response(status=200)                
                if(message.text.strip() == "/ListAdmins" and is_admin):
                    for user in self.usersDb.search(self.query.admin == '1'):
                        usersListStr += user['name'] + '\n'
                    self.NotifyAdmins(admins, 'Administratori: \n' + usersListStr)
                    return Response(status=200)
                if(message.text.strip() == "/GetPublicURL" and is_admin):
                    self.NotifyAdmins(admins, 'Javna adresa: \n' + self.public_url)
                    return Response(status=200)
                if(message.text.strip() == "/GetLocalIP" and is_admin):
                    self.NotifyAdmins(admins, 'Lokalna adresa: \n' + socket.gethostbyname(socket.gethostname()))
                    return Response(status=200)
                if(message.text.strip() == "/XRebootMe" and is_admin):
                    self.NotifyAdmins(admins, 'Rebooting...')
                    self.Reboot()
                    return Response(status=200)
                if(message.text.strip() == "/XRestartViberService" and is_admin):
                    self.NotifyAdmins(admins, 'Restarting Viber service...')
                    self.RestartViber()
                    return Response(status=200)

                UserQ = Query()

                # Handle standard requests
                if message.text.strip().lower() == 'stop':
                    self.usersDb.update({'active': '0'}, UserQ.id == viber_request.sender.id)
                else:
                    if len(self.usersDb.search(UserQ.id == viber_request.sender.id)) == 0:
                        self.usersDb.insert({'id': viber_request.sender.id, 'name': viber_request.sender.name, 'active': '1', 'admin': '0'})
                    else:
                        self.usersDb.update({'active': '1'}, UserQ.id == viber_request.sender.id)
                    self.viber.send_messages(viber_request.sender.id, [ TextMessage(text = 'Uspešna prijava! Pošalji STOP za odjavu.') ])
                    #self.viber.send_messages("/qNmzm5H8vXHIuuJAmJZvw==", [ TextMessage(text = 'Novi korisnik: ' + viber_request.sender.name) ])
                    self.NotifyAdmins(admins, 'Novi korisnik: ' + viber_request.sender.name)
        elif isinstance(viber_request, ViberConversationStartedRequest):
            UserQ = Query()
            #self.viber.send_messages(viber_request.user.id, [ TextMessage(text='Za prijavu pošaljite bilo kakvu poruku.') ])
            if len(self.usersDb.search(UserQ.id == viber_request.user.id)) == 0:
                self.usersDb.insert({'id': viber_request.user.id, 'name': viber_request.user.name, 'active': '1', 'admin': '0'})
            else:
                self.usersDb.update({'active': '0'}, UserQ.id == viber_request.user.id)
        elif isinstance(viber_request, ViberSubscribedRequest):
            UserQ = Query()
            self.viber.send_messages(viber_request.user.id, [ TextMessage(text='Za prijavu pošaljite bilo kakvu poruku.') ])
            if len(self.usersDb.search(UserQ.id == viber_request.user.id)) == 0:
                self.usersDb.insert({'id': viber_request.user.id, 'name': viber_request.user.name, 'active': '1', 'admin': '0'})
            else:
                self.usersDb.update({'active': '1'}, UserQ.id == viber_request.user.id)
        elif isinstance(viber_request, ViberUnsubscribedRequest):
            UserQ = Query()
            self.usersDb.update({'active': '0'}, UserQ.id == viber_request.user_id)
        elif isinstance(viber_request, ViberFailedRequest):
            logger.warn("client failed receiving message. failure: {0}".format(viber_request))

        return Response(status=200)


    def control(self):
        admins = self.GetAdmins()
        #data = request.get_data().decode('utf8')
        if(request.args.get('command') == 'users'):
            if(request.args.get('a') == '0'):
                usersListStr = ""
                for user in self.usersDb.all():
                    usersListStr += user['name'] + ';'
                return Response(status=200, response=usersListStr)
            else:
                usersListStr = ""
                for user in self.usersDb.search(self.query.admin == '1'):
                    usersListStr += user['name'] + ';'
                return Response(status=200, response=usersListStr)

    def set_webhook(self, viber):
        self.viber.set_webhook(self.public_url)  
Example #8
0
import os
import logging

#获取当前目录
current_dir = os.path.abspath(os.path.dirname(__file__))

# 日志
logging.basicConfig(level=logging.INFO,
                    filename="%s/logs/viber_bot.log" % current_dir,
                    format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

bot_configuration = BotConfiguration(
    name='saMonitorBot',
    avatar='http://viber.com/avatar.jpg',
    auth_token='4a73d9dc1127d3a1-bdfac7760afa25ea-6cfb6ca1663b11eb')
viber = Api(bot_configuration)

logger.info(viber.get_account_info())

viber.send_messages('1111', ["Hello World!"])

# viber.set_webhook('https://www.baidu.com')

# 导入viber 信息模块
from viberbot.api.messages import (TextMessage, ContactMessage, PictureMessage,
                                   VideoMessage)
from viberbot.api.messages.data_types.contact import Contact

text_message = TextMessage(text="Hello, World!")
def Message(t_bot, v_bot, message, user):
    settings = db_settings.find_one()
    if user['messenger'] == "viber": # Пользователь написал из вайбера
        if user['operator']['active session'] is None: # Сообщение поступает в чат операторов
            link = f"https://t.me/{t_bot.get_me().username}?start={user['system id']}"
            keyboard = types.InlineKeyboardMarkup()
            keyboard.add(types.InlineKeyboardButton(text="Ответить пользователю", url=link))
            #logging.info(message)
            if isinstance(message.message, PictureMessage):
                t_bot.send_photo(settings["main_id"], message.message.media, caption=f"{user['name']}, ({user['messenger']}) прислал изображение", reply_markup=keyboard)
                return True
            out = f"{user['name']}, ({user['messenger']}) прислал сообщение:\n{message.message.text}"
            t_bot.send_message(settings["main_id"], out, reply_markup=keyboard)
            return True
        else: # Диалог
            tolker = db_users.find_one({"system id": user['operator']['active session']})
            if isinstance(message.message, PictureMessage):
                t_bot.send_photo(tolker['_id'], message.message.media, caption=f"{user['name']}, ({user['messenger']}) прислал изображение")
                return True
            out = f"{user['name']}, ({user['messenger']}) прислал сообщение:\n{message.message.text}"
            t_bot.send_message(tolker["_id"], out)
            return True
    elif user['messenger'] == "telegram": # Пользователь написал из телеги
        if user['operator']['active session'] is None: # Сообщение поступает в чат операторов
            link = f"https://t.me/{t_bot.get_me().username}?start={user['system id']}"
            keyboard = types.InlineKeyboardMarkup()
            keyboard.add(types.InlineKeyboardButton(text="Ответить пользователю", url=link))
            if message.content_type == 'photo':
                t_bot.send_photo(settings["main_id"], message.photo[-1].file_id, caption=f"{user['name']}, ({user['messenger']}) прислал изображение", reply_markup=keyboard)
                return True
            out = f"{user['name']} ({user['messenger']}) прислал сообщение:\n{message.text}"
            t_bot.send_message(settings["main_id"], out, reply_markup=keyboard)
            return True
        else: # Диалог
            tolker = db_users.find_one({"system id": user['operator']['active session']})
            if message.content_type == 'photo':
                if tolker["messenger"] == "telegram":
                    if user["admin"] >= 1:
                        t_bot.send_photo(tolker["_id"], message.photo[-1].file_id, caption=user['name'])
                    else:
                        t_bot.send_photo(tolker["_id"], message.photo[-1].file_id, caption=f"{user['name']}, ({user['messenger']}) прислал изображение")
                    return True
                elif tolker["messenger"] == "viber":
                    photo_id = t_bot.get_file(message.photo[-1].file_id)
                    photo_name = photo_id.file_id
                    file = f'https://api.telegram.org/file/bot{cfg.token}/{photo_id.file_path}'
                    h = httplib2.Http('.cache')
                    response, content = h.request(file)
                    out = open(f'./pic/{photo_name}.jpg', 'wb')
                    out.write(content)
                    out.close()
                    viber = Api(BotConfiguration(name=user['operator']['name'], avatar=cfg.v_avatar, auth_token=cfg.v_token))
                    viber.send_messages(tolker['_id'], [
                        PictureMessage(media=f"https://bot.vizit-net.com/new/pics/{photo_name}.jpg")])
                    out = f'''Изображение отправлено {tolker['name']} ({tolker['messenger']})'''
                    t_bot.send_message(message.chat.id, out)
                    return True
            if tolker["messenger"] == "telegram":
                answer = f"{user['name']}, ({user['messenger']}) прислал сообщение:\n{message.text}"
                if user["admin"] >= 1:
                    answer = f"{user['operator']['name']}\n{message.text}"
                t_bot.send_message(tolker['_id'], answer)
                return True
            elif tolker["messenger"] == "viber":
                try:
                    viber = Api(BotConfiguration(name=user['operator']['name'], avatar=cfg.v_avatar, auth_token=cfg.v_token))
                    viber.send_messages(tolker["_id"], [TextMessage(text=message.text)])
                except Exception as error:
                    logging.exception(f"Error: {error}")
                return True
    return False
Example #10
0
class Viber(BaseMessenger):
    """
    IM connector for Viber REST API
    """
    def __init__(self, token: str, **kwargs):
        super().__init__(token, **kwargs)

        self.bot = Api(
            BotConfiguration(
                auth_token=token,
                name=kwargs.get('name'),
                avatar=kwargs.get('avatar'),
            ))

    def enable_webhook(self, url: str, **kwargs):
        return self.bot.set_webhook(url=url)

    def disable_webhook(self):
        return self.bot.unset_webhook()

    def get_account_info(self) -> Dict[str, Any]:
        # {
        #    "status":0,
        #    "status_message":"ok",
        #    "id":"pa:75346594275468546724",
        #    "name":"account name",
        #    "uri":"accountUri",
        #    "icon":"http://example.com",
        #    "background":"http://example.com",
        #    "category":"category",
        #    "subcategory":"sub category",
        #    "location":{
        #       "lon":0.1,
        #       "lat":0.2
        #    },
        #    "country":"UK",
        #    "webhook":"https://my.site.com",
        #    "event_types":[
        #       "delivered",
        #       "seen"
        #    ],
        #    "subscribers_count":35,
        #    "members":[
        #       {
        #          "id":"01234567890A=",
        #          "name":"my name",
        #          "avatar":"http://example.com",
        #          "role":"admin"
        #       }
        #    ]
        # }
        data = self.bot.get_account_info()
        account_info = {
            'id': data.get('id'),
            'username': data.get('name'),
            'info': data
        }
        return account_info

    def get_user_info(self, user_id: str, **kwargs) -> Dict[str, Any]:
        # {
        #    "status":0,
        #    "status_message":"ok",
        #    "message_token":4912661846655238145,
        #    "user":{
        #       "id":"01234567890A=",
        #       "name":"John McClane",
        #       "avatar":"http://avatar.example.com",
        #       "country":"UK",
        #       "language":"en",
        #       "primary_device_os":"android 7.1",
        #       "api_version":1,
        #       "viber_version":"6.5.0",
        #       "mcc":1,
        #       "mnc":1,
        #       "device_type":"iPhone9,4"
        #    }
        # }
        data = self.bot.get_user_details(user_id).get('user')
        user_info = {
            'id': data.get('id'),
            'username': data.get('name'),
            'info': {
                'avatar': data.get('avatar'),
                'country': data.get('country'),
                'language': data.get('language'),
                'primary_device_os': data.get('primary_device_os'),
                'api_version': data.get('api_version'),
                'viber_version': data.get('viber_version'),
                'device_type': data.get('device_type'),
            }
        }
        return user_info

    def parse_message(self, request: Request) -> Message:
        # NOTE: There is no way to get the body
        #       after processing the request in DRF.
        # # Verify signature
        # sign = request.META.get('HTTP_X_VIBER_CONTENT_SIGNATURE')
        # if not self.bot.verify_signature(request.body, sign):
        #     raise IMApiException(f'Viber message not verified; '
        #                          f'Data={request.data}; Sign={sign};')

        # Parse message data in to viber types
        vb_request = create_request(request.data)

        try:
            return self._get_message(vb_request)
        except Exception as err:
            # TODO: remove this after development
            log.exception(f'Parse message error; Message={vb_request}; '
                          f'Error={err};')
            return Message(MessageType.UNDEFINED)

    @staticmethod
    def _get_message(vb_request: ViberRequest) -> Message:
        if isinstance(vb_request, ViberMessageRequest):
            if isinstance(vb_request.message, TextMessage):
                return Message(message_type=MessageType.TEXT,
                               message_id=vb_request.message_token,
                               user_id=vb_request.sender.id,
                               text=vb_request.message.text,
                               timestamp=vb_request.timestamp)
            elif isinstance(vb_request.message, PictureMessage):
                return Message(message_type=MessageType.PICTURE,
                               message_id=vb_request.message_token,
                               user_id=vb_request.sender.id,
                               image_url=vb_request.message.media,
                               timestamp=vb_request.timestamp)
            elif isinstance(vb_request.message, VideoMessage):
                return Message(message_type=MessageType.PICTURE,
                               message_id=vb_request.message_token,
                               user_id=vb_request.sender.id,
                               video_url=vb_request.message.media,
                               size=vb_request.message.size,
                               timestamp=vb_request.timestamp)
            else:
                return Message(message_type=MessageType.TEXT,
                               message_id=vb_request.message_token,
                               user_id=vb_request.sender.id,
                               text=vb_request.message,
                               timestamp=vb_request.timestamp)
        elif isinstance(vb_request, ViberConversationStartedRequest):
            return Message(message_type=MessageType.START,
                           message_id=vb_request.message_token,
                           user_id=vb_request.user.id,
                           user_name=vb_request.user.name,
                           timestamp=vb_request.timestamp,
                           context=vb_request.context)
        elif isinstance(vb_request, ViberSubscribedRequest):
            return Message(message_type=MessageType.SUBSCRIBED,
                           user_id=vb_request.user.id,
                           user_name=vb_request.user.name,
                           timestamp=vb_request.timestamp)
        elif isinstance(vb_request, ViberUnsubscribedRequest):
            return Message(message_type=MessageType.UNSUBSCRIBED,
                           user_id=vb_request.user_id,
                           timestamp=vb_request.timestamp)
        elif isinstance(vb_request, ViberDeliveredRequest):
            return Message(message_type=MessageType.DELIVERED,
                           message_id=vb_request.meesage_token,
                           user_id=vb_request.user_id,
                           timestamp=vb_request.timestamp)
        elif isinstance(vb_request, ViberSeenRequest):
            return Message(message_type=MessageType.SEEN,
                           message_id=vb_request.meesage_token,
                           user_id=vb_request.user_id,
                           timestamp=vb_request.timestamp)
        elif isinstance(vb_request, ViberFailedRequest):
            log.warning(f'Client failed receiving message; Error={vb_request}')
            return Message(message_type=MessageType.FAILED,
                           message_id=vb_request.meesage_token,
                           user_id=vb_request.user_id,
                           error=vb_request.desc)
        elif vb_request.event_type == 'webhook':
            return Message(message_type=MessageType.WEBHOOK,
                           timestamp=vb_request.timestamp)
        else:
            log.warning(f'VRequest Type={type(vb_request)}; '
                        f'Object={vb_request};')
            return Message(message_type=MessageType.UNDEFINED,
                           timestamp=vb_request.timestamp,
                           event_type=vb_request.event_type)
            # raise IMApiException('Failed parse message; '
            #                      'Request object={}'.format(viber_request))

    def send_message(self,
                     receiver: str,
                     message: str,
                     button_list: list = None,
                     **kwargs) -> str:
        kb = self._get_keyboard(button_list) if button_list else None

        if message:
            vb_message = TextMessage(text=message, keyboard=kb)
        else:
            vb_message = KeyboardMessage(keyboard=kb)

        try:
            return self.bot.send_messages(receiver, [vb_message])[0]
        except Exception as err:
            if str(err) == 'failed with status: 6, message: notSubscribed':
                raise NotSubscribed(err)
            raise MessengerException(err)

    def send_file(self,
                  receiver: str,
                  file_url: str,
                  file_size: int,
                  file_name: str,
                  file_type: str = None,
                  button_list: list = None,
                  **kwargs) -> str:
        kb = self._get_keyboard(button_list) if button_list else None

        if file_type == 'image':
            message = PictureMessage(media=file_url, keyboard=kb)
        elif file_type == 'video':
            message = VideoMessage(media=file_url, size=file_size, keyboard=kb)
        else:
            message = FileMessage(media=file_url,
                                  size=file_size,
                                  file_name=file_name,
                                  keyboard=kb)

        try:
            return self.bot.send_messages(receiver, [message])[0]
        except Exception as err:
            if str(err) == 'failed with status: 6, message: notSubscribed':
                raise NotSubscribed(err)
            raise MessengerException(err)

    def welcome_message(self, text: str) -> Dict[str, str]:
        return {
            "sender": {
                "name": self.name,
                "avatar": self.avatar_url
            },
            "type": "text",
            "text": text
        }

    @staticmethod
    def _get_keyboard(buttons: list):
        if not buttons:
            return None

        kb = {
            'Type': 'keyboard',
            'BgColor': '#ffffff',
            'min_api_version': 6,
            'Buttons': []
        }

        for button in buttons:
            # if not isinstance(button, Button):
            #     continue

            _btn = {
                'Columns':
                2,  # TODO: how is it storage in Model?
                'Rows':
                1,
                'BgColor':
                '#aaaaaa',
                'ActionType':
                'reply',
                'ActionBody':
                button.command,
                'Text':
                '<font color="{clr}"><b>{text}'
                '</b></font>'.format(text=button.text, clr='#131313'),
                'TextVAlign':
                'middle',
                'TextHAlign':
                'center',
                'TextOpacity':
                60,
                'TextSize':
                'large',
                'TextPaddings': [12, 8, 8, 20],  # [up, left, right, bottom]
            }

            try:
                if hasattr(button, 'image'):
                    _btn.update(
                        BgMedia=
                        f'https://bot.it-o.ru/static/img/{button.image}',
                        BgMediaScaleType='fill')
            except IndexError:
                pass

            kb['Buttons'].append(_btn)

        return kb