Git Product home page Git Product logo

twitch-python's Introduction

Twitch Python

Discord Build Status

pip install --user twitch-python

An object-oriented approach to accessing the Twitch API and live chat with relationships and smart caching.

Requirements

Usage

# Twitch API

import twitch

helix = twitch.Helix('client-id', 'client-secret')
# Users

for user in helix.users(['sodapoppin', 'reckful', 24250859]):
    print(user.display_name)


print(helix.user('zarlach').display_name)
# Videos

for video in helix.videos([318017128, 317650435]):
    print(video.title)


print(helix.video(318017128).title)
# Video Comments (VOD chat)

for comment in helix.video(318017128).comments:
    print(comment.commenter.display_name)


for video, comments in helix.videos([318017128, 317650435]).comments:
    for comment in comments:
        print(comment.commenter.display_name, comment.message.body)


for video, comments in helix.user('sodapoppin').videos().comments:
        for comment in comments:
            print(comment.commenter.display_name, comment.message.body)


for user, videos in helix.users(['sodapoppin', 'reckful']).videos(first=5):
        for video, comments in videos.comments:
            for comment in comments:
                print(comment.commenter.display_name, comment.message.body)
# Twitch Chat

twitch.Chat(channel='#sodapoppin', nickname='zarlach', oauth='oauth:xxxxxx').subscribe(
        lambda message: print(message.channel, message.user.display_name, message.text))

Features

  • Object-oriented relationships
  • Smart caching
  • New Twitch API (Helix)
  • VOD chat from Twitch API v5

DocumentationTwitch APITwitch-Chat-Downloader

twitch-python's People

Contributors

dependabot[bot] avatar hokichaio avatar kennbro avatar oshawk avatar petterkraabol avatar pirxthepilot avatar tantusar 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

twitch-python's Issues

getting all user videos

There doesn't seem to be a way to get the paginate cursor when querying more than 100 videos i.e. all videos of a channel. I think you must have implemented that already for the comment endpoint.

An example is if I pass the kwarg first=150 I'll get a KeyError

v = owl.videos(first=150, type='archive')
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-35-852e78385a40> in <module>
----> 1 v = owl.videos(first=150, type='archive')

~\Anaconda3\envs\twitchchat\lib\site-packages\twitch\helix\models\user.py in videos(self, **kwargs)
     30
     31     def videos(self, **kwargs) -> 'helix.Videos':
---> 32         return helix.Videos(api=self._api, user_id=self.id, **kwargs)
     33
     34     def stream(self) -> 'helix.Stream':

~\Anaconda3\envs\twitchchat\lib\site-packages\twitch\helix\videos.py in __init__(self, api, video_ids, **kwargs)
     43         else:
     44             self._data = [helix.Video(api=self._api, data=video) for video in
---> 45                           self._api.get(self._path, params=kwargs)['data']]
     46
     47     def comments(self) -> Generator[Tuple[helix.Video, v5.Comments], None, None]:

KeyError: 'data'

My use case is I'm using your interface through Twitch-Chat-Downloader to get the chat comments of a vod, but because the api endpoints aren't as fully featured I'm using python-twitch-client to get all the video ids of all videos of a channel.

Perhaps I'm misunderstanding the correct way to continue querying the videos through twitch-python.

Error when iterating through videos of a channel

When attempting to iterate through videos as in #3 I'm getting a TypeErrror.

import twitch

helix = twitch.Helix('<client-id>')

for video in helix.user('moonmoon_ow').videos():
    print(video.id)

which yields

 File "c:\Users\yanns\git\Twitch-Python\debug-twitch.py", line 5, in <module>
    for video in helix.user('moonmoon_ow').videos():
  File "c:\Users\yanns\git\Twitch-Python\twitch\helix\resources\resource.py", line 53, in __iter__
    remaining = 0 if remaining is not None and len(elements) > remaining else remaining - self._kwargs['first']
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'

it seems like there might be some invalid boolean logic? From my debugging the variable remaining is indeed None so the if statement immediately fails and the else statement is evaluated. since remaining is None however we get a TypeError trying to subtract an int from a NoneType.

Am I using the videos() method as intended?

400 Client Error: Bad Request for url

I've been using Twitch-Python the same way for almost two months, this is the first time i face this issue. Seems a bit weird as it only happened this one time

helix = twitch.Helix(client_id=CLIENT_ID)
user_data = helix.users([user_name])[0]

user_name is always message.user.display_name.lower()

Traceback (most recent call last):
  File "/home/bledy/projects/barbota/barbota/twitch_chat.py", line 574, in check_user_exists
    user_data = helix.users([user_name])[0]
  File "/home/bledy/projects/barbota/.venv/lib/python3.7/site-packages/twitch/helix/helix.py", line 43, in users
    return helix.Users(self.api, *args)
  File "/home/bledy/projects/barbota/.venv/lib/python3.7/site-packages/twitch/helix/resources/users.py", line 49, in __init__
    for data in self._api.get(self._path, params=params, ignore_cache=True)['data']:
  File "/home/bledy/projects/barbota/.venv/lib/python3.7/site-packages/twitch/api.py", line 111, in get
    return self.request('GET', path, ignore_cache, params=params, headers=self._headers(headers), **kwargs)
  File "/home/bledy/projects/barbota/.venv/lib/python3.7/site-packages/twitch/api.py", line 100, in request
    response.raise_for_status()
  File "/home/bledy/projects/barbota/.venv/lib/python3.7/site-packages/requests/models.py", line 940, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://api.twitch.tv/helix/users?login=%E3%82%A8%E3%83%AD%E3%83%9D%E3%83%8B%E3%83%BC

unhandled missing v5/Commenter causes crash

running tcd fails on a certain video because it seems the user the comment belongs to doesn't exist anymore or something, so the twitch api returns 'null' for that field, which twitch-python doesn't handle and throws a NPE

(tcd_venv) PS C:\Users\mark\Code\Personal\git\get_twitch_vod_chats> tcd --verbose --video 873505779 --format "json,default,irc,srt,ssa" --debug --output "tcd_output.log" --timezone "UTC"
NES speedruns
Downloading JSON data
Traceback (most recent call last):
  File "C:\Python39\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Python39\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\mark\Temp\tcd_venv\Scripts\tcd.exe\__main__.py", line 7, in <module>
  File "c:\users\mark\temp\tcd_venv\lib\site-packages\tcd\__init__.py", line 92, in main
    Downloader().videos(Arguments().video_ids)
  File "c:\users\mark\temp\tcd_venv\lib\site-packages\tcd\downloader.py", line 183, in videos
    self.video(video)
  File "c:\users\mark\temp\tcd_venv\lib\site-packages\tcd\downloader.py", line 100, in video
    for comment in video.comments:
  File "c:\users\mark\temp\tcd_venv\lib\site-packages\twitch\v5\resources\comments.py", line 27, in __iter__
    yield v5.Comment(api=self._api, data=comment)
  File "c:\users\mark\temp\tcd_venv\lib\site-packages\twitch\v5\models\comment.py", line 84, in __init__
    self.commenter: Commenter = Commenter(data.get('commenter'))
  File "c:\users\mark\temp\tcd_venv\lib\site-packages\twitch\v5\models\comment.py", line 18, in __init__
    self.display_name: str = data.get('display_name')
AttributeError: 'NoneType' object has no attribute 'get'

i added logging to both tcd and twitch-python (which i feel you should add to both as an aside, would have made it easier to debug) and as the video will probably be aged out by the time you look at this, i have the full api response output if you want.

Here is the relevant api response (a python dict, not JSON), note the None as the value for commenter

              {'_id': 'f1887ffa-1831-48f0-a989-26b5535b3627',
               'channel_id': '26642416',
               'commenter': None,
               'content_id': '873505779',
               'content_offset_seconds': 10472.579,
               'content_type': 'video',
               'created_at': '2021-01-14T21:54:30.279Z',
               'message': {'body': 'rambo!',
                           'fragments': [{'text': 'rambo!'}],
                           'is_action': False,
                           'user_badges': [{'_id': 'subscriber',
                                            'version': '3'},
                                           {'_id': 'premium', 'version': '1'}],
                           'user_notice_params': {}},
               'source': 'chat',
               'state': 'published',
               'updated_at': '2021-01-14T21:54:30.279Z'},

its fixed by adding a check to see if data.get("commenter") is none, and if so, just set self.commenter = None in v5/models/commenter.py : Comment.__init__, however all of the formatters except for JSON expect a commenter, so those parts of the code need to handle a potential missing commenter

[Question ]error handling

I'm trying to use the lib and it works fine, the problem is when it doesn't work, it doesn't display response or anything on the console, it just stays silent, I would like help to handle any connection error with the Chat class

Certain text can force IRC to crash

if text.find('Login authentication failed') > 0:
logging.fatal('IRC authentication error: ' + text or '')
return

If a user types "Login authentication failed" in chat, regardless of if the IRC connection has actually failed, it will trigger the fatal logging and return from the active loop.

A suggested fix could be to check to make sure it was not sent via a PRIVMSG

if text.find('Login authentication failed') > 0 and text.find('PRIVMSG') == -1:

AttributeError when iterating over comments on certain videos

Code to reproduce:

from twitch import Helix

helix = Helix("REDACTED", "REDACTED")

for i in helix.video(873841025).comments:
    pass

Error:

Traceback (most recent call last):
  File "REDACTED", line 5, in <module>
    for i in helix.video(873841025).comments:
  File "REDACTED", line 24, in __iter__
    yield v5.Comment(api=self._api, data=comment)
  File "REDACTED", line 78, in __init__
    self.commenter: Commenter = Commenter(data.get('commenter'))
  File "REDACTED", line 13, in __init__
    self.display_name: str = data.get('display_name')
AttributeError: 'NoneType' object has no attribute 'get'

Process finished with exit code 1

Documentation

Opening issue for improving on current documentation as the few examples are lacking of documenting the rest of the library. I'm happy to help contribute this.

I will continue to update this issue with progress and roadmap as I work through this.

IRC login error handling

hi, it would be cool if you rise an error when there is an auth failure.

on the irc.py line 36

logging.fatal('IRC authentication error: ' + text or '')
#return
raise Exception('authentication error') 

even better if you create an exceptions.py file:

class AuthenticationError(Exception)
    pass
logging.fatal('IRC authentication error: ' + text or '')
raise AuthenticationError

So we can handle it, renewing the token or skipping the login.
In my case im trying to handle multiple bots so its usefull

ty

[Question] Recording live streams

I am doing a project using NLP and twitch seems to be a good data source for continuous dialogue. Is it possible to grab live stream video data in segments of 1 second each as the stream is running?

Rate limit

Hi again,

from what I can tell you set some rate limiting parameter but it's not clear to me if it's actually used? is that accurate? or am I missing where it's actually limiting the requests by rate limit?

Cheers

Helix responds with 401

Hello there, I tried to fetch the moderators of a channel but got a 401.

self.twitch_helix = twitch.Helix(client_id=f'{os.getenv("TWITCH.CLIENTID")}', use_cache=True, client_secret=f'{os.getenv("TWITCH.SECRET")}')

identifier: str = self.twitch_helix.user("schrottler").id
mods = self.twitch_helix.api.get("moderation/moderators", {"broadcaster_id": identifier}).get()

Both ClientID and ClientSecret are set. Any idea?
Or is this type of request not supported?

cannot import name 'API' from 'twitch.api'

Hello!

I tried to create an example but unfortunately i get the following error:

ImportError: cannot import name 'API' from 'twitch.api' (/home/mspapant/PycharmProjects/twitch-scraper/venv/lib/python3.7/site-packages/twitch/api/init.py)

Do you know what is the problem?

Thanks

Information about time

hello~
I don't know if I can get a comment of time.
for example :
1:30:05 XXXX : XXXXXXXXX~
thank you very much!!

readme.md missing...

$ pip install twitch-python
Collecting twitch-python
Using cached https://files.pythonhosted.org/packages/66/04/9849cd2be54bcc27953691b98235429af2d84e4f89a865fca4a34d7eba6a/twitch-python-0.0.4.tar.gz
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "", line 1, in
File "C:\Cygwin64\tmp\pip-install-7vhnlb2o\twitch-python\setup.py", line 5, in
with open('readme.md') as readme_file:
FileNotFoundError: [Errno 2] No such file or directory: 'readme.md'

----------------------------------------

Command "python setup.py egg_info" failed with error code 1 in C:\Cygwin64\tmp\pip-install-7vhnlb2o\twitch-python\

Namespace conflict with python-twitch-client

Thanks for the great package. I'm trying to use both your package and python-twitch-client but both packages are imported like

import twitch

So naturally there is a namespace conflict. Would it be possible in the future to move away from a common package name and something a bit more specific?

The other option I have is to rename the package myself after pip install but it's a little messy as i'm not sure where all the references to the package name exist in the package code itself.

Get user who owns bearer token with Helix API

The Twitch API returns the user who owns the bearer token when no arguments are provided to https://api.twitch.tv/helix/users.

If neither a user ID nor a login name is specified, the user is looked up by Bearer token.
https://dev.twitch.tv/docs/api/reference/#get-users

This is currently not possible, because of this check:

if len(params['id'] + params['login']):

To keep the API consistent, this behavior should probably only be added for Helix.user() and not to Helix.users(). This way there is no confusion when an empty user list is requested. Otherwise, an empty user list could return a non-empty result.

I have implemented it here, but it seems a bit hacky:
master...alexf91:current_user

Poor shut-down behaviour.

This package often will not cleanly shutdown, leaving a thread running in the background. There are two parts to the problem.

I suspect the root cause is that C++ destructor techniques are being applied to Python code, which has a different model.

  1. There is no way to cleanly shut down a Chat instance.

There is a __del__ method on Chat which sets its local IRC instance to not be active. In Python, the __del__ operation is not automatically called when an object is deleted. It might be called by the garbage collector, sometime later. The garbage collector is not required to run at all, especially at shut-down.

Instead, a close() methods should be defined to all the user to call it. The __del__ method could be defined, and made to call the close() method, but it cannot be relied upon and adds little value here, so I would remove it.

  1. Sometimes programs crash, and don't cleanly shut-down. The program should terminate and not hang.

There is a separate clean-up mechanism available for threads that is appropriate here: daemon threads. The IRC thread should be defined as a daemon thread - if the main thread finishes and the only remained threads are all daemon threads, they will be terminated. This is appropriate for a library such as this one.

I changed IRC.py, line 12, from:

    super().__init__()

to:

    super().__init__(daemon=True)

and my shut-down issues disappeared.

is possible to access more than 1 channel at time?

the title says all, but there's more infos.
i want to build a bot cabable of running on multiple channels at the same time, i thinked of a way to do that but i first want to know if this lib is capable of handling multiple channels already

It's working well.

Library seems to work well,

I'm piecing it together by groking the source.

Subscribe doesn't seem to be threaded, and just blocks, is there a call back function, or is the library just designed for very simple interactions with the twitch irc servers?

twitch.Chat(channel='#sodapoppin', nickname='zarlach', oauth='oauth:xxxxxx').subscribe(
        lambda message: print(message.channel, message.user.display_name, message.text))

This blocks... but it quite possible this is by design.

Is it possible to create clips with this tool?

Hi!

I have managed to get the chat listener to work but would want to be able to create a twitch clip when someone posts "!clip" in the chat. Is there a way to do this? I searched the repository and found some mention of "Clip" and "Clips" but I cant figure out what they do and how to access the feature.

This is the first time I have published an issue on github, I hope asking questions is allowed.

    def handle_message(self, message: twitch.chat.Message) -> None:
        if message.text.startswith("!clip"):
            self.create_clip(message)

    def create_clip(self, message):
        pass

IRC thread fails silently on network issues.

In Python, if a thread's run() method raises an unhandled exception, it is silently ignored, and the thread terminates - unless another thread joins it, or an excepthook is defined.

irc.py defines the IRC thread.

It doesn't handle any exceptions during connection. It doesn't handle any exceptions during authentication. The only exception it handles during normal communications is IOError, and its only response to that is to silently terminate the thread.

Further, this thread object is created in Chat, which offers no method for joining the thread. (Admittedly, the thread is publicly shared, so someone could dig in to the internals of the class to find it.)

The upshot is that if there are any networking issues, the Chat object stops receiving messages, without notice.

In practice, I am finding about 1 in 6 times, when I launch a Chat object, it is failing silently, and I never receive any messages.

I don't have a quick answer here - I imagine it involves joins and/or on_error() callbacks - but this is making the library unusable.

helix.video not returning anything

I'm trying to replicate the code provided in the README. The helix.users seems to be working (so I know I've auth'ed correctly). But the helix.video only return None

[Question] Retrieving Point Rewards Information

Hello. I need help retrieving information about point rewards in my project. How can I detect when someone requests a reward and access the details of the chosen reward using Twitch-Python? Any code examples or guidance would be appreciated.

Thank you for your support.

Edge case when Oauth starts with an 'h'

In the instance that your oauth key begins with the character 'h' it will be stripped from the password at IRC initialization and throw a login error.

class IRC(threading.Thread):

    def __init__(self, nickname: str, password: str, address: str = 'irc.chat.twitch.tv', port: int = 6667):
        super().__init__()

        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.address: str = address
        self.port: int = port
        self.channels: List[str] = []
        self.nickname: str = nickname
        self.password: str = 'oauth:' + password.lstrip('oauth:')
        self.active: bool = True
        self.incoming: Subject = Subject()

Update for Twitch API

Hey @PetterKraabol

kudos for maintaining this, you're doing God's work.
Do you have plans to update the library to be compatible with the GraphQL API so it can get chats from VODs?

Due to the old Helix API being deprecated, this feature currently doesn't work:

for comment in helix.video(318017128).comments:
    print(comment.commenter.display_name)

Cheers.

KeyError: "access_token" Error

image

This is what i get after running the script given in the PYPI page. I tried other ways but it doesn't work. Is it a client side error or its just the module?

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.