示例#1
0
    def get(self, request, *args, **kwargs):
        if 'task_id' in kwargs:
            task = get_task_by_id(kwargs['task_id'])
        else:
            return Http404('Wrong reqest')

        task = get_task_by_id(kwargs['task_id'])
        if not task:
            return Http404('Task not found')

        task.is_completed = True
        task.save()

        try:
            client = TrelloClient(
                api_key=request.user.profile.trello_api_key,
                api_secret=request.user.profile.trello_api_secret)
            desc = client.get_board(task.trello_id_board)
        except:
            return Http404('Wrong reqest')

        # или тут -2 будет
        right_list = desc.list_lists()[-2]
        card = client.get_card(task.trello_id_card)
        card.change_list(right_list.id)

        return HttpResponse('OK')
示例#2
0
def uncomplete_task_trello(task, owner):
    prof = Profile.objects.get(user=owner) #получаем профайл пользователя
    key = prof.trello_key #из профайла достаем ключ
    token = prof.trello_token
    client = TrelloClient(api_key=key, api_secret=token)
    card = client.get_card(task.trello_id)
    board = client.get_board(task.trello_board_id)
    card.change_list(board.list_lists()[0].id)
 def delete_from_trello(self):
     api_key = settings.TRELLO_KEY
     secret = settings.TRELLO_SECRET
     token = settings.TRELLO_TOKEN
     id = self.trello_id
     c = TrelloClient(api_key, secret, token)
     card = c.get_card(id)
     try:
         card.set_closed(True)
     except Exception:
         pass
 def delete_from_trello(self):
     api_key = settings.TRELLO_KEY
     secret = settings.TRELLO_SECRET
     token = settings.TRELLO_TOKEN
     id = self.trello_id
     c = TrelloClient(api_key, secret, token)
     card = c.get_card(id)
     try:
         card.set_closed(True)
     except Exception:
         pass
示例#5
0
def delete_trello_card(trello_card_id):
    """
    Delete (forever) a Trello Card by ID

    :trello_card_id: Trello card ID
    """
    trello_client = TrelloClient(api_key=trello_api_key, api_secret=trello_api_secret, token=trello_token, token_secret=trello_token_secret)
    try:
        trello_card = trello_client.get_card(trello_card_id)
        trello_card.delete()
    except Exception:
        print('Cannot find Trello card with ID {0} deleted in Task Warrior. Maybe you deleted it in Trello too.'.format(trello_card_id))
示例#6
0
def main():
    """Main application method."""
    # Check for keys
    trello_key = environ.get('TRELLO_KEY')
    trello_token = environ.get('TRELLO_TOKEN')
    if not trello_key:
        print("ERROR: Missing environment variable TRELLO_KEY")
        return
    if not trello_token:
        print("ERROR: Missing environment variable TRELLO_TOKEN")
        return

    # Get arguments
    args = ask_arguments()

    # Create client
    print("Connecting to Trello")
    client = TrelloClient(api_key=trello_key, token=trello_token)

    folder = basename(args.folder)
    files = [f for f in listdir(args.folder) if isfile(join(args.folder, f))]
    print("Creating checklist for %d files" % len(files))
    client.get_card(args.card).add_checklist(folder, sorted(files))
示例#7
0
def complete_task(request, uid):
    t = TodoItem.objects.get(id=uid)
    t.is_completed = True
    t.save()
    if t.TRELLO_ID:
        key = request.user.profile.key
        secret = request.user.profile.token
        client = TrelloClient(key, secret)
        card = client.get_card(t.TRELLO_ID)
        board_id = card.board_id
        board = client.get_board(board_id)
        card.change_list(board.list_lists()[-1].id)
    messages.success(request, "Задача выполнена")
    return HttpResponse("OK")
示例#8
0
def delete_trello_card(trello_card_id):
    """
    Delete (forever) a Trello Card by ID

    :trello_card_id: Trello card ID
    """
    trello_client = TrelloClient(api_key=trello_api_key,
                                 api_secret=trello_api_secret,
                                 token=trello_token,
                                 token_secret=trello_token_secret)
    try:
        trello_card = trello_client.get_card(trello_card_id)
        trello_card.delete()
    except Exception:
        print(
            'Cannot find Trello card with ID {0} deleted in Task Warrior. Maybe you deleted it in Trello too.'
            .format(trello_card_id))
示例#9
0
文件: views.py 项目: vialekis/todoapp
def complete_task(request, uid):
    print("Enter")
    t = TodoItem.objects.get(id=uid)
    t.is_completed = True
    t.save()
    print("Save")
    # Trello
    print(t.id_trello)
    client = TrelloClient(api_key=request.user.profile.api_key,
                          api_secret=request.user.profile.api_secret)
    print(client)
    card = client.get_card(t.id_trello)
    print(card.id, card.idList, card.idBoard)
    # Board = client.get_board(card.idBoard)
    list = client.get_board(card.idBoard).list_lists()[-1]
    # list = client.get_board(card.idBoard)
    card.change_list(list.id)

    # card.change_list(untitled_board.list_lists()[1].id)

    return HttpResponse("OK")
示例#10
0
def lambda_handler(event, context):
    # Trello Client
    client = TrelloClient(api_key=os.environ["trello_api_key"],
                          api_secret=os.environ["trello_token"])

    try:
        # イベント管理クラス
        tr_event = te.TrelloEvent(event)
        # デバッグ用
        target_card = client.get_card(tr_event.get_card_id())
        # Scrumに必要な作業を管理
        scrum = sc.Scrum(client, tr_event)
        scrum.stamping(True)
        scrum.request_slack()
        scrum.move_story_to_task()

    except Exception as e:
        # デバッグ用
        t, v, tb = sys.exc_info()
        target_card.comment(f"{e}\n{'>'.join(traceback.format_tb(tb))}")
        return return_context(f"{e}\n{traceback.format_tb(tb)}")

    return return_context("Succeed: Normal Exit")
示例#11
0
class TrelloToPivotal:
    def __init__(self, project_id, board_id, api_key, trello_token,
                 pivotal_token, redis_client):
        self.trello_board = board_id
        self.pivotal_project = project_id
        self.trello_key = api_key
        self.trello_token = trello_token
        self.pivotal_token = pivotal_token
        self.trello_client = TrelloClient(
            api_key=self.trello_key,
            token=self.trello_token,
        )
        self.redis_client = redis_client

    def call_trello_api(self):
        """
        This function call trello api and return list of dictionaries, where each dictionary
        is story from board
        :return:
        """
        params = {'key': self.trello_key, 'token': self.trello_token}
        response = requests.get(
            'https://api.trello.com/1/boards/{}/cards'.format(
                self.trello_board),
            params=params)
        return response.json()

    def create_card(self, list_name, card_title):
        payload = {'name': card_title, 'current_state': list_name}
        headers = {
            'X-TrackerToken': self.pivotal_token,
            'Content-type': 'application/json',
            'Accept': 'application/json'
        }
        response = requests.post(
            'https://www.pivotaltracker.com/services/v5/projects/{}/stories'.
            format(self.pivotal_project),
            data=json.dumps(payload),
            headers=headers).json()
        return response['id']

    def delete_card(self, pivotal_story_id):
        headers = {
            'X-TrackerToken': self.pivotal_token,
            'Content-type': 'application/json',
            'Accept': 'application/json'
        }
        response = requests.delete(
            'https://www.pivotaltracker.com/services/v5/projects/{}/stories/{}'
            ''.format(self.pivotal_project, int(pivotal_story_id)),
            headers=headers)
        logger.info('Pivotal story with {} id is deleted\n{}'.format(
            pivotal_story_id, response))

    def update_card(self, pivotal_story_id, action):
        data = action['data']
        old = data['old']
        card = data['card']
        old_field = list(old.items())[0][0]
        payload = {}
        if old_field == 'name':  # card-name.json
            new_name = card['name']
            payload = {'name': new_name}
        if old_field == 'idList':  # card-list.json
            new_state = data['listAfter']['name']
            payload = {'current_state': new_state}
            if new_state == 'started' or new_state == 'finished' or new_state == 'delivered':
                due_date = self.trello_client.get_card(
                    card_id=card['id']).due_date
                now = datetime.datetime.now()
                if due_date.day - now.day == 0:
                    payload.update({"estimate": 0})
                if due_date.day - now.day == 1:
                    payload.update({"estimate": 0})
                if due_date.day - now.day == 2:
                    payload.update({"estimate": 1})
                if due_date.day - now.day == 3:
                    payload.update({"estimate": 2})
                if due_date.day - now.day == 4:
                    payload.update({"estimate": 2})
                if due_date.day - now.day > 4:
                    payload.update({"estimate": 3})
        if old_field == 'desc':  # card-desc.json
            new_desc = card['desc']
            payload = {'description': new_desc}
        if old_field == 'due':  # card-due.json
            payload = {}
            trello = self.trello_client
            card_id = card['id']
            card_t = trello.get_card(card_id)
            due = card_t.due_date
            if not due:
                payload = {'estimate': 0}
            else:
                due_date = due.day
                now = datetime.datetime.now()
                if due_date - now.day == 0:
                    payload = {'estimate': 0}
                if due_date - now.day == 1:
                    payload = {'estimate': 0}
                if due_date - now.day == 2:
                    payload = {'estimate': 1}
                if due_date - now.day == 3:
                    payload = {"estimate": 2}
                if due_date - now.day == 4:
                    payload = {'estimate': 2}
                if due_date - now.day > 4:
                    payload = {'estimate': 3}
        if old_field == 'closed':  # card-archive.json
            self.delete_card(pivotal_story_id)
            return
        headers = {
            'X-TrackerToken': self.pivotal_token,
            'Content-type': 'application/json',
            'Accept': 'application/json'
        }
        response = requests.put(
            'https://www.pivotaltracker.com/services/v5/projects/{}/stories/{}'
            ''.format(self.pivotal_project, int(pivotal_story_id)),
            data=json.dumps(payload),
            headers=headers).json()

        logger.info('Pivotal story with {} id is updated\n{}'.format(
            pivotal_story_id, response))

    def add_label_to_card(self, pivotal_story_id, card_id):
        labels = self.trello_client.get_card(card_id=card_id).labels
        label_names = [i.name for i in labels]
        payload = {'labels': label_names}
        headers = {
            'X-TrackerToken': self.pivotal_token,
            'Content-type': 'application/json',
            'Accept': 'application/json'
        }
        response = requests.put(
            'https://www.pivotaltracker.com/services/v5/projects/{}/stories/{}'
            ''.format(self.pivotal_project, int(pivotal_story_id)),
            data=json.dumps(payload),
            headers=headers).json()
        logger.info('Pivotal story label with {} id is updated\n{}'.format(
            pivotal_story_id, response))

    def update_label(self, pivotal_story_id, action):
        data = action['data']
        old = data['old']
        card = data['card']
        old_field = list(old.items())[0][0]
        if old_field == 'name':  # card-name.json
            labels = self.trello_client.get_card(card_id=card['id']).labels
            label_names = [i.name for i in labels]
            payload = {'labels': label_names}
            headers = {
                'X-TrackerToken': self.pivotal_token,
                'Content-type': 'application/json',
                'Accept': 'application/json'
            }
            response = requests.put(
                'https://www.pivotaltracker.com/services/v5/projects/{}/stories/{}'
                ''.format(self.pivotal_project, int(pivotal_story_id)),
                data=payload,
                headers=headers).json()
        logger.info('Pivotal story label with {} id is updated\n{}'.format(
            pivotal_story_id, response or 'color'))

    def initialize_board(self):
        trello_stories = self.call_trello_api()
        params = {'key': self.trello_key, 'token': self.trello_token}
        id_couples = []
        for card in trello_stories:
            if not self.redis_client.get(card['id'] + "_created"):
                name = card['name']
                description = card['desc']
                label = [i['name'] for i in card['labels']]
                status = requests.get('https://trello.com/1/lists/{}'.format(
                    card['idList']),
                                      params=params)
                list_name = status.json()['name']
                due = card['due']
                payload = {
                    'name': name,
                    'description': description,
                    'labels': label,
                    'current_state': list_name
                }
                if due:
                    due_date = datetime.datetime.strptime(
                        due, "%Y-%m-%dT%H:%M:%S.%fZ").day
                    now = datetime.datetime.now()
                    if due_date - now.day == 0:
                        payload.update({'estimate': 0})
                    if due_date - now.day == 1:
                        payload.update({'estimate': 0})
                    if due_date - now.day == 2:
                        payload.update({'estimate': 1})
                    if due_date - now.day == 3:
                        payload.update({'estimate': 2})
                    if due_date - now.day == 4:
                        payload.update({'estimate': 2})
                    if due_date - now.day > 4:
                        payload.update({'estimate': 3})
                headers = {
                    'X-TrackerToken': self.pivotal_token,
                    'Content-type': 'application/json',
                    'Accept': 'application/json'
                }
                response = requests.post(
                    'https://www.pivotaltracker.com/services/v5/projects/{}/stories'
                    .format(self.pivotal_project),
                    data=json.dumps(payload),
                    headers=headers).json()
                id_couples.append((card['id'], response['id']))
                self.redis_client.set(card['id'] + "_created", card['name'])
            else:
                logger.warn(
                    f'Card with id: "{card["id"] + "_created"}" and name:'
                    f' "{self.redis_client.get(card["id"] + "_created")}" already exists'
                )
        return id_couples
class TrelloHelper:
    def __init__(self,
                 api_key,
                 token,
                 board_name,
                 exclude_lanes=[],
                 debug=False):
        self.client = TrelloClient(api_key=api_key, token=token)
        self.boards = self.client.list_boards()
        self.dbg = debug
        for b in self.boards:
            if (b.name == board_name):
                self.board = b
        assert hasattr(
            self,
            'board'), "Unable to set board, \"%s\" not found" % board_name
        self.members = self.board.all_members()
        self.labels = self.board.get_labels()
        self.lanes = self.board.list_lists()
        self.exclude_lanes = exclude_lanes

    def set_lane(self, name):
        for l in self.lanes:
            if (l.name == name):
                self.debug("Setting lane: %s" % name)
                self.lane = l
        assert hasattr(self,
                       'lane'), "Unable to set lane, \"%s\" not found" % name

    def set_card(self, card_id):
        self.card = self.client.get_card(card_id)

    def list_boards(self):
        self.debug("Listing Boards")
        for b in self.boards:
            self.debug("%s %s %s" % (b.id, b.url, b.name))
            yield b

    def list_lanes(self):
        self.debug("Listing Lanes")
        for l in self.lanes:
            self.debug("%s %s" % (l.id, l.name))
            yield l

    def list_cards(self):
        self.debug("Listing Cards")
        for c in self.lane.list_cards():
            self.debug("%s %s %s" % (c.id, c.url, c.name))
            yield c

    def list_members(self):
        if hasattr(self, 'card'):
            self.debug("Listing Members of %s card" % self.card.name)
            for cm in self.card.member_id:
                for bm in self.members:
                    if cm == bm.id:
                        self.debug("%s %s" % (bm.id, bm.username))
                        yield bm
        else:
            self.debug("Listing Members of %s board" % self.board.name)
            for bm in self.members:
                self.debug("%s %s" % (bm.id, bm.username))
                yield bm

    def list_labels(self):
        if hasattr(self, 'card'):
            self.debug("Listing Labels for card: %s" % self.card.name)
            for cl in self.card.labels:
                self.debug("%s %s" % (cl.id, cl.name))
                yield cl
        else:
            self.debug("Listing Labels for board: %s" % self.board.name)
            for bl in self.labels:
                self.debug("%s %s" % (bl.id, bl.name))
                yield bl

    def list_checklists(self):
        if hasattr(self, 'card'):
            self.debug("Listing checklists for card: %s" % self.card.name)
            for cl in self.card.checklists:
                self.debug("%s %s" % (cl.id, cl.name))
                for i in cl.items:
                    self.debug("  %s %s %s" %
                               (i['id'], i['checked'], i['name']))
                yield cl

    def create_card(self, name, desc=None):
        self.debug("Create card %s\n%s" % (name, desc))
        card = self.lane.add_card(name, desc)
        return card.id

    def create_checklist(self, title, items):
        if hasattr(self, 'card'):
            self.debug("Adding checklist %s for card %s, items are %s" %
                       (title, self.card.name, items))
            self.card.add_checklist(title, items)

    def find_cards(self, search_text, include_closed=False):
        self.debug("""Excluding Lanes: %s""" % self.exclude_lanes)
        for l in self.lanes:
            if not l.name in self.exclude_lanes:
                #self.debug("""Searching for cards matching "%s" in lane "%s" """ % (search_text, l.name))
                for c in l.list_cards():
                    #self.debug("""    search for: "%s" in name: "%s" desc: "%s..." """ % (search_text, c.name, c.desc[0:30]))
                    if c.name.find(search_text) >= 0 or c.desc.find(
                            search_text) >= 0:
                        if include_closed or c.closed == include_closed:
                            yield c

    def assign_card(self, member_names):
        self.debug("Assign '%s'" % member_names)
        if hasattr(self, 'card'):
            for nm in member_names:
                for bm in self.members:
                    if nm == bm.username:
                        if bm.id in self.card.member_id:
                            self.debug("%s (%s) already assigned to card %s" %
                                       (nm, bm.id, self.card))
                        else:
                            self.debug("Assign card %s to %s (%s)" %
                                       (self.card, nm, bm.id))
                            self.card.assign(bm.id)

    def unassign_card(self, member_names=None):
        self.debug("Unassign '%s'" % member_names)
        if hasattr(self, 'card'):
            if len(member_names) == 0:
                for cm in self.card.member_id:
                    self.debug("Unassign card %s from %s" % (self.card, cm))
                    self.card.unassign(cm)
            else:
                for nm in member_names:
                    for bm in self.members:
                        if nm == bm.username:
                            if bm.id in self.card.member_id:
                                self.debug("Unassign card %s from %s" %
                                           (self.card, bm.id))
                                self.card.unassign(bm.id)
                            else:
                                self.debug("%s (%s) not assigned to card %s" %
                                           (nm, bm.id, self.card))

    def label_card(self, labels):
        if hasattr(self, 'card'):
            for l in self.labels:
                if l.name in labels:
                    self.debug("label card %s as %s (%s)" %
                               (self.card, l.name, l.id))
                    self.card.add_label(l)

    def move_card(self, lane_name):
        if hasattr(self, 'card'):
            for l in self.board.list_lists():
                if l.name == lane_name:
                    self.card.change_list(l.id)

    def archive_card(self):
        if hasattr(self, 'card'):
            self.card.set_closed(True)

    def delete_card(self):
        if hasattr(self, 'card'):
            self.card.set_closed(True)

    def debug(self, m):
        if self.dbg:
            print(m)
示例#13
0
class TrelloBoardTestCase(unittest.TestCase):
    """
    Tests for TrelloClient API. Note these test are in order to
    preserve dependencies, as an API integration cannot be tested
    independently.
    """
    def setUp(self):
        self._trello = TrelloClient(os.environ['TRELLO_API_KEY'],
                                    token=os.environ['TRELLO_TOKEN'])
        for b in self._trello.list_boards():
            if b.name == os.environ['TRELLO_TEST_BOARD_NAME']:
                self._board = b
                break
        try:
            self._list = self._board.open_lists()[0]
        except IndexError:
            self._list = self._board.add_list('List')

    def _add_card(self, name, description=None):
        try:
            card = self._list.add_card(name, description)
            self.assertIsNotNone(card, msg="card is None")
            self.assertIsNotNone(card.id, msg="id not provided")
            self.assertEquals(card.name, name)
            return card
        except Exception as e:
            print(str(e))
            self.fail("Caught Exception adding card")

    def test40_add_card(self):
        name = "Testing from Python - no desc"
        card = self._add_card(name)

        self.assertIsNotNone(card.closed, msg="closed not provided")
        self.assertIsNotNone(card.url, msg="url not provided")

        card2 = self._trello.get_card(card.id)
        self.assertEqual(card.name, card2.name)

    def test41_add_card(self):
        name = "Testing from Python"
        description = "Description goes here"
        card = self._add_card(name, description)

        self.assertEquals(card.description, description)
        self.assertIsNotNone(card.closed, msg="closed not provided")
        self.assertIsNotNone(card.url, msg="url not provided")
        card.fetch()
        self.assertIsNotNone(card.member_id)
        self.assertIsNotNone(card.short_id)
        self.assertIsNotNone(card.list_id)
        self.assertIsNotNone(card.comments)
        self.assertIsNotNone(card.checklists)
        self.assertIsInstance(card.create_date, datetime)

    def test42_add_card_with_comments(self):
        name = "Card with comments"
        comment = "Hello World!"
        card = self._add_card(name)
        card.comment(comment)
        card.fetch(True)

        self.assertEquals(card.description, '')
        self.assertIsNotNone(card.closed, msg="closed not provided")
        self.assertIsNotNone(card.url, msg="url not provided")
        self.assertEquals(len(card.comments), 1)
        self.assertEquals(card.comments[0]['data']['text'], comment)

    def test43_delete_checklist(self):
        name = "Card with comments"
        card = self._list.add_card(name)
        card.fetch(True)

        name = 'Checklists'
        checklist = card.add_checklist(name, ['item1', 'item2'])
        self.assertIsNotNone(checklist, msg="checklist is None")
        self.assertIsNotNone(checklist.id, msg="id not provided")
        self.assertEquals(checklist.name, name)
        checklist.delete()
        card.delete()

    def test44_attach_url_to_card(self):
        name = "Testing from Python - url"
        card = self._add_card(name)

        card.attach(name='lwn', url='http://lwn.net/')
        card.fetch()
        self.assertEquals(card.badges['attachments'], 1)
        card.delete()

    def test52_get_cards(self):
        cards = self._board.get_cards()
        self.assertEquals(len(cards), 4)

        for card in cards:
            if card.name == 'Testing from Python':
                self.assertEqual(card.description, 'Description goes here')
            elif card.name == 'Testing from Python - no desc':
                self.assertEqual(card.description, '')
            elif card.name == 'Card with comments':
                self.assertEqual(card.description, '')
            else:
                self.fail(msg='Unexpected card found')

        self.assertIsInstance(self._board.all_cards(), list)
        self.assertIsInstance(self._board.open_cards(), list)
        self.assertIsInstance(self._board.closed_cards(), list)

    def test52_add_card_set_due(self):
        name = "Testing from Python"
        description = "Description goes here"
        card = self._list.add_card(name, description)

        # Set the due date to be 3 days from now
        today = datetime.today()
        day_detla = timedelta(3)
        due_date = today + day_detla
        card.set_due(due_date)
        expected_due_date = card.due
        # Refresh the due date from cloud
        card.fetch()
        actual_due_date = card.due[:10]
        self.assertEquals(expected_due_date, actual_due_date)

    def test53_checklist(self):
        name = "Testing from Python"
        description = "Description goes here"
        card = self._list.add_card(name, description)

        name = 'Checklists'
        checklist = card.add_checklist(name, ['item1', 'item2'])
        self.assertIsNotNone(checklist, msg="checklist is None")
        self.assertIsNotNone(checklist.id, msg="id not provided")
        self.assertEquals(checklist.name, name)
        checklist.rename('Renamed')
        self.assertEquals(checklist.name, 'Renamed')

    def test54_set(self):
        name = "Testing from Python"
        description = "Description goes here"
        card = self._list.add_card('noname')
        card.set_name(name)
        card.set_description(description)
        self.assertEquals(card.name, name)
        self.assertEquals(card.description, description)

    def test60_delete_cards(self):
        cards = self._board.get_cards()
        for card in cards:
            card.delete()

    def test70_all_members(self):
        self.assertTrue(len(self._board.all_members()) > 0)

    def test71_normal_members(self):
        self.assertTrue(len(self._board.normal_members()) >= 0)

    def test72_admin_members(self):
        self.assertTrue(len(self._board.admin_members()) > 0)

    def test73_owner_members(self):
        members = self._board.owner_members()
        self.assertTrue(len(members) > 0)
        member = members[0].fetch()
        self.assertNotEqual(member.status, None)
        self.assertNotEqual(member.id, None)
        self.assertNotEqual(member.bio, None)
        self.assertNotEqual(member.url, None)
        self.assertNotEqual(member.username, None)
        self.assertNotEqual(member.full_name, None)
        self.assertNotEqual(member.initials, None)
        member2 = self._trello.get_member(member.id)
        self.assertEqual(member.username, member2.username)

    def test80_unauthorized(self):
        client = TrelloClient('a')
        self.assertRaises(Unauthorized, client.list_boards)

    def test81_resource_unavailable(self):
        self.assertRaises(ResourceUnavailable, self._trello.get_card, '0')

    def test90_get_board(self):
        board = self._trello.get_board(self._board.id)
        self.assertEqual(self._board.name, board.name)
示例#14
0
class trello:
    def __init__(self, apiKey, TOKEN):
        self.apiKey = apiKey
        self.token = TOKEN
        self.client = TrelloClient(api_key=apiKey,
                                   api_secret='your-secret',
                                   token=TOKEN,
                                   token_secret='your-oauth-token-secret')

    def printTrello(self):
        all_boards = self.client.list_boards()
        last_board = all_boards[-1]
        print("Boards ")

        for board in all_boards:
            print("Board Name :", board.name, " Board ID", board.id)
            for list in board.all_lists():
                print("\t", "ListName :", list.name, "listID :", list.id)
                for card in list.list_cards(""):
                    print("\t\t", "cardName :", card.name, "cardID :", card.id)

                    #for card in board.all_cards():
                    #   print("\tCard Name :",card.name," Card ID",card.id)
                ####### BOARD OPERATIONS

    def getBoard(self, boardID):
        self.board = self.client.get_board(board_id=boardID)
        return self.board

    def getBoardByName(self, boardName):
        all_boards = self.client.list_boards()
        for board in all_boards:
            if board.name == boardName:
                self.board = board
                return board
        return None

    # close all boards
    def clearBoards(self):
        for board in self.client.list_boards():
            board.close()

    def createBoard(self,
                    boardName,
                    organizationID=None,
                    permission_level="private"):
        self.board = self.client.add_board(board_name=boardName,
                                           source_board=None,
                                           organization_id=organizationID,
                                           permission_level=permission_level)
        for list in self.board.get_lists(None):
            self.board.get_list(list.id).close()
        self.createList("To Do:", self.board.id, 1)
        self.createList("Doing:", self.board.id, 2)
        self.createList("Build:", self.board.id, 3)
        self.createList("Test:", self.board.id, 4)
        self.createList("Deploy:", self.board.id, 5)
        return self.board

    def closeBoardByName(self, boardName=None):
        if boardName != None:
            all_boards = self.client.list_boards()
            for board in all_boards:
                if board.name == boardName:
                    return board.close()
        else:
            if self.board != None:
                self.closeBoard(self.board.id)

    def closeBoard(self, boardId=None):
        if boardId != None:
            return self.getBoard(boardID=boardId).close()
        else:
            if self.board != None:
                self.board.close()
            else:
                return None

    def boardList(self):
        return self.client.list_boards()

    ####### END BOARD OPERATIONS

    ####### LIST OPERATIONS

    def getList(self, listID, boardID):
        return self.client.get_board(board_id=boardID).get_list(list_id=listID)

    def getListByName(self, listID, boardID):
        return self.client.get_board(board_id=boardID).get_list(list_id=listID)

    def createList(self, listName, boardID, sira=None):
        board = self.client.get_board(boardID)
        addedlist = board.add_list(listName, sira)
        return addedlist

    def closeList(self, listID, boardID):
        return self.client.get_board(boardID).get_list(listID).close()

    def closeJustListID(self, listID):  # unsafe
        url = "https://api.trello.com/1/lists/" + listID + "?closed=true&key=" + self.apiKey + "&token=" + self.token
        querystring = {}
        response = requests.request("PUT", url, params=querystring)
        return response.text

    ####### END LIST OPERATIONS

    ####### CARD OPERATIONS

    def getCard(self, cardID):
        return self.client.get_card(card_id=cardID)

    def createCard(self, boardID, listID, cardName):
        self.getList(boardID=boardID, listID=listID).add_card(name=cardName,
                                                              labels=None,
                                                              due="",
                                                              source=None,
                                                              position=None)

    def removeCard(self, cardID):
        url = "https://api.trello.com/1/cards/" + cardID + "?key=" + self.apiKey + "&token=" + self.token
        querystring = {}
        response = requests.request("PUT", url, params=querystring)
        return response.text

    def moveCard(self, cardID, desListID):
        self.getCard(cardID=cardID).change_list(list_id=desListID)

    ####### END CARD OPERATIONS

    #######  TEAM MEMBER OPERATIONS

    def addMemberBoard(self, boardID, memberID):
        board = self.client.get_board(board_id=boardID)
        board.add_member(memberID)

    # ORGANIZATION OPERATIONS

    def getOrganization(self, organizationID):
        return self.client.get_organization(organizationID)

    def getOrganizationByName(self, organizationName):
        for organization in self.listOrganizations():
            if organization.name == "":
                return organization
        return None

    def listOrganizations(self):
        self.client.list_organizations()
        return self.client.list_organizations()

    def createOrganization(self, organizationName):
        url = "https://api.trello.com/1/organizations?displayName=" + organizationName + "&desc=" + organizationName + "&key=" + self.apiKey + "&token=" + self.token
        querystring = {}
        response = requests.request("POST", url, params=querystring)
        organizationID = str.split(response.text, ",")[0].split("\"")[3]
        return organizationID

    def addOrganizationMember(self,
                              organizationID,
                              mail,
                              memberType="normal",
                              fullName="member"):
        configuredMail = str.replace(mail, "@", "%40")
        url = "https://api.trello.com/1/organizations/" + organizationID + "/members?email=" + configuredMail + "&fullName=" + fullName + "&type=" + memberType + "&key=" + self.apiKey + "&token=" + self.token
        querystring = {}
        response = requests.request("PUT", url, params=querystring)

        data = (json.loads(response.text))
        memberID = (data["memberships"][-1]["idMember"])
        return memberID

    def removeOrganizationMember(self, organizationID, memberID):
        url = "https://api.trello.com/1/organizations/" + organizationID + "/members/" + memberID + "?key=" + self.apiKey + "&token=" + self.token
        querystring = {}
        response = requests.request("DELETE", url, params=querystring)
        return response.text

    def removeOrganization(self, organizationID):
        url = "https://api.trello.com/1/organizations/" + organizationID + "?key=" + self.apiKey + "&token=" + self.token
        querystring = {}
        response = requests.request("DELETE", url, params=querystring)
        return response.text

    def addCommendToCard(self, cardID, commendText):
        url = "https://api.trello.com/1/cards/" + cardID + "/actions/comments?text=" + commendText + "&key=" + self.apiKey + "&token=" + self.token
        querystring = {}
        response = requests.request("POST", url, params=querystring)
        return response.text
示例#15
0
class TaskManager():
    _client_trello = None
    _board = None
    _board_labels = None
    _config_file = ''
    _dict_label = {}

    def __init__(self, config_file):
        self._config_file = config_file
        config = ConfigParser.RawConfigParser()
        config.read(config_file)

        api_key = config.get('Management.Task', 'api.key')
        oath_token = config.get('Management.Task', 'oath.token')
        id_board = config.get('Management.Task', 'id.board')
        self._client_trello = TrelloClient(api_key, token=oath_token)
        self._board = self._client_trello.get_board(id_board)
        self._board_labels = self._board.get_labels()
        list_label = [label for label in self._board_labels if label.name != '' and label.color]
        for label in list_label:
            self._dict_label[label.name] = label

    @staticmethod
    def validate_connection():
        url_test = 'https://api.trello.com/1'
        try:
            result = requests.request('GET', url_test, timeout=5)
            return result.status_code == 200
        except ConnectionError as e:
            logger.warning("couldn't connect to trello, see error: %s" % e.message)
            return False
        except RuntimeError as e:
            logger.warning("couldn't connect to trello, timeout error: %s" % e.message)
            return False

    def refresh_list_id(self):
        dao_object = SdaTrackerDao(self._config_file)
        for a_list in self._board.all_lists():
            code_env = a_list.name
            id_list_tracker = a_list.id
            dao_object.update_list_tracker(code_env, id_list_tracker)

    def get_card_ticket(self, id_card_tracker):
        return self._client_trello.get_card(id_card_tracker) if id_card_tracker else None

    def send_ticket_card(self, dict_board_ticket):
        """Send new card or update it"""
        result_card = None
        dict_board = dict_board_ticket['dict_board']
        id_card_tracker = dict_board['id_card_tracker']
        try:
            action = None
            # get trello's card
            a_card = self.get_card_ticket(id_card_tracker)
            list_artifact = dict_board_ticket['artifacts']
            # get id_list trello
            id_list_tracker = dict_board['id_list_tracker']
            # id_ticket = card.name
            id_ticket = dict_board['id_ticket']
            # card's description
            string_json = json.dumps(list_artifact, indent=2)
            labels_artifact = self.get_labels_artifact(list_artifact)

            if a_card:
                action = "UPDATE"
                #print "update card"
                for label in a_card.labels:
                    a_card.client.fetch_json(
                        '/cards/' + a_card.id + '/idLabels/' + label.id,
                        http_method='DELETE')

                a_card.set_description(string_json)
                result_card = a_card

            else:
                action = "NEW"
                #print "new card"
                a_list = self._board.get_list(id_list_tracker)
                new_card = a_list.add_card(id_ticket, string_json)
                result_card = new_card

            result_card.add_label(self._dict_label['requested'])
            for label in labels_artifact:
                result_card.add_label(label)
            return {"result": "OK", "action": action, "result_card": result_card}
        except RuntimeError as e:
            return {"result": "ERROR", "description": e.message}

    def get_labels_artifact(self, list_artifact):
        list_label = []
        for dict_artifact in list_artifact:
            artifact = dict_artifact['artifact']
            ls = [label for label in self._board_labels if label.name == artifact]
            if len(ls) == 0:
                label = self._board.add_label(artifact, None)
                self._board_labels = self._board.get_labels()
                list_label.append(label)
            else:
                list_label.append(ls[0])
        return list_label
示例#16
0
class TrelloModule:
    def __init__(self):
        with open("trello.json") as parameters_data:
            self.config = json.load(parameters_data)

        self.trello = TrelloClient(api_key=self.config['ApiKey'],
                                   api_secret=self.config['ApiSecret'],
                                   token=self.config['Token'],
                                   token_secret=self.config['TokenSecret'])

    def get_board(self):
        '''
        Retourne la liste Trello indiquée dans trello.ini
        '''

        # Chargement des paramètres et identifiants Trello depuis le fichier JSON
        for b in self.trello.list_boards():
            if b.name == self.config['BoardName']:
                return b

        print("Board " + self.config['BoardName'] + " not found.")
        exit()

    def get_list(self, site):
        board = self.get_board()

        for l in board.all_lists():
            if l.name == site:
                return l

        # Liste pas trouvée, on la crée
        return board.add_list(site)

    def post(self):
        '''
        Poste les annonces sur Trello
        '''
        posted = 0

        for annonce in Annonce.select().where(
                Annonce.posted2trello == False).order_by(Annonce.site.asc()):
            title = "%s de %sm² à %s @ %s€" % (annonce.title, annonce.surface,
                                               annonce.city, annonce.price)
            description = "Créé le : %s\n\n" \
                          "%s pièces, %s chambre(s)\n" \
                          "Tel : %s\n\n" % \
                          (annonce.created.strftime("%a %d %b %Y %H:%M:%S"), annonce.rooms, annonce.bedrooms,
                           annonce.telephone)
            if annonce.description is not None:
                description += ">%s" % annonce.description.replace("\n", "\n>")

            card = self.get_list(annonce.site).add_card(title,
                                                        desc=description)

            # On s'assure que ce soit bien un tableau
            if annonce.picture is not None and annonce.picture.startswith("["):
                # Conversion de la chaîne de caractère représentant le tableau d'images en tableau
                for picture in literal_eval(annonce.picture):
                    card.attach(url=picture)
                # Il n'y a qu'une photo
            elif annonce.picture is not None and annonce.picture.startswith(
                    "http"):
                card.attach(url=annonce.picture)

            card.attach(url=annonce.link)

            annonce.posted2trello = True
            annonce.idtrello = card.id
            annonce.save()
            posted += 1
        return posted

    def add_new_link(self, annonce, link):
        try:
            if not annonce.idtrello:
                raise ReferenceError
            card = self.trello.get_card(annonce.idtrello)
            card.attach(url=link)
        except (ResourceUnavailable, ReferenceError):
            logging.error("Trello card not found ( " + annonce.title + " : " +
                          annonce.link + ")")
class TrelloUpdater(object):
    """
    Class for writing to Trello.
    """

    def __init__(self, processed_report, trello_secret):
        self.logger = logging.getLogger(__name__)
        self.client = TrelloClient(api_key = trello_secret[':consumer_key'],
                                   api_secret = trello_secret[':consumer_secret'],
                                   token = trello_secret[':oauth_token'],
                                   token_secret = trello_secret[':oauth_token_secret'])

        #Extract report configuration parameters
        self.projects = processed_report[':collected_content'][':projects'];
        self.epics = processed_report[':collected_content'][':epics'];
        self.assignments = processed_report[':collected_content'][':assignments'];


    def update_projects(self):
        """Main function to update all project cards from config."""
        self.logger.info('---Started writing to Trello---')
        for project in self.projects:
            #find special card for no projects
            if self.projects[project][':name'] == 'No Project':
                no_project = project

            child_cards = [] #tuples of (name of chklist item, state of chklist item)
            #form lists of items for checklists
            for card in list(self.assignments):
                if self.assignments[card][':project'] == self.projects[project][':project'] and self.projects[project][':project'] != []:
                    chk_item_name = self.assignments[card][':short_url'] +" (" + self.assignments[card][':list_name'] + ") (" + self.assignments[card][':board_name'] + ")"
                    child_cards.append((chk_item_name, self.assignments[card][':completed']))
                    #self.logger.debug('Appending assignment %s to the project %s' % (self.assignments[card], self.projects[project][':name']))
                    self.assignments.pop(card,None)
            self.logger.debug("Project %s has assignments : %s" % (self.projects[project][':name'], child_cards))
            child_cards.sort(key = lambda x: x[1]) # Sort, so that unresolved cards are on top
            self.update_card(project, [ i[0] for i in child_cards] ,  [ i[1] for i in child_cards]);

        #assign items with no project to a special project card
        child_cards = []
        for card in self.assignments:
            chk_item_name = self.assignments[card][':short_url'] +" (" + self.assignments[card][':list_name'] + ") (" + self.assignments[card][':board_name'] + ")"
            child_cards.append((chk_item_name, self.assignments[card][':completed']))
            #self.logger.debug('Appending assignment %s to the No Project' % (self.assignments[card]))
        child_cards.sort(key = lambda x: x[1])
        self.logger.debug("Project %s has assignments : %s" % (self.projects[project][':name'], child_cards))
        self.update_card(no_project, [ i[0] for i in child_cards] ,  [ i[1] for i in child_cards]);

    def update_card(self, card_id, checklist_names, checklist_states):
        """
        Clean checklists from the card,
        Write new checklists to the card based on the report
        checklist_data: [("ID", "short_url", "list_name", "board_name", completed),...]
        """
        while True:
            try:
                tr_card = self.client.get_card(card_id)
                tr_card.fetch(eager=True)

                #self.logger.debug('Fetching checklists < %s > for Trello for card: %s' % (tr_card.checklists,self.projects[card_id][':name']))
            except ResourceUnavailable as e:
                self.logger.error('Trello unavailable! %s' % (e))
                continue
            break

        # Remove all existing checklists
        for old_chklist in tr_card.checklists:
            old_chklist.delete()

        assign_chk = tr_card.add_checklist("Assignments", checklist_names, checklist_states)
示例#18
0
class TarDriver:

    #Конструктор класса
    def __init__(
            self,
            trello_apiKey='',  #apiKey для подключения к trello
            trello_token='',  #apiToken для подключения к trello
            local_timezone='Asia/Tomsk'):

        self.API_KEY = trello_apiKey
        self.TOKEN = trello_token
        self.local_timezone = tz(local_timezone)
        self.filter_dates = []
        self.database_is_updating = False

        #Подключение к Trello
        try:
            self.trello_client = TrelloClient(
                api_key=self.API_KEY,
                token=self.TOKEN,
            )
        except Exception as err:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [ERROR] Failed to connect to Trello via API: {err}'
            )
        else:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] Connection to Trello established successful'
            )

        #Создание файла БД и таблиц в БД
        try:
            self.db = TinyDB('tar_database.json')
            #self.db.drop_tables()      !!!!!!!!!!!!!!!!!!!!!

            self.report = self.db.table('report')
            self.worktime = self.db.table('worktime')
            self.local_boards = self.db.table('boards')
            self.local_lists = self.db.table('lists')
            self.local_cards = self.db.table('cards')
            self.local_persons = self.db.table('persons')
            self.local_cards_has_persons = self.db.table('cards_has_persons')

        except Exception as err:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [ERROR] Failed to setup tar_database: {err}'
            )
        else:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] tar_database created'
            )

        self.basic_template = [{
            0:
            'Перечень Задач',
            'cards': [
                'П3 - Описание автоматизируемых функций',
                'П5 - Описание информационного обеспечения',
                'В1 - Описание входных сигналов и данных',
                'В2 - Описание выходных сигналов (сообщений)',
                'ПА - Описание программного обеспечения',
                'ПБ - Описание алгоритма', 'П6 - Описание информационной базы',
                'С9 - Чертеж форм (видеокадра)', 'И3 - Руководство оператора',
                'И3 - Руководство программиста',
                'И4 - Инструкция по ведению БД',
                'ПМИ - Программа и методика испытаний',
                'ПО ПЛК - Программа контроллера',
                'ПО Панели - Программа панели оператора',
                'ПО АРМ - Программа рабочего места оператора',
                'ПО БД - База данных', 'Ежедневная планерка',
                'Планирование цели (спринт)',
                'Анализ завершения цели (спринта)'
            ]
        }, {
            1: 'Комплекс Задач',
            'cards': []
        }, {
            2: 'В Работе',
            'cards': []
        }, {
            3: 'Согласование выполнения',
            'cards': []
        }, {
            4: 'Завершены',
            'cards': []
        }, {
            5: 'Отменены',
            'cards': []
        }]

        self.db.drop_table('worktime')
        self.worktime.insert({
            'work_day_starts': '09:00:00',
            'work_day_ends': '18:00:00',
            'work_day_duration': '09:00:00',
            'lunch_hours_starts': '13:00:00',
            'lunch_hours_ends': '14:00:00',
            'lunch_duration': '01:00:00',
            'day_work_hours': '08:00:00',
            'work_days': '5',
            'week_work_hours': '1 day, 16:00:00',
            'update_period': '00:02:00'
        })

    def add_board(self, board):
        #Добавление новой доски в БД
        try:
            self.local_boards.insert({
                'board_id':
                board.id,
                'board_name':
                board.name,
                'board_description':
                board.description,
                'board_last_modified':
                str(board.date_last_activity)
            })

            for list_ in board.list_lists():
                self.local_lists.insert({
                    'list_id':
                    list_.id,
                    'list_name':
                    list_.name,
                    'list_last_modified':
                    str(datetime.now().strftime("%Y-%m-%d %H:%M:%S")),
                    'board_id':
                    board.id,
                    'board_name':
                    board.name
                })

                for card in list_.list_cards():

                    self.local_cards.insert({
                        'card_id': card.id,
                        'card_name': card.name,
                        'list_id': list_.id,
                        'list_name': list_.name,
                        'board_id': board.id,
                        'board_name': board.name
                    })

                    if len(card.member_id) > 0:
                        for person in self.team:
                            if person.id in card.member_id:
                                query_result = self.local_persons.get(
                                    where('person_id') == str(person.id))
                                self.local_cards_has_persons.insert({
                                    'card_id':
                                    card.id,
                                    'card_name':
                                    card.name,
                                    'person_id':
                                    person.id,
                                    'person_name':
                                    query_result['person_fullname'],
                                    'list_id':
                                    list_.id,
                                    'list_name':
                                    list_.name,
                                    'board_id':
                                    board.id,
                                    'board_name':
                                    board.name
                                })

        except Exception as err:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [ERROR] Failed to add "{board.name}": {err}'
            )
        else:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] "{board.name}" added successful'
            )

    def delete_board(self, board_id, board_name=''):
        #Удаление доски из БД
        try:
            #Удаляем записи из таблицы local_cards_has_persons
            self.local_cards_has_persons.remove(
                where('board_id') == str(board_id))
            #Удаляем записи из таблицы local_cards
            self.local_cards.remove(where('board_id') == str(board_id))
            #Удаляем записи из таблицы local_lists
            self.local_lists.remove(where('board_id') == str(board_id))
            #Удаляем записи из таблицы local_boards
            self.local_boards.remove(where('board_id') == str(board_id))
        except Exception as err:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [ERROR] Failed to delete {board_id}: {err}'
            )
        else:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] {board_id} deleted successful'
            )

    def update_board(self, board):
        #Обновление доски в БД
        datetime_format = "%Y-%m-%d %H:%M:%S.%f%z"

        try:
            query_result = self.local_boards.get(
                where('board_id') == str(board.id))

        except Exception as err:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] Updating "{board.name}"...{err}'
            )
            self.delete_board(board_id=board.id, board_name=board.name)
            self.add_board(board=board)
        else:
            board_date_last_activity = self.unify_time(
                datetime.strptime(query_result['board_last_modified'],
                                  datetime_format))

            if self.unify_time(
                    board.date_last_activity) > board_date_last_activity:
                print(
                    f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] Updating "{board.name}"...'
                )
                self.delete_board(board_id=board.id, board_name=board.name)
                self.add_board(board=board)

    def fill_main_boards(self):
        #Заполнение таблиц local_boards, local_lists, local_cards
        print(
            f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] Filling "local_boards / local_lists / local_cards" tables...'
        )
        try:
            for board in self.trello_client.list_boards():
                self.add_board(board=board)
        except Exception as err:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [ERROR] Failed to fill "local_boards / local_lists / local_cards" tables: {err}'
            )
        else:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] "local_boards / local_lists / local_cards" tables filled successful'
            )

    def fill_persons(self, team_board_name='КАДРЫ'):
        #Заполнение таблицы local_persons
        try:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] Filling "local_persons" table...'
            )
            for board in self.trello_client.list_boards():
                if board.name == team_board_name:
                    self.team = board.get_members(filters='all')
                    for list_ in board.list_lists():
                        for card in list_.list_cards():
                            if len(card.member_id) > 0:
                                for person in self.team:
                                    if person.id in card.member_id:
                                        self.local_persons.insert({
                                            'person_id':
                                            person.id,
                                            'person_username':
                                            person.username,
                                            'person_fullname':
                                            card.name,
                                            'status':
                                            list_.name,
                                            'last_modified':
                                            str(datetime.now().strftime(
                                                "%Y-%m-%d %H:%M:%S"))
                                        })
                    break
        except Exception as err:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [ERROR] Failed to fill "local_persons" table: {err}'
            )
        else:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] "local_persons" table filled successful'
            )

    def fill_cards_has_persons(self):
        #Заполнение таблицы cards_has_persons
        try:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] Filling "cards_has_persons" table...'
            )
            for board in self.trello_client.list_boards():
                for list_ in board.list_lists():
                    for card in list_.list_cards():
                        if len(card.member_id) > 0:
                            for person in self.team:
                                if person.id in card.member_id:
                                    query_result = self.local_persons.get(
                                        where('person_id') == str(person.id))
                                    self.local_cards_has_persons.insert({
                                        'card_id':
                                        card.id,
                                        'card_name':
                                        card.name,
                                        'person_id':
                                        person.id,
                                        'person_name':
                                        query_result['person_fullname'],
                                        'list_id':
                                        list_.id,
                                        'list_name':
                                        list_.name,
                                        'board_id':
                                        board.id,
                                        'board_name':
                                        board.name
                                    })
        except Exception as err:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [ERROR] Failed to fill "cards_has_persons" table: {err}'
            )
        else:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] "cards_has_persons" table filled successful'
            )

    def fill_database(self):
        self.fill_persons()
        self.fill_main_boards()

    def update_database(self, update_on_change=False):

        time_format = "%H:%M:%S"

        self.db.drop_table('persons')
        self.fill_persons()

        update = True

        while update:

            self.database_is_updating = True

            update_period_time = (time.strptime(self.get_update_period(),
                                                time_format))
            update_period_seconds = timedelta(
                hours=update_period_time.tm_hour,
                minutes=update_period_time.tm_min,
                seconds=update_period_time.tm_sec).total_seconds()

            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] Checking for updates...'
            )

            trello_boards = self.trello_client.list_boards()
            local_boards = self.local_boards.all()

            if len(trello_boards) > len(
                    local_boards):  #в trello добавили доску
                #ищем какую
                tempBoards = []

                for board in local_boards:
                    tempBoards.append(board['board_id'])

                for board in trello_boards:
                    if board.id not in tempBoards:  #новая доска обнаружена
                        self.add_board(board=board)

                print(
                    f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] Checking for updates finished'
                )

            elif len(trello_boards) < len(
                    local_boards):  #в trello удалили доску
                #ищем какую
                tempBoards = []

                for board in trello_boards:
                    tempBoards.append(board.id)

                for board in local_boards:
                    if board[
                            'board_id'] not in tempBoards:  #новая доска обнаружена
                        self.delete_board(board_id=board['board_id'],
                                          board_name=board['board_name'])

                print(
                    f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] Checking for updates finished'
                )

            else:  #обновляем все доски. Новых / удаленных не обнаружено
                for board in trello_boards:
                    self.update_board(board=board)

                print(
                    f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] Checking for updates finished'
                )

                if not update_on_change:
                    time.sleep(update_period_seconds)

                    self.database_is_updating = False

    def get_persons_active_tasks(self, person_id, active_list_name='В Работе'):
        query_result = self.local_cards_has_persons.search(
            (where('person_id') == str(person_id))
            & (where('list_name') == str(active_list_name)))
        return len(query_result)

    # !!!!! Изменить чтоб читал пользователей доски, возможно вернуть board_has_persons
    def get_project_members(self, board_id):
        temp_persons = []
        board_persons = []
        query_result = self.local_cards_has_persons.search(
            where('board_id') == str(board_id))
        for result in query_result:
            if result['person_id'] not in temp_persons:
                temp_persons.append(result['person_id'])
                board_persons.append({
                    'person_id': result['person_id'],
                    'person_name': result['person_name']
                })
        return board_persons

    def get_tasks_on_board(self, board_id, list_name='В работе'):
        tasks = []
        query_result = self.local_cards.search(
            where('board_id') == str(board_id))
        for result in query_result:

            if result['list_name'] == list_name:

                query_result_ = self.local_cards_has_persons.search(
                    where('list_id') == str(result['list_id']))
                for result_ in query_result_:
                    if result_['card_name'] == result['card_name']:
                        task = {
                            'task_name': result['card_name'],
                            'task_member': result_['person_name'],
                            'card_in_work_time': result['card_in_work_time']
                        }
                        tasks.append(task)
                        break

        return tasks

    def get_lists_by_board_id(self, board_id):
        query_result = self.local_lists.search(
            (where('board_id') == str(board_id)))
        return query_result

    def get_active_tasks_by_person(self, person_id):
        query_result = self.local_cards_has_persons.search(
            (where('person_id') == str(person_id))
            & ((where('list_name') == str('В Работе'))))
        return query_result

    def get_curr_stage_percent(self, board_id, board_template):
        tasks_planned = self.local_cards.search(
            (where('board_id') == str(board_id))
            & (where('list_name') == str('Комплекс задач')))
        tasks_in_progress = self.local_cards.search(
            (where('board_id') == str(board_id))
            & (where('list_name') == str('В Работе')))
        tasks_on_hold = self.local_cards.search(
            (where('board_id') == str(board_id))
            & (where('list_name') == str('Согласование Выполнения')))
        tasks_done = self.local_cards.search(
            (where('board_id') == str(board_id))
            & (where('list_name') == str('Завершены')))

        if (len(tasks_planned) + len(tasks_in_progress) + len(tasks_on_hold) +
                len(tasks_done)) == 0:
            return 0
        else:
            return round((len(tasks_done) /
                          (len(tasks_planned) + len(tasks_in_progress) +
                           len(tasks_on_hold) + len(tasks_done))) * 100.0)

    def create_new_project(self,
                           project_template,
                           project_name='Новый проект',
                           project_description=''):
        self.trello_client.add_board(board_name=project_name,
                                     source_board=None,
                                     organization_id=None,
                                     permission_level='private',
                                     default_lists=False)

        for board in self.trello_client.list_boards():
            if board.name == project_name:
                board.set_description(desc=project_description)

                for list_ in range(len(project_template) - 1, -1, -1):
                    board.add_list(name=project_template[list_].get(list_),
                                   pos=None)

                for _list in board.list_lists():
                    for list_ in range(0, len(project_template)):
                        if _list.name == project_template[list_].get(list_):
                            for card in project_template[list_]['cards']:
                                _list.add_card(name=card,
                                               desc=None,
                                               labels=None,
                                               due="null",
                                               source=None,
                                               position=None,
                                               assign=None,
                                               keep_from_source="all")
                                print(
                                    f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG] Card {card} was added'
                                )
                            break

    def utc_to_local(self, utc_dt):
        return utc_dt.replace(tzinfo=timezone.utc,
                              microsecond=0).astimezone(tz=None)

    def set_workhours(self, workhours=['09:00:00', '18:00:00']):
        format_ = '%H:%M:%S'
        try:
            work_day_starts = datetime.strptime(workhours[0], format_).time()
            work_day_ends = datetime.strptime(workhours[1], format_).time()
        except Exception as err:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [ERROR] {err}'
            )
            pass
            #self.worktime.update({ 'work_day_starts': str(datetime.strptime('9:00:00', format_).time())})
            #self.worktime.update({ 'work_day_ends': str(datetime.strptime('18:00:00', format_).time())})
        else:
            if work_day_starts < work_day_ends:
                self.worktime.update({'work_day_starts': str(work_day_starts)})
                self.worktime.update({'work_day_ends': str(work_day_ends)})

                work_day_duration = timedelta(hours = work_day_ends.hour, minutes = work_day_ends.minute, seconds = work_day_ends.second) \
                                            - timedelta(hours = work_day_starts.hour, minutes = work_day_starts.minute, seconds = work_day_starts.second)

                self.worktime.update(
                    {'work_day_duration': str(work_day_duration)})

                self.calculate_work_hours()

    def get_workhours(self):
        return self.worktime.get(where('work_day_starts') != None)

    def set_lunch_hours(self, lunch_hours=['13:00:00', '14:00:00']):
        format_ = '%H:%M:%S'
        try:
            lunch_hours_starts = datetime.strptime(lunch_hours[0],
                                                   format_).time()
            lunch_hours_ends = datetime.strptime(lunch_hours[1],
                                                 format_).time()
        except Exception as err:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [ERROR] {err}'
            )
            pass
        else:
            if lunch_hours_starts < lunch_hours_ends:
                self.worktime.update(
                    {'lunch_hours_starts': str(lunch_hours_starts)})
                self.worktime.update(
                    {'lunch_hours_ends': str(lunch_hours_ends)})

                lunch_duration = timedelta(hours = lunch_hours_ends.hour, minutes = lunch_hours_ends.minute, seconds = lunch_hours_ends.second) \
                                            - timedelta(hours = lunch_hours_starts.hour, minutes = lunch_hours_starts.minute, seconds = lunch_hours_starts.second)

                self.worktime.update({'lunch_duration': str(lunch_duration)})

                self.calculate_work_hours()

    def get_lunch_hours(self):
        return self.worktime.get(where('lunch_hours_starts') != None)

    def calculate_work_hours(self):
        format_ = '%H:%M:%S'
        str_work_day_duration = self.worktime.get(
            where('work_day_duration') != None)['work_day_duration']
        str_lunch_duration = self.worktime.get(
            where('lunch_duration') != None)['lunch_duration']

        time_work_day_duration = datetime.strptime(str_work_day_duration,
                                                   format_).time()
        time_lunch_duration = datetime.strptime(str_lunch_duration,
                                                format_).time()

        day_work_hours = timedelta(hours = time_work_day_duration.hour, minutes = time_work_day_duration.minute, seconds = time_work_day_duration.second) \
                                            - timedelta(hours = time_lunch_duration.hour, minutes = time_lunch_duration.minute, seconds = time_lunch_duration.second)

        self.worktime.update({'day_work_hours': str(day_work_hours)})

        work_days = self.worktime.get(where('work_days') != None)['work_days']

        week_work_hours = timedelta(seconds=int(work_days) *
                                    day_work_hours.total_seconds())
        self.worktime.update({'week_work_hours': str(week_work_hours)})

    def is_integer(self, n):
        try:
            float(n)
        except ValueError:
            return False
        else:
            return float(n).is_integer()

    def set_workdays(self, workdays='5'):
        if self.is_integer(workdays):
            if (int(workdays) >= 1) and (int(workdays) <= 7):
                self.worktime.update({'work_days': str(workdays)})
        else:
            print(
                f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [ERROR] workdays not a number'
            )

    def get_workdays(self):
        try:
            return ((self.worktime.get(
                where('work_days') != None))['work_days'])
        except:
            return '--:--'

    def set_database_update_period(self, update_period='01:00:00'):
        format_ = '%H:%M:%S'
        try:
            update_period = datetime.strptime(update_period, format_).time()
        except Exception as err:
            pass
        else:
            self.worktime.update({'update_period': str(update_period)})

    def get_update_period(self):
        try:
            return ((self.worktime.get(
                where('update_period') != None))['update_period'])
        except:
            return '--:--'

    def unify_time(self, datetime):
        return datetime.astimezone(self.local_timezone).replace(microsecond=0)

    def filter_work_hours(self, start_date, end_date):
        time_format = "%H:%M:%S"

        result_time = timedelta(hours=0, minutes=0, seconds=0)
        calculated_end_time = timedelta(hours=0, minutes=0, seconds=0)
        twelve_hours_delta = timedelta(hours=12, minutes=0)
        twenty_four_hours_delta = timedelta(hours=23, minutes=59, seconds=59)

        work_day_starts = self.worktime.get(
            where('work_day_starts') != None)['work_day_starts']
        work_day_ends = self.worktime.get(
            where('work_day_ends') != None)['work_day_ends']
        lunch_starts = self.worktime.get(
            where('lunch_hours_starts') != None)['lunch_hours_starts']
        lunch_ends = self.worktime.get(
            where('lunch_hours_ends') != None)['lunch_hours_ends']
        day_work_hours = self.worktime.get(
            where('day_work_hours') != None)['day_work_hours']

        work_day_starts = datetime.strptime(work_day_starts,
                                            time_format).time()
        work_day_ends = datetime.strptime(work_day_ends, time_format).time()
        lunch_starts = datetime.strptime(lunch_starts, time_format).time()
        lunch_ends = datetime.strptime(lunch_ends, time_format).time()
        day_work_hours = datetime.strptime(day_work_hours, time_format).time()

        while start_date <= end_date:
            till_the_end_of_he_day_delta = twenty_four_hours_delta - timedelta(
                hours=start_date.hour,
                minutes=start_date.minute,
                seconds=start_date.second)
            calculated_end_time = (start_date + till_the_end_of_he_day_delta)

            if calculated_end_time >= end_date:
                if calculated_end_time.time() > end_date.time():
                    calculated_end_time = end_date

            if start_date.weekday(
            ) < 5:  #этот день не выходной // сделать параметром чтоб менять первый день недели
                if (calculated_end_time.time() < work_day_starts
                    ):  #промежуток кончился раньше рабочего дня
                    pass

                elif (calculated_end_time.time() > work_day_starts) and (
                        calculated_end_time.time() <= lunch_starts
                ):  #промежуток кончился после начала рабочего дня но раньше обеда:

                    if start_date.time() <= work_day_starts:
                        result_time += timedelta(hours=calculated_end_time.hour, minutes=calculated_end_time.minute, seconds=calculated_end_time.second) - \
                                                    timedelta(hours=work_day_starts.hour, minutes=work_day_starts.minute, seconds=work_day_starts.second)

                    else:
                        result_time += timedelta(hours=calculated_end_time.hour, minutes=calculated_end_time.minute, seconds=calculated_end_time.second) - \
                                                    timedelta(hours=start_date.hour, minutes=start_date.minute, seconds=start_date.second)

                elif (calculated_end_time.time() > lunch_starts) and (
                        calculated_end_time.time() < lunch_ends
                ):  #промежуток кончился после начала обеда но раньше конца обеда:
                    if start_date.time() <= work_day_starts:
                        result_time += timedelta(hours=lunch_starts.hour, minutes=lunch_starts.minute, seconds=lunch_starts.second) - \
                                                    timedelta(hours=work_day_starts.hour, minutes=work_day_starts.minute, seconds=work_day_starts.second)

                    elif (start_date.time() > work_day_starts) and (
                            start_date.time() < lunch_starts):
                        result_time += timedelta(hours=lunch_starts.hour, minutes=lunch_starts.minute, seconds=lunch_starts.second) - \
                                                    timedelta(hours=start_date.hour, minutes=start_date.minute, seconds=start_date.second)

                    elif (start_date.time() >= lunch_starts):
                        pass

                elif (calculated_end_time.time() >= lunch_ends) and (
                        calculated_end_time.time() < work_day_ends
                ):  #промежуток кончился после конца обеда но раньше конца дня
                    if start_date.time() <= work_day_starts:
                        result_time += (timedelta(hours=lunch_starts.hour, minutes=lunch_starts.minute, seconds=lunch_starts.second) - \
                                                    timedelta(hours=work_day_starts.hour, minutes=work_day_starts.minute, seconds=work_day_starts.second)) + \
                                                    (timedelta(hours=calculated_end_time.hour, minutes=calculated_end_time.minute, seconds=calculated_end_time.second) - \
                                                    timedelta(hours=lunch_ends.hour, minutes=lunch_ends.minute, seconds=lunch_ends.second))

                    elif (start_date.time() > work_day_starts) and (
                            start_date.time() < lunch_starts):
                        result_time += (timedelta(hours=lunch_starts.hour, minutes=lunch_starts.minute, seconds=lunch_starts.second) - \
                                                    timedelta(hours=start_date.hour, minutes=start_date.minute, seconds=start_date.second)) + \
                                                    (timedelta(hours=calculated_end_time.hour, minutes=calculated_end_time.minute, seconds=calculated_end_time.second) - \
                                                    timedelta(hours=lunch_ends.hour, minutes=lunch_ends.minute, seconds=lunch_ends.second))

                    elif (start_date.time() >=
                          lunch_starts) and (start_date.time() < lunch_ends):
                        result_time += (timedelta(hours=calculated_end_time.hour, minutes=calculated_end_time.minute, seconds=calculated_end_time.second) - \
                                        timedelta(hours=lunch_ends.hour, minutes=lunch_ends.minute, seconds=lunch_ends.second))

                    elif (start_date.time() >= lunch_ends):
                        result_time += (timedelta(hours=calculated_end_time.hour, minutes=calculated_end_time.minute, seconds=calculated_end_time.second) - \
                                        timedelta(hours=start_date.hour, minutes=start_date.minute, seconds=start_date.second))

                elif (calculated_end_time.time() >=
                      work_day_ends):  #промежуток кончился позже рабочего дня
                    if start_date.time() <= work_day_starts:
                        result_time += timedelta(hours=day_work_hours.hour,
                                                 minutes=day_work_hours.minute,
                                                 seconds=day_work_hours.second)

                    elif (start_date.time() > work_day_starts) and (
                            start_date.time() < lunch_starts):
                        result_time += (timedelta(hours=lunch_starts.hour, minutes=lunch_starts.minute, seconds=lunch_starts.second) - \
                                                    timedelta(hours=start_date.hour, minutes=start_date.minute, seconds=start_date.second)) + \
                                                    (timedelta(hours=work_day_ends.hour, minutes=work_day_ends.minute, seconds=work_day_ends.second) - \
                                                    timedelta(hours=lunch_ends.hour, minutes=lunch_ends.minute, seconds=lunch_ends.second))

                    elif (start_date.time() >=
                          lunch_starts) and (start_date.time() < lunch_ends):
                        result_time += (timedelta(hours=work_day_ends.hour, minutes=work_day_ends.minute, seconds=work_day_ends.second) - \
                                        timedelta(hours=lunch_ends.hour, minutes=lunch_ends.minute, seconds=lunch_ends.second))

                    elif (start_date.time() >=
                          lunch_ends) and (start_date.time() <= work_day_ends):
                        result_time += (timedelta(hours=work_day_ends.hour, minutes=work_day_ends.minute, seconds=work_day_ends.second) - \
                                        timedelta(hours=start_date.hour, minutes=start_date.minute, seconds=start_date.second))

                    elif (start_date.time() > work_day_ends):
                        pass

            start_date += (till_the_end_of_he_day_delta + timedelta(minutes=1))

        return result_time

    def filter_reports_time(self, start_date, end_date, disable_filter=False):

        datetime_format = "%Y-%m-%d %H:%M:%S"
        filter_start_date = self.unify_time(
            datetime.strptime(self.filter_dates[0], datetime_format))
        filter_end_date = self.unify_time(
            datetime.strptime(self.filter_dates[1], datetime_format))

        result_time = timedelta(hours=0, minutes=0, seconds=0)

        if not disable_filter:

            #1
            if (start_date < filter_start_date) and (end_date <
                                                     filter_start_date):
                return result_time
            #2
            elif (start_date < filter_start_date) and (
                (end_date > filter_start_date) and
                (end_date < filter_end_date)):
                start_date = filter_start_date

                return self.filter_work_hours(start_date=start_date,
                                              end_date=end_date)
            #3
            elif (start_date < filter_start_date) and (end_date >
                                                       filter_end_date):
                start_date = filter_start_date
                end_date = filter_end_date

                return self.filter_work_hours(start_date=start_date,
                                              end_date=end_date)
            #4
            elif ((start_date > filter_start_date) and
                  (start_date < filter_end_date)) and (end_date <
                                                       filter_end_date):
                self.filter_work_hours(start_date=start_date,
                                       end_date=end_date)
            #5
            elif ((start_date > filter_start_date) and
                  (start_date < filter_end_date)) and (end_date >
                                                       filter_end_date):
                end_date = filter_end_date

                return self.filter_work_hours(start_date=start_date,
                                              end_date=end_date)
            #6
            elif (start_date > filter_end_date):
                return result_time

        else:
            #print("filter enabled!")
            return self.filter_work_hours(start_date=start_date,
                                          end_date=end_date)

    def get_card_stats_by_lists(self, card, disable_filter=False):

        board = self.trello_client.get_board(board_id=card.board_id)
        lists = board.list_lists()
        time_in_lists = {
            list_.id: {
                "time": timedelta(minutes=0)
            }
            for list_ in lists
        }

        ordered_list_movements = sorted(card.list_movements(),
                                        key=itemgetter("datetime"))

        if len(ordered_list_movements) == 0:

            time_in_lists[card.list_id]['time'] += self.filter_reports_time(
                start_date=card.created_date,
                end_date=self.unify_time(datetime.now()),
                disable_filter=disable_filter)  #!!!!!!!

        elif len(ordered_list_movements) == 1:
            time_start = card.created_date
            time_end = self.unify_time(ordered_list_movements[0]['datetime'])
            list_id = ordered_list_movements[0]['source']['id']

            time_in_lists[list_id]['time'] += self.filter_reports_time(
                start_date=time_start,
                end_date=time_end,
                disable_filter=disable_filter)

            time_start = self.unify_time(ordered_list_movements[0]['datetime'])
            time_end = self.unify_time(datetime.now())
            list_id = ordered_list_movements[0]['destination']['id']

            time_in_lists[list_id]['time'] += self.filter_reports_time(
                start_date=time_start,
                end_date=time_end,
                disable_filter=disable_filter)

        else:

            for change_index in range(0, len(ordered_list_movements)):
                list_id = ordered_list_movements[change_index]['source']['id']

                if change_index == 0:

                    time_in_lists[list_id]['time'] += self.filter_reports_time(
                        start_date=card.created_date,
                        end_date=self.unify_time(
                            ordered_list_movements[change_index]['datetime']),
                        disable_filter=disable_filter)

                elif change_index > 0:

                    time_start = ordered_list_movements[change_index -
                                                        1]['datetime']
                    time_end = ordered_list_movements[change_index]['datetime']

                    time_in_lists[list_id]['time'] += self.filter_reports_time(
                        start_date=self.unify_time(time_start),
                        end_date=self.unify_time(time_end),
                        disable_filter=disable_filter)

                    if change_index + 1 == len(ordered_list_movements):

                        time_start = ordered_list_movements[change_index][
                            'datetime']
                        time_end = datetime.now()

                        list_id = ordered_list_movements[change_index][
                            'destination']['id']
                        time_in_lists[list_id][
                            'time'] += self.filter_reports_time(
                                start_date=self.unify_time(time_start),
                                end_date=self.unify_time(time_end),
                                disable_filter=disable_filter)

        return time_in_lists

    def get_project_report(self, board_id, lists, members):
        self.db.drop_table('report')
        for list_id in lists:
            for member_id in members:
                query_result = self.local_cards_has_persons.search(
                    (where('board_id') == str(board_id))
                    & (where('person_id') == str(member_id)))

                for result in query_result:
                    try:
                        card = self.trello_client.get_card(
                            card_id=result['card_id'])
                        print(
                            f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [MSG]: got card {result["card_name"], result["card_id"]}'
                        )
                    except Exception as err:
                        print(
                            f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}: [ERROR]: {err}'
                        )
                    else:
                        card_lists_time = self.get_card_stats_by_lists(
                            card=card)

                        for time in card_lists_time:
                            if time == list_id:
                                key = f'{time}'
                                if card_lists_time.get(
                                        key)['time'] > timedelta(minutes=1):
                                    list_name_query = self.local_lists.get(
                                        (where('list_id') == str(time)))

                                    self.report.insert({
                                        'person_id':
                                        result['person_id'],
                                        'person_name':
                                        result['person_name'],
                                        'card_id':
                                        result['card_id'],
                                        'card_name':
                                        result['card_name'],
                                        'list_id':
                                        time,
                                        'list_name':
                                        list_name_query['list_name'],
                                        'list_time':
                                        str(card_lists_time.get(key)['time']),
                                        'board_id':
                                        result['board_id'],
                                        'board_name':
                                        result['board_name']
                                    })

    def convert_seconds_to_readable_time(self, seconds):
        min, sec = divmod(seconds, 60)
        hour, min = divmod(min, 60)
        return "%d:%02d:%02d" % (hour, min, sec)
示例#19
0
class TrelloBoardTestCase(unittest.TestCase):
    """
    Tests for TrelloClient API. Note these test are in order to
    preserve dependencies, as an API integration cannot be tested
    independently.
    """

    def setUp(self):
        self._trello = TrelloClient(os.environ['TRELLO_API_KEY'],
                                    token=os.environ['TRELLO_TOKEN'])
        for b in self._trello.list_boards():
            if b.name == os.environ['TRELLO_TEST_BOARD_NAME']:
                self._board = b
                break
        try:
            self._list = self._board.open_lists()[0]
        except IndexError:
            self._list = self._board.add_list('List')

    def _add_card(self, name, description=None):
        try:
            card = self._list.add_card(name, description)
            self.assertIsNotNone(card, msg="card is None")
            self.assertIsNotNone(card.id, msg="id not provided")
            self.assertEquals(card.name, name)
            return card
        except Exception as e:
            print(str(e))
            self.fail("Caught Exception adding card")

    def test40_add_card(self):
        name = "Testing from Python - no desc"
        card = self._add_card(name)

        self.assertIsNotNone(card.closed, msg="closed not provided")
        self.assertIsNotNone(card.url, msg="url not provided")

        card2 = self._trello.get_card(card.id)
        self.assertEqual(card.name, card2.name)

    def test41_add_card(self):
        name = "Testing from Python"
        description = "Description goes here"
        card = self._add_card(name, description)

        self.assertEquals(card.description, description)
        self.assertIsNotNone(card.closed, msg="closed not provided")
        self.assertIsNotNone(card.url, msg="url not provided")
        card.fetch()
        self.assertIsNotNone(card.member_id)
        self.assertIsNotNone(card.short_id)
        self.assertIsNotNone(card.list_id)
        self.assertIsNotNone(card.comments)
        self.assertIsNotNone(card.checklists)
        self.assertIsInstance(card.create_date, datetime)

    def test42_add_card_with_comments(self):
        name = "Card with comments"
        comment = "Hello World!"
        card = self._add_card(name)
        card.comment(comment)
        card.fetch(True)

        self.assertEquals(card.description, '')
        self.assertIsNotNone(card.closed, msg="closed not provided")
        self.assertIsNotNone(card.url, msg="url not provided")
        self.assertEquals(len(card.comments), 1)
        self.assertEquals(card.comments[0]['data']['text'], comment)

    def test43_delete_checklist(self):
        name = "Card with comments"
        card = self._list.add_card(name)
        card.fetch(True)

        name = 'Checklists'
        checklist = card.add_checklist(name,
                                       ['item1', 'item2'])
        self.assertIsNotNone(checklist, msg="checklist is None")
        self.assertIsNotNone(checklist.id, msg="id not provided")
        self.assertEquals(checklist.name, name)
        checklist.delete()
        card.delete()

    def test44_attach_url_to_card(self):
        name = "Testing from Python - url"
        card = self._add_card(name)

        card.attach(name='lwn', url='http://lwn.net/')
        card.fetch()
        self.assertEquals(card.badges['attachments'], 1)
        card.delete()

    def test52_get_cards(self):
        cards = self._board.get_cards()
        self.assertEquals(len(cards), 4)

        for card in cards:
            if card.name == 'Testing from Python':
                self.assertEqual(card.description, 'Description goes here')
            elif card.name == 'Testing from Python - no desc':
                self.assertEqual(card.description, '')
            elif card.name == 'Card with comments':
                self.assertEqual(card.description, '')
            else:
                self.fail(msg='Unexpected card found')

        self.assertIsInstance(self._board.all_cards(), list)
        self.assertIsInstance(self._board.open_cards(), list)
        self.assertIsInstance(self._board.closed_cards(), list)

    def test52_add_card_set_due(self):
        name = "Testing from Python"
        description = "Description goes here"
        card = self._list.add_card(name, description)

        # Set the due date to be 3 days from now
        today = datetime.today()
        day_detla = timedelta(3)
        due_date = today + day_detla
        card.set_due(due_date)
        expected_due_date = card.due
        # Refresh the due date from cloud
        card.fetch()
        actual_due_date = card.due[:10]
        self.assertEquals(expected_due_date, actual_due_date)
        # Note that set_due passes only the date, stripping time
        self.assertEquals(card.due_date.date(), due_date.date())

    def test53_checklist(self):
        name = "Testing from Python"
        description = "Description goes here"
        card = self._list.add_card(name, description)

        name = 'Checklists'
        checklist = card.add_checklist(name,
                                       ['item1', 'item2'])
        self.assertIsNotNone(checklist, msg="checklist is None")
        self.assertIsNotNone(checklist.id, msg="id not provided")
        self.assertEquals(checklist.name, name)
        checklist.rename('Renamed')
        self.assertEquals(checklist.name, 'Renamed')

    def test54_set(self):
        name = "Testing from Python"
        description = "Description goes here"
        card = self._list.add_card('noname')
        card.set_name(name)
        card.set_description(description)
        self.assertEquals(card.name, name)
        self.assertEquals(card.description, description)

    def test55_set_pos(self):
        card_names = lambda: [c.name for c in self._list.list_cards()]
        self._list.add_card('card1')
        card2 = self._list.add_card('card2')
        names = card_names()
        self.assertGreater(names.index('card2'), names.index('card1'))

        card2.set_pos('top')
        names = card_names()
        self.assertGreater(names.index('card1'), names.index('card2'))

        card2.set_pos('bottom')
        names = card_names()
        self.assertGreater(names.index('card2'), names.index('card1'))

    def test60_delete_cards(self):
        cards = self._board.get_cards()
        for card in cards:
            card.delete()

    def test70_all_members(self):
        self.assertTrue(len(self._board.all_members()) > 0)

    def test71_normal_members(self):
        self.assertTrue(len(self._board.normal_members()) >= 0)

    def test72_admin_members(self):
        self.assertTrue(len(self._board.admin_members()) > 0)

    def test73_owner_members(self):
        members = self._board.owner_members()
        self.assertTrue(len(members) > 0)
        member = members[0].fetch()
        self.assertNotEqual(member.status, None)
        self.assertNotEqual(member.id, None)
        self.assertNotEqual(member.bio, None)
        self.assertNotEqual(member.url, None)
        self.assertNotEqual(member.username, None)
        self.assertNotEqual(member.full_name, None)
        self.assertNotEqual(member.initials, None)
        member2 = self._trello.get_member(member.id)
        self.assertEqual(member.username, member2.username)

    def test80_unauthorized(self):
        client = TrelloClient('a')
        self.assertRaises(Unauthorized,
                          client.list_boards)

    def test81_resource_unavailable(self):
        self.assertRaises(ResourceUnavailable,
                          self._trello.get_card, '0')

    def test90_get_board(self):
        board = self._trello.get_board(self._board.id)
        self.assertEqual(self._board.name, board.name)
    def handle(self, *args, **options):
        trello = TrelloClient(settings.TRELLO_API_KEY, settings.TRELLO_TOKEN)
        master = Board.objects.get(name=settings.TRELLO_MASTER)

        updatedcards_ids = []

        for board in Board.objects.all().order_by('pk'):

            logger.info('Importing board {0}'.format(board.name))

            # search for the remote board
            b = board.remote_object(trello)

            # check if the board was updated since the last update
            if board.last_activity is not None and b.date_last_activity <= board.last_activity:
                logger.info('    - No activity detected')

            # If it is the first update then import all the lists from the board.
            if not board.last_activity:
                logger.info("*** FIRST IMPORT ***")

                for lst in board.boardlist_set.all():
                    l = lst.remote_object(trello)
                    lst.name = l.name
                    lst.closed = l.closed
                    lst.position = l.pos
                    lst.save()
                    lst.import_cards(l)

            else:
                # if is not the first board update, update only the latest modifications
                # the board was already imported once
                query = {
                    'since':
                    board.last_activity.isoformat(timespec='microseconds')
                }
                data = trello.fetch_json('/boards/' + board.remoteid +
                                         '/actions',
                                         query_params=query)

                ids = []
                for update in data:

                    action_type = update.get('type', None)
                    card_info = update['data'].get('card', None)
                    date_last_activity = dateparser.parse(update.get('date'))

                    if card_info:
                        card_id = card_info['id']

                        if action_type == 'deleteCard':
                            try:
                                card = Card.objects.get(remoteid=card_id)
                                card.last_activity = date_last_activity
                                card.delete_remotely = True
                                card.remoteid = None
                                card.save()
                                logger.info(
                                    "The card [{0}] in the board [{1}] was marked to be removed"
                                    .format(card.name,
                                            card.boardlist.board.name))
                            except Card.DoesNotExist:
                                # ignore
                                pass
                        else:
                            # append to the list all the modified cards ids
                            updatedcards_ids.append(card_id)

            board.last_activity = b.date_last_activity
            board.save()

        cards = []

        # search in all the cards from the master board,
        # which cards were updated
        b = master.remote_object(trello)
        for c in b.open_cards():
            try:
                card = Card.objects.get(remoteid=c.id)
                if card.last_activity < c.date_last_activity:
                    cards.append(c)
            except Card.DoesNotExist:
                pass

        # get all the remote cards.
        updatedcards_ids = list(set(updatedcards_ids))
        for idx, i in enumerate(updatedcards_ids):
            logger.info("Get remote card ({0}/{1})".format(
                idx + 1, len(updatedcards_ids)))
            cards.append(trello.get_card(i))

        # sort the cards by activity, so the latest card is the one updated
        cards = sorted(cards, key=lambda x: x.date_last_activity)

        lists = {}  # cache all the boards lists

        for c in cards:
            # check if the boad list is already in cache, otherwise add it
            if c.list_id not in lists:
                lists[c.list_id] = BoardList.objects.get(remoteid=c.list_id)

            try:
                card = Card.objects.get(remoteid=c.id)

                # the card list is diferent, mark it to update
                if card.name != c.name:
                    card.update_name = True
                    card.name = c.name

                if card.desc != c.description:
                    card.update_desc = True
                    card.desc = c.description

                if card.closed != c.closed:
                    card.update_closed = True
                    card.closed = c.closed

                if card.boardlist != lists[c.list_id]:
                    card.update_list = True
                    card.boardlist = lists[c.list_id]

            except Card.DoesNotExist:
                # the card does not exists, create it
                card = Card(remoteid=c.id)
                card.name = c.name
                card.desc = c.description
                card.closed = c.closed
                card.boardlist = lists[c.list_id]

            card.position = c.pos
            card.last_activity = c.date_last_activity
            card.save()
            card.update_members_by_id(trello, c.member_id)
            card.update_labels_by_id(trello, c.idLabels)

            logger.info(
                "Updated card [{1} > {2} > {0}]: name:{3}, description:{4}, closed:{5}, list:{6}, members:{7}, labels:{8}"
                .format(card.name, card.boardlist.board.name,
                        card.boardlist.name, card.update_name,
                        card.update_desc, card.update_closed, card.update_list,
                        card.update_members, card.update_labels))
示例#21
0
class TrelloClient:
    def __init__(self, api_key, api_secret, token, token_secret):
        self.trello_client = Client(api_key=api_key,
                                    api_secret=api_secret,
                                    token=token,
                                    token_secret=token_secret)
        self._uid = None
        self._project = None
        self._board = None
        self._lists = None
        self._board_labels = None
        self._lists_filter = None
        self._only_my_cards = False

    @property
    def whoami(self):
        """
        Get my Trello UID

        :return: my Trello UID
        :rtype: string
        """
        if self._uid is None:
            self._uid = self.trello_client.get_member('me').id
        return self._uid

    def project(self, project):
        """
        Set the class working project

        :param project: TelloWarrior project object
        """
        if self._project == None or self._project.name != project.name:
            self._board = self.get_board(project.trello_board_name)
            self._lists = self.get_lists()
            self._board_labels = self.get_board_labels()
            self._lists_filter = project.trello_lists_filter
            self._only_my_cards = project.only_my_cards

    def get_board(self, board_name):
        """
        Get a open Trello board from name, if it does not exist create it

        :param board_name: the board name
        :return: a Tello board
        :rtype: Trello board object
        """
        for trello_board in self.trello_client.list_boards(
                board_filter='open'):
            if trello_board.name == board_name and not trello_board.closed:
                logger.debug('Trello board {} found'.format(board_name))
                return trello_board
        logger.debug('Creating Trello board {}'.format(board_name))
        return self.trello_client.add_board(board_name)

    def get_lists(self):
        """
        Get the open lists of a Trello board

        :return: a list of Trello list objects
        :rtype: list
        """
        return self._board.open_lists()

    def get_list(self, list_name):
        """
        Get a Trello list from list name, if it does not exist create it

        :param list_name: the list name
        :return: a Tello list
        :rtype: Trello list object
        """
        if self._lists == None:
            raise ClientError('get_list')
        for trello_list in self._lists:
            if trello_list.name == list_name:
                logger.debug('Trello list {} found'.format(list_name))
                return trello_list
        logger.debug('Creating Trello list {}'.format(list_name))
        trello_list = self._board.add_list(list_name)
        self._lists.append(trello_list)  # Update _lists with new list
        return trello_list

    def get_board_labels(self):
        """
        Get the labels of a Trello board

        :param board_name: the board name
        :return: a list of Trello label objects
        :rtype: list
        """
        return self._board.get_labels()

    def get_board_label(self, label_name):
        """
        Get a Trello board label from label name, if it does not exist create it

        :param label_name: the label name
        :return: a Tello label
        :rtype: Trello label object
        """
        if self._board_labels == None:
            raise ClientError('get_board_label')
        for board_label in self._board_labels:
            if board_label.name == label_name:
                logger.debug('Trello board label {} found'.format(label_name))
                return board_label
        logger.debug('Creating Trello board label {}'.format(label_name))
        board_label = self._board.add_label(label_name, 'black')
        self._board_labels.append(
            board_label)  # Update _board_labels with new label
        return board_label

    def get_cards_dict(self):
        """
        Get all cards of a list of Trello lists in a dictionary

        :return: a dict with Cards
        :rtype: dict
        """
        trello_cards_dict = {}
        if self._lists_filter is not None:
            trello_lists = filter(
                lambda trello_list: trello_list.name not in self._lists_filter,
                self._lists)
        for trello_list in trello_lists:
            logger.debug('Getting Trello cards of list {}'.format(
                trello_list.name))
            trello_cards_dict[trello_list.name] = trello_list.list_cards()
            if self._only_my_cards:
                trello_cards_dict[trello_list.name] = filter(
                    lambda trello_card: self.whoami in trello_card.member_ids,
                    trello_cards_dict[trello_list.name])
        return trello_cards_dict

    def delete_trello_card(self, trello_card_id):
        """
        Delete (forever) a Trello card by ID

        :param trello_card_id: ID of Trello card
        """
        try:
            self.trello_client.get_card(trello_card_id).delete()
        except ResourceUnavailable:
            logger.warning(
                'Cannot find Trello card with ID {} deleted in Task Warrior. Maybe you also deleted it in Trello?'
                .format(trello_card_id))
示例#22
0
def generator(request):

    # create variables
    ingredient_list = {}
    context_dict = {}

    # get ll recipe types from database
    recipe_types = RecipeType.objects.all()
    context_dict['recipe_types'] = recipe_types

    # check if any button has been pushed and a POST object has been created
    if request.method == 'POST':

        # collect all the food types from the select boxes
        responses = {u'Måndag': request.POST['monday'],
                     u'Tisdag': request.POST['tuesday'],
                     u'Onsdag': request.POST['wednesday'],
                     u'Torsdag': request.POST['thursday'],
                     u'Fredag': request.POST['friday'],
                     u'Lördag': request.POST['saturday'],
                     u'Söndag': request.POST['sunday']}

        # collect number of portions from portions select boxes
        portions = {u'Måndag': request.POST['monday_portions'],
                    u'Tisdag': request.POST['tuesday_portions'],
                    u'Onsdag': request.POST['wednesday_portions'],
                    u'Torsdag': request.POST['thursday_portions'],
                    u'Fredag': request.POST['friday_portions'],
                    u'Lördag': request.POST['saturday_portions'],
                    u'Söndag': request.POST['sunday_portions']}

        fast = {u'Måndag': request.POST['monday_fast'],
                u'Tisdag': request.POST['tuesday_fast'],
                u'Onsdag': request.POST['wednesday_fast'],
                u'Torsdag': request.POST['thursday_fast'],
                u'Fredag': request.POST['friday_fast'],
                u'Lördag': request.POST['saturday_fast'],
                u'Söndag': request.POST['sunday_fast']}

        # if generate button is pushed
        if 'generate' in request.POST:

            # create empty data structure for matlista
            matlista = gen_empty_matlista()

            # loop over each day and generate a random food (if not NONE). Then multiply
            # the quantity of each ingredient with the number of portions selected.
            for day in responses:
                if responses[day] != 'None':

                    gen_random_food(day, responses[day], matlista, fast[day])
                    multiply_portions(day, portions[day], matlista)

        # check if button to generate new dish on monday has been pushed
        elif 'random_monday' in request.POST:

            # fetch matlista object from session
            day = u'Måndag'
            matlista = request.session['matlista']

            # generate a random recepie and update matlista.
            if responses[day] != 'None':
                gen_random_food(day,responses[day], matlista, fast[day])
                multiply_portions(day, portions[day], matlista)

        # check if any of the other days buttons has been pushed
        elif 'random_tuesday' in request.POST:

            day = u'Tisdag'
            matlista = request.session['matlista']

            if responses[day] != 'None':
                gen_random_food(day,responses[day], matlista, fast[day])
                multiply_portions(day, portions[day], matlista)

        elif 'random_wednesday' in request.POST:

            day = u'Onsdag'
            matlista = request.session['matlista']

            if responses[day] != 'None':
                gen_random_food(day,responses[day], matlista, fast[day])
                multiply_portions(day, portions[day], matlista)

        elif 'random_thursday' in request.POST:

            day = u'Torsdag'
            matlista = request.session['matlista']

            if responses[day] != 'None':
                gen_random_food(day,responses[day], matlista, fast[day])
                multiply_portions(day, portions[day], matlista)

        elif 'random_friday' in request.POST:

            day = u'Fredag'
            matlista = request.session['matlista']

            if responses[day] != 'None':
                gen_random_food(day,responses[day], matlista, fast[day])
                multiply_portions(day, portions[day], matlista)

        elif 'random_saturday' in request.POST:

            day = u'Lördag'
            matlista = request.session['matlista']

            if responses[day] != 'None':
                gen_random_food(day,responses[day], matlista, fast[day])
                multiply_portions(day, portions[day], matlista)

        elif 'random_sunday' in request.POST:

            day = u'Söndag'
            matlista = request.session['matlista']

            if responses[day] != 'None':
                gen_random_food(day,responses[day], matlista, fast[day])
                multiply_portions(day, portions[day], matlista)

        # check if any manual dish selection has been done for monday
        elif 'select_monday_btn' in request.POST:

            day = u'Måndag'
            # get the name of the recipe selected from session
            name = request.POST['select_monday']
            # get matlsta sesion object
            matlista = request.session['matlista']
            #update matlista with the new dish
            gen_dish(day,name, matlista)
            multiply_portions(day, portions[day], matlista)

        # check if any of the other days buttons has been pushed
        elif 'select_tuesday_btn' in request.POST:

            day = u'Tisdag'
            name = request.POST['select_tuesday']
            matlista = request.session['matlista']
            gen_dish(day,name, matlista)
            multiply_portions(day, portions[day], matlista)

        elif 'select_wednesday_btn' in request.POST:

            day = u'Onsdag'
            name = request.POST['select_wednesday']
            matlista = request.session['matlista']
            gen_dish(day,name, matlista)
            multiply_portions(day, portions[day], matlista)

        elif 'select_thursday_btn' in request.POST:

            day = u'Torsdag'
            name = request.POST['select_thursday']
            matlista = request.session['matlista']
            gen_dish(day,name, matlista)
            multiply_portions(day, portions[day], matlista)

        elif 'select_friday_btn' in request.POST:

            day = u'Fredag'
            name = request.POST['select_friday']
            matlista = request.session['matlista']
            gen_dish(day,name, matlista)
            multiply_portions(day, portions[day], matlista)

        elif 'select_saturday_btn' in request.POST:

            day = u'Lördag'
            name = request.POST['select_saturday']
            matlista = request.session['matlista']
            gen_dish(day,name, matlista)
            multiply_portions(day, portions[day], matlista)

        elif 'select_sunday_btn' in request.POST:

            day = u'Söndag'
            name = request.POST['select_sunday']
            matlista = request.session['matlista']
            gen_dish(day,name, matlista)
            multiply_portions(day, portions[day], matlista)

        # check if the send to trello button has been pushed.
        elif 'trello' in request.POST and request.user.is_authenticated():

            # get matlista object and ingredient object from session.
            matlista = request.session['matlista']

            # if there are any ingredients
            if request.session['ingredient_strings']:

                ingredients = request.session['ingredient_strings']
                trello_data = Trello.objects.filter(user=request.user).first()

                # create a trello client object, connect and authenticate
                trello_client = TrelloClient(
                    api_key = trello_data.api_key,
                    api_secret = trello_data.api_secret,
                    token = trello_data.token,
                    token_secret = trello_data.token_secret
                )

                # get matlistan card
                matlistan_card = trello_client.get_card(trello_data.matlista_card_url)

                # add matlista as comment
                matlistan_card.comment(u'Måndag : ' + unicode(matlista[u'Måndag']['dish']) + '\n\n' +
                                               u'Tisdag : ' + unicode(matlista[u'Tisdag']['dish']) + '\n\n' +
                                               u'Onsdag : ' + unicode(matlista[u'Onsdag']['dish']) + '\n\n' +
                                               u'Torsdag : ' + unicode(matlista[u'Torsdag']['dish']) + '\n\n' +
                                               u'Fredag : ' + unicode(matlista[u'Fredag']['dish']) + '\n\n' +
                                               u'Lördag : ' + unicode(matlista[u'Lördag']['dish']) + '\n\n' +
                                               u'Söndag : ' + unicode(matlista[u'Söndag']['dish']) + '\n\n')

                handlingslista_card = trello_client.get_card(trello_data.handlingslista_card_url)
                handlingslista_card.add_checklist('handlingslista', ingredients)

        # save matlist object in session
        request.session['matlista'] = matlista

        # loop over each day.
        for day in matlista:
            # For all the ingredients that day
            for ingredient in matlista[day]['ingredients']:
                # check if a ingredient is already in the ingredient list
                if ingredient in ingredient_list:
                    # if the ingredient is in the list and has the same unit. add the
                    # quantity to the ingredient in the ingredient list
                    if matlista[day]['ingredients'][ingredient]['unit'] == ingredient_list[ingredient]['unit']:
                        quant_to_add = matlista[day]['ingredients'][ingredient]['quantity']
                        ingredient_list[ingredient]['quantity'] += quant_to_add

                    # if the ingredient is in the list but the ingredient doe not have the same type of
                    # unit, flag it as a unit conflict for user to resolve.
                    else:
                        ingredient_list.update(copy.deepcopy({ingredient + ' - UNIT CONFLICT' : matlista[day]['ingredients'][ingredient]}))

                # if the ingredient is not in the ingredient list add it to the list
                else:
                    ingredient_list.update(copy.deepcopy({ingredient: matlista[day]['ingredients'][ingredient]}))

        # create a list for storing final ingredients as strings
        # ready to be sent to template.
        ingredient_strings = []

        # loop over ingredients in ingredient list and make string in
        # format "ingredient-quantity ingredient-unit ingredient-name"
        # and save to sting list
        for ingredient in ingredient_list:
            name = ingredient
            quantity = ingredient_list[ingredient]['quantity']
            unit = ingredient_list[ingredient]['unit']
            ingredient_strings.append(unicode(quantity) + ' ' + unit + ' ' + name)

        #save ingredient string list to session
        request.session['ingredient_strings'] = ingredient_strings

        # create lists of manual recepie selction
        dish_type = RecipeType.objects.filter(name=responses[u'Måndag']).first()
        monday_recipes = Recipe.objects.all().filter(food_type=dish_type)
        dish_type = RecipeType.objects.filter(name=responses[u'Tisdag']).first()
        tuesday_recipes = Recipe.objects.all().filter(food_type=dish_type)
        dish_type = RecipeType.objects.filter(name=responses[u'Onsdag']).first()
        wednesday_recipes = Recipe.objects.all().filter(food_type=dish_type)
        dish_type = RecipeType.objects.filter(name=responses[u'Torsdag']).first()
        thursday_recipes = Recipe.objects.all().filter(food_type=dish_type)
        dish_type = RecipeType.objects.filter(name=responses[u'Fredag']).first()
        friday_recipes = Recipe.objects.all().filter(food_type=dish_type)
        dish_type = RecipeType.objects.filter(name=responses[u'Lördag']).first()
        saturday_recipes = Recipe.objects.all().filter(food_type=dish_type)
        dish_type = RecipeType.objects.filter(name=responses[u'Söndag']).first()
        sunday_recipes = Recipe.objects.all().filter(food_type=dish_type)

        # store in context dic and send to template
        context_dict['monday_recipes'] = monday_recipes
        context_dict['tuesday_recipes'] = tuesday_recipes
        context_dict['wednesday_recipes'] = wednesday_recipes
        context_dict['thursday_recipes'] = thursday_recipes
        context_dict['friday_recipes'] = friday_recipes
        context_dict['saturday_recipes'] = saturday_recipes
        context_dict['sunday_recipes'] = sunday_recipes
        context_dict['matlista'] = matlista
        context_dict['ingredient_strings'] = ingredient_strings

    # if no POST data create an empty data structure and save it in session
    else:

        matlista = gen_empty_matlista()
        request.session['matlista'] = matlista


    return render(request, 'generator.html', context=context_dict)
示例#23
0
targetlist = []

for item in updated_list:
    targetlist.append(item['data']['card']['id'])

for item in created_list:
    targetlist.append(item['data']['card']['id'])

result_target = list(set(targetlist))

# travel each card by id and format dict

payload = {}
es = Elasticsearch("es_address:port")

for item in result_target:
    currentcard = client.get_card(item)
    payload['id'] = currentcard.id
    payload['shortUrl'] = currentcard.short_url
    payload['dateLastActivity'] = str(currentcard.dateLastActivity)[:-22]
    payload['desc'] = currentcard.description
    payload['name'] = currentcard.name

    # insert date to es
    result = es.index(index="tm_trello_card",
                      doc_type="card",
                      id=payload['id'],
                      body=payload)

    logger.info("updated es data %s", str(result))