diff --git a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.js b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.js index b888e721bb..b05b6021af 100644 --- a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.js +++ b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.js @@ -3,7 +3,7 @@ frappe.ui.form.on('LinkedIn Settings', { onload: function(frm){ - if(frm.doc.session_status == 'Expired' && frm.doc.consumer_key && frm.doc.consumer_secret){ + if (frm.doc.session_status == 'Expired' && frm.doc.consumer_key && frm.doc.consumer_secret){ frappe.confirm( __('Session not valid, Do you want to login?'), function(){ @@ -12,45 +12,49 @@ frappe.ui.form.on('LinkedIn Settings', { function(){ window.close(); } - ) + ); } }, refresh: function(frm){ - if(frm.doc.session_status=="Expired"){ + if (frm.doc.session_status=="Expired"){ + let msg = __("Session Not Active. Save doc to login."); frm.dashboard.set_headline_alert( - '
' + - '
' + - ' ' + - '
' + - '
' + `
+
+ +
+
` ); } - if(frm.doc.session_status=="Active"){ - let d = new Date(frm.doc.modified) + + if (frm.doc.session_status=="Active"){ + let d = new Date(frm.doc.modified); d.setDate(d.getDate()+60); - let dn = new Date() + let dn = new Date(); let days = d.getTime() - dn.getTime(); days = Math.floor(days/(1000 * 3600 * 24)); let msg,color; - if(days>0){ + + if (days>0){ msg = __("Your Session will be expire in ") + days + __(" days."); color = "green"; } - else{ + else { msg = __("Session is expired. Save doc to login."); color = "red"; } + frm.dashboard.set_headline_alert( - '
' + - '
' + - ' ' + - '
' + - '
' + `
+
+ +
+
` ); } }, login: function(frm){ - if(frm.doc.consumer_key && frm.doc.consumer_secret){ + if (frm.doc.consumer_key && frm.doc.consumer_secret){ frappe.call({ doc: frm.doc, method: "get_authorization_url", diff --git a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py index 9326e6d046..5df35df3dd 100644 --- a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py +++ b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py @@ -9,6 +9,7 @@ from frappe.utils import get_site_url, get_url_to_form, get_link_to_form from frappe.model.document import Document from frappe.utils.file_manager import get_file, get_file_path from six.moves.urllib.parse import urlencode + class LinkedInSettings(Document): def get_authorization_url(self): params = urlencode({ @@ -46,9 +47,12 @@ class LinkedInSettings(Document): url = "https://api.linkedin.com/v2/me" response = requests.get(url=url, headers=headers) response = frappe.parse_json(response.content.decode()) - self.db_set("person_urn", response["id"]) - self.db_set("account_name", response["vanityName"]) - self.db_set("session_status", "Active") + + frappe.db.set_value(self.doctype, self.name, { + "person_urn": response["id"], + "account_name": response["vanityName"], + "session_status": "Active" + }) frappe.local.response["type"] = "redirect" frappe.local.response["location"] = get_url_to_form("LinkedIn Settings","LinkedIn Settings") @@ -57,6 +61,7 @@ class LinkedInSettings(Document): return self.post_text(text) else: media_id = self.upload_image(media) + if media_id: return self.post_text(text, media_id=media_id) else: @@ -66,7 +71,6 @@ class LinkedInSettings(Document): def upload_image(self, media): media = get_file_path(media) register_url = "https://api.linkedin.com/v2/assets?action=registerUpload" - body = { "registerUploadRequest": { "recipes": ["urn:li:digitalmediaRecipe:feedshare-image"], @@ -81,6 +85,7 @@ class LinkedInSettings(Document): "Authorization": "Bearer {}".format(self.access_token) } response = self.http_post(url=register_url, body=body, headers=headers) + if response.status_code == 200: response = response.json() asset = response["value"]["asset"] @@ -91,11 +96,10 @@ class LinkedInSettings(Document): frappe.throw(_("Error While Uploading Image"), title="{0} {1}".format(response.status_code, response.reason)) return None return asset + return None - def post_text(self, text, media_id=None): - # url = "https://api.linkedin.com/v2/ugcPosts" url = "https://api.linkedin.com/v2/shares" headers = { "X-Restli-Protocol-Version": "2.0.0", @@ -112,6 +116,7 @@ class LinkedInSettings(Document): "text": text } } + if media_id: body["content"]= { "contentEntities": [{ @@ -119,6 +124,7 @@ class LinkedInSettings(Document): }], "shareMediaCategory": "IMAGE" } + response = self.http_post(url=url, headers=headers, body=body) return response @@ -132,17 +138,20 @@ class LinkedInSettings(Document): ) if response.status_code not in [201,200]: raise + except Exception as e: content = json.loads(response.content) + if response.status_code == 401: self.db_set("session_status", "Expired") frappe.db.commit() - frappe.throw(content["message"], title="LinkedIn Error - Unauthorized") + frappe.throw(content["message"], title="LinkedIn Error - Unauthorized") elif response.status_code == 403: frappe.msgprint(_("You Didn't have permission to access this API")) frappe.throw(content["message"], title="LinkedIn Error - Access Denied") else: frappe.throw(response.reason, title=response.status_code) + return response @frappe.whitelist() diff --git a/erpnext/crm/doctype/social_media_post/social_media_post.js b/erpnext/crm/doctype/social_media_post/social_media_post.js index 517b3b4614..c2a17d8bec 100644 --- a/erpnext/crm/doctype/social_media_post/social_media_post.js +++ b/erpnext/crm/doctype/social_media_post/social_media_post.js @@ -2,44 +2,45 @@ // For license information, please see license.txt frappe.ui.form.on('Social Media Post', { validate: function(frm){ - if(frm.doc.twitter==0 && frm.doc.linkedin==0){ + if (frm.doc.twitter === 0 && frm.doc.linkedin === 0){ frappe.throw(__("Select atleast one Social Media from Share on.")) } - if(frm.doc.scheduled_time) { + if (frm.doc.scheduled_time) { let scheduled_time = new Date(frm.doc.scheduled_time); let date_time = new Date(); - if(scheduled_time.getTime() < date_time.getTime()){ + if (scheduled_time.getTime() < date_time.getTime()){ frappe.throw(__("Invalid Scheduled Time")); } } - if(frm.doc.text?.length > 280){ + if (frm.doc.text?.length > 280){ frappe.throw(__("Length Must be less than 280.")) } }, refresh: function(frm){ - if(frm.doc.docstatus === 1){ - if(frm.doc.post_status != "Posted"){ + if (frm.doc.docstatus === 1){ + if (frm.doc.post_status != "Posted"){ add_post_btn(frm); } - else if(frm.doc.post_status == "Posted"){ + else if (frm.doc.post_status == "Posted"){ frm.set_df_property('sheduled_time', 'read_only', 1); } - let html = '
'; - if(frm.doc.twitter){ + + let html=''; + if (frm.doc.twitter){ let color = frm.doc.twitter_post_id ? "green" : "red"; let status = frm.doc.twitter_post_id ? "Posted" : "Not Posted"; - html += '
' + - ' ' + - '
' ; + html += `
+ +
` ; } - if(frm.doc.linkedin){ + if (frm.doc.linkedin){ let color = frm.doc.linkedin_post_id ? "green" : "red"; let status = frm.doc.linkedin_post_id ? "Posted" : "Not Posted"; - html += '
' + - ' ' + - '
' ; + html += `
+ +
` ; } - html += '
'; + html = `
${html}
`; frm.dashboard.set_headline_alert(html); } } diff --git a/erpnext/crm/doctype/social_media_post/social_media_post.py b/erpnext/crm/doctype/social_media_post/social_media_post.py index 2cca60892b..ed1b583944 100644 --- a/erpnext/crm/doctype/social_media_post/social_media_post.py +++ b/erpnext/crm/doctype/social_media_post/social_media_post.py @@ -33,7 +33,7 @@ class SocialMediaPost(Document): self.db_set("linkedin_post_id", linkedin_post.headers['X-RestLi-Id'].split(":")[-1]) self.db_set("post_status", "Posted") - except Exception as e: + except: self.db_set("post_status", "Error") title = _("Error while POSTING {0}").format(self.name) traceback = frappe.get_traceback() diff --git a/erpnext/crm/doctype/twitter_settings/twitter_settings.js b/erpnext/crm/doctype/twitter_settings/twitter_settings.js index be5ae9d710..eae25206b3 100644 --- a/erpnext/crm/doctype/twitter_settings/twitter_settings.js +++ b/erpnext/crm/doctype/twitter_settings/twitter_settings.js @@ -3,7 +3,7 @@ frappe.ui.form.on('Twitter Settings', { onload: function(frm){ - if(frm.doc.session_status == 'Expired' && frm.doc.consumer_key && frm.doc.consumer_secret){ + if (frm.doc.session_status == 'Expired' && frm.doc.consumer_key && frm.doc.consumer_secret){ frappe.confirm( __('Session not valid, Do you want to login?'), function(){ @@ -12,31 +12,30 @@ frappe.ui.form.on('Twitter Settings', { function(){ window.close(); } - ) + ); } }, refresh: function(frm){ - if(frm.doc.session_status=="Active"){ - frm.dashboard.set_headline_alert( - '
' + - '
' + - ' ' + - '
' + - '
' - ); + let msg,color; + if (frm.doc.session_status == "Active"){ + msg = __("Session Active"); + color = 'green'; } - else if(frm.doc.session_status=="Expired"){ - frm.dashboard.set_headline_alert( - '
' + - '
' + - ' ' + - '
' + - '
' - ); + else { + msg = __("Session Not Active. Save doc to login."); + color = 'red'; } + + frm.dashboard.set_headline_alert( + `
+
+ +
+
` + ); }, login: function(frm){ - if(frm.doc.consumer_key && frm.doc.consumer_secret){ + if (frm.doc.consumer_key && frm.doc.consumer_secret){ frappe.call({ doc: frm.doc, method: "get_authorize_url", diff --git a/erpnext/crm/doctype/twitter_settings/twitter_settings.py b/erpnext/crm/doctype/twitter_settings/twitter_settings.py index f069a600dd..64f53b5eb0 100644 --- a/erpnext/crm/doctype/twitter_settings/twitter_settings.py +++ b/erpnext/crm/doctype/twitter_settings/twitter_settings.py @@ -14,6 +14,7 @@ class TwitterSettings(Document): def get_authorize_url(self): callback_url = "{0}/?cmd=erpnext.crm.doctype.twitter_settings.twitter_settings.callback".format(frappe.utils.get_url()) auth = tweepy.OAuthHandler(self.consumer_key, self.get_password(fieldname="consumer_secret"), callback_url) + try: redirect_url = auth.get_authorization_url() return redirect_url @@ -28,16 +29,21 @@ class TwitterSettings(Document): 'oauth_token' : oauth_token, 'oauth_token_secret' : oauth_verifier } + try: auth.get_access_token(oauth_verifier) - self.db_set("oauth_token", auth.access_token) - self.db_set("oauth_secret", auth.access_token_secret) api = self.get_api() user = api.me() - self.db_set("account_name", user._json["screen_name"]) profile_pic = (user._json["profile_image_url"]).replace("_normal","") - self.db_set("profile_pic", profile_pic) - self.db_set("session_status", "Active") + + frappe.db.set_value(self.doctype, self.name, { + "oauth_token" : auth.access_token, + "oauth_secret" : auth.access_token_secret, + "account_name" : user._json["screen_name"], + "profile_pic" : profile_pic, + "session_status" : "Active" + }) + frappe.local.response["type"] = "redirect" frappe.local.response["location"] = get_url_to_form("Twitter Settings","Twitter Settings") except TweepError as e: @@ -64,6 +70,7 @@ class TwitterSettings(Document): media = get_file_path(media) api = self.get_api() media = api.media_upload(media) + return media.media_id def send_tweet(self, text, media_id=None): @@ -73,6 +80,7 @@ class TwitterSettings(Document): response = api.update_status(status = text, media_ids = [media_id]) else: response = api.update_status(status = text) + return response except TweepError as e: @@ -87,4 +95,4 @@ class TwitterSettings(Document): def callback(oauth_token, oauth_verifier): twitter_settings = frappe.get_single("Twitter Settings") twitter_settings.get_access_token(oauth_token,oauth_verifier) - frappe.db.commit() + frappe.db.commit()