diff --git a/hr_linkedin_recruitment/README.rst b/hr_linkedin_recruitment/README.rst
index 30e11c072..48b4d7060 100644
--- a/hr_linkedin_recruitment/README.rst
+++ b/hr_linkedin_recruitment/README.rst
@@ -18,17 +18,24 @@ The module integrates LinkedIn with Odoo HR Recruitment.
* Profile URL of Candidates.
* Automate Odoo HRMS with LinkedIn.
-
Company
-------
* `Cybrosys Technologies `__
+Developers
+----------
+* `Nilmar Shereef `__
+* `Jesni Banu `__
+
Contact
-------
* Mail Contact : odoo@cybrosys.com
* Mail Contact : shereef@cybrosys.in
* Mail Contact : info@cybrosys.com
+Related Blog
+-------
+* `Cybrosys LinkedIn Blog `__
Further information
===================
HTML Description: ``__
diff --git a/hr_linkedin_recruitment/__manifest__.py b/hr_linkedin_recruitment/__manifest__.py
index d9cf42523..9558d344a 100644
--- a/hr_linkedin_recruitment/__manifest__.py
+++ b/hr_linkedin_recruitment/__manifest__.py
@@ -25,7 +25,7 @@
'summary': "Integrates LinkedIn with HR Recruitment",
'description': "Basic module for LnkedIn-HR Recruitment connector",
'category': 'Generic Modules/Human Resources',
- 'version': "10.0.1.1.0",
+ 'version': "10.0.2.0.0",
'depends': ['hr_recruitment', 'auth_oauth'],
'author': 'Cybrosys Techno Solutions',
'company': 'Cybrosys Techno Solutions',
diff --git a/hr_linkedin_recruitment/doc/RELEASE_NOTES.md b/hr_linkedin_recruitment/doc/RELEASE_NOTES.md
new file mode 100644
index 000000000..b24b5dfe5
--- /dev/null
+++ b/hr_linkedin_recruitment/doc/RELEASE_NOTES.md
@@ -0,0 +1,14 @@
+## Module
+
+#### 19.05.2018
+#### Version 10.0.2.0.0
+##### FIX
+- Redirect url
+- Handler for wrong password
+- Handler import error
+
+
+#### 28.04.2018
+#### Version 10.0.1.0.0
+##### ADD
+- Initial commit for LinkedIn-Odoo Integration
diff --git a/hr_linkedin_recruitment/doc/requirment.txt b/hr_linkedin_recruitment/doc/requirment.txt
index ef092c744..6a8ad0917 100644
--- a/hr_linkedin_recruitment/doc/requirment.txt
+++ b/hr_linkedin_recruitment/doc/requirment.txt
@@ -1,5 +1,8 @@
Odoo integration module "hr_linkedin_recruitment" depends on the several external python package.
Please ensure that listed packaged has installed in your system:
-* linkedin
-* mechanize
\ No newline at end of file
+* python-linkedin (sudo python-linkedin)
+* mechanize (sudo pip install mechanize)
+
+
+
diff --git a/hr_linkedin_recruitment/models/hr_job.py b/hr_linkedin_recruitment/models/hr_job.py
index 7fb0bc72e..767a312e5 100644
--- a/hr_linkedin_recruitment/models/hr_job.py
+++ b/hr_linkedin_recruitment/models/hr_job.py
@@ -25,6 +25,7 @@ _logger = logging.getLogger(__name__)
try:
import mechanize
from linkedin import linkedin
+ from mechanize_op import MechanizeRedirectHandler
except ImportError:
_logger.error('Odoo module hr_linkedin_recruitment depends on the several external python package'
@@ -34,8 +35,7 @@ import requests
import json
import urlparse
from odoo import models, fields, api, _
-from odoo.exceptions import ValidationError
-from mechanize_op import MechanizeRedirectHandler
+from odoo.exceptions import ValidationError, Warning
class HrJobShare(models.Model):
@@ -59,15 +59,25 @@ class HrJobShare(models.Model):
has_access_url = 'https://api.linkedin.com/v1/companies/%s/relation-to-viewer/is-company-share-enabled?format=json'%(li_credential['page_id'])
page_share_url = 'https://api.linkedin.com/v1/companies/%s/shares?format=json'%(li_credential['page_id'])
- response = self.has_acces_request('GET', has_access_url, access_token)
- access_response_text = response.json()
+ access_response = self.has_acces_request('GET', has_access_url, access_token)
+ access_response_text = access_response.json()
if access_response_text:
response = self.share_request('POST', page_share_url, access_token, data=json.dumps(share_data))
share_response_text = response.json()
share_response_code = response.status_code
if share_response_code == 201:
self.update_key = share_response_text['updateKey']
+ else:
+ raise Warning("You have no share access in company page.!")
+ def has_acces_request(self, method, has_access_url, access_token):
+ """ Function will return TRUE if credentials user has the access to update """
+ headers = {'x-li-format': 'json', 'Content-Type': 'application/json'}
+ params = {}
+ params.update({'oauth2_access_token': access_token})
+ kw = dict(params=params, headers=headers, timeout=60)
+ req_response = requests.request(method.upper(), has_access_url, **kw)
+ return req_response
def share_request(self, method, page_share_url, access_token, data):
""" Function will return UPDATED KEY , [201] if sharing is OK """
@@ -93,15 +103,15 @@ class HrJobShare(models.Model):
li_credential['page_id'] = self.env['ir.values'].get_default('hr.recruitment.config.settings',
'company_page_id')
else:
- raise exceptions.Warning(_('Please fill up company page ID in LinkedIn Credential settings.'))
+ raise Warning(_('Please fill up company page ID in LinkedIn Credential settings.'))
if self.env['ir.values'].get_default('hr.recruitment.config.settings', 'li_username'):
li_credential['un'] = self.env['ir.values'].get_default('hr.recruitment.config.settings', 'li_username')
else:
- raise exceptions.Warning(_('Please fill up username in LinkedIn Credential settings.'))
+ raise Warning(_('Please fill up username in LinkedIn Credential settings.'))
if self.env['ir.values'].get_default('hr.recruitment.config.settings', 'li_password'):
li_credential['pw'] = self.env['ir.values'].get_default('hr.recruitment.config.settings', 'li_password')
else:
- raise exceptions.Warning(_('Please fill up password in LinkedIn Credential settings.'))
+ raise Warning(_('Please fill up password in LinkedIn Credential settings.'))
# Browser Data Posting And Signing
br = mechanize.Browser()
@@ -109,7 +119,7 @@ class HrJobShare(models.Model):
br.handler_classes['_redirect'] = MechanizeRedirectHandler
br.set_handle_redirect(True)
br.set_handle_robots(False)
- return_uri = 'http://0.0.0.0:8010'
+ return_uri = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
li_permissions = ['r_basicprofile', 'r_emailaddress', 'w_share', 'rw_company_admin']
auth = linkedin.LinkedInAuthentication(li_credential['api_key'],
li_credential['secret_key'],
@@ -117,11 +127,15 @@ class HrJobShare(models.Model):
li_permissions)
br.open(auth.authorization_url)
br.select_form(nr=0)
-
+ print "li_credential", li_credential
br.form['session_key'] = li_credential['un']
br.form['session_password'] = li_credential['pw']
r = br.submit()
- auth.authorization_code = urlparse.parse_qs(urlparse.urlsplit(r.geturl()).query)['code']
+ try:
+ auth.authorization_code = urlparse.parse_qs(urlparse.urlsplit(r.geturl()).query)['code']
+ except:
+ raise Warning("Please cross check your username and password.!")
+
li_suit_credent = {}
li_suit_credent['access_token'] = str(auth.get_access_token().access_token)
li_suit_credent['li_credential'] = li_credential
diff --git a/hr_linkedin_recruitment/models/mechanize_op.py b/hr_linkedin_recruitment/models/mechanize_op.py
index d03dd5386..0b439ad35 100644
--- a/hr_linkedin_recruitment/models/mechanize_op.py
+++ b/hr_linkedin_recruitment/models/mechanize_op.py
@@ -21,52 +21,56 @@
#
###################################################################################
import logging
+from urllib2 import HTTPError
_logger = logging.getLogger(__name__)
try:
import mechanize
-except ImportError:
- _logger.error('Odoo module hr_linkedin_recruitment depends on the several external python package'
- 'Please read the doc/requirement.txt file inside the module.')
-import re
-from mechanize import _response
-from mechanize import _rfc3986
+ from mechanize import _response
+ from mechanize import _rfc3986
+ import re
+
+
+ class MechanizeRedirectHandler(mechanize.HTTPRedirectHandler):
+ def http_error_302(self, req, fp, code, msg, headers):
+ # Code from mechanize._urllib2_fork.HTTPRedirectHandler:
+ if 'location' in headers:
+ newurl = headers.getheaders('location')[0]
+ elif 'uri' in headers:
+ newurl = headers.getheaders('uri')[0]
+ else:
+ return
+ newurl = _rfc3986.clean_url(newurl, "latin-1")
+ newurl = _rfc3986.urljoin(req.get_full_url(), newurl)
+ new = self.redirect_request(req, fp, code, msg, headers, newurl)
+ if new is None:
+ return
-class MechanizeRedirectHandler(mechanize.HTTPRedirectHandler):
- def http_error_302(self, req, fp, code, msg, headers):
- # Code from mechanize._urllib2_fork.HTTPRedirectHandler:
- if 'location' in headers:
- newurl = headers.getheaders('location')[0]
- elif 'uri' in headers:
- newurl = headers.getheaders('uri')[0]
- else:
- return
- newurl = _rfc3986.clean_url(newurl, "latin-1")
- newurl = _rfc3986.urljoin(req.get_full_url(), newurl)
+ if hasattr(req, 'redirect_dict'):
+ visited = new.redirect_dict = req.redirect_dict
+ if (visited.get(newurl, 0) >= self.max_repeats or
+ len(visited) >= self.max_redirections):
+ raise HTTPError(req.get_full_url(), code,
+ self.inf_msg + msg, headers, fp)
+ else:
+ visited = new.redirect_dict = req.redirect_dict = {}
+ visited[newurl] = visited.get(newurl, 0) + 1
- new = self.redirect_request(req, fp, code, msg, headers, newurl)
- if new is None:
- return
+ fp.read()
+ fp.close()
- if hasattr(req, 'redirect_dict'):
- visited = new.redirect_dict = req.redirect_dict
- if (visited.get(newurl, 0) >= self.max_repeats or
- len(visited) >= self.max_redirections):
- raise HTTPError(req.get_full_url(), code,
- self.inf_msg + msg, headers, fp)
- else:
- visited = new.redirect_dict = req.redirect_dict = {}
- visited[newurl] = visited.get(newurl, 0) + 1
+ # If the redirected URL doesn't match
+ new_url = new.get_full_url()
+ if not re.search('^http(?:s)?\:\/\/.*www\.linkedin\.com', new_url):
+ return _response.make_response('', headers.items(), new_url, 200, 'OK')
+ else:
+ return self.parent.open(new)
- fp.read()
- fp.close()
+ http_error_301 = http_error_303 = http_error_307 = http_error_302
+ http_error_refresh = http_error_302
+
+except ImportError:
+ _logger.warning('Odoo module hr_linkedin_recruitment depends on the several external python package'
+ 'Please read the doc/requirement.txt file inside the module.')
- # If the redirected URL doesn't match
- new_url = new.get_full_url()
- if not re.search('^http(?:s)?\:\/\/.*www\.linkedin\.com', new_url):
- return _response.make_response('', headers.items(), new_url, 200, 'OK')
- else:
- return self.parent.open(new)
- http_error_301 = http_error_303 = http_error_307 = http_error_302
- http_error_refresh = http_error_302