1+ import requests
2+ from asgiref .sync import async_to_sync
3+ from bs4 import BeautifulSoup
14from celery import shared_task
25from celery .utils .log import get_task_logger
6+ from channels .layers import get_channel_layer
7+ from django .utils import timezone
38
49from .models import Route
510
@@ -12,3 +17,54 @@ def reset_routes() -> None:
1217
1318 for route in Route .objects .all ():
1419 route .reset_status ()
20+
21+
22+ @shared_task
23+ def fetch_fcps_bus_delays ():
24+ now = timezone .localtime (timezone .now ())
25+ # Check if the current time is within 6-9 AM or 3-6 PM from Mon-Fri
26+ if now .weekday () in (5 , 6 ):
27+ return
28+ if not (now .hour in range (6 , 9 ) or now .hour in range (15 , 18 )):
29+ return
30+ url = "https://busdelay.fcps.edu"
31+ try :
32+ response = requests .get (url , timeout = 10 )
33+ response .raise_for_status ()
34+ except Exception as e :
35+ logger .error ("Error fetching URL: %s" , e )
36+ return
37+
38+ soup = BeautifulSoup (response .text , "html.parser" )
39+ rows = soup .select ("table tr" )
40+ # In case a row is formatted incorrectly, check the amount of cells to make sure it contains all information
41+ if not rows or len (rows ) < 2 :
42+ logger .warning ("Not a complete row with all bus information" )
43+ return
44+ # Sort out the JEFFERSON HIGH bus delays
45+ for row in rows [1 :]:
46+ cells = row .find_all ("td" )
47+ if len (cells ) >= 4 and cells [0 ].text .strip () == "JEFFERSON HIGH" :
48+ route_name = cells [1 ].text .strip ().split ()[0 ]
49+ reason = cells [3 ].text .strip ()
50+ try :
51+ obj = Route .objects .get (route_name = route_name )
52+ # Only can update the status if it is on default status (on time)
53+ if obj .status != "a" :
54+ obj .status = "d"
55+ obj .reason = reason
56+ obj .save (update_fields = ["status" , "reason" ])
57+ logger .info ("Updated route %s with delay: %s" , route_name , reason )
58+ channel_layer = get_channel_layer ()
59+ all_routes = list (Route .objects .values ())
60+ async_to_sync (channel_layer .group_send )(
61+ "bus" ,
62+ {
63+ "type" : "bus.update" ,
64+ "message" : {
65+ "allRoutes" : all_routes ,
66+ },
67+ },
68+ )
69+ except Route .DoesNotExist :
70+ logger .error ("Route with route_name %s does not exist" , route_name )
0 commit comments