Skip to content

Commit 83da185

Browse files
author
Vadim Belov
committed
Refactor user agent detection with typed device info
Introduce UserAgentDeviceInfo and UserAgentDeviceType for structured device detection. Refactor UserAgentHelpers to use modular parser functions and return richer device info (type, model, friendly name). Improve Android model extraction and aliasing. Update tests to cover new device detection logic and Samsung Galaxy models. This enhances extensibility and accuracy of device identification.
1 parent e12257f commit 83da185

4 files changed

Lines changed: 304 additions & 53 deletions

File tree

Sources/EasyExtensions.Tests/UserAgentHelpersTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ public void GetDevice_Identifies_iOS(string ua, string expected)
8080
[TestCase("Mozilla/5.0 (Linux; Android 12; Pixel 6 Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/94.0.4606.61 Mobile Safari/537.36", "Android Phone (Pixel 6)")]
8181
[TestCase("Mozilla/5.0 (Linux; Android 10; SM-G973F Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36", "Android Phone (SM-G973F)")]
8282
[TestCase("Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36", "Android Phone")]
83+
[TestCase("Mozilla/5.0 (Linux; Android 13; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Mobile Safari/537.36", "Android Phone (Samsung Galaxy S20)")]
84+
[TestCase("Mozilla/5.0 (Linux; Android 13; SM-S918B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Mobile Safari/537.36", "Android Phone (Samsung Galaxy S23 Ultra)")]
8385
[TestCase("Mozilla/5.0 (Linux; Android 11; SM-T970 Build/RP1A.200720.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.93 Safari/537.36", "Android Tablet (SM-T970)")]
8486
[TestCase("Mozilla/5.0 (Linux; Android 13; Tablet; rv:102.0) Gecko/102.0 Firefox/102.0", "Android Tablet")]
8587
public void GetDevice_Identifies_Android(string ua, string expected)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// SPDX-License-Identifier: MIT
2+
// Copyright (c) 2025–2026 Vadim Belov <https://belov.us>
3+
4+
namespace EasyExtensions.Helpers
5+
{
6+
/// <summary>
7+
/// Represents device information parsed from a user agent string, including device type, model, and a user-friendly
8+
/// name.
9+
/// </summary>
10+
public sealed class UserAgentDeviceInfo
11+
{
12+
/// <summary>
13+
/// Gets the type of device identified by the user agent string.
14+
/// </summary>
15+
public UserAgentDeviceType Type { get; }
16+
17+
/// <summary>
18+
/// Gets the name or identifier of the model associated with this instance.
19+
/// </summary>
20+
public string? Model { get; }
21+
22+
/// <summary>
23+
/// Gets the user-friendly display name associated with the object.
24+
/// </summary>
25+
public string? FriendlyName { get; }
26+
27+
/// <summary>
28+
/// Initializes a new instance of the UserAgentDeviceInfo class with the specified device type, model, and
29+
/// friendly name.
30+
/// </summary>
31+
/// <param name="type">The type of device represented by this instance.</param>
32+
/// <param name="model">The device model name, or null if not specified.</param>
33+
/// <param name="friendlyName">A user-friendly name for the device, or null if not specified.</param>
34+
public UserAgentDeviceInfo(UserAgentDeviceType type, string? model = null, string? friendlyName = null)
35+
{
36+
Type = type;
37+
Model = model;
38+
FriendlyName = friendlyName;
39+
}
40+
}
41+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// SPDX-License-Identifier: MIT
2+
// Copyright (c) 2025–2026 Vadim Belov <https://belov.us>
3+
4+
namespace EasyExtensions.Helpers
5+
{
6+
/// <summary>
7+
/// Specifies the type of device identified from a user agent string.
8+
/// </summary>
9+
/// <remarks>
10+
/// This enumeration is typically used to classify client devices based on their user agent information, such as
11+
/// distinguishing between mobile phones, tablets, desktop computers, and automated agents like bots or scripts.
12+
/// The values can be used to tailor application behavior or analytics based on the detected device type.
13+
/// </remarks>
14+
public enum UserAgentDeviceType
15+
{
16+
/// <summary>
17+
/// The device type cannot be determined from the available user agent information.
18+
/// </summary>
19+
Unknown = 0,
20+
21+
/// <summary>
22+
/// An automated agent (crawler/indexer) identified as a bot.
23+
/// </summary>
24+
Bot,
25+
26+
/// <summary>
27+
/// An automated client (for example a scriptable HTTP client) that is not classified as a bot.
28+
/// </summary>
29+
Script,
30+
31+
/// <summary>
32+
/// A smart TV device.
33+
/// </summary>
34+
SmartTv,
35+
36+
/// <summary>
37+
/// A game console device.
38+
/// </summary>
39+
GameConsole,
40+
41+
/// <summary>
42+
/// An Apple iPhone device.
43+
/// </summary>
44+
IPhone,
45+
46+
/// <summary>
47+
/// An Apple iPad device.
48+
/// </summary>
49+
IPad,
50+
51+
/// <summary>
52+
/// An Apple iPod device.
53+
/// </summary>
54+
IPod,
55+
56+
/// <summary>
57+
/// An Android-based phone device.
58+
/// </summary>
59+
AndroidPhone,
60+
61+
/// <summary>
62+
/// An Android-based tablet device.
63+
/// </summary>
64+
AndroidTablet,
65+
66+
/// <summary>
67+
/// A ChromeOS device (Chromebook).
68+
/// </summary>
69+
Chromebook,
70+
71+
/// <summary>
72+
/// A Windows desktop or laptop computer.
73+
/// </summary>
74+
WindowsPc,
75+
76+
/// <summary>
77+
/// A macOS desktop or laptop computer.
78+
/// </summary>
79+
Mac,
80+
81+
/// <summary>
82+
/// A Linux desktop or laptop computer.
83+
/// </summary>
84+
LinuxPc,
85+
86+
/// <summary>
87+
/// A generic mobile device when a more specific classification is not available.
88+
/// </summary>
89+
Mobile,
90+
91+
/// <summary>
92+
/// A server-side or non-interactive client (for example, backend-to-backend traffic) when recognizable.
93+
/// </summary>
94+
Server,
95+
}
96+
}

0 commit comments

Comments
 (0)