Esempio n. 1
0
def main(argv):
    """ A simple example of using the the application scripting framework in a
    workbench.
    """

    # Create the GUI.
    gui = GUI()

    # Create the workbench.
    workbench = ExampleScript(state_location=gui.state_location)

    window = workbench.create_window(position=(300, 300), size=(400, 300))
    window.open()

    # Create some objects to edit.
    # FIXME v3: The need to explicitly set the style to its default value is
    # due to a bug in the implementation of Scriptable.
    label = Label(text="Label", style='normal')
    label2 = Label(text="Label2", style='normal')

    # Edit the objects.
    window.edit(label)
    window.edit(label2)

    # Start the GUI event loop.
    gui.start_event_loop()

    return
Esempio n. 2
0
    def _get_label_id(self, name):
        """
        Get or create a database label object, return the ID.
        """
        print('Label name to add:{}'.format(name), flush=True)
        db_session = worker.get_session()
        redis = worker.get_redis()
        label = db_session.query(Label).filter_by(name=name.lower().strip()).first()

        if label:
            print('Found Label :{}'.format(label.id), flush=True)
            return label.id
        else:
            label = Label(name=name.lower().strip())
            db_session.add(label)

            try:
                db_session.commit()
            except IntegrityError:
                db_session.rollback()
                raise
            except AssertionError:
                db_session.rollback()
                raise ValueError(
                    'Label "{}" contains non-alphanumeric character'
                    .format(name)
                )

            redis.publish('label', json.dumps(label.as_dict()))
            print('Created label :{}'.format(label.id), flush=True)
            return label.id
Esempio n. 3
0
def apply_action(mails):
    # we are going to do actions  according to this list
    # actions = ["Mark as read", "mark as unread", "Archive message", "Add label"]
    print("Enter your action: ")
    for i, value in enumerate(actions):
        print("For " + value.upper() + " Enter " + str(i))
    action_choice = int(raw_input("Enter your choice number: "))
    if action_choice == 0:
        # mark as read
        for x in mails:
            label_objects = session.query(Label).filter_by(mail_id=x.mail_id)
            for label in label_objects:
                if label.mail_label == "UNREAD":
                    session.delete(label)
                    session.commit()

    elif action_choice == 1:
        # mark as unread
        for x in mails:
            label_objects = session.query(Label).filter_by(mail_id=x.mail_id)
            applied = False
            for label in label_objects:
                if label.mail_label == "UNREAD":
                    applied = True
            if not applied:
                # if contrast label is not available, let's add this to file
                new_label_object = Label(mail_label="UNREAD",
                                         mail_id=x.mail_id)
                session.add(new_label_object)
                session.commit()
    elif action_choice == 2:
        # archieved message
        for x in mails:
            newArcheiveObj = Archive(mail_id=x.mail_id,
                                     mail_time=x.mail_time,
                                     mail_from=x.mail_from,
                                     mail_to=x.mail_to,
                                     subject=x.subject,
                                     text_of_body=x.text_of_body)
            session.add(newArcheiveObj)
            session.commit()
            # let's delete from mail file
            session.delete(x)
            session.commit()
    elif action_choice == 3:
        # add label
        label = raw_input("Enter your label name: ")
        for x in mails:
            newObj = Label(mail_label=label, mail_id=x.mail_id)
            session.add(newObj)
            session.commit()
    print("Congratulation, It has been applied. Aregorn")
Esempio n. 4
0
 def get(self, pageId):
     p = Paginator(Article.all(self.db), 5)
     page = p.page(int(pageId))
     isAdmin = self.isAdmin()
     label_list = Label.group(self.db)
     self.render('index.html', articles=page.object_list, label_list=label_list,
             isAdmin=isAdmin, page=page, home_title=options.home_title,
             user=options.user, photo=options.photo)
Esempio n. 5
0
    def post(self):
        title = self.get_argument('title')
        content_md = self.get_argument('content')
        pattern = r'\[[^\[\]]+\]'
        labels = re.findall(pattern, self.get_argument('labels'))
        content_html = markdown.markdown(content_md, ['codehilite'])

        try:
            article_id = Article.create(self.db, title, content_md, content_html)
            for label in labels:
                detail = label[1:-1].strip()
                Label.create(self.db, article_id, detail)

            self.redirect('/', permanent=True)
        except:
            error = "The post data invalid"
            self.render('error.html', error=error, home_title=options.home_title)
    def listLabelsInPage(self, page):
        """List all Labels available for a given pageId (can be also used to list Labels for any ContentEntityObject ID)

        @type page: string, or Page object
        @param page: page id, or Page object
        @rtype: list of Labels
        @return: Labels
        """
        return tuple(Label.create(labelDict, self._modelDataManager) for labelDict in self.pm_getSpaceManager().getLabelsById(self._unbox(page)))
    def listLabelsInSpace(self, space, maxLabelsToReturn = 20):
        """List all Labels available for a given Space

        @type space: string, or Space object
        @param space: space key, or Space object
        @param maxLabelsToReturn: maximum number of labels to return
        @rtype: list of Labels
        @return: Labels
        """
        return tuple(Label.create(labelDict, self._modelDataManager) for labelDict in self.pm_getSpaceManager().getLabelsInSpace(self._unbox(space), maxLabelsToReturn))
Esempio n. 8
0
def add_label(label_name, user_id, project_id):

    label = Label(label_name=label_name,
                  user_id=user_id,
                  project_id=project_id)

    db.session.add(label)
    db.session.commit()

    return label
Esempio n. 9
0
    def listLabelsInPage(self, page):
        """List all Labels available for a given pageId (can be also used to list Labels for any ContentEntityObject ID)

        @type page: string, or Page object
        @param page: page id, or Page object
        @rtype: list of Labels
        @return: Labels
        """
        return tuple(
            Label.create(labelDict, self._modelDataManager)
            for labelDict in self.pm_getSpaceManager().getLabelsById(
                self._unbox(page)))
Esempio n. 10
0
 def get(self, id):
     article = Article.get(self.db, id)
     if article is None:
         error = '404: Page Not Found'
         self.render('error.html', error=error, home_title=options.home_title)
     else:
         isAdmin = self.isAdmin()
         label_list = Label.group(self.db)
         blog_hostname = options.blog_hostname
         self.render('article.html', article=article, label_list=label_list,
                 blog_hostname=blog_hostname, isAdmin=isAdmin, home_title=options.home_title,
                 user=options.user, photo=options.photo)
Esempio n. 11
0
    def listLabelsInSpace(self, space, maxLabelsToReturn=20):
        """List all Labels available for a given Space

        @type space: string, or Space object
        @param space: space key, or Space object
        @param maxLabelsToReturn: maximum number of labels to return
        @rtype: list of Labels
        @return: Labels
        """
        return tuple(
            Label.create(labelDict, self._modelDataManager)
            for labelDict in self.pm_getSpaceManager().getLabelsInSpace(
                self._unbox(space), maxLabelsToReturn))
Esempio n. 12
0
def main(argv):
    """ A simple example of using the the undo framework in a workbench. """

    # Create the GUI.
    gui = GUI()

    # Create the workbench.
    workbench = ExampleUndo(state_location=gui.state_location)

    window = workbench.create_window(position=(300, 300), size=(400, 300))
    window.open()

    # Create some objects to edit.
    label = Label(text="Label")
    label2 = Label(text="Label2")

    # Edit the objects.
    window.edit(label)
    window.edit(label2)

    # Start the GUI event loop.
    gui.start_event_loop()
Esempio n. 13
0
    def get(self):
        key = self.get_argument('key', '').strip()
        pageId = int(self.get_argument('page', '1'))
        if len(key) == 0:
            results = Article.all(self.db)
        else:
            results = Search.all(self.db, key)
        p = Paginator(results, 5)
        page = p.page(pageId)
        isAdmin = self.isAdmin()
        label_list = Label.group(self.db)

        self.render('search.html', articles=page.object_list, label_list=label_list,
                isAdmin=isAdmin, page=page, home_title=options.home_title,
                user=options.user, photo=options.photo)
Esempio n. 14
0
def main():
    """Shows basic usage of the Gmail API.

    Creates a Gmail API service object and stores some message in database
    from the user's Gmail account.
    """
    credentials = get_credentials()
    http = credentials.authorize(httplib2.Http())
    service = discovery.build('gmail', 'v1', http=http)
    #let's get messages from google server
    try:
        response = service.users().messages().list(userId='me',
                                                   maxResults=500).execute()
        for x in response['messages']:
            mail_id = x['id']
            #let's get the message from server
            headers = ['X-Original-To', 'Message-ID', 'Date', 'Delivered-To']
            message = service.users().messages().get(userId='me',
                                                     id=mail_id,
                                                     format='full').execute()
            date_of_mail_long_ms = message['internalDate']
            #let's get all the labeles of this mail
            mail_labels = message["labelIds"]
            #let's get headers for subject, to, and from
            headers = message['payload']['headers']
            # we need to convert unicode to string so we can save them into database
            for x in headers:
                if x['name'].decode('unicode_escape') == "Subject":
                    mail_subject = unicodedata.normalize('NFKD',
                                                         x['value']).encode(
                                                             'ascii', 'ignore')
            for x in headers:
                if x['name'].decode('unicode_escape') == "From":
                    mail_from = unicodedata.normalize('NFKD',
                                                      x['value']).encode(
                                                          'ascii', 'ignore')
            for x in headers:
                if x['name'].decode('unicode_escape') == "To":
                    mail_to = unicodedata.normalize('NFKD', x['value']).encode(
                        'ascii', 'ignore')
            # Gmail api's sends different response, depending on the mail format, so
            #  we have to deal with different responses
            if message['payload']['body'].get('data'):
                mail_text = base64.urlsafe_b64decode(
                    message['payload']['body']['data'].encode("UTF8"))
            elif message['payload']['parts'][0]['body'].get('data'):
                mail_text = base64.urlsafe_b64decode(
                    message['payload']['parts'][0]['body']['data'].encode(
                        "UTF8"))
            else:
                messages = message['payload']['parts'][0]['parts']
                for x in messages:
                    if x['mimeType'].decode('unicode_escape') == 'text/plain':
                        mail_text = base64.urlsafe_b64decode(
                            x['body']['data'].encode("UTF8"))
            newMailObj = MailTable(
                mail_id=mail_id,
                mail_time=date_of_mail_long_ms,
                mail_from=mail_from,
                mail_to=mail_to,
                subject=mail_subject,
                text_of_body=mail_text.decode('unicode_escape'))
            session.add(newMailObj)
            session.commit()
            #now lets add label for this mail
            for x in mail_labels:
                label = unicodedata.normalize('NFKD',
                                              x).encode('ascii', 'ignore')
                new_Label_obj = Label(mail_label=label, mail_id=mail_id)
                session.add(new_Label_obj)
                session.commit()
    except errors.HttpError, error:
        print('An error occurred: %s' % error)
Esempio n. 15
0
    def put(self, id_):
        '''
        Update the profile identified by `id` with submitted data.
        The following attribute are modifiable:
           * is_interesting
           * lables

        **Example Request**

        .. sourcecode:: json

            {
                "is_interesting": true,
                "labels": [
                    {"name": "male"},
                    {"name": "british"},
                    ...
                ],
                ...
            }

        **Example Response**

        .. sourcecode:: json

            {
                "avatar_url": "https://quickpin/api/file/1",
                "avatar_thumb_url": "https://quickpin/api/file/2",
                "description": "A human being.",
                "follower_count": 71,
                "friend_count": 28,
                "id": 1,
                "is_stub": false,
                "is_interesting": true,
                "join_date": "2012-01-30T15:11:35",
                "labels": [
                    {
                        "id": 1,
                        "name": "male"
                    },
                    {
                        "id": 2,
                        "name": "british"
                    },
                ],
                "last_update": "2015-08-18T10:51:16",
                "location": "Washington, DC",
                "name": "John Doe",
                "post_count": 1666,
                "private": false,
                "site": "twitter",
                "site_name": "Twitter",
                "time_zone": "Central Time (US & Canada)",
                "upstream_id": "11009418",
                "url": "https://quickpin/api/profile/1",
                "username": "******",
                "usernames": [
                    {
                        "end_date": "2012-06-30T15:00:00",
                        "start_date": "2012-01-01T12:00:00",
                        "username": "******"
                    },
                    ...
                ]
            }

        :<header Content-Type: application/json
        :<header X-Auth: the client's auth token
        :>json bool is_interesting: whether profile is marked as interesting
        :>json list labels: whether profile is marked as interesting

        :>header Content-Type: application/json
        :>json str avatar_url: URL to the user's current avatar
        :>json str avatar_thumb_url: URL to a 32x32px thumbnail of the user's
            current avatar
        :>json str description: profile description
        :>json int follower_count: number of followers
        :>json int friend_count: number of friends (a.k.a. followees)
        :>json int id: unique identifier for profile
        :>json bool is_stub: indicates that this is a stub profile, e.g.
            related to another profile but has not been fully imported
        :>json bool is_interesting: indicates whether this profile has been
            marked as interesting. The value can be null.
        :>json str join_date: the date this profile joined its social network
            (ISO-8601)
        :>json list labels: list of labels for this profile
        :>json int label[n].id: the unique id for this label
        :>json str label[n].name: the label
        :>json str last_update: the last time that information about this
            profile was retrieved from the social media site (ISO-8601)
        :>json str location: geographic location provided by the user, as free
            text
        :>json str name: the full name provided by this user
        :>json int post_count: the number of posts made by this profile
        :>json bool private: true if this is a private account (i.e. not world-
            readable)
        :>json str site: machine-readable site name that this profile belongs to
        :>json str site_name: human-readable site name that this profile belongs
            to
        :>json str time_zone: the user's provided time zone as free text
        :>json str upstream_id: the user ID assigned by the social site
        :>json str url: URL endpoint for retriving more data about this profile
        :>json str username: the current username for this profile
        :>json list usernames: list of known usernames for this profile
        :>json str usernames[n].end_date: the last known date this username was
            used for this profile
        :>json str usernames[n].start_date: the first known date this username
            was used for this profile
        :>json str usernames[n].username: a username used for this profile

        :status 202: accepted for background processing
        :status 400: invalid request body
        :status 401: authentication required

        '''

        redis = worker.get_redis()

        # Get profile.
        id_ = get_int_arg('id_', id_)

        current_avatar_id = self._current_avatar_subquery()

        profile, avatar = g.db.query(Profile, Avatar) \
                              .outerjoin(Avatar, Avatar.id == current_avatar_id) \
                              .filter(Profile.id == id_).first()

        if profile is None:
            raise NotFound("Profile '%s' does not exist." % id_)

        request_json = request.get_json()

        # Validate put data and set attributes
        # Only 'is_interesting' and 'labels' are modifiable
        if 'is_interesting' in request_json:
            if isinstance(request_json['is_interesting'], bool):
                profile.is_interesting = request_json['is_interesting']
            elif request_json['is_interesting'] is None:
                profile.is_interesting = None
            else:
                raise BadRequest("Attribute 'is_interesting' is type boolean,"
                                 " or can be set as null")

        # labels expects the string 'name' rather than id, to avoid the need to
        # create labels before adding them.
        if 'labels' in request_json:
            labels = []
            if isinstance(request_json['labels'], list):
                for label_json in request_json['labels']:
                    if 'name' in label_json:
                        label = g.db.query(Label) \
                                    .filter(Label.name==label_json['name']) \
                                    .first()
                        if label is None:
                            try:
                                label = Label(
                                    name=label_json['name'].lower().strip()
                                )

                                g.db.add(label)
                                g.db.flush()

                                redis.publish(
                                    'label',
                                    json.dumps(label.as_dict())
                                )
                            except IntegrityError:
                                g.db.rollback()
                                raise BadRequest('Label could not be saved')
                            except AssertionError:
                                g.db.rollback()
                                raise BadRequest(
                                    '"{}" contains non-alphanumeric character'
                                    .format(
                                        label_json['name']
                                    )
                                )

                        labels.append(label)
                    else:
                        raise BadRequest("Label 'name' is required")

                profile.labels = labels
            else:
                raise BadRequest("'labels' must be a list")


        response = profile.as_dict()
        response['url'] = url_for('ProfileView:get', id_=profile.id)

        # Save the profile
        try:
            g.db.commit()
            redis.publish('profile_update', json.dumps(profile.as_dict()))
        except DBAPIError as e:
            g.db.rollback()
            raise BadRequest('Profile could not be saved')

        # Create usernames list.
        usernames = list()

        for username in profile.usernames:
            if username.end_date is not None:
                end_date = username.end_date.isoformat()
            else:
                end_date = None

            if username.start_date is not None:
                start_date = username.start_date.isoformat()
            else:
                start_date = None

            usernames.append({
                'end_date': end_date,
                'username': username.username,
                'start_date': start_date,
            })

        response['usernames'] = usernames

        # Create avatar attributes.
        if avatar is not None:
            response['avatar_url'] = url_for(
                'FileView:get',
                id_=avatar.file.id
            )
            response['avatar_thumb_url'] = url_for(
                'FileView:get',
                id_=avatar.thumb_file.id
            )
        else:
            response['avatar_url'] = url_for(
                'static',
                filename='img/default_user.png'
            )
            response['avatar_thumb_url'] = url_for(
                'static',
                filename='img/default_user_thumb.png'
            )

        # Send response.
        return jsonify(**response)
Esempio n. 16
0
    def put(self, id_):
        '''
        Update the profile identified by `id` with submitted data.

        The following attributes are modifiable:

           * is_interesting
           * labels
           * score

        **Example Request**

        .. sourcecode:: json

            {
                "is_interesting": true,
                "labels": [
                    {"name": "male"},
                    {"name": "british"},
                    ...
                ],
                "score": 2323.0,
                ...
            }

        **Example Response**

        .. sourcecode:: json

            {
                "avatar_url": "https://quickpin/api/file/1",
                "avatar_thumb_url": "https://quickpin/api/file/2",
                "description": "A human being.",
                "follower_count": 71,
                "friend_count": 28,
                "id": 1,
                "is_stub": false,
                "is_interesting": true,
                "join_date": "2012-01-30T15:11:35",
                "labels": [
                    {
                        "id": 1,
                        "name": "male"
                    },
                    {
                        "id": 2,
                        "name": "british"
                    },
                ],
                "last_update": "2015-08-18T10:51:16",
                "location": "Washington, DC",
                "name": "John Doe",
                "post_count": 1666,
                "private": false,
                "score": "-2.0621606863",
                "site": "twitter",
                "site_name": "Twitter",
                "time_zone": "Central Time (US & Canada)",
                "upstream_id": "11009418",
                "url": "https://quickpin/api/profile/1",
                "username": "******",
                "usernames": [
                    {
                        "end_date": "2012-06-30T15:00:00",
                        "start_date": "2012-01-01T12:00:00",
                        "username": "******"
                    },
                    ...
                ]
            }

        :<header Content-Type: application/json
        :<header X-Auth: the client's auth token
        :<json bool is_interesting: whether profile is marked as interesting
        :<json list labels: list of profile labels
        :<json float score: profile score

        :>header Content-Type: application/json
        :>json str avatar_url: URL to the user's current avatar
        :>json str avatar_thumb_url: URL to a 32x32px thumbnail of the user's
            current avatar
        :>json str description: profile description
        :>json int follower_count: number of followers
        :>json int friend_count: number of friends (a.k.a. followees)
        :>json int id: unique identifier for profile
        :>json bool is_stub: indicates that this is a stub profile, e.g.
            related to another profile but has not been fully imported
        :>json bool is_interesting: indicates whether this profile has been
            marked as interesting. The value can be null.
        :>json str join_date: the date this profile joined its social network
            (ISO-8601)
        :>json list labels: list of labels for this profile
        :>json int label[n].id: the unique id for this label
        :>json str label[n].name: the label
        :>json str last_update: the last time that information about this
            profile was retrieved from the social media site (ISO-8601)
        :>json str location: geographic location provided by the user, as free
            text
        :>json str name: the full name provided by this user
        :>json int note[n].id: the unique id for this note
        :>json int note[n].category: the user-defined category of this note
        :>json int note[n].body: the user-defined text-body of this note
        :>json int post_count: the number of posts made by this profile
        :>json bool private: true if this is a private account (i.e. not world-
            readable)
        :>json str score: user-defined score for this profile. Can be null.
        :>json str site: machine-readable site name that this profile belongs to
        :>json str site_name: human-readable site name that this profile belongs
            to
        :>json str time_zone: the user's provided time zone as free text
        :>json str upstream_id: the user ID assigned by the social site
        :>json str url: URL endpoint for retriving more data about this profile
        :>json str username: the current username for this profile
        :>json list usernames: list of known usernames for this profile
        :>json str usernames[n].end_date: the last known date this username was
            used for this profile
        :>json str usernames[n].start_date: the first known date this username
            was used for this profile
        :>json str usernames[n].username: a username used for this profile

        :status 202: accepted for background processing
        :status 400: invalid request body
        :status 401: authentication required
        '''

        redis = worker.get_redis()

        # Get profile.
        id_ = get_int_arg('id_', id_)

        profile, avatar = g.db.query(Profile, Avatar) \
                              .outerjoin(Profile.current_avatar) \
                              .filter(Profile.id == id_).first()

        if profile is None:
            raise NotFound("Profile '%s' does not exist." % id_)

        request_json = request.get_json()

        # Validate put data and set attributes
        # Only 'is_interesting', 'score', and 'labels' are modifiable
        if 'is_interesting' in request_json:
            if isinstance(request_json['is_interesting'], bool):
                profile.is_interesting = request_json['is_interesting']
            elif request_json['is_interesting'] is None:
                profile.is_interesting = None
            else:
                raise BadRequest("'is_interesting' is a boolean (true or false.")

        if 'score' in request_json:
            if request_json['score'] is None:
                profile.score = None
            else:
                try:
                    profile.score = float(request_json['score'])
                except:
                    raise BadRequest("'score' must be a decimal number.")


        # labels expects the string 'name' rather than id, to avoid the need to
        # create labels before adding them.
        if 'labels' in request_json:
            labels = []
            if isinstance(request_json['labels'], list):
                for label_json in request_json['labels']:
                    if 'name' in label_json:
                        label = g.db.query(Label) \
                                    .filter(Label.name==label_json['name']) \
                                    .first()
                        if label is None:
                            try:
                                label = Label(
                                    name=label_json['name'].lower().strip()
                                )

                                g.db.add(label)
                                g.db.flush()

                                redis.publish(
                                    'label',
                                    json.dumps(label.as_dict())
                                )
                            except IntegrityError:
                                g.db.rollback()
                                raise BadRequest('Label could not be saved')
                            except AssertionError:
                                g.db.rollback()
                                raise BadRequest(
                                    '"{}" contains non-alphanumeric character'
                                    .format(
                                        label_json['name']
                                    )
                                )

                        labels.append(label)
                    else:
                        raise BadRequest("Label 'name' is required")

                profile.labels = labels
            else:
                raise BadRequest("'labels' must be a list")

        response = profile.as_dict()
        response['url'] = url_for('ProfileView:get', id_=profile.id)

        # Save the profile
        try:
            g.db.commit()
            redis.publish('profile', json.dumps(profile.as_dict()))
        except DBAPIError as e:
            g.db.rollback()
            raise BadRequest('Profile could not be saved')

        # Create usernames list.
        usernames = list()

        for username in profile.usernames:
            if username.end_date is not None:
                end_date = username.end_date.isoformat()
            else:
                end_date = None

            if username.start_date is not None:
                start_date = username.start_date.isoformat()
            else:
                start_date = None

            usernames.append({
                'end_date': end_date,
                'username': username.username,
                'start_date': start_date,
            })

        response['usernames'] = usernames

        # Create avatar attributes.
        if avatar is not None:
            response['avatar_url'] = url_for(
                'FileView:get',
                id_=avatar.file.id
            )
            response['avatar_thumb_url'] = url_for(
                'FileView:get',
                id_=avatar.thumb_file.id
            )
        else:
            response['avatar_url'] = url_for(
                'static',
                filename='img/default_user.png'
            )
            response['avatar_thumb_url'] = url_for(
                'static',
                filename='img/default_user_thumb.png'
            )

        # Send response.
        return jsonify(**response)
    def execute(self, app):
        with app.app_context():
            users = User.query.filter_by(googleEmailAccess=True,
                                         wunderListAccess=True).all()

            for user in users:

                app.logger.debug("Scanning transactions for %s", user.email)

                #Get google credentials of user
                try:
                    googlecredentials = TransactionScheduler.getGoogleCredentials(
                        app, user)
                except Exception as e:
                    app.logger.error(
                        "Error getting Google credentials of user " +
                        user.email)
                    user.googleEmailAccess = False
                    user.save()
                    continue

                #Create Gmail object
                gmail = GMail(googlecredentials, user.email)

                supportedLabels = set(["Bank/SC"])

                userLabels = Label.query.filter_by(user_id=user.id).all()
                userLabelsName = set(map(lambda u: u.name, userLabels))

                notAddedLabels = supportedLabels - userLabelsName

                if len(notAddedLabels) > 0:

                    #Fetch labels from remote
                    remoteLabels = gmail.getLabels()

                    for label in remoteLabels:

                        if label['name'] in notAddedLabels:

                            newLabel = Label()
                            newLabel.name = label['name']
                            newLabel.label_id = label['id']
                            user.labels.append(newLabel)
                            user.save()

                    userLabels = Label.query.filter_by(user_id=user.id).all()

                for label in userLabels:

                    messageIds = gmail.getMessageIdsByLabel([label.label_id])
                    lastReadMessage = label.last_message_read if label.last_message_read else -1
                    for messageId in messageIds:
                        if messageId["id"] == lastReadMessage:
                            break
                        #Set last read message to top of the list
                        label.last_message_read = messageIds[0]["id"]

                        message = gmail.getMessage(messageId["id"])

                        if label.name == "Bank/SC":

                            curr, amount, place = self.handleSCMessages(
                                message)

                            if curr is not None:

                                self.createReminder(app, user,
                                                    curr + " " + amount, place)

                    label.save()

                app.logger.debug("Scanning transactions completed for %s",
                                 user.email)
 def add_label(self,
               text: str,
               pos: tp.Tuple[int, int],
               colour: str = "red"):
     self._labels.append(Label(text, pos, colour))