-
Notifications
You must be signed in to change notification settings - Fork 1
/
RSHighscores.body.php
192 lines (159 loc) · 5.29 KB
/
RSHighscores.body.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
<?php
/**
* <doc>
*/
class RSHiscores {
public static $ch = NULL;
public static $cache = array();
public static $times = 0;
/**
* Setup parser function
*
* @param $parser Parser
* @return bool
*/
public static function register( &$parser ) {
$parser->setFunctionHook( 'hs', 'RSHiscores::renderHiscores' );
return true;
}
/**
* Retrieve the raw hiscores data from RuneScape.
*
* @param string $hs Which hiscores API to retrieve from.
* @param string $player Player's display name.
* @return string Raw hiscores data
*/
private static function retrieveHiscores( $hs, $player ) {
global $wgHTTPTimeout;
if ( $hs == 'rs3' ) {
$url = 'http://services.runescape.com/m=hiscore/index_lite.ws?player=';
} elseif ( $hs == 'osrs' ) {
$url = 'http://services.runescape.com/m=hiscore_oldschool/index_lite.ws?player=';
} else {
// Unknown or unsupported hiscores API.
return 'H';
}
// Setup the cURL handler if not previously initialised.
if ( self::$ch == NULL ) {
self::$ch = curl_init();
curl_setopt( self::$ch, CURLOPT_TIMEOUT, $wgHTTPTimeout );
curl_setopt( self::$ch, CURLOPT_RETURNTRANSFER, TRUE );
}
curl_setopt( self::$ch, CURLOPT_URL, $url . urlencode( $player ) );
if ( $data = curl_exec( self::$ch ) ) {
$status = curl_getinfo( self::$ch, CURLINFO_HTTP_CODE );
if ( $status == 200 ) {
return $data;
} elseif ( $status == 404 ) {
// The player could not be found.
return 'B';
}
// An unexpected HTTP status code was returned, so report it.
return 'D' . $status;
}
// An unexpected curl error occurred, so report it.
$errno = curl_errno( self::$ch );
if( $errno ) {
return 'C' . $errno;
}
// Should be impossible, but odd things happen, so handle it.
return 'C';
}
/**
* Parse the hiscores data.
*
* @param string $data
* @param int $skill Index representing the requested skill.
* @param int $type Index representing the requested type of data for the given skill.
* @return string Requested portion of the hiscores data.
*/
private static function parseHiscores( $data, $skill, $type ) {
// Check to see if an error has already occurred.
// If so, return the error now, otherwise the wrong error will be
// returned. Some errors have int statuses, so only check first char.
if ( ctype_alpha( $data{0} ) ) {
return $data;
}
$data = explode( "\n", $data, $skill + 2 );
if ( !array_key_exists( $skill, $data ) ) {
// The skill does not exist.
return 'F';
}
$data = explode( ',', $data[$skill], $type + 2 );
if ( !array_key_exists( $type, $data ) ) {
// The type does not exist.
return 'G';
}
return $data[$type];
}
/**
* Attempt to lookup hiscore data in the cache, or looks it up in the API if not found.
*
* @param string $hs Which hiscores API to use.
* @param string $player Player's display name. Can not be empty.
* @param int $skill Index representing the requested skill. Leave as -1 for requesting the raw data.
* @param int $type Index representing the requested type of data for the given skill.
* @return string
*/
private static function getHiscores( $hs, $player, $skill, $type ) {
global $wgRSLimit;
if ( $hs != 'rs3' && $hs != 'osrs' ) {
// Unknown or unsupported hiscores API.
return 'H';
}
$player = trim( $player );
if( $player == '' ) {
// No name was entered.
return 'A';
} elseif ( array_key_exists( $hs, self::$cache ) && array_key_exists( $player, self::$cache[$hs] ) ) {
// Get the hiscores data from the cache.
$data = self::$cache[$hs][$player];
} elseif ( self::$times < $wgRSLimit || $wgRSLimit == 0 ) {
// Update the name limit counter.
self::$times++;
// Get the hiscores data from the site.
$data = self::retrieveHiscores( $hs, $player );
// Escape the result as it's from an external API.
$data = htmlspecialchars( $data, ENT_QUOTES );
// Add the hiscores data to the cache.
self::$cache[$hs][$player] = $data;
} else {
// The name limit set by $wgRSLimit was reached.
return 'E';
}
// Finally, return the raw string for use in JS calcs,
// or if requested, parse the hiscores data.
if ( $skill < 0 ) {
return $data;
} else {
return self::parseHiscores( $data, $skill, $type );
}
}
/**
* Gets requested hiscore data and handles any returned error codes.
*
* @param $parser Parser
* @param string $hs Which hiscores API to use.
* @param string $player Player's display name. Can not be empty.
* @param int $skill Index representing the requested skill. Leave as -1 for requesting the raw data.
* @param int $type Index representing the requested type of data for the given skill.
* @return string
*/
public static function renderHiscores( &$parser, $hs = 'rs3', $player = '', $skill = -1, $type = 1 ) {
$ret = self::getHiscores( $hs, $player, $skill, $type );
$first = $ret{0};
if ( ctype_alpha( $first ) ) {
$parser->addTrackingCategory( 'rshiscores-error-category' );
$msg = wfMessage( 'rshiscores-error-' . $first );
// Pass any error codes to the returned message as parameters.
if ( strlen( $ret ) > 1 ) {
$msg = $msg->params( substr( $ret, 1 ) )->parse();
} else {
$msg = $msg->parse();
}
// Return an error format compatible with #iferror.
return '<span class="error">' . $msg . '</span>';
}
return $ret;
}
}