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')
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']} Оператор подключился")
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
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, }
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
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
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)
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
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