Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
coverage: airports search + merchant resolver +718, Titan caps, GRT + Surat Diamond offers
Browse files- app/airports.py +188 -0
- app/airports_data.json +0 -0
- app/card_catalogue.py +5 -1
- app/geo.py +11 -0
- app/main.py +29 -3
- app/merchants.py +745 -0
- app/offers_data/curated_offers.json +0 -0
app/airports.py
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Comprehensive airport search + resolution for the Flights composer.
|
| 3 |
+
|
| 4 |
+
Replaces the ~87-entry hardcoded CITY_IATA map with the full IATA airport
|
| 5 |
+
dataset (7,884 airports, every Indian one). The From/To inputs become a
|
| 6 |
+
type-to-search box that calls search(); flight search calls resolve() to turn
|
| 7 |
+
any typed city or code into the IATA(s) Google Flights speaks; geo classifies a
|
| 8 |
+
route by the airports' COUNTRY, so any route resolves domestic/international -
|
| 9 |
+
not just the ~90 cities that used to be enumerated.
|
| 10 |
+
|
| 11 |
+
Data ships as airports_data.json (generated from the `airportsdata` package) so
|
| 12 |
+
the Space has no runtime dependency on the package.
|
| 13 |
+
"""
|
| 14 |
+
import json, os, re, functools, unicodedata
|
| 15 |
+
from typing import List, Dict, Optional
|
| 16 |
+
|
| 17 |
+
_HERE = os.path.dirname(os.path.abspath(__file__))
|
| 18 |
+
with open(os.path.join(_HERE, "airports_data.json")) as _f:
|
| 19 |
+
_RAW = json.load(_f)
|
| 20 |
+
|
| 21 |
+
# rows: [iata, city, name, country, subd]
|
| 22 |
+
_ROWS = _RAW["airports"]
|
| 23 |
+
METROS: Dict[str, str] = _RAW["metros"]
|
| 24 |
+
_PRIMARY = set(_RAW.get("primary", []))
|
| 25 |
+
_ALIASES: Dict[str, str] = {k.lower(): v for k, v in _RAW["aliases"].items()}
|
| 26 |
+
|
| 27 |
+
def _strip(s: str) -> str:
|
| 28 |
+
return "".join(c for c in unicodedata.normalize("NFKD", s or "") if not unicodedata.combining(c))
|
| 29 |
+
|
| 30 |
+
def _norm(s: str) -> str:
|
| 31 |
+
return _strip(re.sub(r"\s+", " ", (s or "").strip().lower()))
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
# The airport dataset carries several Indian cities under their OLD names
|
| 35 |
+
# (Calicut, Mysore, Mangalore, Pondicherry, Allahabad...). Show the CURRENT name
|
| 36 |
+
# people type, and keep the old/colloquial name searchable so BOTH resolve - a
|
| 37 |
+
# search for "Kozhikode" and one for "Calicut" must both find CCJ.
|
| 38 |
+
_CITY_FIX = {
|
| 39 |
+
"CCJ": "Kozhikode", "MYQ": "Mysuru", "IXE": "Mangaluru", "PNY": "Puducherry",
|
| 40 |
+
"VTZ": "Visakhapatnam", "IXD": "Prayagraj", "IXG": "Belagavi",
|
| 41 |
+
"TCR": "Thoothukudi", "RJA": "Rajahmundry",
|
| 42 |
+
}
|
| 43 |
+
_ALT = {
|
| 44 |
+
"CCJ": "calicut", "MYQ": "mysore", "IXE": "mangalore", "PNY": "pondicherry pondy",
|
| 45 |
+
"VTZ": "vizag vishakhapatnam", "IXD": "allahabad", "IXG": "belgaum",
|
| 46 |
+
"TCR": "tuticorin", "BOM": "bombay", "BLR": "bangalore", "CCU": "calcutta",
|
| 47 |
+
"MAA": "madras", "COK": "cochin ernakulam", "TRV": "trivandrum", "BDQ": "baroda",
|
| 48 |
+
"VNS": "benares banaras", "PNQ": "poona", "IXJ": "jammu", "GAU": "guwahati",
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
BY_IATA: Dict[str, Dict] = {}
|
| 52 |
+
_BY_CITY: Dict[str, list] = {}
|
| 53 |
+
for _iata, _city, _name, _country, _subd in _ROWS:
|
| 54 |
+
_cty = _CITY_FIX.get(_iata, _city or _name)
|
| 55 |
+
rec = {"iata": _iata, "city": _cty, "name": _name, "country": _country, "subd": _subd}
|
| 56 |
+
rec["_c"] = _norm(_cty)
|
| 57 |
+
rec["_n"] = _norm(_name + " " + _ALT.get(_iata, ""))
|
| 58 |
+
rec["_i"] = _iata.lower()
|
| 59 |
+
BY_IATA[_iata] = rec
|
| 60 |
+
_BY_CITY.setdefault((_cty or "").lower(), []).append(rec)
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def is_international(iata_or_country: Optional[str]) -> Optional[bool]:
|
| 65 |
+
"""True if the airport (or the metro's first airport) is outside India.
|
| 66 |
+
None if unknown. Country-based, so EVERY airport classifies correctly."""
|
| 67 |
+
if not iata_or_country:
|
| 68 |
+
return None
|
| 69 |
+
s = iata_or_country.strip().upper()
|
| 70 |
+
if s == "IN":
|
| 71 |
+
return False
|
| 72 |
+
if len(s) == 2: # a country code
|
| 73 |
+
return True
|
| 74 |
+
first = s.split(",")[0]
|
| 75 |
+
rec = BY_IATA.get(first)
|
| 76 |
+
if not rec:
|
| 77 |
+
return None
|
| 78 |
+
return rec["country"] != "IN"
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def label(rec: Dict) -> str:
|
| 82 |
+
"""Human label for a picker row: 'Kochi (COK) - India'."""
|
| 83 |
+
city = rec["city"]
|
| 84 |
+
tail = rec["subd"] if rec["country"] == "IN" and rec["subd"] and rec["subd"].lower() != city.lower() else _country_name(rec["country"])
|
| 85 |
+
return f"{city} ({rec['iata']})" + (f" - {tail}" if tail else "")
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
_COUNTRY = {"IN": "India", "AE": "UAE", "US": "USA", "GB": "UK", "SG": "Singapore",
|
| 89 |
+
"TH": "Thailand", "QA": "Qatar", "SA": "Saudi Arabia", "MY": "Malaysia",
|
| 90 |
+
"LK": "Sri Lanka", "NP": "Nepal", "MV": "Maldives", "ID": "Indonesia"}
|
| 91 |
+
def _country_name(cc: str) -> str:
|
| 92 |
+
return _COUNTRY.get(cc, cc)
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def _score(rec: Dict, q: str) -> int:
|
| 96 |
+
"""Higher = better match for query q (already normalised). Importance boosts
|
| 97 |
+
apply ONLY when the query actually matches, so India airports never leak
|
| 98 |
+
into an unrelated search."""
|
| 99 |
+
iata = rec["_i"]; city = rec["_c"]; name = rec["_n"]
|
| 100 |
+
base = 0
|
| 101 |
+
if q == iata: base += 1000
|
| 102 |
+
if city == q: base += 600
|
| 103 |
+
elif city.startswith(q): base += 400
|
| 104 |
+
elif q in city: base += 220
|
| 105 |
+
if q in name: base += 130
|
| 106 |
+
elif iata.startswith(q): base += 90
|
| 107 |
+
if base == 0:
|
| 108 |
+
return 0
|
| 109 |
+
# importance (no pax data in the set): this is an India-first app, then real
|
| 110 |
+
# intl gateways. Applied only on a genuine match so it breaks ties, never invents them.
|
| 111 |
+
if rec["country"] == "IN": base += 500
|
| 112 |
+
if rec["iata"] in _PRIMARY: base += 350
|
| 113 |
+
if rec["iata"] in METROS: base += 150 # metro-anchor: LHR over LGW, JFK over LGA
|
| 114 |
+
if "international" in name: base += 40
|
| 115 |
+
return base
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
@functools.lru_cache(maxsize=4096)
|
| 119 |
+
def search(q: str, limit: int = 8) -> tuple:
|
| 120 |
+
"""Autocomplete: match on IATA / city / name. Returns a tuple of dicts
|
| 121 |
+
(cached; convert to list at the boundary)."""
|
| 122 |
+
q0 = _norm(q)
|
| 123 |
+
if not q0:
|
| 124 |
+
return tuple()
|
| 125 |
+
q = _norm(_ALIASES.get(q0, q0))
|
| 126 |
+
hits = []
|
| 127 |
+
for rec in BY_IATA.values():
|
| 128 |
+
sc = _score(rec, q)
|
| 129 |
+
if sc > 0:
|
| 130 |
+
hits.append((sc, rec))
|
| 131 |
+
# An alias must never make matching WORSE: if it redirected to a spelling the
|
| 132 |
+
# dataset lacks, fall back to scoring the raw query.
|
| 133 |
+
if not hits and q != q0:
|
| 134 |
+
for rec in BY_IATA.values():
|
| 135 |
+
sc = _score(rec, q0)
|
| 136 |
+
if sc > 0:
|
| 137 |
+
hits.append((sc, rec))
|
| 138 |
+
hits.sort(key=lambda x: (-x[0], x[1]["city"]))
|
| 139 |
+
out = []
|
| 140 |
+
seen = set()
|
| 141 |
+
for _, rec in hits[: limit * 3]:
|
| 142 |
+
key = (rec["city"], rec["country"])
|
| 143 |
+
if rec["iata"] in seen:
|
| 144 |
+
continue
|
| 145 |
+
seen.add(rec["iata"])
|
| 146 |
+
out.append({**rec, "label": label(rec), "intl": rec["country"] != "IN"})
|
| 147 |
+
if len(out) >= limit:
|
| 148 |
+
break
|
| 149 |
+
return tuple(out)
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
def resolve(text: str) -> Optional[str]:
|
| 153 |
+
"""Turn a typed city / IATA / alias into the IATA(s) the flight API speaks.
|
| 154 |
+
Returns a metro comma-list where relevant ('Mumbai' -> 'BOM,NMI'), or None."""
|
| 155 |
+
if not text:
|
| 156 |
+
return None
|
| 157 |
+
t = text.strip()
|
| 158 |
+
# already an IATA (single or metro comma list) - only when typed in caps, so a
|
| 159 |
+
# mixed-case city like "Goa" is read as the city, not the code GOA (Genova).
|
| 160 |
+
if t == t.upper() and re.fullmatch(r"[A-Z]{3}(,[A-Z]{3})*", t):
|
| 161 |
+
return METROS.get(t.split(",")[0], t)
|
| 162 |
+
n = _norm(t)
|
| 163 |
+
n = _norm(_ALIASES.get(n, n))
|
| 164 |
+
# exact city -> prefer the highest-scored airport, apply metro grouping
|
| 165 |
+
res = search(n, limit=1)
|
| 166 |
+
if not res:
|
| 167 |
+
return None
|
| 168 |
+
iata = res[0]["iata"]
|
| 169 |
+
return METROS.get(iata, iata)
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
def cities_for_hotels(q: str, limit: int = 8) -> list:
|
| 173 |
+
"""City suggestions for the hotels/dining city box (dedup by city name)."""
|
| 174 |
+
q = _norm(q)
|
| 175 |
+
if not q:
|
| 176 |
+
return []
|
| 177 |
+
q = _norm(_ALIASES.get(q, q))
|
| 178 |
+
seen, out = set(), []
|
| 179 |
+
for rec in sorted(BY_IATA.values(), key=lambda r: (r["country"] != "IN", r["city"])):
|
| 180 |
+
c = (rec["city"] or "").lower()
|
| 181 |
+
if c and (c.startswith(q) or q in c) and c not in seen:
|
| 182 |
+
seen.add(c)
|
| 183 |
+
out.append({"city": rec["city"], "country": rec["country"],
|
| 184 |
+
"label": f"{rec['city']} - {_country_name(rec['country'])}",
|
| 185 |
+
"intl": rec["country"] != "IN"})
|
| 186 |
+
if len(out) >= limit:
|
| 187 |
+
break
|
| 188 |
+
return out
|
app/airports_data.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
app/card_catalogue.py
CHANGED
|
@@ -1769,7 +1769,11 @@ CATALOGUE += [
|
|
| 1769 |
segment="mid", reward_unit="cashback", point_value_inr=1, base_rate=1.5,
|
| 1770 |
category_rates={},
|
| 1771 |
caps={},
|
| 1772 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1773 |
excluded_categories=["fuel", "wallet_load", "rent", "utilities"],
|
| 1774 |
brand_bonuses={"tanishq": 3, "caratlane": 5, "mia": 5, "zoya": 5, "titan": 7.5, "fastrack": 7.5, "helios": 7.5, "titan_eyeplus": 7.5, "taneira": 7.5, "sonata": 7.5},
|
| 1775 |
upi_eligible=True,
|
|
|
|
| 1769 |
segment="mid", reward_unit="cashback", point_value_inr=1, base_rate=1.5,
|
| 1770 |
category_rates={},
|
| 1771 |
caps={},
|
| 1772 |
+
# Shared quarterly caps (≈ monthly): Tanishq ₹25k/qtr → 8,333/mo; the 5%
|
| 1773 |
+
# jewellery trio (Mia/CaratLane/Zoya) share ₹10k/qtr → 3,333/mo; the 7.5%
|
| 1774 |
+
# Titan-world brands share ₹10k/qtr → 3,333/mo. Every bonused brand must
|
| 1775 |
+
# sit in a cap group or it earns its accelerated rate UNCAPPED.
|
| 1776 |
+
brand_caps=[{"brands": ["tanishq"], "cap": 8333}, {"brands": ["mia", "caratlane", "zoya"], "cap": 3333}, {"brands": ["titan", "fastrack", "helios", "titan_eyeplus", "taneira", "sonata"], "cap": 3333}],
|
| 1777 |
excluded_categories=["fuel", "wallet_load", "rent", "utilities"],
|
| 1778 |
brand_bonuses={"tanishq": 3, "caratlane": 5, "mia": 5, "zoya": 5, "titan": 7.5, "fastrack": 7.5, "helios": 7.5, "titan_eyeplus": 7.5, "taneira": 7.5, "sonata": 7.5},
|
| 1779 |
upi_eligible=True,
|
app/geo.py
CHANGED
|
@@ -11,6 +11,7 @@ Mirrored on-device in app/src/data/geo.ts.
|
|
| 11 |
"""
|
| 12 |
|
| 13 |
from typing import Optional
|
|
|
|
| 14 |
|
| 15 |
# Major Indian airports (domestic when the destination is one of these).
|
| 16 |
INDIA_IATA = {
|
|
@@ -96,6 +97,16 @@ def iata_is_international(code: Optional[str]) -> Optional[bool]:
|
|
| 96 |
continue
|
| 97 |
if not (len(c) == 3 and c.isalpha()):
|
| 98 |
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
all_india = False
|
| 100 |
return False if all_india else True
|
| 101 |
|
|
|
|
| 11 |
"""
|
| 12 |
|
| 13 |
from typing import Optional
|
| 14 |
+
import airports as _ap # comprehensive 7,884-airport dataset (country-based fallback)
|
| 15 |
|
| 16 |
# Major Indian airports (domestic when the destination is one of these).
|
| 17 |
INDIA_IATA = {
|
|
|
|
| 97 |
continue
|
| 98 |
if not (len(c) == 3 and c.isalpha()):
|
| 99 |
return None
|
| 100 |
+
# Consult the full airport dataset before falling back to the heuristic:
|
| 101 |
+
# a real Indian airport MISSING from INDIA_IATA must classify domestic,
|
| 102 |
+
# not international. country=IN -> domestic; a known foreign airport ->
|
| 103 |
+
# international; only a code absent from all 7,884 stays "international,
|
| 104 |
+
# not unknown" (the Indian set is finite; the world's airports are not).
|
| 105 |
+
rec = _ap.BY_IATA.get(c)
|
| 106 |
+
if rec is not None:
|
| 107 |
+
if rec["country"] == "IN":
|
| 108 |
+
continue
|
| 109 |
+
return True
|
| 110 |
all_india = False
|
| 111 |
return False if all_india else True
|
| 112 |
|
app/main.py
CHANGED
|
@@ -307,6 +307,26 @@ def cards():
|
|
| 307 |
return {"cards": [_card_public(c) for c in all_cards()]}
|
| 308 |
|
| 309 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 310 |
@app.get("/offers")
|
| 311 |
def offers():
|
| 312 |
"""All currently-active offers (dated). Fed by the ingestion connectors."""
|
|
@@ -470,14 +490,20 @@ def flights_search(req: FlightSearchRequest, request: Request = None):
|
|
| 470 |
city = normalize_city(req.city)
|
| 471 |
import geo
|
| 472 |
# BOTH endpoints: a return leg into India is still an international trip.
|
| 473 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 474 |
|
| 475 |
# SerpApi's Google Flights results carry a booking token, which is what
|
| 476 |
# unlocks per-platform prices later via /flights/sellers. Prefer it when a
|
| 477 |
# key is configured; otherwise keep the Travelpayouts cached-fare path,
|
| 478 |
# which has no token and therefore no per-platform comparison.
|
| 479 |
flights, source = flight_sellers.search_flights(
|
| 480 |
-
|
| 481 |
adults=req.adults or 1,
|
| 482 |
children=req.children or 0,
|
| 483 |
infants=req.infants or 0,
|
|
@@ -498,7 +524,7 @@ def flights_search(req: FlightSearchRequest, request: Request = None):
|
|
| 498 |
plain_search = (req.cabin or "economy") == "economy" and not (req.children or req.infants)
|
| 499 |
if not flights and plain_search:
|
| 500 |
flights = flights_provider.search_flights(
|
| 501 |
-
|
| 502 |
adults=req.adults or 1, nonstop=req.nonstop or (req.stops == "nonstop"),
|
| 503 |
airlines=req.airlines, max_price=req.max_price,
|
| 504 |
window_days=req.window_days if req.window_days is not None else 3,
|
|
|
|
| 307 |
return {"cards": [_card_public(c) for c in all_cards()]}
|
| 308 |
|
| 309 |
|
| 310 |
+
@app.get("/airports/search")
|
| 311 |
+
def airports_search(q: str = "", limit: int = 8, request: Request = None):
|
| 312 |
+
"""Type-to-search autocomplete over the full 7,884-airport dataset (every
|
| 313 |
+
Indian airport + international). Powers the Flights From/To box. Public +
|
| 314 |
+
rate-limited; no PII, no app key."""
|
| 315 |
+
if request is not None:
|
| 316 |
+
_limit(request, "aps", rate=120)
|
| 317 |
+
import airports
|
| 318 |
+
return {"query": q, "results": list(airports.search(q, min(int(limit or 8), 15)))}
|
| 319 |
+
|
| 320 |
+
|
| 321 |
+
@app.get("/cities/search")
|
| 322 |
+
def cities_search(q: str = "", limit: int = 8, request: Request = None):
|
| 323 |
+
"""City autocomplete for the Hotels/Dining city box (searches by city name)."""
|
| 324 |
+
if request is not None:
|
| 325 |
+
_limit(request, "cts", rate=120)
|
| 326 |
+
import airports
|
| 327 |
+
return {"query": q, "results": airports.cities_for_hotels(q, min(int(limit or 8), 15))}
|
| 328 |
+
|
| 329 |
+
|
| 330 |
@app.get("/offers")
|
| 331 |
def offers():
|
| 332 |
"""All currently-active offers (dated). Fed by the ingestion connectors."""
|
|
|
|
| 490 |
city = normalize_city(req.city)
|
| 491 |
import geo
|
| 492 |
# BOTH endpoints: a return leg into India is still an international trip.
|
| 493 |
+
# Resolve a typed city OR an IATA to the code(s) the flight API speaks: the new
|
| 494 |
+
# searchable From/To sends a picked IATA, but free text ("Kochi", "Goa") also
|
| 495 |
+
# works now via the full airport dataset. Passthrough when already a code.
|
| 496 |
+
import airports as _apx
|
| 497 |
+
src_q = _apx.resolve(req.src) or req.src
|
| 498 |
+
dst_q = _apx.resolve(req.dst) or req.dst
|
| 499 |
+
intl = geo.route_is_international(src_q, dst_q) # international route? offers gate on it
|
| 500 |
|
| 501 |
# SerpApi's Google Flights results carry a booking token, which is what
|
| 502 |
# unlocks per-platform prices later via /flights/sellers. Prefer it when a
|
| 503 |
# key is configured; otherwise keep the Travelpayouts cached-fare path,
|
| 504 |
# which has no token and therefore no per-platform comparison.
|
| 505 |
flights, source = flight_sellers.search_flights(
|
| 506 |
+
src_q, dst_q, req.date,
|
| 507 |
adults=req.adults or 1,
|
| 508 |
children=req.children or 0,
|
| 509 |
infants=req.infants or 0,
|
|
|
|
| 524 |
plain_search = (req.cabin or "economy") == "economy" and not (req.children or req.infants)
|
| 525 |
if not flights and plain_search:
|
| 526 |
flights = flights_provider.search_flights(
|
| 527 |
+
src_q, dst_q, req.date,
|
| 528 |
adults=req.adults or 1, nonstop=req.nonstop or (req.stops == "nonstop"),
|
| 529 |
airlines=req.airlines, max_price=req.max_price,
|
| 530 |
window_days=req.window_days if req.window_days is not None else 3,
|
app/merchants.py
CHANGED
|
@@ -1364,6 +1364,751 @@ MERCHANT_MAP: Dict[str, Tuple[str, Optional[str]]] = {
|
|
| 1364 |
# matrix caught it, 2026-07-29).
|
| 1365 |
}
|
| 1366 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1367 |
# Retailers / merchants preferred over product words so "iPhone at Croma"
|
| 1368 |
# resolves to Croma, not iPhone.
|
| 1369 |
STORE_KEYWORDS = {
|
|
|
|
| 1364 |
# matrix caught it, 2026-07-29).
|
| 1365 |
}
|
| 1366 |
|
| 1367 |
+
# ---------------------------------------------------------------------------
|
| 1368 |
+
# Wider merchant coverage (added 2026-08-08): 719 brand keywords across
|
| 1369 |
+
# every category, folded in from the market sweep. Existing hand-tuned keys
|
| 1370 |
+
# always win (setdefault below), so this only ADDS reach - any store a user
|
| 1371 |
+
# names now resolves to the right category (and a brand key where we have
|
| 1372 |
+
# one) instead of falling through to "general".
|
| 1373 |
+
# ---------------------------------------------------------------------------
|
| 1374 |
+
_PROPOSED_2026_08: Dict[str, Tuple[str, Optional[str]]] = {
|
| 1375 |
+
# --- dining ---
|
| 1376 |
+
"7th heaven": ("dining", "seventh_heaven"),
|
| 1377 |
+
"adigas": ("dining", "adigas"),
|
| 1378 |
+
"amex dining": ("dining", "amex_dining"),
|
| 1379 |
+
"ammi's": ("dining", "ammis_biryani"),
|
| 1380 |
+
"ammis biryani": ("dining", "ammis_biryani"),
|
| 1381 |
+
"anjappar": ("dining", "anjappar"),
|
| 1382 |
+
"barista": ("dining", "barista"),
|
| 1383 |
+
"baskin robbins": ("dining", "baskin_robbins"),
|
| 1384 |
+
"bbk": ("dining", "biryani_by_kilo"),
|
| 1385 |
+
"belgian waffle": ("dining", "belgian_waffle"),
|
| 1386 |
+
"biggies burger": ("dining", "biggies_burger"),
|
| 1387 |
+
"biryani by kilo": ("dining", "biryani_by_kilo"),
|
| 1388 |
+
"burger singh": ("dining", "burger_singh"),
|
| 1389 |
+
"cafe delhi heights": ("dining", "cafe_delhi_heights"),
|
| 1390 |
+
"california pizza kitchen": ("dining", "cpk"),
|
| 1391 |
+
"carl's jr": ("dining", "carls_jr"),
|
| 1392 |
+
"carls jr": ("dining", "carls_jr"),
|
| 1393 |
+
"chai point": ("dining", "chai_point"),
|
| 1394 |
+
"chai sutta bar": ("dining", "chai_sutta_bar"),
|
| 1395 |
+
"charcoal eats": ("dining", "charcoal_eats"),
|
| 1396 |
+
"chinese wok": ("dining", "chinese_wok"),
|
| 1397 |
+
"chowman": ("dining", "chowman"),
|
| 1398 |
+
"costa": ("dining", "costa_coffee"),
|
| 1399 |
+
"costa coffee": ("dining", "costa_coffee"),
|
| 1400 |
+
"cpk": ("dining", "cpk"),
|
| 1401 |
+
"cream stone": ("dining", "cream_stone"),
|
| 1402 |
+
"culinary treats": ("dining", "culinary_treats"),
|
| 1403 |
+
"cult eatfit": ("dining", "eatfit"),
|
| 1404 |
+
"dindigul": ("dining", "thalappakatti"),
|
| 1405 |
+
"dining delights": ("dining", "dining_delights"),
|
| 1406 |
+
"drunken monkey": ("dining", "drunken_monkey"),
|
| 1407 |
+
"dunkin": ("dining", "dunkin"),
|
| 1408 |
+
"dunkin donuts": ("dining", "dunkin"),
|
| 1409 |
+
"eatfit": ("dining", "eatfit"),
|
| 1410 |
+
"effingut": ("dining", "effingut"),
|
| 1411 |
+
"empire restaurant": ("dining", "empire_restaurant"),
|
| 1412 |
+
"firangi bake": ("dining", "firangi_bake"),
|
| 1413 |
+
"flavours of india": ("dining", "amex_dining"),
|
| 1414 |
+
"fresh menu": ("dining", "freshmenu"),
|
| 1415 |
+
"freshmenu": ("dining", "freshmenu"),
|
| 1416 |
+
"frozen bottle": ("dining", "frozen_bottle"),
|
| 1417 |
+
"giani": ("dining", "giani"),
|
| 1418 |
+
"giani's": ("dining", "giani"),
|
| 1419 |
+
"goila": ("dining", "goila_butter_chicken"),
|
| 1420 |
+
"goli": ("dining", "goli_vada_pav"),
|
| 1421 |
+
"goli vada pav": ("dining", "goli_vada_pav"),
|
| 1422 |
+
"good bowl": ("dining", "the_good_bowl"),
|
| 1423 |
+
"good food trail": ("dining", "good_food_trail"),
|
| 1424 |
+
"hard rock cafe": ("dining", "hard_rock_cafe"),
|
| 1425 |
+
"honest restaurant": ("dining", "honest"),
|
| 1426 |
+
"hoppipola": ("dining", "hoppipola"),
|
| 1427 |
+
"hotel empire": ("dining", "empire_restaurant"),
|
| 1428 |
+
"ibaco": ("dining", "ibaco"),
|
| 1429 |
+
"irish house": ("dining", "irish_house"),
|
| 1430 |
+
"johnny rockets": ("dining", "johnny_rockets"),
|
| 1431 |
+
"jumbo king": ("dining", "jumboking"),
|
| 1432 |
+
"jumboking": ("dining", "jumboking"),
|
| 1433 |
+
"junior kuppanna": ("dining", "junior_kuppanna"),
|
| 1434 |
+
"kailash parbat": ("dining", "kailash_parbat"),
|
| 1435 |
+
"karachi bakery": ("dining", "karachi_bakery"),
|
| 1436 |
+
"kathi junction": ("dining", "kathi_junction"),
|
| 1437 |
+
"keventers": ("dining", "keventers"),
|
| 1438 |
+
"kotak dining": ("dining", "kotak_dining"),
|
| 1439 |
+
"krispy kreme": ("dining", "krispy_kreme"),
|
| 1440 |
+
"mad over donuts": ("dining", "mad_over_donuts"),
|
| 1441 |
+
"maharaja bhog": ("dining", "maharaja_bhog"),
|
| 1442 |
+
"mba chai wala": ("dining", "mba_chai_wala"),
|
| 1443 |
+
"meghana foods": ("dining", "meghana_foods"),
|
| 1444 |
+
"mio amore": ("dining", "mio_amore"),
|
| 1445 |
+
"monginis": ("dining", "monginis"),
|
| 1446 |
+
"moti mahal": ("dining", "moti_mahal"),
|
| 1447 |
+
"mtr restaurant": ("dining", "mtr_restaurant"),
|
| 1448 |
+
"murugan idli": ("dining", "murugan_idli"),
|
| 1449 |
+
"nando's": ("dining", "nandos"),
|
| 1450 |
+
"nandos": ("dining", "nandos"),
|
| 1451 |
+
"natural ice cream": ("dining", "naturals"),
|
| 1452 |
+
"naturals ice cream": ("dining", "naturals"),
|
| 1453 |
+
"nic ice cream": ("dining", "nic"),
|
| 1454 |
+
"nirula's": ("dining", "nirulas"),
|
| 1455 |
+
"nirulas": ("dining", "nirulas"),
|
| 1456 |
+
"oh calcutta": ("dining", "oh_calcutta"),
|
| 1457 |
+
"olive bar": ("dining", "olive_group"),
|
| 1458 |
+
"olive bistro": ("dining", "olive_group"),
|
| 1459 |
+
"pf changs": ("dining", "pf_changs"),
|
| 1460 |
+
"pind balluchi": ("dining", "pind_balluchi"),
|
| 1461 |
+
"pirates of grill": ("dining", "pirates_of_grill"),
|
| 1462 |
+
"ponnusamy": ("dining", "ponnusamy"),
|
| 1463 |
+
"popeyes": ("dining", "popeyes"),
|
| 1464 |
+
"punjab grill": ("dining", "punjab_grill"),
|
| 1465 |
+
"rajdhani": ("dining", "rajdhani_thali"),
|
| 1466 |
+
"rolls mania": ("dining", "rolls_mania"),
|
| 1467 |
+
"sangeetha veg": ("dining", "sangeetha"),
|
| 1468 |
+
"sankalp": ("dining", "sankalp"),
|
| 1469 |
+
"sbow": ("dining", "sodabottleopenerwala"),
|
| 1470 |
+
"sigree": ("dining", "sigree"),
|
| 1471 |
+
"smoke house deli": ("dining", "smoke_house_deli"),
|
| 1472 |
+
"smoor": ("dining", "smoor"),
|
| 1473 |
+
"sodabottleopenerwala": ("dining", "sodabottleopenerwala"),
|
| 1474 |
+
"subko": ("dining", "subko"),
|
| 1475 |
+
"taco bell": ("dining", "taco_bell"),
|
| 1476 |
+
"tacobell": ("dining", "taco_bell"),
|
| 1477 |
+
"tea trails": ("dining", "tea_trails"),
|
| 1478 |
+
"thalappakatti": ("dining", "thalappakatti"),
|
| 1479 |
+
"thick shake factory": ("dining", "thickshake_factory"),
|
| 1480 |
+
"thickshake": ("dining", "thickshake_factory"),
|
| 1481 |
+
"tim hortons": ("dining", "tim_hortons"),
|
| 1482 |
+
"toit": ("dining", "toit"),
|
| 1483 |
+
"truffles": ("dining", "truffles"),
|
| 1484 |
+
"vasudev adiga": ("dining", "adigas"),
|
| 1485 |
+
"warmoven": ("dining", "warmoven"),
|
| 1486 |
+
"wat a burger": ("dining", "wat_a_burger"),
|
| 1487 |
+
"wat-a-burger": ("dining", "wat_a_burger"),
|
| 1488 |
+
"wendy's": ("dining", "wendys"),
|
| 1489 |
+
"wendys": ("dining", "wendys"),
|
| 1490 |
+
"wok express": ("dining", "wok_express"),
|
| 1491 |
+
"wokexpress": ("dining", "wok_express"),
|
| 1492 |
+
"wow! china": ("dining", "wow_china"),
|
| 1493 |
+
"yellow chilli": ("dining", "yellow_chilli"),
|
| 1494 |
+
# --- groceries ---
|
| 1495 |
+
"7 eleven": ("groceries", "seven_eleven"),
|
| 1496 |
+
"7-eleven": ("groceries", "seven_eleven"),
|
| 1497 |
+
"akshayakalpa": ("groceries", "akshayakalpa"),
|
| 1498 |
+
"apna bazaar": ("groceries", "apna_bazar"),
|
| 1499 |
+
"apna bazar": ("groceries", "apna_bazar"),
|
| 1500 |
+
"balaji grand bazar": ("groceries", "balaji_grand_bazar"),
|
| 1501 |
+
"best price": ("groceries", "best_price"),
|
| 1502 |
+
"bgb": ("groceries", "balaji_grand_bazar"),
|
| 1503 |
+
"city mall": ("groceries", "citymall"),
|
| 1504 |
+
"citymall": ("groceries", "citymall"),
|
| 1505 |
+
"dealshare": ("groceries", "dealshare"),
|
| 1506 |
+
"deep rooted": ("groceries", "deep_rooted"),
|
| 1507 |
+
"deeprooted": ("groceries", "deep_rooted"),
|
| 1508 |
+
"doodhvale": ("groceries", "doodhvale"),
|
| 1509 |
+
"flipkart wholesale": ("groceries", "best_price"),
|
| 1510 |
+
"food stories": ("groceries", "food_stories"),
|
| 1511 |
+
"foodstories": ("groceries", "food_stories"),
|
| 1512 |
+
"gourmet garden": ("groceries", "verify-first"),
|
| 1513 |
+
"grace supermarket": ("groceries", "grace_supermarket"),
|
| 1514 |
+
"kisan konnect": ("groceries", "kisankonnect"),
|
| 1515 |
+
"kisankonnect": ("groceries", "kisankonnect"),
|
| 1516 |
+
"kovai pazhamudir nilayam": ("groceries", "kpn_fresh"),
|
| 1517 |
+
"kpn fresh": ("groceries", "kpn_fresh"),
|
| 1518 |
+
"le marche": ("groceries", "le_marche"),
|
| 1519 |
+
"lemarche": ("groceries", "le_marche"),
|
| 1520 |
+
"magsons": ("groceries", "magsons"),
|
| 1521 |
+
"magsons supercenter": ("groceries", "magsons"),
|
| 1522 |
+
"margin free": ("groceries", "margin_free_market"),
|
| 1523 |
+
"meatigo": ("groceries", "meatigo"),
|
| 1524 |
+
"mk ahmed": ("groceries", "mk_retail"),
|
| 1525 |
+
"mk retail": ("groceries", "mk_retail"),
|
| 1526 |
+
"modern bazaar": ("groceries", "modern_bazaar"),
|
| 1527 |
+
"mother dairy safal": ("groceries", "safal"),
|
| 1528 |
+
"nesto": ("groceries", "nesto"),
|
| 1529 |
+
"nesto hypermarket": ("groceries", "nesto"),
|
| 1530 |
+
"osia": ("groceries", "osia_hypermart"),
|
| 1531 |
+
"osia hypermart": ("groceries", "osia_hypermart"),
|
| 1532 |
+
"osiamart": ("groceries", "osia_hypermart"),
|
| 1533 |
+
"pazhamudir": ("groceries", "kpn_fresh"),
|
| 1534 |
+
"pothys": ("groceries", "pothys_hyper"),
|
| 1535 |
+
"pothys hyper": ("groceries", "pothys_hyper"),
|
| 1536 |
+
"prasuma": ("groceries", "meatigo"),
|
| 1537 |
+
"q-mart": ("groceries", "q_mart"),
|
| 1538 |
+
"qmart": ("groceries", "q_mart"),
|
| 1539 |
+
"safal": ("groceries", "safal"),
|
| 1540 |
+
"sahakari bhandar": ("groceries", "sahakari_bhandar"),
|
| 1541 |
+
"seven eleven": ("groceries", "seven_eleven"),
|
| 1542 |
+
"sid's farm": ("groceries", "sids_farm"),
|
| 1543 |
+
"sids farm": ("groceries", "sids_farm"),
|
| 1544 |
+
"spar": ("groceries", "spar_india"),
|
| 1545 |
+
"spar hypermarket": ("groceries", "spar_india"),
|
| 1546 |
+
"spar india": ("groceries", "spar_india"),
|
| 1547 |
+
"triveni supermarket": ("groceries", "triveni_supermarkets"),
|
| 1548 |
+
"v-mart": ("groceries", "v_mart"),
|
| 1549 |
+
"vijetha": ("groceries", "vijetha"),
|
| 1550 |
+
"vijetha supermarket": ("groceries", "vijetha"),
|
| 1551 |
+
"vmart": ("groceries", "v_mart"),
|
| 1552 |
+
"zappfresh": ("groceries", "zappfresh"),
|
| 1553 |
+
# --- electronics ---
|
| 1554 |
+
"adishwar": ("electronics", "adishwar"),
|
| 1555 |
+
"adishwar india": ("electronics", "adishwar"),
|
| 1556 |
+
"amazfit": ("electronics", "amazfit"),
|
| 1557 |
+
"apple premium reseller": ("electronics", "india_istore"),
|
| 1558 |
+
"atomberg": ("electronics", "atomberg"),
|
| 1559 |
+
"b new": ("electronics", "b_new_mobiles"),
|
| 1560 |
+
"benq": ("electronics", "benq"),
|
| 1561 |
+
"bismi": ("electronics", "bismi"),
|
| 1562 |
+
"bismi appliances": ("electronics", "bismi"),
|
| 1563 |
+
"bnew mobiles": ("electronics", "b_new_mobiles"),
|
| 1564 |
+
"brother printers": ("electronics", "brother"),
|
| 1565 |
+
"butterfly": ("electronics", "butterfly"),
|
| 1566 |
+
"butterfly gandhimathi": ("electronics", "butterfly"),
|
| 1567 |
+
"canon": ("electronics", "canon"),
|
| 1568 |
+
"canon store": ("electronics", "canon"),
|
| 1569 |
+
"capital electronics": ("electronics", "capital_electronics"),
|
| 1570 |
+
"celekt": ("electronics", "celekt"),
|
| 1571 |
+
"cell point": ("electronics", "cellpoint"),
|
| 1572 |
+
"cellpoint": ("electronics", "cellpoint"),
|
| 1573 |
+
"crompton": ("electronics", "crompton"),
|
| 1574 |
+
"crompton greaves": ("electronics", "crompton"),
|
| 1575 |
+
"dji": ("electronics", "dji"),
|
| 1576 |
+
"ecotank": ("electronics", "epson"),
|
| 1577 |
+
"electronicsmartindia": ("electronics", "electronics_mart"),
|
| 1578 |
+
"elica": ("electronics", "elica"),
|
| 1579 |
+
"emil": ("electronics", "electronics_mart"),
|
| 1580 |
+
"epson": ("electronics", "epson"),
|
| 1581 |
+
"faber": ("electronics", "faber"),
|
| 1582 |
+
"faber chimney": ("electronics", "faber"),
|
| 1583 |
+
"fire-boltt": ("electronics", "fire_boltt"),
|
| 1584 |
+
"fireboltt": ("electronics", "fire_boltt"),
|
| 1585 |
+
"fujifilm": ("electronics", "fujifilm"),
|
| 1586 |
+
"future world": ("electronics", "futureworld"),
|
| 1587 |
+
"futureworld": ("electronics", "futureworld"),
|
| 1588 |
+
"g-mart": ("electronics", "nandilath_gmart"),
|
| 1589 |
+
"garmin": ("electronics", "garmin"),
|
| 1590 |
+
"glen": ("electronics", "glen"),
|
| 1591 |
+
"gmart": ("electronics", "nandilath_gmart"),
|
| 1592 |
+
"gopro": ("electronics", "gopro"),
|
| 1593 |
+
"happi mobiles": ("electronics", "happi_mobiles"),
|
| 1594 |
+
"happimobiles": ("electronics", "happi_mobiles"),
|
| 1595 |
+
"harman audio": ("electronics", "harman_audio"),
|
| 1596 |
+
"harman kardon": ("electronics", "harman_audio"),
|
| 1597 |
+
"hihonor": ("electronics", "honor"),
|
| 1598 |
+
"hmd": ("electronics", "hmd_nokia"),
|
| 1599 |
+
"honor": ("electronics", "honor"),
|
| 1600 |
+
"htech": ("electronics", "honor"),
|
| 1601 |
+
"imagine online": ("electronics", "imagine_apple"),
|
| 1602 |
+
"in.canon": ("electronics", "canon"),
|
| 1603 |
+
"indiaistore": ("electronics", "india_istore"),
|
| 1604 |
+
"infinix": ("electronics", "infinix"),
|
| 1605 |
+
"insta360": ("electronics", "insta360"),
|
| 1606 |
+
"instax": ("electronics", "fujifilm"),
|
| 1607 |
+
"iplanet": ("electronics", "iplanet"),
|
| 1608 |
+
"iqoo store": ("electronics", "iqoo"),
|
| 1609 |
+
"itel": ("electronics", "itel"),
|
| 1610 |
+
"kenstar": ("electronics", "kenstar"),
|
| 1611 |
+
"lava": ("electronics", "lava"),
|
| 1612 |
+
"lava mobiles": ("electronics", "lava"),
|
| 1613 |
+
"livpure": ("electronics", "livpure"),
|
| 1614 |
+
"logitech": ("electronics", "logitech"),
|
| 1615 |
+
"logitech g": ("electronics", "logitech"),
|
| 1616 |
+
"luminous": ("electronics", "luminous"),
|
| 1617 |
+
"luminous inverter": ("electronics", "luminous"),
|
| 1618 |
+
"mahajan electronics": ("electronics", "mahajan_electronics"),
|
| 1619 |
+
"maple store": ("electronics", "maple_apple"),
|
| 1620 |
+
"marshall": ("electronics", "marshall"),
|
| 1621 |
+
"mivi": ("electronics", "mivi"),
|
| 1622 |
+
"morphy richards": ("electronics", "morphy_richards"),
|
| 1623 |
+
"msi": ("electronics", "msi"),
|
| 1624 |
+
"myg": ("electronics", "myg"),
|
| 1625 |
+
"myg digital": ("electronics", "myg"),
|
| 1626 |
+
"myg india": ("electronics", "myg"),
|
| 1627 |
+
"nandilath": ("electronics", "nandilath_gmart"),
|
| 1628 |
+
"nikon": ("electronics", "nikon"),
|
| 1629 |
+
"nikon store": ("electronics", "nikon"),
|
| 1630 |
+
"nokia mobile": ("electronics", "hmd_nokia"),
|
| 1631 |
+
"nokia phones": ("electronics", "hmd_nokia"),
|
| 1632 |
+
"orient": ("electronics", "orient_electric"),
|
| 1633 |
+
"orient electric": ("electronics", "orient_electric"),
|
| 1634 |
+
"oxygen digital": ("electronics", "oxygen_digital"),
|
| 1635 |
+
"oxygen the digital shop": ("electronics", "oxygen_digital"),
|
| 1636 |
+
"pigeon": ("electronics", "pigeon"),
|
| 1637 |
+
"pittappillil": ("electronics", "pittappillil"),
|
| 1638 |
+
"placewell": ("electronics", "placewell"),
|
| 1639 |
+
"poojara": ("electronics", "poojara"),
|
| 1640 |
+
"poojara telecom": ("electronics", "poojara"),
|
| 1641 |
+
"portronics": ("electronics", "portronics"),
|
| 1642 |
+
"preethi": ("electronics", "preethi"),
|
| 1643 |
+
"prestige": ("electronics", "ttk_prestige"),
|
| 1644 |
+
"prestige xclusive": ("electronics", "ttk_prestige"),
|
| 1645 |
+
"ptron": ("electronics", "ptron"),
|
| 1646 |
+
"qrs": ("electronics", "qrs"),
|
| 1647 |
+
"qrs retail": ("electronics", "qrs"),
|
| 1648 |
+
"rathna fan house": ("electronics", "rathna_fan_house"),
|
| 1649 |
+
"razer": ("electronics", "razer"),
|
| 1650 |
+
"sales emporium": ("electronics", "sales_emporium"),
|
| 1651 |
+
"sales india": ("electronics", "sales_india"),
|
| 1652 |
+
"salesindia": ("electronics", "sales_india"),
|
| 1653 |
+
"sargam": ("electronics", "sargam"),
|
| 1654 |
+
"sargam electronics": ("electronics", "sargam"),
|
| 1655 |
+
"sennheiser": ("electronics", "sennheiser"),
|
| 1656 |
+
"siemens appliances": ("electronics", "siemens_home"),
|
| 1657 |
+
"siemens home": ("electronics", "siemens_home"),
|
| 1658 |
+
"skullcandy": ("electronics", "skullcandy"),
|
| 1659 |
+
"sonos": ("electronics", "sonos"),
|
| 1660 |
+
"stovekraft": ("electronics", "pigeon"),
|
| 1661 |
+
"supreme mobiles": ("electronics", "supreme_mobiles"),
|
| 1662 |
+
"suprememobiles": ("electronics", "supreme_mobiles"),
|
| 1663 |
+
"symphony": ("electronics", "symphony"),
|
| 1664 |
+
"symphony cooler": ("electronics", "symphony"),
|
| 1665 |
+
"tecno": ("electronics", "tecno"),
|
| 1666 |
+
"top 10 mobiles": ("electronics", "top10_mobiles"),
|
| 1667 |
+
"top10 mobile": ("electronics", "top10_mobiles"),
|
| 1668 |
+
"ttk prestige": ("electronics", "ttk_prestige"),
|
| 1669 |
+
"unicorn": ("electronics", "unicorn_apple"),
|
| 1670 |
+
"unilet": ("electronics", "unilet"),
|
| 1671 |
+
"unilet stores": ("electronics", "unilet"),
|
| 1672 |
+
"v-guard": ("electronics", "v_guard"),
|
| 1673 |
+
"value plus": ("electronics", "value_plus"),
|
| 1674 |
+
"valueplusretail": ("electronics", "value_plus"),
|
| 1675 |
+
"vasanth": ("electronics", "vasanth_and_co"),
|
| 1676 |
+
"vasanth & co": ("electronics", "vasanth_and_co"),
|
| 1677 |
+
"vasanthandco": ("electronics", "vasanth_and_co"),
|
| 1678 |
+
"vguard": ("electronics", "v_guard"),
|
| 1679 |
+
"voltbek": ("electronics", "voltas_beko"),
|
| 1680 |
+
"vu televisions": ("electronics", "vu"),
|
| 1681 |
+
"vu tv": ("electronics", "vu"),
|
| 1682 |
+
"zebronics": ("electronics", "zebronics"),
|
| 1683 |
+
# --- travel_hotels ---
|
| 1684 |
+
"aman-i-khas": ("travel_hotels", "aman"),
|
| 1685 |
+
"amanbagh": ("travel_hotels", "aman"),
|
| 1686 |
+
"amritara": ("travel_hotels", "amritara"),
|
| 1687 |
+
"anantara": ("travel_hotels", "minor_hotels"),
|
| 1688 |
+
"avani": ("travel_hotels", "minor_hotels"),
|
| 1689 |
+
"beacon hotels": ("travel_hotels", "the_fern"),
|
| 1690 |
+
"best western": ("travel_hotels", "best_western"),
|
| 1691 |
+
"biznotel": ("travel_hotels", "pride_hotels"),
|
| 1692 |
+
"bloom boutique": ("travel_hotels", "bloom_hotels"),
|
| 1693 |
+
"bloom hub": ("travel_hotels", "bloom_hotels"),
|
| 1694 |
+
"bloomrooms": ("travel_hotels", "bloom_hotels"),
|
| 1695 |
+
"cgh earth": ("travel_hotels", "cgh_earth"),
|
| 1696 |
+
"citadines": ("travel_hotels", "ascott"),
|
| 1697 |
+
"clarion hotel": ("travel_hotels", "choice_hotels"),
|
| 1698 |
+
"clarks hotels": ("travel_hotels", "clarks_hotels"),
|
| 1699 |
+
"clarks inn": ("travel_hotels", "clarks_hotels"),
|
| 1700 |
+
"coconut lagoon": ("travel_hotels", "cgh_earth"),
|
| 1701 |
+
"comfort inn": ("travel_hotels", "choice_hotels"),
|
| 1702 |
+
"cozzet": ("travel_hotels", "cygnett"),
|
| 1703 |
+
"cygnett inn": ("travel_hotels", "cygnett"),
|
| 1704 |
+
"cygnett park": ("travel_hotels", "cygnett"),
|
| 1705 |
+
"days inn": ("travel_hotels", "wyndham"),
|
| 1706 |
+
"deltin royale": ("travel_hotels", "deltin"),
|
| 1707 |
+
"deltin suites": ("travel_hotels", "deltin"),
|
| 1708 |
+
"effotel": ("travel_hotels", "sayaji"),
|
| 1709 |
+
"ekostay": ("travel_hotels", "ekostay"),
|
| 1710 |
+
"enrise by sayaji": ("travel_hotels", "sayaji"),
|
| 1711 |
+
"evolve back": ("travel_hotels", "evolve_back"),
|
| 1712 |
+
"expedia": ("travel_hotels", "expedia"),
|
| 1713 |
+
"fateh prakash": ("travel_hotels", "hrh_hotels"),
|
| 1714 |
+
"fern residency": ("travel_hotels", "the_fern"),
|
| 1715 |
+
"four seasons bengaluru": ("travel_hotels", "four_seasons"),
|
| 1716 |
+
"four seasons mumbai": ("travel_hotels", "four_seasons"),
|
| 1717 |
+
"go stops": ("travel_hotels", "gostops"),
|
| 1718 |
+
"golden tulip": ("travel_hotels", "golden_tulip"),
|
| 1719 |
+
"gostops": ("travel_hotels", "gostops"),
|
| 1720 |
+
"grand by grt": ("travel_hotels", "grt_hotels"),
|
| 1721 |
+
"grt grand": ("travel_hotels", "grt_hotels"),
|
| 1722 |
+
"grt hotels": ("travel_hotels", "grt_hotels"),
|
| 1723 |
+
"hotels.com": ("travel_hotels", "expedia"),
|
| 1724 |
+
"howard johnson": ("travel_hotels", "wyndham"),
|
| 1725 |
+
"hrh hotels": ("travel_hotels", "hrh_hotels"),
|
| 1726 |
+
"isprava": ("travel_hotels", "lohono"),
|
| 1727 |
+
"itdc hotels": ("travel_hotels", "itdc_ashok"),
|
| 1728 |
+
"jaypee greens": ("travel_hotels", "jaypee_hotels"),
|
| 1729 |
+
"jaypee palace": ("travel_hotels", "jaypee_hotels"),
|
| 1730 |
+
"jaypee vasant": ("travel_hotels", "jaypee_hotels"),
|
| 1731 |
+
"justa hotels": ("travel_hotels", "justa_hotels"),
|
| 1732 |
+
"justa resorts": ("travel_hotels", "justa_hotels"),
|
| 1733 |
+
"kamat hotels": ("travel_hotels", "the_orchid"),
|
| 1734 |
+
"karma lakelands": ("travel_hotels", "karma_group"),
|
| 1735 |
+
"karma resorts": ("travel_hotels", "karma_group"),
|
| 1736 |
+
"karma royal": ("travel_hotels", "karma_group"),
|
| 1737 |
+
"kempinski": ("travel_hotels", "kempinski"),
|
| 1738 |
+
"lalit suri": ("travel_hotels", "the_lalit"),
|
| 1739 |
+
"lohono stays": ("travel_hotels", "lohono"),
|
| 1740 |
+
"mayfair hotels": ("travel_hotels", "mayfair_hotels"),
|
| 1741 |
+
"mayfair lagoon": ("travel_hotels", "mayfair_hotels"),
|
| 1742 |
+
"moustache escapes": ("travel_hotels", "moustache"),
|
| 1743 |
+
"moustache hostel": ("travel_hotels", "moustache"),
|
| 1744 |
+
"neemrana": ("travel_hotels", "neemrana"),
|
| 1745 |
+
"neemrana fort palace": ("travel_hotels", "neemrana"),
|
| 1746 |
+
"nh collection": ("travel_hotels", "minor_hotels"),
|
| 1747 |
+
"oaks hotels": ("travel_hotels", "minor_hotels"),
|
| 1748 |
+
"oakwood": ("travel_hotels", "ascott"),
|
| 1749 |
+
"orange county resorts": ("travel_hotels", "evolve_back"),
|
| 1750 |
+
"orchid hotel": ("travel_hotels", "the_orchid"),
|
| 1751 |
+
"postcard goa": ("travel_hotels", "postcard_hotel"),
|
| 1752 |
+
"postcard hotel": ("travel_hotels", "postcard_hotel"),
|
| 1753 |
+
"pride hotel": ("travel_hotels", "pride_hotels"),
|
| 1754 |
+
"pride plaza": ("travel_hotels", "pride_hotels"),
|
| 1755 |
+
"quality inn": ("travel_hotels", "choice_hotels"),
|
| 1756 |
+
"ramada": ("travel_hotels", "wyndham"),
|
| 1757 |
+
"ramee grand": ("travel_hotels", "ramee"),
|
| 1758 |
+
"ramee guestline": ("travel_hotels", "ramee"),
|
| 1759 |
+
"regenta": ("travel_hotels", "royal_orchid"),
|
| 1760 |
+
"roseate house": ("travel_hotels", "roseate"),
|
| 1761 |
+
"royal orchid": ("travel_hotels", "royal_orchid"),
|
| 1762 |
+
"royal tulip": ("travel_hotels", "golden_tulip"),
|
| 1763 |
+
"saffron stays": ("travel_hotels", "saffronstays"),
|
| 1764 |
+
"saffronstays": ("travel_hotels", "saffronstays"),
|
| 1765 |
+
"sayaji hotel": ("travel_hotels", "sayaji"),
|
| 1766 |
+
"shangri-la bengaluru": ("travel_hotels", "shangri_la"),
|
| 1767 |
+
"shangri-la eros": ("travel_hotels", "shangri_la"),
|
| 1768 |
+
"shiv niwas": ("travel_hotels", "hrh_hotels"),
|
| 1769 |
+
"somerset": ("travel_hotels", "ascott"),
|
| 1770 |
+
"spice village": ("travel_hotels", "cgh_earth"),
|
| 1771 |
+
"stayvista": ("travel_hotels", "stayvista"),
|
| 1772 |
+
"sure hotel": ("travel_hotels", "best_western"),
|
| 1773 |
+
"the ashok": ("travel_hotels", "itdc_ashok"),
|
| 1774 |
+
"the deltin": ("travel_hotels", "deltin"),
|
| 1775 |
+
"the fern": ("travel_hotels", "the_fern"),
|
| 1776 |
+
"the hosteller": ("travel_hotels", "the_hosteller"),
|
| 1777 |
+
"the lalit": ("travel_hotels", "the_lalit"),
|
| 1778 |
+
"the park hotels": ("travel_hotels", "the_park"),
|
| 1779 |
+
"the roseate": ("travel_hotels", "roseate"),
|
| 1780 |
+
"trip com hotels": ("travel_hotels", "trip_com"),
|
| 1781 |
+
"tulip inn": ("travel_hotels", "golden_tulip"),
|
| 1782 |
+
"vista rooms": ("travel_hotels", "stayvista"),
|
| 1783 |
+
"vits hotels": ("travel_hotels", "the_orchid"),
|
| 1784 |
+
"wyndham grand": ("travel_hotels", "wyndham"),
|
| 1785 |
+
"zo trips": ("travel_hotels", "zostel"),
|
| 1786 |
+
"zone by the park": ("travel_hotels", "the_park"),
|
| 1787 |
+
"zostel": ("travel_hotels", "zostel"),
|
| 1788 |
+
"zostel plus": ("travel_hotels", "zostel"),
|
| 1789 |
+
# --- utilities ---
|
| 1790 |
+
"best mumbai electricity": ("utilities", "best_electricity"),
|
| 1791 |
+
"best undertaking": ("utilities", "best_electricity"),
|
| 1792 |
+
"brpl": ("utilities", "bses"),
|
| 1793 |
+
"bypl": ("utilities", "bses"),
|
| 1794 |
+
"cable tv gujarat": ("utilities", "gtpl"),
|
| 1795 |
+
"delhi electricity": ("utilities", "bses"),
|
| 1796 |
+
"den cable": ("utilities", "den_networks"),
|
| 1797 |
+
"den networks": ("utilities", "den_networks"),
|
| 1798 |
+
"gtpl": ("utilities", "gtpl"),
|
| 1799 |
+
"gtpl broadband": ("utilities", "gtpl"),
|
| 1800 |
+
"maharashtra electricity": ("utilities", "msedcl"),
|
| 1801 |
+
"mumbai power bill": ("utilities", "adani_electricity"),
|
| 1802 |
+
"tikona": ("utilities", "tikona"),
|
| 1803 |
+
"tpddl": ("utilities", "tata_power"),
|
| 1804 |
+
"wireless broadband": ("utilities", "tikona"),
|
| 1805 |
+
# --- insurance ---
|
| 1806 |
+
"acko": ("insurance", "acko"),
|
| 1807 |
+
"bike insurance": ("insurance", "acko"),
|
| 1808 |
+
"car insurance": ("insurance", "acko"),
|
| 1809 |
+
"digit insurance": ("insurance", "digit_insurance"),
|
| 1810 |
+
"godigit": ("insurance", "digit_insurance"),
|
| 1811 |
+
"insurance advisor": ("insurance", "turtlemint"),
|
| 1812 |
+
"insurance comparison": ("insurance", "insurancedekho"),
|
| 1813 |
+
"insurancedekho": ("insurance", "insurancedekho"),
|
| 1814 |
+
"turtlemint": ("insurance", "turtlemint"),
|
| 1815 |
+
# --- education ---
|
| 1816 |
+
"aakash byjus": ("education", "aakash"),
|
| 1817 |
+
"aakash institute": ("education", "aakash"),
|
| 1818 |
+
"allen coaching fees": ("education", "allen"),
|
| 1819 |
+
"allen kota": ("education", "allen"),
|
| 1820 |
+
"byjus": ("education", "byjus"),
|
| 1821 |
+
"certification course": ("education", "simplilearn"),
|
| 1822 |
+
"coursera plus india": ("education", "coursera"),
|
| 1823 |
+
"cuemath": ("education", "cuemath"),
|
| 1824 |
+
"great learning": ("education", "great_learning"),
|
| 1825 |
+
"math classes online": ("education", "cuemath"),
|
| 1826 |
+
"medical coaching fees": ("education", "aakash"),
|
| 1827 |
+
"mygreatlearning": ("education", "great_learning"),
|
| 1828 |
+
"neet jee coaching": ("education", "allen"),
|
| 1829 |
+
"online degree": ("education", "upgrad"),
|
| 1830 |
+
"pg certificate": ("education", "great_learning"),
|
| 1831 |
+
"simplilearn": ("education", "simplilearn"),
|
| 1832 |
+
"think and learn": ("education", "byjus"),
|
| 1833 |
+
"upskilling": ("education", "upgrad"),
|
| 1834 |
+
# --- rent ---
|
| 1835 |
+
"apartment dues": ("rent", "nobrokerhood"),
|
| 1836 |
+
"redgirraffe": ("rent", "redgirraffe"),
|
| 1837 |
+
"rent via credit card": ("rent", "redgirraffe"),
|
| 1838 |
+
"rentpay": ("rent", "redgirraffe"),
|
| 1839 |
+
"society maintenance": ("rent", "nobrokerhood"),
|
| 1840 |
+
# --- entertainment ---
|
| 1841 |
+
"adlabs imagica": ("entertainment", "imagicaa"),
|
| 1842 |
+
"adventure island": ("entertainment", "adventure_island"),
|
| 1843 |
+
"ags cinemas": ("entertainment", "ags_cinemas"),
|
| 1844 |
+
"aha": ("entertainment", "aha_ott"),
|
| 1845 |
+
"aha video": ("entertainment", "aha_ott"),
|
| 1846 |
+
"alt balaji": ("entertainment", "altt"),
|
| 1847 |
+
"altt": ("entertainment", "altt"),
|
| 1848 |
+
"amaazia": ("entertainment", "amaazia"),
|
| 1849 |
+
"amazon music": ("entertainment", "amazon_music"),
|
| 1850 |
+
"apple music": ("entertainment", "apple_music"),
|
| 1851 |
+
"apple tv plus": ("entertainment", "apple_tv_plus"),
|
| 1852 |
+
"apple tv+": ("entertainment", "apple_tv_plus"),
|
| 1853 |
+
"aquatica": ("entertainment", "aquatica"),
|
| 1854 |
+
"audible": ("entertainment", "audible"),
|
| 1855 |
+
"chaupal": ("entertainment", "chaupal"),
|
| 1856 |
+
"city pride": ("entertainment", "city_pride"),
|
| 1857 |
+
"connplex": ("entertainment", "connplex"),
|
| 1858 |
+
"crunchyroll": ("entertainment", "crunchyroll"),
|
| 1859 |
+
"delite cinema": ("entertainment", "delite_cinemas"),
|
| 1860 |
+
"della adventure": ("entertainment", "della_adventure"),
|
| 1861 |
+
"discovery plus": ("entertainment", "discovery_plus"),
|
| 1862 |
+
"discovery+": ("entertainment", "discovery_plus"),
|
| 1863 |
+
"e-square": ("entertainment", "esquare_cinemas"),
|
| 1864 |
+
"escape": ("entertainment", "spi_cinemas"),
|
| 1865 |
+
"esquare": ("entertainment", "esquare_cinemas"),
|
| 1866 |
+
"etv win": ("entertainment", "etv_win"),
|
| 1867 |
+
"explara": ("entertainment", "explara"),
|
| 1868 |
+
"fun cinemas": ("entertainment", "cinepolis"),
|
| 1869 |
+
"fun city": ("entertainment", "fun_city"),
|
| 1870 |
+
"gaana": ("entertainment", "gaana"),
|
| 1871 |
+
"glitz cinemas": ("entertainment", "glitz_cinemas"),
|
| 1872 |
+
"gold cinema": ("entertainment", "gold_cinema"),
|
| 1873 |
+
"imagica": ("entertainment", "imagicaa"),
|
| 1874 |
+
"imagicaa": ("entertainment", "imagicaa"),
|
| 1875 |
+
"iskate": ("entertainment", "iskate"),
|
| 1876 |
+
"jiosaavn": ("entertainment", "jiosaavn"),
|
| 1877 |
+
"kidzania": ("entertainment", "kidzania"),
|
| 1878 |
+
"kuku fm": ("entertainment", "kuku_fm"),
|
| 1879 |
+
"m2k": ("entertainment", "m2k_cinemas"),
|
| 1880 |
+
"manoramamax": ("entertainment", "manorama_max"),
|
| 1881 |
+
"meraevents": ("entertainment", "meraevents"),
|
| 1882 |
+
"mgm dizzee": ("entertainment", "mgm_dizzee"),
|
| 1883 |
+
"mx player": ("entertainment", "mx_player"),
|
| 1884 |
+
"nicco park": ("entertainment", "nicco_park"),
|
| 1885 |
+
"ottplay": ("entertainment", "ottplay"),
|
| 1886 |
+
"palazzo": ("entertainment", "spi_cinemas"),
|
| 1887 |
+
"pocket fm": ("entertainment", "pocket_fm"),
|
| 1888 |
+
"prasads imax": ("entertainment", "prasads"),
|
| 1889 |
+
"prasads multiplex": ("entertainment", "prasads"),
|
| 1890 |
+
"ramoji": ("entertainment", "ramoji_film_city"),
|
| 1891 |
+
"saavn": ("entertainment", "jiosaavn"),
|
| 1892 |
+
"sandhya 70mm": ("entertainment", "sandhya_70mm"),
|
| 1893 |
+
"sathyam": ("entertainment", "spi_cinemas"),
|
| 1894 |
+
"shott": ("entertainment", "shott"),
|
| 1895 |
+
"skillbox": ("entertainment", "skillbox"),
|
| 1896 |
+
"smaaash": ("entertainment", "smaaash"),
|
| 1897 |
+
"snow world": ("entertainment", "snow_world"),
|
| 1898 |
+
"spi cinemas": ("entertainment", "spi_cinemas"),
|
| 1899 |
+
"srs cinemas": ("entertainment", "srs_cinemas"),
|
| 1900 |
+
"stage app": ("entertainment", "stage_ott"),
|
| 1901 |
+
"stage ott": ("entertainment", "stage_ott"),
|
| 1902 |
+
"sun nxt": ("entertainment", "sun_nxt"),
|
| 1903 |
+
"sunnxt": ("entertainment", "sun_nxt"),
|
| 1904 |
+
"timezone": ("entertainment", "timezone"),
|
| 1905 |
+
"townscript": ("entertainment", "townscript"),
|
| 1906 |
+
"vgp marine kingdom": ("entertainment", "vgp_universal"),
|
| 1907 |
+
"vgp universal kingdom": ("entertainment", "vgp_universal"),
|
| 1908 |
+
"wet n joy": ("entertainment", "wetnjoy"),
|
| 1909 |
+
"wetnjoy": ("entertainment", "wetnjoy"),
|
| 1910 |
+
"wonderla": ("entertainment", "wonderla"),
|
| 1911 |
+
"worlds of wonder": ("entertainment", "worlds_of_wonder"),
|
| 1912 |
+
"wow noida": ("entertainment", "worlds_of_wonder"),
|
| 1913 |
+
"xstream play": ("entertainment", "xstream_play"),
|
| 1914 |
+
# --- apparel ---
|
| 1915 |
+
"1 india family mart": ("apparel", "one_india_family_mart"),
|
| 1916 |
+
"1-india family mart": ("apparel", "one_india_family_mart"),
|
| 1917 |
+
"allen solly": ("apparel", "allen_solly"),
|
| 1918 |
+
"american eagle": ("apparel", "american_eagle"),
|
| 1919 |
+
"american tourister": ("apparel", "american_tourister"),
|
| 1920 |
+
"arrow apparel": ("apparel", "arrow_fashion"),
|
| 1921 |
+
"arrow shirts": ("apparel", "arrow_fashion"),
|
| 1922 |
+
"biba": ("apparel", "biba"),
|
| 1923 |
+
"c krishniah chetty": ("apparel", "ckc_jewellers"),
|
| 1924 |
+
"campus activewear": ("apparel", "campus_shoes"),
|
| 1925 |
+
"campus shoes": ("apparel", "campus_shoes"),
|
| 1926 |
+
"celio": ("apparel", "celio"),
|
| 1927 |
+
"central department store": ("apparel", "central_mall"),
|
| 1928 |
+
"central mall": ("apparel", "central_mall"),
|
| 1929 |
+
"city kart": ("apparel", "city_kart"),
|
| 1930 |
+
"citykart": ("apparel", "city_kart"),
|
| 1931 |
+
"ckc jewellers": ("apparel", "ckc_jewellers"),
|
| 1932 |
+
"clarks": ("apparel", "clarks"),
|
| 1933 |
+
"clarks shoes": ("apparel", "clarks"),
|
| 1934 |
+
"crocs": ("apparel", "crocs"),
|
| 1935 |
+
"ethos watch boutique": ("apparel", "ethos_watches"),
|
| 1936 |
+
"ethos watches": ("apparel", "ethos_watches"),
|
| 1937 |
+
"fab india": ("apparel", "fabindia"),
|
| 1938 |
+
"fabindia": ("apparel", "fabindia"),
|
| 1939 |
+
"flying machine": ("apparel", "flying_machine"),
|
| 1940 |
+
"forever new": ("apparel", "forever_new"),
|
| 1941 |
+
"gant": ("apparel", "gant"),
|
| 1942 |
+
"gap india": ("apparel", "gap"),
|
| 1943 |
+
"gap store": ("apparel", "gap"),
|
| 1944 |
+
"gkb opticals": ("apparel", "gkb_opticals"),
|
| 1945 |
+
"grt": ("apparel", "grt_jewellers"),
|
| 1946 |
+
"grt jewellers": ("apparel", "grt_jewellers"),
|
| 1947 |
+
"helios watches": ("apparel", "helios_watches"),
|
| 1948 |
+
"jack & jones": ("apparel", "jack_jones"),
|
| 1949 |
+
"jack and jones": ("apparel", "jack_jones"),
|
| 1950 |
+
"joy alukkas": ("apparel", "joyalukkas"),
|
| 1951 |
+
"joyalukkas": ("apparel", "joyalukkas"),
|
| 1952 |
+
"kalki fashion": ("apparel", "kalki_fashion"),
|
| 1953 |
+
"khazana jewellery": ("apparel", "khazana_jewellery"),
|
| 1954 |
+
"levi's": ("apparel", "levis"),
|
| 1955 |
+
"levis": ("apparel", "levis"),
|
| 1956 |
+
"libas": ("apparel", "libas"),
|
| 1957 |
+
"liberty shoes": ("apparel", "liberty_shoes"),
|
| 1958 |
+
"louis philippe": ("apparel", "louis_philippe"),
|
| 1959 |
+
"mango clothing": ("apparel", "mango_fashion"),
|
| 1960 |
+
"mango fashion": ("apparel", "mango_fashion"),
|
| 1961 |
+
"manyavar": ("apparel", "manyavar"),
|
| 1962 |
+
"mia by tanishq": ("apparel", "mia_by_tanishq"),
|
| 1963 |
+
"mochi shoes": ("apparel", "mochi_shoes"),
|
| 1964 |
+
"mohey": ("apparel", "manyavar"),
|
| 1965 |
+
"only clothing": ("apparel", "only_fashion"),
|
| 1966 |
+
"only fashion": ("apparel", "only_fashion"),
|
| 1967 |
+
"orra": ("apparel", "orra"),
|
| 1968 |
+
"orra jewellery": ("apparel", "orra"),
|
| 1969 |
+
"p n gadgil": ("apparel", "png_jewellers"),
|
| 1970 |
+
"pc jeweller": ("apparel", "pc_jeweller"),
|
| 1971 |
+
"peter england": ("apparel", "peter_england"),
|
| 1972 |
+
"png jewellers": ("apparel", "png_jewellers"),
|
| 1973 |
+
"red tape shoes": ("apparel", "red_tape"),
|
| 1974 |
+
"redtape": ("apparel", "red_tape"),
|
| 1975 |
+
"regal shoes": ("apparel", "regal_shoes"),
|
| 1976 |
+
"reliance jewels": ("apparel", "reliance_jewels"),
|
| 1977 |
+
"safari bags": ("apparel", "safari_bags"),
|
| 1978 |
+
"safari luggage": ("apparel", "safari_bags"),
|
| 1979 |
+
"samsonite": ("apparel", "samsonite"),
|
| 1980 |
+
"senco": ("apparel", "senco_gold"),
|
| 1981 |
+
"senco gold": ("apparel", "senco_gold"),
|
| 1982 |
+
"skechers": ("apparel", "skechers"),
|
| 1983 |
+
"skybags": ("apparel", "skybags"),
|
| 1984 |
+
"specsmakers": ("apparel", "specsmakers"),
|
| 1985 |
+
"style union": ("apparel", "style_union"),
|
| 1986 |
+
"titan eye plus": ("apparel", "titan_eyeplus"),
|
| 1987 |
+
"titan eye+": ("apparel", "titan_eyeplus"),
|
| 1988 |
+
"titan eyeplus": ("apparel", "titan_eyeplus"),
|
| 1989 |
+
"u.s. polo assn": ("apparel", "us_polo"),
|
| 1990 |
+
"under armour": ("apparel", "under_armour"),
|
| 1991 |
+
"underarmour": ("apparel", "under_armour"),
|
| 1992 |
+
"us polo": ("apparel", "us_polo"),
|
| 1993 |
+
"uspa": ("apparel", "us_polo"),
|
| 1994 |
+
"van heusen": ("apparel", "van_heusen"),
|
| 1995 |
+
"vbj jewellers": ("apparel", "vummidi"),
|
| 1996 |
+
"vero moda": ("apparel", "vero_moda"),
|
| 1997 |
+
"vip bags": ("apparel", "vip_bags"),
|
| 1998 |
+
"vip luggage": ("apparel", "vip_bags"),
|
| 1999 |
+
"vision express": ("apparel", "vision_express"),
|
| 2000 |
+
"vummidi bangaru": ("apparel", "vummidi"),
|
| 2001 |
+
"w for woman": ("apparel", "w_for_woman"),
|
| 2002 |
+
"waman hari pethe": ("apparel", "whp_jewellers"),
|
| 2003 |
+
"whp jewellers": ("apparel", "whp_jewellers"),
|
| 2004 |
+
"wildcraft": ("apparel", "wildcraft"),
|
| 2005 |
+
"woodland india": ("apparel", "woodland"),
|
| 2006 |
+
"woodland shoes": ("apparel", "woodland"),
|
| 2007 |
+
"zudio": ("apparel", "zudio"),
|
| 2008 |
+
# --- pharmacy ---
|
| 2009 |
+
"aarogyam": ("pharmacy", "thyrocare"),
|
| 2010 |
+
"agilus": ("pharmacy", "agilus_diagnostics"),
|
| 2011 |
+
"anytime fitness": ("pharmacy", "anytime_fitness"),
|
| 2012 |
+
"aster pharmacy": ("pharmacy", "aster_pharmacy"),
|
| 2013 |
+
"clove dental": ("pharmacy", "clove_dental"),
|
| 2014 |
+
"cultpass": ("pharmacy", "cultfit"),
|
| 2015 |
+
"dava india": ("pharmacy", "davaindia"),
|
| 2016 |
+
"davaindia": ("pharmacy", "davaindia"),
|
| 2017 |
+
"dawaa dost": ("pharmacy", "dawaa_dost"),
|
| 2018 |
+
"dawaadost": ("pharmacy", "dawaa_dost"),
|
| 2019 |
+
"dr agarwal eye": ("pharmacy", "dr_agarwals"),
|
| 2020 |
+
"dr agarwals": ("pharmacy", "dr_agarwals"),
|
| 2021 |
+
"dr lal pathlabs": ("pharmacy", "dr_lal_pathlabs"),
|
| 2022 |
+
"fitness first": ("pharmacy", "fitness_first"),
|
| 2023 |
+
"frank ross": ("pharmacy", "frank_ross"),
|
| 2024 |
+
"frankross pharmacy": ("pharmacy", "frank_ross"),
|
| 2025 |
+
"gold's gym": ("pharmacy", "golds_gym"),
|
| 2026 |
+
"golds gym": ("pharmacy", "golds_gym"),
|
| 2027 |
+
"guardian pharmacy": ("pharmacy", "guardian_pharmacy"),
|
| 2028 |
+
"healthians": ("pharmacy", "healthians"),
|
| 2029 |
+
"healthkart": ("pharmacy", "healthkart"),
|
| 2030 |
+
"kaya clinic": ("pharmacy", "kaya_clinic"),
|
| 2031 |
+
"kaya skin": ("pharmacy", "kaya_clinic"),
|
| 2032 |
+
"lal path labs": ("pharmacy", "dr_lal_pathlabs"),
|
| 2033 |
+
"lalpathlabs": ("pharmacy", "dr_lal_pathlabs"),
|
| 2034 |
+
"lucid diagnostics": ("pharmacy", "lucid_diagnostics"),
|
| 2035 |
+
"lucid medical": ("pharmacy", "lucid_diagnostics"),
|
| 2036 |
+
"med 247": ("pharmacy", "med247"),
|
| 2037 |
+
"med247": ("pharmacy", "med247"),
|
| 2038 |
+
"medibuddy": ("pharmacy", "medibuddy"),
|
| 2039 |
+
"muscleblaze": ("pharmacy", "muscleblaze"),
|
| 2040 |
+
"neuberg": ("pharmacy", "neuberg_diagnostics"),
|
| 2041 |
+
"noble pharmacy": ("pharmacy", "noble_plus"),
|
| 2042 |
+
"noble plus": ("pharmacy", "noble_plus"),
|
| 2043 |
+
"nutrabay": ("pharmacy", "nutrabay"),
|
| 2044 |
+
"o2 spa": ("pharmacy", "o2_spa"),
|
| 2045 |
+
"orange health": ("pharmacy", "orange_health"),
|
| 2046 |
+
"orange health labs": ("pharmacy", "orange_health"),
|
| 2047 |
+
"pathkind": ("pharmacy", "pathkind_labs"),
|
| 2048 |
+
"sabka dentist": ("pharmacy", "sabka_dentist"),
|
| 2049 |
+
"snap fitness": ("pharmacy", "snap_fitness"),
|
| 2050 |
+
"srl diagnostics": ("pharmacy", "agilus_diagnostics"),
|
| 2051 |
+
"suburban diagnostics": ("pharmacy", "suburban_diagnostics"),
|
| 2052 |
+
"suraksha diagnostic": ("pharmacy", "suraksha_diagnostics"),
|
| 2053 |
+
"suraksha diagnostics": ("pharmacy", "suraksha_diagnostics"),
|
| 2054 |
+
"thyrocare": ("pharmacy", "thyrocare"),
|
| 2055 |
+
"truemeds": ("pharmacy", "truemeds"),
|
| 2056 |
+
"vasan eye care": ("pharmacy", "vasan_eye_care"),
|
| 2057 |
+
"vijaya diagnostic": ("pharmacy", "vijaya_diagnostics"),
|
| 2058 |
+
"vijaya diagnostics": ("pharmacy", "vijaya_diagnostics"),
|
| 2059 |
+
"vlcc": ("pharmacy", "vlcc"),
|
| 2060 |
+
"wellbeing nutrition": ("pharmacy", "wellbeing_nutrition"),
|
| 2061 |
+
"zeno health": ("pharmacy", "zeno_health"),
|
| 2062 |
+
"zeno pharmacy": ("pharmacy", "zeno_health"),
|
| 2063 |
+
# --- transport ---
|
| 2064 |
+
"airport transfer": ("transport", "savaari"),
|
| 2065 |
+
"aqua line": ("transport", "mumbai_metro"),
|
| 2066 |
+
"ather grid": ("transport", "ather_grid"),
|
| 2067 |
+
"bangalore metro card": ("transport", "namma_metro"),
|
| 2068 |
+
"bike rental": ("transport", "royal_brothers"),
|
| 2069 |
+
"bmrcl": ("transport", "namma_metro"),
|
| 2070 |
+
"car rental": ("transport", "zoomcar"),
|
| 2071 |
+
"car subscription": ("transport", "revv"),
|
| 2072 |
+
"chargezone": ("transport", "chargezone"),
|
| 2073 |
+
"chennai metro": ("transport", "chennai_metro"),
|
| 2074 |
+
"cityflo": ("transport", "cityflo"),
|
| 2075 |
+
"cmrl": ("transport", "chennai_metro"),
|
| 2076 |
+
"delhi metro": ("transport", "delhi_metro"),
|
| 2077 |
+
"dmrc": ("transport", "delhi_metro"),
|
| 2078 |
+
"electric scooter charging": ("transport", "ather_grid"),
|
| 2079 |
+
"ev charging": ("transport", "ather_grid"),
|
| 2080 |
+
"ev charging app": ("transport", "tata_power_ez_charge"),
|
| 2081 |
+
"ev charging stations": ("transport", "statiq"),
|
| 2082 |
+
"ev fast charging": ("transport", "chargezone"),
|
| 2083 |
+
"ez charge": ("transport", "tata_power_ez_charge"),
|
| 2084 |
+
"gozo": ("transport", "gozo_cabs"),
|
| 2085 |
+
"gozocabs": ("transport", "gozo_cabs"),
|
| 2086 |
+
"metro card recharge": ("transport", "delhi_metro"),
|
| 2087 |
+
"mmrc": ("transport", "mumbai_metro"),
|
| 2088 |
+
"mumbai bus commute": ("transport", "cityflo"),
|
| 2089 |
+
"mumbai metro": ("transport", "mumbai_metro"),
|
| 2090 |
+
"mumbai1": ("transport", "mumbai_metro"),
|
| 2091 |
+
"namma metro": ("transport", "namma_metro"),
|
| 2092 |
+
"ncmc": ("transport", "delhi_metro"),
|
| 2093 |
+
"outstation cab": ("transport", "savaari"),
|
| 2094 |
+
"outstation taxi": ("transport", "gozo_cabs"),
|
| 2095 |
+
"revv": ("transport", "revv"),
|
| 2096 |
+
"royal brothers": ("transport", "royal_brothers"),
|
| 2097 |
+
"savaari": ("transport", "savaari"),
|
| 2098 |
+
"scooter rental": ("transport", "royal_brothers"),
|
| 2099 |
+
"self drive": ("transport", "zoomcar"),
|
| 2100 |
+
"singara chennai card": ("transport", "chennai_metro"),
|
| 2101 |
+
"statiq": ("transport", "statiq"),
|
| 2102 |
+
"tata power ev": ("transport", "tata_power_ez_charge"),
|
| 2103 |
+
"zoomcar": ("transport", "zoomcar"),
|
| 2104 |
+
}
|
| 2105 |
+
for _k, _v in _PROPOSED_2026_08.items():
|
| 2106 |
+
MERCHANT_MAP.setdefault(_k, _v)
|
| 2107 |
+
|
| 2108 |
+
# Surat Diamond — carries a live ICICI 20% offer (2026-08-08 ICICI feed harvest).
|
| 2109 |
+
MERCHANT_MAP.setdefault("surat diamond", ("apparel", "surat_diamond"))
|
| 2110 |
+
|
| 2111 |
+
|
| 2112 |
# Retailers / merchants preferred over product words so "iPhone at Croma"
|
| 2113 |
# resolves to Croma, not iPhone.
|
| 2114 |
STORE_KEYWORDS = {
|
app/offers_data/curated_offers.json
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|