podigee / device_detector Goto Github PK
View Code? Open in Web Editor NEWDeviceDetector is a precise and fast user agent parser and device detector written in Ruby
License: Other
DeviceDetector is a precise and fast user agent parser and device detector written in Ruby
License: Other
the user agent like
"Mozilla/5.0 (Linux; Android 5.1; MX5 Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.49 Mobile MQQBrowser/6.2 TBS/043015 Safari/537.36 MicroMessenger/6.5.3.980 NetType/4G Language/zh_CN"
and the device_type is nil
This gem seems so promising!
I looked into this for a few minutes, but couldn't determine the problem. Here's what I ran in irb:
2.1.5 :001 > require 'device_detector'
=> true
2.1.5 :002 > user_agent = 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.17 Safari/537.36'
=> "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.17 Safari/537.36"
2.1.5 :003 > client = DeviceDetector.new(user_agent)
=> #<DeviceDetector:0x007fab345a3b10 @user_agent="Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.17 Safari/537.36">
2.1.5 :004 > client.name
=> "Chrome"
2.1.5 :005 > client.full_version
=> "30.0.1599.17"
2.1.5 :006 > client.os_name
=> "Windows"
2.1.5 :007 > client.os_full_version
=> "8"
2.1.5 :008 > client.device_name
=> "OW64"
2.1.5 :009 > client.device_type
=> "tv"
In device_detector 1.0.7
DeviceDector.new(nil).device_name # => nil
In device_detector 1.1.0
DeviceDector.new(nil).device_name
raises
gems/device_detector-1.1.0/lib/device_detector.rb:221:in
fix_for_x_music': undefined method
include?' for nil:NilClass (NoMethodError)
This seems like maybe an unintended backwards incompatible change, that may break some dependents that aren't prepared for it?
The easy workaround seems to be to make sure you never pass nil
to DeviceDector.new
; passing an empty string is fine, so DeviceDector.new(str_var || "")
might be the way to go.
But perhaps DeviceDetector should handle this itself?
Hi! I've encountered Encoding::CompatibilityError in my project caused by non-standard characters in a custom User-Agent.
Environment: Ruby 3.2.0, DeviceDetector 1.1.0.
Environment: Ruby 3.0.2, DeviceDetector 1.1.0.
User's agent is Mon User-Agent personnalisé
.
The error:
Encoding::CompatibilityError (incompatible encoding regexp match (UTF-8 regexp with ASCII-8BIT string))
It seems to be caused by user_agent =~ r[:regex]
in device.rb's regex_find
device_detector/lib/device_detector/device.rb
Line 1560 in 609256f
I see that it already rescues RegexpError. I was wondering if Encoding::CompatibilityError stands to be rescued here as well. I've forked the gem and made the change for my project and it no longer raises an error with this User-Agent, removing the last char instead.
Any thoughts on this?
Trace:
device_detector (1.1.0) lib/device_detector/device.rb in each at line 1560
device_detector (1.1.0) lib/device_detector/device.rb in find at line 1560
device_detector (1.1.0) lib/device_detector/device.rb in regex_find at line 1560
device_detector (1.1.0) lib/device_detector/device.rb in block in matching_regex at line 1535
device_detector (1.1.0) lib/device_detector/parser.rb in block in from_cache at line 92
device_detector (1.1.0) lib/device_detector/memory_cache.rb in get_or_set at line 38
device_detector (1.1.0) lib/device_detector/parser.rb in from_cache at line 92
device_detector (1.1.0) lib/device_detector/device.rb in matching_regex at line 1531
device_detector (1.1.0) lib/device_detector/parser.rb in regex_meta at line 31
device_detector (1.1.0) lib/device_detector/device.rb in type at line 1505
device_detector (1.1.0) lib/device_detector.rb in device_type at line 67
How to detect brand name for mobile? There has a device_name field but mostly it shows only the device model and can't detect phone brands such as Samsung, Mi etc...
When parsing a user_agent for Chrome on Mac OSX 10.10.2, the os_full_version is returned as 10_10_2
instead of 10.10.2
Hello, due to the number of changes in the device-detector original library, even if I run the rake tasks for updating the YAML files, the tests do not pass.
I have seen that some fixes have been added to the library so that is presumably the reason why the tests do not pass. I tried to change some results expected as "" but returned as nil and vice versa, but I could not get all the tests passed, so I think the best would be to start adding those fixes to this Ruby implementation of the library.
I am willing to contribute, I will start adding some pull requests.
Thanks and congratulations for the excellent library.
I'm wondering what people use for detecting hosting networks or networks likely to have bots? I see that Amazon advertise their IP address ranges via JSON. Would there be an interest in adding that functionality to this gem? Provided we could find enough network ranges that is.
Hi,
We are encountering an issue that some requests are hanging or even timing out, and our thought is that it has to do with our high load and the device_detector library as it always happens before our first db call which only has the device detection before it. and then specifically caused by the Mutex locking.
Our servers are running with puma and concurrency. but more important, none of the user agents in the time frame of 5000 cached keys is expected to be equal or very little ones.
Is setting the cache amount to 0 enough? or will this break the caching option?
what do you suggest/think?
Kind regards,
Stephan
Now that android 9 is live, the user agents we get from those devices look something like this:
Mozilla/5.0 (Linux; Android 9; Pixel 2 XL Build/PPP3.180510.008; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/67.0.3396.87 Mobile Safari/537.36
^
This is where we should see something like 9.0 instead
(as seen here)
Because the regexp for android devices expects a version number like
(\d+[\.\d]+)
The lone 9
is just not picked up.
You can reproduce it like this:
dd = DeviceDetector.new "Mozilla/5.0 (Linux; Android 9; Pixel 2 Build/PPR1.180610.009) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Mobile Safari/537.36"
dd.os_full_version # => nil
Hi, @peteygao
Great gem, I want to replace user_agent.
But I face a small problem now, I want to get os.family and find it private.
Do you have plan to open the information? Thank you very much.
Hi there! It would be nice to have git tags matching with gem releases. Thank you!
The 1.0 release notes are missing from the changelog.
Hello,
I have the following user agent : "Mozilla/5.0 (Android 7.1.2; Mobile; rv:55.0.2) Gecko/55.0.2 Firefox/55.0.2"
It can't detect that I am using a smartphone
but it detect that I'm using Android..
device = DeviceDetector.new("Mozilla/5.0 (Android 7.1.2; Mobile; rv:55.0.2) Gecko/55.0.2 Firefox/55.0.2")
device.device_type
=> nil
device.os_name
=> "Android"
I see that regexes from original repository has been imported last time at 2022-02-17 (8 months ago at a time when I'm writing this) so I'd like to ask if this gem is still maintained by author and if updates can be expected in future?
Device_name returns nil for user_agent string
'Mozilla/5.0 (Linux; Android 5.1.1; ONE E1003 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.95 Mobile Safari/537.36'
but returns proper OS info:
> c = DeviceDetector.new 'Mozilla/5.0 (Linux; Android 5.1.1; ONE E1003 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.95 Mobile Safari/537.36'
> c.device_name
=> nil
> c.device_brand
=> nil
> c.os_name
=> "Android"
> c.os_full_version
=> "5.1.1"
Please correct me if I'm wrong... The actual parsing of the UA string does not take place until a specific component is requested. At that point only that specific component is extracted from the UA string. So other user agent parsers which extract all components at once will show up slower in your benchmarks.
I can see where your JIT parser approach comes in handy when only one or two components are used within an application. it would be interesting to see how your approach actually compares to a full parse of all components. For example Useragent now supports a #to_h method which provides a nicely structured representation of all of the components of the UA string.
If DeviceDetector had a #to_h feature that did the same thing, how would your regex approach compare benchmark-wise against UserAgent ?
I can see how a #to_h feature may be outside the scope for which DeviceDetector is best suited.
Dewayne
o-*
Mark user_agent: Datadog/Synthetics
as bot
Hi, first thanks for this wonderful and powerful gem.
We run into an issue that took a long time to understand.
Actually we found out that the reason our app has wrong behavior is sue to device detector gem.
Indeed on UC browsers, the original Piwik fixed the issue in order not to output "Chrome" but UC Browser a major browser (in Asia notably).
See matomo-org/device-detector#5617
But in our tests on various UC Browsers, for example on the user agent below, the original piwik after their fix now righfully output client name =uc browser, but ruby device Detector Gem still wrongly output "Chrome"
User agent example
Mozilla/5.0 (Linux; U; Android 4.2.2;en-US;Darkmoon Build Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.0.0.1088 Mobile Safari/537.36
I think it's due to the fact the folder regexes was last updated 11 months ago but the fix in the piwik yaml regexes was done in may 2017, which is before those 11 months.
Is is easy to fix ?
Thanks
M.
Hi! This gem is currently being used as a dependency, and I noticed a gem specific warning that pops up when device_detector
is initialized.
Specifically:
warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression
AND
regular expression has ']' without escape
It looks like the issue is stemming from this file on line 88.
I don't know a ton about Regexp and would probably have a difficult time trying to solve this.
Thanks!
.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/device_detector-1.0.6/lib/device_detector/parser.rb:88: warning: regular expression has ']' without escape
/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/device_detector-1.0.6/lib/device_detector/parser.rb:88: warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression
/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/device_detector-1.0.6/lib/device_detector/parser.rb:88: warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression
/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/device_detector-1.0.6/lib/device_detector/parser.rb:88: warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression
/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/device_detector-1.0.6/lib/device_detector/parser.rb:88: warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression
/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/device_detector-1.0.6/lib/device_detector/parser.rb:88: warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression
/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/device_detector-1.0.6/lib/device_detector/parser.rb:88: warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression
/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/device_detector-1.0.6/lib/device_detector/parser.rb:88: warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression
/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/device_detector-1.0.6/lib/device_detector/parser.rb:88: warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression
How to detect iOS devices (iPhone, Tablets) and Andorid devices ?
Thank you
user_agent = 'Mozilla/5.0 (Android:9; Mobile; rv:67) Gecko/67.0 Firefox/67.0'
=> "Mozilla/5.0 (Android:9; Mobile; rv:67) Gecko/67.0 Firefox/67.0"
client = DeviceDetector.new(user_agent)
=> #<DeviceDetector:0x007fd28ab04d20 @user_agent="Mozilla/5.0 (Android:9; Mobile; rv:67) Gecko/67.0 Firefox/67.0">
[14] pry(main)> client.os_name
=> "Android"
pry(main)> client.name
=> "Firefox Mobile"
[15] pry(main)> client.device_type
=> nil
pry(main)> client.device_name
=> nil
Hello, i created issue in original library here
It looks, that device_detector on this user agent string returns nil
Mozilla/4.0 (compatible; MSIE 6.0; Symbian OS; Series 60/03.83; 9730) Opera 8.65 [ru]
Are you really sure, that regexpes in device_detector gem is really new?
/gems/device_detector-1.1.0/lib/device_detector/device.rb:1560 in block in regex_find
/gems/device_detector-1.1.0/lib/device_detector/device.rb:1560 in each
/gems/device_detector-1.1.0/lib/device_detector/device.rb:1560 in find
/gems/device_detector-1.1.0/lib/device_detector/device.rb:1560 in regex_find
/gems/device_detector-1.1.0/lib/device_detector/device.rb:1535 in block in matching_regex
/gems/device_detector-1.1.0/lib/device_detector/parser.rb:92 in block in from_cache
/gems/device_detector-1.1.0/lib/device_detector/memory_cache.rb:38 in get_or_set
/gems/device_detector-1.1.0/lib/device_detector/parser.rb:92 in from_cache
/gems/device_detector-1.1.0/lib/device_detector/device.rb:1531 in matching_regex
/gems/device_detector-1.1.0/lib/device_detector/parser.rb:31 in regex_meta
/gems/device_detector-1.1.0/lib/device_detector/device.rb:1505 in type
/gems/device_detector-1.1.0/lib/device_detector.rb:67 in device_type
/gems/ahoy_matey-4.1.0/lib/ahoy/base_store.rb:59 in bot?
/gems/ahoy_matey-4.1.0/lib/ahoy/base_store.rb:39 in exclude?
/gems/ahoy_matey-4.1.0/lib/ahoy/tracker.rb:189 in exclude?
/gems/ahoy_matey-4.1.0/lib/ahoy/tracker.rb:20 in track
app/controllers/application_controller.rb:14 in track_action
12:
properties[:method] = request.method
13:
14:
ahoy.track request.fullpath, properties
15:
end
16:
end
When using an app on an iOS, the browser is set correctly, however once the OS in the user agent changes to iPadOS, then the browser is set to be recognised as a mobile safari even though the app is still being used.
e.g.
<app_name>/3.7.1 (iPad; iPadOS 15.6.1; Scale/2.00)/ DeviceId/48C8426D-64B6-4961-BD3E-09FD99C3B046/ BuildNumber/1111
returns browser as "Mobile Safari" but
<app_name>/3.7.1 (iPad; iOS 15.6.1; Scale/2.00)/ DeviceId/48C8426D-64B6-4961-BD3E-09FD99C3B046/ BuildNumber/1111
returns browser as "<app_name>"
Similar thing happens with android where the browser on an android device returns "Android Browser" even though the app name is specified
At the moment I have a hack in place that checks for the app name at the beginning of the user agent string but that is just a hack and I would prefer not to make use of it for long. I'll tinker with this library if I have some time, just thought I would report this issue 🥺
Hi there - this user agent is recognised as a bot:
"Mozilla/5.0 (Linux; Android 9) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Mobile Safari/537.36 DuckDuckGo/5"
But I suspect it is this app: https://github.com/duckduckgo/Android
I don't have Android to test it unfortunately.
As it is stated in this post Google Image Proxy is not a bot. This acts more like proxy. For us this means, that the click/open is real (performed by real person), but we're not able to detect the real device, because user agent has been overwritten by Google Image Proxy.
Link to the regexp: https://github.com/podigee/device_detector/blob/develop/regexes/bots.yml#L588
When using DeviceDetector with Firefox on Android, the Mobile vs Tablet flag isn't registering to show the device type.
Hi @spiderpug,
Thanks for maintaining this so far!
However, there are a bunch of things that could be fixed according to the Ruby style guide.
Would you consider using RuboCop?
I would be happy to raise a PR if so :)
Prematurely submitted, still writing the comment
Hi,
I noticed that Smartphone Googlebot is not listed in bots.yml
. I think it's an important one to have, given the latest news about Google's Algorithm update, and I would like to add it to the list.
Please see here matomo-org/device-detector#5701 for more information.
Is this library still being maintained? The last PR to update regexes was in 2020 and it was still not merged.
Any active forks?
Hi there!
Since release 1.0.6 I get this warning :
/cache/nicolas/concerto/ruby-master/ruby/3.0.0/gems/device_detector-1.0.6/lib/device_detector/parser.rb:88: warning: regular expression has ']' without escape
/cache/nicolas/concerto/ruby-master/ruby/3.0.0/gems/device_detector-1.0.6/lib/device_detector/parser.rb:88: warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression
Thank you!
Roku UserAgent:
Mozilla/5.0 (QSP; Roku; UI; 5.3.0.49)
Hi guys,
I use the gem in my rails app server to check where the user are making the request from.
I just accept "os_name" Android and iOS. But the gem identify iphones as "Mac" instead of iOS.
I build my project using Ionic/Cordova. I think maybe the cordova framework is using WebView, what causes the error, but not completely sure.
Hope this report help someone in the future.
Obvious from looking at oss.yml why this is so, but I have what I believe to be a legitimate user agent string from an old version of Ubuntu that is failing the following test:
def test_ubuntu_10_device_detector
agent_string = 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Ubuntu/10.10 Chromium/10.0.648.133 Chrome/10.0.648.133 Safari/534.16'
uap = UserAgentParser::Parser.new.parse(agent_string)
assert_equal 'Ubuntu 10.10', uap.os.to_s # UAP seemingly has rules to match this
dd = DeviceDetector.new(agent_string)
assert_equal 'Ubuntu', dd.os_name
end
Test output:
1) Failure:
ImprovedUserAgentTest#test_ubuntu_10_device_detector [test/models/user_agent_test.rb:15]:
Expected: "Ubuntu"
Actual: "$1"
When updating to latest upstream regexes tests are failing for a string with special charater, eg:
6) Error:
DeviceDetector::smartphone-7.yml::Mozilla/5.0 (Linux; U; Android 2.3.6; pt-br; XT321 Build/GRK39F) AppleWebKit/533.1 (KHTML, like Gecko) Versão/4.0 Mobile Safari/533.1#test_0001_should be detected:
RegexpError: invalid pattern in look-behind: /(?:^|[^A-Z0-9\-_]|[^A-Z0-9\-]_|sprd-)(?:acer|(?<!ZTE BLADE |ImSmart |ERGO |X-Style Tab )a(?:101|110|2[10]0|211|50[10]|51[10]|70[10])[);\/ ]|Android.*V3[67]0[);\/ ]|Android.*Z1[23456]0 Build|Android.*Z5\d{2} Build|Android.*T0[234678] Build|Android.*S55[);\/ ]|A1-830|A1-81[01]|A1-7[23]4|A3-A[1234][01]|B1-7[1235678][01]|B1-7[23]3|B1-8[1235]0|B1-A71|B3-A[12]0|B3-A3[02]|E39[);\/ ]|S5[12]0 Build|DA[0-9]+HQ?L[);\/ ]|Aspire V5-121|Predator G9-793|GT-810)/i
Source regexp that is causing the issue:
https://github.com/matomo-org/device-detector/blob/118651c4fbff739e7f29acebd1732e7ccbf238a7/regexes/device/mobiles.yml#L735
This seems to be related to a bug in Ruby Regexp
https://bugs.ruby-lang.org/issues/13671
Until the problem is fixed a workaround needs to be implemented. One quick option would be to fail silently when this happens, but that's obviously not a good solution. Any ideas?
So when running in development, (have not tried it in prod as of yet), When I capture the client data in my password reset controller, info is returning as incorrect? this is how I have implemented the call (it will be refactored later).
def create
user_agent = 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.17 Safari/537.36'
client = DeviceDetector.new(user_agent)
@user = User.find_by(email: params[:password_reset][:email].downcase)
if @user
@user.create_reset_digest
PasswordResetDetail.create(
user_id: @user.id,
client_name: client.name,
client_full_version: client.full_version,
client_os_name: client.os_name,
client_os_full_version: client.os_full_version,
client_device_name: client.device_name,
client_device_type: client.device_type,
client_is_known: client.known?
)
UserMailer.password_reset(@user).deliver_now
flash[:info] = 'Email sent with password reset instructions'
redirect_to community_root_url(subdomain: 'community')
else
flash.now[:error] = 'Email address not found'
render 'new'
end
end
This is the server output (no errors and aside from the wrong info it works very well!)
Started POST "/password_resets" for 127.0.0.1 at 2020-09-08 16:58:22 -0600
Processing by PasswordResetsController#create as HTML
Parameters: {"authenticity_token"=>"JAJSpUbqzRKIS/nJ3QO+TFhh8stBF0BzRHdiaDHHpKizKLoAVEY8BhfIRfFlj4o4l6GDbJn4fFVmjOc+/bXWTw==", "password_reset"=>"[FILTERED]"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."email" = $1 LIMIT $2 [["email", "[email protected]"], ["LIMIT", 1]]
↳ app/controllers/password_resets_controller.rb:11:in `create'
(0.2ms) BEGIN
↳ app/models/user.rb:53:in `create_reset_digest'
User Update (0.4ms) UPDATE "users" SET "reset_digest" = $1, "updated_at" = $2 WHERE "users"."id" = $3 [["reset_digest", "$2a$12$z9FXWm6sgdYkwCUfhq5ntunOg5yEBFuCdQ8Cd1mUZ44xD5yHI1R9C"], ["updated_at", "2020-09-08 22:58:22.658982"], ["id", 1]]
↳ app/models/user.rb:53:in `create_reset_digest'
(0.8ms) COMMIT
↳ app/models/user.rb:53:in `create_reset_digest'
(0.1ms) BEGIN
↳ app/models/user.rb:54:in `create_reset_digest'
User Update (0.5ms) UPDATE "users" SET "updated_at" = $1, "reset_sent_at" = $2 WHERE "users"."id" = $3 [["updated_at", "2020-09-08 22:58:22.663686"], ["reset_sent_at", "2020-09-08 22:58:22.663494"], ["id", 1]]
↳ app/models/user.rb:54:in `create_reset_digest'
(0.4ms) COMMIT
↳ app/models/user.rb:54:in `create_reset_digest'
(0.2ms) BEGIN
↳ app/controllers/password_resets_controller.rb:14:in `create'
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/controllers/password_resets_controller.rb:14:in `create'
PasswordResetDetail Create (0.4ms) INSERT INTO "password_reset_details" ("user_id", "client_name", "client_full_version", "client_os_name", "client_os_full_version", "client_device_type", "client_is_known", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING "id" [["user_id", 1], ["client_name", "Chrome"], ["client_full_version", "30.0.1599.17"], ["client_os_name", "Windows"], ["client_os_full_version", "8"], ["client_device_type", "desktop"], ["client_is_known", true], ["created_at", "2020-09-08 22:58:22.671077"], ["updated_at", "2020-09-08 22:58:22.671077"]]
↳ app/controllers/password_resets_controller.rb:14:in `create'
(0.4ms) COMMIT
↳ app/controllers/password_resets_controller.rb:14:in `create'
PasswordResetDetail Load (0.5ms) SELECT "password_reset_details".* FROM "password_reset_details" WHERE "password_reset_details"."user_id" = $1 ORDER BY "password_reset_details"."id" DESC LIMIT $2 [["user_id", 1], ["LIMIT", 1]]
↳ app/mailers/user_mailer.rb:31:in `password_reset'
CACHE PasswordResetDetail Load (0.1ms) SELECT "password_reset_details".* FROM "password_reset_details" WHERE "password_reset_details"."user_id" = $1 ORDER BY "password_reset_details"."id" DESC LIMIT $2 [["user_id", 1], ["LIMIT", 1]]
↳ app/mailers/user_mailer.rb:32:in `password_reset'
UserMailer#password_reset: processed outbound mail in 4.8ms
Breadcrumb ActionMail delivered meta_data from:Mail::AddressContainer has been dropped for having an invalid data type
Breadcrumb ActionMail delivered meta_data date:DateTime has been dropped for having an invalid data type
Delivered mail [email protected] (381.5ms)
Date: Tue, 08 Sep 2020 16:58:22 -0600
From: [email protected]
Reply-To: [email protected]
To: [email protected]
Message-ID: <[email protected]>
Subject: Postmark Template: "user-password-reset"
Mime-Version: 1.0
Content-Type: text/plain;
charset=UTF-8
Content-Transfer-Encoding: 7bit
postmark-template-alias: user-password-reset
This message is using a Postmark template.
Alias: "user-password-reset"
Model:
{
"name": "xxxx",
"action_url": "http://community.lvh.me:3000/password_resets/0sScCHal3P7Zu_1xHfJWdA/edit?email=xxx%xxx-xxx-xxx.com",
"device_name": "Desktop",
"operating_system": "Windows",
"support_url": "[email protected]"
}
Use the #prerender method on this object to contact the Postmark API to pre-render the template.
Cheers,
Your friends at Postmark
Redirected to http://community.lvh.me:3000/
Completed 302 Found in 684ms (ActiveRecord: 4.8ms | Allocations: 15911)
]
I am currently running a macbook pro, with macOS Catalina (v10.15.6)
Is my implementation buggered up or am I doing something wrong?
This user agent OS and device name is not recognised
SAMSUNG-GT-E2152/E2152XXJK2 NetFront/3.5 Profile/MIDP-2.0 Configuration/CLDC-1.1
Hello, I have just run the tasks for updating regexes and fixtures in order to fix some user agents not recognising the device type. This is now fixed, the device type is recognised as expected, however, the rests are failing.
I would like to get my hands on them and fix them, but I was wondering if that's the right way or you usually follow other approach.
Thanks.
I've ran benchmark from the Readme on my set of real user agents (160k) and it seems that the browser
gem is much faster. I didn't compare precision of both though.
Could you compare them with your dataset again?
user system total real
device_detector 4.713362 0.000000 4.713362 ( 4.714573)
browser 1.780024 0.000000 1.780024 ( 1.780048)
DeviceDetector.new(Faker::Internet.user_agent).device_brand
device_detector/lib/device_detector/parser.rb:101:in `block in parse_regexes': no implicit conversion of Symbol into Integer (TypeError)
File structure is different
I was trying out your gem with the user agent from Readme which is:
Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.17 Safari/537.36
.
However when I tried to get device_name
, it returned nil
along with these warnings:
/Users/victor/.rvm/gems/ruby-2.2.1/gems/device_detector-0.9.0/lib/device_detector/parser.rb:74: warning: character class has '-' without escape
/Users/victor/.rvm/gems/ruby-2.2.1/gems/device_detector-0.9.0/lib/device_detector/parser.rb:74: warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression
/Users/victor/.rvm/gems/ruby-2.2.1/gems/device_detector-0.9.0/lib/device_detector/parser.rb:74: warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression
/Users/victor/.rvm/gems/ruby-2.2.1/gems/device_detector-0.9.0/lib/device_detector/device.rb:53: warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression
=> nil
Is this a bug for ruby 2.2.1?
irb(main):040:0> s = 'AppleCoreMedia/1.0.0.10B500 (iPod; U; CPU OS 6_1_6 like Mac OS X; en_gb)'
=> "AppleCoreMedia/1.0.0.10B500 (iPod; U; CPU OS 6_1_6 like Mac OS X; en_gb)"
irb(main):041:0> DeviceDetector.new(s).name
=> "Mobile Safari"
curious why android_tablet_fragment?
and android_mobile_fragment?
require semicolons and other operating systems (Opera) do not? We don't use semicolons in our user agent at Kickstarter, and as far as I can tell there is no standardization here (please correct me if I'm wrong). Another example user agent from Facebook has a semicolon after Android
but not after Mobile
:
Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.121 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/35.0.0.48.273;]
going to open a pr making the semicolon optional.
Encountered a small bug while playing around with user agent client hints. (should be a one-line change)
The full_version
method in DeviceDetector is calling client_hint.platform_version
, which is the property used to get the os version.
It should be client_hint.full_version
instead. This is the browser version. (the one that read from the Sec-CH-UA-Full-Version header)
Let me know if you need more information!
While using the DeviceDetector gem I've noticed, that the same cache is being used to store the final detection results as well as to tackle the internal caching.
This approach causes a YAML reload of regexps when enough browsers are being recognized.
Here's an example of how to reproduce that:
require 'device_detector'
DeviceDetector.configure do |config|
config.max_cache_keys = 10
end
module Bench
def self.call
t = Time.now.to_f
r = yield
p (Time.now.to_f-t)*1000
r
end
end
20.times do
Bench.call { DeviceDetector.new(Time.now.to_f.to_s).full_version }
end
the result is:
16.92676544189453
0.14138221740722656
0.1392364501953125
0.1327991485595703
0.13113021850585938
28.29146385192871
0.7753372192382812
0.11897087097167969
0.11181831359863281
45.581817626953125
1.2042522430419922
1.0809898376464844
1.1005401611328125
17.076730728149414
0.12612342834472656
0.11444091796875
0.10657310485839844
27.06766128540039
0.13065338134765625
0.1087188720703125
So we see spikes in the time needed due to reloading of yaml definitions.
After applying the following patch:
module Patches
module DeviceDetectorParser
CACHE = ::DeviceDetector::MemoryCache.new({})
private_constant :CACHE
def regexes_for(file_paths)
CACHE.get_or_set(filepaths) do
super
end
end
end
end
DeviceDetector::Parser.prepend(Patches::DeviceDetectorParser)
the results are always consistent as only the "public" results are being purged while keeping the regexp definitions intact in the cache.
require 'device_detector'
DeviceDetector.configure do |config|
config.max_cache_keys = 10
end
module Patches
module DeviceDetectorParser
CACHE = ::DeviceDetector::MemoryCache.new({})
private_constant :CACHE
def regexes_for(file_paths)
CACHE.get_or_set(filepaths) do
super
end
end
end
end
DeviceDetector::Parser.prepend(Patches::DeviceDetectorParser)
module Bench
def self.call
t = Time.now.to_f
r = yield
p (Time.now.to_f-t)*1000
r
end
end
20.times do
Bench.call { DeviceDetector.new(Time.now.to_f.to_s).full_version }
end
Result:
19.721269607543945
1.1222362518310547
0.8854866027832031
0.1773834228515625
0.1361370086669922
0.1354217529296875
0.1327991485595703
0.13184547424316406
0.1277923583984375
0.13184547424316406
0.12993812561035156
0.1289844512939453
0.13017654418945312
0.13184547424316406
0.12826919555664062
0.13208389282226562
0.13065338134765625
0.12731552124023438
0.12969970703125
0.13637542724609375
if that approach is ok, I can make a PR.
Hi!
We're running DeviceDetector in Sidekiq and under high load we sometimes are able to get NoMethodError: undefined method '[]' for nil:NilClass
from:
"/webapps/api/vendor/bundle/ruby/2.6.0/gems/device_detector-1.0.1/lib/device_detector/os.rb" line 11 in short_name
"/webapps/api/vendor/bundle/ruby/2.6.0/gems/device_detector-1.0.1/lib/device_detector.rb" line 66 in device_type
That's basically a MemoryCache#get_or_set
call which returns nil.
Here's the code for reference:
device_detector/lib/device_detector/memory_cache.rb
Lines 30 to 39 in f30a385
My belief what happens is:
cache.set('k2', 1)
and purges the cache. K1 was an old key and got purgedget(K1)
and returns, but there is no such key now so it returns nil
Here's a script that can replicate it:
require 'device_detector'
cache = DeviceDetector::MemoryCache.new(max_cache_keys: 3)
# fill the cache 100% capacity
cache.set(1, 1)
cache.set(2, 2)
cache.set(3, 3)
# now on, the oldest keys should be purged on each write
sampler = (1..4).to_a
threads = 20.times.map do |thread_id|
Thread.new do
1_000_000.times do |i|
val = sampler.sample
ret = cache.get_or_set(val, val)
puts "[Thread #{thread_id}] BOOM" if ret.nil?
end
end
end
threads.each(&:join)
A simple solution would be to remove the check key?(string_key)
and just get
the value and return it if it's non-nil.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.