Giter VIP home page Giter VIP logo

stitch-for-roku's Introduction

Stitch (for Roku)

Stitch is a Roku channel that aims to provide an actively maintained, reasonably feature-complete Twitch experience while respecting Twitch's business model (ads, monetization, and the like).

Stich exists because Twitch does not presently have any official channel for Roku, despite Roku being the most popular smart TV platform, with (as of early 2022), a 39% market share in North America and a 31% market share worldwide.

If you work at Twitch, go make an official Twitch app so I don't have to. If you want this one you can have it. (See Authorship and License.)

Installation

You can add Stitch to your Roku account by clicking the following link: https://my.roku.com/account/add?channel=LL5GKQ

Support

If you have questions or comments, or if you want to receive announcements, you can join the Stitch Discord server:

Discord

Contributing

If you are comfortable using the GitHub interface, you can report bugs or request features by opening a GitHub Issue. (Please check to see if your issue has already been reported before opening a new one.)

We are currently looking into integrations between GitHub and Discord in order to make this process easier for everyone.

In addition to issues, Pull Requests are welcome. All contributions must be made under the Unlicense.

Authorship and License

Stitch began as a hard fork of Twoku, due to that application's apparent abandonment. Since then Stitch has been almost completely rewritten.

Twoku was released without an explicit license, but, as a non-cleanroom rewrite, all subsequent contributions to Stitch are released under the Unlicense.

If license encumberance is an issue for you, you can compare the final upstream commit to this repository to see what code is unclearly licensed.

While removing any residual upstream code is not a priority for Stitch, Pull Requests replacing unclearly licensed code with unencumbered code are welcome.

Stitch is released on a non-commercial basis and derives no revenue. If you work for Twitch, please feel free to use the license-unencumbered portions of this repository as the basis for an official Twitch app.

stitch-for-roku's People

Contributors

0xw1sky avatar elsiehupp avatar worldreboot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

stitch-for-roku's Issues

Add a VOD-user specific interface

I think it would be cool if we had a menu option specific to VOD users that allows easier sorting through a list of followed streamers and the vods they have.

Personally, i'm a fan of the Youtube App's subscriptions page. I think we could replicate this to make a better experience for vodboys.

Enhacement

Please try it's okay if you can't make one with if have a subscription there's no ads pls im in highschool so I can't rlly spell good.

Login/Oauth Problem

Won't stay logged in. I leave it for a time, go into stitch but I'm no longer signed in.

Accessing Any Offline Streamer's Channel Page From The "Following" Menu Causes The App To Force Close

Stitch Channel Version: 1.21 * Build 0
Roku Device Model: 9101X - Roku Smart Soundbar
Roku Software Version: 11.5.0 * Build 4312-95
Date Tested: March 20th 2023
Description of Issue: I cannot access any offline streamers channel page. Whenever I try and open an offline streamers page from the "following" tab, the app attempts to load the page and then force closes. This can be repeated over and over and over again with the exact same result. It does not matter which offline streamer's channel I try to access. This makes Stitch completely useless for me versus Twoku. VODs are the number one thing I watch on Twitch as I don't often catch my favorite streamers live. Please fix this.

Support Polls?

  • Option in settings to enable polls
  • task and event sub for polls. Show pop up when polls become active and let user vote
  • show poll results when it's done.

No Video on LiveStreams

Hi just tried out the app via developer install and we get no video - the app goes to a grey load screen once you click on any livestream and plays audio for an Ad and then plays audio for the stream, all while the screen still shows a grey load screen. Just wanted to let you know. I'm not a coder but trying to help.

Set follow bar to refresh on a timer so that its always up to date

Add a timer for follow bar refresh so that its always up to date. There is already a timer that refreshes it for various scene changes but we still miss sometimes dependent on user activity. A timer to poll and then perform the refresh I think would be a lot cleaner. We should probably leave the scene change driven workflow in there to account for user activity to provide best user experience.

Channel Videos Missing Titles!

Nobody's mentioned this in past months so I sat waiting to see if it was an issue on my end that'd resolve, but no luck.

Version 2.8, build 2
Titles are entirely missing on videos on a channel. Featured clips is fine, but everything else gone. It's been an issue since the last update to the app, when twitch messed with something that was freezing things (which is resolved since 3 months ago, but this title thing has persisted.)

Scuffed TV screenshots included. Discover tab/live videos are fine.

20240825_233544
20240825_233552

Need a better solution for versioning

Right now, my versioning is haphazard. This is mostly because i'm a self-taught dev rather than classically trained.

Also, being that i've been the only contributor I haven't cared too much so long as something is incremented allowing for:
A) Roku to properly identify updates
and
B) end users to validate that they're on the right version.

Right now, I have a githook that increments the version number in our manifest file.
I'm sure there is a better way to do this. I'm open to recommendations or contributions from others on a better way to handle this.

Dynamic UI Sizing

Update UI elements to use percentage of m.uiresolution.width & m.uiresolution.height

Currently, most items are statically sized making them display differently depending on if a user is on a 720p, 1080p, or 4k screen.

Resolution Setting (feature request)

Fantastic app, replaced Twoku as soon as I found this. One thing I would love to see is a permanent resolution setting (Video/Stream Quality is the setting in Twoku). This would allow us to limit streaming quality on certain Roku units that might need it due to poor wifi in a certain room, data caps, etc. I know you can do it per stream after you first connect, but a permanent solution that could be "set and forget" would be so convenient. Great job guys, Amazon needs to hire you to make this app official.

Why the hard fork?

I looked at the Git commit history of this repository, and, yep, Stitch is a hard fork of Twoku!

But since Stitch is a hard fork of Twoku, I have to ask… why? Why not do a Pull Request, instead? It actually takes substantial effort to do a hard fork on GitHub (i.e. to sever a repository from an upstream fork), so… why?

(Oh, also: no, Amazon is not going to adopt a third-party Twitch client unless it is fully cleared by their legal department to have a permissive MIT/BSD-style license. As far as I can tell, neither Twoku nor Stitch has an explicit license, and getting any official adoption, or even just substantial third-party code contribution, is extremely unlikely unless that changes.)

Triaging Remaining Upstream Code

To find remaining upstream code, I concatenated all the text files from 268187c and all the text files from 4730a81 and put them through a plagiarism checker.

Instances

I found the following overlaps, most of which are only partial matches, amounting to approximately 3% of the total codebase.

1. Much of CustomVideo

You thought this might be from Jellyfin?

2. getRelativeTimePublished

function getRelativeTimePublished(timePublished as string) as string
    secondsSincePublished = createObject("roDateTime")
    secondsSincePublished.FromISO8601String(timePublished)
    currentTime = createObject("roDateTime").AsSeconds()
    elapsedTime = currentTime - secondsSincePublished.AsSeconds()

    elapsedTime = Int(elapsedTime / 60)
    if elapsedTime < 60
        if elapsedTime = 1
            return "1 minute ago"
        else
            return elapsedTime.ToStr() + " minutes ago"
        end if
    end if

    elapsedTime = Int(elapsedTime / 60)
    if elapsedTime < 24
        if elapsedTime = 1
            return "1 hour ago"
        else
            return elapsedTime.ToStr() + " hours ago"
        end if
    end if

    elapsedTime = Int(elapsedTime / 24)
    if elapsedTime < 30
        if elapsedTime = 1
            return "1 day ago"
        else
            return elapsedTime.ToStr() + " days ago"
        end if
    end if

    elapsedTime = Int(elapsedTime / 30)
    if elapsedTime < 12
        if elapsedTime = 1
            return "Last month"
        else
            return elapsedTime.ToStr() + " months ago"
        end if
    end if

    elapsedTime = Int(elapsedTime / 12)
    if elapsedTime = 1
        return "1 year ago"
    else
        return elapsedTime.ToStr() + " years ago"
    end if

end function

3. numberToText

sub numberToText(number) as object
    s = StrI(number)
    result = ""
    if number >= 100000 and number < 1000000
        result = Left(s, 4) + "K"
    else if number >= 10000 and number < 100000
        result = Left(s, 3) + "." + Mid(s, 4, 1) + "K"
    else if number >= 1000 and number < 10000
        result = Left(s, 2) + "." + Mid(s, 3, 1) + "K"
    else if number < 1000
        result = s
    end if
    return result
end sub

4. Various Snippets from Chat

if tcpListen.GetCountRcvBuf() > 0
    while not get = Chr(10)
        get = tcpListen.ReceiveStr(1)
        '? "receive Status " tcpListen.Status()
        received += get
    end while
end if
if tcpListen.GetCountRcvBuf() = 0 and tcpListen.IsReadable()
    tcpListen = createObject("roStreamSocket")
    tcpListen.SetSendToAddress(addr)
    tcpListen.Connect()
    tcpListen.SendStr("CAP REQ :twitch.tv/tags twitch.tv/commands" + Chr(13) + Chr(10))
    tcpListen.SendStr("PASS SCHMOOPIIE" + Chr(13) + Chr(10))
    tcpListen.SendStr("NICK justinfan32006" + Chr(13) + Chr(10))
    tcpListen.SendStr("JOIN #" + m.top.channel + Chr(13) + Chr(10))
end if
if not received = ""
    if Left(received, 4) = "PING"
        tcpListen.SendStr("PONG :tmi.twitch.tv" + Chr(13) + Chr(10))
    else
        queue.unshift(received)
        receivedNewMessage = true
    end if
end if
function buildUsername(display_name, color)
    username = createObject("roSGNode", "SimpleLabel")
    username.text = display_name
    if color = ""
        color = "FFFFFF"
    end if
    username.color = "0x" + color + "FF"
    username.visible = true
    username.fontSize = m.font_size
    username.fontUri = "pkg:/fonts/KlokanTechNotoSansCJK-Bold.otf"
    return username
end function
sub onEnterChannel()
    ' ? "Chat >> onEnterChannel > " m.top.channel
    if get_user_setting("ChatWebOption", "true") = "true"
        m.chat = m.top.findnode("ChatJob")
        m.chat.forceLive = m.top.forceLive
        ' m.chat.observeField("nextComment", "onNewComment")
        m.chat.observeField("nextCommentObj", "onNewCommentObj")
        ' m.chat.observeField("clientComment", "onNewComment")
        m.chat.channel = m.top.channel
        m.chat.control = "stop"
        m.chat.control = "run"
    end if
    m.EmoteJob = m.top.findnode("EmoteJob")
    m.EmoteJob.channel_id = m.top.channel_id
    m.EmoteJob.channel = m.top.channel
    m.EmoteJob.control = "run"
end sub
sub extractMessage(section) as object
    m.userstate_change = false
    words = section.Split(" ")
    if words[2] = "USERSTATE"
        m.userstate_change = true
    end if
    message = ""
    for i = 4 to words.Count() - 1
        message += words[i] + " "
    end for
    return message
end sub
function buildBadges(badges)
    group = createObject("roSGNode", "Group")
    group.visible = true
    badge_translation = 0
    for each badge in badges
        if badge <> invalid and badge <> ""
            if m.global.twitchBadges <> invalid
                if m.global.twitchBadges[badge] <> invalid
                    poster = createObject("roSGNode", "Poster")
                    poster.uri = m.global.twitchBadges[badge]
                    poster.width = m.badge_size
                    poster.height = m.badge_size
                    poster.visible = true
                    poster.translation = [badge_translation, 0]
                    group.appendChild(poster)
                    badge_translation += (m.badge_size + (m.badge_size / 6))
                end if
            end if
        end if
    end for
    return group
end function

5. FollowedStreamsBar

Various snippets, including:

sub onKeyEvent(key, press) as boolean
    handled = false
    if press
        if key = "left"
            return true
        end if
        if key = "up"
            if m.currentIndex = 0
                return false
                'tofix: add behaviour to move to top bar'
            end if
            if m.currentIndex - 1 >= 0
                m.children[m.currentIndex].focused = false
                m.currentIndex -= 1
                if m.currentIndex < m.min
                    for each stream in m.children
                        stream.translation = [m.xTranslation, (stream.translation[1] + 60)]
                        ' stream.translation = "[9," + (stream.translation[1] + 60).ToStr() + "]"
                        if stream.translation[1] > 0
                            stream.visible = true
                        end if
                    end for
                    m.min -= 1
                    m.max -= 1
                end if
                m.children[m.currentIndex].focused = true
            end if
            handled = true
        else if key = "down"
            if m.currentIndex + 1 < m.top.getChildCount() - 1
                m.children[m.currentIndex].focused = false
                if m.children[m.currentIndex + 1] <> invalid
                    m.currentIndex += 1
                end if
                if m.currentIndex > m.max
                    for each stream in m.children
                        stream.translation = [m.xTranslation, (stream.translation[1] - 60)]
                        ' stream.translation = "[9," + (stream.translation[1] - 60).ToStr() + "]"
                        if stream.translation[1] <= 0
                            stream.visible = false
                        end if
                    end for
                    m.min += 1
                    m.max += 1
                end if
                m.children[m.currentIndex].focused = true
            end if
            handled = true
        else if key = "OK"
            if m.children[m.currentIndex] <> invalid
                m.top.streamerSelected = m.children[m.currentIndex].twitch_id
                m.top.contentSelected = m.children[m.currentIndex].content
                m.children[m.currentIndex].focused = false
                handled = true
            end if
        end if
    end if
    return handled
end sub

What to do?

Some of these residual snippets are fairly minimal and would be relatively easy to replace. Others are probably not big enough priorities to deal with.

One way of triaging these could be to put a header comment in each affected file (and above each affected function) mentioning its licensing issues and then to put a header comment reading 'SPDX-License-Identifier: Unlicense in every other file. (The licensing for image and font assets should also be listed where relevant.)

As an aside, the SPDX guide mentions the option of specifying a choice of licenses for licensees. So if you want to be more broad, you could specify something like 'SPDX-License-Identifier: 0BSD OR Unlicense.

How does this sound?

Login won't stick

Login isn't sticking so I deleted the app. Reinstalled. And still doesn't stick. I leave it for an hour or more and it's not logged in anymore.

Quick Switch Between Accounts (Feature Request)

My wife and I have separate accounts, and it would be great to be able to quick switch between the two accounts.

Great app. Replaced Twoku immediately. Thanks for developing this and supporting it.

PiHOle

Feel free to close this if you don't agree, but maybe add some comments to the ReadMe about whitelisting badges.twitch.tv to PiHole if users are using that....

Login still not sticking

Still not sticking for me. I deleted it, restarted roku, reinstalled, and after some time went back to it. Nothing.

Fix crash on login

after successful login, the app crashes. not sure why.
The login process succeeds and saves user access token etc.
needs to be debugged and fixed. <3

Add ability to filter based on language

Twitch supports filtering results based on language and I'd love to see this added to Stitch. There are a lot of categories that are almost unbrowsable without it. For example GTA V has a lot of non-english streamers so you need to visually sort them out based on their stream title, which can be hit or miss.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.