Voice-Controlled Desktop Assistant

import speech_recognition as sr

import pyttsx3

import subprocess

import os

import webbrowser

import time

from datetime import datetime

import threading


# -------------------- Configuration --------------------

# Change these to match your environment

MUSIC_FOLDER = os.path.expanduser("~/Music")  # folder to play music from

SEARCH_ROOT = os.path.expanduser("~")         # root folder for file searches

DEFAULT_BROWSER = None                        # None will use webbrowser.open

# Map simple app names to commands (Windows, macOS, Linux)

COMMANDS = {

    "notepad": {"win": "notepad"},

    "calculator": {"win": "calc", "mac": "open -a Calculator", "linux": "gnome-calculator"},

    "vscode": {"win": r"C:\Users\%USERNAME%\AppData\Local\Programs\Microsoft VS Code\Code.exe",

               "mac": "open -a Visual\\ Studio\\ Code", "linux": "code"},

    "explorer": {"win": "explorer", "mac": "open", "linux": "xdg-open"},

}


# -------------------- Helpers --------------------

def speak(text, engine):

    """Speak text asynchronously so we don't block the main loop."""

    def _s():

        engine.say(text)

        engine.runAndWait()

    t = threading.Thread(target=_s, daemon=True)

    t.start()


def recognize_speech_from_mic(recognizer, microphone, timeout=5, phrase_time_limit=6):

    """Capture audio and return recognized text (or None)."""

    with microphone as source:

        recognizer.adjust_for_ambient_noise(source, duration=0.6)

        try:

            audio = recognizer.listen(source, timeout=timeout, phrase_time_limit=phrase_time_limit)

        except sr.WaitTimeoutError:

            return None

    try:

        # Using Google Web Speech API (requires internet) — good accuracy

        return recognizer.recognize_google(audio)

    except sr.RequestError:

        # API unreachable

        return "[error_api]"

    except sr.UnknownValueError:

        return None


def open_app(app_key):

    """Open an application based on COMMANDS map."""

    platform = os.name  # 'nt' on Windows, 'posix' on macOS/Linux

    is_windows = platform == "nt"

    cmd_map = COMMANDS.get(app_key.lower())

    if not cmd_map:

        return False, f"No mapping for app '{app_key}'."


    try:

        if is_windows:

            cmd = cmd_map.get("win")

            if not cmd:

                return False, "No Windows command available for this app."

            # Support environment vars in path

            cmd = os.path.expandvars(cmd)

            subprocess.Popen(cmd, shell=True)

        else:

            # macOS or Linux (posix)

            cmd = cmd_map.get("mac") or cmd_map.get("linux")

            if not cmd:

                return False, "No command available for this platform."

            subprocess.Popen(cmd, shell=True)

        return True, f"Opened {app_key}."

    except Exception as e:

        return False, str(e)


def open_folder(folder_name):

    """Open a common folder name like downloads, documents, desktop"""

    name = folder_name.strip().lower()

    user = os.path.expanduser("~")

    mapping = {

        "downloads": os.path.join(user, "Downloads"),

        "documents": os.path.join(user, "Documents"),

        "desktop": os.path.join(user, "Desktop"),

        "pictures": os.path.join(user, "Pictures"),

        "music": os.path.join(user, "Music"),

    }

    path = mapping.get(name) or os.path.join(user, name)

    if os.path.exists(path):

        if os.name == "nt":

            os.startfile(path)

        else:

            subprocess.Popen(f'xdg-open "{path}"', shell=True)

        return True, f"Opened folder {path}"

    return False, f"Folder {path} does not exist."


def search_files(query, root=SEARCH_ROOT, limit=10):

    """Simple filename search returning up to `limit` results."""

    results = []

    q = query.lower()

    for dirpath, dirs, files in os.walk(root):

        for f in files:

            if q in f.lower():

                results.append(os.path.join(dirpath, f))

                if len(results) >= limit:

                    return results

    return results


def play_random_music():

    """Play a random music file from MUSIC_FOLDER (if available)."""

    if not os.path.exists(MUSIC_FOLDER):

        return False, f"Music folder {MUSIC_FOLDER} not found."

    exts = (".mp3", ".wav", ".ogg", ".flac")

    files = [f for f in os.listdir(MUSIC_FOLDER) if f.lower().endswith(exts)]

    if not files:

        return False, "No music files found in your music folder."

    choice = os.path.join(MUSIC_FOLDER, files[0])  # pick the first for now

    try:

        if os.name == "nt":

            os.startfile(choice)

        else:

            subprocess.Popen(f'xdg-open "{choice}"', shell=True)

        return True, f"Playing {os.path.basename(choice)}"

    except Exception as e:

        return False, str(e)


def confirm_action(recognizer, microphone, engine, prompt="Are you sure? Say 'yes' to confirm"):

    speak(prompt, engine)

    text = recognize_speech_from_mic(recognizer, microphone, timeout=5, phrase_time_limit=4)

    if text:

        txt = text.lower()

        return "yes" in txt or "yeah" in txt or "yup" in txt

    return False


# -------------------- Main Assistant --------------------

def main():

    # Initialize recognizer and TTS

    recognizer = sr.Recognizer()

    microphone = sr.Microphone()

    engine = pyttsx3.init()

    engine.setProperty('rate', 160)


    speak("Hello — voice assistant activated. Say a command.", engine)

    print("Assistant is listening... (say 'help' for suggestions)")


    while True:

        print("\nListening...")

        text = recognize_speech_from_mic(recognizer, microphone)

        if text is None:

            print("No speech detected.")

            continue

        if text == "[error_api]":

            print("Speech API not reachable. Check internet or use offline recognizer.")

            speak("Sorry, speech service is unreachable.", engine)

            continue


        command = text.lower().strip()

        print("You said:", command)


        # Exit

        if any(w in command for w in ("exit", "quit", "stop", "shutdown assistant", "bye")):

            speak("Goodbye!", engine)

            print("Exiting assistant.")

            break


        # Help

        if "help" in command:

            help_text = ("You can say: open notepad, open calculator, open downloads, search file invoice, "

                         "play music, open website youtube, what's the time, shutdown system (requires confirmation).")

            speak(help_text, engine)

            print(help_text)

            continue


        # Time

        if "time" in command:

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

            speak(f"The time is {now}", engine)

            print("Time:", now)

            continue


        # Open website

        if command.startswith("open website") or command.startswith("open url") or command.startswith("open "):

            # e.g. "open website youtube" or "open youtube"

            parts = command.replace("open website", "").replace("open url", "").replace("open ", "").strip()

            site = parts.split()[0] if parts else None

            if site:

                url = site if site.startswith("http") else f"https://{site}.com"

                webbrowser.open(url)

                speak(f"Opening {site}", engine)

                print("Open URL:", url)

                continue


        # Open app mapping

        if command.startswith("open ") and not command.startswith("open website"):

            # e.g. "open notepad" or "open vscode"

            app = command.replace("open ", "").strip()

            success, msg = open_app(app)

            speak(msg if msg else ("Opened " + app), engine)

            print(msg)

            continue


        # Open folder

        if command.startswith("open folder") or command.startswith("open downloads") or command.startswith("open desktop"):

            folder_name = command.replace("open folder", "").replace("open ", "").strip()

            success, msg = open_folder(folder_name or "downloads")

            speak(msg, engine)

            print(msg)

            continue


        # Search files

        if command.startswith("search file") or command.startswith("find file") or command.startswith("search for file"):

            # e.g. "search file invoice 2024"

            query = command.split("file", 1)[-1].strip()

            if not query:

                speak("Please say the file name to search for.", engine)

                continue

            speak(f"Searching for files that match {query}", engine)

            print("Searching for:", query)

            results = search_files(query)

            if not results:

                speak("No files found.", engine)

                print("No results.")

            else:

                speak(f"I found {len(results)} files. First one is {os.path.basename(results[0])}", engine)

                print("\n".join(results[:10]))

            continue


        # Play music

        if "music" in command or command.startswith("play music"):

            ok, msg = play_random_music()

            speak(msg, engine) if ok else speak("Could not play music.", engine)

            print(msg)

            continue


        # Shutdown system (dangerous) — confirm first

        if "shutdown" in command or "restart system" in command:

            speak("You asked to perform a system operation. This requires confirmation.", engine)

            confirmed = confirm_action(recognizer, microphone, engine,

                                       prompt="Please say yes to confirm shutting down the system.")

            if confirmed:

                speak("Performing the operation now.", engine)

                print("Confirmed. Executing shutdown/restart.")

                if "shutdown" in command:

                    if os.name == "nt":

                        subprocess.Popen("shutdown /s /t 5", shell=True)

                    else:

                        subprocess.Popen("sudo shutdown -h now", shell=True)

                else:

                    # restart

                    if os.name == "nt":

                        subprocess.Popen("shutdown /r /t 5", shell=True)

                    else:

                        subprocess.Popen("sudo reboot", shell=True)

            else:

                speak("Operation cancelled.", engine)

            continue


        # Search web (fallback)

        if command.startswith("search ") or command.startswith("google "):

            query = command.replace("search", "").replace("google", "").strip()

            url = f"https://www.google.com/search?q={query.replace(' ', '+')}"

            webbrowser.open(url)

            speak(f"Searching the web for {query}", engine)

            print("Web search:", query)

            continue


        # Unknown command fallback

        speak("I did not understand that. Say help for suggestions.", engine)

        print("Unhandled command.")


if __name__ == "__main__":

    try:

        main()

    except KeyboardInterrupt:

        print("\nAssistant stopped by user.")

Virtual Phone Dialer

import tkinter as tk

from tkinter import messagebox

import sqlite3

from datetime import datetime


# ------------------ DATABASE ------------------ #


conn = sqlite3.connect('call_history.db')

cursor = conn.cursor()

cursor.execute('''

    CREATE TABLE IF NOT EXISTS calls (

        id INTEGER PRIMARY KEY AUTOINCREMENT,

        number TEXT NOT NULL,

        timestamp TEXT NOT NULL

    )

''')

conn.commit()



# ------------------ MAIN DIALER APP ------------------ #


class PhoneDialer:

    def __init__(self, root):

        self.root = root

        self.root.title("📱 Virtual Phone Dialer")

        self.number_var = tk.StringVar()


        self.create_widgets()


    def create_widgets(self):

        # Entry to show the number

        self.display = tk.Entry(self.root, textvariable=self.number_var, font=('Helvetica', 20), bd=10, justify='right')

        self.display.grid(row=0, column=0, columnspan=3, pady=10)


        # Keypad buttons

        btn_texts = [

            '1', '2', '3',

            '4', '5', '6',

            '7', '8', '9',

            '*', '0', '#'

        ]


        r = 1

        c = 0

        for text in btn_texts:

            tk.Button(self.root, text=text, font=('Helvetica', 18), width=5, height=2,

                      command=lambda t=text: self.append_number(t)).grid(row=r, column=c, padx=5, pady=5)

            c += 1

            if c > 2:

                c = 0

                r += 1


        # Call button

        tk.Button(self.root, text="📞 Call", bg="green", fg="white", font=('Helvetica', 18),

                  command=self.make_call).grid(row=5, column=0, pady=10, padx=5, sticky='we')


        # Clear button

        tk.Button(self.root, text="❌ Clear", bg="orange", fg="black", font=('Helvetica', 18),

                  command=self.clear).grid(row=5, column=1, pady=10, padx=5, sticky='we')


        # History button

        tk.Button(self.root, text="🕒 History", bg="blue", fg="white", font=('Helvetica', 18),

                  command=self.show_history).grid(row=5, column=2, pady=10, padx=5, sticky='we')


    def append_number(self, val):

        current = self.number_var.get()

        self.number_var.set(current + val)


    def clear(self):

        self.number_var.set("")


    def make_call(self):

        number = self.number_var.get()

        if number:

            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

            cursor.execute("INSERT INTO calls (number, timestamp) VALUES (?, ?)", (number, timestamp))

            conn.commit()

            messagebox.showinfo("Calling", f"Calling {number}...\n(Call logged)")

            self.clear()

        else:

            messagebox.showwarning("Empty", "Please enter a number")


    def show_history(self):

        history_win = tk.Toplevel(self.root)

        history_win.title("📜 Call History")


        tk.Label(history_win, text="Number", font=('Helvetica', 14, 'bold')).grid(row=0, column=0, padx=10, pady=5)

        tk.Label(history_win, text="Timestamp", font=('Helvetica', 14, 'bold')).grid(row=0, column=1, padx=10, pady=5)


        cursor.execute("SELECT number, timestamp FROM calls ORDER BY id DESC")

        rows = cursor.fetchall()


        for idx, (number, timestamp) in enumerate(rows):

            tk.Label(history_win, text=number, font=('Helvetica', 12)).grid(row=idx+1, column=0, padx=10, sticky='w')

            tk.Label(history_win, text=timestamp, font=('Helvetica', 12)).grid(row=idx+1, column=1, padx=10, sticky='w')



# ------------------ RUN APP ------------------ #


if __name__ == "__main__":

    root = tk.Tk()

    app = PhoneDialer(root)

    root.mainloop()


Text-to-World Map

pip install geopy folium nltk

import folium
from geopy.geocoders import Nominatim
import nltk
import re

from nltk import word_tokenize, pos_tag, ne_chunk
from nltk.tree import Tree

nltk.download("punkt")
nltk.download("averaged_perceptron_tagger")
nltk.download("maxent_ne_chunker")
nltk.download("words")


def extract_locations(text):
    """
    Extracts named entities (like countries/cities) using NLTK.
    """
    locations = set()
    tokens = word_tokenize(text)
    pos_tags = pos_tag(tokens)
    chunks = ne_chunk(pos_tags)

    for chunk in chunks:
        if isinstance(chunk, Tree) and chunk.label() == "GPE":
            name = " ".join(c[0] for c in chunk.leaves())
            locations.add(name)
    return list(locations)


def geocode_locations(location_names):
    """
    Uses geopy to convert place names into latitude and longitude.
    """
    geolocator = Nominatim(user_agent="world_map_app")
    geo_data = []

    for name in location_names:
        try:
            location = geolocator.geocode(name)
            if location:
                geo_data.append({
                    "name": name,
                    "lat": location.latitude,
                    "lon": location.longitude
                })
        except Exception as e:
            print(f"Geocoding error for {name}: {e}")

    return geo_data


def create_world_map(locations):
    """
    Create a world map using folium with markers on identified locations.
    """
    m = folium.Map(location=[20, 0], zoom_start=2)

    for loc in locations:
        folium.Marker(
            location=[loc["lat"], loc["lon"]],
            popup=loc["name"],
            icon=folium.Icon(color="blue", icon="info-sign")
        ).add_to(m)

    m.save("world_map.html")
    print("✅ Map saved to world_map.html")


# --------- MAIN FUNCTIONALITY ---------

if __name__ == "__main__":
    print("Paste your text below (press Enter twice to end input):")
    lines = []
    while True:
        line = input()
        if line.strip() == "":
            break
        lines.append(line)

    input_text = "\n".join(lines)

    places = extract_locations(input_text)
    print(f"📍 Places Found: {places}")

    coords = geocode_locations(places)
    create_world_map(coords)

Memory Trainer App

pip install playsound


import tkinter as tk
import random
import time
from threading import Thread
from playsound import playsound

# Constants
PATTERN_LENGTH = 5
DELAY_SECONDS = 3

class MemoryTrainer:
    def __init__(self, root):
        self.root = root
        self.root.title("🧠 Memory Trainer")
        self.root.geometry("400x300")
        self.pattern = []

        self.label = tk.Label(root, text="Click Start to Begin", font=("Arial", 16))
        self.label.pack(pady=30)

        self.start_button = tk.Button(root, text="Start", command=self.start_game, font=("Arial", 14))
        self.start_button.pack()

        self.input_entry = tk.Entry(root, font=("Arial", 14))
        self.submit_button = tk.Button(root, text="Submit", command=self.check_answer, font=("Arial", 12))

        self.feedback = tk.Label(root, text="", font=("Arial", 14), fg="blue")
        self.feedback.pack(pady=10)

    def start_game(self):
        self.pattern = [random.randint(0, 9) for _ in range(PATTERN_LENGTH)]
        self.label.config(text=f"Memorize: {' '.join(map(str, self.pattern))}")
        self.feedback.config(text="")
        self.start_button.config(state=tk.DISABLED)
        self.root.after(DELAY_SECONDS * 1000, self.show_input)

        # Optional sound cue
        Thread(target=lambda: playsound("ding.mp3")).start()  # Replace with a valid sound path

    def show_input(self):
        self.label.config(text="Now enter the pattern:")
        self.input_entry.pack()
        self.submit_button.pack()

    def check_answer(self):
        user_input = self.input_entry.get().strip().split()
        try:
            user_pattern = list(map(int, user_input))
            if user_pattern == self.pattern:
                self.feedback.config(text="✅ Correct!", fg="green")
            else:
                self.feedback.config(text=f"❌ Wrong! Pattern was: {' '.join(map(str, self.pattern))}", fg="red")
        except ValueError:
            self.feedback.config(text="⚠️ Please enter valid numbers.", fg="orange")

        self.input_entry.delete(0, tk.END)
        self.start_button.config(state=tk.NORMAL)
        self.input_entry.pack_forget()
        self.submit_button.pack_forget()

if __name__ == "__main__":
    root = tk.Tk()
    app = MemoryTrainer(root)
    root.mainloop()

Job Description Keyword Extractor

pip install pymupdf nltk wordcloud

import nltk
nltk.download('punkt')
nltk.download('stopwords')


import fitz  # PyMuPDF
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from wordcloud import WordCloud
import tkinter as tk
from tkinter import filedialog
import matplotlib.pyplot as plt
import string

def extract_text_from_pdf(pdf_path):
    doc = fitz.open(pdf_path)
    text = ""
    for page in doc:
        text += page.get_text()
    return text

def clean_and_tokenize(text):
    # Lowercase, remove punctuation
    text = text.lower().translate(str.maketrans("", "", string.punctuation))
    tokens = word_tokenize(text)

    # Remove stopwords & short words
    stop_words = set(stopwords.words("english"))
    keywords = [word for word in tokens if word not in stop_words and len(word) > 2]
    return keywords

def generate_wordcloud(keywords):
    word_freq = nltk.FreqDist(keywords)
    wordcloud = WordCloud(width=800, height=400, background_color='white').generate_from_frequencies(word_freq)

    plt.figure(figsize=(10, 5))
    plt.imshow(wordcloud, interpolation="bilinear")
    plt.axis("off")
    plt.title("Top Keywords in Job Description", fontsize=16)
    plt.show()

def main():
    # Open file dialog
    root = tk.Tk()
    root.withdraw()
    file_path = filedialog.askopenfilename(title="Select Job Description PDF", filetypes=[("PDF Files", "*.pdf")])

    if not file_path:
        print("No file selected.")
        return

    print("Processing...")
    text = extract_text_from_pdf(file_path)
    keywords = clean_and_tokenize(text)
    generate_wordcloud(keywords)

    print("\nTop 20 Keywords:")
    for word, freq in nltk.FreqDist(keywords).most_common(20):
        print(f"{word} - {freq}")

if __name__ == "__main__":
    main()

Custom Retro Snake Game with Skins

import pygame

import tkinter as tk

from tkinter import filedialog, simpledialog

from PIL import Image

import os

import random

import sys


# === Constants ===

TILE_SIZE = 20

DEFAULT_GRID = 20

FPS = 10


# === Globals (updated via GUI) ===

snake_head_img_path = "assets/default_head.png"

snake_body_img_path = "assets/default_body.png"

GRID_SIZE = DEFAULT_GRID



def load_skin(path, size):

    img = Image.open(path).resize((size, size)).convert("RGBA")

    return pygame.image.fromstring(img.tobytes(), img.size, img.mode)



def ask_user_inputs():

    global snake_head_img_path, snake_body_img_path, GRID_SIZE


    root = tk.Tk()

    root.withdraw()


    if filedialog.askyesno("Snake Skin", "Do you want to upload custom snake head image?"):

        snake_head_img_path = filedialog.askopenfilename(title="Select Head Image")


    if filedialog.askyesno("Snake Skin", "Do you want to upload custom snake body image?"):

        snake_body_img_path = filedialog.askopenfilename(title="Select Body Image")


    try:

        GRID_SIZE = int(simpledialog.askstring("Grid Size", "Enter grid size (e.g., 20 for 20x20):") or DEFAULT_GRID)

    except:

        GRID_SIZE = DEFAULT_GRID



def draw_grid(screen, color=(40, 40, 40)):

    for x in range(0, GRID_SIZE * TILE_SIZE, TILE_SIZE):

        for y in range(0, GRID_SIZE * TILE_SIZE, TILE_SIZE):

            rect = pygame.Rect(x, y, TILE_SIZE, TILE_SIZE)

            pygame.draw.rect(screen, color, rect, 1)



class Snake:

    def __init__(self):

        self.body = [(5, 5), (4, 5), (3, 5)]

        self.direction = (1, 0)

        self.grow = False


    def move(self):

        head = self.body[0]

        new_head = (head[0] + self.direction[0], head[1] + self.direction[1])

        self.body.insert(0, new_head)

        if not self.grow:

            self.body.pop()

        else:

            self.grow = False


    def change_direction(self, new_dir):

        # Prevent reversing

        if (new_dir[0] * -1, new_dir[1] * -1) != self.direction:

            self.direction = new_dir


    def draw(self, screen, head_img, body_img):

        for i, segment in enumerate(self.body):

            x, y = segment[0] * TILE_SIZE, segment[1] * TILE_SIZE

            if i == 0:

                screen.blit(head_img, (x, y))

            else:

                screen.blit(body_img, (x, y))


    def check_collision(self):

        head = self.body[0]

        return (

            head in self.body[1:] or

            head[0] < 0 or head[1] < 0 or

            head[0] >= GRID_SIZE or head[1] >= GRID_SIZE

        )



def generate_food(snake):

    while True:

        pos = (random.randint(0, GRID_SIZE - 1), random.randint(0, GRID_SIZE - 1))

        if pos not in snake.body:

            return pos



def main():

    ask_user_inputs()


    pygame.init()

    screen = pygame.display.set_mode((GRID_SIZE * TILE_SIZE, GRID_SIZE * TILE_SIZE))

    pygame.display.set_caption("🐍 Custom Snake Game")

    clock = pygame.time.Clock()


    head_img = load_skin(snake_head_img_path, TILE_SIZE)

    body_img = load_skin(snake_body_img_path, TILE_SIZE)


    snake = Snake()

    food = generate_food(snake)


    running = True

    while running:

        clock.tick(FPS)

        screen.fill((0, 0, 0))

        draw_grid(screen)


        for event in pygame.event.get():

            if event.type == pygame.QUIT:

                running = False

            elif event.type == pygame.KEYDOWN:

                if event.key == pygame.K_UP:

                    snake.change_direction((0, -1))

                elif event.key == pygame.K_DOWN:

                    snake.change_direction((0, 1))

                elif event.key == pygame.K_LEFT:

                    snake.change_direction((-1, 0))

                elif event.key == pygame.K_RIGHT:

                    snake.change_direction((1, 0))


        snake.move()


        if snake.body[0] == food:

            snake.grow = True

            food = generate_food(snake)


        if snake.check_collision():

            print("Game Over!")

            pygame.quit()

            sys.exit()


        snake.draw(screen, head_img, body_img)

        fx, fy = food[0] * TILE_SIZE, food[1] * TILE_SIZE

        pygame.draw.rect(screen, (255, 0, 0), (fx, fy, TILE_SIZE, TILE_SIZE))


        pygame.display.flip()



if __name__ == "__main__":

    main()


Telegram Bot File Vault

 pip install python-telegram-bot==13.15


import os
import sqlite3
import uuid
import logging
from telegram import Update, File
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, CallbackContext

# === Config ===
BOT_TOKEN = 'YOUR_BOT_TOKEN_HERE'
FILES_DIR = "files"
os.makedirs(FILES_DIR, exist_ok=True)

# === Logger ===
logging.basicConfig(level=logging.INFO)

# === Database ===
conn = sqlite3.connect("vault.db", check_same_thread=False)
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS files (
    id TEXT PRIMARY KEY,
    user_id INTEGER,
    file_name TEXT,
    file_path TEXT,
    tags TEXT
)
''')
conn.commit()

# === Command Handlers ===

def start(update: Update, context: CallbackContext):
    update.message.reply_text("📁 Welcome to File Vault Bot!\nSend me a file and add tags in the caption.")

def handle_file(update: Update, context: CallbackContext):
    file = update.message.document or update.message.photo[-1] if update.message.photo else None
    caption = update.message.caption or ""
    tags = caption.strip() if caption else "untagged"
    
    if not file:
        update.message.reply_text("❌ Unsupported file type.")
        return

    file_id = str(uuid.uuid4())
    file_name = file.file_name if hasattr(file, 'file_name') else f"{file_id}.jpg"
    file_path = os.path.join(FILES_DIR, file_name)

    telegram_file: File = context.bot.get_file(file.file_id)
    telegram_file.download(file_path)

    cursor.execute("INSERT INTO files VALUES (?, ?, ?, ?, ?)",
                   (file_id, update.message.from_user.id, file_name, file_path, tags))
    conn.commit()

    update.message.reply_text(f"✅ File saved with ID: {file_id} and tags: {tags}")

def get_file(update: Update, context: CallbackContext):
    if not context.args:
        update.message.reply_text("Usage: /get filename")
        return

    file_name = " ".join(context.args)
    cursor.execute("SELECT file_path FROM files WHERE file_name=?", (file_name,))
    result = cursor.fetchone()

    if result:
        update.message.reply_document(open(result[0], "rb"))
    else:
        update.message.reply_text("❌ File not found.")

def search_by_tag(update: Update, context: CallbackContext):
    if not context.args:
        update.message.reply_text("Usage: /search tag")
        return

    tag = " ".join(context.args)
    cursor.execute("SELECT file_name, tags FROM files")
    results = cursor.fetchall()

    found = [name for name, tags in results if tag.lower() in tags.lower()]
    if found:
        update.message.reply_text("🔍 Matching files:\n" + "\n".join(found))
    else:
        update.message.reply_text("❌ No matching files.")

# === Main Bot ===

def main():
    updater = Updater(BOT_TOKEN)
    dp = updater.dispatcher

    dp.add_handler(CommandHandler("start", start))
    dp.add_handler(CommandHandler("get", get_file))
    dp.add_handler(CommandHandler("search", search_by_tag))
    dp.add_handler(MessageHandler(Filters.document | Filters.photo, handle_file))

    updater.start_polling()
    print("Bot started.")
    updater.idle()

if __name__ == '__main__':
    main()

WhatsApp Chat Analyzer

pip install pandas matplotlib emoji


import re

import emoji

import pandas as pd

import matplotlib.pyplot as plt

from collections import Counter


# Define anger and happy keywords

anger_keywords = ['angry', 'hate', 'stupid', 'idiot', 'mad', 'annoy', 'fight']

happy_keywords = ['happy', 'love', 'joy', 'awesome', 'great', '😊', '😁', '😍']


def extract_chat_data(chat_file):

    with open(chat_file, 'r', encoding='utf-8') as f:

        lines = f.readlines()


    chat_data = []

    for line in lines:

        # Match typical WhatsApp line format

        match = re.match(r'^(\d{1,2}/\d{1,2}/\d{2,4}),\s(\d{1,2}:\d{2})\s[-–]\s(.+?):\s(.+)', line)

        if match:

            date, time, sender, message = match.groups()

            chat_data.append([date, time, sender, message])

    return pd.DataFrame(chat_data, columns=['Date', 'Time', 'Sender', 'Message'])


def count_emojis(text):

    return [char for char in text if char in emoji.EMOJI_DATA]


def analyze_emojis(df):

    emoji_counter = Counter()

    sender_emoji = {}


    for _, row in df.iterrows():

        emojis = count_emojis(row['Message'])

        emoji_counter.update(emojis)

        sender = row['Sender']

        if sender not in sender_emoji:

            sender_emoji[sender] = Counter()

        sender_emoji[sender].update(emojis)

    

    return emoji_counter.most_common(10), sender_emoji


def analyze_mood(df):

    mood_scores = []

    for _, row in df.iterrows():

        message = row['Message'].lower()

        mood = 0

        mood += sum(word in message for word in happy_keywords)

        mood -= sum(word in message for word in anger_keywords)

        mood_scores.append(mood)

    df['MoodScore'] = mood_scores

    return df


def plot_top_emoji_users(sender_emoji):

    emoji_counts = {sender: sum(emojis.values()) for sender, emojis in sender_emoji.items()}

    users = list(emoji_counts.keys())

    counts = list(emoji_counts.values())


    plt.figure(figsize=(8, 4))

    plt.bar(users, counts, color='teal')

    plt.title("Emoji Usage by User")

    plt.ylabel("Total Emojis Used")

    plt.xticks(rotation=45)

    plt.tight_layout()

    plt.show()


def plot_mood_over_time(df):

    mood_by_day = df.groupby("Date")["MoodScore"].sum()

    plt.figure(figsize=(8, 4))

    mood_by_day.plot(kind="line", marker="o", color="purple")

    plt.title("Mood Trend Over Time")

    plt.xlabel("Date")

    plt.ylabel("Mood Score")

    plt.xticks(rotation=45)

    plt.tight_layout()

    plt.show()


if __name__ == "__main__":

    chat_file = "chat.txt"  # exported WhatsApp chat file

    df = extract_chat_data(chat_file)


    df = analyze_mood(df)

    top_emojis, sender_emoji = analyze_emojis(df)


    print("\n🔝 Top Emojis Used:")

    for emo, count in top_emojis:

        print(f"{emo}: {count}")


    print("\n🙋‍♂️ Emoji Usage by Users:")

    for sender, emojis in sender_emoji.items():

        print(f"{sender}: {sum(emojis.values())} emojis")


    plot_top_emoji_users(sender_emoji)

    plot_mood_over_time(df)

 

File Compression Tool

pip install pyminizip

import tkinter as tk
from tkinter import filedialog, messagebox
import os
import zipfile
import pyminizip

class FileCompressorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("File Compression Tool 🗜️")
        self.root.geometry("450x300")
        self.files = []

        self.label = tk.Label(root, text="Drag and Drop Files or Use 'Browse'", font=("Helvetica", 12))
        self.label.pack(pady=10)

        self.file_listbox = tk.Listbox(root, width=50, height=8)
        self.file_listbox.pack()

        self.browse_button = tk.Button(root, text="Browse Files", command=self.browse_files)
        self.browse_button.pack(pady=5)

        self.password_label = tk.Label(root, text="Password (optional):")
        self.password_label.pack()
        self.password_entry = tk.Entry(root, show="*")
        self.password_entry.pack(pady=2)

        self.compress_button = tk.Button(root, text="Compress to ZIP", command=self.compress_files)
        self.compress_button.pack(pady=10)

    def browse_files(self):
        paths = filedialog.askopenfilenames()
        for path in paths:
            if path not in self.files:
                self.files.append(path)
                self.file_listbox.insert(tk.END, path)

    def compress_files(self):
        if not self.files:
            messagebox.showerror("No Files", "Please select files to compress.")
            return

        zip_path = filedialog.asksaveasfilename(defaultextension=".zip", filetypes=[("ZIP files", "*.zip")])
        if not zip_path:
            return

        password = self.password_entry.get()

        try:
            if password:
                # Use pyminizip for password protection
                compression_level = 5
                pyminizip.compress_multiple(self.files, [], zip_path, password, compression_level)
            else:
                # Use zipfile for normal compression
                with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
                    for file in self.files:
                        arcname = os.path.basename(file)
                        zipf.write(file, arcname)

            messagebox.showinfo("Success", f"Files compressed successfully to:\n{zip_path}")
        except Exception as e:
            messagebox.showerror("Error", f"Compression failed:\n{str(e)}")

if __name__ == "__main__":
    root = tk.Tk()
    app = FileCompressorApp(root)
    root.mainloop()

Live Webcam Effects App

pip install opencv-python dlib numpy imutils


live_webcam_filters.py


import cv2
import dlib
import numpy as np

# Load face detector and landmark predictor
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

# Load overlay images (with transparency)
glasses = cv2.imread("filters/glasses.png", cv2.IMREAD_UNCHANGED)
mustache = cv2.imread("filters/mustache.png", cv2.IMREAD_UNCHANGED)
dog_ears = cv2.imread("filters/dog_ears.png", cv2.IMREAD_UNCHANGED)

def overlay_transparent(background, overlay, x, y, scale=1):
    """Overlay PNG with alpha channel"""
    overlay = cv2.resize(overlay, (0, 0), fx=scale, fy=scale)
    h, w, _ = overlay.shape

    if x + w > background.shape[1] or y + h > background.shape[0]:
        return background

    alpha_overlay = overlay[:, :, 3] / 255.0
    for c in range(0, 3):
        background[y:y+h, x:x+w, c] = background[y:y+h, x:x+w, c] * (1 - alpha_overlay) + overlay[:, :, c] * alpha_overlay
    return background

cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()
    if not ret:
        break

    # Flip frame for mirror effect
    frame = cv2.flip(frame, 1)
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    faces = detector(gray)

    for face in faces:
        landmarks = predictor(gray, face)

        # Coordinates for glasses
        left_eye = (landmarks.part(36).x, landmarks.part(36).y)
        right_eye = (landmarks.part(45).x, landmarks.part(45).y)
        eye_center = ((left_eye[0] + right_eye[0]) // 2, (left_eye[1] + right_eye[1]) // 2)
        eye_width = int(1.5 * abs(right_eye[0] - left_eye[0]))
        glasses_resized = cv2.resize(glasses, (eye_width, int(glasses.shape[0] * eye_width / glasses.shape[1])))
        frame = overlay_transparent(frame, glasses_resized, eye_center[0] - eye_width // 2, eye_center[1] - 25)

        # Coordinates for mustache
        nose = (landmarks.part(33).x, landmarks.part(33).y)
        mustache_resized = cv2.resize(mustache, (eye_width, int(mustache.shape[0] * eye_width / mustache.shape[1])))
        frame = overlay_transparent(frame, mustache_resized, nose[0] - eye_width // 2, nose[1] + 10)

        # Dog ears
        top_head = (landmarks.part(27).x, landmarks.part(27).y - 100)
        ears_resized = cv2.resize(dog_ears, (eye_width * 2, int(dog_ears.shape[0] * (eye_width * 2) / dog_ears.shape[1])))
        frame = overlay_transparent(frame, ears_resized, top_head[0] - eye_width, top_head[1])

    cv2.imshow("Live Webcam Filters 🧑‍🎤", frame)
    if cv2.waitKey(1) == 27:
        break  # ESC to quit

cap.release()
cv2.destroyAllWindows()

Puzzle Image Generator

 pip install pillow

puzzle.py

import tkinter as tk
from PIL import Image, ImageTk
import random

GRID_SIZE = 3  # 3x3 puzzle
TILE_SIZE = 100  # Pixel size for each tile
IMAGE_PATH = "sample.jpg"  # Replace with your image path


class PuzzleGame:
    def __init__(self, root):
        self.root = root
        self.root.title("🧩 Image Puzzle Game")

        self.image = Image.open(IMAGE_PATH)
        self.image = self.image.resize((TILE_SIZE * GRID_SIZE, TILE_SIZE * GRID_SIZE))
        self.tiles = []
        self.tile_images = []
        self.buttons = []

        self.empty_pos = (GRID_SIZE - 1, GRID_SIZE - 1)

        self.create_tiles()
        self.shuffle_tiles()
        self.draw_tiles()

    def create_tiles(self):
        for row in range(GRID_SIZE):
            row_tiles = []
            for col in range(GRID_SIZE):
                if (row, col) == self.empty_pos:
                    row_tiles.append(None)
                    continue
                left = col * TILE_SIZE
                upper = row * TILE_SIZE
                right = left + TILE_SIZE
                lower = upper + TILE_SIZE
                tile = self.image.crop((left, upper, right, lower))
                tk_img = ImageTk.PhotoImage(tile)
                self.tile_images.append(tk_img)
                row_tiles.append(tk_img)
            self.tiles.append(row_tiles)

    def shuffle_tiles(self):
        # Flatten and shuffle the tiles
        flat_tiles = [tile for row in self.tiles for tile in row if tile is not None]
        random.shuffle(flat_tiles)

        idx = 0
        for row in range(GRID_SIZE):
            for col in range(GRID_SIZE):
                if (row, col) == self.empty_pos:
                    continue
                self.tiles[row][col] = flat_tiles[idx]
                idx += 1

    def draw_tiles(self):
        for row in range(GRID_SIZE):
            for col in range(GRID_SIZE):
                btn = tk.Button(self.root, image=self.tiles[row][col],
                                command=lambda r=row, c=col: self.move_tile(r, c))
                btn.grid(row=row, column=col)
                self.buttons.append(btn)

    def move_tile(self, r, c):
        er, ec = self.empty_pos
        if abs(er - r) + abs(ec - c) == 1:  # Must be adjacent
            # Swap tiles
            self.tiles[er][ec], self.tiles[r][c] = self.tiles[r][c], self.tiles[er][ec]
            self.empty_pos = (r, c)
            self.update_tiles()

    def update_tiles(self):
        for row in range(GRID_SIZE):
            for col in range(GRID_SIZE):
                btn = self.root.grid_slaves(row=row, column=col)[0]
                img = self.tiles[row][col]
                if img:
                    btn.config(image=img)
                else:
                    btn.config(image='', text='')


if __name__ == "__main__":
    root = tk.Tk()
    game = PuzzleGame(root)
    root.mainloop()



Command Palette GUI app

pip install fuzzywuzzy python-Levenshtein

import tkinter as tk
from tkinter import messagebox
import subprocess
import os
from fuzzywuzzy import process

# Sample commands/apps to match
COMMANDS = {
    "Open Notepad": "notepad",
    "Open Calculator": "calc",
    "Command Prompt": "cmd",
    "Open Task Manager": "taskmgr",
    "Open Paint": "mspaint",
    "Open Explorer": "explorer",
    "Shutdown": "shutdown /s /t 1",
    "Restart": "shutdown /r /t 1",
    "Open Downloads": os.path.expanduser("~/Downloads"),
    "Open VSCode": r"C:\Users\ASUS\AppData\Local\Programs\Microsoft VS Code\Code.exe",  # Modify as needed
}

class CommandPaletteApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Command Palette")
        self.root.geometry("500x300")
        self.root.configure(bg="#1e1e1e")

        self.entry = tk.Entry(self.root, font=("Segoe UI", 16), bg="#252526", fg="white", insertbackground="white")
        self.entry.pack(pady=20, padx=20, fill="x")
        self.entry.bind("<KeyRelease>", self.update_suggestions)
        self.entry.bind("<Return>", self.execute_selection)

        self.listbox = tk.Listbox(self.root, font=("Segoe UI", 14), bg="#1e1e1e", fg="white", selectbackground="#007acc")
        self.listbox.pack(padx=20, fill="both", expand=True)
        self.listbox.bind("<Double-Button-1>", self.execute_selection)

        self.commands = list(COMMANDS.keys())
        self.update_list(self.commands)

    def update_suggestions(self, event=None):
        typed = self.entry.get()
        if typed == "":
            self.update_list(self.commands)
        else:
            results = process.extract(typed, self.commands, limit=8)
            self.update_list([r[0] for r in results if r[1] > 40])

    def update_list(self, data):
        self.listbox.delete(0, tk.END)
        for item in data:
            self.listbox.insert(tk.END, item)

    def execute_selection(self, event=None):
        selection = self.listbox.get(tk.ACTIVE)
        if selection in COMMANDS:
            command = COMMANDS[selection]
            try:
                if os.path.isfile(command):
                    subprocess.Popen(command)
                elif os.path.isdir(command):
                    os.startfile(command)
                else:
                    subprocess.Popen(command, shell=True)
            except Exception as e:
                messagebox.showerror("Error", f"Failed to execute: {e}")
        else:
            messagebox.showinfo("Not Found", "No matching command to run.")

if __name__ == "__main__":
    root = tk.Tk()
    app = CommandPaletteApp(root)
    root.mainloop()

Social Media Content Scheduler

Install Dependencies

pip install streamlit schedule selenium

Project Structure

social_scheduler/
├── scheduler.py
├── social_scheduler_app.py
├── database.db  (auto-created)


Streamlit App – social_scheduler_app.py


import streamlit as st
import sqlite3
import datetime

# === DB Setup ===
conn = sqlite3.connect('database.db', check_same_thread=False)
c = conn.cursor()

c.execute('''CREATE TABLE IF NOT EXISTS posts
             (id INTEGER PRIMARY KEY AUTOINCREMENT,
              platform TEXT, 
              content TEXT, 
              post_time TEXT)''')
conn.commit()

# === Functions ===
def add_post(platform, content, post_time):
    c.execute("INSERT INTO posts (platform, content, post_time) VALUES (?, ?, ?)", 
              (platform, content, post_time))
    conn.commit()

def get_all_posts():
    c.execute("SELECT * FROM posts ORDER BY post_time")
    return c.fetchall()

def delete_post(post_id):
    c.execute("DELETE FROM posts WHERE id = ?", (post_id,))
    conn.commit()

# === Streamlit UI ===
st.title("📅 Social Media Content Scheduler")

with st.form("post_form"):
    platform = st.selectbox("Platform", ["Twitter", "LinkedIn", "Facebook", "Instagram"])
    content = st.text_area("Post Content", max_chars=500)
    post_time = st.time_input("Post Time (24H)")
    submit = st.form_submit_button("➕ Schedule Post")

    if submit:
        post_datetime = datetime.datetime.combine(datetime.date.today(), post_time)
        add_post(platform, content, post_datetime.strftime("%Y-%m-%d %H:%M:%S"))
        st.success("✅ Post scheduled!")

st.subheader("📋 Scheduled Posts")
posts = get_all_posts()
for post in posts:
    st.markdown(f"**[{post[1]}]** {post[2]}  \n⏰ {post[3]}")
    if st.button(f"❌ Delete", key=post[0]):
        delete_post(post[0])
        st.experimental_rerun()

Background Scheduler – scheduler.py

import sqlite3
import schedule
import time
import datetime
from selenium import webdriver
from selenium.webdriver.common.by import By

# === Dummy Post Logic ===
def post_to_platform(platform, content):
    print(f"🟢 Posting to {platform}: {content}")
    # You can replace below with Selenium logic to auto-login and post

# === Actual Scheduler ===
def check_and_post():
    conn = sqlite3.connect('database.db')
    c = conn.cursor()

    now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    c.execute("SELECT * FROM posts WHERE post_time <= ?", (now,))
    posts_due = c.fetchall()

    for post in posts_due:
        post_to_platform(post[1], post[2])
        c.execute("DELETE FROM posts WHERE id = ?", (post[0],))

    conn.commit()
    conn.close()

# === Start Scheduler ===
schedule.every(1).minutes.do(check_and_post)

print("⏳ Scheduler running every minute...")
while True:
    schedule.run_pending()
    time.sleep(30)

How to Run It

  1. Start Streamlit App:

        streamlit run social_scheduler_app.py
   
   2. In another terminal, run the scheduler:

        python scheduler.py

Travel Planner with Map Integration

import tkinter as tk

from tkinter import messagebox

import requests

import folium

from geopy.geocoders import Nominatim

import webbrowser


# === API KEY ===

WEATHER_API_KEY = "YOUR_OPENWEATHER_API_KEY"


# === Core Functions ===


def get_coordinates(place):

    geolocator = Nominatim(user_agent="travel_planner")

    location = geolocator.geocode(place)

    if location:

        return (location.latitude, location.longitude)

    return None


def get_weather(city):

    url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={WEATHER_API_KEY}&units=metric"

    response = requests.get(url)

    data = response.json()

    if data.get("main"):

        temp = data["main"]["temp"]

        weather = data["weather"][0]["description"]

        return f"{temp}°C, {weather}"

    return "Not found"


def estimate_cost(destinations):

    return len(destinations) * 1500  # ₹1500 per destination (sample logic)


def show_map(destinations):

    if not destinations:

        messagebox.showerror("Error", "No destinations added!")

        return


    m = folium.Map(location=[20.5937, 78.9629], zoom_start=5)


    for city in destinations:

        coord = get_coordinates(city)

        if coord:

            weather = get_weather(city)

            folium.Marker(coord, tooltip=f"{city}: {weather}").add_to(m)

        else:

            messagebox.showwarning("Warning", f"Could not locate {city}")


    # Optional: Add route lines

    coords = [get_coordinates(city) for city in destinations if get_coordinates(city)]

    if len(coords) > 1:

        folium.PolyLine(coords, color="blue", weight=2.5).add_to(m)


    m.save("travel_map.html")

    webbrowser.open("travel_map.html")


# === GUI ===


destinations = []


def add_destination():

    city = city_entry.get()

    if city:

        destinations.append(city)

        city_listbox.insert(tk.END, city)

        city_entry.delete(0, tk.END)


def clear_destinations():

    destinations.clear()

    city_listbox.delete(0, tk.END)


def plan_trip():

    if not destinations:

        messagebox.showwarning("Empty", "Add destinations first.")

        return

    cost = estimate_cost(destinations)

    show_map(destinations)

    messagebox.showinfo("Trip Estimate", f"🗺️ Trip planned for {len(destinations)} places.\nEstimated Cost: ₹{cost}")


root = tk.Tk()

root.title("🧳 Travel Planner")

root.geometry("400x450")


tk.Label(root, text="Enter Destination City").pack(pady=5)

city_entry = tk.Entry(root, width=30)

city_entry.pack(pady=5)


tk.Button(root, text="➕ Add", command=add_destination).pack()

city_listbox = tk.Listbox(root, width=40)

city_listbox.pack(pady=10)


tk.Button(root, text="🗺️ Plan Trip", command=plan_trip).pack(pady=10)

tk.Button(root, text="❌ Clear All", command=clear_destinations).pack()


root.mainloop()


System Cleanup Scheduler

import os

import shutil

import hashlib

import schedule

import time

from datetime import datetime, timedelta


# === CONFIG ===

TEMP_DIRS = ["temp"]

LOG_DIRS = ["logs"]

DUPLICATE_SCAN_DIRS = ["temp", "logs"]

LOG_EXPIRY_DAYS = 7


# === 1. Delete temp files ===

def clean_temp_folders():

    print("🧹 Cleaning temp folders...")

    for folder in TEMP_DIRS:

        for filename in os.listdir(folder):

            file_path = os.path.join(folder, filename)

            try:

                if os.path.isfile(file_path) or os.path.islink(file_path):

                    os.remove(file_path)

                    print(f"Deleted file: {file_path}")

                elif os.path.isdir(file_path):

                    shutil.rmtree(file_path)

                    print(f"Deleted folder: {file_path}")

            except Exception as e:

                print(f"❌ Failed to delete {file_path}: {e}")


# === 2. Delete old logs ===

def delete_old_logs():

    print("📁 Deleting old logs...")

    for folder in LOG_DIRS:

        for root, dirs, files in os.walk(folder):

            for file in files:

                file_path = os.path.join(root, file)

                try:

                    file_time = datetime.fromtimestamp(os.path.getmtime(file_path))

                    if datetime.now() - file_time > timedelta(days=LOG_EXPIRY_DAYS):

                        os.remove(file_path)

                        print(f"🗑️ Removed old log: {file_path}")

                except Exception as e:

                    print(f"❌ Error checking {file_path}: {e}")


# === 3. Delete duplicate files ===

def delete_duplicates():

    print("🔍 Searching for duplicates...")

    hashes = {}

    for folder in DUPLICATE_SCAN_DIRS:

        for root, _, files in os.walk(folder):

            for file in files:

                path = os.path.join(root, file)

                try:

                    with open(path, 'rb') as f:

                        file_hash = hashlib.md5(f.read()).hexdigest()

                    if file_hash in hashes:

                        os.remove(path)

                        print(f"❌ Duplicate removed: {path}")

                    else:

                        hashes[file_hash] = path

                except Exception as e:

                    print(f"❌ Error reading {path}: {e}")


# === 4. Master cleanup function ===

def run_cleanup():

    print(f"\n🔧 Running system cleanup @ {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")

    clean_temp_folders()

    delete_old_logs()

    delete_duplicates()

    print("✅ Cleanup complete.")


# === 5. Scheduler ===

schedule.every().sunday.at("08:00").do(run_cleanup)


print("🕒 System Cleanup Scheduler started... (Press Ctrl+C to exit)")

run_cleanup()  # Run once on start


while True:

    schedule.run_pending()

    time.sleep(60)


Book Cover & Title Generator

import random

from faker import Faker

from PIL import Image, ImageDraw, ImageFont

import os

import openai


# === CONFIG ===

OUTPUT_FOLDER = "covers"

os.makedirs(OUTPUT_FOLDER, exist_ok=True)

fake = Faker()


# Optional: Set your OpenAI API Key

openai.api_key = "YOUR_API_KEY"  # Replace with your key


# === 1. Generate Book Title ===

def generate_book_title(prompt=None):

    if prompt:

        response = openai.ChatCompletion.create(

            model="gpt-4",

            messages=[{"role": "user", "content": prompt}],

            max_tokens=30

        )

        return response['choices'][0]['message']['content'].strip()

    else:

        adjectives = ["Lost", "Silent", "Hidden", "Broken", "Eternal"]

        nouns = ["Dream", "Kingdom", "Secret", "Shadow", "Memory"]

        return f"The {random.choice(adjectives)} {random.choice(nouns)}"


# === 2. Generate Author Name ===

def generate_author_name():

    return fake.name()


# === 3. Generate Cover Image ===

def generate_cover_image(title, author, background="background.jpg"):

    WIDTH, HEIGHT = 600, 900

    cover = Image.new("RGB", (WIDTH, HEIGHT), "white")


    try:

        bg = Image.open(background).resize((WIDTH, HEIGHT))

        cover.paste(bg)

    except:

        print("⚠️ No background image found. Using plain white.")


    draw = ImageDraw.Draw(cover)


    try:

        title_font = ImageFont.truetype("arial.ttf", 40)

        author_font = ImageFont.truetype("arial.ttf", 30)

    except:

        title_font = ImageFont.load_default()

        author_font = ImageFont.load_default()


    # Draw title

    draw.text((40, HEIGHT // 3), title, font=title_font, fill="black", spacing=2)


    # Draw author

    draw.text((40, HEIGHT // 3 + 100), f"by {author}", font=author_font, fill="darkgray")


    filename = os.path.join(OUTPUT_FOLDER, f"{title[:20].replace(' ', '_')}.png")

    cover.save(filename)

    print(f"✅ Cover saved to: {filename}")


# === MAIN ===

if __name__ == "__main__":

    print("📚 Generating random book cover...")

    # title = generate_book_title("Suggest a fantasy book title")

    title = generate_book_title()

    author = generate_author_name()


    print(f"Title: {title}")

    print(f"Author: {author}")


    generate_cover_image(title, author)


AI Chat Summarizer for WhatsApp

import re

import pandas as pd

import matplotlib.pyplot as plt

from textblob import TextBlob

from collections import Counter

from datetime import datetime

import os


# ========== CONFIG ==========

CHAT_FILE = "chat.txt"

PLOTS_FOLDER = "chat_analysis_plots"

os.makedirs(PLOTS_FOLDER, exist_ok=True)


# ========== 1. Parse WhatsApp Chat ==========

def parse_chat(file_path):

    with open(file_path, 'r', encoding='utf-8') as f:

        raw_text = f.readlines()


    messages = []

    pattern = r'^(\d{1,2}/\d{1,2}/\d{2,4}), (\d{1,2}:\d{2}) (AM|PM|am|pm)? - ([^:]+): (.*)'


    for line in raw_text:

        match = re.match(pattern, line)

        if match:

            date, time, am_pm, sender, message = match.groups()

            dt = datetime.strptime(date + " " + time + (" " + am_pm if am_pm else ""), "%d/%m/%Y %I:%M %p")

            messages.append([dt, sender.strip(), message.strip()])

    

    df = pd.DataFrame(messages, columns=["datetime", "sender", "message"])

    return df


# ========== 2. Sentiment & Stats ==========

def analyze_sentiments(df):

    df['polarity'] = df['message'].apply(lambda x: TextBlob(x).sentiment.polarity)

    df['sentiment'] = df['polarity'].apply(lambda x: 'positive' if x > 0.1 else 'negative' if x < -0.1 else 'neutral')

    return df


def top_senders(df, top_n=5):

    return df['sender'].value_counts().head(top_n)


# ========== 3. Plotting Functions ==========

def plot_message_frequency(df):

    df['date'] = df['datetime'].dt.date

    daily_counts = df.groupby('date').size()


    plt.figure(figsize=(12, 5))

    daily_counts.plot(kind='line', color='teal')

    plt.title("Messages Per Day")

    plt.xlabel("Date")

    plt.ylabel("Number of Messages")

    plt.tight_layout()

    plt.savefig(f"{PLOTS_FOLDER}/messages_per_day.png")

    plt.close()


def plot_sender_activity(df):

    sender_counts = df['sender'].value_counts()

    sender_counts.plot(kind='bar', figsize=(10,5), color='orchid')

    plt.title("Messages by Sender")

    plt.ylabel("Message Count")

    plt.tight_layout()

    plt.savefig(f"{PLOTS_FOLDER}/messages_by_sender.png")

    plt.close()


def plot_sentiment_distribution(df):

    sentiment_counts = df['sentiment'].value_counts()

    sentiment_counts.plot(kind='pie', autopct='%1.1f%%', figsize=(6,6), colors=['lightgreen', 'lightcoral', 'lightgrey'])

    plt.title("Sentiment Distribution")

    plt.tight_layout()

    plt.savefig(f"{PLOTS_FOLDER}/sentiment_distribution.png")

    plt.close()


# ========== 4. Generate Summary ==========

def generate_summary(df):

    summary = []

    summary.append(f"Total messages: {len(df)}")

    summary.append(f"Total participants: {df['sender'].nunique()}")

    summary.append("Top 5 active senders:")

    summary.extend(top_senders(df).to_string().split('\n'))


    sentiment_split = df['sentiment'].value_counts(normalize=True) * 100

    summary.append("\nSentiment Breakdown:")

    summary.extend(sentiment_split.round(2).to_string().split('\n'))


    with open("summary_output.txt", "w") as f:

        f.write("\n".join(summary))

    

    return "\n".join(summary)


# ========== MAIN ==========

if __name__ == "__main__":

    print("📥 Parsing chat...")

    df = parse_chat(CHAT_FILE)


    print("🧠 Analyzing sentiments...")

    df = analyze_sentiments(df)


    print("📊 Generating plots...")

    plot_message_frequency(df)

    plot_sender_activity(df)

    plot_sentiment_distribution(df)


    print("📝 Writing summary...")

    summary_text = generate_summary(df)

    print(summary_text)


    print("\n✅ Done! Plots saved to 'chat_analysis_plots' and summary to 'summary_output.txt'")


Auto Meeting Notes Generator

import os

import re

import pandas as pd

import whisper

from datetime import datetime


# Optional: For GPT-4 summarization

import openai

from dotenv import load_dotenv


load_dotenv()

openai.api_key = os.getenv("OPENAI_API_KEY")


# ========== CONFIG ==========

AUDIO_FOLDER = "audio"

TRANSCRIPT_FOLDER = "transcriptions"

NOTES_FOLDER = "notes_output"


# ========== SETUP ==========

os.makedirs(TRANSCRIPT_FOLDER, exist_ok=True)

os.makedirs(NOTES_FOLDER, exist_ok=True)


# ========== 1. Transcribe Audio ==========

def transcribe_audio(file_path, model_name="base"):

    model = whisper.load_model(model_name)

    result = model.transcribe(file_path)

    

    filename = os.path.basename(file_path).split('.')[0]

    output_path = os.path.join(TRANSCRIPT_FOLDER, f"{filename}.txt")

    

    with open(output_path, "w", encoding="utf-8") as f:

        f.write(result["text"])

    

    return result["text"]


# ========== 2. Extract Action Items ==========

def extract_action_items(text):

    bullet_pattern = r"(?:-|\*|\d\.)\s*(.+)"

    action_keywords = ["should", "need to", "must", "let's", "we will", "assign", "follow up", "due"]


    actions = []

    for line in text.split('\n'):

        line = line.strip()

        if any(keyword in line.lower() for keyword in action_keywords):

            actions.append(line)


    # Fallback: try extracting bullets

    bullets = re.findall(bullet_pattern, text)

    for b in bullets:

        if any(k in b.lower() for k in action_keywords):

            actions.append(b)

    

    return list(set(actions))


# ========== 3. Summarize with GPT (Optional) ==========

def summarize_with_gpt(transcript_text):

    response = openai.ChatCompletion.create(

        model="gpt-4-turbo",

        messages=[

            {"role": "system", "content": "You are an AI assistant that summarizes meeting transcripts."},

            {"role": "user", "content": f"Summarize this meeting:\n\n{transcript_text}"}

        ]

    )

    return response['choices'][0]['message']['content']


# ========== 4. Save Final Notes ==========

def save_notes(transcript, actions, summary=None, filename="meeting_notes"):

    now = datetime.now().strftime("%Y%m%d_%H%M")

    csv_path = os.path.join(NOTES_FOLDER, f"{filename}_{now}.csv")


    df = pd.DataFrame({

        "Section": ["Transcript", "Action Items", "Summary"],

        "Content": [transcript, "\n".join(actions), summary or "Not generated"]

    })

    df.to_csv(csv_path, index=False)

    print(f"[✔] Notes saved to {csv_path}")


# ========== MAIN ==========

def process_meeting(file_path, use_gpt=False):

    print(f"🔊 Transcribing: {file_path}")

    transcript = transcribe_audio(file_path)


    print("✅ Extracting action items...")

    actions = extract_action_items(transcript)


    summary = None

    if use_gpt:

        print("🤖 Summarizing with GPT...")

        summary = summarize_with_gpt(transcript)


    file_name = os.path.basename(file_path).split('.')[0]

    save_notes(transcript, actions, summary, file_name)



# ========== RUN ==========

if __name__ == "__main__":

    audio_files = [f for f in os.listdir(AUDIO_FOLDER) if f.endswith(('.mp3', '.wav'))]


    if not audio_files:

        print("⚠️ No audio files found in /audio folder.")

    else:

        for file in audio_files:

            process_meeting(os.path.join(AUDIO_FOLDER, file), use_gpt=True)