Skip to content

Commit 7db6c91

Browse files
committed
2 parents 56b12c5 + e74f5ae commit 7db6c91

File tree

9 files changed

+225
-7
lines changed

9 files changed

+225
-7
lines changed

.github/ISSUE_TEMPLATE/bug.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
name: 🐛 Bug Report
3+
description: Submit a bug report for TwitchIO
4+
title: "[Bug]: "
5+
labels: ["Unconfirmed Bug", "Needs Verification"]
6+
body:
7+
- type: textarea
8+
id: what-happened
9+
attributes:
10+
label: "What actually happened?"
11+
description: "Please enter details about the issue, including tracebacks if applicable (in codeblocks)."
12+
placeholder: "My Bot will not start!"
13+
validations:
14+
required: true
15+
- type: textarea
16+
id: expected-outcome
17+
attributes:
18+
label: "What did you expect to happen instead?"
19+
description: "Please enter what you hoped or expected to happen instead of the issue that occurred."
20+
placeholder: "My Bot started successfully!"
21+
validations:
22+
required: true
23+
- type: textarea
24+
id: mre
25+
attributes:
26+
label: "Minimum reproducible example:"
27+
description: "Please provide the minimum necessary code to reproduce your issue, if relevant."
28+
render: python
29+
- type: textarea
30+
id: repro-steps
31+
attributes:
32+
label: "Steps to reproduce the problem"
33+
description: "It may not be obvious how to *cause* the issue, so please explain below."
34+
validations:
35+
required: true
36+
- type: textarea
37+
id: logs
38+
attributes:
39+
label: "Additional logs:"
40+
description: "If there is any logging output that may be relevant, please add it here."
41+
- type: textarea
42+
id: environment-details
43+
attributes:
44+
label: "System and Environment information"
45+
description: "Please put the output of `python -m twitchio --version` here:"
46+
validations:
47+
required: true

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
blank_issues_enabled: false
2+
contact_links:
3+
- name: TwitchIO Documentation
4+
url: https://twitchio.dev/en/latest/index.html
5+
about: Official TwitchIO documentation - please check here before opening an issue.
6+
- name: Discord
7+
url: https://discord.gg/RAKc3HF
8+
about: Join our Discord community to chat or receive help, or get in touch with the maintainers.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: "Feature Request"
2+
description: Create an issue for a new feature request
3+
title: "Enhancement: <title>"
4+
labels:
5+
- "Enhancement"
6+
body:
7+
- type: textarea
8+
id: summary
9+
attributes:
10+
label: "Summary"
11+
description: Provide a brief summary of your feature request
12+
placeholder: Describe in a few lines your feature request
13+
validations:
14+
required: true
15+
- type: textarea
16+
id: basic_example
17+
attributes:
18+
label: "Basic Examples"
19+
description: Indicate here some basic examples of your feature.
20+
placeholder: Provide some basic example of your feature request
21+
validations:
22+
required: false
23+
- type: textarea
24+
id: drawbacks
25+
attributes:
26+
label: "Drawbacks and Impact"
27+
description: What are the drawbacks or impacts of your feature request?
28+
placeholder: Describe any of the drawbacks or impacts of your feature request
29+
validations:
30+
required: false
31+
- type: textarea
32+
id: unresolved_question
33+
attributes:
34+
label: "Unresolved questions"
35+
description: What, if any, unresolved questions do you have about your feature request?
36+
placeholder: Identify any unresolved issues.
37+
validations:
38+
required: false

docs/getting-started/faq.rst

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,28 @@ You can also create a :class:`~twitchio.PartialUser` with :meth:`~twitchio.Clien
8383
If you are using :class:`~twitchio.ext.commands.Command`'s or anywhere :class:`~twitchio.ext.commands.Context` is available,
8484
or are receiving a :class:`~twitchio.ChatMessage`, consider looking at :class:`~twitchio.Chatter` for a more complete object
8585
with more information and helpers.
86+
87+
.. _bot-id-owner-id:
88+
89+
How do I get the user IDs for BOT_ID and OWNER_ID?
90+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
91+
92+
If you do not know your user ID you can quickly fetch it using the :meth:`~twitchio.Client.fetch_users` method.
93+
94+
.. code:: python3
95+
96+
import asyncio
97+
import twitchio
98+
99+
CLIENT_ID: str = "..."
100+
CLIENT_SECRET: str = "..."
101+
102+
async def main() -> None:
103+
async with twitchio.Client(client_id=CLIENT_ID, client_secret=CLIENT_SECRET) as client:
104+
await client.login()
105+
user = await client.fetch_users(logins=["chillymosh", "my_bot"])
106+
for u in user:
107+
print(f"User: {u.name} - ID: {u.id}")
108+
109+
if __name__ == "__main__":
110+
asyncio.run(main())

docs/getting-started/quickstart.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ Before running the code below, there just a couple more steps we need to take.
3737
#. Stop the bot and uncomment everything in ``setup_hook``.
3838
#. Start the bot.
3939

40+
.. note::
41+
If you are unsure how to get the user IDs for BOT_ID and OWNER_ID, please check :ref:`bot-id-owner-id`
42+
4043
**You only have to do this sequence of steps once. Or if the scopes need to change.**
4144

4245
.. code:: python3

twitchio/client.py

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
from .http import HTTPAsyncIterator
6060
from .models.clips import Clip
6161
from .models.entitlements import Entitlement, EntitlementStatus
62-
from .models.eventsub_ import EventsubSubscriptions
62+
from .models.eventsub_ import EventsubSubscription, EventsubSubscriptions
6363
from .models.search import SearchChannel
6464
from .models.streams import Stream, VideoMarkers
6565
from .models.videos import Video
@@ -1660,6 +1660,56 @@ async def fetch_users(
16601660
data = await self._http.get_users(ids=ids, logins=logins, token_for=token_for)
16611661
return [User(d, http=self._http) for d in data["data"]]
16621662

1663+
async def fetch_user(
1664+
self,
1665+
*,
1666+
id: str | int | None = None,
1667+
login: str | None = None,
1668+
token_for: str | PartialUser | None = None,
1669+
) -> User | None:
1670+
"""|coro|
1671+
1672+
Fetch information about one user.
1673+
1674+
.. note::
1675+
1676+
You may look up a specific user using their user ID or login name.
1677+
1678+
If you don't specify an ID or login name but provide the `token_for` parameter,
1679+
the request returns information about the user associated with the access token.
1680+
1681+
To include the user's verified email address in the response,
1682+
you must have a user access token that includes the `user:read:email` scope.
1683+
1684+
Parameters
1685+
----------
1686+
id: str | int | None
1687+
The id of the user to fetch information about.
1688+
login: str | None
1689+
The login name of the user to fetch information about.
1690+
token_for: str | PartialUser | None
1691+
|token_for|
1692+
1693+
If this parameter is provided, the token must have the `user:read:email` scope
1694+
in order to request the user's verified email address.
1695+
1696+
Returns
1697+
-------
1698+
:class:`twitchio.User`
1699+
A :class:`twitchio.User` object.
1700+
1701+
Raises
1702+
------
1703+
ValueError
1704+
Please provide only one of `id` or `login`.
1705+
"""
1706+
1707+
if id is not None and login is not None:
1708+
raise ValueError("Please provide only one of `id` or `login`.")
1709+
1710+
data = await self._http.get_users(ids=id, logins=login, token_for=token_for)
1711+
return User(data["data"][0], http=self._http) if data["data"] else None
1712+
16631713
def search_categories(
16641714
self,
16651715
query: str,
@@ -2363,6 +2413,7 @@ async def fetch_eventsub_subscriptions(
23632413
token_for: str | PartialUser | None = None,
23642414
type: str | None = None,
23652415
user_id: str | PartialUser | None = None,
2416+
subscription_id: str | None = None,
23662417
status: Literal[
23672418
"enabled",
23682419
"webhook_callback_verification_pending",
@@ -2389,7 +2440,7 @@ async def fetch_eventsub_subscriptions(
23892440
Fetches Eventsub Subscriptions for either webhook or websocket.
23902441
23912442
.. note::
2392-
type, status and user_id are mutually exclusive and only one can be passed, otherwise ValueError will be raised.
2443+
type, status, user_id, and subscription_id are mutually exclusive and only one can be passed, otherwise ValueError will be raised.
23932444
23942445
This endpoint returns disabled WebSocket subscriptions for a minimum of 1 minute as compared to webhooks which returns disabled subscriptions for a minimum of 10 days.
23952446
@@ -2403,6 +2454,8 @@ async def fetch_eventsub_subscriptions(
24032454
Filter subscriptions by subscription type. e.g. ``channel.follow`` For a list of subscription types, see `Subscription Types <https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types/#subscription-types>`_.
24042455
user_id: str | PartialUser | None
24052456
Filter subscriptions by user ID, or PartialUser. The response contains subscriptions where this ID matches a user ID that you specified in the Condition object when you created the subscription.
2457+
subscription_id: str | None
2458+
The specific subscription ID to fetch.
24062459
status: str | None = None
24072460
Filter subscriptions by its status. Possible values are:
24082461
@@ -2457,18 +2510,58 @@ async def fetch_eventsub_subscriptions(
24572510
Raises
24582511
------
24592512
ValueError
2460-
Only one of 'status', 'user_id', or 'type' can be provided.
2513+
Only one of 'status', 'user_id', 'subscription_id', or 'type' can be provided.
24612514
"""
24622515

2463-
provided: int = len([v for v in (type, user_id, status) if v])
2516+
provided: int = len([v for v in (type, user_id, status, subscription_id) if v])
24642517
if provided > 1:
2465-
raise ValueError("Only one of 'status', 'user_id', or 'type' can be provided.")
2518+
raise ValueError("Only one of 'status', 'user_id', 'subscription_id', or 'type' can be provided.")
24662519

24672520
return await self._http.get_eventsub_subscription(
24682521
type=type,
24692522
max_results=max_results,
24702523
token_for=token_for,
2524+
subscription_id=subscription_id,
2525+
user_id=user_id,
2526+
status=status,
2527+
)
2528+
2529+
async def fetch_eventsub_subscription(
2530+
self,
2531+
subscription_id: str,
2532+
*,
2533+
token_for: str | PartialUser | None = None,
2534+
) -> EventsubSubscription | None:
2535+
"""|coro|
2536+
2537+
Fetches a specific Eventsub Subscription for either webhook or websocket.
2538+
2539+
.. note::
2540+
This endpoint returns disabled WebSocket subscriptions for a minimum of 1 minute as compared to webhooks which returns disabled subscriptions for a minimum of 10 days.
2541+
2542+
Parameters
2543+
-----------
2544+
subscription_id: str
2545+
The specific subscription ID to fetch.
2546+
token_for: str | PartialUser | None
2547+
By default, if this is ignored or set to None then the App Token is used. This is the case when you want to fetch webhook events.
2548+
2549+
Provide a user ID here for when you want to fetch websocket events tied to a user.
2550+
2551+
Returns
2552+
--------
2553+
EventsubSubscription | None
2554+
"""
2555+
2556+
data = await self._http.get_eventsub_subscription(
2557+
type=None,
2558+
max_results=None,
2559+
token_for=token_for,
2560+
subscription_id=subscription_id,
2561+
user_id=None,
2562+
status=None,
24712563
)
2564+
return await anext(data.subscriptions, None)
24722565

24732566
async def delete_eventsub_subscription(self, id: str, *, token_for: str | PartialUser | None = None) -> None:
24742567
"""|coro|

twitchio/eventsub/subscriptions.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ class ChannelBitsUseSubscription(SubscriptionPayload):
427427
- Cheers in a channel
428428
- Uses a Power-up
429429
- Will not emit when a streamer uses a Power-up for free in their own channel.
430+
- Sends Combos
430431
431432
.. important::
432433
Requires a user access token that includes the ``bits:read`` scope. This must be the broadcaster's token.

twitchio/http.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1486,6 +1486,7 @@ async def get_eventsub_subscription(
14861486
]
14871487
| None = None,
14881488
user_id: str | PartialUser | None = None,
1489+
subscription_id: str | None = None,
14891490
type: str | None = None,
14901491
max_results: int | None = None,
14911492
token_for: str | PartialUser | None = None,
@@ -1498,6 +1499,8 @@ async def get_eventsub_subscription(
14981499
params["status"] = status
14991500
if user_id is not None:
15001501
params["user_id"] = str(user_id)
1502+
if subscription_id is not None:
1503+
params["subscription_id"] = subscription_id
15011504

15021505
route: Route = Route("GET", "eventsub/subscriptions", params=params, token_for=token_for)
15031506

twitchio/user.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class PartialUser:
8888
id: str | int
8989
The user's ID.
9090
name: str | None
91-
The user's name. In most cases, this is provided. There are however, rare cases where it is not.
91+
The user's name. Also known as *username* or *login name*. In most cases, this is provided. There are however, rare cases where it is not.
9292
display_name: str | None
9393
The user's display name in chat. In most cases, this is provided otherwise fallsback to `name`. There are however, rare cases where it is not.
9494
"""
@@ -3459,7 +3459,7 @@ class User(PartialUser):
34593459
id: str
34603460
The user's ID.
34613461
name: str | None
3462-
The user's name. In most cases, this is provided. There are however, rare cases where it is not.
3462+
The user's name. Also known as *username* or *login name*. In most cases, this is provided. There are however, rare cases where it is not.
34633463
display_name: str
34643464
The display name of the user.
34653465
type: Literal["admin", "global_mod", "staff", ""]

0 commit comments

Comments
 (0)