File Coverage

blib/lib/Duadua.pm
Criterion Covered Total %
statement 63 64 98.4
branch 45 46 97.8
condition 6 8 75.0
subroutine 24 24 100.0
pod 14 14 100.0
total 152 156 97.4


line stmt bran cond sub pod time code
1             package Duadua;
2 11     11   446432 use strict;
  11         22  
  11         388  
3 11     11   50 use warnings;
  11         16  
  11         506  
4 11     11   4182 use Duadua::Parser;
  11         30  
  11         14839  
5              
6             our $VERSION = '0.36';
7              
8             my @PARSER_PROC_LIST = qw/
9             Duadua::Parser::Browser::MicrosoftEdge
10             Duadua::Parser::Browser::GoogleChrome
11             Duadua::Parser::Browser::MicrosoftInternetExplorer
12              
13             Duadua::Parser::Bot::Googlebot
14             Duadua::Parser::Bot::GooglebotMobile
15             Duadua::Parser::Bot::Bingbot
16              
17             Duadua::Parser::Browser::MozillaFirefox
18              
19             Duadua::Parser::Bot::Twitterbot
20             Duadua::Parser::Bot::FacebookCrawler
21             Duadua::Parser::Bot::Slackbot
22             Duadua::Parser::Bot::BingPreview
23              
24             Duadua::Parser::Browser::Opera
25              
26             Duadua::Parser::Bot::GooglebotAd
27             Duadua::Parser::Bot::GoogleRead
28             Duadua::Parser::Bot::AdIdxBot
29             Duadua::Parser::Browser::YahooJapanAppBrowser
30             Duadua::Parser::Bot::ChatGPTUser
31             Duadua::Parser::Bot::Perplexity
32              
33             Duadua::Parser::Browser::AppleSafari
34             Duadua::Parser::Browser::Vivaldi
35              
36             Duadua::Parser::Bot::Huawei
37             Duadua::Parser::Bot::Sakura
38             Duadua::Parser::HTTPClient::HTTPClient
39              
40             Duadua::Parser::Bot::YahooSlurp
41             Duadua::Parser::Bot::Baiduspider
42             Duadua::Parser::Bot::Bytespider
43             Duadua::Parser::Bot::TikTokSpider
44             Duadua::Parser::Bot::YandexBot
45             Duadua::Parser::Bot::GooglebotMisc
46             Duadua::Parser::Bot::DuckDuckBot
47             Duadua::Parser::Bot::Applebot
48             Duadua::Parser::Bot::Msnbot
49             Duadua::Parser::Bot::BotMisc
50             Duadua::Parser::Bot::Log4Shell
51              
52             Duadua::Parser::Browser::GoogleApp
53             Duadua::Parser::Browser::SamsungInternetBrowser
54             Duadua::Parser::Browser::Yandex
55             Duadua::Parser::Browser::DuckDuckGo
56             Duadua::Parser::Bot::OracleGrapeshotCrawler
57             Duadua::Parser::Bot::MailRUBot
58             Duadua::Parser::Browser::PaleMoon
59             Duadua::Parser::Browser::UCBrowser
60             Duadua::Parser::Browser::BrowserMisc
61              
62             Duadua::Parser::Bot::YahooJapanBot
63             Duadua::Parser::Bot::HatenaBot
64             Duadua::Parser::Bot::Feedly
65             Duadua::Parser::Bot::Reeder
66             Duadua::Parser::Bot::QuiteRSS
67             Duadua::Parser::Bot::Feedbin
68             Duadua::Parser::Bot::Inoreader
69             Duadua::Parser::Bot::Fastladder
70             Duadua::Parser::Bot::Feedeen
71             Duadua::Parser::Bot::Feedspot
72             Duadua::Parser::Bot::OldReader
73             Duadua::Parser::Bot::Flipboard
74             Duadua::Parser::Bot::Skype
75              
76             Duadua::Parser::Browser::Xiaomi
77             Duadua::Parser::Bot::OWLer
78             Duadua::Parser::FeaturePhone::FeaturePhone
79             Duadua::Parser::Bot::Netcraft
80             Duadua::Parser::Bot::Barkrowler
81             Duadua::Parser::Bot::SMTBot
82             Duadua::Parser::Bot::AdstxtCom
83             Duadua::Parser::Bot::CentroAdsCrawler
84             Duadua::Parser::Bot::LetsEncrypt
85             Duadua::Parser::Bot::ClaudeBot
86             /;
87              
88             for my $parser (@PARSER_PROC_LIST) {
89             eval "require $parser;"; ## no critic
90             die "Could not load $parser, $@" if $@;
91             }
92              
93             sub new {
94 456   100 456 1 3448329 my $opt = $_[2] || {};
95              
96 456         1266 my $ua = $_[1];
97 456 100       2189 if (!defined $ua) {
    100          
98 3 100 66     19 $ua = exists $ENV{HTTP_USER_AGENT} && defined $ENV{HTTP_USER_AGENT} ? $ENV{HTTP_USER_AGENT} : '';
99             } elsif (ref($ua) =~ m!^HTTP::Headers!) {
100 2         6 $ua = $ua->header('User-Agent');
101             }
102              
103             bless {
104             _ua => $ua,
105             _parsed => 0,
106             _result => {},
107             _parsers => $_[0]->_build_parsers($opt),
108             _opt_version => $opt->{version},
109 456         1906 }, $_[0];
110             }
111              
112             sub _build_parsers {
113 456     456   1128 my ($class, $opt) = @_;
114              
115 456 100       1347 if (exists $opt->{skip}) {
116 1         3 my @parsers;
117 1         3 for my $p (@PARSER_PROC_LIST) {
118 66 100       98 next if grep { $p eq $_ } @{$opt->{skip}};
  132         306  
  66         132  
119 64         129 push @parsers, $p;
120             }
121 1         12 return \@parsers;
122             }
123              
124 455         3983 return \@PARSER_PROC_LIST;
125             }
126              
127 354     354 1 1345 sub opt_version { shift->{_opt_version} }
128              
129 444     444 1 1426 sub parsers { shift->{_parsers} }
130              
131 2493     2493 1 12343 sub ua { shift->{_ua} }
132              
133             sub reparse {
134 6     6 1 19 my $self = shift;
135              
136 6         14 my $ua = $_[0];
137 6 100       59 if (!defined $ua) {
    50          
138 2 100 66     17 $ua = exists $ENV{HTTP_USER_AGENT} && defined $ENV{HTTP_USER_AGENT} ? $ENV{HTTP_USER_AGENT} : '';
139             } elsif (ref($ua) =~ m!^HTTP::Headers!) {
140 0         0 $ua = $ua->header('User-Agent');
141             }
142              
143 6         29 $self->{_ua} = $ua;
144 6         21 $self->{_result} = {};
145              
146 6         47 return $self->_parse;
147             }
148              
149             sub _result {
150 2472 100   2472   8487 if (@_ == 1) {
151 2028 100       8567 $_[0]->parse unless $_[0]->{_parsed};
152 2028         15450 return $_[0]->{_result};
153             }
154              
155 444         1200 $_[0]->{_result} = $_[1];
156 444         1008 return $_[0];
157             }
158              
159             sub parse {
160 438     438 1 3213 my $self = shift;
161              
162 438 100       1239 if (ref $self eq __PACKAGE__) {
    100          
163 434         1312 $self->_parse;
164             }
165             elsif ($self eq __PACKAGE__) {
166             # my $d_obj = Duadua->parse('User-Agent String', $opt);
167 2         8 my $d = __PACKAGE__->new(@_);
168 2         7 return $d->_parse;
169             }
170             else {
171             # my $d_obj = Duadua::parse('User-Agent String', $opt);
172 2         9 my $d = __PACKAGE__->new($self, @_);
173 2         6 return $d->_parse;
174             }
175             }
176              
177             sub _parse {
178 444     444   750 my $self = shift;
179              
180 444         2676 $self->_result(Duadua::Parser->parse($self));
181 444         885 $self->{_parsed} = 1;
182              
183 444         868 return $self;
184             }
185              
186             sub name {
187 264     264 1 908 shift->_result->{name};
188             }
189              
190             sub is_bot {
191 262 100   262 1 236587 shift->_result->{is_bot} ? 1 : 0;
192             }
193              
194             sub is_ios {
195 262 100   262 1 233272 shift->_result->{is_ios} ? 1 : 0;
196             }
197              
198             sub is_android {
199 262 100   262 1 232093 shift->_result->{is_android} ? 1 : 0;
200             }
201              
202             sub is_linux {
203 262 100   262 1 247392 shift->_result->{is_linux} ? 1 : 0;
204             }
205              
206             sub is_windows {
207 264 100   264 1 251993 shift->_result->{is_windows} ? 1 : 0;
208             }
209              
210             sub is_chromeos {
211 259 100   259 1 254382 shift->_result->{is_chromeos} ? 1 : 0;
212             }
213              
214             sub version {
215 193 100   193 1 1315 shift->_result->{version} || '';
216             }
217              
218             sub _contain_mozilla {
219             return 1 if shift->{_contain_mozilla}
220 273 100   273   1732 }
221              
222             sub _contain_mozilla_top {
223             return 1 if shift->{_contain_mozilla_top}
224 878 100   878   3888 }
225              
226             sub _prefix {
227 1594 100   1594   9119 return 1 if index(shift->{_ua}, shift) == 0;
228             }
229              
230             sub _contain {
231 30788 100   30788   140503 return 1 if index(shift->{_ua}, shift) != -1;
232             }
233              
234             1;
235              
236             __END__