Skip to content
This repository has been archived by the owner on Mar 2, 2024. It is now read-only.

Commit

Permalink
add generic analytics section for segment compatible api
Browse files Browse the repository at this point in the history
  • Loading branch information
the-newman committed Oct 9, 2023
1 parent 1131e5a commit 6569f72
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 14 deletions.
5 changes: 3 additions & 2 deletions mautrix_instagram/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ def prepare_bridge(self) -> None:
self.provisioning_api = ProvisioningAPI(
shared_secret=cfg["shared_secret"],
device_seed=self.config["instagram.device_seed"],
segment_key=cfg["segment_key"],
segment_user_id=cfg["segment_user_id"],
analytics_host=self.config["analytics.host"],
analytics_token=self.config["analytics.token"],
analytics_user_id=self.config["analytics.user_id"],
)
self.az.app.add_subapp(cfg["prefix"], self.provisioning_api.app)

Expand Down
13 changes: 11 additions & 2 deletions mautrix_instagram/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,17 @@ def do_update(self, helper: ConfigUpdateHelper) -> None:
copy("bridge.provisioning.shared_secret")
if base["bridge.provisioning.shared_secret"] == "generate":
base["bridge.provisioning.shared_secret"] = self._new_token()
copy("bridge.provisioning.segment_key")
copy("bridge.provisioning.segment_user_id")

copy("analytics.host")
if "appservice.provisioning.segment_key" in self:
base["analytics.token"] = self["appservice.provisioning.segment_key"]
else:
copy("analytics.token")
if "appservice.provisioning.segment_user_id" in self:
base["analytics.user_id"] = self["appservice.provisioning.segment_user_id"]
else:
copy("analytics.user_id")


copy("bridge.command_prefix")

Expand Down
13 changes: 9 additions & 4 deletions mautrix_instagram/example-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ appservice:
as_token: "This value is generated when generating the registration"
hs_token: "This value is generated when generating the registration"

# Segment-compatible analytics endpoint for tracking some events, like provisioning API login and encryption errors.
analytics:
# Hostname of the tracking server. The path is hardcoded to /v1/track
host: api.segment.io
# API key to send with tracking requests. Tracking is disabled if this is null.
token: null
# Optional user ID for tracking events. If null, defaults to using Matrix user ID.
user_id: null

# Prometheus telemetry config. Requires prometheus-client to be installed.
metrics:
enabled: false
Expand Down Expand Up @@ -335,10 +344,6 @@ bridge:
# The shared secret to authorize users of the API.
# Set to "generate" to generate and save a new token.
shared_secret: generate
# Segment API key to enable analytics tracking for web server endpoints. Set to null to disable.
segment_key: null
# Optional user_id to use when sending Segment events. If null, defaults to using mxID.
segment_user_id: null

# The prefix for commands. Only required in non-management rooms.
command_prefix: "!ig"
Expand Down
45 changes: 45 additions & 0 deletions mautrix_instagram/web/analytics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from __future__ import annotations

from urllib.parse import urlunparse
import logging

import aiohttp

from mautrix.util import background_task

from .. import user as u

log = logging.getLogger("mau.web.public.analytics")
http: aiohttp.ClientSession | None = None
analytics_url: str | None = None
analytics_token: str | None = None
analytics_user_id: str | None = None


async def _track(user: u.User, event: str, properties: dict) -> None:
await http.post(
analytics_url,
json={
"userId": analytics_user_id or user.mxid,
"event": event,
"properties": {"bridge": "instagram", **properties},
},
auth=aiohttp.BasicAuth(login=analytics_token, encoding="utf-8"),
)
log.debug(f"Tracked {event}")


def track(user: u.User, event: str, properties: dict | None = None):
if analytics_token:
background_task.create(_track(user, event, properties or {}))


def init(host: str | None, key: str | None, user_id: str | None = None):
log.debug("analytics is a go go")
if not host or not key:
return
global analytics_url, analytics_token, analytics_user_id, http
analytics_url = urlunparse(("https", host, "/v1/track", "", "", ""))
analytics_token = key
analytics_user_id = user_id
http = aiohttp.ClientSession()
11 changes: 6 additions & 5 deletions mautrix_instagram/web/provisioning_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@

from .. import user as u
from ..commands.auth import get_login_state
from .segment import init as init_segment, track
from .analytics import init as init_analytics, track


class ProvisioningAPI:
Expand All @@ -64,14 +64,15 @@ def __init__(
self,
shared_secret: str,
device_seed: str,
segment_key: str | None,
segment_user_id: str | None,
analytics_host: str | None,
analytics_token: str | None,
analytics_user_id: str | None,
) -> None:
self.app = web.Application()
self.shared_secret = shared_secret
self.device_seed = device_seed
if segment_key:
init_segment(segment_key, segment_user_id)
if analytics_host and analytics_token:
init_analytics(analytics_host, analytics_token, analytics_user_id)
self.app.router.add_get("/api/whoami", self.status)
self.app.router.add_options("/api/login", self.login_options)
self.app.router.add_options("/api/login/2fa", self.login_options)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import setuptools

from mautrix_instagram.get_version import git_tag, git_revision, version, linkified_version
from mautrix_instagram.get_version import git_revision, git_tag, linkified_version, version

with open("requirements.txt") as reqs:
install_requires = reqs.read().splitlines()
Expand Down

0 comments on commit 6569f72

Please sign in to comment.