Skip to content

Commit df219eb

Browse files
committed
chore: retooling for new web API
1 parent 8b0751c commit df219eb

11 files changed

Lines changed: 330 additions & 32 deletions

File tree

.envrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export OAUTH_CLIENT_ID=7v4bnRCzelHg6DdEtw6K81ayjTP3GJV0seFtsRv8
2+
export TOKEN_FILE_PATH=".token-file.json"
3+
export API_URI="http://localhost:8000"

.pre-commit-config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,5 @@ repos:
3030
rev: v1.19.1
3131
hooks:
3232
- id: mypy
33+
additional_dependencies:
34+
- 'types-requests'

.token-file.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"access": {"token_value": "GuXYyK7iC0l4GOGE5N8pU8Q99z0aaf", "expiry_time": 1770967462.992627}, "refresh": {"token_value": "J8ZSFtUqKFPDKoer71bODFx4wyqXwR"}}

intercomclient/aws.py

Lines changed: 0 additions & 27 deletions
This file was deleted.

intercomclient/config.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
from dataclasses import dataclass
22
from typing import Tuple
33
import logging
4+
import os
45

56

67
@dataclass()
78
class Config:
89
segment_duration: int = 60
910
fps: int = 5
1011
resolution: Tuple[int, int] = (320, 240)
11-
s3_bucket_name: str = "segment-uploads"
1212
debug_mode: bool = True
1313
video_source: int = 0
1414
output_dir_path: str = "/tmp/intercom_videos"
1515
fourcc: str = "XVID"
1616
video_format: str = "avi"
17+
oauth_scope: str = "openid email profile"
18+
oauth_grant: str = "urn:ietf:params:oauth:grant-type:device_code"
19+
oauth_client_id: str = os.getenv("OAUTH_CLIENT_ID", "wrong")
20+
token_file_path: str = os.getenv("TOKEN_FILE_PATH", "wrong")
21+
api_uri: str = os.getenv("API_URI", "wrong")
22+
max_polling_time_mins: int = int(os.getenv("MAX_POLLING_TIME_MINS", 5))
1723

1824

1925
logging.basicConfig(level=logging.DEBUG if Config.debug_mode else logging.INFO)

intercomclient/device.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import platform
2+
3+
4+
def get_os_info():
5+
return platform.platform()
6+
7+
8+
def get_device_type():
9+
return platform.machine()
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from .device import get_device_type, get_os_info
2+
from .config import Config
3+
from time import sleep
4+
from datetime import datetime, timedelta
5+
import requests
6+
7+
8+
def initiate_device_authorization(config: Config) -> dict:
9+
client_id = Config.oauth_client_id
10+
device_type = get_device_type()
11+
device_os = get_os_info()
12+
url = f"{Config.api_uri}/api/v1/oauth/device-authorization/"
13+
14+
api_response = requests.post(
15+
url,
16+
data={
17+
"client_id": client_id,
18+
"device_type": device_type,
19+
"device_os": device_os,
20+
"scope": "profile email",
21+
},
22+
)
23+
return api_response.json()
24+
25+
26+
def poll_for_token(config: Config, device_code: str, interval: int) -> dict:
27+
client_id = Config.oauth_client_id
28+
29+
continue_polling = True
30+
polling_end_time = datetime.now() + timedelta(minutes=config.max_polling_time_mins)
31+
url = f"{Config.api_uri}/oauth/token/"
32+
while continue_polling:
33+
if datetime.now() > polling_end_time:
34+
continue_polling = False
35+
break
36+
sleep(interval)
37+
api_response = requests.post(
38+
url,
39+
data={
40+
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
41+
"device_code": device_code,
42+
"client_id": client_id,
43+
},
44+
)
45+
resp_json = api_response.json()
46+
if "error" in resp_json and resp_json["error"] == "authorization_pending":
47+
continue
48+
else:
49+
return api_response.json()
50+
51+
return api_response.json()
52+
53+
54+
def refresh_tokens(config: Config, refresh_token) -> dict:
55+
client_id = Config.oauth_client_id
56+
url = f"{Config.api_uri}/oauth/token/"
57+
58+
api_response = requests.post(
59+
url,
60+
data={
61+
"grant_type": "refresh_token",
62+
"client_id": client_id,
63+
"refresh_token": refresh_token,
64+
},
65+
)
66+
67+
return api_response.json()

intercomclient/local_store.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import json
2+
from .config import Config
3+
4+
5+
def load_tokens():
6+
with open(Config.token_file_path, "r") as token_file_handle:
7+
return json.load(token_file_handle)
8+
9+
10+
def store_tokens(tokens: dict[str, str], access_token_expiry):
11+
data = {
12+
"access": {
13+
"token_value": tokens["access_token"],
14+
"expiry_time": access_token_expiry,
15+
},
16+
"refresh": {"token_value": tokens["refresh_token"]},
17+
}
18+
with open(Config.token_file_path, "w") as token_file_handle:
19+
token_file_handle.write(json.dumps(data))

main.py

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,39 @@
1-
from intercomclient.video_pipeline import VideoPipeline
1+
from intercomclient.device_authorization import (
2+
initiate_device_authorization,
3+
poll_for_token,
4+
refresh_tokens,
5+
)
26
from intercomclient.config import Config
7+
import logging
8+
from datetime import datetime, timedelta, UTC
9+
from intercomclient.local_store import store_tokens, load_tokens
310

4-
if __name__ == "__main__":
5-
pipeline = VideoPipeline(config=Config)
6-
pipeline.record_segment()
11+
logging.basicConfig(level=logging.INFO)
12+
LOG = logging.getLogger(__name__)
13+
config = Config()
14+
15+
authorization_response = initiate_device_authorization(config)
16+
LOG.info(f"User code: {authorization_response['user_code']}")
17+
18+
token_response = poll_for_token(
19+
config,
20+
authorization_response["device_code"],
21+
interval=authorization_response["interval"],
22+
)
23+
print(token_response)
24+
25+
token_expiry = (
26+
datetime.now(tz=UTC) + timedelta(seconds=token_response["expires_in"])
27+
).timestamp()
28+
29+
store_tokens(
30+
{
31+
"access_token": token_response["access_token"],
32+
"refresh_token": token_response["refresh_token"],
33+
},
34+
access_token_expiry=token_expiry,
35+
)
36+
37+
refresh_token_response = refresh_tokens(config, load_tokens()["refresh"]["token_value"])
38+
39+
print(refresh_token_response)

pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ dependencies = [
88
"boto3>=1.42.39",
99
"numpy>=2.4.1",
1010
"opencv-python>=4.13.0.90",
11+
"pip==26.0",
12+
"requests>=2.32.5",
1113
"ruff>=0.14.14",
14+
"transparenc-sdk",
1215
]
1316

1417
[dependency-groups]
@@ -17,3 +20,6 @@ dev = [
1720
"pytest>=9.0.2",
1821
"pytest-watch>=4.2.0",
1922
]
23+
24+
[tool.uv.sources]
25+
transparenc-sdk = { url = "https://github.com/kieranmanning/IntercomClientSDKs/releases/download/v0.9/transparenc_sdk-1.0.0-py3-none-any.whl" }

0 commit comments

Comments
 (0)