def save_data(self, trigger_id, **data): """ let's save the data :param trigger_id: trigger ID from which to save data :param data: the data to check to be used and save :type trigger_id: int :type data: dict :return: the status of the save statement :rtype: boolean """ status = False # set the title and content of the data title, content = super(ServiceTwitter, self).save_data(trigger_id, **data) if data.get('link') and len(data.get('link')) > 0: # remove html tag if any content = html.strip_tags(content) if self.title_or_content(title): content = str("{title} {link}").format(title=title, link=data.get('link')) content += get_tags(Twitter, trigger_id) else: content = self.set_twitter_content(content) try: self.twitter_api.update_status(status=content) status = True except Exception as inst: logger.critical("Twitter ERR {}".format(inst)) update_result(trigger_id, msg=inst, status=False) status = False return status
def save_data(self, trigger_id, **data): """ let's save the data :param trigger_id: trigger ID from which to save data :param data: the data to check to be used and save :type trigger_id: int :type data: dict :return: the status of the save statement :rtype: boolean """ if data.get('link'): if len(data.get('link')) > 0: # get the pocket data of this trigger from th_pocket.models import Pocket as PocketModel trigger = PocketModel.objects.get(trigger_id=trigger_id) title = self.set_title(data) # convert htmlentities title = HtmlEntities(title).html_entity_decode status = self._create_entry(url=data.get('link'), title=title, tags=(trigger.tag.lower())) else: msg = "no link provided for trigger ID {}, so we ignore it".format(trigger_id) logger.warning(msg) update_result(trigger_id, msg=msg, status=True) status = True else: msg = "no token provided for trigger ID {}".format(trigger_id) logger.critical(msg) update_result(trigger_id, msg=msg, status=False) status = False return status
def _create_entry(self, title, data, tags): """ create an entry :param title: string :param data: dict :param tags: list :return: boolean """ if data.get('link') and len(data.get('link')) > 0: wall = self.new_wall(self.token) try: wall.post_entries(url=data.get('link').encode(), title=title, tags=(tags.lower())) logger.debug('wallabag {} created'.format(data.get('link'))) status = True except Exception as e: if e.errno == 401: status = self._new_token(data.get('userservice_id'), data.get('link').encode(), title, tags.lower()) else: logger.critical('issue with something else that a token' ' link ? : {}'.format(data.get('link'))) logger.critical(e.errno, e.strerror) update_result(self.trigger_id, msg=e, status=False) status = False else: status = True # we ignore empty link return status
def wall(self): """ refresh the token from the API then call a Wallabag instance then store the token :return: wall instance """ us = UserService.objects.get(user=self.user, name='ServiceWallabag') params = { 'client_id': us.client_id, 'client_secret': us.client_secret, 'username': us.username, 'password': us.password, } try: token = Wall.get_token(host=us.host, **params) except Exception as e: update_result(self.trigger_id, msg=e, status=False) logger.critical('{} {}'.format(self.user, e)) return False wall = Wall(host=us.host, client_secret=us.client_secret, client_id=us.client_id, token=token) UserService.objects.filter(user=self.user, name='ServiceWallabag').update(token=token) return wall
def save_data(self, trigger_id, **data): """ let's save the data :param trigger_id: trigger ID from which to save data :param data: the data to check to be used and save :type trigger_id: int :type data: dict :return: the status of the save statement :rtype: boolean """ title, content = super(ServicePushbullet, self).save_data(trigger_id, **data) if self.token: trigger = Pushbullet.objects.get(trigger_id=trigger_id) if trigger.type == 'note': status = self.pushb.push_note(title=title, body=content) elif trigger.type == 'link': status = self.pushb.push_link(title=title, body=content, url=data.get('link')) sentence = str('pushbullet {} created').format(title) logger.debug(sentence) else: # no valid type of pushbullet specified msg = "no valid type of pushbullet specified" logger.critical(msg) update_result(trigger_id, msg=msg) status = False else: msg = "no token or link provided for trigger " \ "ID {} ".format(trigger_id) logger.critical(msg) update_result(trigger_id, msg=msg) status = False return status
def save_data(self, trigger_id, **data): """ let's save the data :param trigger_id: trigger ID from which to save data :param data: the data to check to be used and save :type trigger_id: int :type data: dict :return: the status of the save statement :rtype: boolean """ status = False # set the title and content of the data title, content = super(ServiceTwitter, self).save_data(trigger_id, **data) if data.get('link') and len(data.get('link')) > 0: if self.title_or_content(title): content = str("{title} {link}").format(title=title, link=data.get('link')) content += self.get_tags(trigger_id) else: content = self.set_twitter_content(content) try: self.twitter_api.update_status(status=content) status = True except Exception as inst: logger.critical("Twitter ERR {}".format(inst)) update_result(trigger_id, msg=inst, status=False) status = False return status
def save_data(self, trigger_id, **data): """ let's save the data :param trigger_id: trigger ID from which to save data :param data: the data to check to be used and save :type trigger_id: int :type data: dict :return: the status of the save statement :rtype: boolean """ title, content = super(ServicePushbullet, self).save_data(trigger_id, **data) if self.token: trigger = Pushbullet.objects.get(trigger_id=trigger_id) if trigger.type == 'note': status = self.pushb.push_note(title=title, body=content) elif trigger.type == 'link': status = self.pushb.push_link(title=title, body=content, url=data.get('link')) sentence = str('pushbullet {} created').format(title) logger.debug(sentence) else: # no valid type of pushbullet specified msg = "no valid type of pushbullet specified" logger.critical(msg) update_result(trigger_id, msg=msg, status=False) status = False else: msg = "no token or link provided for trigger ID {} ".format(trigger_id) logger.critical(msg) update_result(trigger_id, msg=msg, status=False) status = False return status
def save_data(self, trigger_id, **data): """ let's save the data :param trigger_id: trigger ID from which to save data :param data: the data to check to be used and save :type trigger_id: int :type data: dict :return: the status of the save statement :rtype: boolean """ # convert the format to be released in Markdown status = False data['output_format'] = 'md' title, content = super(ServiceReddit, self).save_data(trigger_id, **data) if self.token: trigger = Reddit.objects.get(trigger_id=trigger_id) if trigger.share_link: status = self.reddit.subreddit(trigger.subreddit).submit( title=title, url=content) else: status = self.reddit.subreddit(trigger.subreddit).submit( title=title, selftext=content) sentence = str('reddit submission {} created').format(title) logger.debug(sentence) else: msg = "no token or link provided for trigger ID {} ".format( trigger_id) logger.critical(msg) update_result(trigger_id, msg=msg, status=False) return status
def create_note(note_store, note, trigger_id, data): """ create a note :param note_store Evernote instance :param note :param trigger_id id of the trigger :param data to save or to put in cache :type note_store: Evernote Instance :type note: Note instance :type trigger_id: int :type data: dict :return boolean :rtype boolean """ # create the note ! try: created_note = note_store.createNote(note) sentence = str('note %s created') % created_note.guid logger.debug(sentence) return True except EDAMSystemException as e: return error(trigger_id, data, e) except EDAMUserException as e: if e.errorCode == EDAMErrorCode.ENML_VALIDATION: sentence = "Data ignored due to validation error : err {code} {msg}".format( code=e.errorCode, msg=e.parameter) logger.warning(sentence) update_result(trigger_id, msg=sentence, status=True) return True except Exception as e: logger.critical(e) update_result(trigger_id, msg=e, status=False) return False
def _create_entry(self, title, data, tags): """ create an entry :param title: string :param data: dict :param tags: list :return: boolean """ if data.get('link') and len(data.get('link')) > 0: wall = self.new_wall(self.token) try: wall.post_entries(url=data.get('link').encode(), title=title, tags=(tags.lower())) logger.debug('wallabag {} created'.format(data.get('link'))) status = True except Exception as e: if e.errno == 401: status = self._new_token(data.get('userservice_id'), data.get('link').encode(), title, tags.lower()) else: logger.critical('issue with something else that a token' ' link ? : {}'.format(data.get('link'))) logger.critical(e.errno, e.strerror) update_result(self.trigger_id, msg=e) status = False else: status = True # we ignore empty link return status
def __init__(self, token=None, **kwargs): super(ServiceTrello, self).__init__(token, **kwargs) # app name self.app_name = DjangoThConfig.verbose_name # expiration self.expiry = "30days" # scope define the rights access self.scope = 'read,write' self.oauth = 'oauth1' self.service = 'ServiceTrello' base = 'https://www.trello.com' self.AUTH_URL = '{}/1/OAuthAuthorizeToken'.format(base) self.REQ_TOKEN = '{}/1/OAuthGetRequestToken'.format(base) self.ACC_TOKEN = '{}/1/OAuthGetAccessToken'.format(base) self.consumer_key = settings.TH_TRELLO_KEY['consumer_key'] self.consumer_secret = settings.TH_TRELLO_KEY['consumer_secret'] if token: token_key, token_secret = token.split('#TH#') try: self.trello_instance = TrelloClient(self.consumer_key, self.consumer_secret, token_key, token_secret) except ResourceUnavailable as e: us = UserService.objects.get(token=token) logger.error(e.msg, e.error_code) update_result(us.trigger_id, msg=e.msg, status=False)
def create_note(note_store, note, trigger_id, data): """ create a note :param note_store Evernote instance :param note :param trigger_id id of the trigger :param data to save or to put in cache :type note_store: Evernote Instance :type note: Note instance :type trigger_id: int :type data: dict :return boolean :rtype boolean """ # create the note ! try: created_note = note_store.createNote(note) sentence = str('note %s created') % created_note.guid logger.debug(sentence) return True except EDAMSystemException as e: return error(trigger_id, data, e) except EDAMUserException as e: if e.errorCode == EDAMErrorCode.ENML_VALIDATION: sentence = "Data ignored due to validation error : err {code} {msg}".format(code=e.errorCode, msg=e.parameter) logger.warning(sentence) update_result(trigger_id, msg=sentence, status=True) return True except Exception as e: logger.critical(e) update_result(trigger_id, msg=e, status=False) return False
def __init__(self, token=None, **kwargs): super(ServiceTrello, self).__init__(token, **kwargs) # app name self.app_name = DjangoThConfig.verbose_name # expiration self.expiry = "30days" # scope define the rights access self.scope = 'read,write' self.oauth = 'oauth1' self.service = 'ServiceTrello' base = 'https://www.trello.com' self.AUTH_URL = '{}/1/OAuthAuthorizeToken'.format(base) self.REQ_TOKEN = '{}/1/OAuthGetRequestToken'.format(base) self.ACC_TOKEN = '{}/1/OAuthGetAccessToken'.format(base) self.consumer_key = settings.TH_TRELLO['consumer_key'] self.consumer_secret = settings.TH_TRELLO['consumer_secret'] if token: token_key, token_secret = token.split('#TH#') try: self.trello_instance = TrelloClient(self.consumer_key, self.consumer_secret, token_key, token_secret) except ResourceUnavailable as e: us = UserService.objects.get(token=token) logger.error(e.msg, e.error_code) update_result(us.trigger_id, msg=e.msg, status=False)
def _create_entry(self, title, data, tags): """ create an entry :param title: string :param data: dict :param tags: list :return: boolean """ status = False if data.get('link') and len(data.get('link')) > 0: wall = self.wall() if wall is not False: try: wall.post_entries(url=data.get('link').encode(), title=title, tags=(tags.lower())) logger.debug('wallabag {} created'.format( data.get('link'))) status = True except Exception as e: logger.critical('issue with something else that a token' ' link ? : {}'.format(data.get('link'))) logger.critical(e) update_result(self.trigger_id, msg=e, status=False) status = False else: status = True # we ignore empty link return status
def _get_tweets(twitter_obj, search): """ get the tweets from twitter and return the filters to use : search and count :param twitter_obj: from Twitter model :param search: filter used for twython.search() or twython.get_user_timeline()) :type twitter_obj: Object :type search: dict :return: count that limit the quantity of tweet to retrieve, the filter named search, the tweets :rtype: list """ """ explanations about statuses : when we want to track the tweet of a screen 'statuses' contain all of them when we want to track all the tweet matching a tag 'statuses' contain statuses + metadata array this is why we need to do statuses = statuses['statuses'] to be able to handle the result as for screen_name """ # get the tweets for a given tag # https://dev.twitter.com/docs/api/1.1/get/search/tweets statuses = '' count = 100 if twitter_obj.tag: count = 100 search['count'] = count search['q'] = twitter_obj.tag search['result_type'] = 'recent' # do a search statuses = self.twitter_api.search(**search) # just return the content of te statuses array statuses = statuses['statuses'] # get the tweets from a given user # https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline elif twitter_obj.screen: count = 200 search['count'] = count search['screen_name'] = twitter_obj.screen # call the user timeline and get his tweet try: if twitter_obj.fav: count = 20 search['count'] = 20 # get the favorites https://dev.twitter.com/rest/ # reference/get/favorites/list statuses = self.twitter_api.get_favorites(**search) else: statuses = self.twitter_api.get_user_timeline(**search) except TwythonAuthError as e: logger.error(e.msg, e.error_code) update_result(trigger_id, msg=e.msg, status=False) return count, search, statuses
def save_data(self, trigger_id, **data): """ get the data from the service :param trigger_id: id of the trigger :params data, dict :rtype: dict """ title, content = super(ServiceMastodon, self).save_data(trigger_id, **data) # check if we have a 'good' title if self.title_or_content(title): content = str("{title} {link}").format(title=title, link=data.get('link')) content += self.get_tags(trigger_id) # if not then use the content else: content += " " + data.get('link') content += " " + self.get_tags(trigger_id) content = self.set_mastodon_content(content) us = UserService.objects.get(user=self.user, token=self.token, name='ServiceMastodon') try: toot_api = MastodonAPI(client_id=us.client_id, client_secret=us.client_secret, access_token=self.token, api_base_url=us.host) except ValueError as e: logger.error(e) status = False update_result(trigger_id, msg=e, status=status) media_ids = None try: if settings.DJANGO_TH['sharing_media']: # do we have a media in the content ? content, media = self.media_in_content(content) if media: # upload the media first media_ids = toot_api.media_post(media_file=media) media_ids = [media_ids] toot_api.status_post(content, media_ids=media_ids) status = True except Exception as inst: logger.critical("Mastodon ERR {}".format(inst)) status = False update_result(trigger_id, msg=inst, status=status) return status
def _notestore(self, trigger_id, data): try: note_store = self.client.get_note_store() return note_store except EDAMSystemException as e: return error(trigger_id, data, e) except Exception as e: logger.critical(e) update_result(trigger_id, msg=e, status=False) return False
def __init__(self, token=None, **kwargs): super(ServicePocket, self).__init__(token, **kwargs) self.consumer_key = settings.TH_POCKET_KEY['consumer_key'] self.token = token self.oauth = 'oauth1' self.service = 'ServicePocket' if token: try: self.pocket = Pocket(self.consumer_key, token) except (AuthException, RateLimitException) as e: us = UserService.objects.get(token=token) logger.error(e.msg, e.error_code) update_result(us.trigger_id, msg=e.msg, status=False)
def __init__(self, token=None, **kwargs): super(ServicePocket, self).__init__(token, **kwargs) self.consumer_key = settings.TH_POCKET['consumer_key'] self.token = token self.oauth = 'oauth1' self.service = 'ServicePocket' if token: try: self.pocket = Pocket(self.consumer_key, token) except (AuthException, RateLimitException) as e: us = UserService.objects.get(token=token) logger.error(e.msg, e.error_code) update_result(us.trigger_id, msg=e.msg, status=False)
def error(trigger_id, data, error): if error.errorCode == EDAMErrorCode.RATE_LIMIT_REACHED: sentence = "Rate limit reached {code}\nRetry your request in {msg} seconds\n" \ "Data set to cache again until limit reached".format(code=error.errorCode, msg=error.rateLimitDuration) logger.warning(sentence) cache.set('th_evernote_' + str(trigger_id), data, version=2) update_result(trigger_id, msg=sentence, status=True) return True else: logger.critical(error) update_result(trigger_id, msg=error, status=False) return False
def save_data(self, trigger_id, **data): """ let's save the data :param trigger_id: trigger ID from which to save data :param data: the data to check to be used and save :type trigger_id: int :type data: dict :return: the status of the save statement :rtype: boolean """ title, content = super(ServiceMastodon, self).save_data(trigger_id, **data) # check if we have a 'good' title if self.title_or_content(title): content = str("{title} {link}").format(title=title, link=data.get('link')) content += get_tags(Mastodon, trigger_id) # if not then use the content else: content += " " + data.get('link') + " " + get_tags(Mastodon, trigger_id) content = self.set_mastodon_content(content) us = UserService.objects.get(user=self.user, token=self.token, name='ServiceMastodon') try: toot_api = MastodonAPI(client_id=us.client_id, client_secret=us.client_secret, access_token=self.token, api_base_url=us.host) except ValueError as e: logger.error(e) status = False update_result(trigger_id, msg=e, status=status) media_ids = None try: if settings.DJANGO_TH['sharing_media']: # do we have a media in the content ? content, media = self.media_in_content(content) if media: # upload the media first media_ids = toot_api.media_post(media_file=media) media_ids = [media_ids] toot_api.status_post(content, media_ids=media_ids) status = True except Exception as inst: logger.critical("Mastodon ERR {}".format(inst)) status = False update_result(trigger_id, msg=inst, status=status) return status
def save_data(self, trigger_id, **data): """ let's save the data :param trigger_id: trigger ID from which to save data :param data: the data to check to be used and save :type trigger_id: int :type data: dict :return: the status of the save statement :rtype: boolean """ if self.token: title = self.set_title(data) body = self.set_content(data) # get the details of this trigger trigger = Github.objects.get(trigger_id=trigger_id) # check if it remains more than 1 access # then we can create an issue limit = self.gh.ratelimit_remaining if limit > 1: # repo goes to "owner" # project goes to "repository" r = self.gh.create_issue(trigger.repo, trigger.project, title, body) else: # rate limit reach logger.warn("Rate limit reached") update_result(trigger_id, msg="Rate limit reached", status=True) # put again in cache the data that could not be # published in Github yet cache.set('th_github_' + str(trigger_id), data, version=2) return True sentence = str('github {} created').format(r) logger.debug(sentence) status = True else: sentence = "no token or link provided for " \ "trigger ID {} ".format(trigger_id) logger.critical(sentence) update_result(trigger_id, msg=sentence, status=False) status = False return status
def save_data(self, trigger_id, **data): """ let's save the data :param trigger_id: trigger ID from which to save data :param data: the data to check to be used and save :type trigger_id: int :type data: dict :return: the status of the save statement :rtype: boolean """ if self.token: title = self.set_title(data) body = self.set_content(data) # get the details of this trigger trigger = Github.objects.get(trigger_id=trigger_id) # check if it remains more than 1 access # then we can create an issue limit = self.gh.ratelimit_remaining if limit > 1: # repo goes to "owner" # project goes to "repository" r = self.gh.create_issue(trigger.repo, trigger.project, title, body) else: # rate limit reach logger.warn("Rate limit reached") update_result(trigger_id, msg="Rate limit reached") # put again in cache the data that could not be # published in Github yet cache.set('th_github_' + str(trigger_id), data, version=2) return True sentence = str('github {} created').format(r) logger.debug(sentence) status = True else: sentence = "no token or link provided for " \ "trigger ID {} ".format(trigger_id) logger.critical(sentence) update_result(trigger_id, msg=sentence) status = False return status
def _create_entry(self, url, title, tags): """ Create an entry :param url: url to save :param title: title to set :param tags: tags to set :return: status """ try: self.pocket.add(url=url, title=title, tags=tags) sentence = str('pocket {} created').format(url) logger.debug(sentence) status = True except Exception as e: logger.critical(e) update_result(self.trigger_id, msg=e) status = False return status
def _create_entry(self, url, title, tags): """ Create an entry :param url: url to save :param title: title to set :param tags: tags to set :return: status """ try: self.pocket.add(url=url, title=title, tags=tags) sentence = str('pocket {} created').format(url) logger.debug(sentence) status = True except Exception as e: logger.critical(e) update_result(self.trigger_id, msg=e, status=False) status = False return status
def save_data(self, trigger_id, **data): """ get the data from the service :param trigger_id: id of the trigger :params data, dict :rtype: dict """ title, content = super(ServiceMastodon, self).save_data( trigger_id, **data) if self.title_or_content(title): content = str("{title} {link}").format( title=title, link=data.get('link')) content += self.get_tags(trigger_id) content = self.set_mastodon_content(content) us = UserService.objects.get(user=self.user, token=self.token, name='ServiceMastodon') try: toot_api = MastodonAPI( client_id=us.client_id, client_secret=us.client_secret, access_token=self.token, api_base_url=us.host ) except ValueError as e: logger.error(e) update_result(trigger_id, msg=e, status=False) try: toot_api.toot(content) status = True except Exception as inst: logger.critical("Mastodon ERR {}".format(inst)) update_result(trigger_id, msg=inst, status=False) status = False return status
def read_data(self, **kwargs): """ get the data from the service as the pocket service does not have any date in its API linked to the note, add the triggered date to the dict data thus the service will be triggered when data will be found :param kwargs: contain keyword args : trigger_id at least :type kwargs: dict :rtype: list """ self.date_triggered = arrow.get(kwargs.get('date_triggered')) self.trigger_id = kwargs.get('trigger_id') self.user = kwargs.get('user', '') responses = self._get_wall_data() data = [] try: json_data = responses.json() for d in json_data['_embedded']['items']: created_at = arrow.get(d.get('created_at')) date_triggered = arrow.get(self.date_triggered) if created_at > date_triggered: data.append({ 'title': d.get('title'), 'content': d.get('content') }) # digester self.send_digest_event(self.trigger_id, d.get('title'), link='') if len(data) > 0: cache.set('th_wallabag_' + str(self.trigger_id), data) except Exception as e: logger.critical(e) update_result(self.trigger_id, msg=e, status=False) return data
def read_data(self, **kwargs): """ get the data from the service :param kwargs: contain keyword args : trigger_id at least :type kwargs: dict :rtype: list """ trigger_id = kwargs.get('trigger_id') date_triggered = str(kwargs.get('date_triggered')).replace(' ', 'T') data = list() if self.token: # check if it remains more than 1 access # then we can create an issue if self.gh.ratelimit_remaining > 1: import pypandoc trigger = Github.objects.get(trigger_id=trigger_id) issues = self.gh.issues_on(trigger.repo, trigger.project, since=date_triggered) for issue in issues: content = pypandoc.convert(issue.body, 'md', format='html') content += self.gh_footer(trigger, issue) data.append({'title': issue.title, 'content': content}) # digester self.send_digest_event(trigger_id, issue.title, '') cache.set('th_github_' + str(trigger_id), data) else: # rate limit reach, do nothing right now logger.warning("Rate limit reached") update_result(trigger_id, msg="Rate limit reached", status=True) else: logger.critical("no token provided") update_result(trigger_id, msg="No token provided", status=True) return data
def _notestore(self, trigger_id, data): try: note_store = self.client.get_note_store() return note_store except EDAMSystemException as e: # rate limit reach have to wait 1 hour ! if e.errorCode == EDAMErrorCode.RATE_LIMIT_REACHED: sentence = "Rate limit reached {code}\n" \ "Retry your request in {msg} seconds\n" \ "Data set to cache again until" \ " limit reached".format(code=e.errorCode, msg=e.rateLimitDuration) logger.warning(sentence) cache.set('th_evernote_' + str(trigger_id), data, version=2) update_result(trigger_id, msg=sentence, status=True) return True else: logger.critical(e) update_result(trigger_id, msg=e, status=False) return False except Exception as e: logger.critical(e) update_result(trigger_id, msg=e, status=False) return False
def read_data(self, **kwargs): """ get the data from the service as the pocket service does not have any date in its API linked to the note, add the triggered date to the dict data thus the service will be triggered when data will be found :param kwargs: contain keyword args : trigger_id at least :type kwargs: dict :rtype: list """ self.date_triggered = arrow.get(kwargs.get('date_triggered')) self.trigger_id = kwargs.get('trigger_id') self.user = kwargs.get('user', '') responses = self._get_wall_data() data = [] try: json_data = responses.json() for d in json_data['_embedded']['items']: created_at = arrow.get(d.get('created_at')) date_triggered = arrow.get(self.date_triggered) if created_at > date_triggered: data.append({'title': d.get('title'), 'content': d.get('content')}) # digester self.send_digest_event(self.trigger_id, d.get('title'), link='') if len(data) > 0: cache.set('th_wallabag_' + str(self.trigger_id), data) except Exception as e: logger.critical(e) update_result(self.trigger_id, msg=e, status=False) return data
def _notestore(self, trigger_id, data): try: note_store = self.client.get_note_store() return note_store except EDAMSystemException as e: # rate limit reach have to wait 1 hour ! if e.errorCode == EDAMErrorCode.RATE_LIMIT_REACHED: sentence = "Rate limit reached {code}\n" \ "Retry your request in {msg} seconds\n" \ "Data set to cache again until" \ " limit reached".format(code=e.errorCode, msg=e.rateLimitDuration) logger.warn(sentence) cache.set('th_evernote_' + str(trigger_id), data, version=2) update_result(trigger_id, msg=sentence) return True else: logger.critical(e) update_result(trigger_id, msg=e) return False except Exception as e: logger.critical(e) update_result(trigger_id, msg=e) return False
def __init__(self, token=None, **kwargs): super(ServiceEvernote, self).__init__(token, **kwargs) self.sandbox = settings.TH_EVERNOTE_KEY['sandbox'] self.consumer_key = settings.TH_EVERNOTE_KEY['consumer_key'] self.consumer_secret = settings.TH_EVERNOTE_KEY['consumer_secret'] self.token = token self.service = 'ServiceEvernote' self.oauth = 'oauth1' kwargs = {'consumer_key': self.consumer_key, 'consumer_secret': self.consumer_secret, 'sandbox': self.sandbox} if self.token: kwargs = {'token': token, 'sandbox': self.sandbox} try: self.client = EvernoteClient(**kwargs) except EDAMUserException as e: us = UserService.objects.get(token=token) logger.error(e.msg, e.error_code) update_result(us.trigger_id, msg=e.msg, status=False)
def __init__(self, token=None, **kwargs): """ :param token: :param kwargs: """ super(ServiceTwitter, self).__init__(token, **kwargs) self.consumer_key = settings.TH_TWITTER_KEY['consumer_key'] self.consumer_secret = settings.TH_TWITTER_KEY['consumer_secret'] self.token = token self.oauth = 'oauth1' self.service = 'ServiceTwitter' if self.token is not None: token_key, token_secret = self.token.split('#TH#') try: self.twitter_api = Twython(self.consumer_key, self.consumer_secret, token_key, token_secret) except (TwythonAuthError, TwythonRateLimitError) as e: us = UserService.objects.get(token=token) logger.error(e.msg, e.error_code) update_result(us.trigger_id, msg=e.msg, status=False)
def _new_token(self, userservice_id, link, title, tags): """ create a new token :param userservice_id: id of the UserService :param link: string :param title: string :param tags: list :return: boolean """ new_token = self._refresh_token() logger.info('new token : {}'.format(new_token)) UserService.objects.filter(id=userservice_id).update(token=new_token) new_wall = self.new_wall(new_token) try: status = new_wall.post_entries(url=link, title=title, tags=tags) except Exception as e: logger.critical('could not create a post link ? : {}'.format(link)) logger.critical(e) update_result(self.trigger_id, msg=e) status = False return status
def _new_token(self, userservice_id, link, title, tags): """ create a new token :param userservice_id: id of the UserService :param link: string :param title: string :param tags: list :return: boolean """ new_token = self._refresh_token() logger.info('new token : {}'.format(new_token)) UserService.objects.filter(id=userservice_id).update(token=new_token) new_wall = self.new_wall(new_token) try: status = new_wall.post_entries(url=link, title=title, tags=tags) except Exception as e: logger.critical('could not create a post link ? : {}'.format(link)) logger.critical(e) update_result(self.trigger_id, msg=e, status=False) status = False return status
def read_data(self, **kwargs): """ get the data from the service :param kwargs: contain keyword args : trigger_id at least :type kwargs: dict :rtype: list """ trigger_id = kwargs.get('trigger_id') date_triggered = str(kwargs.get('date_triggered')).replace(' ', 'T') data = list() if self.token: # check if it remains more than 1 access # then we can create an issue if self.gh.ratelimit_remaining > 1: import pypandoc trigger = Github.objects.get(trigger_id=trigger_id) issues = self.gh.issues_on(trigger.repo, trigger.project, since=date_triggered) for issue in issues: content = pypandoc.convert(issue.body, 'md', format='html') content += self.gh_footer(trigger, issue) data.append({'title': issue.title, 'content': content}) cache.set('th_github_' + str(trigger_id), data) else: # rate limit reach, do nothing right now logger.warn("Rate limit reached") update_result(trigger_id, msg="Rate limit reached") else: logger.critical("no token provided") update_result(trigger_id, msg="No token provided") return data
def log_update(self, service, to_update, status, count): """ lets log everything at the end :param service: service object :param to_update: boolean to check if we have to update :param status: is everything worked fine ? :param count: number of data to update :type service: service object :type to_update: boolean :type status: boolean :type count: interger """ if to_update: if status: msg = "{} - {} new data".format(service, count) update_result(service.id, msg="OK") logger.info(msg) else: msg = "{} AN ERROR OCCURS ".format(service) update_result(service.id, msg=msg) logger.warn(msg) else: logger.debug("{} nothing new ".format(service))
def save_data(self, trigger_id, **data): """ let's save the data :param trigger_id: trigger ID from which to save data :param data: the data to check to be used and save :type trigger_id: int :type data: dict :return: the status of the save statement :rtype: boolean """ if data.get('link'): if len(data.get('link')) > 0: # get the pocket data of this trigger from th_pocket.models import Pocket as PocketModel trigger = PocketModel.objects.get(trigger_id=trigger_id) title = self.set_title(data) # convert htmlentities title = HtmlEntities(title).html_entity_decode status = self._create_entry(url=data.get('link'), title=title, tags=(trigger.tag.lower())) else: msg = "no link provided for trigger ID {}," \ " so we ignore it".format(trigger_id) logger.warning(msg) update_result(trigger_id, msg=msg, status=True) status = True else: msg = "no token provided for trigger ID {}".format(trigger_id) logger.critical(msg) update_result(trigger_id, msg=msg, status=False) status = False return status
def _create_entry(self, title, data, tags): """ create an entry :param title: string :param data: dict :param tags: list :return: boolean """ status = False if data.get('link') and len(data.get('link')) > 0: wall = self.wall() if wall is not False: try: wall.post_entries(url=data.get('link').encode(), title=title, tags=(tags.lower())) logger.debug('wallabag {} created'.format(data.get('link'))) status = True except Exception as e: logger.critical('issue with something else that a token link ? : {}'.format(data.get('link'))) logger.critical(e) update_result(self.trigger_id, msg=e, status=False) status = False else: status = True # we ignore empty link return status
def create_note(note_store, note, trigger_id, data): """ create a note :param note_store Evernote instance :param note :param trigger_id id of the trigger :param data to save or to put in cache :type note_store: Evernote Instance :type note: Note instance :type trigger_id: int :type data: dict :return boolean :rtype boolean """ # create the note ! try: created_note = note_store.createNote(note) sentence = str('note %s created') % created_note.guid logger.debug(sentence) return True except EDAMSystemException as e: if e.errorCode == EDAMErrorCode.RATE_LIMIT_REACHED: sentence = "Rate limit reached {code} " \ "Retry your request in {msg} seconds".format( code=e.errorCode, msg=e.rateLimitDuration) logger.warn(sentence) # put again in cache the data that could not be # published in Evernote yet cache.set('th_evernote_' + str(trigger_id), data, version=2) update_result(trigger_id, msg=sentence) return True else: logger.critical(e) return False except EDAMUserException as e: if e.errorCode == EDAMErrorCode.ENML_VALIDATION: sentence = "Data ignored due to validation" \ " error : err {code} {msg}".format( code=e.errorCode, msg=e.parameter) logger.warn(sentence) update_result(trigger_id, msg=sentence) return True except Exception as e: logger.critical(e) update_result(trigger_id, msg=e) return False
def create_note(note_store, note, trigger_id, data): """ create a note :param note_store Evernote instance :param note :param trigger_id id of the trigger :param data to save or to put in cache :type note_store: Evernote Instance :type note: Note instance :type trigger_id: int :type data: dict :return boolean :rtype boolean """ # create the note ! try: created_note = note_store.createNote(note) sentence = str('note %s created') % created_note.guid logger.debug(sentence) return True except EDAMSystemException as e: if e.errorCode == EDAMErrorCode.RATE_LIMIT_REACHED: sentence = "Rate limit reached {code} " \ "Retry your request in {msg} seconds".format( code=e.errorCode, msg=e.rateLimitDuration) logger.warn(sentence) # put again in cache the data that could not be # published in Evernote yet cache.set('th_evernote_' + str(trigger_id), data, version=2) update_result(trigger_id, msg=sentence, status=True) return True else: logger.critical(e) return False except EDAMUserException as e: if e.errorCode == EDAMErrorCode.ENML_VALIDATION: sentence = "Data ignored due to validation" \ " error : err {code} {msg}".format( code=e.errorCode, msg=e.parameter) logger.warn(sentence) update_result(trigger_id, msg=sentence, status=True) return True except Exception as e: logger.critical(e) update_result(trigger_id, msg=e, status=False) return False
def save_data(self, trigger_id, **data): """ let's save the data :param trigger_id: trigger ID from which to save data :param data: the data to check to be used and save :type trigger_id: int :type data: dict :return: the status of the save statement :rtype: boolean """ from th_trello.models import Trello data['output_format'] = 'md' title, content = super(ServiceTrello, self).save_data(trigger_id, **data) if len(title): # get the data of this trigger t = Trello.objects.get(trigger_id=trigger_id) # footer of the card footer = self.set_card_footer(data, t) content += footer # 1 - we need to search the list and board where we will # store the card so ... # 1.a search the board_id by its name # by retrieving all the boards boards = self.trello_instance.list_boards() board_id = '' my_list = '' for board in boards: if t.board_name == board.name.decode('utf-8'): board_id = board.id break if board_id: # 1.b search the list_id by its name my_board = self.trello_instance.get_board(board_id) lists = my_board.open_lists() # just get the open list ; not all the archive ones for list_in_board in lists: # search the name of the list we set in the form if t.list_name == list_in_board.name.decode('utf-8'): # return the (trello) list object # to be able to add card at step 3 my_list = my_board.get_list(list_in_board.id) break # we didnt find the list in that board # create it if my_list == '': my_list = my_board.add_list(t.list_name) else: # 2 if board_id and/or list_id does not exist, create it/them my_board = self.trello_instance.add_board(t.board_name) # add the list that didnt exists and # return a (trello) list object my_list = my_board.add_list(t.list_name) # 3 create the card # create the Trello card my_list.add_card(title, content) sentence = str('trello {} created').format(data['link']) logger.debug(sentence) status = True else: sentence = "no token or link provided for trigger ID " \ "{}".format(trigger_id) update_result(trigger_id, msg=sentence) status = False return status
def read_data(self, **kwargs): """ get the data from the service :param kwargs: contain keyword args : trigger_id at least :type kwargs: dict :rtype: list """ now = arrow.utcnow().to(settings.TIME_ZONE) my_toots = [] search = {} since_id = None trigger_id = kwargs['trigger_id'] date_triggered = arrow.get(kwargs['date_triggered']) def _get_toots(toot_api, toot_obj, search): """ get the toots from mastodon and return the filters to use : search and count :param toot_obj: from Mastodon model :param search: filter used for MastodonAPI.search() :type toot_obj: Object :type search: dict :return: count that limit the quantity of tweet to retrieve, the filter named search, the tweets :rtype: list """ # get the toots for a given tag statuses = '' count = 100 if toot_obj.tag: count = 100 search['count'] = count search['q'] = toot_obj.tag search['result_type'] = 'recent' # do a search statuses = toot_api.search(**search) # just return the content of te statuses array statuses = statuses['statuses'] # get the tweets from a given user elif toot_obj.tooter: count = 200 search['count'] = count search['username'] = toot_obj.tooter # call the user timeline and get his toot if toot_obj.fav: count = 20 search['count'] = 20 statuses = toot_api.favourites(max_id=max_id, since_id=since_id, limit=count) else: statuses = toot_api.account_statuses( id=toot_obj.tooter, max_id=max_id, since_id=since_id, limit=count) return count, search, statuses if self.token is not None: kw = {'app_label': 'th_mastodon', 'model_name': 'Mastodon', 'trigger_id': trigger_id} toot_obj = super(ServiceMastodon, self).read_data(**kw) us = UserService.objects.get(user=self.user, token=self.token, name='ServiceMastodon') try: toot_api = MastodonAPI( client_id=us.client_id, client_secret=us.client_secret, access_token=self.token, api_base_url=us.host ) except ValueError as e: logger.error(e) update_result(trigger_id, msg=e, status=False) if toot_obj.since_id is not None and toot_obj.since_id > 0: since_id = toot_obj.since_id search = {'since_id': toot_obj.since_id} # first request to Mastodon count, search, statuses = _get_toots(toot_api, toot_obj, search) if len(statuses) > 0: newest = None for status in statuses: if newest is None: newest = True # first query ; get the max id search['max_id'] = max_id = status['id'] since_id = search['since_id'] = statuses[-1]['id'] - 1 count, search, statuses = _get_toots(toot_api, toot_obj, search) newest = None if len(statuses) > 0: my_toots = [] for s in statuses: if newest is None: newest = True max_id = s['id'] - 1 toot_name = s['account']['username'] # get the text of the tweet + url to this one if toot_obj.fav: url = '{0}/api/v1/statuses/{1}'.format( self.api_base_url, s['id']) title = _('Toot Fav from @{}'.format(toot_name)) else: url = '{0}/api/v1/accounts/{1}/statuses'.format( self.api_base_url, s['id']) title = _('Toot from @{}'.format(toot_name)) # Wed Aug 29 17:12:58 +0000 2012 my_date = arrow.get(s['created_at'], 'ddd MMM DD HH:mm:ss Z YYYY') published = arrow.get(my_date).to(settings.TIME_ZONE) if date_triggered is not None and \ published is not None and \ now >= published >= date_triggered: my_toots.append({'title': title, 'content': s['content'], 'link': url, 'my_date': my_date}) # digester self.send_digest_event(trigger_id, title, url) cache.set('th_mastodon_' + str(trigger_id), my_toots) Mastodon.objects.filter(trigger_id=trigger_id).update( since_id=since_id, max_id=max_id, count=count) return my_toots
def read_data(self, **kwargs): """ get the data from the service :param kwargs: contain keyword args : trigger_id at least :type kwargs: dict :rtype: list """ now = arrow.utcnow().to(settings.TIME_ZONE) my_toots = [] search = {} since_id = None trigger_id = kwargs['trigger_id'] date_triggered = arrow.get(kwargs['date_triggered']) def _get_toots(toot_api, toot_obj, search): """ get the toots from mastodon and return the filters to use :param toot_obj: from Mastodon model :param search: filter used for MastodonAPI.search() :type toot_obj: Object ServiceMastodon :type search: dict :return: the filter named search, the toots :rtype: list """ max_id = 0 if toot_obj.max_id is None else toot_obj.max_id since_id = 0 if toot_obj.since_id is None else toot_obj.since_id # get the toots for a given tag statuses = '' if toot_obj.tag: search['q'] = toot_obj.tag # do a search statuses = toot_api.search(**search) # just return the content of te statuses array statuses = statuses['statuses'] # get the tweets from a given user elif toot_obj.tooter: search['id'] = toot_obj.tooter # call the user timeline and get his toot if toot_obj.fav: statuses = toot_api.favourites(max_id=max_id, since_id=since_id) else: user_id = toot_api.account_search(q=toot_obj.tooter) statuses = toot_api.account_statuses( id=user_id[0]['id'], max_id=toot_obj.max_id, since_id=toot_obj.since_id) return search, statuses if self.token is not None: kw = { 'app_label': 'th_mastodon', 'model_name': 'Mastodon', 'trigger_id': trigger_id } toot_obj = super(ServiceMastodon, self).read_data(**kw) us = UserService.objects.get(token=self.token, name='ServiceMastodon') try: toot_api = MastodonAPI( client_id=us.client_id, client_secret=us.client_secret, access_token=self.token, api_base_url=us.host, ) except ValueError as e: logger.error(e) update_result(trigger_id, msg=e, status=False) if toot_obj.since_id is not None and toot_obj.since_id > 0: since_id = toot_obj.since_id search = {'since_id': toot_obj.since_id} # first request to Mastodon search, statuses = _get_toots(toot_api, toot_obj, search) if len(statuses) > 0: newest = None for status in statuses: if newest is None: newest = True # first query ; get the max id search['max_id'] = max_id = status['id'] since_id = search['since_id'] = statuses[-1]['id'] - 1 search, statuses = _get_toots(toot_api, toot_obj, search) newest = None if len(statuses) > 0: my_toots = [] for s in statuses: if newest is None: newest = True max_id = s['id'] - 1 toot_name = s['account']['username'] # get the text of the tweet + url to this one title = _('Toot from <a href="{}">@{}</a>'.format( us.host, toot_name)) my_date = arrow.get(s['created_at']).to( settings.TIME_ZONE) published = arrow.get(my_date).to(settings.TIME_ZONE) if date_triggered is not None and \ published is not None and \ now >= published >= date_triggered: my_toots.append({ 'title': title, 'content': s['content'], 'link': s['url'], 'my_date': my_date }) # digester self.send_digest_event(trigger_id, title, s['url']) cache.set('th_mastodon_' + str(trigger_id), my_toots) Mastodon.objects.filter(trigger_id=trigger_id).update( since_id=since_id, max_id=max_id) return my_toots
def test_update_result(self): t = self.create_triggerservice() self.assertTrue(isinstance(t, TriggerService)) update_result(t.id, msg='a dummy result message', status=True)
def read_data(self, **kwargs): """ get the data from the service :param kwargs: contain keyword args : trigger_id at least :type kwargs: dict :rtype: list """ now = arrow.utcnow().to(settings.TIME_ZONE) my_toots = [] search = {} since_id = None trigger_id = kwargs['trigger_id'] date_triggered = arrow.get(kwargs['date_triggered']) def _get_toots(toot_api, toot_obj, search): """ get the toots from mastodon and return the filters to use :param toot_obj: from Mastodon model :param search: filter used for MastodonAPI.search() :type toot_obj: Object ServiceMastodon :type search: dict :return: the filter named search, the toots :rtype: list """ max_id = 0 if toot_obj.max_id is None else toot_obj.max_id since_id = 0 if toot_obj.since_id is None else toot_obj.since_id # get the toots for a given tag statuses = '' if toot_obj.tag: search['q'] = toot_obj.tag # do a search statuses = toot_api.search(**search) # just return the content of te statuses array statuses = statuses['statuses'] # get the tweets from a given user elif toot_obj.tooter: search['id'] = toot_obj.tooter # call the user timeline and get his toot if toot_obj.fav: statuses = toot_api.favourites(max_id=max_id, since_id=since_id) else: user_id = toot_api.account_search(q=toot_obj.tooter) statuses = toot_api.account_statuses( id=user_id[0]['id'], max_id=toot_obj.max_id, since_id=toot_obj.since_id) return search, statuses if self.token is not None: kw = {'app_label': 'th_mastodon', 'model_name': 'Mastodon', 'trigger_id': trigger_id} toot_obj = super(ServiceMastodon, self).read_data(**kw) us = UserService.objects.get(token=self.token, name='ServiceMastodon') try: toot_api = MastodonAPI( client_id=us.client_id, client_secret=us.client_secret, access_token=self.token, api_base_url=us.host, ) except ValueError as e: logger.error(e) update_result(trigger_id, msg=e, status=False) if toot_obj.since_id is not None and toot_obj.since_id > 0: since_id = toot_obj.since_id search = {'since_id': toot_obj.since_id} # first request to Mastodon search, statuses = _get_toots(toot_api, toot_obj, search) if len(statuses) > 0: newest = None for status in statuses: if newest is None: newest = True # first query ; get the max id search['max_id'] = max_id = status['id'] since_id = search['since_id'] = statuses[-1]['id'] - 1 search, statuses = _get_toots(toot_api, toot_obj, search) newest = None if len(statuses) > 0: my_toots = [] for s in statuses: if newest is None: newest = True max_id = s['id'] - 1 toot_name = s['account']['username'] # get the text of the tweet + url to this one title = _('Toot from <a href="{}">@{}</a>'. format(us.host, toot_name)) my_date = arrow.get(s['created_at']).to( settings.TIME_ZONE) published = arrow.get(my_date).to(settings.TIME_ZONE) if date_triggered is not None and \ published is not None and \ now >= published >= date_triggered: my_toots.append({'title': title, 'content': s['content'], 'link': s['url'], 'my_date': my_date}) # digester self.send_digest_event(trigger_id, title, s['url']) cache.set('th_mastodon_' + str(trigger_id), my_toots) Mastodon.objects.filter(trigger_id=trigger_id).update( since_id=since_id, max_id=max_id) return my_toots
def save_data(self, trigger_id, **data): """ let's save the data :param trigger_id: trigger ID from which to save data :param data: the data to check to be used and save :type trigger_id: int :type data: dict :return: the status of the save statement :rtype: boolean """ data['output_format'] = 'md' title, content = super(ServiceTrello, self).save_data(trigger_id, **data) if len(title): # get the data of this trigger t = Trello.objects.get(trigger_id=trigger_id) # footer of the card footer = self.set_card_footer(data, t) content += footer # 1 - we need to search the list and board where we will # store the card so ... # 1.a search the board_id by its name # by retrieving all the boards boards = self.trello_instance.list_boards() board_id = '' my_list = '' for board in boards: if t.board_name == board.name: board_id = board.id break if board_id: # 1.b search the list_id by its name my_board = self.trello_instance.get_board(board_id) lists = my_board.open_lists() # just get the open list ; not all the archive ones for list_in_board in lists: # search the name of the list we set in the form if t.list_name == list_in_board.name: # return the (trello) list object to be able to add card at step 3 my_list = my_board.get_list(list_in_board.id) break # we didnt find the list in that board -> create it if my_list == '': my_list = my_board.add_list(t.list_name) else: # 2 if board_id and/or list_id does not exist, create it/them my_board = self.trello_instance.add_board(t.board_name) # add the list that didn't exists and return a (trello) list object my_list = my_board.add_list(t.list_name) # 3 create the card my_list.add_card(title, content) logger.debug(str('trello {} created').format(data['link'])) status = True else: sentence = "no token or link provided for trigger ID {}".format(trigger_id) update_result(trigger_id, msg=sentence, status=False) status = False return status