Русский
Русский
English
Статистика
Реклама

Бот в телеграм, озвучивающий ваши эмоции в сообщении

Привет!


В этой статье я опишу своего бота в телеграм, который работает и сейчас.


Для чего бот создавался, его цель и умения


В реальности человек использует множество звуков для выражения своих эмоций и отношений. Но почти все системы искусственного интеллекта и голосовые помощники "слишком интеллектуальные". Они просто отбрасывают эмоциональные звуки, не понимают и не могут правильно использовать междометия. Поэтому я создал бота, и он открывает возможность естественной речи, полной мычанием, скрипами, всхлипываниями, рыками и сотней других эмоциональных тонов и полутонов.
Предпологаю, что разрабатываемый алгоритм будет работать в коммерческом секторе, например, отслеживая эмоциональное состояние клиента и направлять ветвление алгоритма чтобы предупредить его возможные действия. Эмоции первые регуляторы поведения и по тону речи или, например, по хмыканью легко отследить замешательство и раздражение пользователя и среагировать до того как он начнёт ругаться и требовать.
Можно так же придать и самим голосовым помощникам больше "человечности". Они могут откашливаться перед длинной лекцией или усмехаться вместо того, чтобы стандартным голосом объяснять что сейчас была шутка.
В медицинской практике программа поможет определить состояние пациента, который не может членораздельно говорить и по отдельным всхлипываниям сориентировать персонал на процедуру лечения. Она может применяться и для отдельных категорий заболеваний, таких как аутизм и дислексия.
В мессенджерах бот поможет передать чувства и отношения через сеть наравне, в дополнении или вместо стандартных эмоджи.
Как площадку для экспериментов и разработки я использую мессенджер "Телеграм".
На текущем моменте бот @YouToneBot возвращает звук эмоции на стандартный смайлик.
В дальнейшем планируется научить бота совершать обратную операцию, то есть на звуковой тон выдавать "эмодзи".


Какой он в итоге получится?


Он сможет отправлять голосовые сообщение, озвучивающие смайл, так же он сможет это делать прямо в чате! Даже не придётся переносить сообщение, достаточно будет написать его имя в сообщении, и написать свое сообщение.


image
image
image

Код


Итак, сейчас бот умеет выдавать голосовое сообщение, на смайл. Впрочем, ничего сложного, начнем.
Я написал бота на Python, используя библиотеку PyTelegramBotApi.
Сначала нужно узнать, как послать голосовое сообщение от бота. Я узнал, что бот может посылать те голосовые сообщения, которые были посланы ему, Т.К. у PyTelegramBotApi есть функция send_voice() используя id голосовго сообщения, его можно получить просто у функции message_handler() взять message.voice.file_id.
Теперь нужно придумать как хранить звуки к смайликам, и вот как я придумал: хранить в JSON , как ключ будет смайлик к которому бот будет отправлять звук, а как значение id голосового сообщения.
Соответственно, нам нужно послать голосовое сообщение боту, и записать его id, к смайлику. Вот и сложилось представление о базе данных звуков, нам всего лишь нужен "python словарь", и в него нужно записовать как ключ смайл, а как значение id голосового сообщения.
Вот примерно так:


{    "emoji1": "voice_id1",    "emoji2": "voice_id2",    "emoji3": "voice_id3",    "emoji4": "voice_id4",    "emoji5": "voice_id5",    "emoji6": "voice_id6",}#почему-то не отображаются смайлики, поэтому "emoji" == ~смайлик

Вот именно так у меня устроена база данных звуков.


Теперь код.
Для начала я сделал класс YouTone(), чтобы писать все методы бота там.
В def init(self) я прописал TOKEN, VOICE_SOUNDS
TOKEN Это просто токен бота
VOICE_SOUNDS это словарь, из смайлов и id голосовых сообщений#база данных
И там же, в init, создаю переменную self.BOT, вот таким кодом


TL.TeleBot(self.TOKEN)

Это собственно, сам бот.
Итак, в классе сразу написал 3 функции, это
LS_handler() отвечающая за личную переписку с ботом
start_handler() отвечающая за команды боту (/start и /get) в личной переписке
local_lerning() для записи голосовых сообщений к смайлам
В LS_handler() пока сделаем echo бота


LS_handler()
def LS_handler(self):    @self.BOT.message_handler(content_types=['text'])    def send_text(message):        def msg(message_text):            self.BOT.send_message(message.chat.id, str(message_text))        msg(message.text)

В start_handler() пока просто на команду /start бот будет отвечать привет


start_handler()
def start_handler(self):    @self.BOT.message_handler(commands=['start', "get"])    def commands(message):        if message.text == "/start":            self.BOT.send_message(message.chat.id, 'Привет. Я высылаю тебе звуки по смайлам')

И теперь займемся local_lerning(). Нам нужно записать к смайлам звуки охарактеризовающие смайл, для этого нужно послать голосовое сообщение боту, принять его на стороне бота, и записать к соответствующему смайлу.
Сделал я это так чтобы было удобо озвучивать, используя tkinter. На окне в tkitner показывается какой смайл нужно озвучить, посылается звук боту, на окне tkitner появляется кнопка "прослушить звук", я прослушиваю и если мне он нравится то нажимаю на "сохранить звук к смайлу", и к словарю базы данных дописывается (или перезаписывается):
смайл как ключ
id голосового сообщения как значение


Для этой функции я сделал 3 функции, и также базу данных просто смайликов без значений
window_smile() само окно tkitner
bot_work() это запуск работы бота, с возможностю приема голосовых сообщений.
save_sound() для сохранения в файл смайла и id голосового сообщения
База данных смайликов она нужна будет для создание базы данных смайликов со значениями


Итак, window_smile() это просто функция где рисуется и запускается окно


window_smile()
def window_smile():#эта функция принадлежит функции local_lerning()    self.root = Tk()    self.root.geometry("500x500")    self.smile_tkinter = Label(text=self.AUDIO_SOUNDS_ITEMS[self.index][0],font='Times 30')    self.open_sound = Button(text="Открыть звук",font='Times 10',command=lambda: webbrowser.open(url=r"путь/до/файла/в/котором/звук.ogg"))    self.Y_or_N = Button(text="Принять звук",font='Times 15',command=save_sound)    self.info = Label(text="""\n\n\n\n\n\n\nСмотришь на смайл, озвучиваешь,\n проверяешь,\n нажимаешь 'Принять звук',\n смайл меняется,\n ты его озвучивашь,\n проверяешь,\n нажимаешь принять звук.""",font="Consolas 11")    self.smile_tkinter.pack()    self.open_sound.pack()    self.Y_or_N.pack()    self.info.pack()    self.root.mainloop() 

bot_work() эта функция запускает бота, отслеживает входящие голосовые сообщения, и записывает их в "путь/до/файла/в/котором/звук.ogg",


bot_work()
def bot_work():    @self.BOT.message_handler(content_types=['text',"voice"])    def send_text(message):        def msg(message_text):            self.BOT.send_message(message.chat.id, str(message_text))        self.smile_now = self.SOUNDS_DB[self.index][0]        self.smile_tkinter.config(text=self.smile_now)        try:            self.id_voice = message.voice.file_id            self.voice_info = self.BOT.get_file(file_id=self.id_voice)            self.voice_file = requests.get('https://api.telegram.org/file/bot{0}/{1}'.format(self.TOKEN, self.voice_info.file_path)).content        except BaseException as e:            print(e)        else:            with open("путь/до/файла/в/котором/звук.ogg", "wb") as f:                f.write(self.voice_file)

Тут мы с помощю get_file(), поулчаем id файла (не голосового сообщения), с помощю id получаем сам файл через requests, и записываем его.
Также получаем id голосовго сообщения, и записываем его в self.voice_id.


save_sound()
def save_sound():    self.voices_good.update({self.smile_now:str(self.id_voice)})    self.index += 1    self.smile_now = self.SMILES_DB[self.index][0]    self.smile_tkinter.config(text=self.smile_now)    with open("data.txt","w",encoding="utf-8") as f:        f.write(str(self.voices_good))

Эта функция вызывается по кнопке "принять звук".
Здесь мы обновляем словарь смайликов и голосовых сообщений новым смайлом и голосовым сообщением.
Также тут есть перменная о которой я не сказал, это self.index, в этой перменной хранится индекс смайлика который нужно озвучить на данный момент, Т.Е. индекс в списке self.SMILES_DB


Дальше я в функции local_lerning(), запускаю 2 функции в разных потоках, это
window_smile()и bot_work().
Делаю это я с помощю threading.
Вот так


from threading import Threadth1 = Thread(target=window_smile)th1.start()th2 = Thread(target=bot_work)th2.start()

local_lerning()
def local_lerning(self):    from threading import Thread    self.smile_now = None    self.index = 0    self.id_voice = None    self.voices_good = {    }    self.smile_tkinter = None    def save_sound():        self.voices_good.update({self.smile_now:str(self.id_voice)})        self.index += 1        self.smile_now = self.AUDIO_SOUNDS_ITEMS[self.index][0]        self.smile_tkinter.config(text=self.smile_now)        with open("data.txt","w",encoding="utf-8") as f:            f.write(str(self.voices_good))    def window_smile():        self.root = Tk()        self.root.geometry("500x500")        self.smile_tkinter = Label(text=self.AUDIO_SOUNDS_ITEMS[self.index][0],font='Times 30')        self.open_sound = Button(text="Открыть звук",font='Times 10',command=lambda: webbrowser.open(url=r"C:\Program Files\JetBrains\projects\telegram\voice.ogg"))        self.Y_or_N = Button(text="Принять звук",font='Times 15',command=save_sound)        self.info = Label(text="""\n\n\n\n\n\n\nСмотришь на смайл, озвучиваешь,\n проверяешь,\n нажимаешь 'Принять звук',\n смайл меняется,\n ты его озвучивашь,\n проверяешь,\n нажимаешь принять звук.""",font="Consolas 11")        self.smile_tkinter.pack()        self.open_sound.pack()        self.Y_or_N.pack()        self.info.pack()        self.root.mainloop()    def bot_work():        @self.BOT.message_handler(content_types=['text',"voice"])        def send_text(message):            def msg(message_text):                self.BOT.send_message(message.chat.id, str(message_text))            def snd_doc(name_doc):                self.BOT.send_document(message.chat.id, open(name_doc, "rb"))            self.smile_now = self.AUDIO_SOUNDS_ITEMS[self.index][0]            self.smile_tkinter.config(text=self.smile_now)            try:                self.id_voice = message.voice.file_id                self.voice_info = self.BOT.get_file(file_id=self.id_voice)                self.voice_file = requests.get('https://api.telegram.org/file/bot{0}/{1}'.format(self.TOKEN, self.voice_info.file_path)).content            except BaseException as e:                print("ошибка: ",e)            else:                with open("voice.ogg", "wb") as f:                    f.write(self.voice_file)    th1 = Thread(target=window_smile)    th1.start()    th2 = Thread(target=bot_work)    th2.start()

Вот так выглядит озвучивание смаликов.
image


Итак, с помощю этой функции можно записать голосовые сообщения к смайлам. Так я и сделал.
В итоге у меня появилась база данных смайлов, и голосовых сообщений к ник.


Теперь нужно релизовать логику отправления голосовых сообщений при виде смайлов. Начнем сначала с личных сообщений, потом будет делать бота inline.
Для того чтобы обноружить смайлы в сообщении, я сделал простую функцию, разбивания сообщения на список, а потом проверяя нету ли в базе данных звуков и смайлов такого символа, если есть, то тогда звук на смайл найден.
Вот так она выгдялит


message_list = list(message.text)is_send = Falsefor word in message_list:    if word in self.VOICE_SOUNDS:        if self.VOICE_SOUNDS[word]:            snd_voice(voice_id=self.VOICE_SOUNDS[word])            print("smile has been found")            is_send = True            breakif not is_send:    print("smile has been not found")

LS_handler()
def LS_handler(self):    @self.BOT.message_handler(content_types=['text'])    def send_text(message):        def msg(message_text):            self.BOT.send_message(message.chat.id, str(message_text))        def snd_doc(name_doc):            self.BOT.send_document(message.chat.id, open(name_doc, "rb"))        def snd_voice(voice_id: str):            self.BOT.send_voice(message.chat.id,voice=voice_id)        message_list = list(message.text)        is_send = False        for word in message_list:            if word in self.VOICE_SOUNDS:                if self.VOICE_SOUNDS[word]:                    snd_voice(voice_id=self.VOICE_SOUNDS[word])                    is_send = True                    break        if not is_send:            msg("Я не нашел знакомого мне смайла 

Вот собственно и весь LS_handler(), теперь почти тоже самое, только в inline_handler()


как работает бот inline

Бот inline работатет так что его нужно вызвать, просто написав его имя, и дальше написать ему сообщение, которое он прочитает и уже выдаст вам какой-то результат


inline_handler()
def inline_handler(self):    @self.BOT.inline_handler(lambda query: len(query.query) > 0)    def query_text(query):        message_list = list(query.query)        #ставлю сразу что не нашел, а если найду, то поменяю ;)        output_msg = [types.InlineQueryResultArticle(            id="1",            title="Я не нашел знакомого мне смайла ",            input_message_content=types.InputTextMessageContent(message_text="Я не нашел знакомого мне смайла")        )]        is_send = False        id_now = 1#id для сообщений        for word in message_list:            try:                self.VOICE_SOUNDS[word]            except KeyError:                pass            else:                if self.VOICE_SOUNDS[word]:                    if is_send == False:                        output_msg = []                    is_send = True                    if not word in [i.title for i in output_msg]:#если смайла нет в списке уже выданных смайлов, то надо добавить ;)                        output_msg.append(types.InlineQueryResultCachedVoice(                            id=str(id_now),                            voice_file_id=self.VOICE_SOUNDS[word],                            title=str(word),                            caption=query.query                        ))                    else:                        pass#типа если есть уже такой смайл то добавлять второй такой жене надо                    id_now +=1 #это для того чтобы id сообщений увеличивался        self.BOT.answer_inline_query(query.id, output_msg)

Почти тоже самое, потому что там нужо сохранять в список множество смайлов которые были написаны боту, и потом выводить список доступных озвучиваемых смайлов.
Т.Е. мы разделям строку поданую пользователем на символы, как и в прошлый раз, но не останавливаемся на первом смайле (в прошлый при виде смайла мы вызывали break), а сохраняем смайл в список, и ищем следующие смайлы. После чего выводим все звуки к смайлам.


И вот так сейчас уже можно использовать бота в inline


image

Заключение


В этой статье я рассказал больше про логику, нежели про код, почти как и в прошлой статье.
Бота @YouToneBot я еще буду развивать, хочу сделать чтобы пользователь мог записать голосовое сообщение, а бот выдать по нему смайл, Т.Е. наоборот нынешней работе бота.
Спасибо!

Источник: habr.com
К списку статей
Опубликовано: 29.08.2020 12:21:18
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Python

Python3

Telegram

Telegram bots

Звук

Эмоции

Смайлики

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru