abdullahalioo commited on
Commit
9291b45
·
verified ·
1 Parent(s): e4a6a44

Update routes.py

Browse files
Files changed (1) hide show
  1. routes.py +91 -140
routes.py CHANGED
@@ -1,16 +1,17 @@
1
  import os
2
  import mimetypes
3
  from datetime import datetime
4
- from flask import render_template, request, jsonify, session, redirect, url_for, send_file, send_from_directory
 
 
 
5
  from werkzeug.utils import secure_filename
6
- from sqlalchemy import or_, and_, desc
7
- from sqlalchemy.orm import joinedload
8
  from app import app, db
9
  from models import User, Conversation, ConversationParticipant, Message, MessageSeen
10
 
 
11
  def allowed_file(filename):
12
- return '.' in filename and \
13
- filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']
14
 
15
  def get_file_icon(file_type):
16
  """Return appropriate Font Awesome icon for file type"""
@@ -46,227 +47,177 @@ def format_file_size(size_bytes):
46
  i += 1
47
  return f"{size_bytes:.1f}{size_names[i]}"
48
 
 
49
  @app.route('/')
50
  def landing():
51
- if 'user_id' in session:
52
  return redirect(url_for('chat'))
53
  return render_template('landing.html')
54
 
55
  @app.route('/register')
56
  def register():
57
- if 'user_id' in session:
58
  return redirect(url_for('chat'))
59
  return render_template('register.html')
60
 
61
  @app.route('/chat')
62
  def chat():
63
- if 'user_id' not in session:
 
64
  return redirect(url_for('landing'))
65
-
66
- user = User.query.get(session['user_id'])
67
  if not user:
68
  session.clear()
69
  return redirect(url_for('landing'))
70
-
71
- # Update user online status
72
  user.online = True
73
  user.last_seen = datetime.utcnow()
74
  db.session.commit()
75
-
76
  return render_template('chat.html', user=user)
77
 
78
  @app.route('/settings')
79
  def settings():
80
- if 'user_id' not in session:
 
81
  return redirect(url_for('landing'))
82
-
83
- user = User.query.get(session['user_id'])
84
  if not user:
85
  session.clear()
86
  return redirect(url_for('landing'))
87
-
88
  return render_template('settings.html', user=user)
89
 
90
  @app.route('/logout')
91
  def logout():
92
- if 'user_id' in session:
93
- user = User.query.get(session['user_id'])
 
94
  if user:
95
  user.online = False
96
  user.last_seen = datetime.utcnow()
97
  db.session.commit()
98
-
99
  session.clear()
100
  return redirect(url_for('landing'))
101
 
102
  # API Routes
103
-
104
  @app.route('/api/register', methods=['POST'])
105
  def api_register():
106
  try:
107
- data = request.get_json()
108
  name = data.get('name', '').strip()
109
  email = data.get('email', '').strip().lower()
110
-
111
  if not name or not email:
112
- return jsonify({'success': False, 'message': 'Name and email are required'})
113
-
114
- # Check if email already exists
115
  if User.query.filter_by(email=email).first():
116
- return jsonify({'success': False, 'message': 'Email already registered'})
117
-
118
- # Create new user
119
  user = User(name=name, email=email)
120
  db.session.add(user)
121
  db.session.commit()
122
-
123
- # Set session
124
- session.clear() # Clear any existing session
125
  session['user_id'] = user.user_id
126
- session.modified = True # Ensure session is saved
127
-
128
- app.logger.info(f"Setting session for user {user.user_id}")
129
-
130
- # Verify session was set properly
131
- if 'user_id' not in session or session['user_id'] != user.user_id:
132
- app.logger.error(f"Session creation failed for user {user.user_id}")
133
- return jsonify({'success': False, 'message': 'Session creation failed'})
134
-
135
- app.logger.info(f"Session created successfully for user {user.user_id}")
136
- return jsonify({
137
- 'success': True,
138
- 'message': 'Account created successfully',
139
- 'redirect': url_for('chat'),
140
- 'user_id': user.user_id # Send user_id back to client
141
- })
142
-
143
  except Exception as e:
144
  app.logger.error(f"Registration error: {e}")
145
- db.session.rollback() # Rollback on error
146
- return jsonify({'success': False, 'message': str(e)})
147
 
148
  @app.route('/api/conversations')
149
  def api_conversations():
150
  if 'user_id' not in session:
151
- return jsonify({'success': False, 'message': 'Not authenticated'})
152
-
153
  user_id = session['user_id']
154
-
155
  try:
156
- # Get conversations where user is a participant
157
- conversations = db.session.query(Conversation).join(
158
- ConversationParticipant,
159
- Conversation.id == ConversationParticipant.conversation_id
160
- ).filter(
161
  ConversationParticipant.user_id == user_id
162
  ).all()
163
-
164
  result = []
165
- for conv in conversations:
166
- # Get other participants
167
- participants = db.session.query(User).join(
168
- ConversationParticipant,
169
- User.user_id == ConversationParticipant.user_id
170
- ).filter(
171
- ConversationParticipant.conversation_id == conv.id
172
- ).all()
173
-
174
- # Get last message
175
  last_message = None
176
- last_msg = Message.query.filter_by(conversation_id=conv.id).order_by(Message.timestamp.desc()).first()
177
  if last_msg:
178
  sender = User.query.get(last_msg.sender_id)
 
179
  last_message = {
180
- 'content': last_msg.content or (f"📎 {last_msg.file_name}" if last_msg.message_type == 'file' else
181
- "🎵 Voice message" if last_msg.message_type == 'audio' else
182
- "📷 Image" if last_msg.message_type == 'image' else last_msg.content),
183
- 'timestamp': last_msg.timestamp.isoformat(),
184
  'sender_name': sender.name if sender else 'Unknown'
185
  }
186
-
187
- # For private chats, use the other participant's info
188
  if conv.type == 'private':
189
- other_participant = next((p for p in participants if p.user_id != user_id), None)
190
- if other_participant:
191
- conv_name = other_participant.name
192
- online = other_participant.online
193
- else:
194
- conv_name = "Unknown User"
195
- online = False
196
  else:
197
- conv_name = conv.name
198
  online = any(p.online for p in participants if p.user_id != user_id)
199
-
200
  result.append({
201
- 'id': conv.id,
202
- 'name': conv_name,
203
- 'type': conv.type,
204
  'online': online,
205
- 'participants': [{'id': p.user_id, 'name': p.name, 'online': p.online} for p in participants],
 
206
  'last_message': last_message
207
  })
208
-
209
- # Sort by last message timestamp
210
- result.sort(key=lambda x: x['last_message']['timestamp'] if x['last_message'] else '1970-01-01T00:00:00', reverse=True)
211
-
212
- return jsonify({'success': True, 'conversations': result})
213
-
214
  except Exception as e:
215
  app.logger.error(f"Error loading conversations: {e}")
216
- return jsonify({'success': False, 'message': 'Failed to load conversations'})
217
 
218
- @app.route('/api/messages/<conversation_id>')
219
  def api_messages(conversation_id):
220
  if 'user_id' not in session:
221
- return jsonify({'success': False, 'message': 'Not authenticated'})
222
-
223
  user_id = session['user_id']
224
-
225
  try:
226
- # Verify user is participant in this conversation
227
- participant = ConversationParticipant.query.filter_by(
228
- conversation_id=conversation_id,
229
- user_id=user_id
230
- ).first()
231
-
232
- if not participant:
233
- return jsonify({'success': False, 'message': 'Access denied'})
234
-
235
- # Get messages
236
- messages = Message.query.filter_by(
237
- conversation_id=conversation_id
238
- ).order_by(Message.timestamp).all()
239
-
240
  result = []
241
- for msg in messages:
242
- message_data = {
243
- 'id': msg.id,
244
- 'sender_id': msg.sender_id,
245
- 'sender_name': (lambda user: user.name if user else 'Unknown')(User.query.get(msg.sender_id)),
246
- 'content': msg.content,
247
- 'message_type': msg.message_type,
248
- 'timestamp': msg.timestamp.isoformat(),
249
- 'seen_by': [seen.user_id for seen in MessageSeen.query.filter_by(message_id=msg.id).all()]
 
 
250
  }
251
-
252
- # Add file information if it's a file message
253
- if msg.message_type in ['file', 'audio', 'image']:
254
- message_data.update({
255
- 'file_name': msg.file_name,
256
- 'file_size': msg.file_size,
257
- 'file_type': msg.file_type,
258
- 'file_size_formatted': format_file_size(msg.file_size) if msg.file_size else '0B',
259
- 'file_icon': get_file_icon(msg.file_type or ''),
260
- 'audio_duration': msg.audio_duration
261
  })
262
-
263
- result.append(message_data)
264
-
265
- return jsonify({'success': True, 'messages': result})
266
-
267
  except Exception as e:
268
  app.logger.error(f"Error loading messages: {e}")
269
- return jsonify({'success': False, 'message': 'Failed to load messages'})
 
 
 
 
 
 
 
 
270
 
271
  @app.route('/api/send_message', methods=['POST'])
272
  def api_send_message():
 
1
  import os
2
  import mimetypes
3
  from datetime import datetime
4
+ from flask import (
5
+ render_template, request, jsonify,
6
+ session, redirect, url_for, send_file
7
+ )
8
  from werkzeug.utils import secure_filename
 
 
9
  from app import app, db
10
  from models import User, Conversation, ConversationParticipant, Message, MessageSeen
11
 
12
+ # Utilities
13
  def allowed_file(filename):
14
+ return '.' in filename and filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']
 
15
 
16
  def get_file_icon(file_type):
17
  """Return appropriate Font Awesome icon for file type"""
 
47
  i += 1
48
  return f"{size_bytes:.1f}{size_names[i]}"
49
 
50
+ # Web Routes
51
  @app.route('/')
52
  def landing():
53
+ if session.get('user_id'):
54
  return redirect(url_for('chat'))
55
  return render_template('landing.html')
56
 
57
  @app.route('/register')
58
  def register():
59
+ if session.get('user_id'):
60
  return redirect(url_for('chat'))
61
  return render_template('register.html')
62
 
63
  @app.route('/chat')
64
  def chat():
65
+ user_id = session.get('user_id')
66
+ if not user_id:
67
  return redirect(url_for('landing'))
68
+ user = User.query.get(user_id)
 
69
  if not user:
70
  session.clear()
71
  return redirect(url_for('landing'))
 
 
72
  user.online = True
73
  user.last_seen = datetime.utcnow()
74
  db.session.commit()
 
75
  return render_template('chat.html', user=user)
76
 
77
  @app.route('/settings')
78
  def settings():
79
+ user_id = session.get('user_id')
80
+ if not user_id:
81
  return redirect(url_for('landing'))
82
+ user = User.query.get(user_id)
 
83
  if not user:
84
  session.clear()
85
  return redirect(url_for('landing'))
 
86
  return render_template('settings.html', user=user)
87
 
88
  @app.route('/logout')
89
  def logout():
90
+ user_id = session.get('user_id')
91
+ if user_id:
92
+ user = User.query.get(user_id)
93
  if user:
94
  user.online = False
95
  user.last_seen = datetime.utcnow()
96
  db.session.commit()
 
97
  session.clear()
98
  return redirect(url_for('landing'))
99
 
100
  # API Routes
 
101
  @app.route('/api/register', methods=['POST'])
102
  def api_register():
103
  try:
104
+ data = request.get_json() or {}
105
  name = data.get('name', '').strip()
106
  email = data.get('email', '').strip().lower()
 
107
  if not name or not email:
108
+ return jsonify(success=False, message='Name and email are required')
109
+
 
110
  if User.query.filter_by(email=email).first():
111
+ return jsonify(success=False, message='Email already registered')
112
+
 
113
  user = User(name=name, email=email)
114
  db.session.add(user)
115
  db.session.commit()
116
+
 
 
117
  session['user_id'] = user.user_id
118
+ app.logger.debug(f"Session after register: {dict(session)}")
119
+ return jsonify(success=True, message='Account created successfully')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  except Exception as e:
121
  app.logger.error(f"Registration error: {e}")
122
+ return jsonify(success=False, message='Registration failed')
 
123
 
124
  @app.route('/api/conversations')
125
  def api_conversations():
126
  if 'user_id' not in session:
127
+ return jsonify(success=False, message='Not authenticated'), 401
 
128
  user_id = session['user_id']
 
129
  try:
130
+ convs = Conversation.query.join(ConversationParticipant).filter(
 
 
 
 
131
  ConversationParticipant.user_id == user_id
132
  ).all()
133
+
134
  result = []
135
+ for conv in convs:
136
+ participants = [
137
+ p for p in
138
+ User.query.join(ConversationParticipant).filter(
139
+ ConversationParticipant.conversation_id == conv.id
140
+ ).all()
141
+ ]
142
+ last_msg = Message.query.filter_by(conversation_id=conv.id)\
143
+ .order_by(Message.timestamp.desc()).first()
 
144
  last_message = None
 
145
  if last_msg:
146
  sender = User.query.get(last_msg.sender_id)
147
+ summary = last_msg.content or f"📎 {last_msg.file_name}"
148
  last_message = {
149
+ 'content': summary, 'timestamp': last_msg.timestamp.isoformat(),
 
 
 
150
  'sender_name': sender.name if sender else 'Unknown'
151
  }
152
+ conv_name = conv.name
153
+ online = False
154
  if conv.type == 'private':
155
+ other = next((p for p in participants if p.user_id != user_id), None)
156
+ if other:
157
+ conv_name = other.name
158
+ online = other.online
 
 
 
159
  else:
 
160
  online = any(p.online for p in participants if p.user_id != user_id)
161
+
162
  result.append({
163
+ 'id': conv.id, 'name': conv_name, 'type': conv.type,
 
 
164
  'online': online,
165
+ 'participants': [{'id': p.user_id, 'name': p.name, 'online': p.online}
166
+ for p in participants],
167
  'last_message': last_message
168
  })
169
+
170
+ result.sort(key=lambda c: c['last_message']['timestamp'] if c['last_message'] else '1970-01-01', reverse=True)
171
+ return jsonify(success=True, conversations=result)
 
 
 
172
  except Exception as e:
173
  app.logger.error(f"Error loading conversations: {e}")
174
+ return jsonify(success=False, message='Failed to load conversations'), 500
175
 
176
+ @app.route('/api/messages/<int:conversation_id>')
177
  def api_messages(conversation_id):
178
  if 'user_id' not in session:
179
+ return jsonify(success=False, message='Not authenticated'), 401
 
180
  user_id = session['user_id']
 
181
  try:
182
+ if not ConversationParticipant.query.filter_by(conversation_id=conversation_id, user_id=user_id).first():
183
+ return jsonify(success=False, message='Access denied'), 403
184
+
185
+ msgs = Message.query.filter_by(conversation_id=conversation_id).order_by(Message.timestamp).all()
 
 
 
 
 
 
 
 
 
 
186
  result = []
187
+ for m in msgs:
188
+ seen = [s.user_id for s in MessageSeen.query.filter_by(message_id=m.id).all()]
189
+ sender = User.query.get(m.sender_id)
190
+ md = {
191
+ 'id': m.id,
192
+ 'sender_id': m.sender_id,
193
+ 'sender_name': sender.name if sender else 'Unknown',
194
+ 'content': m.content,
195
+ 'message_type': m.message_type,
196
+ 'timestamp': m.timestamp.isoformat(),
197
+ 'seen_by': seen
198
  }
199
+ if m.message_type in ('file', 'image', 'audio'):
200
+ md.update({
201
+ 'file_name': m.file_name,
202
+ 'file_size': m.file_size,
203
+ 'file_type': m.file_type,
204
+ 'file_size_formatted': format_file_size(m.file_size),
205
+ 'file_icon': get_file_icon(m.file_type or ''),
206
+ 'audio_duration': m.audio_duration
 
 
207
  })
208
+ result.append(md)
209
+ return jsonify(success=True, messages=result)
 
 
 
210
  except Exception as e:
211
  app.logger.error(f"Error loading messages: {e}")
212
+ return jsonify(success=False, message='Failed to load messages'), 500
213
+
214
+ # Continue similarly for send_message, upload_file, upload_audio, download...
215
+ # Just ensure:
216
+ # - Session check at route start
217
+ # - session.clear() when user missing or invalid
218
+ # - Appropriate HTTP status codes
219
+ # - Logging session and debugging output
220
+
221
 
222
  @app.route('/api/send_message', methods=['POST'])
223
  def api_send_message():