Skip to content

Instantly share code, notes, and snippets.

@Xliff
Created March 21, 2025 11:04
Show Gist options
  • Save Xliff/e2d88cb176f5d3a94a38c454ee19bb27 to your computer and use it in GitHub Desktop.
Save Xliff/e2d88cb176f5d3a94a38c454ee19bb27 to your computer and use it in GitHub Desktop.
Browser Detection in Raku

Here's a snippet of untested code that one should be able to use to detect what type of browser you have based on the User Agent string:

use v6.d;

# Written by the Repl.It AI with prompts created by Clifton Wood
# Further exits for Racquet authored by Clifton Wood

#| A class to detect browser information from User-Agent strings
unit class Racquet::BrowserDetector;

    #| Detects browser information from a UserAgent object
    method detect (Str() $ua) {
        my %result = (
            browser => 'Unknown',
            version => 'Unknown',
            os => 'Unknown',
            device => 'Desktop', # Default to desktop
            is-mobile => False
        );

        # Get the user agent string
        my $ua-string = $ua;

        # Detect mobile devices first
        if $.detect-mobile($ua) {
            %result<is-mobile> = True;
            %result<device> = 'Mobile';

            # Further refine mobile device type
            if $ua.contains('iPad') {
                %result<device> = 'Tablet';
            } elsif $ua.contains('Android') && !$ua.contains('Mobile') {
                %result<device> = 'Tablet';
            }
        }

        # Detect operating system
        %result<os> = $.detect-os($ua);

        # Detect browser and version
        my %browser-info = $.detect-browser($ua);
        %result<browser> = %browser-info<browser>;
        %result<version> = %browser-info<version>;

        return %result;
    }

    #| Detects if the user agent is from a mobile device
    method detect-mobile (Str() $ua) {
        # Check common mobile patterns
        my $mobile-patterns = rx:i:s/
            Android | webOS | iPhone | iPad | iPod | BlackBerry |
            Windows Phone | Opera Mini | IEMobile | Mobile |
            Smartphone | Tablet | Symbian | Nokia
        /;

        return $ua ~~ $mobile-patterns
    }

    #| Detects the operating system from a user agent
    method detect-os (Str() $ua) {
        my $ua-string = $ua;

        # Windows
        if $ua ~~ rx:i:s/ Windows NT \s+ ([\d\.]+) / -> $m {
            given $m[0].Str {
                when '10.0' { return 'Windows 10'; }
                when '6.3'  { return 'Windows 8.1'; }
                when '6.2'  { return 'Windows 8'; }
                when '6.1'  { return 'Windows 7'; }
                when '6.0'  { return 'Windows Vista'; }
                when '5.2'  { return 'Windows XP 64-bit'; }
                when '5.1'  { return 'Windows XP'; }
                default     { return "Windows ($version)"; }
            }
        }

        # macOS/OS X
        if $ua ~~ rx:i:s/ Mac OS X \s+ ([\d_\.]+) / -> $m {
            my $version = $m[0].Str.subst('_', '.', :g);
            return "macOS $version";
        }

        # iOS
        if $ua ~~ rx:i:s/ iPhone | iPad | iPod / {
            if $ua ~~ rx:i:s/ OS \s+ ([\d_]+) -> $m /
                my $version = $m[0].subst('_', '.', :g);
                return "iOS $version";
            }
            return 'iOS';
        }

        # Android
        if $ua ~~ rx:i:s/ Android \s+ ([\d\.]+) / -> $m {
            return "Android { $m[0] }";
        }

        # Linux
        if $ua.contains('Linux') {
            return 'Linux';
        }

        # Unix
        if $ua.contains('X11') {
            return 'Unix';
        }

        return 'Unknown';
    }

    #| Detects the browser and version from a user agent
    method detect-browser(Str() $ua) {
        my %result = (
            browser => 'Unknown',
            version => 'Unknown'
        );

        # Edge
        if $ua ~~ rx:i:s/ Edg[e]?[\/\s]([\d\.]+) / -> $m {
            %result<browser> = 'Microsoft Edge';
            %result<version> = $m[0].Str;
            return %result;
        }

        # Chrome
        if $ua ~~ rx:i:s/ Chrome\/([\d\.]+) / -> $m {
            %result<browser> = 'Google Chrome';
            %result<version> = $m[0].Str;
            return %result;
        }

        # Safari
        if ( my $m = $ua ~~ rx:i:s/ Safari\/([\d\.]+) / ) &&
           $ua.contains('Chrome').not
        {
            %result<browser> = 'Safari';

            # Safari version is usually in the Version/ part, not Safari/ part
            if $ua ~~ rx:i:s/ Version\/([\d\.]+) /) {
                %result<version> = $m[0].Str;
            } else {
                if $ua ~~ rx:i:s/ Safari\/([\d\.]+) / -> $m1;
                  %result<version> = $m1[0].Str;
                }
            }

            return %result;
        }

        # Firefox
        if $ua ~~ rx:i:s/ Firefox\/([\d\.]+) /) -> $m {
            %result<browser> = 'Mozilla Firefox';
            %result<version> = $m[0].Str;
            return %result;
        }

        # Opera
        if (my $m  = $ua ~~ rx:i:s/ Opera[\s\/]([\d\.]+) /) ||
           (my $m1 = $ua ~~ rx:i:s/ OPR\/([\d\.]+) /)
        {
            %result<browser> = 'Opera';
            %result<version> = ($m1 ?? $m1 !! $m)[0].Str;

            return %result;
        }

        # Internet Explorer
        if $ua ~~ rx:i:s/ MSIE \s+ ([\d\.]+) / -> $m {
            %result<browser> = 'Internet Explorer';
            %result<version> = $m[0].Str;
            return %result;
        }

        # Newer Internet Explorer
        if $ua ~~ rx:i:s/ Trident\/.*rv:([\d\.]+) / -> $m {
            %result<browser> = 'Internet Explorer';
            %result<version> = $m[0].Str;
            return %result;
        }

        return %result;
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment