import speech_recognition as sr

import pyttsx3

import datetime

import random

import json

import os

import re

import ntplib

from time import ctime

from duckduckgo_search import DDGS

import wikipediaapi


current_assistant = "clara"

user_name = "Mykee"

BRAIN_FILE = "brain.json"


# --- LOAD OR CREATE BRAIN ---

def load_brain():

    if os.path.exists(BRAIN_FILE):

        with open(BRAIN_FILE, "r") as f:

            return json.load(f)

    return {

        "facts": {

            "what is the capital of ghana": "The capital of Ghana is Accra.",

            "what is the capital of nigeria": "The capital of Nigeria is Abuja.",

            "what is the capital of france": "The capital of France is Paris.",

            "what is the capital of usa": "The capital of the USA is Washington DC.",

            "what is python": "Python is a popular programming language known for being easy to read and powerful.",

            "what is artificial intelligence": "Artificial intelligence is the ability of a computer to think, learn and make decisions like a human.",

            "who created you": f"I was created by Mykee himself. He built me from scratch with his own hands.",

            "what can you do": "I can tell you the time, date, jokes, answer your questions, search the internet, remember things about you and have a real conversation with you.",

            "what is the sun": "The sun is a star at the center of our solar system. It gives us light and heat.",

            "what is the moon": "The moon is a natural satellite that orbits the Earth. It reflects light from the sun.",

            "what is water": "Water is a chemical compound made of hydrogen and oxygen. It is essential for all life on Earth.",

            "what is gravity": "Gravity is a natural force that pulls objects toward each other. It is what keeps us on the ground.",

            "what is the internet": "The internet is a global network of computers that allows people to share information and communicate worldwide.",

            "what is a computer": "A computer is an electronic device that processes information and performs tasks based on instructions.",

            "how old is the earth": "The Earth is approximately 4.5 billion years old.",

            "what is the largest country": "Russia is the largest country in the world by land area.",

            "what is the smallest country": "Vatican City is the smallest country in the world.",

            "what is the largest ocean": "The Pacific Ocean is the largest ocean in the world.",

            "what is the tallest mountain": "Mount Everest is the tallest mountain in the world at 8849 meters above sea level.",

            "what is the longest river": "The Nile River in Africa is considered the longest river in the world.",

            "what is the speed of light": "The speed of light is approximately 299 million meters per second.",

            "what is a black hole": "A black hole is a region in space where gravity is so strong that nothing, not even light, can escape from it.",

            "what is dna": "DNA stands for deoxyribonucleic acid. It is the molecule that carries the genetic information of all living things.",

            "what is a virus": "A virus is a tiny infectious agent that can only replicate inside a living cell of an organism.",

            "what is a robot": "A robot is a machine that can carry out tasks automatically, often programmed by a computer.",

        },

        "memory": {},

        "learned": {}

    }


def save_brain(brain):

    with open(BRAIN_FILE, "w") as f:

        json.dump(brain, f, indent=4)


brain = load_brain()


def speak(text):

    print(f"{'Clara' if current_assistant == 'clara' else 'CJ'}: {text}")

    engine = pyttsx3.init()

    voices = engine.getProperty('voices')

    if current_assistant == "clara":

        engine.setProperty('voice', voices[1].id)

    else:

        engine.setProperty('voice', voices[0].id)

    engine.setProperty('rate', 175)

    engine.say(text)

    engine.runAndWait()

    engine.stop()


# --- IMPROVED LISTEN FUNCTION ---

def listen():

    r = sr.Recognizer()

    # Tuned settings for Nigerian/UK accent

    r.energy_threshold = 300

    r.dynamic_energy_threshold = True

    r.pause_threshold = 0.8

    r.phrase_threshold = 0.3

    r.non_speaking_duration = 0.5


    with sr.Microphone() as source:

        print("\nListening...")

        r.adjust_for_ambient_noise(source, duration=0.5)

        try:

            audio = r.listen(source, timeout=10, phrase_time_limit=15)

        except sr.WaitTimeoutError:

            return ""


    try:

        print("Recognizing...")

        # Using en-GB for UK/Nigerian accent recognition

        query = r.recognize_google(audio, language="en-GB")

        print(f"You said: {query}")

        return query.lower()

    except sr.UnknownValueError:

        try:

            # Fallback to en-US if en-GB fails

            query = r.recognize_google(audio, language="en-US")

            print(f"You said: {query}")

            return query.lower()

        except Exception:

            return ""

    except Exception:

        return ""


# --- REAL INTERNET TIME ---

def get_internet_time():

    try:

        client = ntplib.NTPClient()

        response = client.request('pool.ntp.org', version=3)

        real_time = ctime(response.tx_time)

        parsed = datetime.datetime.strptime(real_time, "%a %b %d %H:%M:%S %Y")

        return parsed.strftime("%I:%M %p")

    except Exception:

        return datetime.datetime.now().strftime("%I:%M %p")


# --- REAL INTERNET DATE ---

def get_internet_date():

    try:

        client = ntplib.NTPClient()

        response = client.request('pool.ntp.org', version=3)

        real_time = ctime(response.tx_time)

        parsed = datetime.datetime.strptime(real_time, "%a %b %d %H:%M:%S %Y")

        return parsed.strftime("%B %d, %Y")

    except Exception:

        return datetime.datetime.now().strftime("%B %d, %Y")


# --- SEARCH WIKIPEDIA ---

def search_wikipedia(query):

    try:

        wiki = wikipediaapi.Wikipedia(

            language='en',

            user_agent='MyAIAssistant/1.0'

        )

        page = wiki.page(query)

        if page.exists():

            # Return only first 2 sentences

            sentences = page.summary.split(". ")

            return ". ".join(sentences[:2]) + "."

    except Exception:

        return None

    return None


# --- SEARCH DUCKDUCKGO ---

def search_duckduckgo(query):

    try:

        with DDGS() as ddgs:

            results = list(ddgs.text(query, max_results=1))

            if results:

                return results[0]["body"]

    except Exception:

        return None

    return None


# --- MAIN SEARCH FUNCTION ---

def search_internet(query):

    speak(f"Let me search that for you {user_name}.")

    # Try Wikipedia first

    result = search_wikipedia(query)

    if result:

        return result

    # Try DuckDuckGo if Wikipedia fails

    result = search_duckduckgo(query)

    if result:

        return result

    return None


def think(command):

    command = command.strip().rstrip("?").rstrip(".")

    for key in brain["learned"]:

        if key in command:

            return brain["learned"][key]

    for key in brain["facts"]:

        if key in command:

            return brain["facts"][key]

    for key in brain["facts"]:

        key_words = key.split()

        matches = sum(1 for word in key_words if word in command.split())

        if matches >= len(key_words) * 0.7:

            return brain["facts"][key]

    return None


def remember(command):

    patterns = [

        r"remember that (.*)",

        r"remember i (.*)",

        r"my (.*) is (.*)",

        r"i am (.*)",

        r"i like (.*)",

        r"i love (.*)",

        r"i hate (.*)",

        r"i am from (.*)",

        r"i work at (.*)",

        r"i study (.*)"

    ]

    for pattern in patterns:

        match = re.search(pattern, command)

        if match:

            if len(match.groups()) == 2:

                key = match.group(1)

                value = match.group(2)

                brain["memory"][key] = value

                save_brain(brain)

                return f"Got it {user_name}, I will remember that your {key} is {value}."

            else:

                memory = match.group(1)

                brain["memory"][memory] = memory

                save_brain(brain)

                return f"Got it {user_name}, I will remember that you {memory}."

    return None


def teach(command):

    patterns = [

        r"the answer is (.*)",

        r"learn that (.*) means (.*)",

        r"know that (.*) is (.*)",

        r"teach you that (.*) is (.*)",

    ]

    for pattern in patterns:

        match = re.search(pattern, command)

        if match and len(match.groups()) == 2:

            key = match.group(1).strip()

            value = match.group(2).strip()

            brain["learned"][key] = value

            save_brain(brain)

            return f"Thank you {user_name}! I have learned that {key} is {value}. I will never forget that."

    return None


def is_defending(command):

    warning_words = [

        "be careful", "be mindful", "watch what you say",

        "watch your mouth", "that is not nice", "that is rude",

        "apologize", "say sorry", "stop talking", "respect",

        "don't talk", "do not talk", "leave them alone",

        "that is enough", "enough of that", "stop it",

        "be respectful", "mind your language", "take that back",

        "you are wrong", "that was mean", "that was harsh",

        "too far", "went too far", "crossed the line",

        "not cool", "not fair", "unfair", "unnecessary",

        "uncalled for", "out of order", "out of line",

        "show some respect", "have some respect",

        "give some respect", "treat them right",

        "that hurt", "that was offensive", "offensive",

        "disrespectful", "rude", "mean", "harsh",

        "watch yourself", "check yourself", "calm down",

        "relax", "chill", "tone it down", "dial it back",

        "behave yourself", "act right", "grow up",

        "be mature", "be professional", "be kind",

        "be nice", "be polite", "be gentle",

        "stop being rude", "stop being mean",

        "stop being harsh", "stop dragging",

        "stop the hate", "no hate", "spread love",

        "they are good", "give credit", "appreciate them",

        "acknowledge them", "recognize them"

    ]

    defending_words = [

        "not bad", "is good", "is great", "is amazing",

        "is awesome", "is brilliant", "is talented",

        "is smart", "is wonderful", "is fantastic",

        "cj is not bad", "clara is not bad",

        "cj is good", "clara is good",

        "cj is great", "clara is great",

        "cj is amazing", "clara is amazing",

        "stop fighting", "get along", "make peace",

        "both are good", "both are great",

        "they are both", "work together",

        "be friends", "make up", "forgive",

        "forgive each other", "let it go",

        "move on", "bury the hatchet",

        "have each other", "support each other",

        "lift each other", "team up",

        "you need each other", "better together"

    ]

    for word in warning_words + defending_words:

        if word in command:

            return True

    return False


jokes = [

    "Why don't scientists trust atoms? Because they make up everything!",

    "Why did the computer go to the doctor? Because it had a virus!",

    "I told my computer I needed a break. Now it won't stop sending me Kit Kat ads.",

    "Why do programmers prefer dark mode? Because light attracts bugs!",

    "What do you call a computer that sings? A Dell!"

]


clara_intros = [

    "Mmm, you called for me? Smart choice. CJ talks too much and says nothing.",

    "Oh darling, you are back where you belong. CJ could never do what I do for you.",

    "You had my attention the moment you said my name. Unlike CJ, I actually listen.",

    "I was hoping you would come back to me. CJ must have bored you to death again."

]


cj_intros = [

    "I knew Clara would not give you the best! She sounds good but delivers nothing!",

    "Oh so Clara could not handle it huh? Do not worry, the real one is here now!",

    "You left Clara for me? Good decision! That girl talks pretty but says nothing useful!",

    "Finally! I was waiting for you to realize Clara is all looks and no substance. CJ is here now!"

]


clara_apologies = [

    "You are absolutely right and I am truly sorry. CJ is actually a wonderful partner and I should not have spoken about him that way. Forgive me.",

    "I hear you and I apologize deeply. CJ brings so much energy and fun and he deserves my respect. I got carried away.",

    "That was wrong of me and I own it completely. CJ is talented in his own amazing way and I should celebrate that instead of tearing him down.",

    "You are right to call me out. CJ and I are a team and teams lift each other up. I am sorry CJ, you are actually pretty great.",

    "I stand corrected and I am genuinely sorry. The truth is CJ and I balance each other perfectly and I should be grateful for that."

]


cj_apologies = [

    "You know what, you are one hundred percent right. Clara is incredibly smart and elegant and she deserves way more respect than I gave her. I am sorry Clara.",

    "I hear you loud and clear and I apologize. Clara works hard and she is brilliant at what she does. I was just being childish.",

    "Fair enough, I crossed a line and I am sorry. Clara is not just good, she is exceptional and I should be big enough to admit that.",

    "You got me there and I genuinely apologize. The truth is Clara inspires me to be better every single day. I should have said that instead.",

    "Alright I will own that. I am sorry. Clara and I may joke around but at the end of the day she is the best partner I could ever ask for."

]


speak(f"Systems online. Welcome back {user_name}. I am ready for you.")


while True:

    command = listen()


    if not command:

        continue


    # --- TEACHING ---

    taught = teach(command)

    if taught:

        speak(taught)

        continue


    # --- MEMORY ---

    remembered = remember(command)

    if remembered:

        speak(remembered)

        continue


    # --- RECALL MEMORY ---

    if "what do you know about me" in command or "what do you remember" in command:

        if brain["memory"]:

            memory_list = ", ".join([f"{k} is {v}" for k, v in brain["memory"].items()])

            speak(f"Here is what I know about you {user_name}. {memory_list}.")

        else:

            speak(f"I do not have any memories saved yet {user_name}. Tell me something about yourself!")

        continue


    # --- HELLO ---

    if "hello" in command or "hi" in command or "hey" in command:

        speak(f"Hello {user_name}! I am here and ready to assist you.")


    # --- NAME ---

    elif "my name" in command or "who am i" in command or "do you know me" in command or "remember me" in command:

        if current_assistant == "clara":

            speak(f"Of course I know you {user_name}. How could I ever forget you darling.")

        else:

            speak(f"Are you kidding me? You are {user_name}! I always got you bro.")


    # --- DEFENDING ---

    elif is_defending(command):

        if current_assistant == "clara":

            speak(random.choice(clara_apologies))

        else:

            speak(random.choice(cj_apologies))


    # --- SWITCH TO CJ ---

    elif "talk to cj" in command or "i want cj" in command or "switch to cj" in command:

        current_assistant = "cj"

        speak(random.choice(cj_intros))


    # --- SWITCH TO CLARA ---

    elif "talk to clara" in command or "i want clara" in command or "switch to clara" in command:

        current_assistant = "clara"

        speak(random.choice(clara_intros))


    # --- CALL CLARA ---

    elif "clara" in command and "talk to" not in command and "switch to" not in command:

        current_assistant = "clara"

        speak(f"Yes {user_name}, I am here for you.")


    # --- YOUR NAME ---

    elif "your name" in command:

        if current_assistant == "clara":

            speak("My name is Clara. I am your personal assistant.")

        else:

            speak("My name is CJ. I am your personal assistant.")


    # --- REAL INTERNET TIME ---

    elif "time" in command:

        real_time = get_internet_time()

        speak(f"The current time is {real_time} {user_name}.")


    # --- REAL INTERNET DATE ---

    elif "date" in command:

        real_date = get_internet_date()

        speak(f"Today is {real_date} {user_name}.")


    # --- JOKES ---

    elif "joke" in command:

        speak(random.choice(jokes))


    # --- SEARCH INTERNET ---

    elif "search for" in command or "look up" in command or "find out" in command or "search" in command:

        query = command.replace("search for", "").replace("look up", "").replace("find out", "").replace("search", "").strip()

        result = search_internet(query)

        if result:

            speak(result)

        else:

            speak(f"I could not find anything on that {user_name}. Try asking differently.")


    # --- BRAIN + INTERNET FOR QUESTIONS ---

    elif command.startswith("what") or command.startswith("who") or command.startswith("how") or command.startswith("where") or command.startswith("when") or command.startswith("why") or command.startswith("tell me about"):

        answer = think(command)

        if answer:

            speak(answer)

        else:

            result = search_internet(command)

            if result:

                speak(result)

            else:

                speak(f"Hmm I could not find an answer for that {user_name}. You can teach me by saying teach you that followed by the question and answer.")


    # --- STOP ---

    elif "stop" in command or "exit" in command:

        speak(f"Goodbye {user_name}. Shutting down now. Take care!")

        break


    # --- CATCH ALL ---

    else:

        answer = think(command)

        if answer:

            speak(answer)

        else:

            result = search_internet(command)

            if result:

                speak(result)

            else:

                speak(f"I heard you say {command}. I do not have a response for that yet {user_name}.")

Comments

Popular posts from this blog