# ai_assistant.py
# By Shivansh (merged & stable)
import speech_recognition as sr
from googletrans import Translator
from gtts import gTTS
import tempfile, os, time, re, requests, wikipedia, datetime, threading, subprocess, random
import pygame
import psutil
from dateutil import tz
import webbrowser
import urllib.parse
# -------------- CONFIG --------------
OPENWEATHER_API_KEY = "259ad0a2e3545e5051f5df22a79d52db" # <-- YOUR KEY
NEWS_API_KEY = "" # optional
DEFAULT_CITY = "Jaunpur"
LANG_EN = "en"
LANG_HI = "hi"
# -------------------------------------
# Init audio & translator
pygame.mixer.pre_init(frequency=44100, size=-16, channels=2, buffer=4096)
pygame.mixer.init()
recognizer = sr.Recognizer()
translator = Translator()
# Arduino serial
try:
import serial
arduino = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
time.sleep(2)
print("Arduino connected")
except Exception as e:
arduino = None
print("Arduino not connected:", e)
def led(state):
if arduino:
try:
arduino.write(state.encode())
except:
pass
def speak(text, lang='en'):
print("Assistant:", text)
led('S')
try:
tts = gTTS(text=text, lang=lang, tld='co.in', slow=False)
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as fp:
tts.save(fp.name)
pygame.mixer.music.load(fp.name)
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
time.sleep(0.1)
os.remove(fp.name)
except Exception as e:
print("TTS error:", e)
led('E')
def wait_for_internet(timeout=30):
import socket
for i in range(timeout):
try:
socket.create_connection(("8.8.8.8", 53), timeout=2)
print("Internet up")
return True
except:
time.sleep(1)
return False
# -------- TIME / DATE / WEATHER --------
def get_time_str():
return datetime.datetime.now().strftime("%I:%M %p")
def get_date_str():
return datetime.date.today().strftime("%d %B %Y")
def get_weather(city=DEFAULT_CITY):
if not OPENWEATHER_API_KEY:
return None
try:
url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&units=metric&appid={OPENWEATHER_API_KEY}"
r = requests.get(url, timeout=8)
if r.status_code != 200:
return None
data = r.json()
temp = data['main']['temp']
desc = data['weather'][0]['description']
return f"{city} ka mausam: {temp} degree Celsius, {desc}."
except:
return None
def get_forecast(city=DEFAULT_CITY):
if not OPENWEATHER_API_KEY:
return None
try:
url = f"https://api.openweathermap.org/data/2.5/forecast?q={city}&units=metric&appid={OPENWEATHER_API_KEY}"
r = requests.get(url, timeout=8)
if r.status_code != 200:
return None
data = r.json()
lines = []
for i in range(0, min(24, len(data['list'])), 8):
item = data['list'][i]
dt = item['dt_txt'].split()[0]
temp = item['main']['temp']
desc = item['weather'][0]['description']
lines.append(f"{dt}: {temp}°C, {desc}")
return " ; ".join(lines)
except:
return None
# -------- WIKIPEDIA --------
def wiki_search(query):
try:
wikipedia.set_lang("en")
return wikipedia.summary(query, sentences=2)
except:
return None
# -------- NEWS --------
# -------- SAFE MATH --------
MATH_ALLOWED = re.compile(r'^[0-9\.\+\-\*\/\(\) %]+$')
def safe_calc(expr):
expr = expr.replace('x','*').replace('X','*').strip()
if not MATH_ALLOWED.match(expr):
return None
try:
return str(eval(expr, {'__builtins__': None}, {}))
except:
return None
# -------- DICTIONARY API --------
def define_word_api(word):
try:
r = requests.get(f"https://api.dictionaryapi.dev/api/v2/entries/en/{word}", timeout=6)
if r.status_code != 200:
return None
d = r.json()
return d[0]['meanings'][0]['definitions'][0]['definition']
except:
return None
def youtube_web_play(song):
try:
query = urllib.parse.quote(song)
url = f"https://m.youtube.com/results?search_query={query}"
webbrowser.open(url)
return True
except Exception as e:
print("Youtube Web Error:", e)
return False
# -------- COMMAND PATTERNS --------
COMMAND_PATTERNS = [
(r'\b(time|samay)\b', 'time'),
(r'\b(date|tareekh|tarikh)\b', 'date'),
(r'\b(weather in )\s*([A-Za-z ]+)', 'weather_city'),
(r'\b(weather|mausam|temperature)\b', 'weather'),
(r'\b(forecast)\b', 'forecast'),
(r'\b(who is|what is|tell me about|ke baare mein|kaun hai|kya hai)\b', 'wiki'),
(r'\b(solve|calculate|compute|solve:)\b\s*(.*)', 'math'),
(r'\b(joke|jokes|joke sunao)\b', 'joke'),
(r'\b(alarm|set alarm)\b\s*([0-2]?\d[:\.][0-5]\d)', 'alarm'),
(r'\b(timer|set timer|timer set)\b\s*([0-9]+)\b', 'timer'),
(r'\b(play|music|gana|song)\b\s*(.*)', 'music'),
(r'\b(meaning of|define|definition of|what does)\b\s*(.*)', 'dictionary'),
(r'\b(good morning|namaste|hello|hi)\b', 'greeting'),
(r'\b(system info|status|uptime)\b', 'sysinfo'),
(r'\b(exit|stop|quit|band karo)\b', 'exit'),
]
def detect_command(text):
t = text.lower()
for pat, cmd in COMMAND_PATTERNS:
m = re.search(pat, t)
if m:
return cmd, m.groups()
return None, None
# -------- LISTEN --------
def listen_once(timeout=25, phrase_time_limit=35):
with sr.Microphone() as source:
recognizer.adjust_for_ambient_noise(source, duration=1)
led('L')
print("Listening...")
try:
audio = recognizer.listen(source, timeout=timeout, phrase_time_limit=phrase_time_limit)
except sr.WaitTimeoutError:
led('E')
speak("I didn't hear anything.", LANG_EN)
return None
try:
text = recognizer.recognize_google(audio)
print("User:", text)
return text
except sr.UnknownValueError:
led('E')
speak("Sorry, I didn't catch that. Please repeat.", LANG_EN)
return None
except sr.RequestError:
led('E')
speak("Speech service is unavailable.", LANG_EN)
return None
# -------- ALARM --------
alarms = []
def alarm_worker():
while True:
now = datetime.datetime.now().strftime("%H:%M")
for a in alarms[:]:
if a == now:
speak("Alarm! It's " + now, LANG_EN)
alarms.remove(a)
time.sleep(10)
threading.Thread(target=alarm_worker, daemon=True).start()
# -------- MAIN LOOP --------
def run_assistant():
wait_for_internet(20)
speak("Namaste here I am an assistant and voice translator programmed by Shivansh Shukla reading in Class 10th in Harihar Public School,Jaunpur Please say something in Hindi or English.", LANG_HI)
current_music_player = None
while True:
try:
text = listen_once()
if not text:
continue
try:
detected_lang = translator.detect(text).lang
except:
detected_lang = 'en'
resp_lang = LANG_EN if detected_lang != 'hi' else LANG_HI
cmd, groups = detect_command(text)
# TIME
if cmd == 'time':
speak("The time is " + get_time_str(), resp_lang)
# DATE
elif cmd == 'date':
speak("Today's date is " + get_date_str(), resp_lang)
# WEATHER DEFAULT CITY
elif cmd == 'weather':
w = get_weather(DEFAULT_CITY)
speak(w or "Weather not available.", resp_lang)
# WEATHER BY CITY
elif cmd == 'weather_city':
city = groups[1] if len(groups) > 1 else DEFAULT_CITY
w = get_weather(city.strip())
speak(w or f"Weather not available for {city}", resp_lang)
# FORECAST
elif cmd == 'forecast':
f = get_forecast(DEFAULT_CITY)
speak(f or "Forecast not available.", resp_lang)
# WIKIPEDIA
elif cmd == 'wiki':
q = re.sub(r'^(tell me about|who is|what is|ke baare mein)\s*', '', text, flags=re.I)
ans = wiki_search(q)
speak(ans or "I could not find that.", resp_lang)
# MATH
elif cmd == 'math':
expr = groups[1] if len(groups) > 1 else text
result = safe_calc(expr)
speak("The answer is " + result if result else "I can't calculate that.", resp_lang)
# JOKE
elif cmd == 'joke':
speak(random.choice([
"Why did the computer show up late? It had a hard drive.",
"Why do programmers prefer dark mode? Because light attracts bugs.",
"My computer needed a break, and it crashed."
]), resp_lang)
# NEWS
# ALARM
elif cmd == 'alarm':
if groups and len(groups) >= 2 and groups[1]:
time_str = groups[1]
alarms.append(time_str)
speak("Alarm set for " + time_str, resp_lang)
else:
speak("Please say alarm time like alarm 06:30", resp_lang)
# TIMER
elif cmd == 'timer':
if groups and len(groups) >= 2 and groups[1]:
secs = int(groups[1])
speak(f"Setting timer for {secs} seconds.", resp_lang)
threading.Thread(
target=lambda s: (time.sleep(s), speak("Timer finished.", resp_lang)),
args=(secs,),
daemon=True
).start()
else:
speak("Say timer in seconds like set timer 10", resp_lang)
# MUSIC
elif cmd == 'music':
song = groups[-1].strip() if groups and groups[-1] else ""
speak(f"Playing {song}" if song else "Playing music", resp_lang)
ok = youtube_web_play(song if song else "music")
if ok:
speak("Please wait playing.", resp_lang)
else:
speak("could not play that song.", resp_lang)
# DICTIONARY
elif cmd == 'dictionary':
word = groups[-1].split()[-1]
meaning = define_word_api(word)
speak(meaning or "Definition not found.", resp_lang)
# GREETING
elif cmd == 'greeting':
speak("Namaste! Kaise madad karu?", resp_lang)
# SYSTEM INFO
elif cmd == 'sysinfo':
try:
cpu = psutil.cpu_percent(interval=1)
mem = psutil.virtual_memory().percent
speak(f"CPU {cpu}% , RAM {mem}%", resp_lang)
except:
speak("System info not available.", resp_lang)
# EXIT
elif cmd == 'exit':
speak("Goodbye! See you soon.", resp_lang)
break
# DEFAULT (Translate or Wiki fallback)
else:
if re.search(r"\b(who|what|where|when|why|how|kaun|kya|kahan|kab|kyun)\b", text.lower()):
ans = wiki_search(text)
if ans:
speak(ans, resp_lang)
continue
try:
lang = translator.detect(text).lang
except:
lang = 'en'
if lang == 'hi':
out = translator.translate(text, src='hi', dest='en').text
speak("The English translation is: " + out, LANG_EN)
else:
out = translator.translate(text, src='en', dest='hi').text
speak("Anuvad hai: " + out, LANG_HI)
time.sleep(0.5)
except KeyboardInterrupt:
speak("Stopping assistant. Goodbye!", LANG_EN)
break
except Exception as e:
print("Main error:", e)
led('E')
speak("Something went wrong.", LANG_EN)
if __name__ == "__main__":
run_assistant()
Comments