Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simple Unban Request manager #68

Merged
merged 4 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ These examples are testable on GitHub pages, and will prompt for implicit authen
<tr><td><a href="https://barrycarlyon.github.io/twitch_misc/examples/channel_dashboard/">Near Clone of the Dashboard</a></td><td><a href="https://github.com/BarryCarlyon/twitch_misc/tree/main/examples/channel_dashboard">Source</a></td><td>The <a href="https://dashboard.twitch.tv/stream-manager">Dashboard</a> core parts (edit stream info) but via the API</td></tr>
<tr><td><a href="https://barrycarlyon.github.io/twitch_misc/examples/poll_tool/">Simple Poll Tool/Results Display</a></td><td><a href="https://github.com/BarryCarlyon/twitch_misc/tree/main/examples/poll_tool">Source</a></td><td>A simple tool to create a poll and monitor the results</td></tr>
<tr><td><a href="https://barrycarlyon.github.io/twitch_misc/examples/channel_points/">Simple Channel Points Manager</a></td><td><a href="https://github.com/BarryCarlyon/twitch_misc/tree/main/examples/channel_points">Source</a></td><td>A simple tool to manage rewards</td></tr>
<tr><td><a href="https://barrycarlyon.github.io/twitch_misc/examples/ban_request_manager/">Simple UnBan Requests Manager</a></td><td><a href="https://github.com/BarryCarlyon/twitch_misc/tree/main/examples/ban_request_manager">Source</a></td><td>A simple tool to manage unban requests</td></tr>
<tr><td><a href="https://barrycarlyon.github.io/twitch_misc/examples/stream_key/">Get my Stream Key</a></td><td><a href="https://github.com/BarryCarlyon/twitch_misc/tree/main/examples/stream_key">Source</a></td><td>A simple demo to auth the user and show the user their own stream key.</td></tr>
<tr><td><a href="https://barrycarlyon.github.io/twitch_misc/examples/clips_navigator/">Clips Navigator</a></td><td><a href="https://github.com/BarryCarlyon/twitch_misc/tree/main/examples/clips_navigator">Source</a></td><td>A simple demo fetch and display clips using started_at and ended_at parameters.</td></tr>
<tr><td><a href="https://barrycarlyon.github.io/twitch_misc/examples/twitchemotes/">TwitchEmotes</a></td><td><a href="https://github.com/BarryCarlyon/twitch_misc/tree/main/examples/twitchemotes/">Source</a></td><td></td></tr>
Expand All @@ -53,7 +54,7 @@ These examples are testable on GitHub pages, and will prompt for implicit authen
<tbody>
<tr><td><a href="https://barrycarlyon.github.io/twitch_misc/eventsub/websockets/web/basic/">The Basics</a></td><td><a href="https://github.com/BarryCarlyon/twitch_misc/tree/main/eventsub/websockets/web/basic">Source</a></td><td>A basic EventSub WebSocket connector</td></tr>
<tr><td><a href="https://barrycarlyon.github.io/twitch_misc/eventsub/websockets/web/chat/">The Chat Topics</a></td><td><a href="https://github.com/BarryCarlyon/twitch_misc/tree/main/eventsub/websockets/web/chat">Source</a></td><td>Testing the new Chat Topics</td></tr>
<tr><td colspan="3">Notes about how Authentication works for Chat over EventSub - https://github.com/BarryCarlyon/twitch_misc/tree/main/eventsub/websockets/web/chat#how-does-authentication-work</td></tr>
<tr><td colspan="3">Notes about how Authentication works for Chat over EventSub <a href="https://github.com/BarryCarlyon/twitch_misc/tree/main/eventsub/websockets/web/chat#how-does-authentication-work">Found Here</a></td></tr>
<tr><td><a href="https://barrycarlyon.github.io/twitch_misc/eventsub/websockets/web/creatorgoals/">Creator Goals EventSub WebSocket</a></td><td><a href="https://github.com/BarryCarlyon/twitch_misc/tree/main/eventsub/websockets/web/creatorgoals/">Source</a></td><td>A EventSub WebSocket CreatorGoals Example</td></tr>
<tr><td><a href="https://barrycarlyon.github.io/twitch_misc/eventsub/websockets/web/charity/">Charity EventSub WebSocket</a></td><td><a href="https://github.com/BarryCarlyon/twitch_misc/tree/main/eventsub/websockets/web/charity/">Source</a></td><td>A EventSub WebSocket Charity Example</td></tr>
<tr><td><a href="https://barrycarlyon.github.io/twitch_misc/examples/poll_tool/">Simple Poll Tool/Results Display</a></td><td><a href="https://github.com/BarryCarlyon/twitch_misc/tree/main/examples/poll_tool">Source</a></td><td>A simple tool to create a poll and monitor the results via EventSub WebSocket.</td></tr>
Expand Down
1 change: 1 addition & 0 deletions eventsub/websockets/web/eventsub.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ class initSocket {
}

trigger() {
// this function lets you test the disconnect on send method
this.eventsub.send('cat');
}
close() {
Expand Down
32 changes: 32 additions & 0 deletions examples/ban_request_manager/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## What is this example

An example project to manage unban requests on any channel the logged in user is a moderator on

This is an example on how to

- Obtain a token
- Use that token to get the channels that logged in user is a moderator for
- Upon selecting a channel, get the unban requests for that channel
- Update/Resolve the unban requests

Resoling an unban request to "unban the user" will mark the request as accepted and unban the user, so you do not need to make a second API request to unban the user.

## TRY THIS EXAMPLE NOW!

This example is also available via GitHub Pages!

Give it a [whirl here](https://barrycarlyon.github.io/twitch_misc/examples/ban_request_manager/)

## Reference Documentation

- [Get Moderated Channels](https://dev.twitch.tv/docs/api/reference/#get-moderated-channels)
- [Get Unban Requests](https://dev.twitch.tv/docs/api/reference/#get-unban-requests)
- [Resolve Unban Request](https://dev.twitch.tv/docs/api/reference/#resolve-unban-requests)

## Running the example

If you have PHP installed

> sudo php -S 127.0.0.1:80

or just throw the code up on a webpage somewhere
256 changes: 256 additions & 0 deletions examples/ban_request_manager/ban_manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
// go populate this with a client_id
var client_id = 'hozgh446gdilj5knsrsxxz8tahr3koz';
var redirect = window.location.origin + '/twitch_misc/';

// setup a memory space for the token/userID
// and the state machine
var access_token = '';
var user_id = '';
var channel_id = '';
var unban_request_id = '';

let status = document.getElementById('status');

// setup authorise link
document.getElementById('authorize').setAttribute('href', 'https://id.twitch.tv/oauth2/authorize?client_id=' + client_id + '&redirect_uri=' + encodeURIComponent(redirect) + '&response_type=token&scope=user:read:moderated_channels+moderator:read:unban_requests+moderator:manage:unban_requests');

async function processToken(token) {
access_token = token;

status.textContent = 'Got Token. Loading Things';

// who are we
let user_resp = await fetch(
'https://api.twitch.tv/helix/users',
{
method: 'GET',
headers: {
'Client-ID': client_id,
'Authorization': `Bearer ${access_token}`,
'Accept': 'application/json'
}
}
);

if (user_resp.status != 200) {
status.textContent = `Failed to obtain User information ${user_resp.status} - ${await user_resp.text()}`;
return;
}

let user_data = await user_resp.json();
if (user_data.data.length != 1) {
status.textContent = `Failed to obtain a User`;
return;
}

user_id = user_data.data[0].id;
status.textContent = `Hello ${user_id} - ${user_data.data[0].login}`;

getPageChannels();
}

// get "targets"
async function getPageChannels(after) {
let channels_url = new URL('https://api.twitch.tv/helix/moderation/channels');
let p = [
[ 'user_id', user_id ],
[ 'first', 100 ]
]
if (after) {
p.push([ 'after', after ]);
}
channels_url.search = new URLSearchParams(p);
let channels_req = await fetch(
channels_url,
{
method: 'GET',
headers: {
'Client-ID': client_id,
'Authorization': `Bearer ${access_token}`,
'Accept': 'application/json'
}
}
);

if (channels_req.status != 200) {
status.textContent = `Failed to get channels you mod: ${channels_req.status} - ${await channels_req.text()}`;
return;
}

let channels_resp = await channels_req.json();
let { data, pagination } = channels_resp;

// draw targets
channel_select.textContent = '';
channel_select.removeAttribute('disabled');

let opt = document.createElement('option');
opt.value = user_id;
opt.textContent = 'You';
channel_select.append(opt);

data.forEach(channel => {
let { broadcaster_id, broadcaster_name } = channel;

let opt = document.createElement('option');
opt.value = broadcaster_id;
opt.textContent = broadcaster_name;
channel_select.append(opt);
});

// next?
channel_id = user_id;
initIt();
}

channel_select.addEventListener('change', (e) => {
channel_id = e.target.value;
console.log('CID', channel_id);
status.textContent = `Loading into ${channel_id}`;

initIt();
});

async function initIt() {
// open up websocket for eventsub for real time

resetUnbanRequests();
}

async function resetUnbanRequests() {
requests.textContent = '';
// load current data
loadUnbanRequests();
}
async function loadUnbanRequests(after) {
let unbans_url = new URL('https://api.twitch.tv/helix/moderation/unban_requests');
let p = [
[ 'broadcaster_id', channel_id ],
[ 'moderator_id', user_id ],
[ 'status', 'pending' ],
[ 'first', 100 ]
]
if (after) {
p.push([ 'after', after ]);
}
unbans_url.search = new URLSearchParams(p);

let unbans_req = await fetch(
unbans_url,
{
method: 'GET',
headers: {
'Client-ID': client_id,
'Authorization': `Bearer ${access_token}`,
'Accept': 'application/json'
}
}
);

if (unbans_req.status != 200) {
status.textContent = `Failed to get requests: ${unbans_req.status} - ${await unbans_req.text()}`;
return;
}

let { data, pagination } = await unbans_req.json();

data.forEach(unban => {
let { broadcaster_login, user_login, user_name } = unban;
let { id, text } = unban;
let { created_at } = unban;

let dsp = '';

// add to le stack
let dat = new Date(created_at);
let y = dat.getFullYear();
let m = dat.getMonth() + 1;
let d = dat.getDate();

dsp += `${y}/${m}/${d}`;

dsp += ' ';

let h = dat.getHours();
if (h < 10) { h = `0${h}`; }
let i = dat.getMinutes();
if (i < 10) { i = `0${i}`; }
dsp += `${h}:${i}`;

let r = requests.insertRow();
var c = r.insertCell();
c.textContent = user_name;
var c = r.insertCell();
c.textContent = dsp;
var c = r.insertCell();
c.textContent = text;

var c = r.insertCell();
var b = document.createElement('a');
b.href = `https://www.twitch.tv/popout/${broadcaster_login}/viewercard/${user_login}?popout=`;
b.textContent = 'UserCard';
b.target = '_blank';
c.append(b);

var c = r.insertCell();
var b = document.createElement('div');
b.textContent = 'Act';
b.classList.add('alink');
b.setAttribute('data-ban-id', id);
c.append(b);

b.addEventListener('click', (e) => {
act.showModal();
//act_act.setAttribute('data-ban-id', e.target.getAttribute('data-ban-id'));
unban_request_id = e.target.getAttribute('data-ban-id');
});
});
}

act_accept.addEventListener('click', (e) => {
processRequest('approved');
});
act_reject.addEventListener('click', (e) => {
processRequest('denied');
});
act_noact.addEventListener('click', (e) => {
act.close();
unban_request_id = '';
});

async function processRequest(status) {
// add a spinner?
let resolution_text = resolution_text_text.value;

let take_action_req = await fetch(
'https://api.twitch.tv/helix/moderation/unban_requests',
{
method: 'PATCH',
headers: {
'Client-ID': client_id,
'Authorization': `Bearer ${access_token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
broadcaster_id: channel_id,
moderator_id: user_id,
unban_request_id,
status,
resolution_text
})
}
);

act.close();
unban_request_id = '';

if (take_action_req.status != 200) {
status.textContent = `Failed to take action ${status} - ${take_action_req.status} - ${await take_action_req.text()}`;
return;
}
status.textContent = 'Completed the requested action';

// trigger reload?
resetUnbanRequests();
}
Loading
Loading