muhammadrazapathan commited on
Commit
9f88035
·
verified ·
1 Parent(s): 3957393

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +154 -0
app.py ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import uuid
2
+ import sqlite3
3
+ import gradio as gr
4
+ from datetime import datetime
5
+ from passlib.context import CryptContext
6
+
7
+ # ================= DATABASE =================
8
+ conn = sqlite3.connect("chat.db", check_same_thread=False)
9
+ cursor = conn.cursor()
10
+
11
+ cursor.execute("""CREATE TABLE IF NOT EXISTS users(email TEXT PRIMARY KEY,password TEXT)""")
12
+ cursor.execute("""CREATE TABLE IF NOT EXISTS invites(code TEXT PRIMARY KEY,user1 TEXT,user2 TEXT)""")
13
+ cursor.execute("""CREATE TABLE IF NOT EXISTS messages(id TEXT PRIMARY KEY,room TEXT,sender TEXT,message TEXT,time TEXT)""")
14
+
15
+ conn.commit()
16
+
17
+ pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
18
+
19
+ # ================= AUTH =================
20
+ def register_or_login(email, password):
21
+ cursor.execute("SELECT password FROM users WHERE email=?", (email,))
22
+ data = cursor.fetchone()
23
+
24
+ if data:
25
+ if pwd_context.verify(password, data[0]):
26
+ return email, "Welcome back ✅"
27
+ return None, "Wrong password ❌"
28
+
29
+ hashed = pwd_context.hash(password)
30
+ cursor.execute("INSERT INTO users VALUES (?,?)", (email, hashed))
31
+ conn.commit()
32
+ return email, "Account created ✅"
33
+
34
+ # ================= INVITES =================
35
+ def create_invite(user):
36
+ code = str(uuid.uuid4())[:8]
37
+ cursor.execute("INSERT INTO invites VALUES (?,?,?)", (code, user, ""))
38
+ conn.commit()
39
+ return code, f"Invite Code: {code}"
40
+
41
+ def join_invite(user, code):
42
+ cursor.execute("SELECT user1,user2 FROM invites WHERE code=?", (code,))
43
+ data = cursor.fetchone()
44
+
45
+ if not data:
46
+ return None, "Invalid Code"
47
+
48
+ if data[1]:
49
+ return None, "Room already full"
50
+
51
+ cursor.execute("UPDATE invites SET user2=? WHERE code=?", (user, code))
52
+ conn.commit()
53
+ return code, f"Connected with {data[0]}"
54
+
55
+ # ================= CHAT =================
56
+ def send_message(user, room, msg):
57
+ if not msg or not room:
58
+ return
59
+ cursor.execute("INSERT INTO messages VALUES (?,?,?,?,?)",
60
+ (str(uuid.uuid4()), room, user, msg,
61
+ datetime.now().strftime("%H:%M")))
62
+ conn.commit()
63
+
64
+ def fetch_messages(room, current_user):
65
+ if not room:
66
+ return "<div class='system'>Join a room to start chatting.</div>"
67
+
68
+ cursor.execute("SELECT sender,message,time FROM messages WHERE room=? ORDER BY rowid", (room,))
69
+ chats = cursor.fetchall()
70
+
71
+ html = ""
72
+ for sender, msg, t in chats:
73
+ side = "me" if sender == current_user else "other"
74
+ html += f"""
75
+ <div class='msg {side}'>
76
+ <div class='bubble'>
77
+ <div class='text'>{msg}</div>
78
+ <div class='time'>{t}</div>
79
+ </div>
80
+ </div>
81
+ """
82
+ return html
83
+
84
+ # ================= UI =================
85
+ custom_css = """
86
+ body {background:#0f172a;}
87
+ .container {max-width:900px;margin:auto;}
88
+ .header {text-align:center;color:white;font-size:26px;font-weight:600;margin-bottom:10px;}
89
+ .msg {display:flex;margin:8px;}
90
+ .msg.me {justify-content:flex-end;}
91
+ .msg.other {justify-content:flex-start;}
92
+ .bubble {
93
+ padding:12px 16px;
94
+ border-radius:18px;
95
+ max-width:60%;
96
+ box-shadow:0 4px 14px rgba(0,0,0,0.2);
97
+ }
98
+ .me .bubble {background:#22c55e;color:white;}
99
+ .other .bubble {background:#1e293b;color:white;}
100
+ .time {font-size:10px;opacity:0.6;margin-top:4px;text-align:right;}
101
+ .chatbox {
102
+ height:420px;
103
+ overflow-y:auto;
104
+ padding:10px;
105
+ background:#020617;
106
+ border-radius:14px;
107
+ }
108
+ .system {color:#94a3b8;text-align:center;margin-top:20px;}
109
+ """
110
+
111
+ with gr.Blocks(css=custom_css) as app:
112
+
113
+ user_state = gr.State()
114
+ room_state = gr.State()
115
+
116
+ gr.Markdown("<div class='header'>🔐 DuoSecure — Private 2-Person Chat</div>")
117
+
118
+ with gr.Tab("Login"):
119
+ email = gr.Textbox(label="Email")
120
+ password = gr.Textbox(type="password", label="Password")
121
+ btn = gr.Button("Enter")
122
+ status = gr.Markdown()
123
+
124
+ btn.click(register_or_login, [email, password], [user_state, status])
125
+
126
+ with gr.Tab("Invitation"):
127
+ create_btn = gr.Button("Create Private Room")
128
+ code_box = gr.Textbox(label="Room Code")
129
+ join_btn = gr.Button("Join Room")
130
+ invite_status = gr.Markdown()
131
+
132
+ create_btn.click(create_invite, user_state, [code_box, invite_status])
133
+ join_btn.click(join_invite, [user_state, code_box], [room_state, invite_status])
134
+
135
+ with gr.Tab("Chat"):
136
+ chat_html = gr.HTML(elem_classes="chatbox")
137
+ msg = gr.Textbox(placeholder="Type message and press Enter...", show_label=False)
138
+
139
+ msg.submit(send_message, [user_state, room_state, msg], None)
140
+
141
+ timer = gr.Timer(1)
142
+ timer.tick(fetch_messages, [room_state, user_state], chat_html)
143
+
144
+ with gr.Tab("Voice / Video"):
145
+ gr.Markdown("Allow camera & microphone to start secure conversation.")
146
+ gr.HTML("""
147
+ <video id="v" autoplay muted style="width:70%;border-radius:14px;"></video>
148
+ <script>
149
+ navigator.mediaDevices.getUserMedia({video:true,audio:true})
150
+ .then(s=>{document.getElementById("v").srcObject=s;});
151
+ </script>
152
+ """)
153
+
154
+ app.launch()