I'm new to programming and Fastapi and i have a problem when trying to run a script from a Postman. After first sentence from list, runAndWait() gets stuck and does not continue. When I run a script alone from for example tkinter it works fine.
I have threading because i want to pause, resume, etc. reading.
This is my script
import PyPDF2
import pyttsx3
import threading
import re
alphabets = "([A-Za-z])"
prefixes = "(Mr|St|Mrs|Ms|Dr)[.]"
suffixes = "(Inc|Ltd|Jr|Sr|Co)"
starters = "(Mr|Mrs|Ms|Dr|He\\s|She\\s|It\\s|They\\s|Their\\s|Our\\s|We\\s|But\\s|However\\s|That\\s|This\\s|Wherever)"
acronyms = "([A-Z][.][A-Z][.](?:[A-Z][.])?)"
websites = "[.](com|net|org|io|gov)"
digits = "([0-9])"
class Speaking(threading.Thread):
def __init__(self, list_of_sentences, **kw):
super().__init__(**kw)
self.sentences = list_of_sentences
self.paused = False
self.speaker = pyttsx3.init()
self.speaker.setProperty('rate', 160)
self.voices = self.speaker.getProperty('voices')
self.speaker.setProperty('voice', self.voices[0].id)
def run(self):
self.running = True
while self.sentences and self.running:
if not self.paused:
sentence = self.sentences.pop(0)
print(sentence)
self.speaker.say(sentence)
self.speaker.runAndWait()
print(self.running)
print("finished")
self.running = False
def stop(self):
self.running = False
def pause(self):
self.paused = True
def resume(self):
self.paused = False
speak = None
def read():
global speak
if speak is None or not speak.running:
speak = Speaking(book, daemon=True)
speak.start()
def stop():
global speak
if speak:
speak.stop()
speak = None
def pause():
if speak:
speak.pause()
def unpause():
if speak:
speak.resume()
def split_into_sentences(text):
text = " " + text + " "
text = text.replace("\n", " ")
text = re.sub(prefixes, "\\1<prd>", text)
text = re.sub(websites, "<prd>\\1", text)
text = re.sub(digits + "[.]" + digits, "\\1<prd>\\2", text)
if "..." in text: text = text.replace("...", "<prd><prd><prd>")
if "Ph.D" in text: text = text.replace("Ph.D.", "Ph<prd>D<prd>")
if "e.g." in text: text = text.replace("e.g.", "e<prd>g<prd>")
if "i.e." in text: text = text.replace("i.e.", "i<prd>e<prd>")
text = re.sub("\\s" + alphabets + "[.] ", " \\1<prd> ", text)
text = re.sub(acronyms + " " + starters, "\\1<stop> \\2", text)
text = re.sub(alphabets + "[.]" + alphabets + "[.]" + alphabets + "[.]", "\\1<prd>\\2<prd>\\3<prd>", text)
text = re.sub(alphabets + "[.]" + alphabets + "[.]", "\\1<prd>\\2<prd>", text)
text = re.sub(" "+suffixes+"[.] "+starters, " \\1<stop> \\2", text)
text = re.sub(" "+suffixes+"[.]", " \\1<prd>", text)
text = re.sub(" " + alphabets + "[.]", " \\1<prd>", text)
if "”" in text: text = text.replace(".”", "”.")
if "\"" in text: text = text.replace(".\"", "\".")
if "!" in text: text = text.replace("!\"", "\"!")
if "?" in text: text = text.replace("?\"", "\"?")
text = text.replace(".", ".<stop>")
text = text.replace("?", "?<stop>")
text = text.replace("!", "!<stop>")
text = text.replace("<prd>", ".")
sentences = text.split("<stop>")
sentences = sentences[:-1]
sentences = [s.strip() for s in sentences]
return sentences
book = None
def read_book(path, page_num):
global book
file = ""
page = page_num
# path = 'D:\Books\Hobbit.pdf'
pdfReader = PyPDF2.PdfFileReader(open(rf"{path}", 'rb'))
num_of_pages = pdfReader.numPages
for count in range(page, num_of_pages):
pageObj = pdfReader.getPage(count)
file += pageObj.extractText()
book = split_into_sentences(file)
And this is my API
from fastapi import HTTPException, Depends, APIRouter, status, Request, Form
from fastapi.responses import HTMLResponse
from sqlalchemy.orm import Session
from .. import schemas, models, oauth2
from ..database import get_db
from typing import Optional, List
from .. import audiobook
from fastapi.templating import Jinja2Templates
templates = Jinja2Templates(directory="app/templates")
#router.get("/{id}", response_class=HTMLResponse)
def get_book(request: Request, id: int, db: Session = Depends(get_db)):
book = db.query(models.Book).filter(models.Book.id == id).first()
if not book:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"book with id {id} is not found")
image = book.img
name = book.name
audiobook.read_book(book.path, 0)
return templates.TemplateResponse("audiobook.html", {"request": request, "image": image, "name": name})
#router.put("/{id}")
def get_book(to_do: schemas.BookPlay, id: int, db: Session = Depends(get_db)):
book = db.query(models.Book).filter(models.Book.id == id).first()
if not book:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"book with id {id} is not found")
if to_do.play == 0:
audiobook.read()
elif to_do.play == 1:
audiobook.pause()
elif to_do.play == 2:
audiobook.unpause()
elif to_do.play == 3:
audiobook.stop()
return HTMLResponse(status_code=status.HTTP_204_NO_CONTENT)
Any advice would be helpful. Thanks in advance.
Related
I am looking for a small pause of 3 secound after each mp3 file made in the batch folder. I tried to modify the script to do this but I didn't succeed
import requests, base64, random, argparse, os, playsound, time, re, textwrap
#
voices = [
# ENGLISH VOICES
'en_au_001', # English AU - Female
]
def tts(session_id: str, text_speaker: str = "en_us_002", req_text: str = "TikTok Text To Speech", filename: str = 'voice.mp3', play: bool = False):
req_text = req_text.replace("+", "plus")
req_text = req_text.replace(" ", "+")
req_text = req_text.replace("&", "and")
headers = {
'User-Agent': 'com.zhiliaoapp.musically/2022600030 (Linux; U; Android 7.1.2; es_ES; SM-G988N; Build/NRD90M;tt-ok/3.12.13.1)',
'Cookie': f'sessionid={session_id}'
}
url = f"https://api22-normal-c-useast1a.tiktokv.com/media/api/text/speech/invoke/?text_speaker={text_speaker}&req_text={req_text}&speaker_map_type=0&aid=1233"
r = requests.post(url, headers = headers)
if r.json()["message"] == "Couldn't load speech. Try again.":
output_data = {"status": "Session ID is invalid", "status_code": 5}
print(output_data)
return output_data
vstr = [r.json()["data"]["v_str"]][0]
msg = [r.json()["message"]][0]
scode = [r.json()["status_code"]][0]
log = [r.json()["extra"]["log_id"]][0]
dur = [r.json()["data"]["duration"]][0]
spkr = [r.json()["data"]["speaker"]][0]
b64d = base64.b64decode(vstr)
with open(filename, "wb") as out:
out.write(b64d)
output_data = {
"status": msg.capitalize(),
"status_code": scode,
"duration": dur,
"speaker": spkr,
"log": log
}
print(output_data)
if play is True:
playsound.playsound(filename)
os.remove(filename)
return output_data
def tts_batch(session_id: str, text_speaker: str = 'en_us_002', req_text: str = 'TikTok Text to Speech', filename: str = 'voice.mp3'):
req_text = req_text.replace("+", "plus")
req_text = req_text.replace(" ", "+")
req_text = req_text.replace("&", "and")
headers = {
'User-Agent': 'com.zhiliaoapp.musically/2022600030 (Linux; U; Android 7.1.2; es_ES; SM-G988N; Build/NRD90M;tt-ok/3.12.13.1)',
'Cookie': f'sessionid={session_id}'
}
url = f"https://api22-normal-c-useast1a.tiktokv.com/media/api/text/speech/invoke/?text_speaker={text_speaker}&req_text={req_text}&speaker_map_type=0&aid=1233"
r = requests.post(url, headers=headers)
if r.json()["message"] == "Couldn't load speech. Try again.":
output_data = {"status": "Session ID is invalid", "status_code": 5}
print(output_data)
return output_data
vstr = [r.json()["data"]["v_str"]][0]
msg = [r.json()["message"]][0]
scode = [r.json()["status_code"]][0]
log = [r.json()["extra"]["log_id"]][0]
dur = [r.json()["data"]["duration"]][0]
spkr = [r.json()["data"]["speaker"]][0]
b64d = base64.b64decode(vstr)
with open(filename, "wb") as out:
out.write(b64d)
output_data = {
"status": msg.capitalize(),
"status_code": scode,
"duration": dur,
"speaker": spkr,
"log": log
}
print(output_data)
return output_data
def batch_create(filename: str = 'voice.mp3'):
out = open(filename, 'wb')
def sorted_alphanumeric(data):
convert = lambda text: int(text) if text.isdigit() else text.lower()
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
return sorted(data, key=alphanum_key)
for item in sorted_alphanumeric(os.listdir('./batch/')):
filestuff = open('./batch/' + item, 'rb').read()
out.write(filestuff)
out.close()
def main():
parser = argparse.ArgumentParser(description = "Simple Python script to interact with the TikTok TTS API")
parser.add_argument("-v", "--voice", help = "the code of the desired voice")
parser.add_argument("-t", "--text", help = "the text to be read")
parser.add_argument("-s", "--session", help = "account session id")
parser.add_argument("-f", "--file", help = "use this if you wanna use 'text.txt'")
parser.add_argument("-n", "--name", help = "The name for the output file (.mp3)")
parser.add_argument("-p", "--play", action='store_true', help = "use this if you want to play your output")
args = parser.parse_args()
text_speaker = args.voice
if args.file is not None:
req_text = open(args.file, 'r', errors='ignore', encoding='utf-8').read()
else:
if args.text == None:
req_text = 'TikTok Text To Speech'
print('You need to have one form of text! (See README.md)')
else:
req_text = args.text
if args.play is not None:
play = args.play
if args.voice == None:
text_speaker = 'en_us_002'
print('You need to have a voice! (See README.md)')
if text_speaker == "random":
text_speaker = randomvoice()
if args.name is not None:
filename = args.name
else:
filename = 'voice.mp3'
if args.session is None:
print('FATAL: You need to have a TikTok session ID!')
exit(1)
if args.file is not None:
chunk_size = 200
textlist = textwrap.wrap(req_text, width=chunk_size, break_long_words=True, break_on_hyphens=False)
os.makedirs('./batch/')
for i, item in enumerate(textlist):
tts_batch(args.session, text_speaker, item, f'./batch/{i}.mp3')
batch_create(filename)
for item in os.listdir('./batch/'):
os.remove('./batch/' + item)
os.removedirs('./batch/')
return
tts(args.session, text_speaker, req_text, filename, play)
def randomvoice():
count = random.randint(0, 15)
text_speaker = voices[count]
return text_speaker
def sampler():
for item in voices:
text_speaker = item
filename = item
print(item)
req_text = 'TikTok Text To Speech Sample'
tts(text_speaker, req_text, filename)
if __name__ == "__main__":
main()
if I add more dots and commas in the text file then I manage to get breaks. but they are not good enough and I don't think this is the best solution
Code below is my test that has no pauses, sadly.. Any ideas or suggestions?
I want to make a word contain 3 characters only and no words duplicated
import requests, random
from colorama import Fore
while True:
usr = ""
for charachter in random.choices("abcdefghijklmnopqrstvwxyz1234567890"):
user = usr+ charachter
response = requests.get(f"https://www.instagram.com/{user}/")
if (response.status_code == 200):
print(Fore.RED + "Taken: " + Fore.BLUE + user)
elif(response.status_code == 400):
print(Fore.GREEN + "Avilable User: "+ Fore.BLUE +user)
try this:
import requests, random
from colorama import Fore
while True:
usr = ""
for i in range(3):
while True:
charachter = random.choices("abcdefghijklmnopqrstvwxyz1234567890")
if str(charachter[-1]) not in usr:
usr += str(charachter[-1])
break
response = requests.get(f"https://www.instagram.com/{usr}/")
if (response.status_code == 200):
print(Fore.RED + "Taken: " + Fore.BLUE + usr)
elif(response.status_code == 400):
print(Fore.GREEN + "Avilable User: "+ Fore.BLUE +usr)
from string import ascii_lowercase, digits
from random import sample
"".join(sample(ascii_lowercase + digits, 3))
try
#!/usr/bin/python
import requests, random
#from colorama import Fore
def get_user():
str = "abcdefghijklmnopqrstvwxyz1234567890"
usr = "".join(random.sample(str, 3))
return usr
unique_user = set()
while True:
usr = get_user()
if usr not in unique_user:
print(f"Unique User, calling API >>>> {usr}")
unique_user.add(usr)
else:
print(f"duplicate user skipping >>>> {usr}")
continue
as #MoRe suggested "".join(sample(ascii_lowercase + digits, 3)) can be used in place of str = "abcdefghijklmnopqrstvwxyz1234567890"
I created a Voice Assistant using speech recognition and GTTS modules in Python. The code works perfectly fine when run from script. But when I converted it using pyinstaller --onefile Speak.py(The name of the file) it stopped working. It is using my microphone but its not responding to anything. Suppose if I say hey google which is the wake up keyword it simply doesnt respond. I tried after a while but of no use. Can anyone please help me???
Code:
"from gtts import gTTS
import speech_recognition as sr
import os
import playsound
from datetime import datetime
import webbrowser
keeprunning = True
WAKING = "HEY GOOGLE"
def chec(cond, tex):
if cond in tex:
return True
else:
return False
def speak(text):
speaker = gTTS(text = text, lang = "en")
speaker.save("Voice.mp3")
playsound.playsound("voice.mp3")
os.remove("Voice.mp3")
def cleanify(text, wtremove, wtremove2=""):
try:
text = text.replace(wtremove)
except:
if not wtremove2 == "":
text = text.replace(wtremove2, "")
return text
#Main controlling part here(Oof!)
def Control(comnd):
if chec("SEARCH", comnd) or chec("GOOGLE", comnd):
comnd = cleanify(comnd, "SEARCH", "GOOGLE")
webbrowser.open(f"https://google.com/search?q={comnd.lower()}")
elif chec("WHO ARE YOU", comnd):
speak("I am your virtual assistant, google")
keepcontrol()
elif chec("TIME", comnd):
t = datetime.now()
t = time.strptime(t.strftime("%H:%S"), "%H:%M")
tt = time.strftime( "%I:%M %p", t )
speak(f"The current time is {tt}")
elif chec("NOTE", comnd) or chec("REMEMBER", comnd) or chec("JOT", comnd):
try:
text = comnd.replace("NOTE")
except:
try:
text = text.replace("REMEMBER")
except:
text = text.replace("JOT")
try:
with open("This_File_Name_Is_Very_Big_Because_I_dont_Want_to_overwrite_anyother_files_so_forgive_me_plz.txt", "rt") as file:
previous = file.read()
except:
with open("This_File_Name_Is_Very_Big_Because_I_dont_want_to_overwrite_any_other_files_so_forgive_me_plz.txt", "wt") as file:
ttw = f"""
•{text.lower()}
"""
file.write(previous + ttw)
previous = ""
with open("Notes.txt", "wt") as file:
ttw = previous + " •" + text
file.write(ttw)
speak("Got it! I noted it down")
elif chec("OPEN", comnd):
web = cleanify(comnd, "OPEN")
bruh = cleanify(web, ".com")
speak(f"Opening {bruh}")
print(comnd)
web = cleanify(comnd, "OPEN")
if web == "":
web = listen()
else:
if "https://" in web:
webbrowser.open(web.lower())
else:
web = "https://" + web
webbrowser.open(web.lower())
keepcontrol()
#Main controlling part ends
def listen():
r = sr.Recognizer()
with sr.Microphone() as source:
listen = r.listen(source)
try:
text = r.recognize_google(listen)
return text.upper()
except Exception as e:
if not e == "":
return ""
keepcontrol()
else:
speak("Sorry we couldnt catch that, please try again")
keepcontrol()
def keepcontrol():
while keeprunning:
text = listen()
if not text == None:
if text.count(WAKING) == 1:
speak("I am listening..")
text = listen()
if not text == None and not text == "":
Control(text)
else:
speak("Sorry i did not get that. Try again in a few seconds")
keepcontrol()
elif chec("QUIT", text):
exit()
elif chec("", text):
keepcontrol()
else:
speak("Sorry we didnt get that right. Please try again.")
speak("I am booting up...")
keepcontrol()
"
When you have converted it into exe,I think you have forgot to put files that you have used to build the assistant in the folder.
When your exe get converted, just simply copy those files(the files you have used) in the same folder in which you have kept your exe.
Hope it will work.
Problem:
Telegram bot doesn't recognise seen messages and keeps responding to the latest message until I send "quit" or crtl-c in command line.
Completely new to python. There may be a flaw in my programming logic.
In 'for last_update_id in updates["result"]' I tried to add 1 to the last_update_id variable after each loop. But the variable doesn't seem to update.
# chatbot.py not included. It trains NN model.
import json
import requests
import time
import urllib
import telegram
TOKEN = "xxx"
URL = "https://api.telegram.org/bot{}/".format(TOKEN)
def get_url(url):
response = requests.get(url)
content = response.content.decode("utf8")
return content
def get_json_from_url(url):
content = get_url(url)
js = json.loads(content)
return js
def get_updates(offset): #gets json file from URL
url = URL + "getUpdates"
if offset:
url += "?offset={}".format(offset)
js = get_json_from_url(url)
return js
def get_last_update_id(updates):
update_ids = []
for update in updates["result"]:
update_ids.append(int(update["update_id"]))
return max(update_ids)
def get_last_chat_text(updates):
num_updates = len(updates["result"])
last_update = num_updates - 1
text = updates["result"][last_update]["message"]["text"] #text input
return text
def get_last_chat_id(updates):
chat_id = updates["result"][-1]["message"]["chat"]["id"]
return chat_id
def send_message(output,chat_id):
bot = telegram.Bot(token=TOKEN)
bot.sendMessage(chat_id=chat_id, text = output)
def main():
input_text = get_last_chat_text(updates)
return input_text
print("Let's chat! (type 'quit' to exit)")
last_update_id = None
while True:
updates = get_updates(last_update_id) #returns json file
last_update_id = get_last_update_id(updates) #returns max_update_id
for last_update_id in updates["result"]:
main()
input_text = main()
if input_text == "quit":
break
input_text = tokenize(input_text)
X = bag_of_words(input_text, all_words)
X = X.reshape(1, X.shape[0])
X = torch.from_numpy(X).to(device)
output = model(X)
_, predicted = torch.max(output, dim=1)
tag = tags[predicted.item()]
probs = torch.softmax(output, dim=1)
prob = probs[0][predicted.item()]
if prob.item() > 0.75:
for intent in intents['intents']:
if tag == intent["tag"]:
output = f"{random.choice(intent['responses'])}"
else:
output = f"{bot_name}: I do not understand..."
print(output)
chat_id = get_last_chat_id(updates)
print(chat_id)
send_message(output, chat_id)
time.sleep(0.1)
last_update_id =+ 1 #returns max_id in the json file and adds 1
continue
I managed to fix this problem by adding a break in the loop so it loops back to the outside 'while' loop. Below is the edited code:
# chatbot.py module imported above this line not included. It trains NN model.
import json
import requests
import time
import urllib
import telegram
TOKEN = "XXX"
URL = "https://api.telegram.org/bot{}/".format(TOKEN)
def get_url(url):
response = requests.get(url)
content = response.content.decode("utf8")
return content
def get_json_from_url(url):
content = get_url(url)
js = json.loads(content)
return js
def get_updates(offset): #gets json file from URL
url = URL + "getUpdates"
if offset:
url += "?offset={}".format(offset)
js = get_json_from_url(url)
return js
def get_last_update_id(updates):
update_ids = []
for update in updates["result"]:
update_ids.append(update["update_id"])
return max(update_ids, default = last_update_id)
def get_last_chat_text(updates):
# num_updates = len(updates["result"])
# last_update = num_updates - 1
text = updates["result"][-1]["message"]["text"] #text input
return text
def get_last_chat_id(updates):
chat_id = updates["result"][-1]["message"]["chat"]["id"]
return chat_id
def send_message(output,chat_id):
bot = telegram.Bot(token=TOKEN)
bot.sendMessage(chat_id=chat_id, text = output)
def main():
input_text = get_last_chat_text(updates)
return input_text
bot_name = "XXX"
print("Let's chat! (type 'quit' to exit)")
last_update_id = 0
while True:
updates = get_updates(last_update_id) #returns json file
for last_update_id in updates["result"]:
main()
input_text = main()
if input_text == "quit":
break
input_text = tokenize(input_text)
X = bag_of_words(input_text, all_words)
X = X.reshape(1, X.shape[0])
X = torch.from_numpy(X).to(device)
output = model(X)
_, predicted = torch.max(output, dim=1)
tag = tags[predicted.item()]
probs = torch.softmax(output, dim=1)
prob = probs[0][predicted.item()]
if prob.item() > 0.75:
for intent in intents['intents']:
if tag == intent["tag"]:
output = f"{random.choice(intent['responses'])}"
else:
output = f"{bot_name}: I do not understand..."
print(output)
chat_id = get_last_chat_id(updates)
print(chat_id)
send_message(output, chat_id)
time.sleep(0.1)
break
last_update_id = get_last_update_id(updates) + 1 #returns max_id in the json file and adds 1
I have a script that alerts me by mail when a phrase changes on a web page. I tried many things, but I can't fix the isAvailable() function: the script says "not available" every time, whether or not I give it an available server. Have you any clues?
# CONFIG
TARGET_KIMSUFI_ID = "160sk1" # something like 160sk1
TARGET_DESCR = ""
EMAIL_FROM_ADDRS = ""
EMAIL_TO_ADRS = ""
EMAIL_SMTP_LOGIN = EMAIL_FROM_ADDRS
EMAIL_SMTP_PASSWD = ""
EMAIL_SMTP_SERVER = ""
# CODE
import urllib.request
import smtplib
import time
def isAvailable():
rawPageContent = urllib.request.urlopen("https://www.kimsufi.com/en/servers.xml").read()
rawPageContent = str(rawPageContent)
poz = rawPageContent.find(TARGET_KIMSUFI_ID)
row = rawPageContent[poz:]
poz = row.find("</tr>")
row = row[:poz]
searchText = "Currently being replenished"
poz = row.find(searchText)
return poz != -1
def sendEmailWithMessageAvailable():
msg = "From: KIMSUFI HUNTER <"+EMAIL_FROM_ADDRS+">\r\n"+\
"To: "+EMAIL_TO_ADRS+"\r\n"+\
"Subject: [KIMSUFI] "+TARGET_DESCR+" is now AVAILABLE!\r\n"+\
"\r\n"+\
"kimsufi-hunter.py has detected that "+TARGET_DESCR+" is now ["+time.ctime()+"] available!\r\n"+\
"https://www.kimsufi.com/en/\r\n"
server = smtplib.SMTP(EMAIL_SMTP_SERVER)
server.starttls()
server.login(EMAIL_SMTP_LOGIN,EMAIL_SMTP_PASSWD)
server.sendmail(EMAIL_FROM_ADDRS, EMAIL_TO_ADRS, msg)
server.quit()
while True:
if isAvailable():
print(time.ctime() + " -- KIMSUFI "+TARGET_DESCR+" not available")
nextSleep = 5 #5secs
else:
print(time.ctime() + " -- KIMSUFI "+TARGET_DESCR+" AVAILABLE!!! -- sleeping for 5 minutes")
sendEmailWithMessageAvailable()
nextSleep = 5*60 #5mins
time.sleep(nextSleep)
Your isAvailable() function returns True if the website is available, False otherwise. You should change the if statement to:
if not isAvailable():
...