Skip to content

Commit

Permalink
feat: Enforce highest quality resolution #87
Browse files Browse the repository at this point in the history
  • Loading branch information
rabilrbl committed Sep 28, 2023
1 parent e4c9a90 commit f06424f
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 13 deletions.
3 changes: 3 additions & 0 deletions cmd/jiotv_go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ func main() {
app.Post("/login/verifyOTP", handlers.LoginVerifyOTPHandler)
app.Post("/login", handlers.LoginHandler)
app.Get("/live/:id", handlers.LiveHandler)
app.Get("/live/high/:id", handlers.LiveHighHandler)
app.Get("/live/medium/:id", handlers.LiveMediumHandler)
app.Get("/live/low/:id", handlers.LiveLowHandler)
app.Get("/render.m3u8", handlers.RenderHandler)
app.Get("/render.ts", handlers.RenderTSHandler)
app.Get("/render.key", handlers.RenderKeyHandler)
Expand Down
17 changes: 17 additions & 0 deletions cmd/jiotv_go/static/channels.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ if (category) {
categoryElement.value = category;
}

const onQualityChange = (elem) => {
const quality = elem.value;
if (quality === "auto") {
// remove quality from url
url.searchParams.delete("q");
} else {
url.searchParams.set("q", quality);
}
const playElems = document.getElementsByClassName("btn btn-outline btn-info btn-md");
for (let i = 0; i < playElems.length; i++) {
const elem = playElems[i];
const href = elem.getAttribute("href");
elem.setAttribute("href", href.split("?")[0] + url.search);
}
console.log(playElems);
};

const scrollToTop = () => {
// make smooth scroll to top
window.scrollTo({
Expand Down
13 changes: 11 additions & 2 deletions cmd/jiotv_go/views/channel_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,17 @@
id="portexe-search-input"
type="text"
placeholder="Search channels here"
class="input input-bordered input-primary input-sm sm:input-md w-full rounded-xl"
class="input input-bordered input-primary input-md w-full rounded-xl"
/>
<select
id="portexe-quality-select"
class="select select-primary select-sm sm:select-md w-full max-w-auto sm:max-w-xs sm:w-auto rounded-xl"
onchange="onQualityChange(this)"
>
{{ range $key, $value := .Qualities }}
<option value="{{$key}}">{{$value}}</option>
{{ end }}
</select>
<select
id="portexe-category-select"
class="select select-primary select-sm sm:select-md w-full max-w-auto sm:max-w-xs sm:w-auto rounded-xl"
Expand Down Expand Up @@ -50,7 +59,7 @@
src="/jtvimage/{{$channel.LogoURL}}"
loading="lazy"
alt="{{$channel.Name}}"
class="h-8 w-8 sm:h-10 sm:w-10 md:h-12 md:w-12 lg:h-16 lg:w-16 p-1 rounded-full bg-sky-100"
class="h-8 w-8 sm:h-10 sm:w-10 md:h-12 md:w-12 lg:h-16 lg:w-16 sm:p-1 rounded-sm rounded-full bg-sky-100"
/>
</td>
<td>
Expand Down
98 changes: 92 additions & 6 deletions internals/handlers/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,25 @@ func IndexHandler(c *fiber.Ctx) error {
"IsNotLoggedIn": !utils.CheckLoggedIn(),
"Categories": categoryMap,
"Languages": languageMap,
"Qualities": map[string]string{
"auto": "Quality (Auto)",
"high": "High",
"medium": "Medium",
"low": "Low",
},
})
} else {
return c.Render("views/index", fiber.Map{
"Channels": channels.Result,
"IsNotLoggedIn": !utils.CheckLoggedIn(),
"Categories": categoryMap,
"Languages": languageMap,
"Qualities": map[string]string{
"auto": "Quality (Auto)",
"high": "High",
"medium": "Medium",
"low": "Low",
},
})
}
}
Expand Down Expand Up @@ -96,7 +108,61 @@ func LiveHandler(c *fiber.Ctx) error {
}
}
// quote url
coded_url := url.QueryEscape(liveResult)
coded_url := url.QueryEscape(liveResult.Auto)
return c.Redirect("/render.m3u8?auth="+coded_url+"&channel_key_id="+id, fiber.StatusFound)
}

func LiveHighHandler(c *fiber.Ctx) error {
id := c.Params("id")
// remove suffix .m3u8 if exists
id = strings.Replace(id, ".m3u8", "", 1)
liveResult, err := TV.Live(id)
if err != nil {
utils.Log.Println(err)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": err,
})
}
}
// quote url
coded_url := url.QueryEscape(liveResult.High)
return c.Redirect("/render.m3u8?auth="+coded_url+"&channel_key_id="+id, fiber.StatusFound)
}

func LiveMediumHandler(c *fiber.Ctx) error {
id := c.Params("id")
// remove suffix .m3u8 if exists
id = strings.Replace(id, ".m3u8", "", 1)
liveResult, err := TV.Live(id)
if err != nil {
utils.Log.Println(err)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": err,
})
}
}
// quote url
coded_url := url.QueryEscape(liveResult.Medium)
return c.Redirect("/render.m3u8?auth="+coded_url+"&channel_key_id="+id, fiber.StatusFound)
}

func LiveLowHandler(c *fiber.Ctx) error {
id := c.Params("id")
// remove suffix .m3u8 if exists
id = strings.Replace(id, ".m3u8", "", 1)
liveResult, err := TV.Live(id)
if err != nil {
utils.Log.Println(err)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": err,
})
}
}
// quote url
coded_url := url.QueryEscape(liveResult.Low)
return c.Redirect("/render.m3u8?auth="+coded_url+"&channel_key_id="+id, fiber.StatusFound)
}

Expand Down Expand Up @@ -194,6 +260,7 @@ func RenderTSHandler(c *fiber.Ctx) error {
}

func ChannelsHandler(c *fiber.Ctx) error {
quality := c.Query("q")
apiResponse := television.Channels()
// hostUrl should be request URL like http://localhost:5001
hostURL := strings.ToLower(c.Protocol()) + "://" + c.Hostname()
Expand All @@ -204,7 +271,12 @@ func ChannelsHandler(c *fiber.Ctx) error {
m3uContent := "#EXTM3U\n"
logoURL := "/jtvimage"
for _, channel := range apiResponse.Result {
channelURL := fmt.Sprintf("%s/live/%d.m3u8", hostURL, channel.ID)
var channelURL string
if quality != "" {
channelURL = fmt.Sprintf("%s/live/%s/%d.m3u8", hostURL, quality, channel.ID)
} else {
channelURL = fmt.Sprintf("%s/live/%d.m3u8", hostURL, channel.ID)
}
channelLogoURL := fmt.Sprintf("%s/%s", logoURL, channel.LogoURL)
m3uContent += fmt.Sprintf("#EXTINF:-1 tvg-name=%q tvg-logo=%q tvg-language=%q tvg-type=%q group-title=%q, %s\n%s\n",
channel.Name, channelLogoURL, television.LanguageMap[channel.Language], television.CategoryMap[channel.Category], television.CategoryMap[channel.Category], channel.Name, channelURL)
Expand All @@ -225,23 +297,36 @@ func ChannelsHandler(c *fiber.Ctx) error {

func PlayHandler(c *fiber.Ctx) error {
id := c.Params("id")
player_url := "/player/" + id
quality := c.Query("q")
player_url := "/player/" + id + "?q=" + quality
return c.Render("views/play", fiber.Map{
"player_url": player_url,
})
}

func PlayerHandler(c *fiber.Ctx) error {
id := c.Params("id")
play_url := "/live/" + id + ".m3u8"
quality := c.Query("q")
var play_url string
if quality != "" {
play_url = "/live/" + quality + "/" + id + ".m3u8"
} else {
play_url = "/live/" + id + ".m3u8"
}
return c.Render("views/flow_player", fiber.Map{
"play_url": play_url,
})
}

func ClapprHandler(c *fiber.Ctx) error {
id := c.Params("id")
play_url := "/live/" + id + ".m3u8"
quality := c.Query("q")
var play_url string
if quality != "" {
play_url = "/live/" + quality + "/" + id + ".m3u8"
} else {
play_url = "/live/" + id + ".m3u8"
}
return c.Render("views/clappr", fiber.Map{
"play_url": play_url,
})
Expand All @@ -252,7 +337,8 @@ func FaviconHandler(c *fiber.Ctx) error {
}

func PlaylistHandler(c *fiber.Ctx) error {
return c.Redirect("/channels?type=m3u", fiber.StatusMovedPermanently)
quality := c.Query("q")
return c.Redirect("/channels?type=m3u&q="+quality, fiber.StatusMovedPermanently)
}

func ImageHandler(c *fiber.Ctx) error {
Expand Down
10 changes: 5 additions & 5 deletions internals/television/television.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func NewTelevision(credentials *utils.JIOTV_CREDENTIALS) *Television {
}
}

func (tv *Television) Live(channelID string) (string, error) {
func (tv *Television) Live(channelID string) (*Bitrates, error) {
formData := fasthttp.AcquireArgs()
defer fasthttp.ReleaseArgs(formData)

Expand Down Expand Up @@ -83,7 +83,7 @@ func (tv *Television) Live(channelID string) (string, error) {
// Perform the HTTP POST request
if err := tv.Client.Do(req, resp); err != nil {
utils.Log.Panic(err)
return "", err
return nil, err
}

if resp.StatusCode() != fasthttp.StatusOK {
Expand All @@ -95,16 +95,16 @@ func (tv *Television) Live(channelID string) (string, error) {
utils.Log.Println("Request data:", formData.String())
utils.Log.Panicln("Response: ", response)

return "", fmt.Errorf("Request failed with status code: %d\nresponse: %s", resp.StatusCode(), response)
return nil, fmt.Errorf("Request failed with status code: %d\nresponse: %s", resp.StatusCode(), response)
}

var result LiveURLOutput
if err := json.Unmarshal(resp.Body(), &result); err != nil {
utils.Log.Panic(err)
return "", err
return nil, err
}

return result.Bitrates.Auto, nil
return &result.Bitrates, nil
}

func (tv *Television) Render(url string) []byte {
Expand Down

0 comments on commit f06424f

Please sign in to comment.