Skip to content

Commit 27bcc1f

Browse files
committed
Fixed twitch data collection
1 parent 979576b commit 27bcc1f

File tree

1 file changed

+104
-69
lines changed

1 file changed

+104
-69
lines changed

laravel/app/Http/Controllers/Api/Twitch/User/Controller.php

Lines changed: 104 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -4,107 +4,142 @@
44

55
use Illuminate\Http\Request;
66
use Illuminate\Support\Facades\Http;
7+
use Illuminate\Support\Facades\Cache;
78
use Illuminate\Http\JsonResponse;
89

910
class Controller extends \App\Http\Controllers\Controller
1011
{
12+
private const TWITCH_GQL_URL = 'https://gql.twitch.tv/gql';
13+
private const TWITCH_CLIENT_ID = 'kimne78kx3ncx6brgo4mv6wki5h1ko';
14+
1115
public function __invoke(Request $request, string $username): JsonResponse
1216
{
1317
try {
14-
$tokenResponse = Http::asForm()->post('https://id.twitch.tv/oauth2/token', [
15-
'client_id' => config('services.twitch.client_id'),
16-
'client_secret' => config('services.twitch.client_secret'),
17-
'grant_type' => 'client_credentials',
18+
// Clean the username - remove trailing slashes and spaces
19+
$username = trim($username, "/ \t\n\r\0\x0B");
20+
21+
// Query for full user data following the documented structure
22+
$query = <<<GQL
23+
query {
24+
user(login: "{$username}") {
25+
id
26+
login
27+
displayName
28+
description
29+
createdAt
30+
roles {
31+
isPartner
32+
isAffiliate
33+
}
34+
profileImageURL(width: 300)
35+
offlineImageURL
36+
lastBroadcast {
37+
title
38+
game {
39+
name
40+
}
41+
}
42+
stream {
43+
id
44+
title
45+
type
46+
viewersCount
47+
createdAt
48+
game {
49+
name
50+
}
51+
}
52+
}
53+
}
54+
GQL;
55+
56+
// Make GraphQL request
57+
$response = Http::withHeaders([
58+
'Client-ID' => self::TWITCH_CLIENT_ID,
59+
'Content-Type' => 'application/json',
60+
])->post(self::TWITCH_GQL_URL, [
61+
'query' => $query,
62+
'variables' => (object)[]
1863
]);
1964

20-
if (!$tokenResponse->successful()) {
65+
if (!$response->successful()) {
2166
return response()->json([
22-
'error' => 'Failed to authenticate with Twitch',
23-
'details' => $tokenResponse->json(),
67+
'error' => 'Failed to fetch Twitch data',
68+
'details' => $response->json()
2469
], 500);
2570
}
2671

27-
$accessToken = $tokenResponse->json()['access_token'];
28-
$headers = [
29-
'Client-ID' => config('services.twitch.client_id'),
30-
'Authorization' => 'Bearer ' . $accessToken,
31-
];
32-
33-
// Get user data first
34-
$userResponse = Http::withHeaders($headers)
35-
->get("https://api.twitch.tv/helix/users", [
36-
'login' => $username,
37-
]);
72+
$data = $response->json();
3873

39-
if (!$userResponse->successful()) {
74+
// Validate response structure
75+
if (!isset($data['data'])) {
4076
return response()->json([
41-
'error' => 'Failed to fetch user data',
42-
'details' => $userResponse->json(),
77+
'error' => 'Invalid response format',
78+
'details' => $data
4379
], 500);
4480
}
4581

46-
$userData = $userResponse->json();
47-
48-
if (empty($userData['data'])) {
82+
// Check if user exists
83+
if (empty($data['data']['user'])) {
4984
return response()->json([
50-
'error' => 'User not found',
85+
'error' => 'User not found'
5186
], 404);
5287
}
5388

54-
$user = $userData['data'][0];
55-
56-
// Get stream data
57-
$streamResponse = Http::withHeaders($headers)
58-
->get("https://api.twitch.tv/helix/streams", [
59-
'user_id' => $user['id'],
60-
]);
89+
$user = $data['data']['user'];
6190

62-
if (!$streamResponse->successful()) {
91+
// Fall back to basic stream status if we hit any issues
92+
try {
6393
return response()->json([
64-
'error' => 'Failed to fetch stream data',
65-
'details' => $streamResponse->json(),
66-
], 500);
67-
}
68-
69-
$streamData = $streamResponse->json();
70-
71-
// Get channel information
72-
$channelResponse = Http::withHeaders($headers)
73-
->get("https://api.twitch.tv/helix/channels", [
74-
'broadcaster_id' => $user['id'],
94+
'user' => [
95+
'id' => $user['id'],
96+
'login' => $user['login'],
97+
'display_name' => $user['displayName'],
98+
'type' => $user['roles']['isPartner'] ? 'partner' :
99+
($user['roles']['isAffiliate'] ? 'affiliate' : ''),
100+
'description' => $user['description'],
101+
'profile_image_url' => $user['profileImageURL'],
102+
'offline_image_url' => $user['offlineImageURL'],
103+
'created_at' => $user['createdAt']
104+
],
105+
'channel' => [
106+
'broadcaster_language' => 'en',
107+
'game_name' => $user['lastBroadcast']['game']['name'] ?? null,
108+
'title' => $user['lastBroadcast']['title'] ?? null
109+
],
110+
'stream' => [
111+
'is_live' => !empty($user['stream']),
112+
'data' => $user['stream'] ? [
113+
'id' => $user['stream']['id'],
114+
'game_name' => $user['stream']['game']['name'],
115+
'title' => $user['stream']['title'],
116+
'viewer_count' => $user['stream']['viewersCount'],
117+
'started_at' => $user['stream']['createdAt'],
118+
'thumbnail_url' => sprintf(
119+
'https://static-cdn.jtvnw.net/previews-ttv/live_user_%s-{width}x{height}.jpg',
120+
strtolower($user['login'])
121+
)
122+
] : null
123+
]
75124
]);
76-
77-
if (!$channelResponse->successful()) {
125+
} catch (\Exception $e) {
126+
// If we hit any issues parsing the full response, just return stream status
78127
return response()->json([
79-
'error' => 'Failed to fetch channel data',
80-
'details' => $channelResponse->json(),
81-
], 500);
128+
'is_live' => !empty($user['stream']),
129+
'stream_id' => $user['stream']['id'] ?? null
130+
]);
82131
}
83132

84-
$channelData = $channelResponse->json();
85-
86-
return response()->json([
87-
'user' => [
88-
'id' => $user['id'],
89-
'login' => $user['login'],
90-
'display_name' => $user['display_name'],
91-
'type' => $user['type'],
92-
'broadcaster_type' => $user['broadcaster_type'],
93-
'description' => $user['description'],
94-
'profile_image_url' => $user['profile_image_url'],
95-
'offline_image_url' => $user['offline_image_url'],
96-
'created_at' => $user['created_at'],
97-
],
98-
'channel' => $channelData['data'][0] ?? null,
99-
'stream' => [
100-
'is_live' => !empty($streamData['data']),
101-
'data' => $streamData['data'][0] ?? null,
102-
],
103-
]);
104133
} catch (\Exception $e) {
134+
logger()->error('Twitch GraphQL API Error', [
135+
'message' => $e->getMessage(),
136+
'trace' => $e->getTraceAsString()
137+
]);
138+
105139
return response()->json([
106140
'error' => 'An error occurred',
107141
'message' => $e->getMessage(),
142+
'trace' => $e->getTraceAsString()
108143
], 500);
109144
}
110145
}

0 commit comments

Comments
 (0)