Spaces:
Sleeping
Sleeping
Upload 6 files
Browse files- UserStatus.py +7 -0
- bot.py +191 -0
- config.py +4 -0
- db_connection(1).py +158 -0
- db_connection.py +158 -0
- requirements.txt +5 -0
UserStatus.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
class UserStatus:
|
2 |
+
COUPLED = "coupled"
|
3 |
+
IDLE = "idle"
|
4 |
+
IN_SEARCH = "in_search"
|
5 |
+
PARTNER_LEFT = "partner_left"
|
6 |
+
|
7 |
+
possible_states = [COUPLED, IDLE, IN_SEARCH, PARTNER_LEFT]
|
bot.py
ADDED
@@ -0,0 +1,191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import logging
|
2 |
+
from telegram import Update, ChatMember
|
3 |
+
from telegram.ext import (filters, ApplicationBuilder, ContextTypes, CommandHandler, ConversationHandler,
|
4 |
+
MessageHandler, ChatMemberHandler)
|
5 |
+
from UserStatus import UserStatus
|
6 |
+
from config import BOT_TOKEN, ADMIN_ID
|
7 |
+
import db_connection
|
8 |
+
|
9 |
+
logging.basicConfig(
|
10 |
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
11 |
+
level=logging.WARNING # Set the logging level to: (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
12 |
+
)
|
13 |
+
|
14 |
+
"""
|
15 |
+
####### List of commands #######
|
16 |
+
---> start - 🤖 starts the bot
|
17 |
+
---> chat - 💬 start searching for a partner
|
18 |
+
---> exit - 🔚 exit from the chat
|
19 |
+
---> newchat - ⏭ exit from the chat and open a new one
|
20 |
+
---> stats - 📊 show bot statistics (only for admin)
|
21 |
+
"""
|
22 |
+
|
23 |
+
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
24 |
+
await context.bot.send_message(chat_id=update.effective_chat.id,
|
25 |
+
text="Welcome to this ChatBot! 🤖\nType /chat to start searching for a partner")
|
26 |
+
user_id = update.effective_user.id
|
27 |
+
db_connection.insert_user(user_id)
|
28 |
+
return USER_ACTION
|
29 |
+
|
30 |
+
async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
31 |
+
user_id = update.effective_user.id
|
32 |
+
if db_connection.get_user_status(user_id=user_id) == UserStatus.COUPLED:
|
33 |
+
other_user_id = db_connection.get_partner_id(user_id)
|
34 |
+
if other_user_id is None:
|
35 |
+
return await handle_not_in_chat(update, context)
|
36 |
+
else:
|
37 |
+
return await in_chat(update, other_user_id)
|
38 |
+
else:
|
39 |
+
return await handle_not_in_chat(update, context)
|
40 |
+
|
41 |
+
async def handle_chat(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
42 |
+
current_user_id = update.effective_user.id
|
43 |
+
current_user_status = db_connection.get_user_status(user_id=current_user_id)
|
44 |
+
|
45 |
+
if current_user_status == UserStatus.PARTNER_LEFT:
|
46 |
+
db_connection.set_user_status(user_id=current_user_id, new_status=UserStatus.IDLE)
|
47 |
+
return await start_search(update, context)
|
48 |
+
elif current_user_status == UserStatus.IN_SEARCH:
|
49 |
+
return await handle_already_in_search(update, context)
|
50 |
+
elif current_user_status == UserStatus.COUPLED:
|
51 |
+
other_user = db_connection.get_partner_id(current_user_id)
|
52 |
+
if other_user is not None:
|
53 |
+
await context.bot.send_message(chat_id=current_user_id,
|
54 |
+
text="🤖 You are already in a chat, type /exit to exit from the chat.")
|
55 |
+
return None
|
56 |
+
else:
|
57 |
+
return await start_search(update, context)
|
58 |
+
elif current_user_status == UserStatus.IDLE:
|
59 |
+
return await start_search(update, context)
|
60 |
+
|
61 |
+
async def handle_not_in_chat(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
62 |
+
current_user_id = update.effective_user.id
|
63 |
+
current_user_status = db_connection.get_user_status(user_id=current_user_id)
|
64 |
+
|
65 |
+
if current_user_status in [UserStatus.IDLE, UserStatus.PARTNER_LEFT]:
|
66 |
+
await context.bot.send_message(chat_id=current_user_id,
|
67 |
+
text="🤖 You are not in a chat, type /chat to start searching for a partner.")
|
68 |
+
return
|
69 |
+
elif current_user_status == UserStatus.IN_SEARCH:
|
70 |
+
await context.bot.send_message(chat_id=current_user_id,
|
71 |
+
text="🤖 Message not delivered, you are still in search!")
|
72 |
+
return
|
73 |
+
|
74 |
+
async def handle_already_in_search(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
75 |
+
await context.bot.send_message(chat_id=update.effective_chat.id, text="🤖 You are already in search!")
|
76 |
+
return
|
77 |
+
|
78 |
+
async def start_search(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
79 |
+
current_user_id = update.effective_chat.id
|
80 |
+
db_connection.set_user_status(user_id=current_user_id, new_status=UserStatus.IN_SEARCH)
|
81 |
+
await context.bot.send_message(chat_id=current_user_id, text="🤖 Searching for a partner...")
|
82 |
+
other_user_id = db_connection.couple(current_user_id=current_user_id)
|
83 |
+
if other_user_id is not None:
|
84 |
+
await context.bot.send_message(chat_id=current_user_id, text="🤖 You have been paired with an user")
|
85 |
+
await context.bot.send_message(chat_id=other_user_id, text="🤖 You have been paired with an user")
|
86 |
+
return
|
87 |
+
|
88 |
+
async def handle_exit_chat(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
89 |
+
await exit_chat(update, context)
|
90 |
+
return
|
91 |
+
|
92 |
+
async def handle_stats(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
93 |
+
user_id = update.effective_user.id
|
94 |
+
if user_id == ADMIN_ID:
|
95 |
+
total_users_number, paired_users_number = db_connection.retrieve_users_number()
|
96 |
+
await context.bot.send_message(chat_id=user_id, text="Welcome to the admin panel")
|
97 |
+
await context.bot.send_message(chat_id=user_id,
|
98 |
+
text="Number of paired users: " + str(paired_users_number))
|
99 |
+
await context.bot.send_message(chat_id=user_id,
|
100 |
+
text="Number of active users: " + str(total_users_number))
|
101 |
+
else:
|
102 |
+
logging.warning("User " + str(user_id) + " tried to access the admin panel")
|
103 |
+
return
|
104 |
+
|
105 |
+
async def exit_chat(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
106 |
+
current_user = update.effective_user.id
|
107 |
+
if db_connection.get_user_status(user_id=current_user) != UserStatus.COUPLED:
|
108 |
+
await context.bot.send_message(chat_id=current_user, text="🤖 You are not in a chat!")
|
109 |
+
return
|
110 |
+
other_user = db_connection.get_partner_id(current_user)
|
111 |
+
if other_user is None:
|
112 |
+
return
|
113 |
+
db_connection.uncouple(user_id=current_user)
|
114 |
+
await context.bot.send_message(chat_id=current_user, text="🤖 Ending chat...")
|
115 |
+
await context.bot.send_message(chat_id=other_user,
|
116 |
+
text="🤖 Your partner has left the chat, type /chat to start searching for a new "
|
117 |
+
"partner.")
|
118 |
+
await update.message.reply_text("🤖 You have left the chat.")
|
119 |
+
return
|
120 |
+
|
121 |
+
async def exit_then_chat(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
122 |
+
current_user = update.effective_user.id
|
123 |
+
if db_connection.get_user_status(user_id=current_user) == UserStatus.IN_SEARCH:
|
124 |
+
return await handle_already_in_search(update, context)
|
125 |
+
await exit_chat(update, context)
|
126 |
+
return await start_search(update, context)
|
127 |
+
|
128 |
+
async def in_chat(update: Update, other_user_id) -> None:
|
129 |
+
if update.message.reply_to_message is not None:
|
130 |
+
if update.message.reply_to_message.from_user.id == update.effective_user.id:
|
131 |
+
await update.effective_chat.copy_message(chat_id=other_user_id, message_id=update.message.message_id,
|
132 |
+
protect_content=True,
|
133 |
+
reply_to_message_id=update.message.reply_to_message.message_id + 1)
|
134 |
+
elif update.message.reply_to_message.has_protected_content is None:
|
135 |
+
await update.effective_chat.copy_message(chat_id=other_user_id, message_id=update.message.message_id,
|
136 |
+
protect_content=True)
|
137 |
+
else:
|
138 |
+
await update.effective_chat.copy_message(chat_id=other_user_id, message_id=update.message.message_id,
|
139 |
+
protect_content=True,
|
140 |
+
reply_to_message_id=update.message.reply_to_message.message_id - 1)
|
141 |
+
else:
|
142 |
+
await update.effective_chat.copy_message(chat_id=other_user_id, message_id=update.message.message_id,
|
143 |
+
protect_content=True)
|
144 |
+
return
|
145 |
+
|
146 |
+
def is_bot_blocked_by_user(update: Update) -> bool:
|
147 |
+
new_member_status = update.my_chat_member.new_chat_member.status
|
148 |
+
old_member_status = update.my_chat_member.old_chat_member.status
|
149 |
+
return new_member_status == ChatMember.BANNED and old_member_status == ChatMember.MEMBER
|
150 |
+
|
151 |
+
async def blocked_bot_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
152 |
+
if is_bot_blocked_by_user(update):
|
153 |
+
user_id = update.effective_user.id
|
154 |
+
user_status = db_connection.get_user_status(user_id=user_id)
|
155 |
+
if user_status == UserStatus.COUPLED:
|
156 |
+
other_user = db_connection.get_partner_id(user_id)
|
157 |
+
db_connection.uncouple(user_id=user_id)
|
158 |
+
await context.bot.send_message(chat_id=other_user, text="🤖 Your partner has left the chat, type /chat to "
|
159 |
+
"start searching for a new partner.")
|
160 |
+
db_connection.remove_user(user_id=user_id)
|
161 |
+
return ConversationHandler.END
|
162 |
+
else:
|
163 |
+
return USER_ACTION
|
164 |
+
|
165 |
+
USER_ACTION = 0
|
166 |
+
|
167 |
+
if __name__ == '__main__':
|
168 |
+
application = ApplicationBuilder().token(BOT_TOKEN).build()
|
169 |
+
db_connection.create_db()
|
170 |
+
db_connection.reset_users_status()
|
171 |
+
|
172 |
+
conv_handler = ConversationHandler(
|
173 |
+
entry_points=[CommandHandler("start", start)],
|
174 |
+
states={
|
175 |
+
USER_ACTION: [
|
176 |
+
ChatMemberHandler(blocked_bot_handler),
|
177 |
+
MessageHandler(
|
178 |
+
(filters.TEXT | filters.ATTACHMENT) & ~ filters.COMMAND & ~filters.Regex("exit") & ~filters.Regex(
|
179 |
+
"chat")
|
180 |
+
& ~filters.Regex("newchat") & ~filters.Regex("stats"),
|
181 |
+
handle_message),
|
182 |
+
CommandHandler("exit", handle_exit_chat),
|
183 |
+
CommandHandler("chat", handle_chat),
|
184 |
+
CommandHandler("newchat", exit_then_chat),
|
185 |
+
CommandHandler("stats", handle_stats)]
|
186 |
+
},
|
187 |
+
fallbacks=[MessageHandler(filters.TEXT, handle_not_in_chat)]
|
188 |
+
)
|
189 |
+
application.add_handler(conv_handler)
|
190 |
+
application.run_polling()
|
191 |
+
|
config.py
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# config.py
|
2 |
+
|
3 |
+
BOT_TOKEN = "7930660432:AAF2p5Ai07yVxiFdIYS2ES9-N8z7pxYZeY8"
|
4 |
+
ADMIN_ID = "@uptimecoding"
|
db_connection(1).py
ADDED
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sqlite3
|
2 |
+
from UserStatus import UserStatus
|
3 |
+
|
4 |
+
|
5 |
+
def create_db():
|
6 |
+
# Connect to the chatbot database
|
7 |
+
conn = sqlite3.connect('chatbot_database.db')
|
8 |
+
c = conn.cursor()
|
9 |
+
# Create the users table if it does not exist (user_id, status, partner_id)
|
10 |
+
c.execute("CREATE TABLE IF NOT EXISTS users (user_id TEXT PRIMARY KEY, status TEXT, partner_id TEXT)")
|
11 |
+
conn.commit()
|
12 |
+
conn.close()
|
13 |
+
|
14 |
+
|
15 |
+
def insert_user(user_id):
|
16 |
+
# Connect to the chatbot database
|
17 |
+
conn = sqlite3.connect('chatbot_database.db')
|
18 |
+
c = conn.cursor()
|
19 |
+
# Check if the user is already in the users table
|
20 |
+
c.execute("SELECT * FROM users WHERE user_id=?", (user_id,))
|
21 |
+
if c.fetchone():
|
22 |
+
# If the user is already in the users table, do nothing
|
23 |
+
conn.close()
|
24 |
+
return
|
25 |
+
|
26 |
+
# Otherwise, insert the user into the users table
|
27 |
+
c.execute("INSERT INTO users VALUES (?, ?, ?)", (user_id, UserStatus.IDLE, None)) # No partner_id initially
|
28 |
+
conn.commit()
|
29 |
+
conn.close()
|
30 |
+
|
31 |
+
|
32 |
+
def remove_user(user_id):
|
33 |
+
# If a user disconnects, remove him/her from the users table
|
34 |
+
conn = sqlite3.connect('chatbot_database.db') # Connect to the chatbot database
|
35 |
+
c = conn.cursor()
|
36 |
+
# Check if the user had a partner
|
37 |
+
partner_id = get_partner_id(user_id)
|
38 |
+
if partner_id:
|
39 |
+
# If the user had a partner, remove the user from the partner's row
|
40 |
+
c.execute("UPDATE users SET partner_id=NULL WHERE user_id=?", (partner_id,))
|
41 |
+
# Update the partner's status to UserStatus.PARTNER_LEFT
|
42 |
+
set_user_status(partner_id, UserStatus.PARTNER_LEFT)
|
43 |
+
else:
|
44 |
+
# Simply remove the user from the users table
|
45 |
+
c.execute("DELETE FROM users WHERE user_id=?", (user_id,))
|
46 |
+
conn.commit()
|
47 |
+
conn.close()
|
48 |
+
|
49 |
+
|
50 |
+
def get_user_status(user_id):
|
51 |
+
# Connect to the chatbot database
|
52 |
+
conn = sqlite3.connect('chatbot_database.db')
|
53 |
+
c = conn.cursor()
|
54 |
+
# Get the status of the user
|
55 |
+
c.execute("SELECT status FROM users WHERE user_id=?", (user_id,))
|
56 |
+
status = c.fetchone()[0]
|
57 |
+
conn.close()
|
58 |
+
return status
|
59 |
+
|
60 |
+
|
61 |
+
def set_user_status(user_id, new_status):
|
62 |
+
# Connect to the chatbot database
|
63 |
+
conn = sqlite3.connect('chatbot_database.db')
|
64 |
+
c = conn.cursor()
|
65 |
+
# Set the status of the user
|
66 |
+
c.execute("UPDATE users SET status=? WHERE user_id=?", (new_status, user_id))
|
67 |
+
conn.commit()
|
68 |
+
conn.close()
|
69 |
+
|
70 |
+
|
71 |
+
def get_partner_id(user_id):
|
72 |
+
# Connect to the chatbot database
|
73 |
+
conn = sqlite3.connect('chatbot_database.db')
|
74 |
+
c = conn.cursor()
|
75 |
+
# If the user is a guest, then search for the host
|
76 |
+
c.execute("SELECT user_id FROM users WHERE partner_id=?", (user_id,))
|
77 |
+
other_user_id = c.fetchone()
|
78 |
+
if not other_user_id:
|
79 |
+
# If no user is found, return None
|
80 |
+
conn.close()
|
81 |
+
return None
|
82 |
+
# otherwise, return the other user's id
|
83 |
+
other_user_id = other_user_id[0]
|
84 |
+
conn.close()
|
85 |
+
|
86 |
+
return other_user_id
|
87 |
+
|
88 |
+
|
89 |
+
def couple(current_user_id):
|
90 |
+
# Connect to the chatbot database
|
91 |
+
conn = sqlite3.connect('chatbot_database.db')
|
92 |
+
c = conn.cursor()
|
93 |
+
# If the user is not the current one and is in search, then couple them
|
94 |
+
c.execute("SELECT user_id FROM users WHERE status=? AND user_id!=?", (UserStatus.IN_SEARCH, current_user_id,))
|
95 |
+
# Verify if another user in search is found
|
96 |
+
other_user_id = c.fetchone()
|
97 |
+
if not other_user_id:
|
98 |
+
# If no user is found, return None
|
99 |
+
return None
|
100 |
+
# If another user in search is found, couple the users
|
101 |
+
other_user_id = other_user_id[0]
|
102 |
+
# Update both users' partner_id to reflect the coupling
|
103 |
+
c.execute("UPDATE users SET partner_id=? WHERE user_id=?", (other_user_id, current_user_id))
|
104 |
+
c.execute("UPDATE users SET partner_id=? WHERE user_id=?", (current_user_id, other_user_id))
|
105 |
+
|
106 |
+
# Update both users' status to UserStatus.COUPLED
|
107 |
+
c.execute("UPDATE users SET status=? WHERE user_id=?", (UserStatus.COUPLED, current_user_id))
|
108 |
+
c.execute("UPDATE users SET status=? WHERE user_id=?", (UserStatus.COUPLED, other_user_id))
|
109 |
+
|
110 |
+
conn.commit()
|
111 |
+
conn.close()
|
112 |
+
|
113 |
+
return other_user_id
|
114 |
+
|
115 |
+
|
116 |
+
def uncouple(user_id):
|
117 |
+
# Connect to the chatbot database
|
118 |
+
conn = sqlite3.connect('chatbot_database.db')
|
119 |
+
c = conn.cursor()
|
120 |
+
# Retrieve the partner_id of the user
|
121 |
+
partner_id = get_partner_id(user_id)
|
122 |
+
if not partner_id:
|
123 |
+
# If the user is not coupled, return None
|
124 |
+
return None
|
125 |
+
|
126 |
+
# Update both users' partner_id to reflect the uncoupling
|
127 |
+
c.execute("UPDATE users SET partner_id=NULL WHERE user_id=?", (user_id,))
|
128 |
+
c.execute("UPDATE users SET partner_id=NULL WHERE user_id=?", (partner_id,))
|
129 |
+
# Update both users' status to UserStatus.IDLE
|
130 |
+
c.execute("UPDATE users SET status=? WHERE user_id=?", (UserStatus.IDLE, user_id))
|
131 |
+
c.execute("UPDATE users SET status=? WHERE user_id=?", (UserStatus.IDLE, partner_id))
|
132 |
+
conn.commit()
|
133 |
+
conn.close()
|
134 |
+
return
|
135 |
+
|
136 |
+
|
137 |
+
def retrieve_users_number():
|
138 |
+
# Connect to the chatbot database
|
139 |
+
conn = sqlite3.connect('chatbot_database.db')
|
140 |
+
c = conn.cursor()
|
141 |
+
# Retrieve the number of users in the users table
|
142 |
+
c.execute("SELECT COUNT(*) FROM users")
|
143 |
+
total_users_number = c.fetchone()[0]
|
144 |
+
# Retrieve the number of users who are currently coupled
|
145 |
+
c.execute("SELECT COUNT(*) FROM users WHERE status='coupled'")
|
146 |
+
paired_users_number = c.fetchone()[0]
|
147 |
+
conn.close()
|
148 |
+
return total_users_number, paired_users_number
|
149 |
+
|
150 |
+
|
151 |
+
def reset_users_status():
|
152 |
+
# Connect to the chatbot database
|
153 |
+
conn = sqlite3.connect('chatbot_database.db')
|
154 |
+
c = conn.cursor()
|
155 |
+
# Reset the status of all users to UserStatus.IDLE
|
156 |
+
c.execute("UPDATE users SET status=?", (UserStatus.IDLE,))
|
157 |
+
conn.commit()
|
158 |
+
conn.close()
|
db_connection.py
ADDED
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sqlite3
|
2 |
+
from UserStatus import UserStatus
|
3 |
+
|
4 |
+
|
5 |
+
def create_db():
|
6 |
+
# Connect to the chatbot database
|
7 |
+
conn = sqlite3.connect('chatbot_database.db')
|
8 |
+
c = conn.cursor()
|
9 |
+
# Create the users table if it does not exist (user_id, status, partner_id)
|
10 |
+
c.execute("CREATE TABLE IF NOT EXISTS users (user_id TEXT PRIMARY KEY, status TEXT, partner_id TEXT)")
|
11 |
+
conn.commit()
|
12 |
+
conn.close()
|
13 |
+
|
14 |
+
|
15 |
+
def insert_user(user_id):
|
16 |
+
# Connect to the chatbot database
|
17 |
+
conn = sqlite3.connect('chatbot_database.db')
|
18 |
+
c = conn.cursor()
|
19 |
+
# Check if the user is already in the users table
|
20 |
+
c.execute("SELECT * FROM users WHERE user_id=?", (user_id,))
|
21 |
+
if c.fetchone():
|
22 |
+
# If the user is already in the users table, do nothing
|
23 |
+
conn.close()
|
24 |
+
return
|
25 |
+
|
26 |
+
# Otherwise, insert the user into the users table
|
27 |
+
c.execute("INSERT INTO users VALUES (?, ?, ?)", (user_id, UserStatus.IDLE, None)) # No partner_id initially
|
28 |
+
conn.commit()
|
29 |
+
conn.close()
|
30 |
+
|
31 |
+
|
32 |
+
def remove_user(user_id):
|
33 |
+
# If a user disconnects, remove him/her from the users table
|
34 |
+
conn = sqlite3.connect('chatbot_database.db') # Connect to the chatbot database
|
35 |
+
c = conn.cursor()
|
36 |
+
# Check if the user had a partner
|
37 |
+
partner_id = get_partner_id(user_id)
|
38 |
+
if partner_id:
|
39 |
+
# If the user had a partner, remove the user from the partner's row
|
40 |
+
c.execute("UPDATE users SET partner_id=NULL WHERE user_id=?", (partner_id,))
|
41 |
+
# Update the partner's status to UserStatus.PARTNER_LEFT
|
42 |
+
set_user_status(partner_id, UserStatus.PARTNER_LEFT)
|
43 |
+
else:
|
44 |
+
# Simply remove the user from the users table
|
45 |
+
c.execute("DELETE FROM users WHERE user_id=?", (user_id,))
|
46 |
+
conn.commit()
|
47 |
+
conn.close()
|
48 |
+
|
49 |
+
|
50 |
+
def get_user_status(user_id):
|
51 |
+
# Connect to the chatbot database
|
52 |
+
conn = sqlite3.connect('chatbot_database.db')
|
53 |
+
c = conn.cursor()
|
54 |
+
# Get the status of the user
|
55 |
+
c.execute("SELECT status FROM users WHERE user_id=?", (user_id,))
|
56 |
+
status = c.fetchone()[0]
|
57 |
+
conn.close()
|
58 |
+
return status
|
59 |
+
|
60 |
+
|
61 |
+
def set_user_status(user_id, new_status):
|
62 |
+
# Connect to the chatbot database
|
63 |
+
conn = sqlite3.connect('chatbot_database.db')
|
64 |
+
c = conn.cursor()
|
65 |
+
# Set the status of the user
|
66 |
+
c.execute("UPDATE users SET status=? WHERE user_id=?", (new_status, user_id))
|
67 |
+
conn.commit()
|
68 |
+
conn.close()
|
69 |
+
|
70 |
+
|
71 |
+
def get_partner_id(user_id):
|
72 |
+
# Connect to the chatbot database
|
73 |
+
conn = sqlite3.connect('chatbot_database.db')
|
74 |
+
c = conn.cursor()
|
75 |
+
# If the user is a guest, then search for the host
|
76 |
+
c.execute("SELECT user_id FROM users WHERE partner_id=?", (user_id,))
|
77 |
+
other_user_id = c.fetchone()
|
78 |
+
if not other_user_id:
|
79 |
+
# If no user is found, return None
|
80 |
+
conn.close()
|
81 |
+
return None
|
82 |
+
# otherwise, return the other user's id
|
83 |
+
other_user_id = other_user_id[0]
|
84 |
+
conn.close()
|
85 |
+
|
86 |
+
return other_user_id
|
87 |
+
|
88 |
+
|
89 |
+
def couple(current_user_id):
|
90 |
+
# Connect to the chatbot database
|
91 |
+
conn = sqlite3.connect('chatbot_database.db')
|
92 |
+
c = conn.cursor()
|
93 |
+
# If the user is not the current one and is in search, then couple them
|
94 |
+
c.execute("SELECT user_id FROM users WHERE status=? AND user_id!=?", (UserStatus.IN_SEARCH, current_user_id,))
|
95 |
+
# Verify if another user in search is found
|
96 |
+
other_user_id = c.fetchone()
|
97 |
+
if not other_user_id:
|
98 |
+
# If no user is found, return None
|
99 |
+
return None
|
100 |
+
# If another user in search is found, couple the users
|
101 |
+
other_user_id = other_user_id[0]
|
102 |
+
# Update both users' partner_id to reflect the coupling
|
103 |
+
c.execute("UPDATE users SET partner_id=? WHERE user_id=?", (other_user_id, current_user_id))
|
104 |
+
c.execute("UPDATE users SET partner_id=? WHERE user_id=?", (current_user_id, other_user_id))
|
105 |
+
|
106 |
+
# Update both users' status to UserStatus.COUPLED
|
107 |
+
c.execute("UPDATE users SET status=? WHERE user_id=?", (UserStatus.COUPLED, current_user_id))
|
108 |
+
c.execute("UPDATE users SET status=? WHERE user_id=?", (UserStatus.COUPLED, other_user_id))
|
109 |
+
|
110 |
+
conn.commit()
|
111 |
+
conn.close()
|
112 |
+
|
113 |
+
return other_user_id
|
114 |
+
|
115 |
+
|
116 |
+
def uncouple(user_id):
|
117 |
+
# Connect to the chatbot database
|
118 |
+
conn = sqlite3.connect('chatbot_database.db')
|
119 |
+
c = conn.cursor()
|
120 |
+
# Retrieve the partner_id of the user
|
121 |
+
partner_id = get_partner_id(user_id)
|
122 |
+
if not partner_id:
|
123 |
+
# If the user is not coupled, return None
|
124 |
+
return None
|
125 |
+
|
126 |
+
# Update both users' partner_id to reflect the uncoupling
|
127 |
+
c.execute("UPDATE users SET partner_id=NULL WHERE user_id=?", (user_id,))
|
128 |
+
c.execute("UPDATE users SET partner_id=NULL WHERE user_id=?", (partner_id,))
|
129 |
+
# Update both users' status to UserStatus.IDLE
|
130 |
+
c.execute("UPDATE users SET status=? WHERE user_id=?", (UserStatus.IDLE, user_id))
|
131 |
+
c.execute("UPDATE users SET status=? WHERE user_id=?", (UserStatus.IDLE, partner_id))
|
132 |
+
conn.commit()
|
133 |
+
conn.close()
|
134 |
+
return
|
135 |
+
|
136 |
+
|
137 |
+
def retrieve_users_number():
|
138 |
+
# Connect to the chatbot database
|
139 |
+
conn = sqlite3.connect('chatbot_database.db')
|
140 |
+
c = conn.cursor()
|
141 |
+
# Retrieve the number of users in the users table
|
142 |
+
c.execute("SELECT COUNT(*) FROM users")
|
143 |
+
total_users_number = c.fetchone()[0]
|
144 |
+
# Retrieve the number of users who are currently coupled
|
145 |
+
c.execute("SELECT COUNT(*) FROM users WHERE status='coupled'")
|
146 |
+
paired_users_number = c.fetchone()[0]
|
147 |
+
conn.close()
|
148 |
+
return total_users_number, paired_users_number
|
149 |
+
|
150 |
+
|
151 |
+
def reset_users_status():
|
152 |
+
# Connect to the chatbot database
|
153 |
+
conn = sqlite3.connect('chatbot_database.db')
|
154 |
+
c = conn.cursor()
|
155 |
+
# Reset the status of all users to UserStatus.IDLE
|
156 |
+
c.execute("UPDATE users SET status=?", (UserStatus.IDLE,))
|
157 |
+
conn.commit()
|
158 |
+
conn.close()
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
streamlit==1.18.0
|
2 |
+
python-telegram-bot==21.7
|
3 |
+
nest-asyncio==1.5.6
|
4 |
+
altair==4.2.0
|
5 |
+
vega-datasets==0.9.0
|