Skip to content

Commit 73e6f89

Browse files
committed
[Twitch] Add caching to endpoints: avatar, game, status/title and viewercount
Extend caching of endpoint 'subpoints' from 60 seconds to 120 seconds
1 parent e829e5b commit 73e6f89

2 files changed

Lines changed: 60 additions & 93 deletions

File tree

app/Http/Controllers/TwitchController.php

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use App\Exceptions\TwitchFormatException;
66
use Illuminate\Http\Request;
77

8-
use App\Http\Requests;
98
use App\Http\Controllers\Controller;
109

1110
use App\User;
@@ -18,13 +17,8 @@
1817
use App\Repositories\TwitchEmotesApiRepository;
1918

2019
use Carbon\Carbon;
21-
use Carbon\CarbonInterval;
2220
use DateTimeZone;
2321

24-
use Symfony\Component\DomCrawler\Crawler;
25-
use Symfony\Component\CssSelector;
26-
use GuzzleHttp\Client;
27-
2822
use Crypt;
2923
use Illuminate\Contracts\Encryption\DecryptException;
3024

@@ -248,6 +242,14 @@ public function avatar(Request $request, $user = null)
248242
return Helper::text(__('generic.username_required'));
249243
}
250244

245+
/**
246+
* Return avatar URL from cache if it exists.
247+
*/
248+
$cacheKey = sprintf('twitch_avatar_%s', md5($user));
249+
if (Cache::has($cacheKey)) {
250+
return Helper::text(Cache::get($cacheKey));
251+
}
252+
251253
$id = $request->input('id', 'false');
252254
try {
253255
$data = $id === 'true' ? $this->api->userById($user) : $this->api->userByUsername($user);
@@ -268,11 +270,13 @@ public function avatar(Request $request, $user = null)
268270
]));
269271
}
270272

271-
if (empty($data['avatar'])) {
272-
return Helper::text($this->defaultAvatar);
273-
}
273+
// Fallback to the default avatar if necessary.
274+
$avatar = $data['avatar'] ?? $this->defaultAvatar;
275+
276+
// Cache the avatar URL for 5 minutes.
277+
Cache::put($cacheKey, $avatar, config('twitch.cache.avatar'));
274278

275-
return Helper::text($data['avatar']);
279+
return Helper::text($avatar);
276280
}
277281

278282
/**
@@ -851,6 +855,18 @@ public function gameOrStatus(Request $request, $route, $channel = null)
851855
}
852856
}
853857

858+
/**
859+
* Check cache for game/status.
860+
*/
861+
$cacheId = md5($channel);
862+
$cacheGame = sprintf('twitch_game_%s', $cacheId);
863+
$cacheStatus = sprintf('twitch_status_%s', $cacheId);
864+
865+
$cacheKey = $route === 'game' ? $cacheGame : $cacheStatus;
866+
if (Cache::has($cacheKey)) {
867+
return Helper::text(Cache::get($cacheKey));
868+
}
869+
854870
try {
855871
$getChannel = $this->api->channelById($channel);
856872
} catch (TwitchApiException $ex) {
@@ -859,11 +875,20 @@ public function gameOrStatus(Request $request, $route, $channel = null)
859875
return Helper::text($ex->getMessage());
860876
}
861877

878+
$game = $getChannel['game']['name'];
879+
$status = $getChannel['title'];
880+
881+
/**
882+
* We can cache both values as it's from the same request anyways.
883+
*/
884+
Cache::put($cacheGame, $game, config('twitch.cache.game'));
885+
Cache::put($cacheStatus, $status, config('twitch.cache.status'));
886+
862887
if ($route === 'game') {
863-
return Helper::text($getChannel['game']['name'] ?: '');
888+
return Helper::text($game ?: '');
864889
}
865890

866-
return Helper::text($getChannel['title']);
891+
return Helper::text($status);
867892
}
868893

869894
/**
@@ -1811,7 +1836,7 @@ public function subpoints(Request $request, $channel = null)
18111836
* Cache subpoints for one minute,
18121837
* to prevent excessive requests to the Twitch API.
18131838
*/
1814-
Cache::put($cacheKey, $subpoints, 60);
1839+
Cache::put($cacheKey, $subpoints, config('twitch.cache.subpoints'));
18151840

18161841
/**
18171842
* Subtract user-supplied value.
@@ -2190,6 +2215,14 @@ public function viewercount(Request $request, $channel = null)
21902215
}
21912216
}
21922217

2218+
/**
2219+
* Load viewercount from cache to prevent unneccessary API request.
2220+
*/
2221+
$cacheKey = sprintf('twitch_viewercount_%s', md5($channel));
2222+
if (Cache::has($cacheKey)) {
2223+
return Helper::text(Cache::get($cacheKey));
2224+
}
2225+
21932226
$stream = $this->twitchApi->streams($channel, $this->version);
21942227

21952228
if (!empty($stream['status'])) {
@@ -2202,6 +2235,8 @@ public function viewercount(Request $request, $channel = null)
22022235
}
22032236

22042237
$viewers = $stream['stream']['viewers'];
2238+
// Add viewercount to the cache and cache it for 60 seconds.
2239+
Cache::put($cacheKey, $viewers, config('twitch.cache.viewercount'));
22052240
return Helper::text($viewers);
22062241
}
22072242

config/twitch.php

Lines changed: 12 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,17 @@
11
<?php
22
return [
3-
'emoteslots' => [
4-
0 => 2,
5-
25 => 4,
6-
50 => 6,
7-
100 => 8,
8-
250 => 10,
9-
500 => 15,
10-
1000 => 20,
11-
2000 => 25,
12-
3000 => 30,
13-
4000 => 35,
14-
5000 => 40,
15-
6000 => 45,
16-
7000 => 50
3+
/**
4+
* $endpoint => $seconds
5+
*
6+
* $seconds = how long a value per channel / user should be cached.
7+
*/
8+
'cache' => [
9+
'avatar' => 300,
10+
'game' => 60,
11+
// Stream title/status
12+
'status' => 60,
13+
'subpoints' => 120,
14+
'viewercount' => 60,
1715
],
18-
'help' => [
19-
'articles' => [
20-
'About Site Suspensions, DMCA Suspensions, and Chat Bans' => 1727973,
21-
'Adding a Game and Box Art to the Directory' => 2348988,
22-
'Authy FAQ' => 2186821,
23-
'Channel Banned Words' => 2100263,
24-
'Chat Commands' => 659095,
25-
'Chat Replay FAQ' => 2337148,
26-
'Community Guidelines' => 983016,
27-
'Creative FAQ' => 2176641,
28-
'Guide to Broadcast Health and Using Twitch Inspector' => 2420572,
29-
'Guide to Cheering (Bits)' => 2449458,
30-
'Guide to Closed Captions' => 2564215,
31-
'Guide to Custom Resub Messages' => 2457351,
32-
'Guide to Earning Revenue from Game Sales' => 2582870,
33-
'Guide to Twitch Crates' => 2772801,
34-
'How to Buy Games on Twitch' => 2771293,
35-
'How to Claim In-Game Content' => 2773669,
36-
'How to Edit Info Panels' => 2416760,
37-
'How to File a User Report' => 725568,
38-
'How to Handle Viewbots/Followbots' => 2435640,
39-
'How to Link Your Amazon Account' => 2574978,
40-
'How to Manage Harassment in Chat' => 2329145,
41-
'How to Redeem Coupon Codes' => 2392092,
42-
'How to Use AutoMod' => 2662186,
43-
'How to use Channel Feed' => 2377877,
44-
'How to Use Clips' => 2442508,
45-
'How to use the Friends Feature' => 2418761,
46-
'How to Use Host Mode' => 2508329,
47-
'How to use Pulse' => 2752590,
48-
'How To Use VOD Thumbnails' => 2218412,
49-
'HTML5 Video Player Beta' => 2477288,
50-
'List of Prohibited/Banned Games' => 1992676,
51-
'Missed Email Responses' => 1626286,
52-
'Moderation Team Building FAQ' => 1360598,
53-
'Partner Program Overview' => 735069,
54-
'Partner Emoticon and Badge Guide' => 2348985,
55-
'Partner Help and Contact Information' => 735178,
56-
'Partner Payment FAQ' => 735169,
57-
'Partner Payout FAQ' => 735169,
58-
'Partner Revenue Guide' => 2347894,
59-
'Partner Settings Guide' => 2401004,
60-
'Purchase Support FAQ' => 2341636,
61-
'Social Eating FAQ' => 2483343,
62-
'Subscription Program FAQ' => 735176,
63-
'Terms of Service (ToS)' => 735191,
64-
'Tips for Applying to the Partner Program' => 735127,
65-
'Twitch Chat Badges Guide' => 659115,
66-
'Twitch IRC' => 1302780,
67-
'Twitch IRL FAQ' => 2672652,
68-
'Twitch Music FAQ' => 1824967,
69-
'Twitch Prime Guide' => 2572060,
70-
'Twitch Rules of Conduct (RoC)' => 983016,
71-
'Twitch Turbo' => 973896,
72-
'Twitch Twitter "@TwitchSupport" FAQ' => 1210307,
73-
'Two Factor Authentication (2FA) with Authy' => 2186271,
74-
'Username Rename (Name Changes) and Recycling Policies' => 1015624,
75-
'Whispers FAQ' => 2215236,
76-
// Sorted at the bottom for lower priority
77-
'Android Subscriptions FAQ' => 2297883,
78-
'Creative Commissions' => 2337107,
79-
'How to File a Whisper Report' => 2329782,
80-
'How to Use Twitch Prime Subscriptions (Free)' => 2574674,
81-
'Twitch Prime Game Code Redemption and Installation' => 2574721
82-
]
83-
]
8416
];
8517
?>

0 commit comments

Comments
 (0)