File size: 3,035 Bytes
b2ff92e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
038aba5
b2ff92e
 
 
 
 
 
 
 
038aba5
b2ff92e
 
 
 
038aba5
b2ff92e
 
 
 
 
 
 
 
 
 
 
038aba5
b2ff92e
 
 
 
 
038aba5
b2ff92e
 
 
 
 
 
 
 
 
038aba5
b2ff92e
038aba5
 
 
 
 
 
 
 
b2ff92e
038aba5
b2ff92e
 
038aba5
b2ff92e
 
038aba5
b2ff92e
038aba5
b2ff92e
038aba5
 
 
b2ff92e
038aba5
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import requests
from typing import Tuple, Optional, Dict, Any


class CamptocampAPI:
    """
    A Python wrapper for the Camptocamp.org REST API v6.
    Supports querying outings, routes, waypoints, and more.
    """

    BASE_URL = "https://api.camptocamp.org"

    def __init__(self, language: str = "en") -> None:
        self.language = language

    def _request(self, endpoint: str, params: Dict[str, Any]) -> Dict[str, Any]:
        params["pl"] = self.language
        response = requests.get(f"{self.BASE_URL}{endpoint}", params=params)
        response.raise_for_status()
        return response.json()

    def get_recent_outings(
        self,
        bbox: Tuple[float, float, float, float],
        date_range: Optional[Tuple[str, str]] = None,
        activity: Optional[str] = None,
        limit: int = 10
    ) -> Dict[str, Any]:
        params = {
            "bbox": ",".join(map(str, bbox)),
            "limit": limit,
            "orderby": "-date"
        }
        if date_range:
            params["date"] = f"{date_range[0]},{date_range[1]}"
        if activity:
            params["act"] = activity
        return self._request("/outings", params)

    def search_routes_by_activity(
        self,
        bbox: Tuple[float, float, float, float],
        activity: str,
        limit: int = 10
    ) -> Dict[str, Any]:
        params = {
            "bbox": ",".join(map(str, bbox)),
            "act": activity,
            "limit": limit,
            "orderby": "-date"
        }
        return self._request("/routes", params)

    def get_route_details(self, route_id: int) -> Dict[str, Any]:
        return self._request(f"/routes/{route_id}/{self.language}", {})

    def search_waypoints(
        self,
        bbox: Tuple[float, float, float, float],
        limit: int = 10
    ) -> Dict[str, Any]:
        params = {
            "bbox": ",".join(map(str, bbox)),
            "limit": limit
        }
        return self._request("/waypoints", params)

    @staticmethod
    def get_bbox_from_location(query: str) -> Optional[Tuple[float, float, float, float]]:
        """
        Geocode a location string and return a bounding box.

        Args:
            query: Name of the place or location (e.g., "Chamonix, France").

        Returns:
            Bounding box as (west, south, east, north) or None if not found.
        """
        url = "https://nominatim.openstreetmap.org/search"
        params = {
            "q": query,
            "format": "json",
            "limit": 1
        }
        headers = {"User-Agent": "camptocamp-api-wrapper"}
        response = requests.get(url, params=params, headers=headers)
        response.raise_for_status()
        results = response.json()
        if not results:
            return None
        bbox = results[0]["boundingbox"]  # ['south', 'north', 'west', 'east']
        return (
            float(bbox[2]),  # west
            float(bbox[0]),  # south
            float(bbox[3]),  # east
            float(bbox[1])   # north
        )