API reference¶
Auto-generated from docstrings in the ovh_voip_spam_filter package.
OVH client¶
ovh_voip_spam_filter.ovh_api
¶
Minimal OVH API client (stdlib only).
Implements OVH's "$1$" signed-request scheme:
signature = "$1$" + sha1(
application_secret + "+" + consumer_key + "+" +
METHOD + "+" + URL + "+" + BODY + "+" + TIMESTAMP
).hexdigest()
Designed for a non-interactive cron/K8s context: - Client-side throttle between calls (default 1 req/s, configurable). - 429 backoff respecting Retry-After header, with jittered exponential fallback and an absolute cap. - Auto-adapts the throttle: after 3 consecutive 429s the inter-call interval is doubled for the rest of the session (no manual tuning required if OVH's per-account quota differs from the documented 60/min).
OvhClient
¶
Source code in src/ovh_voip_spam_filter/ovh_api.py
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 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 | |
total_throttle_adaptations
property
¶
Number of times min_interval_seconds was auto-doubled this session.
Reconciliation pipeline¶
ovh_voip_spam_filter.reconcile
¶
Reconciliation pipeline: OVH state ← target patterns (Saracroche or ARCEP fallback).
Two modes, determined at runtime by Saracroche reachability:
Normal mode (Saracroche fetched OK): Saracroche is the source of truth. to_add = target - current (POST) to_remove = current - target (DELETE) Strict sync.
Degraded mode (Saracroche unreachable): Fall back to hard-coded ARCEP prefixes (23 entries, 100% démarchage légal FR). to_add = arcep - current (POST) to_remove = [] (NEVER delete — partial knowledge could regress) Additive-only.
The dry-run variant returns the plan without applying it.
CurrentEntry
dataclass
¶
ensure_blacklist_enabled(client, billing_account, service_name)
¶
If incomingScreenList is 'disabled', PUT it to 'blacklist' preserving outgoing.
Per design (validated with user): auto-activate, never block, WARN log.
Source code in src/ovh_voip_spam_filter/reconcile.py
load_current(client, billing_account, service_name)
¶
Read every existing screenList entry. N + 1 GETs (throttled by client).
Source code in src/ovh_voip_spam_filter/reconcile.py
load_target()
¶
Saracroche live → fallback to hard-coded ARCEP. Cache is not used here.
The Phase-1 file cache is bypassed in K8s/cron context: container is
ephemeral, Saracroche is cheap to refetch (~150 KB JSON). The CLI mode
(Phase 1) still has its own cached path via generate.
Source code in src/ovh_voip_spam_filter/reconcile.py
summarize_plan(plan, rate_limit_ms)
¶
Human-readable summary of the plan (for dry-run output).
Source code in src/ovh_voip_spam_filter/reconcile.py
Saracroche client¶
ovh_voip_spam_filter.saracroche
¶
Client for the Saracroche community blocklist API.
Endpoint: GET https://saracroche.org/api/v1/lists/french-list-arcep-operators Auth: none Schema: { version, name, license, description, blocked_numbers_count, patterns: [{name, pattern, action}] }
Source cascade (see load_block_patterns): 1. Live API 2. Local cache file (last successful snapshot) 3. Caller decides what to do with the FetchError (CLI falls back to ARCEP)
Configuration¶
ovh_voip_spam_filter.config
¶
Credentials and runtime configuration loader.
Precedence (highest first): 1. CLI flags (handled in cli.py) 2. Environment variables (operational mode: Docker / K8s) 3. JSON config file (developer convenience, default .ovh-credentials.json)
Env vars
OVH_ENDPOINT ovh-eu | ovh-ca | ovh-us (default: ovh-eu) OVH_APPLICATION_KEY (required for signed requests) OVH_APPLICATION_SECRET (required for signed requests) OVH_CONSUMER_KEY (required for signed requests) OVH_BILLING_ACCOUNT target billing account (required for sync) OVH_SERVICE_NAME target SIP line (required for sync) RATE_LIMIT_MS min ms between calls (default: 1000) LOG_LEVEL DEBUG | INFO | WARNING | ERROR (default: INFO)
require_signed_credentials(config)
¶
Validate that we have everything needed for signed OVH API calls.
Raises ConfigError with a clear remediation message if any is missing.
Source code in src/ovh_voip_spam_filter/config.py
require_target(config)
¶
Validate billing_account + service_name presence (required for sync).
Source code in src/ovh_voip_spam_filter/config.py
Patterns¶
ovh_voip_spam_filter.patterns
¶
BlockPattern
dataclass
¶
A pattern flagged for blocking.
raw is the Saracroche-style pattern in international form without +
and with # as trailing wildcards (e.g. 33162######).
name is the human label from the source (Préfixe démarchage ARCEP, etc.).
Source code in src/ovh_voip_spam_filter/patterns.py
deduplicate_ovh_prefixes(prefixes)
¶
Drop prefixes that are subsumed by a shorter prefix already present.
OVH matches by prefix, so +33162345 is redundant if +33162 is also in the list.
Preserves the order of first occurrence.
Source code in src/ovh_voip_spam_filter/patterns.py
prioritize(patterns)
¶
Stable sort that puts ARCEP entries first, preserving input order within each group.
Used so that --max-entries N truncation always keeps the ARCEP coverage critical
to the user's reported numbers.
Source code in src/ovh_voip_spam_filter/patterns.py
ARCEP fallback¶
ovh_voip_spam_filter.arcep
¶
Hard-coded ARCEP démarchage prefix ranges.
Source: ARCEP numbering plan decision (effective 2022-09-01). This is the last-resort fallback when the Saracroche API is unreachable and no local cache is available.
Each prefix is the international form (33...) and matches any number starting with that sequence. Saracroche's main list is a superset.