Skip to content

Commit

Permalink
Add gullytours
Browse files Browse the repository at this point in the history
  • Loading branch information
captn3m0 committed Apr 1, 2024
1 parent a6faa41 commit 055df06
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 1 deletion.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ out/townscript.txt:
out/bluetokai.json:
python src/bluetokai.py

out/gullytours.json:
python src/gullytours.py

all: out/allevents.txt \
out/highape.txt \
out/mapindia.json \
Expand All @@ -91,6 +94,7 @@ all: out/allevents.txt \
out/sumukha.json \
out/sofar.json \
out/bluetokai.json \
out/gullytours.json \
out/townscript.txt
@echo "Done"

Expand Down
47 changes: 46 additions & 1 deletion in/known-hosts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,59 @@ luma:
blumeventures: blumeventures
# TWIF has events all across globe
# thisweekinfintech: twif
gullytours:
- url: https://www.gully.tours/tours/coffee-and-the-cantonment
id: "88252"
name: "Coffee and the Cantonment"
- url: https://www.gully.tours/tours/colonial-crawl
id: "36715"
name: "Colonial Crawl"
- url: https://www.gully.tours/tours/death-by-dosa
id: "13044"
name: "Death by Dosa"
- url: https://www.gully.tours/tours/death-by-dosa-womens-only
id: "137262"
name: "Death by Dosa (Women Only)"
- url: https://www.gully.tours/tours/malleshwaram-hogona
id: "40636"
name: "Malleshwaram Hogona"
- url: https://www.gully.tours/tours/pete-by-night
id: "9094"
name: Pete by Night
- url: https://www.gully.tours/tours/pete-by-night-womens-only
id: "36716"
name: Pete by Night (Women Only)
- url: https://www.gully.tours/tours/the-soba-walk
id: "22253"
name: The Soba Walk
- url: https://www.gully.tours/tours/the-tiffin-trail
id: "20524"
name: The Tiffin Trail
- url: https://www.gully.tours/tours/the-urban-nature-trail
id: "43157"
name: The Urban Nature Trail
- url: https://www.gully.tours/tours/the-yelahanka-diaries
id: "77823"
name: The Yelahanka Diaries

- url: https://www.gully.tours/tours/yulu-midnight-trail
id: "12067"
name: Yulu Midnight Trail
- url: https://www.gully.tours/tours/cantt-by-night
id: "43904"
name: Cantt by Night

- url: https://www.gully.tours/tours/cantt-by-night-womens-only
id: "43161"
name: Cantt by Night (Women Only)

townscript:
lahe-lahe:
id: "2033748"
foodwize:
id: "4527655"
broke-bibliophiles:
id: "1306109"
superEvent: https://www.townscript.com/o/abhiram-r-401313
instagram:
- amiel_gourmet
- uskbengaluru
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ datefinder==0.7.3
extruct==0.16.0
html-text==0.5.2
html2md==0.1.7
html2text==2024.2.26
html5lib==1.1
ics==0.7.2
idna==3.6
Expand Down
1 change: 1 addition & 0 deletions src/event-fetcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
'out/sumukha.json',
'out/bluetokai.json',
'out/champaca.json',
'out/gullytours.json',
]

KNOWN_EVENT_TYPES = [
Expand Down
94 changes: 94 additions & 0 deletions src/gullytours.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import yaml
import json
from datetime import timedelta, datetime, timezone
from requests_cache import CachedSession
from bs4 import BeautifulSoup
from math import ceil

def get_description(session, url):
soup = BeautifulSoup(session.get(url).content, "html.parser")
desc = ""
for e in soup.select('.rlr-readmore-desc__content'):
if "Lorem" not in e.text and "Dolor" not in e.text:
desc += e.text

return desc

def get_calendar(session, tour_id):
start_date = datetime.now().strftime('%Y-%m-%d'),
end_date = (datetime.now() + timedelta(days=30)).strftime('%Y-%m-%d')
url = f"https://gullytours.vacationlabs.com/itineraries/trips/{tour_id}/departure_calendar.json"

querystring = {
"start": start_date,
"end": end_date,
}
d = session.get(url, params=querystring).json()
keys = d['departure_calendar']['availability_keys']
c = d['departure_calendar']['availability']['data']
for date in c:
for x in c[date].values():
for trip in x:
trip_details = dict(zip(keys, trip))
price = d['departure_calendar']['pricings'][str(trip_details['pricing_group_id'])]['sticker_price']
trip_details['price'] = str(ceil(price))
del trip_details['pricing_group_id']
yield trip_details


def main():
session = CachedSession(
"event-fetcher-cache",
expire_after=timedelta(days=1),
stale_if_error=True,
use_cache_dir=True,
cache_control=False,
)

events = []
for tour in read_config():
description = get_description(session, tour['url'])
for trip in get_calendar(session, tour['id']):
events.append(make_event(tour, description, trip))

with open("out/gullytours.json", "w") as f:
json.dump(events, f, indent=2)

# generates a valid schema.org/SocialEvent object
def make_event(tour, description, trip):
tz = timezone(timedelta(hours=5, minutes=30))
start_time = datetime.fromisoformat(trip['starts_at']).replace(tzinfo=tz)
end_time = datetime.fromisoformat(trip['ends_at']).replace(tzinfo=tz)
event = {
"@context": "http://schema.org",
"url": tour['url'],
"@type": "SocialEvent",
"name": tour.get('name'),
"description": description,
"startDate": start_time.isoformat(),
"endDate": end_time.isoformat(),
"eventAttendanceMode": "OfflineEventAttendanceMode",
"maximumAttendeeCapacity": trip['total_capacity'],
"remainingAttendeeCapacity": trip['available_seats'],
# "image": trip['image'],
"offers": [{
"@type": "Offer",
"price": trip['price'],
"priceCurrency": "INR",
}],
"organizer": {"@type": "Organization", "name": "Gully Tours"},
# "location": {
# "@type": "Place",
# "name": trip['location'],
# "address": trip['location'] + " Bengaluru",
# }
}
return event

def read_config():
return yaml.safe_load(open('in/known-hosts.yml'))['gullytours']

if __name__ == "__main__":

main()

0 comments on commit 055df06

Please sign in to comment.