Jofax commited on
Commit
cbbafe4
·
verified ·
1 Parent(s): 2f91b4b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -68
app.py CHANGED
@@ -1,104 +1,82 @@
1
  import os
2
- import requests
3
  from flask import Flask, request, jsonify, render_template
4
  from flask_sqlalchemy import SQLAlchemy
5
  from datetime import datetime, timedelta
6
- from twilio.twiml.messaging_response import MessagingResponse
7
 
8
  app = Flask(__name__)
9
 
10
- # --- Configuration ---
11
- app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///odistay.db'
 
 
 
12
  app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
13
  db = SQLAlchemy(app)
14
 
15
- # --- Database Models (The Neural Grid) ---
16
  class StayNode(db.Model):
17
  id = db.Column(db.Integer, primary_key=True)
18
  name = db.Column(db.String(100), nullable=False)
19
- category = db.Column(db.String(50)) # Resort, Guesthouse, Safari, Urban
 
20
  lat = db.Column(db.Float)
21
  lng = db.Column(db.Float)
22
- whatsapp_number = db.Column(db.String(20))
23
- rooms_available = db.Column(db.Integer, default=0)
24
- last_updated = db.Column(db.DateTime, default=datetime.utcnow)
25
  is_active = db.Column(db.Boolean, default=False)
 
26
 
27
- # --- Logic: Stay-Motion Sync ---
28
- def get_vessels_near(lat, lng, radius=10):
29
- """Fetch live data from FollowMe.mv (Simulated API Logic)"""
30
- # In a real scenario, you'd scrape or use FollowMe's public feed
31
- # For now, we return a structured sync object
32
  return [
33
- {"name": "Dhigurah Express", "eta": "15 mins", "dist": "2km", "link": "https://m.followme.mv/public/123"},
34
- {"name": "Supply Dhoni 04", "eta": "1 hr", "dist": "12km", "link": "https://m.followme.mv/public/456"}
35
  ]
36
 
37
- # --- Route: The Global Map (Customer View) ---
38
  @app.route('/')
39
  def index():
40
- # Filter only nodes with active tokens (updated in last 24hrs)
41
- expiry_limit = datetime.utcnow() - timedelta(hours=24)
42
- active_stays = StayNode.query.filter(StayNode.last_updated > expiry_limit, StayNode.is_active == True).all()
43
- return render_template('map.html', stays=active_stays)
 
44
 
45
- # --- Route: WhatsApp Bot (Admin Portal) ---
46
- @app.route('/whatsapp/webhook', methods=['POST'])
47
- def whatsapp_bot():
48
- incoming_msg = request.values.get('Body', '').upper()
49
- sender_number = request.values.get('From', '')
50
- response = MessagingResponse()
51
- msg = response.message()
52
-
53
- # Find host by phone number
54
- host = StayNode.query.filter_by(whatsapp_number=sender_number).first()
55
 
56
- if not host:
57
- msg.body("Welcome to OdiStay. Please register your property first at odistay.mv")
58
- return str(response)
59
 
60
- # Command Logic: "AVAIL [rooms]" or "FULL"
61
- if "AVAIL" in incoming_msg:
62
  try:
63
- count = int(incoming_msg.split()[-1])
64
- host.rooms_available = count
65
  host.is_active = True
66
- host.last_updated = datetime.utcnow()
67
  db.session.commit()
68
- msg.body(f"OdiStay Grid Updated! {host.name} is now LIVE with {count} rooms.")
69
- except:
70
- msg.body("Format error. Use: AVAIL 2")
71
-
72
- elif "FULL" in incoming_msg:
73
  host.is_active = False
74
  db.session.commit()
75
- msg.body(f"Status updated: {host.name} is now marked as FULL.")
76
-
77
- return str(response)
78
 
79
- # --- Route: Sync API (Logistics Coupling) ---
80
- @app.route('/api/sync/<int:stay_id>')
81
- def sync_stay(stay_id):
82
- stay = StayNode.query.get_or_404(stay_id)
83
- vessels = get_vessels_near(stay.lat, stay.lng)
84
- return jsonify({
85
- "stay": stay.name,
86
- "rooms": stay.rooms_available,
87
- "vessels_nearby": vessels
88
- })
89
 
90
- if __name__ == '__main__':
91
  with app.app_context():
92
  db.create_all()
93
- # Initial Seed Node
94
  if not StayNode.query.first():
95
- seed = StayNode(
96
- name="Sunny Suites Hulhumale",
97
- category="Urban",
98
- lat=4.212, lng=73.542,
99
- whatsapp_number="whatsapp:+9607770000",
100
- is_active=True
101
- )
102
- db.session.add(seed)
103
  db.session.commit()
104
- app.run(debug=True, port=5000)
 
 
 
1
  import os
 
2
  from flask import Flask, request, jsonify, render_template
3
  from flask_sqlalchemy import SQLAlchemy
4
  from datetime import datetime, timedelta
5
+ import requests
6
 
7
  app = Flask(__name__)
8
 
9
+ # --- Archipelagic Persistence ---
10
+ # Hugging Face provides /data for persistent storage if enabled
11
+ PERSISTENT_DIR = "/data" if os.path.exists("/data") else "."
12
+ db_path = os.path.join(PERSISTENT_DIR, "odistay.db")
13
+ app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{db_path}'
14
  app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
15
  db = SQLAlchemy(app)
16
 
17
+ # --- The Data Models ---
18
  class StayNode(db.Model):
19
  id = db.Column(db.Integer, primary_key=True)
20
  name = db.Column(db.String(100), nullable=False)
21
+ island = db.Column(db.String(50))
22
+ category = db.Column(db.String(20)) # Resort, Guesthouse, Safari
23
  lat = db.Column(db.Float)
24
  lng = db.Column(db.Float)
25
+ whatsapp = db.Column(db.String(20), unique=True)
26
+ rooms = db.Column(db.Integer, default=0)
 
27
  is_active = db.Column(db.Boolean, default=False)
28
+ last_pulse = db.Column(db.DateTime, default=datetime.utcnow)
29
 
30
+ # --- Logic: FollowMe Sync Simulation ---
31
+ def get_live_vessels():
32
+ # In production, this scrapes or calls the FollowMe API
 
 
33
  return [
34
+ {"name": "Dhigurah Express", "type": "Speedboat", "lat": 4.17, "lng": 73.51, "status": "En-route"},
35
+ {"name": "Baa Cargo", "type": "Supply", "lat": 4.20, "lng": 73.55, "status": "Docked"}
36
  ]
37
 
38
+ # --- Routes ---
39
  @app.route('/')
40
  def index():
41
+ # Only show nodes that have "pulsed" in the last 24 hours (Real-time Truth)
42
+ expiry = datetime.utcnow() - timedelta(hours=24)
43
+ active_stays = StayNode.query.filter(StayNode.last_pulse > expiry, StayNode.is_active == True).all()
44
+ vessels = get_live_vessels()
45
+ return render_template('index.html', stays=active_stays, vessels=vessels)
46
 
47
+ @app.route('/whatsapp', methods=['POST'])
48
+ def whatsapp_webhook():
49
+ # This acts as the OdiStay Admin Portal
50
+ incoming = request.values.get('Body', '').upper()
51
+ sender = request.values.get('From', '')
 
 
 
 
 
52
 
53
+ host = StayNode.query.filter_by(whatsapp=sender).first()
54
+ if not host: return "Unauthorized", 403
 
55
 
56
+ if "AVAIL" in incoming:
 
57
  try:
58
+ count = int(incoming.split()[-1])
59
+ host.rooms = count
60
  host.is_active = True
61
+ host.last_pulse = datetime.utcnow()
62
  db.session.commit()
63
+ return "Success"
64
+ except: return "Format Error", 400
65
+
66
+ if "FULL" in incoming:
 
67
  host.is_active = False
68
  db.session.commit()
69
+ return "Closed"
 
 
70
 
71
+ return "OK"
 
 
 
 
 
 
 
 
 
72
 
73
+ if __name__ == "__main__":
74
  with app.app_context():
75
  db.create_all()
76
+ # Seed local nodes for testing if DB is empty
77
  if not StayNode.query.first():
78
+ db.session.add(StayNode(name="OdiStay Sample Maafushi", island="Maafushi", category="Guesthouse", lat=3.94, lng=73.48, whatsapp="whatsapp:+9607770000", is_active=True))
 
 
 
 
 
 
 
79
  db.session.commit()
80
+
81
+ # Port 7860 is mandatory for Hugging Face
82
+ app.run(host="0.0.0.0", port=7860, debug=False, use_reloader=False)