Skip to content

Commit 989ab20

Browse files
committed
improve examples and comments
also bumps twitch_oauth2
1 parent 38dca41 commit 989ab20

File tree

23 files changed

+374
-284
lines changed

23 files changed

+374
-284
lines changed

CONTRIBUTING.md

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,111 @@
1+
# Contributing to twitch_api
2+
3+
## Git basics
4+
5+
### Cloning the repo
6+
7+
```sh
8+
git clone https://github.com/twitch-rs/twitch_api.git --recurse-submodules
9+
cd twitch_api
10+
```
11+
12+
You can also use the [GitHub CLI](https://cli.github.com/) to clone the repository.
13+
14+
```sh
15+
gh repo clone twitch-rs/twitch_api
16+
cd twitch_api
17+
```
18+
19+
### Checking out a branch
20+
21+
```sh
22+
git checkout <branch_name>
23+
```
24+
25+
to create a new branch (this is now default behaviour in newer git version)
26+
27+
```sh
28+
git checkout -b <branch_name>
29+
```
30+
31+
### Fetching the git submodules
32+
33+
To get started with using this repository, ensure you have initialized and updated the submodules in order to retrieve their contents.
34+
35+
```sh
36+
git submodule update --init --recursive
37+
```
38+
39+
alternatively, you can also run
40+
41+
```sh
42+
git submodule init
43+
git submodule update
44+
```
45+
46+
### Resetting
47+
48+
```sh
49+
# reset the last commit, keeping changes
50+
git reset HEAD~1
51+
# reset the last commit, discarding changes
52+
git reset HEAD~1 --hard
53+
```
54+
55+
### Rebasing
56+
57+
To rebase your branch on top of the latest changes on the main branch, run
58+
59+
```sh
60+
git pull upstream main --rebase
61+
```
62+
63+
if you want to combine changes into one commit, you can also use rebase to interactively squash commits
64+
65+
```sh
66+
# Using relative commit
67+
git rebase -i HEAD~<number_of_commits>
68+
# Using a specific commit
69+
git rebase -i <commit_hash>
70+
```
71+
72+
## Creating a pull request
73+
74+
To create a pull request, see [GitHub's documentation](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request).
75+
76+
To make things easy, you can use the [GitHub CLI](https://cli.github.com/) to fork the repository, checkout issues and create pull requests from the command line.
77+
78+
```sh
79+
# fork the repository, creates a upstream remote, can be used in an already cloned repository as well
80+
gh repo fork twitch-rs/twitch_api --clone
81+
# navigate into the fork
82+
cd twitch_api
83+
84+
# sync submodules
85+
git submodule update --init --recursive
86+
87+
# create a branch
88+
git checkout -b <branch_name>
89+
90+
# checkout an issue and create a branch
91+
gh issue develop -c <number/url>
92+
93+
# create a pull request
94+
gh pr create
95+
96+
# rebase changes with main
97+
git pull upstream main --rebase
98+
```
99+
100+
### Maintaining
101+
1102
#### Updating twitch_oauth2
2103

3104
To update the `twitch_oauth2` submodule, run the appropriate
4105
[`git submodule` command](https://git-scm.com/book/en/v2/Git-Tools-Submodules).
5106
For example, to update to the latest commit on the remote default branch,
6107
you may want to run:
7108

8-
```
109+
```sh
9110
git submodule update --remote twitch_oauth2
10111
```

Cargo.lock

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ exclude = ["twitch_types", "twitch_oauth2"]
2828

2929
[workspace.dependencies]
3030
twitch_api = { version = "0.7.0-rc.6", path = "." }
31-
twitch_oauth2 = { version = "0.12.0", path = "twitch_oauth2/" }
31+
twitch_oauth2 = { version = "0.12.1", path = "twitch_oauth2/" }
3232
twitch_types = { version = "0.4.1", features = [
3333
"serde",
3434
], path = "./twitch_types" }
@@ -69,7 +69,7 @@ default = ["deser_borrow"]
6969
client = ["twitch_oauth2/client", "dep:futures", "dep:hyper"]
7070

7171
unsupported = ["serde_json?/raw_value", "beta"]
72-
beta = []
72+
beta = ["serde_json?/raw_value"]
7373
deny_unknown_fields = []
7474
trace_unknown_fields = ["dep:serde_ignored", "tracing"]
7575

README.md

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,24 @@ See [documentation](https://docs.rs/twitch_api) for more info.
1111

1212
You can see current unpublished docs for the main branch here: [![local-docs]](https://twitch-rs.github.io/twitch_api/twitch_api)
1313

14-
See [examples](./examples) for examples.
14+
See [examples](./examples) for examples. If you want to run them locally,
15+
make sure you [get the git submodules](./CONTRIBUTING.md#fetching-the-git-submodules) first.
1516

1617
[local-docs]: https://img.shields.io/github/actions/workflow/status/twitch-rs/twitch_api/gh-pages.yml?label=dev%20docs&style=flat-square&event=push
1718

1819
```rust ,no_run
1920
use twitch_api::helix::HelixClient;
2021
use twitch_api::twitch_oauth2::{AccessToken, UserToken};
21-
use reqwest::Client as ReqwestClient;
2222

2323
#[tokio::main]
2424
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
25-
let client: HelixClient<ReqwestClient> = HelixClient::default();
25+
// Create the HelixClient, which is used to make requests to the Twitch API
26+
let client: HelixClient<reqwest::Client> = HelixClient::default();
27+
// Create a UserToken, which is used to authenticate requests
28+
let token = UserToken::from_token(&client, AccessToken::from("mytoken")).await?;
2629

27-
let token = UserToken::from_existing(
28-
&client,
29-
AccessToken::new("mytoken".to_string()),
30-
None, // Refresh Token
31-
None, // Client Secret
32-
)
33-
.await?;
34-
35-
println!("Channel: {:?}",
30+
println!(
31+
"Channel: {:?}",
3632
client.get_channel_from_login("twitchdev", &token).await?
3733
);
3834

examples/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Examples
2+
3+
## Getting a token
4+
5+
To run the examples, you will need to have a Twitch OAuth token. You can get one by following the [Twitch OAuth guide](https://dev.twitch.tv/docs/authentication/getting-tokens-oauth).
6+
7+
There are sites available that can help you generate these tokens, or you can use the official [Twitch CLI](https://github.com/twitchdev/twitch-cli), `twitch_oauth2::UserToken::builder()` or `twitch_oauth2::tokens::ImplicitUserTokenBuilder`
8+
9+
## Running the examples
10+
11+
To run an example, ensure you've gotten the [submodules](../CONTRIBUTING.md#fetching-the-git-submodules) and have a [token](#getting-a-token) available.
12+
13+
```sh
14+
git clone https://github.com/twitch-rs/twitch_api.git --recurse-submodules
15+
cd twitch_api
16+
# if you didn't get the submodules, run
17+
# git submodule update --init --recursive
18+
cargo run --example <example_name> -- <token>
19+
```
20+
21+
Some examples are their own crates/workspace members, you can run these with
22+
23+
```sh
24+
cargo run -p <example> -- <args>
25+
```
26+
27+
## .env
28+
29+
Instead of passing a token to every example, you can also create a `.env` file in the root of the repository with the following contents
30+
31+
```txt
32+
# .env
33+
TWITCH_TOKEN=mytoken
34+
CLIENT_ID=myclientid
35+
CLIENT_SECRET=myclientid
36+
```

examples/eventsub/Dockerfile

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,16 @@ COPY ../../ .
1010
ARG RUSTFLAGS=-Ctarget-feature=-crt-static
1111
ARG CARGO_UNSTABLE_SPARSE_REGISTRY=true
1212
RUN --mount=type=cache,target=$CARGO_HOME/git \
13-
--mount=type=cache,target=$CARGO_HOME/registry \
14-
--mount=type=cache,sharing=private,target=/app/target \
15-
cargo -V; cargo build --release -p eventsub && mv /app/target/release/eventsub /app/is_live
13+
--mount=type=cache,target=$CARGO_HOME/registry \
14+
--mount=type=cache,sharing=private,target=/app/target \
15+
cargo -V
16+
cargo build --release -p eventsub && mv /app/target/release/eventsub /app/is_live
1617
FROM alpine:3.16 as runtime
1718
WORKDIR /app
1819
ARG RUN_DEPS="ca-certificates openssl libgcc"
1920
RUN apk add --no-cache \
20-
${RUN_DEPS}
21+
${RUN_DEPS}
2122
COPY --from=builder /app/is_live /app/is_live
2223
COPY ./examples/eventsub/static ./static
23-
ENTRYPOINT "/app/is_live"
24+
EXPOSE 80
25+
ENTRYPOINT ["/app/is_live", "--interface", "0.0.0.0"]

examples/eventsub/src/main.rs

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@ async fn main() -> Result<(), eyre::Report> {
5454
Ok(())
5555
}
5656

57+
/// Run the application
5758
pub async fn run(opts: &Opts) -> eyre::Result<()> {
58-
let client: HelixClient<'static, _> = twitch_api::HelixClient::with_client(
59+
// Create the HelixClient, which is used to make requests to the Twitch API
60+
let client: HelixClient<_> = twitch_api::HelixClient::with_client(
5961
<reqwest::Client>::default_client_with_name(Some(
6062
"twitch-rs/eventsub"
6163
.parse()
@@ -65,6 +67,7 @@ pub async fn run(opts: &Opts) -> eyre::Result<()> {
6567
.wrap_err_with(|| "when creating client")?,
6668
);
6769

70+
// Get the app access token
6871
let token = twitch_oauth2::AppAccessToken::get_app_access_token(
6972
&client,
7073
opts.client_id.clone(),
@@ -73,29 +76,37 @@ pub async fn run(opts: &Opts) -> eyre::Result<()> {
7376
)
7477
.await?;
7578

79+
// Get the user we want to listen to
7680
let broadcaster = client
7781
.get_user_from_login(&opts.broadcaster_login, &token)
7882
.await?
7983
.ok_or_else(|| eyre::eyre!("broadcaster not found"))?;
8084

85+
// Create the config, which is shared between all requests
8186
let config = Arc::new(Config {
8287
broadcaster_url: stream_url_from_user(&broadcaster.login),
8388
broadcaster,
8489
website_url: opts.website.clone(),
8590
});
8691

92+
// Status of the channel
8793
let live = twitch::is_live(&config, &client, &token).await?;
8894

95+
// make the token sharable via an Arc<RwLock<_>>
8996
let token = Arc::new(tokio::sync::RwLock::new(token));
97+
98+
// watch channel for the live status, sent to every website websocket client
9099
let (sender, recv) = watch::channel(live);
91100
let sender = Arc::new(sender);
101+
102+
// Retainer/cache for the eventsub subscriptions, stores the header Twitch-Eventsub-Message-Id to check if we've already seen the request from twitch.
92103
let retainer = Arc::new(retainer::Cache::<axum::http::HeaderValue, ()>::new());
93104
let ret = retainer.clone();
94-
let retainer_cleanup = async move {
105+
let retainer_cleanup = tokio::spawn(async move {
95106
ret.monitor(10, 0.50, tokio::time::Duration::from_secs(86400 / 2))
96107
.await;
97108
Ok::<(), eyre::Report>(())
98-
};
109+
});
99110

100111
let app = Router::new()
101112
.route(
@@ -143,23 +154,27 @@ pub async fn run(opts: &Opts) -> eyre::Result<()> {
143154
.layer(CatchPanicLayer::new()),
144155
);
145156

157+
// spawn the server
158+
let address = (opts.interface, opts.port).into();
146159
let server = tokio::spawn(async move {
147-
axum::Server::bind(
148-
&"0.0.0.0:80"
149-
.parse()
150-
.wrap_err_with(|| "when parsing address")?,
151-
)
152-
.serve(app.into_make_service())
153-
.await
154-
.wrap_err_with(|| "when serving")?;
160+
axum::Server::bind(&address)
161+
.serve(app.into_make_service())
162+
.await
163+
.wrap_err_with(|| "when serving")?;
155164
Ok::<(), eyre::Report>(())
156165
});
157-
tracing::info!("spinning up server!");
166+
tracing::info!("spinning up server! http://{}", address);
167+
158168
if std::env::var("IM_A_SERVER").is_err() {
159-
tracing::warn!("to run this example you need to be a server with a url with tls,
160-
this means you're either behind a reverse-proxy, or you've setup this example to handle that");
169+
tracing::warn!("to run this example you need to be a server with a url and have https via tls,
170+
this means you're either behind a reverse-proxy, or you've setup this example to handle that");
171+
tracing::warn!(
172+
"set IM_A_SERVER=1 to bypass this check, see eventsub_websocket
173+
for an example which doesn't require a server"
174+
);
161175
std::env::set_var("DEV", "1");
162176
}
177+
163178
let r = tokio::try_join!(
164179
flatten(server),
165180
flatten(tokio::spawn(twitch::checker(
@@ -181,7 +196,7 @@ pub async fn run(opts: &Opts) -> eyre::Result<()> {
181196
opts.website_callback.clone(),
182197
opts.sign_secret.clone()
183198
))),
184-
flatten(tokio::spawn(retainer_cleanup)),
199+
flatten(retainer_cleanup),
185200
);
186201
r?;
187202
Ok(())

examples/eventsub/src/opts.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ pub struct Opts {
1717
pub website_callback: String,
1818
#[clap(long, env, hide_env = true)]
1919
pub website: String,
20+
/// port to use for the server
21+
#[clap(long, short, default_value = "80")]
22+
pub port: u16,
23+
/// interface to use for the server
24+
#[clap(long, short, default_value = "127.0.0.1")]
25+
pub interface: std::net::IpAddr,
2026
}
2127

2228
#[derive(Clone)]

0 commit comments

Comments
 (0)