Giter Site home page Giter Site logo

python-twitch-client's Introduction

python-twitch-client

Latest docs Latest version Latest build Coverage

python-twitch-client is an easy to use Python library for accessing the Twitch API

You can find more information in the documentation or for support, you can join the Discord Server.

Note

python-twitch-client currently supports Twitch API v5 and the new Helix API.

If you find a missing endpoint or a bug please raise an issue or contribute and open a pull request.

Basic Usage

Helix API

from itertools import islice
from twitch import TwitchHelix

client = TwitchHelix(client_id='<my client id>')
streams_iterator = client.get_streams(page_size=100)
for stream in islice(streams_iterator, 0, 500):
    print(stream)

Twitch API v5

from twitch import TwitchClient

client = TwitchClient(client_id='<my client id>')
channel = client.channels.get_by_id(44322889)

print(channel.id)
print(channel.name)
print(channel.display_name)

python-twitch-client's People

Contributors

ambrozic avatar boraxtheclean avatar btbn avatar dependabot[bot] avatar disabledtech avatar fabaff avatar garciabruno avatar garyking avatar goldbattle avatar grover-c13 avatar jacquerie avatar jchristgit avatar jollex avatar jonnekaunisto avatar jvtrigueros avatar m3adow avatar nicolaskyejo avatar nihaals avatar nipun-air avatar scop avatar truenicfel avatar tsifrer 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  avatar  avatar  avatar  avatar

python-twitch-client's Issues

Encoding Error when emoji used

Getting a error when querying streams that have emojis in any of their status

UnicodeEncodeError: 'UCS-2' codec can't encode characters in position 711-711: Non-BMP character not supported in Tk

Not sure the exact fix. :'(

ImportError: cannot import name 'TwitchClient' from 'twitch'

Can't find this name in twitch module. I've checked dir(twitch) and get this list: ['Callable', 'Chat', 'Helix', 'List', 'TMI', 'V5', 'all', 'annotations', 'builtins', 'cached', 'doc', 'file', 'loader', 'name', 'package', 'path', 'spec', 'api', 'baseresource', 'cache', 'chat', 'helix', 'name', 'tmi', 'v5']
Where TwitchHelix and TwitchClient?
OC: Windows 10 LTSC
Python 3.8.5

Collecting python-twitch-client
Using cached python_twitch_client-0.6.0-py3-none-any.whl (20 kB)
Requirement already satisfied: requests>=2.18.4 in c:\users\sweetbaget\appdata\local\programs\python\python38-32\lib\site-packages (from python-twitch-client) (2.24.0)
Requirement already satisfied: six>=1.11.0 in c:\users\sweetbaget\appdata\roaming\python\python38\site-packages (from python-twitch-client) (1.15.0)
Requirement already satisfied: idna<3,>=2.5 in c:\users\sweetbaget\appdata\local\programs\python\python38-32\lib\site-packages (from requests>=2.18.4->python-twitch-client) (2.10)
Requirement already satisfied: certifi>=2017.4.17 in c:\users\sweetbaget\appdata\local\programs\python\python38-32\lib\site-packages (from requests>=2.18.4->python-twitch-client) (2020.6.20)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in c:\users\sweetbaget\appdata\local\programs\python\python38-32\lib\site-packages (from requests>=2.18.4->python-twitch-client) (1.25.10)
Requirement already satisfied: chardet<4,>=3.0.2 in c:\users\sweetbaget\appdata\local\programs\python\python38-32\lib\site-packages (from requests>=2.18.4->python-twitch-client) (3.0.4)
Installing collected packages: python-twitch-client
Successfully installed python-twitch-client-0.6.0

games.get_top brings less items above 10

client.games.get_top(10) and client.games.get_top(11) gets same number of items, which is 10.
That means client.games.get_top(12) brings 11 items, client.games.get_top(13) brings 12 items and so on.

OAuth requests not working

My auth token was generated with channel_editor and channel_read scopes.
Validated it by using this on the browser:
https://api.twitch.tv/kraken/channels/pwnographers/editors?client_id=[my client id]&oauth_token=[my auth token]

It returned: {"_links":{"self":"https://api.twitch.tv/kraken/channels/pwnographers/editors"},"users":[]}

However, when I try to use your package as per docs like so....

`>>> from twitch import TwitchClient

client = TwitchClient('[my client id]', '[my auth token]')
channel = client.channels.get()
Traceback (most recent call last):
File "", line 1, in
File "E:\Code\dolores\python\twitch\decorators.py", line 8, in wrapper
return func(*args, **kwargs)
File "E:\Code\dolores\python\twitch\api\channels.py", line 14, in get
response = self._request_get('channels')
File "E:\Code\dolores\python\twitch\api\base.py", line 31, in _request_get
response.raise_for_status()
File "C:\Users\Hue\AppData\Local\Programs\Python\Python35\lib\site-packages\requests\models.py", line 909, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://api.twitch.tv/kraken/channels`

Dealing with 5xx errors

I've worked with the Twitch API before without using any library and the API returning a 5xx error code (internal server error) seems to be quite common.
This appears to be a known issue, as several Twitch Developer Forum threads talk about it:

TL;DR:

Yes our API is flaky, yes we are working on increasing it's stability. Most of our apps have retry logic to minimize the impact of a request failing, I'd recommend the same approach for your cron jobs. Just make sure to cap the number of retries and use exponential backoff and you should be fine.

I think having the mentioned exponential backoff with a capped number of retries in a library for the API would be great.

Looking at the source, it appears that the functions for requesting data are in base.py.

Could something like this be implemented? I'd be more than happy to help, are there any guidelines that I should be aware of?

Thanks in advance!

`TwitchObject` is not natively JSON serializable

Due to using a datetime.datetime instance in TwitchObject, TwitchObject is not natively JSON serializable.

Example:

json.dumps(client.search.channels("example"))

Running this will result in:

Traceback (most recent call last):
  File ".../twitch-viewer/proto.py", line 17, in <module>
    print(json.dumps(client.search.channels("example")))
  File "/usr/lib/python3.6/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python3.6/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.6/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python3.6/json/encoder.py", line 180, in default
    o.__class__.__name__)
TypeError: Object of type 'datetime' is not JSON serializable

Though this can be addressed on the developers end. I feel that a TwitchObject should be able to be easily converted into JSON without additional effort.

A easy solution would be to use a str or int timestamp (eg: from epoc) for dates in a TwitchObject instead of using a datetime.datetime instance.

clips.get_top cannot be used

clips = client.clips.get_top(game='League of Legends', limit=10)
AttributeError: 'TwitchClient' object has no attribute 'clips'

Timeouts

Please add timeouts (e. g., here) to the requests which are performed.

We are moving to this module for our twitch integration. Thus, it would be nice if you publish a new release after you have added the timeouts.

Thanks in advance.

teams.get returns error 400 bad request

tclient = TwitchClient(client_id='<removed>')
teams = tclient.teams.get('area51gaming')

returns 400 error bad request

but

tclient = TwitchClient(client_id='<removed>')
communities = tclient.communities.get_by_name('area51gaming')

returns fine

Channel Subscriptions Snipped..?

I've set the oauth token when creating the client object and the return json is incomplete, seems to be snipped. Because of this the _total attribute is missing.

client = TwitchClient(client_id=XXXX, oauth_token=XXXX)
client.channels.get_subscribers(XXXX)

The partial data that is being returned is correct. There are only 6 subscriptions so it's not due to limits. When limiting to a number less than total subscriptions, all are listed, but _total attribute is missing.

get_streams by user_ids spam

I am running a bit of code where I've shoved into a task that runs every 6000 seconds
Problem is I've given it 3 ID's from which the function totally spams and freezes program.
I believe the problem is within the cursor
image
This the bit of code I am running

get_followers does not return cursor

It appears that channel.get_followers does not return the cursor.
So the maximum number of followers you can get is 100.
maybe add a get_all_followers function or just return the entire response which would include the cursor.

HTTPError

my code:
from twitch import TwitchClient
client=TwitchClient(client_id='')
channel=client.channels.get_by_id("44322889")
print(channel.id)
print(channel.name)
print(channel.display_name)

response from the command:
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://api.twitch.tv/kraken/channels/44322889

Add OAuth Token Fetch

Piggybacking off of #12

Issue

Since the Helix API requires OAuth , I propose this library grow the capability of fetching an OAuth token given a client_id and client_secret.

Proposed Behavior

If TwitchHelix is initialized without an OAuth token and with both a client_id and client_secret, a request is made to https://id.twitch.tv/oauth2/token to fetch a valid OAuth token.

If the TwitchHelix is initialized without an OAuth token and without either a client_id/client_secret a Credential exception is raised.

I'll Build It

If the maintainer blesses this as a valid new feature to add, I will gladly open a PR with this change for review.

channels.update() not working (HTTP error 400)

Hey, after fixing #8 I tried updating my stream title. Unfortunately there seems to be an error. Reproducable script:

oauth = 'yourid'
client_id = 'yourclientid'
newstatus='There is now cow level'

tc = TwitchClient(client_id=client_id, oauth_token=oauth)
tc.channels.update(channel_id=tc.channels.get()['id'], status=newstatus)

This will return a requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://api.twitch.tv/kraken/channels/XXXXXX. The error message is Missing required parameter channel.

This is because the body status=newstatus is sent instead of channel[status]=status here: https://github.com/tsifrer/python-twitch-client/blob/master/twitch/api/channels.py#L22

I've already found a (dirty) workaround by changing the keys of data to include channel (like this: data['channel[status]'] = status) but it's neither tested thoroughly nor is it a good way in my eyes.

"get_follows" should get all follows by a user

There should be an option for users. get_follows() to get all users that a user follows. The Twitch API limits each call to 100, but you can use the offset key to technically get all follows.

So, this library should simplify this process, by adding an option. If the option is enabled, then the library will get the first 100 follows, then the next 100, etc. until they are all retrieved.

chat

hi is there a way to get a bot to type a message in chat? if so how would i do it?

Twitch Endpoint v5 Ending

since the beginning of the year, twitch has been sending emails to users of the v5 endpoint with the message that v5 support will be switched off on 2/28/2022.

Different result from api than the website

I am using
client.clips.get_top(game="fortnite", limit=1, period="week")
and the results which I get are different from
https://www.twitch.tv/directory/game/Fortnite/clips?range=7d

Expected

The result of the api should return the top video from the website.

Outcome

A video other than that is returned.

Update to Helix API

The Helix version of the Twitch API seems to finally support most, if not all, of the methods that Kraken supported. So please update this package to support that instead, since Kraken will be deprecated by the end of the year.

Get clips wrong parameters

I'm getting an error 500 when trying to get a specific clip by id. I noticed that you've named it "clip_id" while in the helix api on Twitch it's just "id"

https://dev.twitch.tv/docs/api/reference#get-clips

twitch.py
param = { "broadcaster_id": broadcaster_id, "game_id": game_id, "clip_id": clip_id, "after": after, "before": before, "first": first, "ended_at": datetime_to_str(ended_at), "started_at": datetime_to_str(started_at), }

The following fixed the issue:
param = { "broadcaster_id": broadcaster_id, "game_id": game_id, "id": clip_id, "after": after, "before": before, "first": first, "ended_at": datetime_to_str(ended_at), "started_at": datetime_to_str(started_at), }

Installed the module and yet it can't call it correctly.

Hi,
I just installed the module and for some reason, it keeps returning the error:
Traceback (most recent call last):
File "C:\Users\Bram\AppData\Local\Programs\Python\Python36\Discord-Twitch_Notifyer.py", line 1, in
from twitch import TwitchClient
ModuleNotFoundError: No module named 'twitch'

Just to confirm I installed it correctly, here's a printout of when I installed it:
C:\Users\Bram\AppData\Local\Programs\Python\Python36>python -m pip install python-twitch-client
Collecting python-twitch-client
Using cached python_twitch_client-0.3.0-py3-none-any.whl
Collecting requests>=2.13.0 (from python-twitch-client)
Downloading requests-2.18.2-py2.py3-none-any.whl (88kB)
100% |████████████████████████████████| 92kB 274kB/s
Requirement already satisfied: six>=1.10.0 in c:\users\bram\appdata\local\programs\python\python36\lib\site-packages (from python-twitch-client)
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in c:\users\bram\appdata\local\programs\python\python36\lib\site-packages (from requests>=2.13.0->python-twitch-client)
Collecting idna<2.6,>=2.5 (from requests>=2.13.0->python-twitch-client)
Downloading idna-2.5-py2.py3-none-any.whl (55kB)
100% |████████████████████████████████| 61kB 902kB/s
Collecting certifi>=2017.4.17 (from requests>=2.13.0->python-twitch-client)
Downloading certifi-2017.7.27.1-py2.py3-none-any.whl (349kB)
100% |████████████████████████████████| 358kB 553kB/s
Collecting urllib3<1.23,>=1.21.1 (from requests>=2.13.0->python-twitch-client)
Downloading urllib3-1.22-py2.py3-none-any.whl (132kB)
100% |████████████████████████████████| 133kB 421kB/s
Installing collected packages: idna, certifi, urllib3, requests, python-twitch-client
Successfully installed certifi-2017.7.27.1 idna-2.5 python-twitch-client-0.3.0 requests-2.18.2 urllib3-1.22

Proxy support

I'm developing a console application to browse and watch Twitch streams (among other things) and would like to see if there's any interest in a PR that would add HTTPS proxy support. The requests library can already read from the HTTP_PROXY and HTTPS _PROXY variables, but sometimes it's preferable to set proxies on the fly (in application configuration) instead of in the shell environment before the program is started.

My thinking is this: instead of calling requests.get(), requests.post(), etc., the API objects could use a requests.Session() object, which could either come from the calling application as a parameter, or, if not provided, be created. In the v5 API, it looks something like this

    def __init__(self, client_id, oauth_token=None, session=None):
        """Initialize the API."""
        super(TwitchAPI, self).__init__()
        self._session = session or requests.Session()

Then, the _request_get, _request_post, etc. methods would do the following:

response = self._session.get(url, params=params, headers=headers)

I figured since I'm doing this work anyway, it might be useful as a PR. Thoughts?

Module 'twitch' has no attribute 'Helix'

In what version can i use this syntax?

Traceback (most recent call last):
File "C:\Users\fede\Desktop\main.py", line 9, in
helix = twitch.Helix('XXXXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXXXX')
^^^^^^^^^^^^
AttributeError: module 'twitch' has no attribute 'Helix'

"self" defined as string?

Traceback (most recent call last):
  File "run.py", line 16, in <module>
    posts = api.channel_feed.ChannelFeed.get_posts(str(channel.id), 100)
  File "C:\Python\Python36\lib\site-packages\twitch\api\channel_feed.py", line 22, in get_posts
    response = self._request_get('feed/%s/posts' % channel_id, params=params)
AttributeError: 'str' object has no attribute '_request_get'

400 error when "'Accept': 'application/vnd.twitchtv.v5+json'" is included in headers

From this line, the Accept header, when included in requests, returns a 400 error for most methods.

For instance, when running the following (with <twitch-client-id> and <twitch-username> replaced):

from twitch import TwitchClient

TWITCH_CLIENT_ID = '<twitch-client-id>'
TWITCH_USERNAME = '<twitch-username>'

client = TwitchClient(client_id=TWITCH_CLIENT_ID)
client.users.get_by_id(TWITCH_USERNAME)

I get in response:

'{"error":"Bad Request","status":400,"message":"User ID \\"<twitch-username>\\" is invalid"}'

If I perform the same request with requests but exclude the Accept field, then it works fine.

Also, if "'Accept': 'application/vnd.twitchtv.v5+json'" is removed from most of the API calls (but not all), then they return 404, which is to be expected, I guess.

AttributeError when requesting stream resource

When requesting a stream resource, e.g. with client.streams.get_stream_by_user(someID), and the channel is offline, following error is thrown:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python35\lib\site-packages\twitch\api\streams.py", line 19, in get_stream_by_user
    return Stream.construct_from(response['stream'])
  File "C:\Python35\lib\site-packages\twitch\resources.py", line 61, in construct_from
    instance.refresh_from(values)
  File "C:\Python35\lib\site-packages\twitch\resources.py", line 65, in refresh_from
    for key, value in six.iteritems(values.copy()):
AttributeError: 'NoneType' object has no attribute 'copy'

I guess Twitch changed something on their end, since it worked a few days ago.

Documentation needed on the return values of the class methods

Taking an example, I want to make a bot that behaves differently for subscribed users, followers etc...

to get subscriptions, I should use :

client = twitch.TwitchClient(client_id, oauth)

channel = client.channel.get()

subscribes = channel.get_subscriptions(args) #offset moving 100 at a time in a loop

so now, what exactly is in subscribes, it's a list, but how are users represented in python ?

twitch dev gives :

{

    "_total": 4,

    "subscriptions": [

        {

            "_id": "e5e2ddc37e74aa9636625e8d2cc2e54648a30418",

            "created_at": "2016-04-06T04:44:31Z",

            "sub_plan": "1000",

            "sub_plan_name": "Channel Subscription (mr_woodchuck)",

            "user": {

                "_id": "89614178",

                "bio": "Twitch staff member who is a heimerdinger main on the road to diamond.",

                "created_at": "2015-04-26T18:45:34Z",

                "display_name": "Mr_Woodchuck",

                "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/mr_woodchuck-profile_image-a8b10154f47942bc-300x300.jpeg",

                "name": "mr_woodchuck",

                "type": "staff",

                "updated_at": "2017-04-06T00:14:13Z"

            }

        },

    . . .

   ]

}

so to access the id of the first user, should I use subscribes[0].user.id_ ?

Also I think you're missing the token revoke endpoint.

I also think you could add some image stuff to the library to parse images from the links, and have them accessible as python objects (using pillow maybe)

Also, sub_plan refers to sub tiers ? so 1000 is 4.99$, 2000 9.99$ and 6000(or 3000, read somewhere that 25$ subs count for 6 so just interpreting the data) 24.99$ ?

Issue with Twitch v5 Users - offset parameter does not affect get_follows method

Test done: ran twitch_client.users.get_follows() twice for the same user_id, using different offset parameter values: 0 and 1

  • Expected outcome: different list of followed channels for different offset parameter values. For example, I expect the response for offset=1 to be shifted by one channel, when compared to the response for offset=0.
  • Observed outcome: the same exact response for the two different calls to the get_follows() method with different offset parameter values.

TypeError upon empty games search results.

Description

Upon searching for a game using the games() function in twitch.api.search.Search, if the query yields no results a TypeError is thrown.

Expected Behavior

games() should return an empty list like the rest of the Search functions when no results are returned from Twitch.

Actual Behavior

Since the search function tries to perform a list comprehension on the None response of self._request_get(), a TypeError is raised and the program is terminated.

Possible Fix

Do a quick sanity check on the datatype of response from self._request_get() in games() before trying to parse it.

Steps to Reproduce

Create a client instance and search for a game title that doesn't exist.

from twitch import TwitchClient
client = TwitchClient('<my client id>')
client.search.games('This is not a valid game title')

This should cause a TypeError to get raised with the following output:

Traceback (most recent call last):
  File "crash_test.py", line 3, in <module>
    client.search.games('This is not a valid game title')
  File "C:\Python36\lib\site-packages\twitch\api\search.py", line 27, in games
    return [Game.construct_from(x) for x in response['games']]
TypeError: 'NoneType' object is not iterable

Context

I was doing some exploratory research into making a small script to sync a private streaming community's live stream metadata (Game title, stream title, etc) to their twitch restream.

My Environment

  • Windows 10
  • Python 3.6.4
  • python-twitch-client 0.5.1 installed via pip3

Question about get_clips

Hello,

I'm pretty sure I'm doing something wrong, but I didn't find examples, so maybe it really doesn't work.
this is the request I'm doing for get_clips:

clip_settings = {
"broadcaster_id": None,
"game_id": 509658,
"clip_ids": None,
"after": None,
"before": None,
"started_at": (datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=7)).isoformat(),
"ended_at": None,
"page_size": 100
}

clips = client.get_clips(**clip_settings)

and I'm trying to write all the clips to CSV file, but it doesn't stop , it seems that when it gets to the end, it just writes the last page over and over again (so I added if i==4000)

with open('clips.csv', 'w', encoding='utf-8') as f:
writer = csv.writer(f)
for i, clip in enumerate(clips):
if i == 0:
writer.writerow([x for x in clip])
writer.writerow([clip[x] for x in clip])
if i == 4000:
break

how to I go over the results of each page and ask to continue only if there is another page?

thanks

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.