我用PHP完全制作了一个PHP,希望对代码进行回顾,并希望就我应该添加的内容提出建议。这是GitHub回购。
除了需要一个通用代码审查之外,我还有几个有指导意义的问题:
我存储设置的方法是个好主意,我不想使用sql,因为我希望这是非常可移植的。
我的面板很安全吗?我对它没有太多的验证,它应该托管在一个具有类似apache身份验证之类内容的webdir中。
我对代码做了一些相当大的更改,如果没有配置文件,面板也会自动生成配置文件。它在一些测试中运行得很好,但是我不知道实践有多糟糕,因为它是一个由php和html混合而成的负载,并且非常感谢对它的反馈。
我也会在这里张贴所有的部分:
bot.php:
attachments;
$avatar = $callback->avatar_url;
$name = $callback->name;
$type = $callback->sender_type;
$text = $callback->text;
$userid = $callback->user_id;
$admins = read_array('admins.php');
$ignored = read_array('ignore.php');
$settings = read_array('settings.php');
//If logging is enables in the config, this logs the chat to specified file and directory
logging($userid, $name, $text);
//Only handles messages from users to prevent infinite loops
if ($type == 'user' && !in_array($userid, $ignored) && $text[0] != '/') {
//Basic response is a simple response to a found phrase
basic_response($text, $name, $userid);
//If the Weather Underground API token and location are set and weather has been enabled, this will return a forecast if someone says "weather"
if ($settings['weather']) {
weather_response($text);
}
//If anyone says "bitcoin" and the bitcoin setting is enabled, this will return the price in USD
if ($settings['bitcoin']) {
btc_response($text);
}
//If anyone says "ethereum" and the ethereum setting is enabled, this will return the price in USD and BTC
if ($settings['ethereum']) {
eth_response($text);
}
//If anyone says "litecoin" and the litecoin setting is enabled, this will return the price in USD and BTC
if ($settings['litecoin']) {
ltc_response($text);
}
if ($settings['lights']) {
blink($ip, $pins, "50", "20");
}
}
if (in_array($userid, $admins) && $type == 'user' && $text[0] == '/') {
$command = parse_cmd($text);
if ($text == '/help') {
disp_help();
} elseif ($text == '/ignorelist') {
list_ignored();
} elseif (strpos($text, '/ignore') !== FALSE && isset($command[0])) {
send(add_ignore($command[0]));
} elseif (strpos($text, '/unignore') !== FALSE && isset($command[0])) {
send(del_ignore($command[0]));
} elseif ($text == '/responses') {
list_responses();
} elseif (strpos($text, '/addresponse') !== FALSE && isset($command[0]) && isset($command[1])) {
send(add_response($command[0], $command[1]));
} elseif (strpos($text, '/delresponse') !== FALSE && isset($command[0])) {
send(del_response($command[0]));
} elseif ($text == '/admins') {
list_admins();
} elseif (strpos($text, '/getuserid') !== FALSE && isset($command[0])) {
send("$command[0]'s User ID is " . get_user_id($command[0]));
} elseif (strpos($text, '/addadmin') !== FALSE && isset($command[0])) {
send(add_admin($command[0]));
} elseif (strpos($text, '/deladmin') !== FALSE && isset($command[0])) {
send(del_admin($command[0]));
} elseif (strpos($text, '/enable') !== FALSE && isset($command[0])) {
send(enable_custom($command[0]));
} elseif (strpos($text, '/disable') !== FALSE && isset($command[0])) {
send(disable_custom($command[0]));
} elseif ($text == '/status') {
list_status();
} elseif ($text == '/lightson') {
lights_on($ip, $pins);
} elseif ($text == '/lightsoff') {
lights_off($ip, $pins);
} else {
send('Invalid Command');
}
}functions.php:
current_observation->feelslike_string;
$weather = $rawweather->current_observation->weather;
$icon = $rawweather->current_observation->icon_url;
$forecast = "The weather is $weather with a temperature of $temperature";
send_img($forecast, $icon);
} else {
send('WUnderground token and location are not set');
}
}
}
function btc_response($text) {
if (stripos($text, 'bitcoin') !== FALSE) {
$pricedata = json_decode(file_get_contents("https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD"));
$usdprice = $pricedata->USD;
$message = "Bitcoin is worth \$usdprice";
$btclogo = 'https://files.coinmarketcap.com/static/img/coins/32x32/bitcoin.png';
send_img($message, $btclogo);
}
}
function eth_response($text) {
if (stripos($text, 'ethereum') !== FALSE) {
$pricedata = json_decode(file_get_contents("https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=BTC,USD"));
$usdprice = $pricedata->USD;
$btcprice = $pricedata->BTC;
$message = "Ethereum is worth \$usdprice and $btcprice Bitcoin";
$ethlogo = 'https://files.coinmarketcap.com/static/img/coins/32x32/ethereum.png';
send_img($message, $ethlogo);
}
}
function ltc_response($text) {
if (stripos($text, 'litecoin') !== FALSE) {
$pricedata = json_decode(file_get_contents("https://min-api.cryptocompare.com/data/price?fsym=LTC&tsyms=BTC,USD"));
$usdprice = $pricedata->USD;
$btcprice = $pricedata->BTC;
$message = "Litecoin is worth \$usdprice and $btcprice Bitcoin";
$ltclogo = 'https://files.coinmarketcap.com/static/img/coins/32x32/litecoin.png';
send_img($message, $ltclogo);
}
}
function curl_post($postfields) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.groupme.com/v3/bots/post');
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
curl_exec($ch);
curl_close($ch);
}
function send($message) {
include 'config.php';
$postdata = [
'bot_id' => $bottoken,
'text' => $message
];
curl_post(http_build_query($postdata));
}
function send_img($message, $image) {
include 'config.php';
$attachments = [
'type' => 'image',
'url' => $image
];
$postdata = [
'bot_id' => $bottoken,
'text' => $message,
'attachments' => [$attachments]
];
curl_post(json_encode($postdata));
}
function mention($message, $name) {
include 'config.php';
$loci = [
stripos($message, $name),
strlen($name)
];
$attachments = [
'loci' => [$loci],
'type' => 'mentions',
'user_ids' => [get_user_id($name)]
];
$postdata = [
'bot_id' => $bottoken,
'text' => $message,
'attachments' => [$attachments]
];
curl_post(json_encode($postdata));
}
function store_array($array, $file) {
$array = json_encode($array);
file_put_contents($file, "response as $element) {
if ($element->bot_id == $bottoken) {
return $element->group_id;
}
}
}
function get_user_id($name) {
include 'config.php';
$user_id = 'No member with that name found';
$groupid = get_bot_group();
$groups = json_decode(file_get_contents("https://api.groupme.com/v3/groups?token=$apitoken"));
foreach($groups->response as $element) {
if ($element->id == $groupid) {
foreach($element->members as $member) {
if (stripos($member->nickname, $name) !== FALSE) {
$user_id = $member->user_id;
}
}
}
}
return $user_id;
}
function get_name($userid) {
include 'config.php';
$name = 'Invalid userid';
$groupid = get_bot_group();
$groups = json_decode(file_get_contents("https://api.groupme.com/v3/groups?token=$apitoken"));
foreach($groups->response as $element) {
if ($element->id == $groupid) {
foreach($element->members as $member) {
if ($userid == $member->user_id) {
$name = $member->nickname;
}
}
}
}
return $name;
}
function parse_cmd($command) {
$command = explode(' -"', $command);
array_splice($command, 0, 1);
foreach($command as &$element) {
$element = substr($element, 0, strlen($element) -1);
}
return $command;
}
function disp_help() {
$help = <<<'EOHELP'
'/help' displays this message
'/ignorelist' lists all users who are being ignored
'/ignore -"userid"' ignores all messages from specified user
'/unignore -"userid"' removed ignore on specified user
'/responses' displays all current responses
'/addresponse -"find" -"respond"' adds a response to the "find" phrase %n = name, %u = userid
'/delresponse -"find"' deletes a response for phrase "find"
'/admins' displays all current admins
'/getuserid -"name"' displays user id of a member of the group
'/addadmin -"userid" adds the specified user ID to the admin list
'/deladmin -"userid" adds the specified user ID to the admin list
'/enable -"(weather|btc|eth)"' enables a custom response
'/disable -"(weather|btc|eth)"' disables a custom response
'/status' lists all settings and their current status
EOHELP;
send($help);
}
function list_ignored() {
$message = null;
$ignored = read_array('ignore.php');
foreach($ignored as $element) {
$name = get_name($element);
$message .= "$element($name)\n";
}
send($message);
}
function add_ignore($userid) {
$ignored = read_array('ignore.php');
$message = "Something bad happened :(";
$name = get_name($userid);
if (!in_array($userid, $ignored)) {
if ($name !== 'Invalid userid') {
$ignored[count($ignored)] = $userid;
store_array($ignored, 'ignore.php');
$message = "$userid($name) has been added to the ignore list";
} else {
$message = "No member associated with User ID \"$userid\" is in the group";
}
} else {
$message = "$userid($name) is already being ignored";
}
return $message;
}
function del_ignore($userid) {
$ignored = read_array('ignore.php');
$message = "Something bad happened :(";
$name = get_name($userid);
if (in_array($userid, $ignored)) {
array_splice($ignored, array_search($userid, $ignored), 1);
$message = "$userid($name) was removed from the ignore list";
store_array($ignored, 'ignore.php');
} else {
$message = "$userid($name) is not being ignored";
}
return $message;
}
function list_responses() {
$message = null;
$responses = read_array('responses.php');
foreach($responses as $element) {
$message .= "$element[0] -> $element[1]\n";
}
send($message);
}
function search_responses($needle) {
$responses = read_array('responses.php');
$counter = 0;
$position = false;
foreach($responses as $element) {
if (stripos($element[0], $needle) !== FALSE || stripos($needle, $element[0]) !== FALSE) {
$position = $counter;
}
$counter++;
}
return $position;
}
function add_response($find, $response) {
$responses = read_array('responses.php');
$message = "Something bad happened :(";
if (search_responses($find) !== FALSE) {
$message = "There is already a similar response for $find";
} else {
$responses[count($responses)] = [$find, $response];
store_array($responses, 'responses.php');
$message = "Added response $find -> $response";
}
return $message;
}
function del_response($find) {
$responses = read_array('responses.php');
$message = "Something bad happened :(";
if (search_responses($find) !== FALSE) {
array_splice($responses, search_responses($find), 1);
store_array($responses, 'responses.php');
$message = "Deleted response for $find";
} else {
$message = "There is not a response for $find, nothing to delete";
}
return $message;
}
function list_admins() {
$message = null;
$admins = read_array('admins.php');
foreach($admins as $element) {
$name = get_name($element);
$message .= "$element($name)\n";
}
send($message);
}
function add_admin($userid) {
$admins = read_array('admins.php');
$message = "Something bad happened :(";
$name = get_name($userid);
if (!in_array($userid, $admins)) {
if ($name !== 'Invalid userid') {
$admins[count($admins)] = $userid;
store_array($admins, 'admins.php');
$message = "$userid($name) has been added to the admin list";
} else {
$message = "No member associated with User ID \"$userid\" is in the group";
}
} else {
$message = "$userid($name) is already an admin";
}
return $message;
}
function del_admin($userid) {
$admins = read_array('admins.php');
$message = "Something bad happened :(";
$name = get_name($userid);
if (in_array($userid, $admins)) {
array_splice($admins, array_search($userid, $admins), 1);
$message = "$userid($name) was removed from the admin list";
store_array($admins, 'admins.php');
} else {
$message = "$userid($name) is not an admin";
}
return $message;
}
function enable_custom($setting) {
$settings = read_array('settings.php');
$message = "Something bad happened :(";
if ($settings[$setting] == 1) {
$message = "Already enabled, no changes made";
} else {
$settings[$setting] = 1;
$message = "Response enabled";
store_array($settings, 'settings.php');
}
return $message;
}
function disable_custom($setting) {
$settings = read_array('settings.php');
$message = "Something bad happened :(";
if ($settings[$setting] == 0) {
$message = "Already disabled, no changes made";
} else {
$settings[$setting] = 0;
$message = "Response disabled";
store_array($settings, 'settings.php');
}
return $message;
}
function list_status() {
$message = null;
$settings = read_array('settings.php');
foreach($settings as $setting => $state) {
$message .= "$setting -> $state\n";
}
send($message);
}lights.php:
$ip) {
$ch[$element] = curl_init();
curl_setopt($ch[$element], CURLOPT_URL, $ip);
curl_setopt($ch[$element], CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch[$element], CURLOPT_HEADER, 0);
curl_setopt($ch[$element], CURLOPT_RETURNTRANSFER, 1);
curl_multi_add_handle($mh, $ch[$element]);
}
$active = null;
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
foreach ($ips as $element=>$ip) {
curl_multi_remove_handle($mh, $ch[$element]);
}
curl_multi_close($mh);
}
function get_gpio_state($ip, $pin) {
$request = "http://" . "$ip" . "/gpio.php?" . "p=" . "$pin" . "&r=1";
return perform_curl($request);
}
function blink($ip, $pins, $delay, $count) {
usleep($delay);
foreach($pins as $element=>$pin) {
$pinstate[$element] = get_gpio_state($ip, $pin);
}
for ($i = 0; $i < $count; $i++) {
foreach($pins as $element=>$pin) {
if ($pinstate[$element]) {
$requests[$element] = "http://" . "$ip" . "/gpio.php?" . "p=". "$pin" . "&w=1" . "&s=0";
$pinstate[$element] = 0;
} else {
$requests[$element] = "http://" . "$ip" . "/gpio.php?" . "p=". "$pin" . "&w=1" . "&s=1";
$pinstate[$element] = 1;
}
}
multicurl($requests);
}
usleep($delay);
}
function lights_on($ip, $pins) {
foreach($pins as $element=>$pin) {
$requests[$element] = "http://" . "$ip" . "/gpio.php?" . "p=". "$pin" . "&w=1" . "&s=1";
}
multicurl($requests);
}
function lights_off($ip, $pins) {
foreach($pins as $element=>$pin) {
$requests[$element] = "http://" . "$ip" . "/gpio.php?" . "p=". "$pin" . "&w=1" . "&s=0";
}
multicurl($requests);
}panel.php:
$value) {
if (isset($update[$key])) {
$settings[$key] = 1;
} else {
$settings[$key] = 0;
}
}
store_array($settings, 'settings.php');
}
if (isset($_POST['del_setting'])) {
$settings = read_array('settings.php');
$delete = $_POST['del_setting'];
foreach ($settings as $key=>$value) {
if (isset($delete[$key])) {
unset($settings[$key]);
}
}
store_array($settings, 'settings.php');
}
if (isset($_POST['new_setting']) && !empty($_POST['new_setting'])) {
$settings = read_array('settings.php');
$settings[$_POST['new_setting']] = 1;
store_array($settings, 'settings.php');
}
if (isset($_POST['send']) && !empty($_POST['send'])) {
send($_POST['send']);
}?>
PHP GroupMe Bot
tr:nth-child(even) {
background-color: #dddddd;
}
When adding a response, %n can be used to mention a user by name and %u will be replace by their user id
";
echo "";
echo "";
echo "";
$iteration++;
}?>
Find
Respond
Delete
$element[0]$element[1]";
echo "
$value) {
echo "";
echo "";
if ($value) {
echo "";
}?>
Name
State
Delete
$key";
} else {
echo "";
}
echo "";
echo "
Add setting
response->id;
$admins = "
PHP GroupMe Bot Setup发布于 2018-01-05 15:53:08
我只会在你存储设置的方式上具体说明。
将设置存储在JSON文件中是个好主意。我想说的是,你做的一些事情是不必要的。
您可以将JSON存储在PHP文件中,但是使用启动PHP文件,然后用read_array()去掉它。如果您不打算以PHP文件的形式运行它,那么您就不需要使用启动它,而只是希望它不能被公开访问。
同样,您也可以使用.json文件,或者使用web服务器禁止web访问该文件,或者更好地将该文件放置在web根文件夹之外。
发布于 2018-03-07 03:42:57
尽早返回,而不是有大量嵌套的if块。
在panel.php上有这样的代码,
if (file_exists('config.php')) {
//massive amount of code
}
else{
//show warning
}相反,你可以通过做,
if (!file_exists('config.php')) {
//show warning
exit 1;
}我也不喜欢函数中的include语句
function logging($userid, $name, $text) {
include 'config.php';
if ($log) {
if (!is_dir($logdir)) {
mkdir($logdir, $logdirchmod);
}
file_put_contents($logdir . '/' . $logfile, "$userid($name): $text\n", FILE_APPEND);
}
}我认为最好将这些变量传递到函数中,而不是包含配置文件。
https://codereview.stackexchange.com/questions/184179
复制相似问题