Repository: streamlink/streamlink

Issue:
Schoolism Video Feedbacks Plugins Compatibility?
Checklist

- [ ] This is a bug report.
- [ ] This is a feature request.
- [x] This is a plugin (improvement) request.
- [x] I have read the contribution guidelines.

With the Schoolism plugin, you can download lessons with Streamlink.exe --schoolism-email XXXX --schoolism-password XXXX --schoolism-part 1 -v "https://www.schoolism.com/watchLesson.php?type=st&id=506" best -o "LOCATION"

Is there a way to download the video feedbacks from urls such as https://www.schoolism.com/viewAssignment.php?type=st&courseID=44&id=506&notSubmitted=true as well? If there isn't, I'd greatly appreciate a modification to the plugin to allow for one to download the video feedbacks.




Discussion:
It's not supported by the plugin, it could be added - but I don't have access to schoolism, when I wrote it the first time I borrowed someones credentials. 

You can check using your browsers dev tools to find the m3u8 URL and use that along with the auth cookies (not sure of the their names though) with streamlink.
**just for your interest, nobody here has an account**

if someone wants this feature,
the person must share it with someone who wants to add this feature

---

**at some point** it's not worth to have an **unfixable issue** open
like some of the other Schoolism issues https://github.com/streamlink/streamlink/issues/1046#issuecomment-386712317 _(over one year)_
and it will be closed, so it can disappear in the shadows
No response received.

Resolving patch:
diff --git a/src/streamlink/plugins/schoolism.py b/src/streamlink/plugins/schoolism.py
--- a/src/streamlink/plugins/schoolism.py
+++ b/src/streamlink/plugins/schoolism.py
@@ -1,20 +1,23 @@
 from __future__ import print_function
 
+import logging
 import re
 from functools import partial
 
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
-from streamlink.stream import HLSStream
+from streamlink.stream import HLSStream, HTTPStream
 from streamlink.utils import parse_json
 
+log = logging.getLogger(__name__)
+
 
 class Schoolism(Plugin):
-    url_re = re.compile(r"https?://(?:www\.)?schoolism\.com/watchLesson.php")
+    url_re = re.compile(r"https?://(?:www\.)?schoolism\.com/(viewAssignment|watchLesson).php")
     login_url = "https://www.schoolism.com/index.php"
     key_time_url = "https://www.schoolism.com/video-html/key-time.php"
-    playlist_re = re.compile(r"var allVideos=(\[\{.*\}]);", re.DOTALL)
+    playlist_re = re.compile(r"var allVideos\s*=\s*(\[\{.*\}]);", re.DOTALL)
     js_to_json = partial(re.compile(r'(?!<")(\w+):(?!/)').sub, r'"\1":')
     playlist_schema = validate.Schema(
         validate.transform(playlist_re.search),
@@ -27,13 +30,13 @@ class Schoolism(Plugin):
                 validate.transform(parse_json),
                 [{
                     "sources": validate.all([{
-                        "playlistTitle": validate.text,
+                        validate.optional("playlistTitle"): validate.text,
                         "title": validate.text,
                         "src": validate.text,
                         "type": validate.text,
                     }],
                         # only include HLS streams
-                        validate.filter(lambda s: s["type"] == "application/x-mpegurl")
+                        # validate.filter(lambda s: s["type"] == "application/x-mpegurl")
                     )
                 }]
             )
@@ -63,7 +66,7 @@ class Schoolism(Plugin):
             default=1,
             metavar="PART",
             help="""
-        Play part number PART of the lesson.
+        Play part number PART of the lesson, or assignment feedback video.
 
         Defaults is 1.
         """
@@ -83,44 +86,50 @@ def login(self, email, password):
         """
         if self.options.get("email") and self.options.get("password"):
             res = self.session.http.post(self.login_url, data={"email": email,
-                                                  "password": password,
-                                                  "redirect": None,
-                                                  "submit": "Login"})
+                                                               "password": password,
+                                                               "redirect": None,
+                                                               "submit": "Login"})
 
             if res.cookies.get("password") and res.cookies.get("email"):
                 return res.cookies.get("email")
             else:
-                self.logger.error("Failed to login to Schoolism, incorrect email/password combination")
+                log.error("Failed to login to Schoolism, incorrect email/password combination")
         else:
-            self.logger.error("An email and password are required to access Schoolism streams")
+            log.error("An email and password are required to access Schoolism streams")
 
     def _get_streams(self):
         user = self.login(self.options.get("email"), self.options.get("password"))
         if user:
-            self.logger.debug("Logged in to Schoolism as {0}", user)
+            log.debug("Logged in to Schoolism as {0}", user)
             res = self.session.http.get(self.url, headers={"User-Agent": useragents.SAFARI_8})
             lesson_playlist = self.playlist_schema.validate(res.text)
 
             part = self.options.get("part")
+            video_type = "Lesson" if "lesson" in self.url_re.match(self.url).group(1).lower() else "Assignment Feedback"
 
-            self.logger.info("Attempting to play lesson Part {0}", part)
+            log.info("Attempting to play {0} Part {1}", video_type, part)
             found = False
 
             # make request to key-time api, to get key specific headers
-            res = self.session.http.get(self.key_time_url, headers={"User-Agent": useragents.SAFARI_8})
+            _ = self.session.http.get(self.key_time_url, headers={"User-Agent": useragents.SAFARI_8})
 
             for i, video in enumerate(lesson_playlist, 1):
                 if video["sources"] and i == part:
                     found = True
                     for source in video["sources"]:
-                        for s in HLSStream.parse_variant_playlist(self.session,
-                                                                  source["src"],
-                                                                  headers={"User-Agent": useragents.SAFARI_8,
-                                                                           "Referer": self.url}).items():
-                            yield s
+                        if source['type'] == "video/mp4":
+                            yield "live", HTTPStream(self.session, source["src"],
+                                                     headers={"User-Agent": useragents.SAFARI_8,
+                                                              "Referer": self.url})
+                        elif source['type'] == "application/x-mpegurl":
+                            for s in HLSStream.parse_variant_playlist(self.session,
+                                                                      source["src"],
+                                                                      headers={"User-Agent": useragents.SAFARI_8,
+                                                                               "Referer": self.url}).items():
+                                yield s
 
             if not found:
-                self.logger.error("Could not find lesson Part {0}", part)
+                log.error("Could not find {0} Part {1}", video_type, part)
 
 
 __plugin__ = Schoolism


Test patch: