Skip to content
48 changes: 48 additions & 0 deletions __tests__/UserAgent.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Platform } from 'react-native';
import { getUserAgent } from '../src/utils/UserAgent';

// Mock Platform from react-native
jest.mock('react-native', () => ({
Platform: {
OS: 'ios',
Version: '17.0',
},
}));

describe('getUserAgent', () => {
afterEach(() => {
jest.clearAllMocks();
});

test('should return iOS user agent when platform is iOS', () => {
(Platform as any).OS = 'ios';
(Platform as any).Version = '17.0';

const userAgent = getUserAgent();

expect(userAgent).toBe('WMBRApp/0.0.1 (iOS; iPhone)');
});

test('should return Android user agent when platform is Android', () => {
(Platform as any).OS = 'android';
(Platform as any).Version = 33;

const userAgent = getUserAgent();

expect(userAgent).toBe('WMBRApp/0.0.1 (Android; SDK 33)');
});

test('should include correct SDK version for Android', () => {
(Platform as any).OS = 'android';
(Platform as any).Version = 30;

const userAgent = getUserAgent();

expect(userAgent).toContain('SDK 30');
});

test('should always include app version in user agent', () => {
const iosUserAgent = getUserAgent();
expect(iosUserAgent).toContain('WMBRApp/0.0.1');
});
});
3 changes: 3 additions & 0 deletions src/app/Home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { WmbrRouteName } from '../../types/Navigation';
import { DEFAULT_NAME } from '../../types/Playlist';
import { COLORS, CORE_COLORS } from '../../utils/Colors';
import { formatArchiveDate } from '../../utils/DateTime';
import { getUserAgent } from '../../utils/UserAgent';

import HomeNowPlaying from './HomeNowPlaying';

Expand Down Expand Up @@ -131,6 +132,7 @@ export default function HomeScreen() {
title: DEFAULT_NAME,
artist: 'Live Radio',
artwork: require('../../../assets/cover.png'),
userAgent: getUserAgent(),
});

setIsPlayerInitialized(true);
Expand Down Expand Up @@ -163,6 +165,7 @@ export default function HomeScreen() {
title: DEFAULT_NAME,
artist: currentShow || 'Live Radio',
artwork: require('../../../assets/cover.png'),
userAgent: getUserAgent(),
});
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/services/ArchiveService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import TrackPlayer, { Track } from 'react-native-track-player';
import { Show, Archive } from '../types/RecentlyPlayed';
import { debugLog, debugError } from '../utils/Debug';
import { DEFAULT_NAME } from '../types/Playlist';
import { getUserAgent } from '../utils/UserAgent';

export interface ArchivePlaybackState {
isPlayingArchive: boolean;
Expand Down Expand Up @@ -59,6 +60,7 @@ export class ArchiveService {
title: `${show.name} - Archive`,
artist: `${DEFAULT_NAME} - ${archive.date}`,
artwork: require('../../../assets/cover.png'),
userAgent: getUserAgent(),
};

// Add and play archive
Expand Down Expand Up @@ -95,6 +97,7 @@ export class ArchiveService {
title: DEFAULT_NAME,
artist: currentShowTitle || 'Live Radio',
artwork: require('../../../assets/cover.png'),
userAgent: getUserAgent(),
};

// Add and play live stream
Expand Down
2 changes: 2 additions & 0 deletions src/services/AudioPreviewService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import TrackPlayer, { Track, State, Event } from 'react-native-track-player';
import { debugError } from '../utils/Debug';
import { getUserAgent } from '../utils/UserAgent';

export interface PreviewState {
isPlaying: boolean;
Expand Down Expand Up @@ -141,6 +142,7 @@ export class AudioPreviewService {
url: url,
title: 'Preview',
artist: 'Apple Music Preview',
userAgent: getUserAgent(),
};

// Reset the queue with just the preview track
Expand Down
21 changes: 21 additions & 0 deletions src/utils/UserAgent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Platform } from 'react-native';

/**
* Generates a platform-specific user agent string for HTTP requests.
* This helps servers identify iOS vs Android clients.
*
* Format: WMBRApp/{version} ({platform}; {os})
* Examples:
* - "WMBRApp/0.0.1 (iOS; iPhone)"
* - "WMBRApp/0.0.1 (Android; SDK 33)"
*/
export function getUserAgent(): string {
const version = '0.0.1'; // Should match package.json version
const osVersion = Platform.Version;

if (Platform.OS === 'ios') {
return `WMBRApp/${version} (iOS; iPhone)`;
} else {
return `WMBRApp/${version} (Android; SDK ${osVersion})`;
}
}