Teambition is a cross-platform team collaboration and project management tool, equivalent to Trello. Teambition allows you to manage your project progress in the same way you manage a whiteboard and sticky paper, as shown in the following figure.

Teambition is easy to manage projects, but if you create a task corresponding to a project directly on Teambition, it is easy to fall into the awkward situation of facing a blank board and not knowing how to split tasks. As shown in the figure below.

What tasks should I add to this empty window? Think directly, I’m afraid it’s easy to lose one thing and lose another or simply miss the task.

When I want to start a project, I don’t just open Teambition and write tasks. I use an outline tool — Workflowy to streamline my thinking and divide tasks. When the task is segmented, transcribe it to Teambition, as shown in the picture below.

But there is a problem: write the tasks you need to do on Workflowy first. Then open Teambition and transfer these tasks to Teambition. In order to reduce duplication of effort in the copying step, TeamFlowy is a small tool. It is used to automatically transcribe specific entries in Workflowy to Teambition.

Function is introduced

TeamFlowy is a Python script that, when run, logs into the Workflowy account and reads all of the above entries. The entry named [Teambition] is the mark at the start of the task. The level below this entry is added to Teambition as a task. If there are secondary entries below the task, they are added to the task as subtasks. Teambition organizes a project in the form of project-stage-task-subtask (where Stage corresponds to the panel under the project in Teambition, for example, ‘to be processed’, ‘in progress’, ‘done’). There is no subtask for subtask, so in Workflowy, [Teambition] has at most two level indentation below it. As shown in the figure below.

Realize the principle of

Workflowy

To get the entry on Workflowy, perform three steps:

  1. Login Workflowy
  2. Gets the JSON strings corresponding to all entries
  3. Extracts the entry that you want to add to Teambition

Login Workflowy

Open Chrome monitoring login Wokrflowy process, you can see the login Workflowy needs access interface is: https://workflowy.com/accounts/login/. Send the request using HTTP POST, submit data including username, password, and an unknown next. As shown in the figure below.

Use Python’s third-party networking module Requests to send a POST request to this module, submitting a user name and password to log in. The code is as follows:

login_url = 'https://workflowy.com/accounts/login/'
session = requests.Session()
session.post(login_url,
             data={'username': '[email protected]'.'password': '8888888'.'next': ' '})Copy the code

Get all entries

After logging in to Workflowy using Requests’s session, Cookies are automatically saved to the Session object. Using session to continue access Workfowy, you can view your entries as you logged in.

Through Chrome can see access to all the entries of interface for https://workflowy.com/get_initialization_data?client_version=18, the interface the data returned is a mega JSON string containing all the entries, as shown in the figure below.

Using Python’s JSON module, you can parse this JSON string into a dictionary and retrieve all entries as follows:

outline_url = 'https://workflowy.com/get_initialization_data?client_version=18'
outlines_json = session.get(outline_url).text
outlines_dict = json.loads(outlines_json)
project_list = outlines_dict.get('projectTreeData', {})\
    .get('mainProjectTreeInfo', {})\
    .get('rootProjectChildren'[]),Copy the code

Extract tasks and subtasks

All entries are nested layer by layer in a list-dictionary structure that looks like this:

{
    "ch": [sub-entry],"lm": 308496."id": "957996b9-67ce-51c7-a796-bfbee44e3d3f"."nm": "AutoEmo"
}Copy the code

Where nm is the name of the entry. If an entry has children, then there will be many dictionaries in the CH list, each of which will have this structure. If an entry has no children, then there will be no ch key. So it’s nested layer by layer:

 {
    "ch": [{"lm": 558612."id": "5117e20b-25ba-ba91-59e1-790c0636f78e"."nm": "Prepare and memorize an introduction for any situation where you need to introduce yourself."
        }, 
        {
            "lm": 558612."id": "4894b23e-6f47-8028-a26a-5fb315fc4e6f"."nm": "Name, where you're from, what kind of job?"."ch": [{"lm": 5435246."id": "4894b23e-6f47-8028-a26a-5fbadfasdc4e6f"."nm": "Work Experience"}}]]."lm": 558612."id": "ea282a1c-94f3-1a44-c5b3-7907792e9e6e"."nm": "Introduce yourself"
}Copy the code

Since the structure of an entry is the same as that of its children, each entry can be resolved recursively. Since you need to add tasks to Teambition, start with the entry named [Teambition], you can resolve this using a function like this:

task_dict = {}
def extract_task(sections, task_dict, target_section=False):
    for section in sections:
        name = section['nm']
        if target_section:
            task_dict[name] = [x['nm'] for x in section.get('ch'], [])continue

        if name == '[Teambition]':
            target_section = True
        sub_sections = section.get('ch', [])
        extract_task(sub_sections, task_dict, target_section=target_section)Copy the code

The following is an item that needs to be added to Teambition. When running this function, it results in:

{'login Workflowy': [].'Get content that needs to be added to Teambition': ['Get task'.'Get subtasks'].'Debug Teambition API': [].'Add task to Teambition': []}Copy the code

Teambition

To add a task to Teambition, log in to Teambition using the Python SDK of Teambition and call the API to add the task. The Python SDK of Teambition has a pit when accessing access_token using OAuth2. It needs special attention.

Login Teambition

Set Teambition application

Teambition uses OAuth2 for permission authentication, so it needs to get access_token.

First open the Developer center of Teambition and click New Application as shown below.

You can write the name of the application as you like. After creating an application, you can view the information about the application. Record the Client ID and Secret, as shown in the following figure.

Click the OAuth2 configuration on the left and fill in the callback URL as shown below. The URL here can be the domain name of any accessible website, for example my blog address.

Obtain access_token using Python

Install Teambition SDK in Python first:

pip install teambitionCopy the code

Next, get the authorization URL in Python:

from teambition import Teambition

tb_client_id = '7bfae080-a8dc-11e7-b543-77a936726657'
tb_client_secret = '9830fc8c-81b3-45ed-b3c0-e039ab8f2d8b'
tb = Teambition(tb_client_id,
                tb_client_secret)
authorize_url = tb.oauth.get_authorize_url('https://kingname.info')
print(authorize_url)Copy the code

When the code runs, it gets an authorization URL that looks like this:

https://account.teambition.com/oauth2/authorize?client_id=7bfae080-a8dc-11e7-b543-77a936726657&redirect_uri=https://kingname.info&state=&lang=zhCopy the code

Manually accessing this URL in a computer browser will bring up a page like the following.

Click Authorize and Log in. You can see that the url on your browser changes to something like: https://kingname.info/?code=Pn7ebs4sZh3NYOz2FvVJQ4uu. In this case, record the string following code=Pn7ebs4sZh3NYOz2FvVJQ4uu.

To obtain the access_token, you need only the following two codes:

code = 'Pn7ebs4sZh3NYOz2FvVJQ4uu' # string in previous browser
tb.oauth.fetch_access_token(code)
The above code does the authorization, then directly use tb.xxxx to operate the task.Copy the code

But in fact, this code is bound to report an error. Prompt Grant Invaild. To solve this problem, it is necessary to manually obtain the access_token using the HTTP interface of Teambition.

code = 'Pn7ebs4sZh3NYOz2FvVJQ4uu' # string in previous browser
fetch_result_dict = session.post('https://account.teambition.com/oauth2/access_token',
                  data={'client_id': tb_client_id,
                        'client_secret': tb_client_secret,
                        'code': code,
                        'grant_type': 'code'}).json()
tb_access_token = fetch_result_dict.get('access_token'.' ')Copy the code

The resulting access_token is a very long string. Next, reinitialize the TB variable:

tb = Teambition(tb_client_id,
                tb_client_secret,
                access_token=tb_access_token)Copy the code

After initialization, you can perform various operations on projects and tasks using the TB variable.

Simple use of Teambition

To create a task within a project, you need to know the project ID. First, manually create a project in Teambition, open the project in the browser, you can see the project ID in the URL, as shown below.

Once you have a project ID, you can create a task using the following code:

    def create_task(task_name, sub_task_list):
        tasklist = tb.tasklists.get(project_id='59d396ee1013d919f3348675') [0]
        tasklist_id = tasklist['_id']
        todo_stage_id = tasklist['stageIds'] [0]
        task_info = tb.tasks.create(task_name, tasklist_id=tasklist_id, stage_id=todo_stage_id)
        if sub_task_list:
            task_id = task_info['_id']
            for sub_task_name in sub_task_list:
                tb.subtasks.create(sub_task_name, task_id=task_id)
        print(f'task: {task_name} with sub tasks: {sub_task_list} added.')Copy the code

This code first uses tb.tasklists. Get () to get the ID of the task group and the ID of the panel to be processed based on the project ID, then calls the tB.tasks.create () interface to add the task. Call tb.subtasks.create() to add the subtask ID based on the task ID.

Effect of the test

The above code implements the basic logic of TeamFlowy. After running the TeamFlowy script, the task under [Teambition] is successfully added to Teambition, as shown below.

Put the code together and refine it to make it easier to use. The complete code can be found at github.com/kingname/Te… . The complete code is shown below.