File Coverage

blib/lib/WebService/Careerjet.pm
Criterion Covered Total %
statement 24 55 43.6
branch 0 10 0.0
condition 0 16 0.0
subroutine 8 11 72.7
pod 3 3 100.0
total 35 95 36.8


line stmt bran cond sub pod time code
1             package WebService::Careerjet;
2              
3 1     1   97154 use strict;
  1         3  
  1         43  
4 1     1   7 use warnings;
  1         2  
  1         78  
5              
6 1     1   10 use base qw/Class::AutoAccess/;
  1         2  
  1         904  
7              
8 1     1   1434 use URI::Escape;
  1         2337  
  1         103  
9 1     1   1153 use LWP::UserAgent;
  1         78332  
  1         51  
10 1     1   11 use HTTP::Request;
  1         3  
  1         36  
11 1     1   7 use Carp;
  1         2  
  1         85  
12 1     1   1152 use JSON;
  1         14308  
  1         9  
13              
14             =head1 NAME
15              
16             WebService::Careerjet - Perl interface to Careerjet's public job search API
17              
18             =head1 VERSION
19              
20             Version 4.3
21              
22             =cut
23              
24             our $VERSION = '4.3';
25              
26             =head1 SYNOPSIS
27              
28             This module provides a Perl interface to the public search API of Careerjet,
29             a vertical search engine for job offers that features job offers in over 60 countries.
30             (https://www.careerjet.com/sites)
31              
32             An API key will be required which you can get when by opening a partner account
33             with Careerjet ((https://www.careerjet.com/partners/).
34              
35             Code example:
36              
37             use WebService::Careerjet;
38              
39             # Create Perl interface to API
40             my $careerjet = WebService::Careerjet->new('en_GB', "");
41              
42             # Perform a search
43             my $result = $careerjet->query({
44             'keywords' => 'perl developer',
45             'location' => 'london',
46             'user_ip' => '11.22.33.44',
47             'user_agent' => 'Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0',
48             'referrer' => 'https://www.example.com/jobs/search?s=perl+developer&l=london',
49             });
50              
51             # Go through results
52             if ($result->{'type'} eq 'JOBS') {
53             print "Found ". $result->{'hits'}. " jobs\n";
54             my $jobs = $result->{'jobs'};
55              
56             foreach my $j(@$jobs) {
57             print "URL :".$j->{'url'}."\n";
58             print "TITLE :".$j->{'title'}."\n";
59             print "COMPANY :".$j->{'company'}."\n";
60             print "SALARY :".$j->{'salary'}."\n";
61             print "DATE :".$j->{'date'}."\n";
62             print "DESCRIPTION :".$j->{'description'}."\n";
63             print "LOCATIONS :".$j->{'locations'}."\n";
64             print "\n";
65             }
66             }
67              
68             =cut
69              
70             =head1 FUNCTIONS
71              
72             =head2 new
73              
74             Creates a Webservice::Careerjet API client object for a given UNIX locale
75             and API key.
76              
77             The API key is mandatory and is provided by Careerjet when you open a partner
78             account (https://www.careerjet.com/partners/).
79              
80             Each locale corresponds to an existing Careerjet site and determines
81             which language job-related information is returned as well
82             as which default location filter is used. For example, if your users
83             are primarily Dutch-speaking Belgians use "nl_BE".
84              
85             First two letters : ISO 639-1 alpha-2 language code
86              
87             See https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
88              
89             Last two letters : ISO 3166-1 alpha-2 country code
90              
91             See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
92              
93              
94             Usage:
95             my $careerjet = WebService::Careerjet->new($locale, $api_key);
96              
97             Available locales:
98              
99             LOCALE LANGUAGE DEFAULT LOCATION CAREERJET SITE
100             cs_CZ Czech Czech Republic https://www.careerjet.cz
101             da_DK Danish Denmark https://www.careerjet.dk
102             de_AT German Austria https://www.careerjet.at
103             de_CH German Switzerland https://www.careerjet.ch
104             de_DE German Germany https://www.careerjet.de
105             en_AE English United Arab Emirates https://www.careerjet.ae
106             en_AU English Australia https://www.careerjet.com.au
107             en_BD English Bangladesh https://www.careerjet.com.bd
108             en_CA English Canada https://www.careerjet.ca
109             en_CN English China https://www.career-jet.cn
110             en_HK English Hong Kong https://www.careerjet.hk
111             en_IE English Ireland https://www.careerjet.ie
112             en_IN English India https://www.careerjet.co.in
113             en_KW English Kuwait https://www.careerjet.com.kw
114             en_MY English Malaysia https://www.careerjet.com.my
115             en_NZ English New Zealand https://www.careerjet.co.nz
116             en_OM English Oman https://www.careerjet.com.om
117             en_PH English Philippines https://www.careerjet.ph
118             en_PK English Pakistan https://www.careerjet.com.pk
119             en_QA English Qatar https://www.careerjet.com.qa
120             en_SG English Singapore https://www.careerjet.sg
121             en_TH English Thai https://www.career-jet.co.th
122             en_GB English United Kingdom https://www.careerjet.co.uk
123             en_US English United States https://www.careerjet.com
124             en_ZA English South Africa https://www.careerjet.co.za
125             en_SA English Saudi Arabia https://www.careerjet.com.sa
126             en_TW English Taiwan https://www.careerjet.com.tw
127             en_VN English Vietnam https://www.careerjet.vn
128             es_AR Spanish Argentina https://www.opcionempleo.com.ar
129             es_BO Spanish Bolivia https://www.opcionempleo.com.bo
130             es_CL Spanish Chile https://www.opcionempleo.cl
131             es_CO Spanish Colombia https://www.opcionempleo.com.co
132             es_CR Spanish Costa Rica https://www.opcionempleo.co.cr
133             es_DO Spanish Dominican Republic https://www.opcionempleo.com.do
134             es_EC Spanish Ecuador https://www.opcionempleo.ec
135             es_ES Spanish Spain https://www.opcionempleo.com
136             es_GT Spanish Guatemala https://www.opcionempleo.com.gt
137             es_MX Spanish Mexico https://www.opcionempleo.com.mx
138             es_PA Spanish Panama https://www.opcionempleo.com.pa
139             es_PE Spanish Peru https://www.opcionempleo.com.pe
140             es_PR Spanish Puerto Rico https://www.opcionempleo.com.pr
141             es_PY Spanish Paraguay https://www.opcionempleo.com.py
142             es_UY Spanish Uruguay https://www.opcionempleo.com.uy
143             es_VE Spanish Venezuela https://www.opcionempleo.com.ve
144             fi_FI Finnish Finland https://www.careerjet.fi
145             fr_CA French Canada https://www.option-carriere.ca
146             fr_BE French Belgium https://www.optioncarriere.be
147             fr_CH French Switzerland https://www.optioncarriere.ch
148             fr_FR French France https://www.optioncarriere.com
149             fr_LU French Luxembourg https://www.optioncarriere.lu
150             fr_MA French Morocco https://www.optioncarriere.ma
151             hu_HU Hungarian Hungary https://www.careerjet.hu
152             it_IT Italian Italy https://www.careerjet.it
153             ja_JP Japanese Japan https://www.careerjet.jp
154             ko_KR Korean Korea https://www.careerjet.co.kr
155             nl_BE Dutch Belgium https://www.careerjet.be
156             nl_NL Dutch Netherlands https://www.careerjet.nl
157             no_NO Norwegian Norway https://www.careerjet.no
158             pl_PL Polish Poland https://www.careerjet.pl
159             pt_PT Portuguese Portugal https://www.careerjet.pt
160             pt_BR Portuguese Brazil https://www.careerjet.com.br
161             ru_RU Russian Russia https://www.careerjet.ru
162             ru_UA Russian Ukraine https://www.careerjet.com.ua
163             sv_SE Swedish Sweden https://www.careerjet.se
164             sk_SK Slovak Slovakia https://www.careerjet.sk
165             th_TH Thailand Thai https://www.careerjet.co.th
166             tr_TR Turkish Turkey https://www.careerjet.com.tr
167             uk_UA Ukrainian Ukraine https://www.careerjet.ua
168             vi_VN Vietnamese Vietnam https://www.careerjet.com.vn
169             zh_CN Chinese China https://www.careerjet.cn
170              
171              
172             =head2 agent
173              
174             Gets/sets the LWP::UserAgent to be used in the API calls.
175              
176             This is useful for custom proxy, timeout or username settings.
177              
178             Usage:
179              
180             $this->agent();
181             $this->agent($myAgent);
182              
183             =cut
184              
185             sub new {
186 0     0 1   my ($class, $locale, $api_key) = @_;
187 0   0       $locale ||= 'en_GB';
188 0   0       $api_key ||= '';
189              
190 0           my $ua = LWP::UserAgent->new();
191 0           $ua->agent('careerjet-api-client-v' . $VERSION . '-perl-v' . $]);
192              
193 0 0         my $self = {
194             'locale' => $locale,
195             'agent' => $ua,
196             'api_key' => $api_key,
197             'is_legacy_mode' => ($api_key) ? 0 : 1,
198             };
199              
200 0           return bless $self, $class;
201             }
202              
203             =head2 query
204              
205             Performs a search query using Careerjet's public search API.
206             Search parameters are passed on as a reference to a hash.
207              
208             The end-users IP address and user agent are mandatory parameters.
209              
210             Example:
211            
212             my $result = $api->query({
213             'keywords' => 'perl developer',
214             'location' => 'london',
215             'user_ip' => '11.22.33.44',
216             'user_agent' => 'Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0',
217             'referrer' => 'https://www.example.com/jobs/search?s=perl+developer&l=london',
218             });
219              
220             # The result is a job list if the location is not ambiguous
221             if ($result->{'type'} eq 'JOBS') {
222             print "Found ". $result->{'hits'}. " jobs\n";
223             print "Total number of result pages: ". $result->{'pages'}. "\n";
224             my $jobs = $result->{'jobs'};
225             foreach my $j (@$jobs) {
226             print "URL :".$j->{'url'}."\n";
227             print "TITLE :".$j->{'title'}."\n";
228             print "COMPANY :".$j->{'company'}."\n";
229             print "SALARY :".$j->{'salary'}."\n";
230             print "DATE :".$j->{'date'}."\n";
231             print "DESCRIPTION :".$j->{'description'}."\n";
232             print "SITE :".$j->{'site'}."\n";
233             print "\n" ;
234             }
235            
236             }
237              
238             # If the location is ambiguous, a list of suggested locations
239             # is returned
240             if ($result->{'type'} eq 'LOCATIONS') {
241             print "Suggested locations:\n" ;
242             my $locations = $result->{'solveLocations'};
243             foreach my $l (@$locations) {
244             print $l->{'name'}."\n" ; ## For end-user display
245             ## Use $l->{'location_id'} when making next search call
246             ## as 'location_id' parameter (see parameters below)
247             }
248             }
249              
250             Mandatory parameters:
251              
252             user_ip : IP address of the end-user to whom the search results will be displayed.
253              
254             user_agent : User agent of the end-user's browser.
255              
256             referrer : Web page that the user is currently viewing and that triggered this job search.
257            
258             Options:
259              
260             All options have default values and are not mandatory
261            
262             keywords : Keywords to match either title, content or company name of job offer
263             Examples: 'perl developer', 'ibm', 'software architect'
264             Default : none
265            
266             location : Location of requested job postings.
267             Examples: 'London' , 'Yorkshire', 'France'
268             Default: country specified by country code
269              
270             sort : Type of sort. This can be:
271             'relevance' - sorted by decreasing relevancy (default)
272             'date' - sorted by decreasing date
273             'salary' - sorted by decreasing salary
274            
275             start_num : Position of returned job postings within the entire result space.
276             This should be a least 1 but not more than the total number of job offers.
277             Default : 1
278            
279             pagesize : Number of returned results
280             Default : 20
281              
282             page : Page number of returned job postings within the entire result space.
283             This can be used instead of start_num. The minimum page number is 1.
284             The maximum number of pages is given by $result->{'pages'}
285             If this value is set, it overrides start_num.
286            
287             contract_type : Selected contract type. The following codes can be used:
288             'p' - permanent
289             'c' - contract
290             't' - temporary
291             'i' - training
292             'v' - voluntary
293             Default: none (all contract types)
294            
295             work_hours : Selected work hours. The following codes can be used:
296             'f' - full time
297             'p' - part time
298             Default: none (all work hours)
299              
300            
301             =cut
302              
303             sub query {
304 0     0 1   my ($self, $args) = @_;
305              
306 0           my $url;
307 0 0         if ($self->is_legacy_mode) {
308 0           $url = "http://public.api.careerjet.net/search?locale_code=" . $self->{locale};
309             } else {
310 0           $url = "http://search.api.careerjet.net/v4/query?locale_code=" . $self->{locale};
311             }
312              
313 0 0 0       if ($self->is_legacy_mode && !$args->{affid}) {
314             return {
315 0           type => 'ERROR',
316             error => "You haven't supplied an API key, so legacy mode is assumed. " .
317             "In this case your legacy Careerjet affiliate ID needs to be supplied as 'affid' parameter."
318             };
319             }
320              
321 0           foreach my $k (keys %$args) {
322 0           $url .= '&' . $k . '=' . URI::Escape::uri_escape_utf8($args->{$k});
323             }
324              
325 0           my $req = HTTP::Request->new('GET' => $url);
326 0           $req->authorization_basic($self->api_key, '');
327 0 0 0       if ($args->{referrer} || $args->{referer}) {
328 0   0       $req->header('Referer' => $args->{referrer} || $args->{referer});
329             }
330              
331 0           my $res = $self->{'agent'}->request($req);
332 0           my $content = $res->content();
333              
334 0           my $ret;
335 0           eval {
336 0           $ret = decode_json($content);
337             };
338              
339 0 0 0       if (!$res->is_success() && !defined $ret) {
340 0           $ret->{'type'} = 'ERROR';
341 0           $ret->{'error'} = $res->status_line();
342             }
343              
344 0           return $ret;
345              
346             }
347              
348             =head2 search
349              
350             Alternative name for 'query' for backwards compatibility reasons
351              
352             =cut
353              
354             sub search {
355 0     0 1   my ($self, $args) = @_;
356 0           return $self->query($args);
357             }
358              
359             =head1 AUTHORS
360              
361             Thomas Busch (version 0.13 onwards)
362              
363             Jerome Eteve (version 0.01-0.12)
364              
365             =head1 FEEDBACK
366              
367             Any feedback is welcome. Please send your suggestions to
368              
369             =head1 COPYRIGHT & LICENSE
370              
371             Copyright 2007-2025 Careerjet Limited. All rights reserved.
372              
373             This program is free software; you can redistribute it and/or modify it
374             under the same terms as Perl itself.
375              
376             =head1 DISCLAIMER OF WARRANTY
377              
378             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE
379             SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
380             STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
381             SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
382             INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
383             FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
384             PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE,
385             YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
386              
387             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY
388             COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
389             SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES,
390             INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
391             OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO
392             LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
393             THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER
394             SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
395             POSSIBILITY OF SUCH DAMAGES.
396              
397             =cut
398              
399             1; # End of WebService::Careerjet