Updated list of commands to v4.3. Added groups & permissions. Added connections. Updated redemptions and actions to v4.3.
This commit is contained in:
@ -15,22 +15,22 @@ export async function GET(req: Request) {
|
||||
|
||||
// Verify state against user id in user table.
|
||||
const user = await db.user.findFirst({
|
||||
where: {
|
||||
id: state
|
||||
}
|
||||
where: {
|
||||
id: state
|
||||
}
|
||||
})
|
||||
|
||||
if (!user) {
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
}
|
||||
|
||||
// Post to https://id.twitch.tv/oauth2/token
|
||||
const token: { access_token:string, expires_in:number, refresh_token:string, token_type:string, scope:string[] } = (await axios.post("https://id.twitch.tv/oauth2/token", {
|
||||
const token: { access_token: string, expires_in: number, refresh_token: string, token_type: string, scope: string[] } = (await axios.post("https://id.twitch.tv/oauth2/token", {
|
||||
client_id: process.env.TWITCH_BOT_CLIENT_ID,
|
||||
client_secret: process.env.TWITCH_BOT_CLIENT_SECRET,
|
||||
code: code,
|
||||
grant_type: "authorization_code",
|
||||
redirect_uri: "https://hermes.goblincaves.com/api/account/authorize"
|
||||
redirect_uri: "https://tomtospeech.com/api/account/authorize"
|
||||
})).data
|
||||
|
||||
// Fetch values from token.
|
||||
@ -49,17 +49,17 @@ export async function GET(req: Request) {
|
||||
const broadcasterId = info.data.data[0]['id']
|
||||
|
||||
await db.twitchConnection.create({
|
||||
data: {
|
||||
broadcasterId: broadcasterId,
|
||||
accessToken: access_token,
|
||||
refreshToken: refresh_token,
|
||||
userId: state
|
||||
}
|
||||
data: {
|
||||
broadcasterId: broadcasterId,
|
||||
accessToken: access_token,
|
||||
refreshToken: refresh_token,
|
||||
userId: state
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
return new NextResponse("", { status: 200 });
|
||||
} catch (error) {
|
||||
console.log("[ACCOUNT]", error);
|
||||
console.log("[ACCOUNT/AUTHORIZE]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
@ -39,7 +39,8 @@ export async function GET(req: Request) {
|
||||
user_id: user.id,
|
||||
access_token: data?.accessToken,
|
||||
refresh_token: data?.refreshToken,
|
||||
broadcaster_id: connection.broadcasterId
|
||||
broadcaster_id: connection.broadcasterId,
|
||||
expires_in
|
||||
}
|
||||
return NextResponse.json(dataFormatted, { status: 201 });
|
||||
}
|
||||
@ -75,7 +76,8 @@ export async function GET(req: Request) {
|
||||
user_id: user.id,
|
||||
access_token,
|
||||
refresh_token,
|
||||
broadcaster_id: connection.broadcasterId
|
||||
broadcaster_id: connection.broadcasterId,
|
||||
expires_in
|
||||
}
|
||||
|
||||
return NextResponse.json(data)
|
||||
|
@ -18,16 +18,21 @@ export async function GET(req: Request) {
|
||||
if (!auth)
|
||||
return new NextResponse("Bad Request", { status: 400 })
|
||||
|
||||
const redemptions = await axios.get("https://api.twitch.tv/helix/channel_points/custom_rewards?broadcaster_id=" + auth.broadcaster_id,
|
||||
{
|
||||
headers: {
|
||||
"Client-Id": process.env.TWITCH_BOT_CLIENT_ID,
|
||||
"Authorization": "Bearer " + auth.access_token
|
||||
try {
|
||||
const redemptions = await axios.get("https://api.twitch.tv/helix/channel_points/custom_rewards?broadcaster_id=" + auth.broadcaster_id,
|
||||
{
|
||||
headers: {
|
||||
"Client-Id": process.env.TWITCH_BOT_CLIENT_ID,
|
||||
"Authorization": "Bearer " + auth.access_token
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
return NextResponse.json(redemptions.data);
|
||||
return NextResponse.json(redemptions.data);
|
||||
} catch (error: any) {
|
||||
console.error('Fetching Twitch channel redemptions:', error.response.data)
|
||||
}
|
||||
return NextResponse.json([]);
|
||||
} catch (error) {
|
||||
console.log("[REDEMPTIONS/ACTIONS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
|
@ -6,9 +6,16 @@ import fetchUser from "@/lib/fetch-user";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUser(req)
|
||||
if (!user) return new NextResponse("Internal Error", { status: 401 })
|
||||
return NextResponse.json(user)
|
||||
const user = await fetchUser(req)
|
||||
if (!user) return new NextResponse("Internal Error", { status: 401 })
|
||||
|
||||
const account = await db.account.findFirst({
|
||||
where: {
|
||||
userId: user.id
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json({ ... user, broadcasterId: account?.providerAccountId })
|
||||
} catch (error) {
|
||||
console.log("[ACCOUNT]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
@ -22,29 +29,29 @@ export async function POST(req: Request) {
|
||||
if (!user) {
|
||||
return new NextResponse("Internal Error", { status: 401 })
|
||||
}
|
||||
|
||||
|
||||
const exist = await db.user.findFirst({
|
||||
where: {
|
||||
name: user
|
||||
}
|
||||
where: {
|
||||
name: user
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (exist) {
|
||||
return NextResponse.json({
|
||||
id: exist.id,
|
||||
username: exist.name
|
||||
id: exist.id,
|
||||
username: exist.name
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const newUser = await db.user.create({
|
||||
data: {
|
||||
name: user,
|
||||
}
|
||||
data: {
|
||||
name: user,
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
id: newUser.id,
|
||||
username: newUser.name
|
||||
id: newUser.id,
|
||||
username: newUser.name
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("[ACCOUNT]", error);
|
||||
|
92
app/api/connection/authorize/route.ts
Normal file
92
app/api/connection/authorize/route.ts
Normal file
@ -0,0 +1,92 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserWithImpersonation from '@/lib/fetch-user-impersonation';
|
||||
import axios from "axios";
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req);
|
||||
if (!user)
|
||||
return NextResponse.json({ error: null, message: "Unauthorized", success: false }, { status: 401 });
|
||||
|
||||
let { access_token, expires_in, token_type, scope, state } = await req.json();
|
||||
|
||||
if (!token_type)
|
||||
return NextResponse.json({ error: null, message: 'No token type given for the authorization.', success: false }, { status: 400 })
|
||||
|
||||
if (!access_token)
|
||||
return NextResponse.json({ error: null, message: 'No access token given for the authorization.', success: false }, { status: 400 })
|
||||
|
||||
if (!scope)
|
||||
return NextResponse.json({ error: null, message: 'No scope given for the authorization.', success: false }, { status: 400 })
|
||||
|
||||
if (!state)
|
||||
return NextResponse.json({ error: null, message: 'No state given for the authorization.', success: false }, { status: 400 })
|
||||
|
||||
// Fetch connection state data
|
||||
const info = await db.connectionState.findUnique({
|
||||
where: {
|
||||
state: state
|
||||
}
|
||||
})
|
||||
if (!info)
|
||||
return NextResponse.json({ error: null, message: 'No authorization code was received previously.', success: false }, { status: 400 })
|
||||
|
||||
if (info.type == "twitch") {
|
||||
const response = await axios.get("https://id.twitch.tv/oauth2/validate", {
|
||||
headers: {
|
||||
Authorization: 'OAuth ' + access_token
|
||||
}
|
||||
})
|
||||
expires_in = response.data.expires_in
|
||||
}
|
||||
if (!expires_in)
|
||||
return NextResponse.json({ error: null, message: 'No expiration given for the authorization.', success: false }, { status: 400 })
|
||||
|
||||
let expiration = new Date()
|
||||
expiration.setSeconds(expiration.getSeconds() + parseInt(expires_in) - 600);
|
||||
|
||||
await db.connection.upsert({
|
||||
where: {
|
||||
userId_name: {
|
||||
userId: info.userId,
|
||||
name: info.name
|
||||
}
|
||||
},
|
||||
create: {
|
||||
userId: info.userId,
|
||||
name: info.name,
|
||||
type: info.type,
|
||||
clientId: info.clientId,
|
||||
accessToken: access_token,
|
||||
scope,
|
||||
grantType: token_type,
|
||||
expiresAt: expiration
|
||||
},
|
||||
update: {
|
||||
clientId: info.clientId,
|
||||
accessToken: access_token,
|
||||
scope,
|
||||
grantType: token_type,
|
||||
expiresAt: expiration
|
||||
}
|
||||
})
|
||||
|
||||
await db.connectionState.delete({
|
||||
where: {
|
||||
userId_name: {
|
||||
userId: user.id,
|
||||
name: info.name
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json({ error: null, message: "", success: true }, { status: 200 });
|
||||
} catch (error: any) {
|
||||
if (error.name == 'PrismaClientKnownRequestError') {
|
||||
if (error.code == 'P2002')
|
||||
return NextResponse.json({ error, message: "Connection already saved.", success: false }, { status: 500 });
|
||||
}
|
||||
return NextResponse.json({ error, message: "Failed to save connection", success: false }, { status: 500 });
|
||||
}
|
||||
}
|
75
app/api/connection/default/route.ts
Normal file
75
app/api/connection/default/route.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserWithImpersonation from '@/lib/fetch-user-impersonation';
|
||||
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req);
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: null, message: "Unauthorized", success: false }, { status: 401 });
|
||||
}
|
||||
|
||||
const data = await db.connection.findMany({
|
||||
where: {
|
||||
userId: user.id,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json({ error: null, message: "", success: true, data }, { status: 200 });
|
||||
} catch (error: any) {
|
||||
return NextResponse.json({ error, message: "Failed to get default connection", success: false }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req);
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: null, message: "Unauthorized", success: false }, { status: 401 });
|
||||
}
|
||||
|
||||
const { name } = await req.json();
|
||||
if (!name)
|
||||
return NextResponse.json({ error: null, message: 'Requires "name" param to be passed in - name of the connection.', success: false }, { status: 400 })
|
||||
|
||||
const connection = await db.connection.findFirst({
|
||||
where: {
|
||||
userId: user.id,
|
||||
name
|
||||
}
|
||||
})
|
||||
|
||||
if (!connection) {
|
||||
return NextResponse.json({ error: null, message: 'Connection with that name does not exist.', success: false }, { status: 400 })
|
||||
}
|
||||
|
||||
await db.connection.updateMany({
|
||||
where: {
|
||||
userId: user.id,
|
||||
type: connection.type,
|
||||
default: true
|
||||
},
|
||||
data: {
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const data = await db.connection.update({
|
||||
where: {
|
||||
userId_name: {
|
||||
userId: user.id,
|
||||
name,
|
||||
}
|
||||
},
|
||||
data: {
|
||||
default: true as boolean
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json({ error: null, message: "", success: true, data }, { status: 200 });
|
||||
} catch (error: any) {
|
||||
return NextResponse.json({ error, message: "Failed to update default connection", success: false }, { status: 500 });
|
||||
}
|
||||
}
|
59
app/api/connection/prepare/route.ts
Normal file
59
app/api/connection/prepare/route.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserWithImpersonation from '@/lib/fetch-user-impersonation';
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req);
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: null, message: "Unauthorized", success: false }, { status: 401 });
|
||||
}
|
||||
|
||||
let { state, name, type, grantType, clientId } = await req.json();
|
||||
|
||||
if (!clientId)
|
||||
return NextResponse.json({ error: null, message: 'No client id given for the authorization.', success: false }, { status: 400 })
|
||||
|
||||
if (!type)
|
||||
return NextResponse.json({ error: null, message: 'No type given for the authorization.', success: false }, { status: 400 })
|
||||
|
||||
if (!state)
|
||||
return NextResponse.json({ error: null, message: 'No state given for the authorization.', success: false }, { status: 400 })
|
||||
|
||||
if (!name)
|
||||
return NextResponse.json({ error: null, message: 'No name given for the authorization.', success: false }, { status: 400 })
|
||||
|
||||
if (!grantType)
|
||||
return NextResponse.json({ error: null, message: 'No grant type given for the authorization.', success: false }, { status: 400 })
|
||||
|
||||
await db.connectionState.upsert({
|
||||
where: {
|
||||
userId_name: {
|
||||
userId: user.id,
|
||||
name
|
||||
}
|
||||
},
|
||||
create: {
|
||||
userId: user.id,
|
||||
name,
|
||||
type,
|
||||
state,
|
||||
grantType,
|
||||
clientId
|
||||
},
|
||||
update: {
|
||||
name,
|
||||
state,
|
||||
grantType,
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json({ error: null, message: "", success: true }, { status: 200 });
|
||||
} catch (error: any) {
|
||||
if (error.name == 'PrismaClientKnownRequestError') {
|
||||
if (error.code == 'P2002')
|
||||
return NextResponse.json({ error, message: "Connection already prepared.", success: false }, { status: 500 });
|
||||
}
|
||||
return NextResponse.json({ error, message: "Failed to prepare connection", success: false }, { status: 500 });
|
||||
}
|
||||
}
|
74
app/api/connection/route.ts
Normal file
74
app/api/connection/route.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserWithImpersonation from '@/lib/fetch-user-impersonation';
|
||||
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req);
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: null, message: "Unauthorized", success: false }, { status: 401 });
|
||||
}
|
||||
|
||||
//const { searchParams } = new URL(req.url)
|
||||
const data = await db.connection.findMany({
|
||||
where: {
|
||||
userId: user.id
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json({ error: null, message: "", success: true, data }, { status: 200 });
|
||||
} catch (error: any) {
|
||||
return NextResponse.json({ error, message: "Failed to fetch connections", success: false }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req);
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: null, message: "Unauthorized", success: false }, { status: 401 });
|
||||
}
|
||||
|
||||
const { searchParams } = new URL(req.url)
|
||||
const name = searchParams.get('name') as string
|
||||
|
||||
if (!name)
|
||||
return NextResponse.json({ error: null, message: 'Requires "name" param to be passed in - name of the service.', success: false }, { status: 400 })
|
||||
|
||||
const data = await db.connection.delete({
|
||||
where: {
|
||||
userId_name: {
|
||||
userId: user.id,
|
||||
name: name
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const connections = await db.connection.findMany({
|
||||
where: {
|
||||
userId: user.id,
|
||||
type: data.type
|
||||
}
|
||||
})
|
||||
|
||||
if (connections.length > 0 && connections.every(c => !c.default)) {
|
||||
const connectionName = connections[0].name
|
||||
await db.connection.update({
|
||||
where: {
|
||||
userId_name: {
|
||||
userId: user.id,
|
||||
name: connectionName
|
||||
}
|
||||
},
|
||||
data: {
|
||||
default: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return NextResponse.json({ error: null, message: "", success: true, data }, { status: 200 });
|
||||
} catch (error: any) {
|
||||
return NextResponse.json({ error, message: "Failed to delete connection", success: false }, { status: 500 });
|
||||
}
|
||||
}
|
@ -2,10 +2,22 @@ import { NextResponse } from "next/server";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
return NextResponse.json({
|
||||
major_version: 3,
|
||||
major_version: 4,
|
||||
minor_version: 3,
|
||||
download: "https://drive.proton.me/urls/KVGW0ZKE9C#2Y0WGGt5uHFZ",
|
||||
changelog: "Revised the redeem system, activated via channel point redeems.\nAdded OBS transformation to redeems.\nLogs changed & writes to logs folder as well."
|
||||
download: "https://drive.proton.me/urls/YH86153EWM#W6VTyaoAVHKP",
|
||||
changelog: "Reconnecting should be fixed.\nNew TTS messages when queue is empty will be played faster, up to 200 ms.\nRemoved subscriptions errors when reconnecting on Twitch\nAdded !refresh connections"
|
||||
|
||||
//changelog: "When using multiple voices (ex: brian: hello amy: world), TTS messages are now merged as a single TTS message.\nNightbot integration\nTwitch authentication changed. Need to refresh connection every 30-60 days.\nFixed raid spam, probably."
|
||||
//changelog: "Added raid spam prevention (lasts 30 seconds; works on joined chats as well).\nAdded permission check for chat messages with bits."
|
||||
//changelog: "Fixed group permissions.\nRemoved default permissions.\nSome commands may have additional permission requirements, which are more strict.\nAdded support for redeemable actions via adbreak, follow, subscription.\nMessage deletion and bans automatically remove TTS messages from queue and playing.\nAdded support to read TTS from multiple chats via !tts join.\nFixed some reconnection problems."
|
||||
//changelog: "Fixed several requests for data.\nRe-did the command system.\nAdded !skip all (!skipall still works)"
|
||||
//changelog: "Fixed initial TTS voice change.\nRandom TTS voice ensures a different voice.\nBetter connection handling."
|
||||
//changelog: "Fixed permissions.\nInternal changes."
|
||||
//changelog: "Added groups (custom + subscribers/vip/moderators/etc).\nAdded group permissions.\nFixed 7tv reconnection.\nNew website link. Old one will be on July 19, 2024.\nAdded !refresh permissions & !refresh username_filters"
|
||||
//changelog: "Fixed toggle OBS scene item visibility. Added more logs. Added version data to login."
|
||||
//changelog: "Added ability to change or toggle OBS visibility via actions.\nAdded sleep via actions.\nAdded ability to change OBS index."
|
||||
//changelog: "Fix OBS crashing the app.\nAdded '!refresh redemptions' command.\nAdded TTS voice randomizer and specifc TTS voice redemptions."
|
||||
//changelog: "Revised the redeem system, activated via channel point redeems.\nAdded OBS transformation to redeems.\nLogs changed & writes to logs folder as well."
|
||||
//changelog: "Added new command for mods: !refresh <username_filters|word_filters|default_voice> - Used to refresh data if done via website.\nAdded new command for mods: !tts <voice_name> <remove|enable|disable> - To delete, enable, or disable a specific voice."
|
||||
//changelog: "Save TTS voices set by chatters.\nAdded more options for TTS voices." 3.1
|
||||
//changelog: "Added a message when new updates are available.\nFixed 7tv renames not being applied correctly." 3.0
|
||||
|
127
app/api/settings/groups/chatters/route.ts
Normal file
127
app/api/settings/groups/chatters/route.ts
Normal file
@ -0,0 +1,127 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
import axios from "axios";
|
||||
import { env } from "process";
|
||||
import { TwitchUpdateAuthorization } from "@/lib/twitch";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user)
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
|
||||
const { searchParams } = new URL(req.url)
|
||||
const groupId = searchParams.get('groupId') as string
|
||||
const pageString = searchParams.get('page') as string
|
||||
const search = searchParams.get('search') as string
|
||||
|
||||
if (!groupId && search != 'all')
|
||||
return new NextResponse("Bad Request", { status: 400 })
|
||||
|
||||
let page = parseInt(pageString)
|
||||
if (isNaN(page) || page === undefined || page === null)
|
||||
page = 0
|
||||
|
||||
let chatters: { userId: string, groupId: string, chatterId: bigint, chatterLabel: string }[]
|
||||
|
||||
if (search != 'all')
|
||||
chatters = await db.chatterGroup.findMany({
|
||||
where: {
|
||||
userId: user.id,
|
||||
groupId
|
||||
}
|
||||
})
|
||||
else
|
||||
chatters = await db.chatterGroup.findMany({
|
||||
where: {
|
||||
userId: user.id
|
||||
}
|
||||
})
|
||||
|
||||
const paginated = search == 'all' ? chatters : chatters.slice(page * 50, (page + 1) * 50)
|
||||
if (!paginated || paginated.length == 0) {
|
||||
console.log('No users returned from db')
|
||||
return NextResponse.json([])
|
||||
}
|
||||
|
||||
const ids = chatters.map(c => c.chatterId)
|
||||
const idsString = 'id=' + ids.map(i => i.toString()).reduce((a, b) => a + '&id=' + b)
|
||||
|
||||
const auth = await TwitchUpdateAuthorization(user.id)
|
||||
if (!auth) {
|
||||
return new NextResponse("", { status: 403 })
|
||||
}
|
||||
|
||||
const users = await axios.get("https://api.twitch.tv/helix/users?" + idsString, {
|
||||
headers: {
|
||||
"Authorization": "Bearer " + auth.access_token,
|
||||
"Client-Id": env.TWITCH_BOT_CLIENT_ID
|
||||
}
|
||||
})
|
||||
|
||||
if (!users) {
|
||||
return new NextResponse("", { status: 400 })
|
||||
}
|
||||
|
||||
if (users.data.data.length == 0) {
|
||||
console.log('No users returned from twitch')
|
||||
return NextResponse.json([])
|
||||
}
|
||||
|
||||
return NextResponse.json(users.data.data.map((u: any) => ({ id: u.id, username: u.login })));
|
||||
} catch (error) {
|
||||
console.log("[GROUPS/USERS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user)
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
|
||||
const { groupId, users }: { groupId: string, users: { id: number, username: string }[] } = await req.json();
|
||||
if (!groupId || !users)
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
|
||||
const chatters = await db.chatterGroup.createMany({
|
||||
data: users.map(u => ({ userId: user.id, chatterId: u.id, groupId, chatterLabel: u.username }))
|
||||
});
|
||||
|
||||
return NextResponse.json(chatters, { status: 200 });
|
||||
} catch (error) {
|
||||
console.log("[GROUPS/USERS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user)
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
|
||||
const { searchParams } = new URL(req.url)
|
||||
const groupId = searchParams.get('groupId') as string
|
||||
const ids = searchParams.get('ids') as string
|
||||
if (!groupId || !ids)
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
|
||||
const chatters = await db.chatterGroup.deleteMany({
|
||||
where: {
|
||||
userId: user.id,
|
||||
chatterId: {
|
||||
in: ids.split(',').map(i => parseInt(i)).filter(i => !i || !isNaN(i))
|
||||
},
|
||||
groupId
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json(chatters);
|
||||
} catch (error) {
|
||||
console.log("[GROUPS/USERS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
101
app/api/settings/groups/permissions/route.ts
Normal file
101
app/api/settings/groups/permissions/route.ts
Normal file
@ -0,0 +1,101 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
import { ActionType, Prisma } from "@prisma/client";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user)
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
|
||||
const commands = await db.groupPermission.findMany({
|
||||
where: {
|
||||
userId: user.id
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json(commands.map(({userId, ...attrs}) => attrs));
|
||||
} catch (error) {
|
||||
console.log("[GROUPS/PERMISSIONS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user)
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
|
||||
const { path, allow, groupId }: { path: string, allow: boolean, groupId: string } = await req.json();
|
||||
if (!path)
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
|
||||
const permission = await db.groupPermission.create({
|
||||
data: {
|
||||
userId: user.id,
|
||||
path,
|
||||
allow,
|
||||
groupId
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json(permission, { status: 200 });
|
||||
} catch (error) {
|
||||
console.log("[GROUPS/PERMISSIONS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user)
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
|
||||
const { id, path, allow }: { id: string, path: string, allow: boolean|null } = await req.json();
|
||||
if (!id)
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
if (!path)
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
|
||||
let data: any = {}
|
||||
if (!!path)
|
||||
data = { ...data, path }
|
||||
data = { ...data, allow }
|
||||
|
||||
const permission = await db.groupPermission.update({
|
||||
where: {
|
||||
id
|
||||
},
|
||||
data: data
|
||||
});
|
||||
|
||||
return NextResponse.json(permission, { status: 200 });
|
||||
} catch (error) {
|
||||
console.log("[GROUPS/PERMISSIONS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user)
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
|
||||
const { searchParams } = new URL(req.url)
|
||||
const id = searchParams.get('id') as string
|
||||
const permission = await db.groupPermission.delete({
|
||||
where: {
|
||||
id
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json(permission);
|
||||
} catch (error) {
|
||||
console.log("[GROUPS/PERMISSIONS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
105
app/api/settings/groups/route.ts
Normal file
105
app/api/settings/groups/route.ts
Normal file
@ -0,0 +1,105 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
import { ActionType, Prisma } from "@prisma/client";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const actions = await db.group.findMany({
|
||||
where: {
|
||||
userId: user.id
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json(actions.map(({userId, ...attrs}) => attrs));
|
||||
} catch (error) {
|
||||
console.log("[GROUPS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const { name, priority }: { name: string, priority: number } = await req.json();
|
||||
if (!name)
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
|
||||
const group = await db.group.create({
|
||||
data: {
|
||||
userId: user.id,
|
||||
name: name.toLowerCase(),
|
||||
priority
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json(group, { status: 200 });
|
||||
} catch (error) {
|
||||
console.log("[GROUPS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const { id, name, priority }: { id: string, name: string, priority: number } = await req.json();
|
||||
if (!id)
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
if (!name && !priority)
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
|
||||
let data: any = {}
|
||||
if (!!name)
|
||||
data = { ...data, name: name.toLowerCase() }
|
||||
if (!!priority)
|
||||
data = { ...data, priority }
|
||||
|
||||
const group = await db.group.update({
|
||||
where: {
|
||||
id
|
||||
},
|
||||
data: data
|
||||
});
|
||||
|
||||
return NextResponse.json(group, { status: 200 });
|
||||
} catch (error) {
|
||||
console.log("[GROUPS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const { searchParams } = new URL(req.url)
|
||||
const id = searchParams.get('id') as string
|
||||
const group = await db.group.delete({
|
||||
where: {
|
||||
id
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json(group);
|
||||
} catch (error) {
|
||||
console.log("[GROUPS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
55
app/api/settings/groups/twitchchatters/route.ts
Normal file
55
app/api/settings/groups/twitchchatters/route.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
import axios from "axios";
|
||||
import { env } from "process";
|
||||
import { TwitchUpdateAuthorization } from "@/lib/twitch";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user)
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
|
||||
const { searchParams } = new URL(req.url)
|
||||
const logins = (searchParams.get('logins') as string)?.split(',').reduce((a,b) => a + ',&login=' + b)
|
||||
const ids = (searchParams.get('ids') as string)?.split(',').reduce((a,b) => a + ',&id=' + b)
|
||||
if (!logins && !ids) {
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
}
|
||||
|
||||
let suffix = ""
|
||||
if (!!logins)
|
||||
suffix += "&login=" + logins
|
||||
if (!!ids)
|
||||
suffix += "&id=" + ids
|
||||
if (!!suffix)
|
||||
suffix = "?" + suffix.substring(1)
|
||||
|
||||
const auth = await TwitchUpdateAuthorization(user.id)
|
||||
if (!auth) {
|
||||
return new NextResponse("", { status: 403 })
|
||||
}
|
||||
|
||||
console.log('TWITCH URL:', 'https://api.twitch.tv/helix/users' + suffix)
|
||||
console.log("AUTH", auth)
|
||||
const users = await axios.get("https://api.twitch.tv/helix/users" + suffix, {
|
||||
headers: {
|
||||
"Authorization": "Bearer " + auth.access_token,
|
||||
"Client-Id": env.TWITCH_BOT_CLIENT_ID
|
||||
}
|
||||
})
|
||||
|
||||
if (!users || !users.data) {
|
||||
return new NextResponse("", { status: 400 })
|
||||
}
|
||||
|
||||
if (users.data.data.length == 0) {
|
||||
return NextResponse.json([])
|
||||
}
|
||||
|
||||
return NextResponse.json(users.data.data.map((u: any) => ({ id: u.id, username: u.login })));
|
||||
} catch (error) {
|
||||
console.log("[GROUPS/USERS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
40
app/api/settings/groups/users/route.ts
Normal file
40
app/api/settings/groups/users/route.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
import axios from "axios";
|
||||
import { env } from "process";
|
||||
import { TwitchUpdateAuthorization } from "@/lib/twitch";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user)
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
|
||||
const { searchParams } = new URL(req.url)
|
||||
const groupId = searchParams.get('groupId') as string
|
||||
|
||||
let chatters: { userId: string, groupId: string, chatterId: bigint, chatterLabel: string }[]
|
||||
|
||||
if (!!groupId)
|
||||
chatters = await db.chatterGroup.findMany({
|
||||
where: {
|
||||
userId: user.id,
|
||||
groupId
|
||||
}
|
||||
})
|
||||
else
|
||||
chatters = await db.chatterGroup.findMany({
|
||||
where: {
|
||||
userId: user.id
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json(chatters.map(u => ({ ...u, chatterId: Number(u.chatterId) }))
|
||||
.map(({userId, chatterLabel, ...attrs}) => attrs))
|
||||
|
||||
} catch (error) {
|
||||
console.log("[GROUPS/USERS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
import { ActionType, Prisma } from "@prisma/client";
|
||||
import { JsonSerializer } from "typescript-json-serializer";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
@ -17,111 +16,104 @@ export async function GET(req: Request) {
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json(actions.map(({userId, ...attrs}) => attrs));
|
||||
return NextResponse.json(actions.map(({ userId, ...attrs }) => attrs));
|
||||
} catch (error) {
|
||||
console.log("[REDEMPTIONS/ACTIONS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
async function common(req: Request, action: (id: string, name: string, type: ActionType, data: any) => void) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const { name, type, scene_name, scene_item_name, rotation, position_x, position_y, file_path, file_content, tts_voice, obs_visible, obs_index, sleep, oauth_name, oauth_type }:
|
||||
{
|
||||
name: string, type: ActionType, scene_name: string, scene_item_name: string, rotation: string, position_x: string, position_y: string, file_path: string, file_content: string, tts_voice: string, obs_visible: boolean, obs_index: number, sleep: number,
|
||||
oauth_name: string, oauth_type: string
|
||||
} = await req.json();
|
||||
if (!name && !type)
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
if (type == ActionType.OBS_TRANSFORM && (!scene_name || !scene_item_name || !rotation && !position_x && !position_y))
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
if ((type == ActionType.WRITE_TO_FILE || type == ActionType.APPEND_TO_FILE) && (!file_path || !file_content))
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
if (type == ActionType.AUDIO_FILE && !file_path)
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
if ([ActionType.OAUTH, ActionType.NIGHTBOT_PLAY, ActionType.NIGHTBOT_PAUSE, ActionType.NIGHTBOT_SKIP, ActionType.NIGHTBOT_CLEAR_PLAYLIST, ActionType.NIGHTBOT_CLEAR_QUEUE, ActionType.TWITCH_OAUTH].some(t => t == type) && (!oauth_name || !oauth_type))
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
|
||||
let data: any = {}
|
||||
if (type == ActionType.WRITE_TO_FILE || type == ActionType.APPEND_TO_FILE) {
|
||||
data = { file_path, file_content }
|
||||
} else if (type == ActionType.OBS_TRANSFORM) {
|
||||
data = { scene_name, scene_item_name }
|
||||
if (!!rotation)
|
||||
data = { rotation, ...data }
|
||||
if (!!position_x)
|
||||
data = { position_x, ...data }
|
||||
if (!!position_y)
|
||||
data = { position_y, ...data }
|
||||
} else if (type == ActionType.AUDIO_FILE) {
|
||||
data = { file_path }
|
||||
} else if (type == ActionType.SPECIFIC_TTS_VOICE) {
|
||||
data = { tts_voice }
|
||||
} else if (type == ActionType.TOGGLE_OBS_VISIBILITY) {
|
||||
data = { scene_name, scene_item_name }
|
||||
} else if (type == ActionType.SPECIFIC_OBS_VISIBILITY) {
|
||||
data = { scene_name, scene_item_name, obs_visible }
|
||||
} else if (type == ActionType.SPECIFIC_OBS_INDEX) {
|
||||
data = { scene_name, scene_item_name, obs_index }
|
||||
} else if (type == ActionType.SLEEP) {
|
||||
data = { sleep }
|
||||
} else if ([ActionType.OAUTH, ActionType.NIGHTBOT_PLAY, ActionType.NIGHTBOT_PAUSE, ActionType.NIGHTBOT_SKIP, ActionType.NIGHTBOT_CLEAR_PLAYLIST, ActionType.NIGHTBOT_CLEAR_QUEUE, ActionType.TWITCH_OAUTH].some(t => t == type)) {
|
||||
data = {
|
||||
oauth_name,
|
||||
oauth_type
|
||||
}
|
||||
}
|
||||
|
||||
action(user.id, name, type, data)
|
||||
|
||||
return new NextResponse("", { status: 200 });
|
||||
} catch (error: any) {
|
||||
//console.log("[REDEMPTIONS/ACTIONS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const { name, type, scene_name, scene_item_name, rotation, position_x, position_y, file_path, file_content }: { name: string, type: ActionType, scene_name: string, scene_item_name: string, rotation: string, position_x: string, position_y: string, file_path: string, file_content: string } = await req.json();
|
||||
if (!name && !type)
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
if (type == ActionType.OBS_TRANSFORM && (!scene_name || !scene_item_name || !rotation && !position_x && !position_y))
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
if ((type == ActionType.WRITE_TO_FILE || type == ActionType.APPEND_TO_FILE) && (!file_path || !file_content))
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
if (type == ActionType.AUDIO_FILE && !file_path)
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
|
||||
let data:any = { }
|
||||
if (type == ActionType.WRITE_TO_FILE || type == ActionType.APPEND_TO_FILE) {
|
||||
data = { file_path, file_content, ...data }
|
||||
} else if (type == ActionType.OBS_TRANSFORM) {
|
||||
data = { scene_name, scene_item_name, ...data }
|
||||
if (!!rotation)
|
||||
data = { rotation, ...data }
|
||||
if (!!position_x)
|
||||
data = { position_x, ...data }
|
||||
if (!!position_y)
|
||||
data = { position_y, ...data }
|
||||
} else if (type == ActionType.AUDIO_FILE) {
|
||||
data = { file_path, ...data }
|
||||
}
|
||||
|
||||
return common(req, async (id, name, type, data) => {
|
||||
await db.action.create({
|
||||
data: {
|
||||
userId: user.id,
|
||||
userId: id,
|
||||
name,
|
||||
type,
|
||||
data: data as Prisma.JsonObject
|
||||
}
|
||||
});
|
||||
|
||||
return new NextResponse("", { status: 200 });
|
||||
} catch (error) {
|
||||
console.log("[REDEMPTIONS/ACTIONS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function PUT(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const { name, type, scene_name, scene_item_name, rotation, position_x, position_y, file_path, file_content }: { name: string, type: ActionType, scene_name: string, scene_item_name: string, rotation: string, position_x: string, position_y: string, file_path: string, file_content: string } = await req.json();
|
||||
if (!name && !type)
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
if (type == ActionType.OBS_TRANSFORM && (!scene_name || !scene_item_name || !rotation && !position_x && !position_y))
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
if ((type == ActionType.WRITE_TO_FILE || type == ActionType.APPEND_TO_FILE) && (!file_path || !file_content))
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
if (type == ActionType.AUDIO_FILE && !file_path)
|
||||
return new NextResponse("Bad Request", { status: 400 });
|
||||
|
||||
let data:any = { }
|
||||
if (type == ActionType.WRITE_TO_FILE || type == ActionType.APPEND_TO_FILE) {
|
||||
data = { file_path, file_content, ...data }
|
||||
} else if (type == ActionType.OBS_TRANSFORM) {
|
||||
data = { scene_name, scene_item_name, ...data }
|
||||
if (!!rotation)
|
||||
data = { rotation, ...data }
|
||||
if (!!position_x)
|
||||
data = { position_x, ...data }
|
||||
if (!!position_y)
|
||||
data = { position_y, ...data }
|
||||
} else if (type == ActionType.AUDIO_FILE) {
|
||||
data = { file_path, ...data }
|
||||
}
|
||||
|
||||
return common(req, async (id, name, type, data) => {
|
||||
await db.action.update({
|
||||
where: {
|
||||
userId_name: {
|
||||
userId: user.id,
|
||||
userId: id,
|
||||
name
|
||||
}
|
||||
},
|
||||
data: {
|
||||
name,
|
||||
type,
|
||||
data: data as Prisma.JsonObject
|
||||
}
|
||||
});
|
||||
|
||||
return new NextResponse("", { status: 200 });
|
||||
} catch (error) {
|
||||
console.log("[REDEMPTIONS/ACTIONS]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export async function DELETE(req: Request) {
|
||||
|
@ -4,24 +4,20 @@ import { NextResponse } from "next/server";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
console.log("ABC 1")
|
||||
const user = await fetchUserWithImpersonation(req);
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
console.log("ABC 2")
|
||||
|
||||
const api = await db.twitchConnection.findFirst({
|
||||
where: {
|
||||
userId: user.id
|
||||
}
|
||||
})
|
||||
console.log("ABC 3")
|
||||
if (!api) {
|
||||
return new NextResponse("Forbidden", { status: 403 });
|
||||
}
|
||||
|
||||
console.log("ABC 4")
|
||||
const data = {
|
||||
client_id: process.env.TWITCH_BOT_CLIENT_ID,
|
||||
client_secret: process.env.TWITCH_BOT_CLIENT_SECRET,
|
||||
@ -29,7 +25,6 @@ export async function GET(req: Request) {
|
||||
refresh_token: api.refreshToken,
|
||||
broadcaster_id: api.broadcasterId
|
||||
}
|
||||
console.log("ABC 5", data)
|
||||
return NextResponse.json(data);
|
||||
} catch (error) {
|
||||
console.log("[TOKENS/GET]", error);
|
||||
|
Reference in New Issue
Block a user