From f6a72b0a19a4cca73ea4d5c48ad39d23fe2817a8 Mon Sep 17 00:00:00 2001
From: magnus2142 <magnus.bredeli@hotmail.com>
Date: Fri, 1 Apr 2022 18:06:49 +0200
Subject: [PATCH] Added more create content methods

---
 bbcli/cli.py                            |  7 ++-
 bbcli/commands/contents.py              | 79 ++++++++++++++++++++++---
 bbcli/services/announcements_service.py |  2 +-
 bbcli/services/contents_service.py      | 59 +++++++++++++++---
 bbcli/services/courses_service.py       |  9 ++-
 bbcli/services/utils/content_builder.py |  4 +-
 bbcli/utils/utils.py                    |  2 +-
 7 files changed, 137 insertions(+), 25 deletions(-)

diff --git a/bbcli/cli.py b/bbcli/cli.py
index 279f9b8..efa09ae 100644
--- a/bbcli/cli.py
+++ b/bbcli/cli.py
@@ -13,7 +13,7 @@ import click
 
 from bbcli.commands.courses import list_courses
 from bbcli.commands.announcements import list_announcements, create_announcement, delete_announcement, update_announcement
-from bbcli.commands.contents import list_contents, create_content, create_document, create_file
+from bbcli.commands.contents import create_courselink, create_folder, list_contents, create_content, create_document, create_file, create_web_link
 from bbcli.services.authorization_service import login
 
 load_dotenv()
@@ -110,4 +110,7 @@ def create(ctx):
 
 # create.add_command(create_content)
 create.add_command(create_document)
-create.add_command(create_file)
\ No newline at end of file
+create.add_command(create_file)
+create.add_command(create_web_link)
+create.add_command(create_folder)
+create.add_command(create_courselink)
\ No newline at end of file
diff --git a/bbcli/commands/contents.py b/bbcli/commands/contents.py
index b740156..bcbd748 100644
--- a/bbcli/commands/contents.py
+++ b/bbcli/commands/contents.py
@@ -1,21 +1,25 @@
 from datetime import datetime
 import click
-from bbcli.entities.content_builder_entitites import FileOptions, StandardOptions
+from bbcli.entities.content_builder_entitites import FileOptions, StandardOptions, WeblinkOptions
 from bbcli.services import contents_service
 from bbcli.views import content_view
 import os
 
 def standard_options(function):
-    function = click.option('-h', '--hide-content', is_flag=True)(function)
-    function = click.option('-r', '--reviewable', is_flag=True)(function)
-    function = click.option('--start-date', type=str)(function)
-    function = click.option('--end-date', type=str)(function)
+    function = click.option('-h', '--hide-content', is_flag=True, help='Hide contents for students')(function)
+    function = click.option('-r', '--reviewable', is_flag=True, help='Make content reviewable')(function)
+    function = click.option('--start-date', type=str, help='When to make content available. Format: DD/MM/YY HH:MM:SS')(function)
+    function = click.option('--end-date', type=str, help='When to make content unavailable. Format: DD/MM/YY HH:MM:SS')(function)
     return function
 
 def file_options(function):
     function = click.option('-n', '--new-window', 'launch_in_new_window', is_flag=True)(function)
     return function
 
+def web_link_options(function):
+    function = click.option('-n', '--new-window', 'launch_in_new_window', is_flag=True)(function)
+    return function
+
 
 #, help='List a spesific course with the corresponding id'
 @click.command(name='list')
@@ -24,7 +28,6 @@ def file_options(function):
 # @click.option('-a', '--all/--no-all', 'show_all', default=False, help='Lists all courses you have ever been signed up for')
 @click.pass_context
 def list_contents(ctx, course_id: str=None, content_id: str=None):
-
     """
     This command lists contents of a course.
     """
@@ -57,7 +60,7 @@ def upload_file(ctx):
 @click.pass_context
 def create_document(ctx, course_id: str, parent_id: str, title: str, hide_content: bool, reviewable: bool, start_date: str=None, end_date: str=None):
     """
-    Creates a document content in blackboard
+    Creates a document content
     """
 
     standard_options = StandardOptions(hide_content=hide_content, reviewable=reviewable)
@@ -79,7 +82,7 @@ def create_file(ctx, course_id: str, parent_id: str, title: str, file_path: str,
                         launch_in_new_window:bool, hide_content: bool, reviewable: bool,
                         start_date: str=None, end_date: str=None):
     """
-    Creates a file content in blackboard
+    Creates a file content
     """
 
     file_options = FileOptions(launch_in_new_window)
@@ -104,3 +107,63 @@ def validate_dates(standard_options: StandardOptions, start_date: str, end_date:
             click.echo('Value format is not valid, please see --help for more info')
             raise click.Abort()
 
+
+
+@click.command(name='web-link')
+@click.argument('course_id', required=True, type=str)
+@click.argument('parent_id', required=True, type=str)
+@click.argument('title', required=True, type=str)
+@click.argument('url', required=True, type=str)
+@standard_options
+@web_link_options
+@click.pass_context
+def create_web_link(ctx, course_id: str, parent_id: str, title: str, url: str, 
+                        launch_in_new_window:bool, hide_content: bool, reviewable: bool,
+                        start_date: str=None, end_date: str=None):
+    """
+    Create a web link content
+    """
+    web_link_options = WeblinkOptions(launch_in_new_window)
+    standard_options = StandardOptions(hide_content, reviewable)
+    validate_dates(standard_options, start_date, end_date)
+    response = contents_service.create_externallink(ctx.obj['SESSION'], course_id, parent_id, title, url, web_link_options, standard_options)
+    print(response)
+
+
+@click.command(name='folder')
+@click.argument('course_id', required=True, type=str)
+@click.argument('title', required=True, type=str)
+@click.option('-p', '--parent_id', required=False, type=str, help='Id of parent folder')
+@click.option('--is-bb-page', is_flag=True, help='Make folder a blackboard page')
+@standard_options
+@click.pass_context
+def create_folder(ctx, course_id: str, parent_id: str, title: str,
+                        hide_content: bool, reviewable: bool, is_bb_page: bool = False,
+                        start_date: str=None, end_date: str=None):
+    """
+    Create a folder either in top level or inside another content
+    """
+    standard_options = StandardOptions(hide_content, reviewable)
+    validate_dates(standard_options, start_date, end_date)
+    response = contents_service.create_folder(ctx.obj['SESSION'], course_id, parent_id, title, is_bb_page, standard_options)
+    print(response)
+
+@click.command(name='course-link')
+@click.argument('course_id', required=True, type=str)
+@click.argument('parent_id', required=True, type=str)
+@click.argument('title', required=True, type=str)
+@click.argument('target_id', required=True, type=str)
+@standard_options
+@click.pass_context
+def create_courselink(ctx, course_id: str, parent_id: str, title: str, target_id: str,
+                        hide_content: bool, reviewable: bool, 
+                        start_date: str=None, end_date: str=None):
+    """
+    Create a course link content which redirects user to the target content
+    """
+    standard_options = StandardOptions(hide_content, reviewable)
+    validate_dates(standard_options, start_date, end_date)
+    response = contents_service.create_courselink(ctx.obj['SESSION'], course_id, parent_id, title, target_id, standard_options)
+    print(response)
+
+
diff --git a/bbcli/services/announcements_service.py b/bbcli/services/announcements_service.py
index 985bd53..b8689ba 100644
--- a/bbcli/services/announcements_service.py
+++ b/bbcli/services/announcements_service.py
@@ -68,7 +68,7 @@ def delete_announcement(session: requests.Session, course_id: str, announcement_
 def update_announcement(session: requests.Session, course_id: str, announcement_id: str):
 
     announcement = list_announcement(session=session, course_id=course_id, announcement_id=announcement_id)
-    MARKER = '# Everything below is ignored\n'
+    MARKER = '# Everything below is ignored.\n'
     editable_data = {
         'title': announcement['title'],
         'body': announcement['body'],
diff --git a/bbcli/services/contents_service.py b/bbcli/services/contents_service.py
index 887b042..7cce7aa 100644
--- a/bbcli/services/contents_service.py
+++ b/bbcli/services/contents_service.py
@@ -51,7 +51,7 @@ def list_assignments(cookies: Dict, course_id: str):
 # NB: Alle options sende som values i enkle fields i bodyen
 
 # Alle disse blir sendt til post content endpoint. title, body er samme. Options varirerer. Største ulikheten
-# er i content-handler. None kan også ha attachments.
+# er i content-handler. Noen kan også ha attachments.
 
 # Tror svaret er en ContentBuilder
 
@@ -105,23 +105,66 @@ def create_file(session: requests.Session, course_id: str, parent_id: str, title
 # Title, URL, body, eventuelt attachments?, Weblink options: open in new window?, Standard options: as above
 
 
-def create_externallink():
-    pass
+def create_externallink(session: requests.Session, course_id: str, parent_id: str, title: str, url: str, web_link_options: WeblinkOptions, standard_options: StandardOptions):
+
+    data = content_builder\
+        .add_parent_id(parent_id)\
+        .add_title(title)\
+        .add_standard_options(standard_options)\
+        .add_weblink_options(web_link_options)\
+        .add_content_handler_externallink(url)\
+        .create()
+    
+    data = json.dumps(data)
+    url = generate_create_content_url(course_id, parent_id)
+    response = session.post(url, data=data)
+    return response.text
 
 # Title, body, Standard options: as above
 
+def create_folder(session: requests.Session, course_id: str, parent_id: str, title: str, is_bb_page:bool, standard_options: StandardOptions):
+
+    data_body = input_body()
+    
+    data = content_builder\
+        .add_title(title)\
+        .add_body(data_body)\
+        .add_standard_options(standard_options)\
+        .add_content_handler_folder(is_bb_page=is_bb_page)
+    
+    if parent_id:
+        url = generate_create_content_url(course_id, parent_id)
+        data.add_parent_id(parent_id)
+    else:
+        url = url_builder.base_v1().add_courses().add_id(course_id).add_contents().create()
+    data = data.create()
+
+    data = json.dumps(data)
+    response = session.post(url, data=data)
+    return response.text
 
-def create_folder():
-    pass
 
 # Title, body, location(?), targetId content, Standard Options: as above
 
+# FUNKER IKKE PGA targetType
+def create_courselink(session: requests.Session, course_id: str, parent_id: str, title: str, target_id: str, standard_options: StandardOptions):
 
-def create_courselink():
-    pass
+    data_body = input_body()
 
-# Se egen metode i BBL REST API
+    data = content_builder\
+        .add_title(title)\
+        .add_body(data_body)\
+        .add_standard_options(standard_options)\
+        .add_content_handler_courselink(target_id=target_id)\
+        .create()
+    
+    data = json.dumps(data)
+    url = generate_create_content_url(course_id, parent_id)
 
+    response = session.post(url, data=data)
+    return response.text
+
+# Se egen metode i BBL REST API
 
 def create_assignment():
     pass
diff --git a/bbcli/services/courses_service.py b/bbcli/services/courses_service.py
index c69fae7..a7fbae8 100644
--- a/bbcli/services/courses_service.py
+++ b/bbcli/services/courses_service.py
@@ -51,11 +51,14 @@ def list_all_courses(session: requests.Session, user_name: str) -> Any:
 def list_course(session: requests.Session, course_id:str) -> Any:
     url = url_builder.base_v3().add_courses().add_id(course_id).create()
     response = session.get(url)
+    response.raise_for_status()
+        
+
     return json.loads(response.text)
 
-def list_favorite_courses(session: requests.Session, user_name: str) -> Any:
-    return "Blackboard rest api do not have an option for this yet"
-    # response = requests.get('https://ntnu.blackboard.com/learn/api/public/v1/users/userName:{}/courses'.format(user_name), cookies=cookies)
+# def list_favorite_courses(session: requests.Session, user_name: str) -> Any:
+#     return "Blackboard rest api do not have an option for this yet"
+#     # response = requests.get('https://ntnu.blackboard.com/learn/api/public/v1/users/userName:{}/courses'.format(user_name), cookies=cookies)
 
 
 """
diff --git a/bbcli/services/utils/content_builder.py b/bbcli/services/utils/content_builder.py
index 53be014..7bc3a11 100644
--- a/bbcli/services/utils/content_builder.py
+++ b/bbcli/services/utils/content_builder.py
@@ -176,9 +176,9 @@ class ContentBuilder(Builder):
     def add_content_handler_courselink(self, target_id: str, target_type: str = 'Unset') -> Builder:
         self._product.add({
             'contentHandler' : {
-                'id': 'resource/x-bb-folder',
+                'id': 'resource/x-bb-courselink',
                 'targetId': target_id,
-                'targeType': target_type
+                'targetType': target_type
             }
         })
         return self
diff --git a/bbcli/utils/utils.py b/bbcli/utils/utils.py
index 809888f..4921ba4 100644
--- a/bbcli/utils/utils.py
+++ b/bbcli/utils/utils.py
@@ -51,7 +51,7 @@ def html_to_text(html_data: str):
 	return to_text.handle(html_data)
 
 def input_body():
-	MARKER = '# Everything below is ignored\n'
+	MARKER = '# Everything below is ignored. Leave blank if you want empty body.\n'
 	body = click.edit('\n\n' + MARKER)
 	if body is not None:
 		body = body.split(MARKER, 1)[0].rstrip('\n')
-- 
GitLab