Skip to content

Commit

Permalink
Add VRC support.
Browse files Browse the repository at this point in the history
  • Loading branch information
ProjectInfinity committed Nov 23, 2017
1 parent 0a09996 commit 7676ede
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 2 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ crashlytics-build.properties
fabric.properties

cacert.pem
/config.yml
/config.yml
vrc/
2 changes: 1 addition & 1 deletion plugin.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: PocketVote
main: ProjectInfinity\PocketVote\PocketVote
version: 2.0.3
version: 2.1.0
api: [3.0.0-ALPHA6, 3.0.0-ALPHA7, 3.0.0-ALPHA8, 3.0.0-ALPHA9]
author: ProjectInfinity
permissions:
Expand Down
20 changes: 20 additions & 0 deletions src/ProjectInfinity/PocketVote/PocketVote.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class PocketVote extends PluginBase {

public static $cert;
public static $dev;
public static $hasVRC;

/** @var VoteManager $voteManager */
private $voteManager;
Expand Down Expand Up @@ -128,6 +129,25 @@ public function onEnable() {

$this->getServer()->getPluginManager()->registerEvents(new VoteListener($this), $this);

# Check if the VRC folder exists for legacy voting sites.
if(file_exists($this->getDataFolder().'vrc')) {
$this->getLogger()->info(TextFormat::GOLD.'VRC folder found, to enable sites that support VRC files. Place them in the plugins/PocketVote/vrc folder and ensure the file name ends with .vrc');
$vrcFiles = glob($this->getDataFolder().'vrc/*.{vrc}', GLOB_BRACE);
foreach($vrcFiles as $file) {
$fh = fopen($file, 'rb');
$raw = fread($fh, filesize($file));
fclose($fh);
$data = json_decode($raw);
if(!$raw || !$data) {
$this->getLogger()->warning(TextFormat::RED.'VRC file '.$file.' could not be read.');
continue;
}
$this->voteManager->addVRC((object)['website' => $data->website, 'check' => $data->check, 'claim' => $data->claim]);
self::$hasVRC = true;
$this->getLogger()->info(TextFormat::GREEN.'VRC enabled for '.$data->website);
}
}

$this->schedulerTask = $this->getServer()->getScheduler()->scheduleRepeatingTask(new SchedulerTask($this), 1200); # 1200 ticks = 60 seconds.
# Get voting link.
$this->getServer()->getScheduler()->scheduleAsyncTask(new VoteLinkTask($this->identity));
Expand Down
1 change: 1 addition & 0 deletions src/ProjectInfinity/PocketVote/VoteListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public function onVoteEvent(VoteEvent $event) {
* @priority LOWEST
*/
public function onPlayerJoin(PlayerJoinEvent $event) {
if(PocketVote::$hasVRC) $this->vm->scheduleVRCTask($event->getPlayer()->getName()); # TODO: This should be possible to disable and only allow through commands.
if(!$this->vm->hasVotes($event->getPlayer()->getName())) return;

$sender = new ConsoleCommandSender();
Expand Down
159 changes: 159 additions & 0 deletions src/ProjectInfinity/PocketVote/task/VRCCheckTask.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<?php

namespace ProjectInfinity\PocketVote\task;

use pocketmine\scheduler\AsyncTask;
use pocketmine\Server;
use ProjectInfinity\PocketVote\data\TaskResult;
use ProjectInfinity\PocketVote\data\VRCRecord;
use ProjectInfinity\PocketVote\event\VoteEvent;
use ProjectInfinity\PocketVote\PocketVote;

class VRCCheckTask extends AsyncTask {

public $vm, $vrcs, $player, $cert;

public function __construct(string $player) {
$this->player = $player;
$this->vrcs = PocketVote::getPlugin()->getVoteManager()->getVRC();
$this->cert = PocketVote::$cert;
}

public function onRun() {
$results = [];
foreach($this->vrcs as $vrc) {
$curl = curl_init(str_replace('{USERNAME}', $this->player, $vrc->check));

$url = parse_url($vrc->check);

curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_PORT => $url['scheme'] === 'https' ? 443 : 80,
CURLOPT_HEADER => false,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2,
CURLOPT_CAINFO => $this->cert
]);

$res = curl_exec($curl);

if($res === false) {
$results[] = $this->createResult(true, null, curl_error($curl));
curl_close($curl);
} else {

$result = json_decode($res);

if(!isset($result->voted) || !isset($result->claimed)) {
$results[] = $this->createResult(true, ['message' => 'Vote or claim field was missing in response from '.$url['host']]);
$this->setResult($results);
curl_close($curl);
return;
}

# There is a vote to claim.
if($result->voted && !$result->claimed) {
curl_close($curl);

$curl = curl_init(str_replace('{USERNAME}', $this->player, $vrc->claim));

$url = parse_url($vrc->check);

curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_PORT => $url['scheme'] === 'https' ? 443 : 80,
CURLOPT_HEADER => false,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2,
CURLOPT_CAINFO => $this->cert
]);

$res = curl_exec($curl);

if($res === false) {
$results[] = $this->createResult(true, null, curl_error($curl));
curl_close($curl);
} else {

$result = json_decode($res);
curl_close($curl);

if(!isset($result->voted) || !isset($result->claimed)) {
$results[] = $this->createResult(true, ['message' => 'Vote or claim field was missing in response from '.$url['host']]);
$this->setResult($results);
return;
}

# Claim failed.
if($result->voted && !$result->claimed) {
$results[] = $this->createResult(true, ['message' => 'Attempted to claim a vote but it failed. Site: '.$url['host']]);
$this->setResult($results);
return;
}

# Vote claim succeeded!
$results[] = $this->createResult(false, json_decode(json_encode([
'success' => true,
'payload' => [
'player' => $this->player,
'ip' => 'unknown',
'site' => $url['host']
]
])));

}
}

}
}
$this->setResult($results);
}

private function createResult($error, $res, $customError = null) {
$r = new TaskResult();
$r->setError($error);
if($error) {
if(!isset($customError)) {
$r->setErrorData(['message' => $res->message]);
}
else {
$r->setErrorData(['message' => $customError]);
}
}
# Had votes.
if(isset($res->payload) && $res->success) $r->setVotes($res->payload);

return $r;
}

public function onCompletion(Server $server) {
if(!$this->hasResult()) {
$server->getLogger()->emergency('A VRC task finished without a result. This should never happen.');
return;
}

/** @var TaskResult[] $results */
$results = $this->getResult();

if(!is_array($results)) {
$server->getLogger()->warning('VRCCheckTask result was not an array. This is a problem...');
return;
}

foreach($results as $result) {
$vote = (object) $result->getVotes();
$server->getPluginManager()->callEvent(
new VoteEvent(PocketVote::getPlugin(),
$vote->player,
$vote->ip,
$vote->site
)
);
}

# Removes task from the array that prevents duplicate tasks.
PocketVote::getPlugin()->getVoteManager()->removeVRCTask($this->player);
}
}
28 changes: 28 additions & 0 deletions src/ProjectInfinity/PocketVote/util/VoteManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,50 @@

use ProjectInfinity\PocketVote\PocketVote;
use ProjectInfinity\PocketVote\task\ExpireVotesTask;
use ProjectInfinity\PocketVote\task\VRCCheckTask;

class VoteManager {

private $plugin;

/** @var $votes array */
private $votes;
/** @var $loadedVRC array */
private $loadedVRC;
/** @var $currentVRCTasks array */
private $currentVRCTasks;

private $voteLink = null;

public function __construct(PocketVote $plugin) {
$this->plugin = $plugin;
$this->votes = $plugin->getConfig()->get('votes', []);
$this->loadedVRC = [];
$this->currentVRCTasks = [];
if($this->plugin->expiration > 0) $plugin->getServer()->getScheduler()->scheduleDelayedRepeatingTask(new ExpireVotesTask(), 300, 6000);
}

public function addVRC($record) {
$this->loadedVRC[] = $record;
}

public function getVRC(): array {
return $this->loadedVRC;
}

public function removeVRCTask($player) {
if(!isset($this->currentVRCTasks[$player])) return;
unset($this->currentVRCTasks[$player]);
}

public function scheduleVRCTask($player) {
if((PocketVote::$hasVRC && !$this->plugin->multiserver) || (PocketVote::$hasVRC && $this->plugin->multiserver && $this->plugin->multiserver_role === 'master')) {
if(isset($this->currentVRCTasks[$player])) return;
# Only run when VRC is enabled and multiserver is off or VRC is enabled and multiserver and server role is set to master.
$this->plugin->getServer()->getScheduler()->scheduleAsyncTask(new VRCCheckTask($player));
}
}

public function getVoteLink() {
return $this->voteLink;
}
Expand Down

0 comments on commit 7676ede

Please sign in to comment.