Stop sending UI events to IMVU
CI / test (push) Successful in 1m9s

The client also posts UI events (clicks and open tabs, with the user and session IDs) to api.imvu.com/events every 30 seconds or so; the analytics patch missed them, and the reporting blocklist now refuses the endpoint too.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
dhkatzandClaude Opus 5.5 committed 2026-10-28 07:20:12 -07:00
1 parent b926601bd9
commit d29ec1a6d3
2 files changed
+64 -9

No files matched your search

@@ -5,7 +5,9 @@ Subject: [PATCH] Stop sending usage analytics and metrics to IMVU
Drops every usage fact (UI clicks, modes opened, shop actions, preference changes) where facts are Drops every usage fact (UI clicks, modes opened, shop actions, preference changes) where facts are
queued for upload, plus the room loading time gauge, the room loading video skip counter and the queued for upload, plus the room loading time gauge, the room loading video skip counter and the
camera picture counter. camera picture counter. UI events (the user's clicks and open tabs, with their user and session IDs,
sent to api.imvu.com/events every 30 seconds or so) are no longer recorded, and any queued from before
are discarded.
Co-Authored-By: Claude Opus 5.5 <[email protected]> Co-Authored-By: Claude Opus 5.5 <[email protected]>
T5de-Id: no-analytics T5de-Id: no-analytics
@@ -13,10 +15,11 @@ T5de-Group: privacy
T5de-Required: true T5de-Required: true
T5de-Name: Block analytics T5de-Name: Block analytics
--- ---
imvuContent/widgets/photo/PhotoWidget.js | 17 ----------------- imvuContent/widgets/photo/PhotoWidget.js | 17 ------------
library/imvu/account.py | 10 ---------- library/imvu/account.py | 10 -------
library/imvu/widget/roomloadingwidget.py | 14 ++------------ library/imvu/data/uieventmanager.py | 33 +-----------------------
3 files changed, 2 insertions(+), 39 deletions(-) library/imvu/widget/roomloadingwidget.py | 14 ++--------
4 files changed, 3 insertions(+), 71 deletions(-)
diff --git a/imvuContent/widgets/photo/PhotoWidget.js b/imvuContent/widgets/photo/PhotoWidget.js diff --git a/imvuContent/widgets/photo/PhotoWidget.js b/imvuContent/widgets/photo/PhotoWidget.js
index f533850b0daf47f80c43f2ce25b0ef0ee83c5d8a..bbad77c6713b11dba5c79a5d000af819e9eab2e2 100644 index f533850b0daf47f80c43f2ce25b0ef0ee83c5d8a..bbad77c6713b11dba5c79a5d000af819e9eab2e2 100644
@@ -67,6 +70,58 @@ index e7a00dd236be5568c9216d3a50abf87947d5209e..0c5fa264b27ff53fb92bcd6b6f958724
return return
def notifyClientSessionEvent(self, event, blocking=False, clientSessionId=None): def notifyClientSessionEvent(self, event, blocking=False, clientSessionId=None):
diff --git a/library/imvu/data/uieventmanager.py b/library/imvu/data/uieventmanager.py
index 86ab03521584a5c8463b29a7a9625a82de2de124..7fcdffe32e9129f5a93fbc8cb0af2fd801ce1168 100644
--- a/library/imvu/data/uieventmanager.py
+++ b/library/imvu/data/uieventmanager.py
@@ -65,16 +65,6 @@ class UIEventManager(HasTaskConstructor, TaskOwner, EventSink):
return
def recordEvent(self, uiEvent):
- if self.__modeManager != None:
- uiEvent.params['activeMode'] = self.__modeManager.topLevelWindow.activeTabId
- else:
- uiEvent.params['activeMode'] = None
- uiEvent.timestamp = int(self.__serviceProvider.timeProvider())
- uiEvent.actor = {'user_id': (str(self.__userAccount.getUserId())),
- 'client_session_id': (str(self.__userAccount.getClientSessionId()))}
- self.__queuedEvents.append(uiEvent)
- self.__save()
- self.__receivedEvent.set()
return
def __save(self):
@@ -120,29 +110,8 @@ class UIEventManager(HasTaskConstructor, TaskOwner, EventSink):
@task
def __sendEventsToServer(self):
- if not self.__userAccount.getUIEventUri() or 'dev_null' in self.__userAccount.getUIEventUri():
- yield Return()
- eventsToSend = self.__queuedEvents[:]
self.__queuedEvents = []
self.__save()
- self.__lastSendTime = self.__timeProvider()
- if eventsToSend:
- try:
- postData = {'post_time': (int(self.__timeProvider())), 'events': []}
- for uiEvent in eventsToSend:
- postData['events'].append({'application': 'imvu',
- 'timestamp': (uiEvent.timestamp),
- 'actor': (uiEvent.actor),
- 'ui': {'attributes': (uiEvent.params),
- 'context': (uiEvent.context),
- 'action': (uiEvent.action)}})
-
- result = yield imvu.http.securePost(url=self.__userAccount.getUIEventUri(), params=postData, auth=self.__userAccount.getAuth(), responseSchema=[], network=self.__serviceProvider.network, method='POST', gzip=False)
- except networkExceptions as e:
- logger.exception('Error while trying to send events')
- self.__receivedEvent.set()
- self.__queuedEvents = eventsToSend + self.__queuedEvents
-
+ yield Return()
return
-
diff --git a/library/imvu/widget/roomloadingwidget.py b/library/imvu/widget/roomloadingwidget.py diff --git a/library/imvu/widget/roomloadingwidget.py b/library/imvu/widget/roomloadingwidget.py
index c6bac210166f5340cab531441ecde9764b8cfc9f..cad1b63bf8ccd22d3929b462a5db82db3c87d064 100644 index c6bac210166f5340cab531441ecde9764b8cfc9f..cad1b63bf8ccd22d3929b462a5db82db3c87d064 100644
--- a/library/imvu/widget/roomloadingwidget.py --- a/library/imvu/widget/roomloadingwidget.py
@@ -5,8 +5,8 @@ Subject: [PATCH] Block IMVU's reporting endpoints in the network layer
A backstop for the other patches: every HTTP request the client's Python makes goes through A backstop for the other patches: every HTTP request the client's Python makes goes through
Network.urlopen or Network.post_multipart, which now refuse Bugzilla, DRV error reports, counters, Network.urlopen or Network.post_multipart, which now refuse Bugzilla, DRV error reports, counters,
gauges and log uploads, and log each refusal as "t5de: blocked request to ...". Both wrap IMVU's gauges, log uploads and UI events, and log each refusal as "t5de: blocked request to ...". Both wrap
original methods rather than recompiling them. IMVU's original methods rather than recompiling them.
This also stops the first-launch counter, which fires again since patch 15 gave the client its own, This also stops the first-launch counter, which fires again since patch 15 gave the client its own,
empty settings. empty settings.
@@ -21,7 +21,7 @@ T5de-Name: Block reporting servers
1 file changed, 13 insertions(+), 72 deletions(-) 1 file changed, 13 insertions(+), 72 deletions(-)
diff --git a/library/imvu/network.py b/library/imvu/network.py diff --git a/library/imvu/network.py b/library/imvu/network.py
index 6cfdc939ca1207bc26c801d1b641df8988de0847..07b92b2feab29ace3032ff6dd64cdc0ab7e33a39 100644 index 6cfdc939ca1207bc26c801d1b641df8988de0847..88c3be8adc0c8203748da25b1c848d9f5d33c8c6 100644
--- a/library/imvu/network.py --- a/library/imvu/network.py
+++ b/library/imvu/network.py +++ b/library/imvu/network.py
@@ -259,60 +259,8 @@ class Network(ActiveObject): @@ -259,60 +259,8 @@ class Network(ActiveObject):
@@ -94,7 +94,7 @@ index 6cfdc939ca1207bc26c801d1b641df8988de0847..07b92b2feab29ace3032ff6dd64cdc0a
+ def _t5de_blockReporting(self, url): + def _t5de_blockReporting(self, url):
+ # IMVU's crash, error and metrics reporting endpoints. Every HTTP request goes through urlopen or + # IMVU's crash, error and metrics reporting endpoints. Every HTTP request goes through urlopen or
+ # post_multipart, so this also stops reporting that the other patches miss. + # post_multipart, so this also stops reporting that the other patches miss.
+ for endpoint in ('bugs.imvu.com', '/api/drv.php', '/api/increment_counter.php', '/api/record_gauge.php', '/catalog/web_submit_logs.php', '/catalog/imvu_monitor_submit.php'): + for endpoint in ('bugs.imvu.com', '/api/drv.php', '/api/increment_counter.php', '/api/record_gauge.php', '/catalog/web_submit_logs.php', '/catalog/imvu_monitor_submit.php', 'api.imvu.com/events'):
+ if endpoint in url.lower(): + if endpoint in url.lower():
+ logger.warning('t5de: blocked request to %s', url) + logger.warning('t5de: blocked request to %s', url)
+ raise URLError('t5de: blocked request to %s' % url) + raise URLError('t5de: blocked request to %s' % url)