From e7965b947994aefb2082341cf4e1130e9f826b6a Mon Sep 17 00:00:00 2001 From: ai6s10 Date: Fri, 16 Jan 2026 08:56:00 +0000 Subject: [PATCH] Initial commit --- .DS_Store | Bin 0 -> 6148 bytes ...tabase Integration _ Beginner's Guide.html | 1525 +++++++++++++++++ .../css2 | 315 ++++ jokes-bot-v3.0/.DS_Store | Bin 0 -> 6148 bytes jokes-bot-v3.0/README.md | 45 + jokes-bot-v3.0/app.py | 35 + jokes-bot-v3.0/requirements.txt | 1 + 7 files changed, 1921 insertions(+) create mode 100644 .DS_Store create mode 100644 Joke Bot Upgrade_ SQLite Database Integration _ Beginner's Guide.html create mode 100644 Joke Bot Upgrade_ SQLite Database Integration _ Beginner's Guide_files/css2 create mode 100644 jokes-bot-v3.0/.DS_Store create mode 100644 jokes-bot-v3.0/README.md create mode 100644 jokes-bot-v3.0/app.py create mode 100644 jokes-bot-v3.0/requirements.txt diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d375a572a6475f4c21113dc3c1e7a1b506229444 GIT binary patch literal 6148 zcmeHK&rcIU6n+Dhwji*SQjut~NfQ$j1S&){9xSECpe7}>)*?UZZaXb2+nr{2OF<;* zS&#k!-n@JB;>C;p1A6uD$-5qWvojU2TJ>U#*_X_GZ{NK4X6M_TeLDa^QjKx~KmmXd zHjaUQ?0z78oVO0?krqBkyc`Z(038^(h`#s?_ze8(4Dh`>1P^e}ZUcp*`*#OsVG3sS zrc>8Vrla3Wy>1$gJ2Ug1^z;T!^aX?A;6QLAyTzJWS92RqO0(DaRgN)JZ|j<#H)yk{ zL>HOmYKBE^FTf~MbXmV^SY_5sv4&N4yx6Q52!})AqB6d}f92w&nwU)-Ose~dL}GqY zotvLKI0%Qv;?q}GirZ$*VvhyM1iwL^3`%Un6I8mcvFwyg9q*YZ=;~NO&);%1N;{G@ z^19912W3R^77F(doE#h)Rz@PD(a2aN7K=qsjmJ(;Oq?kyqqho*YQd$uZq|56i%R4>*A-gcJT&F@>gW?aGMTMA3Q&Vb@D!fG3wQ-@;T?R0FQkt|$vHAjE|UdvliVhENS+kP2H7M<5#Q5( zf6lfi5lFTWyS^4?HIXf`TKz~|SN|GIr{$gsJ-_t%d>?zW@T)m$to+9@^{tNkI&zD= zW^)M*2=sfO0iOY%fo}}(?}LhsV^U&Ep!ey(&N~7i2GHyY>ijIhV^oPri7kORf;Lti zpZ|{s`By#zJ_G+110;~nrc<~iSz9|6$7`*M?LIax+^;3j3&Bp7V^86wcpRH2IHqz1 XF)6Vn5G^SFkAO#m-}wyuRR+ESX^#P~ literal 0 HcmV?d00001 diff --git a/Joke Bot Upgrade_ SQLite Database Integration _ Beginner's Guide.html b/Joke Bot Upgrade_ SQLite Database Integration _ Beginner's Guide.html new file mode 100644 index 0000000..70c20db --- /dev/null +++ b/Joke Bot Upgrade_ SQLite Database Integration _ Beginner's Guide.html @@ -0,0 +1,1525 @@ + + + + + + Joke Bot Upgrade: SQLite Database Integration | Beginner's Guide + + + + +
+ +
+
+
+

Joke Bot Upgrade

+

From Simple Lists to SQLite Database with User Interaction

+
+ +
+

Goal: Upgrade joke bot with database, user submissions, and ratings

+

Prerequisites: Basic Python knowledge, our existing joke bot

+

Time: 60 minutes to complete upgrade

+

Tools: Python IDLE, Command Line/PowerShell

+
+
+
+ + +
+

How You Earn Points in Class! 🌟

+ +
+
+
🏆
+
+

EARN UP TO 5 POINTS EACH DAY!

+

Track your progress and earn rewards for active participation

+
+
+ +
+
+
+

+2 You Came to Class!

+

Great job! Just by being in class, you get 2 points. Yay!

+
+ +
+
👂
+

+1 You Listened Quietly!

+

You didn't talk when the teacher was talking. Good listening!

+
+ +
+
✏️
+

+1 You Tried Your Work!

+

You didn't finish everything? That's OK! If you tried, you still get a point.

+
+ +
+
🎉
+

+1 You Finished ALL Your Work!

+

Wow! You did every single part — even the last task! You get a big high-five!

+
+
+ +
+

📊 Points Legend:

+

H = You were here! Points depend on what you did.

+

= You were absent → 0 points

+
+
+ +
+ Today's Goal: +

Complete ALL steps of the joke bot upgrade to earn the full 5 points! 🎯

+

Follow along, ask questions, and help your classmates to maximize your learning!

+
+
+ + +
+

Learning Outcomes

+

By the end of this session, you will be able to:

+ +
+
+
+
+

1. Understand SQLite Database Basics

+

Explain what SQLite is and why it's perfect for small Python projects

+
+
+ +
+
+
+

2. Design Database Tables

+

Create tables with proper columns, data types, and relationships

+
+
+ +
+
+
+

3. Implement CRUD Operations

+

Write Python code to Create, Read, Update, and Delete database records

+
+
+ +
+
+
+

4. Integrate Database with Telegram Bot

+

Connect your existing joke bot to a persistent database

+
+
+ +
+
+
+

5. Add User Interaction Features

+

Implement joke submission, rating system, and statistics

+
+
+ +
+
+
+

6. Use Virtual Environments

+

Set up and manage Python dependencies using venv

+
+
+
+ +
+

Why These Skills Matter:

+
+
💼
+
Industry Standard: Databases are used in 99% of real-world applications
+
+ +
+
🚀
+
Career Boost: Database skills are highly sought after by employers
+
+ +
+
🧠
+
Problem Solving: Learn to structure and manage complex data
+
+ +
+
📱
+
App Development: Build apps that remember user data between sessions
+
+
+
+ + +
+

Why Databases Matter

+

Moving beyond simple lists to persistent storage

+ +
+ The Problem with Lists: +

Our current joke bot stores jokes in a Python list:

+
+JOKE_LIST = [ + "Why did the robot go to school? To recharge his brain! 🔋", + "Knock knock!\nWho's there?\nLettuce!\nLettuce who?\nLettuce in!", + "Why don't eggs tell jokes? They'd crack each other up! 🥚" +]
+

Problems:

+

• Jokes are lost when bot restarts

+

• No way for users to add jokes

+

• Can't track ratings or popularity

+

• Hard to search or organize jokes

+
+ +
+

Database Advantages:

+
+
💾
+
Persistence: Data survives bot restarts and crashes
+
+ +
+
👥
+
User Contributions: Community can add content
+
+ +
+
📊
+
Analytics: Track what jokes are popular
+
+ +
+
🔍
+
Searchability: Find jokes by keywords or ratings
+
+ +
+
+
Scalability: Handle thousands of jokes efficiently
+
+
+ +
+

Real-World Examples:

+

Reddit: Database stores posts, votes, comments, user profiles

+

YouTube: Database stores videos, views, likes, subscriptions

+

Banking Apps: Database stores accounts, transactions, balances

+

Games: Database stores player scores, achievements, progress

+
+
+ + +
+

Step-by-Step Setup Guide

+

Before We Start - Check Your Python Installation

+ +
+
+ 1 + Open Command Prompt or PowerShell: +

Press Windows + R, type cmd or powershell, press Enter

+
+ +
+ 2 + Check Python Version: +

Type the following command and press Enter:

+
+
+ +
+ python --version
+ # Should show: Python 3.x.x

+ + # If that doesn't work, try:
+ python3 --version
+ # Or on some systems:
+ py --version +
+ +
+ Troubleshooting: +

If Python is not installed:

+

1. Go to python.org/downloads

+

2. Download Python 3.9 or later

+

3. Run installer (CHECK "Add Python to PATH" option!)

+

4. Restart your computer, then try again

+
+ +
+

Verify Installation:

+

Open Python IDLE to test:

+
+ python
+ # You should see Python interactive shell:
+ Python 3.9.0 (tags/v3.9.0:9cf6752, Oct 5 2020, 15:34:40) ...
+ Type "help", "copyright", "credits" or "license" for more information.
+ >>> print("Hello, World!")
+ Hello, World!
+ >>> exit()
+ # Type exit() to leave Python shell +
+
+
+ + +
+

Create Your Project Folder

+

Organize your files properly from the start

+ +
+
+ 1 + Open PowerShell or Command Prompt: +

Make sure you're not in the Python shell (should see C:\> or PS C:\>)

+
+ +
+ 2 + Navigate to Desktop or Documents: +

Let's create a folder on your Desktop for easy access:

+
+
+ +
+ # Go to Desktop (Windows)
+ cd Desktop

+ + # Create a new folder for your joke bot
+ mkdir joke_bot_upgrade

+ + # Go into your new folder
+ cd joke_bot_upgrade

+ + # Verify you're in the right place
+ pwd
+ # Should show: C:\Users\YourName\Desktop\joke_bot_upgrade
+ # Or use 'dir' to see files (should be empty)
+ dir +
+ +
+ Folder Structure: +
+joke_bot_upgrade/ +├── app.py # Main bot file +├── database.py # SQLite database class +├── joke_bot.db # Database file (auto-created) +├── requirements.txt # Python dependencies +└── venv/ # Virtual environment (we'll create this)
+

Best Practice: Keep all related files in one folder for easy management!

+
+
+ + +
+

Set Up Virtual Environment (venv)

+

Isolate project dependencies for clean development

+ +
+
+ 1 + Why Virtual Environment? +

• Keeps project dependencies separate

+

• Avoids version conflicts between projects

+

• Makes sharing and deployment easier

+
+ +
+ 2 + Create Virtual Environment: +

Make sure you're in your joke_bot_upgrade folder, then run:

+
+
+ +
+ # Create virtual environment named 'venv'
+ python -m venv venv

+ + # Check if venv folder was created
+ dir
+ # You should see a 'venv' folder in the list +
+ +
+ What Happened? +

The venv command created a complete Python installation in the venv folder:

+

• Python interpreter copy

+

• pip (package installer)

+

• Standard library

+

• Empty site-packages for our libraries

+
+ +
+

Activate Virtual Environment:

+

Windows PowerShell:

+
+ venv\Scripts\Activate.ps1
+ # If you get an error about execution policy, run this first:
+ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
+ venv\Scripts\Activate.ps1 +
+ +

Windows Command Prompt:

+
+ venv\Scripts\activate.bat +
+ +

Mac/Linux Terminal:

+
+ source venv/bin/activate +
+ +

Success Indicator: You should see (venv) at the start of your command line!

+
+
+ + +
+

Install Required Libraries

+

Get the Python packages we need for our upgraded bot

+ +
+
+ 1 + First, activate your venv: +

Make sure you see (venv) before the prompt

+
+ +
+ 2 + Install python-telegram-bot: +

This is the main library for creating Telegram bots

+
+
+ +
+ # Install the Telegram bot library (version 20.3)
+ pip install python-telegram-bot==20.3

+ + # Verify installation
+ pip show python-telegram-bot
+ # Should show version 20.3 +
+ +
+ What We're Installing: +

python-telegram-bot: Official library for Telegram Bot API

+

Version 20.3: Specific version that matches our code examples

+

Note: SQLite comes built-in with Python - no need to install!

+
+ +
+

Create Requirements File:

+

Save the list of dependencies for future use:

+
+ pip freeze > requirements.txt

+ + # View the requirements file
+ type requirements.txt
+ # (Mac/Linux: use 'cat requirements.txt' instead of 'type') +
+ +

requirements.txt contents:

+
+python-telegram-bot==20.3
+ +

Why this matters: Anyone can install exact same versions with pip install -r requirements.txt

+
+ +
+
+ 3 + Test Your Setup: +

Open Python IDLE or use Python shell to test imports:

+
+
+ +
+ # Open Python interactive shell
+ python

+ + # Try importing the libraries
+ >>> import sqlite3
+ >>> from telegram import Update
+ >>> from telegram.ext import Application
+ >>> print("All imports successful!")
+ All imports successful!
+ >>> exit() +
+
+ + +
+

Copy Existing Bot Code

+

Start with our working joke bot and upgrade it

+ +
+
+ 1 + Create app.py file: +

In your joke_bot_upgrade folder, create a new file:

+
+
+ +
+ # Using Python IDLE or any text editor:
+ notepad app.py
+ # (Or use VS Code, Sublime Text, or Python's IDLE) +
+ +
+ Our Starting Code: +

Copy this code into app.py - this is our current working bot:

+
from telegram import Update +from telegram.ext import Application, CommandHandler, ContextTypes +import random + +JOKE_LIST = [ + "Why did the robot go to school? To recharge his brain! 🔋", + "Knock knock!\nWho's there?\nLettuce!\nLettuce who?\nLettuce in!", + "Why don't eggs tell jokes? They'd crack each other up! 🥚" +] + +async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): + await update.message.reply_text("Hi! Type /joke for a funny joke! 😄") + +async def send_joke(update: Update, context: ContextTypes.DEFAULT_TYPE): + joke = random.choice(JOKE_LIST) + await update.message.reply_text(joke) + +def main(): + # Using the provided bot token + BOT_TOKEN = "YOUR_BOT_TOKEN_HERE" + + app = Application.builder().token(BOT_TOKEN).build() + app.add_handler(CommandHandler("start", start)) + app.add_handler(CommandHandler("joke", send_joke)) + print("Bot is running... Press Ctrl+C to stop.") + app.run_polling() + +if __name__ == "__main__": + main()
+
+ +
+

Important: Get Your Bot Token

+
+
1
+
Open Telegram: Search for @BotFather
+
+ +
+
2
+
Create New Bot: Type /newbot and follow instructions
+
+ +
+
3
+
Get Token: Copy the token (looks like: 1234567890:ABCdefGHIjklMNOpqrsTUVwxyz)
+
+ +
+
4
+
Replace in Code: Change YOUR_BOT_TOKEN_HERE with your actual token
+
+
+ +
+
+ 2 + Test Current Bot: +

Make sure the basic bot works before we upgrade it:

+
+
+ +
+ # Make sure venv is activated and you're in the right folder
+ (venv) C:\Users\YourName\Desktop\joke_bot_upgrade> python app.py

+ + # Should see:
+ Bot is running... Press Ctrl+C to stop.

+ + # Open Telegram, find your bot, type /start and /joke
+ # Press Ctrl+C to stop the bot when done testing +
+
+ + +
+

What Is SQLite?

+

Serverless, self-contained SQL database perfect for Telegram bots

+ +
+

Why SQLite for Our Joke Bot?

+
+
1
+
No Server Needed: Database lives in a single file
+
+ +
+
2
+
Zero Configuration: Just import and use
+
+ +
+
3
+
Lightweight: Perfect for small to medium applications
+
+ +
+
4
+
SQL Standard: Uses standard SQL commands
+
+ +
+
5
+
Built-in Python: No extra installation needed
+
+
+ +
+ Think of it like this: +

SQLite is like an Excel file that speaks SQL. It's a complete database in a single file that you can include with your application.

+

Perfect for Telegram bots, mobile apps, and desktop applications.

+
+ +
+# SQLite comes built-in with Python! +import sqlite3 + +# Connect to database (creates if doesn't exist) +conn = sqlite3.connect('joke_bot.db') +cursor = conn.cursor() + +# Create a table +cursor.execute('''CREATE TABLE jokes ( + id INTEGER PRIMARY KEY, + text TEXT NOT NULL, + added_by TEXT, + likes INTEGER DEFAULT 0, + dislikes INTEGER DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + )''') + +conn.commit() +conn.close()
+
+ + +
+

Our Upgrade Goals

+

From static list to dynamic, user-powered joke database

+ +
+ Current Limitations: +

1. Jokes are hardcoded in Python list

+

2. No way for users to add new jokes

+

3. No rating system to find the best jokes

+

4. Jokes are lost when bot restarts

+
+ +

New Features We'll Add:

+
+
+
1
+
+ SQLite Database:
+ Store jokes permanently in a database file +
+
+ +
+
2
+
+ User Submissions:
+ /addjoke command for users to submit jokes +
+
+ +
+
3
+
+ Rating System:
+ /like and /dislike commands to rate jokes +
+
+ +
+
4
+
+ Top Jokes:
+ /top command to show most popular jokes +
+
+ +
+
5
+
+ Random with Weight:
+ Better jokes appear more often +
+
+
+
+ + +
+

Step 1: Database Setup (10 minutes)

+

Create the SQLite database and connection functions

+ +
# Create a new file: database.py +# This will handle all database operations + +import sqlite3 +from datetime import datetime + +class JokeDatabase: + def __init__(self, db_name='joke_bot.db'): + self.db_name = db_name + self.init_database() + + def get_connection(self): + """Get a database connection""" + conn = sqlite3.connect(self.db_name) + conn.row_factory = sqlite3.Row # Access columns by name + return conn + + def init_database(self): + """Initialize database tables""" + conn = self.get_connection() + cursor = conn.cursor() + + # Create jokes table + cursor.execute('''CREATE TABLE IF NOT EXISTS jokes ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + joke_text TEXT NOT NULL, + user_id INTEGER, + username TEXT, + likes INTEGER DEFAULT 0, + dislikes INTEGER DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + )''') + + # Create ratings table to track user votes + cursor.execute('''CREATE TABLE IF NOT EXISTS ratings ( + user_id INTEGER, + joke_id INTEGER, + vote INTEGER, -- 1 for like, -1 for dislike + PRIMARY KEY (user_id, joke_id), + FOREIGN KEY (joke_id) REFERENCES jokes(id) + )''') + + conn.commit() + conn.close() + + # Add some default jokes if table is empty + self.add_default_jokes() + + def add_default_jokes(self): + """Add default jokes if database is empty""" + conn = self.get_connection() + cursor = conn.cursor() + + cursor.execute("SELECT COUNT(*) FROM jokes") + count = cursor.fetchone()[0] + + if count == 0: + default_jokes = [ + ("Why did the robot go to school? To recharge his brain! 🔋", 0, "System"), + ("Knock knock!\nWho's there?\nLettuce!\nLettuce who?\nLettuce in!", 0, "System"), + ("Why don't eggs tell jokes? They'd crack each other up! 🥚", 0, "System") + ] + + cursor.executemany('''INSERT INTO jokes (joke_text, user_id, username) + VALUES (?, ?, ?)''', default_jokes) + + conn.commit() + print(f"Added {len(default_jokes)} default jokes to database") + + conn.close()
+ +
+

Database Schema Explained:

+
+
📝
+
jokes table: Stores all jokes with ratings
+
+
+
+
ratings table: Tracks who voted for which joke
+
+
+
🆔
+
Primary keys: Unique IDs for each record
+
+
+
🔗
+
Foreign key: Links ratings to jokes
+
+
+
+ + +
+

Step 2: Database Operations (15 minutes)

+

Add CRUD (Create, Read, Update, Delete) functions

+ +
# Add these methods to the JokeDatabase class + +def add_joke(self, joke_text, user_id, username): + """Add a new joke to the database""" + conn = self.get_connection() + cursor = conn.cursor() + + cursor.execute('''INSERT INTO jokes (joke_text, user_id, username) + VALUES (?, ?, ?)''', (joke_text, user_id, username)) + + joke_id = cursor.lastrowid + conn.commit() + conn.close() + + return joke_id + +def get_random_joke(self): + """Get a random joke, weighted by rating""" + conn = self.get_connection() + cursor = conn.cursor() + + # Weighted random: jokes with higher likes appear more often + cursor.execute('''SELECT * FROM jokes + ORDER BY (likes - dislikes + 5) * RANDOM() DESC + LIMIT 1''') + + joke = cursor.fetchone() + conn.close() + + return dict(joke) if joke else None + +def get_joke_by_id(self, joke_id): + """Get a specific joke by ID""" + conn = self.get_connection() + cursor = conn.cursor() + + cursor.execute("SELECT * FROM jokes WHERE id = ?", (joke_id,)) + joke = cursor.fetchone() + conn.close() + + return dict(joke) if joke else None + +def get_top_jokes(self, limit=5): + """Get top-rated jokes""" + conn = self.get_connection() + cursor = conn.cursor() + + cursor.execute('''SELECT * FROM jokes + ORDER BY (likes - dislikes) DESC, likes DESC + LIMIT ?''', (limit,)) + + jokes = [dict(row) for row in cursor.fetchall()] + conn.close() + + return jokes + +def get_total_jokes(self): + """Get total number of jokes""" + conn = self.get_connection() + cursor = conn.cursor() + + cursor.execute("SELECT COUNT(*) FROM jokes") + count = cursor.fetchone()[0] + conn.close() + + return count
+ +
+

SQL Functions Explained:

+
+
📊
+
Weighted Random: (likes - dislikes + 5) * RANDOM()
+
+
+
⬆️
+
Top Jokes: Sorted by net score (likes - dislikes)
+
+
+
💾
+
Parameterized Queries: Safe from SQL injection
+
+
+
🔄
+
Connection Management: Open/close connections properly
+
+
+
+ + +
+

Step 3: Rating System (15 minutes)

+

Implement like/dislike functionality with vote tracking

+ +
# Add rating methods to JokeDatabase class + +def rate_joke(self, user_id, joke_id, vote): + """ + Rate a joke (like or dislike) + vote: 1 for like, -1 for dislike, 0 to remove rating + """ + conn = self.get_connection() + cursor = conn.cursor() + + # Check if user already voted + cursor.execute('''SELECT vote FROM ratings + WHERE user_id = ? AND joke_id = ?''', (user_id, joke_id)) + + existing_vote = cursor.fetchone() + + if existing_vote: + old_vote = existing_vote[0] + + if vote == 0: + # Remove vote + cursor.execute('''DELETE FROM ratings + WHERE user_id = ? AND joke_id = ?''', (user_id, joke_id)) + + # Update joke counts + if old_vote == 1: + cursor.execute('''UPDATE jokes SET likes = likes - 1 + WHERE id = ?''', (joke_id,)) + elif old_vote == -1: + cursor.execute('''UPDATE jokes SET dislikes = dislikes - 1 + WHERE id = ?''', (joke_id,)) + elif old_vote != vote: + # Change vote + cursor.execute('''UPDATE ratings SET vote = ? + WHERE user_id = ? AND joke_id = ?''', (vote, user_id, joke_id)) + + # Update joke counts (remove old, add new) + if old_vote == 1 and vote == -1: + cursor.execute('''UPDATE jokes + SET likes = likes - 1, dislikes = dislikes + 1 + WHERE id = ?''', (joke_id,)) + elif old_vote == -1 and vote == 1: + cursor.execute('''UPDATE jokes + SET likes = likes + 1, dislikes = dislikes - 1 + WHERE id = ?''', (joke_id,)) + else: + if vote != 0: + # New vote + cursor.execute('''INSERT INTO ratings (user_id, joke_id, vote) + VALUES (?, ?, ?)''', (user_id, joke_id, vote)) + + # Update joke counts + if vote == 1: + cursor.execute('''UPDATE jokes SET likes = likes + 1 + WHERE id = ?''', (joke_id,)) + elif vote == -1: + cursor.execute('''UPDATE jokes SET dislikes = dislikes + 1 + WHERE id = ?''', (joke_id,)) + + conn.commit() + + # Get updated joke info + cursor.execute("SELECT likes, dislikes FROM jokes WHERE id = ?", (joke_id,)) + result = cursor.fetchone() + conn.close() + + return { + 'likes': result[0] if result else 0, + 'dislikes': result[1] else 0 + } + +def get_user_vote(self, user_id, joke_id): + """Get user's vote for a specific joke""" + conn = self.get_connection() + cursor = conn.cursor() + + cursor.execute('''SELECT vote FROM ratings + WHERE user_id = ? AND joke_id = ?''', (user_id, joke_id)) + + result = cursor.fetchone() + conn.close() + + return result[0] if result else 0
+ +
+

Rating Logic:

+
+
1
+
Prevent Double Voting: Users can only vote once per joke
+
+
+
2
+
Change Votes: Users can change their mind
+
+
+
3
+
Remove Votes: Users can remove their rating
+
+
+
4
+
Real-time Updates: Counts update immediately
+
+
+
+ + +
+

Step 4: Telegram Bot Integration (15 minutes)

+

Update app.py to use the database

+ +
# Updated app.py with database integration + +from telegram import Update, InlineKeyboardMarkup, InlineKeyboardButton +from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters, CallbackQueryHandler +from database import JokeDatabase +import random + +# Initialize database +db = JokeDatabase() + +async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): + """Start command handler""" + welcome_text = """🤖 Welcome to Joke Bot 2.0! 🤖 + +Commands: +/joke - Get a random joke +/addjoke - Submit your own joke +/top - See top-rated jokes +/like - Like the last joke +/dislike - Dislike the last joke +/stats - Bot statistics + +Now with database, user submissions, and ratings!""" + + await update.message.reply_text(welcome_text) + +async def send_joke(update: Update, context: ContextTypes.DEFAULT_TYPE): + """Send a random joke from database""" + joke = db.get_random_joke() + + if not joke: + await update.message.reply_text("No jokes in database yet! Use /addjoke to add one.") + return + + # Store joke ID in context for rating + context.user_data['last_joke_id'] = joke['id'] + + # Format joke with rating info + rating_text = f"👍 {joke['likes']} 👎 {joke['dislikes']}" + joke_text = f"{joke['joke_text']}\n\n{rating_text}" + + # Add inline buttons for quick rating + keyboard = [ + [ + InlineKeyboardButton("👍 Like", callback_data=f"like_{joke['id']}"), + InlineKeyboardButton("👎 Dislike", callback_data=f"dislike_{joke['id']}") + ] + ] + reply_markup = InlineKeyboardMarkup(keyboard) + + await update.message.reply_text(joke_text, reply_markup=reply_markup) + +async def add_joke_command(update: Update, context: ContextTypes.DEFAULT_TYPE): + """Handle /addjoke command""" + if not context.args: + await update.message.reply_text( + "Please provide a joke after the command:\n" + "Example: /addjoke Why did the chicken cross the road?" + ) + return + + joke_text = " ".join(context.args) + user = update.effective_user + + # Add to database + joke_id = db.add_joke(joke_text, user.id, user.username) + + await update.message.reply_text( + f"✅ Joke added successfully! (ID: {joke_id})\n" + "Others can now rate it with /like and /dislike" + )
+ +
+

New Bot Features:

+
+
🤖
+
Inline Buttons: Quick like/dislike without commands
+
+
+
💾
+
User Context: Remember last joke for rating
+
+
+ 📊 +
Real Stats: Display actual like/dislike counts
+
+
+
👤
+
User Tracking: Record who submitted each joke
+
+
+
+ + + +
+ + + + \ No newline at end of file diff --git a/Joke Bot Upgrade_ SQLite Database Integration _ Beginner's Guide_files/css2 b/Joke Bot Upgrade_ SQLite Database Integration _ Beginner's Guide_files/css2 new file mode 100644 index 0000000..b7d63d9 --- /dev/null +++ b/Joke Bot Upgrade_ SQLite Database Integration _ Beginner's Guide_files/css2 @@ -0,0 +1,315 @@ +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7W0Q5nw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7W0Q5nw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7W0Q5nw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7W0Q5nw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7W0Q5nw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/jokes-bot-v3.0/.DS_Store b/jokes-bot-v3.0/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7595df5eb08ea51a7927277b57dd384b9b3e94d5 GIT binary patch literal 6148 zcmeHKF;2r!47DLcB$ke_{VQ}}|5RZHsRsa+B9LgCE_BYuJ-7@PVC52=fM@#yiJ~$x zz_aB4@@>ET`+ooBp+67|u7U>E404lF(b0PQ#44c9(P0FwoPxnLKF2uy^<*e5x_%-~~Q0wJbycGkz6=P$q__$Y>>>Bx8unTlL;!X$hN5FKU JQGwr3-~;r)E7t%3 literal 0 HcmV?d00001 diff --git a/jokes-bot-v3.0/README.md b/jokes-bot-v3.0/README.md new file mode 100644 index 0000000..ed329ec --- /dev/null +++ b/jokes-bot-v3.0/README.md @@ -0,0 +1,45 @@ +# Telegram Joke Bot + +A simple Telegram bot that tells jokes when you send it the `/joke` command. + +## Setup Instructions + +1. **Install required packages** + ```bash + pip install -r requirements.txt + ``` + +2. **Get a bot token** + - Talk to [@BotFather](https://t.me/BotFather) on Telegram + - Create a new bot with `/newbot` + - Copy the token provided by BotFather + +3. **Set your bot token** + You can set your bot token in two ways: + + Option A: Set as environment variable + ```bash + export BOT_TOKEN="your_token_here" + ``` + + Option B: Replace "YOUR_BOT_TOKEN_HERE" in jokes.py with your actual token + +4. **Run the bot** + ```bash + python jokes.py + ``` + +## Bot Commands + +- `/start` - Start the bot and get welcome message +- `/joke` - Get a random joke +- `/help` - Show help message + +## Features + +- Sends random jokes from a predefined list +- Easy to add more jokes to the collection +- Simple and lightweight implementation + + + diff --git a/jokes-bot-v3.0/app.py b/jokes-bot-v3.0/app.py new file mode 100644 index 0000000..26b686e --- /dev/null +++ b/jokes-bot-v3.0/app.py @@ -0,0 +1,35 @@ +# app.py — Teacher-Only Telegram Joke Bot +from telegram import Update +from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes +import random + +# 🔑 REPLACE WITH REAL TOKEN FROM @BotFather +BOT_TOKEN = "" + +# --- COPY STUDENT JOKES HERE BEFORE CLASS --- +JOKE_LIST = [ + "Why did the robot go to school? To recharge his brain! 🔋", + "Knock knock!\\nWho's there?\\nBoo!\\nBoo who?\\nDon't cry! 😂", + "Why don't eggs tell jokes? They'd crack each other up! 🥚", + "What do you call a penguin in the desert? Lost! 🐧", + # Add student jokes here +] + +async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): + await update.message.reply_text("🤖 Hi! I'm your Joke Bot!\nType /joke for a funny joke in English! 😄") + +async def send_joke(update: Update, context: ContextTypes.DEFAULT_TYPE): + joke = random.choice(JOKE_LIST) + await update.message.reply_text(joke) + + +def main(): + print("🚀 Starting Joke Bot...") + app = ApplicationBuilder().token(BOT_TOKEN).build() + app.add_handler(CommandHandler("start", start)) + app.add_handler(CommandHandler("joke", send_joke)) + print("✅ Bot is running! Press Ctrl+C to stop.") + app.run_polling() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/jokes-bot-v3.0/requirements.txt b/jokes-bot-v3.0/requirements.txt new file mode 100644 index 0000000..11a50f9 --- /dev/null +++ b/jokes-bot-v3.0/requirements.txt @@ -0,0 +1 @@ +python-telegram-bot \ No newline at end of file