diff --git a/.gitignore b/.gitignore
index 4510d84b7..fc855a3a9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,3 +42,5 @@ package-lock.json
index.php
.DS_Store
static/.DS_Store
+vendor
+composer.lock
\ No newline at end of file
diff --git a/.htaccess b/.htaccess
index 66a37f293..c81b3e212 100644
--- a/.htaccess
+++ b/.htaccess
@@ -5,3 +5,5 @@ RewriteRule ^gym_data$ gym_data.php?$1 [QSA,L]
RewriteRule ^motd_data$ motd_data.php?$1 [QSA,L]
RewriteRule ^weather_data$ weather_data.php?$1 [QSA,L]
RewriteRule ^serviceWorker.min.js$ static/dist/js/serviceWorker.min.js?$1 [QSA,L]
+RewriteRule ^user$ user.php?$1 [QSA,L]
+RewriteRule ^discord-login$ discord-login.php?$1 [QSA,L]
\ No newline at end of file
diff --git a/DiscordAuth.php b/DiscordAuth.php
new file mode 100644
index 000000000..67ec2dfe6
--- /dev/null
+++ b/DiscordAuth.php
@@ -0,0 +1,79 @@
+ 'https://discordapp.com']);
+ $redirector = new DiscordRedirector($this);
+
+ global $discordBotClientId, $discordBotClientSecret, $discordBotRedirectUri;
+
+ $clientConfig = new ClientConfig([
+ 'client_id' => $discordBotClientId,
+ 'client_secret' => $discordBotClientSecret,
+ 'redirect_uri' => $discordBotRedirectUri
+ ]);
+
+ $serverConfig = new ServerConfig([
+ 'authorization_endpoint' => '/api/oauth2/authorize',
+ 'token_endpoint' => '/api/oauth2/token',
+ ]);
+
+ $this->oauthSession = new AuthorizationCodeSession(
+ $httpClient,
+ $redirector,
+ $clientConfig,
+ $serverConfig
+ );
+
+ $scope = new Scope(['identify']);
+ $this->oauthSession->setScope($scope);
+ }
+
+ public function gotoDiscord()
+ {
+ $this->setUpOAuth();
+ return $this->oauthSession->authorize();
+ }
+
+ public function handleAuthorizationResponse()
+ {
+ $this->setUpOAuth();
+ $authorizationResponse = new AuthorizationResponse($_GET);
+ $this->oauthSession->handleAuthorizationResponse($authorizationResponse);
+ }
+
+ private function setUpResource()
+ {
+ if ($this->resource != null) {
+ return $this->resource;
+ }
+ $handler = \GuzzleHttp\HandlerStack::create();
+ $handler->before('http_errors', function ($callable) {
+ return new \EasyBib\Guzzle\BearerAuthMiddleware($callable, $this->oauthSession);
+ });
+ $this->resource = new \GuzzleHttp\Client([
+ 'base_uri' => 'https://discordapp.com',
+ 'handler' => $handler,
+ ]);
+ }
+
+ public function get($uri)
+ {
+ $this->setUpResource();
+ return $this->resource->get($uri)->getBody()->getContents();
+ }
+}
diff --git a/DiscordRedirector.php b/DiscordRedirector.php
new file mode 100644
index 000000000..ce585b673
--- /dev/null
+++ b/DiscordRedirector.php
@@ -0,0 +1,18 @@
+ https://discordapp.com/developers/applications/me
+ // 2. Install composer with "apt-get install composer".
+ // 3. Navigate to your website's root folder and type "composer install" to install the dependencies.
+ // 4. Add your callback-page as a REDIRECT URI to your discord bot. Should be the same as $discordBotRedirectUri.
+ // 5. Enter Client ID, Client Secret and Redirect URI below.
+$discordBotClientId = 0;
+$discordBotClientSecret = "";
+$discordBotRedirectUri = "https://example.com/discord-callback.php";
+
+$adminUsers = array('admin@example.com', 'Superadmin#13337'); // You can add multiple admins by adding them to the array.
+$logfile = '../members.log'; // Path to log file. Make sure this works as it will be your life saver if your db crashes.
+$daysMembershipPerQuantity = 31; // How many days membership one selly quantity will give.
+$sellyPage = ''; // Link to selly purchase page for membership renewal.
+$sellyWebhookSecret = ''; // Add a secret key at https://selly.gg/settings to make sure the payment webhook is sent from selly to prevent fake payments.
+ // Add the same key to the $sellyWebhookSecret variable.
+
//-----------------------------------------------------
// FRONTEND SETTINGS
//-----------------------------------------------------
+if ($noNativeLogin === true && $noDiscordLogin == true || (($noNativeLogin === false || $noDiscordLogin === false) && !empty($_SESSION['user']->expire_timestamp) && $_SESSION['user']->expire_timestamp > time())) {
+
+ /*
+ THESE SETTINGS WILL BE APPLIED IF:
+ - LOGIN IS DISABLED
+ - LOGIN IS ENABLED AND THE USER IS LOGGED ON
+ */
+
+ /* Marker Settings */
+ $noExcludeMinIV = false; // true/false
+ $noMinIV = false; // true/false
+ $noMinLevel = false; // true/false
+ $noHighLevelData = false; // true/false
+
+ /* Notification Settings */
+ $noNotifyPokemon = false; // true/false
+ $noNotifyRarity = false; // true/false
+ $noNotifyIv = false; // true/false
+ $noNotifyLevel = false; // true/false
+ $noNotifyRaid = false; // true/false
+ $noNotifySound = false; // true/false
+ $noCriesSound = false; // true/false
+ $noNotifyBounce = false; // true/false
+ $noNotifyNotification = false; // true/false
+
+ /* Style Settings */
+ $iconNotifySizeModifier = 15; // 0, 15, 30, 45
+} else {
+
+ /*
+ THESE SETTINGS WILL BE APPLIED IF:
+ - LOGIN IS ENABLED AND THE USER IS NOT A DONATOR
+ */
+
+ /* Marker Settings */
+ $noExcludeMinIV = true; // true/false
+ $noMinIV = true; // true/false
+ $noMinLevel = true; // true/false
+ $noHighLevelData = true; // true/false
+
+ /* Notification Settings */
+ $noNotifyPokemon = true; // true/false
+ $noNotifyRarity = true; // true/false
+ $noNotifyIv = true; // true/false
+ $noNotifyLevel = true; // true/false
+ $noNotifyRaid = true; // true/false
+ $noNotifySound = true; // true/false
+ $noCriesSound = true; // true/false
+ $noNotifyBounce = true; // true/false
+ $noNotifyNotification = true; // true/false
+
+ /* Style Settings */
+ $iconNotifySizeModifier = 0; // 0, 15, 30, 45
+}
+
/* Marker Settings */
$noPokemon = false; // true/false
$enablePokemon = 'true'; // true/false
$noPokemonNumbers = false; // true/false
-$noHighLevelData = false; // true/false
$noHidePokemon = false; // true/false
$hidePokemon = '[10, 13, 16, 19, 21, 29, 32, 41, 46, 48, 50, 52, 56, 74, 77, 96, 111, 133,
161, 163, 167, 177, 183, 191, 194, 168]'; // [] for empty
-$hidePokemonCoords = true; // true/false
-$noExcludeMinIV = false; // true/false
+$hidePokemonCoords = false; // true/false
+
$excludeMinIV = '[131, 143, 147, 148, 149, 248]'; // [] for empty
-$noMinIV = false; // true/false
$minIV = '0'; // "0" for empty or a number
-
-$noMinLevel = false; // true/false
$minLevel = '0'; // "0" for empty or a number
$noBigKarp = false; // true/false
@@ -148,31 +223,22 @@
/* Notification Settings */
-$noNotifyPokemon = false; // true/false
$notifyPokemon = '[201]'; // [] for empty
-$noNotifyRarity = false; // true/false
$notifyRarity = '[]'; // "Common", "Uncommon", "Rare", "Very Rare", "Ultra Rare"
-$noNotifyIv = false; // true/false
$notifyIv = '""'; // "" for empty or a number
-$noNotifyLevel = false; // true/false
$notifyLevel = '""'; // "" for empty or a number
-$noNotifyRaid = false; // true/false
$notifyRaid = 5; // O to disable
-$noNotifySound = false; // true/false
$notifySound = 'false'; // true/false
-$noCriesSound = false; // true/false
$criesSound = 'false'; // true/false
-$noNotifyBounce = false; // true/false
$notifyBounce = 'true'; // true/false
-$noNotifyNotification = false; // true/false
$notifyNotification = 'true'; // true/false
/* Style Settings */
@@ -189,7 +255,6 @@
$iconSize = 0; // -8, 0, 10, 20
$noIconNotifySizeModifier = false; // true/false | Increase size of notified Pokemon
-$iconNotifySizeModifier = 15; // 0, 15, 30, 45
$noGymStyle = false; // true/false
$gymStyle = 'ingame'; // ingame, shield
diff --git a/config/example.config.php b/config/example.config.php
index 0b73bb85d..4f6315c1a 100644
--- a/config/example.config.php
+++ b/config/example.config.php
@@ -65,29 +65,103 @@
$motdTitle = "Message of the Day";
$motdContent = "This is an example MOTD
Do whatever you like with it.";
+//-----------------------------------------------------
+// Login
+//-----------------------------------------------------
+
+$noNativeLogin = true; // true/false - This will enable the built in login system.
+$domainName = ''; // If this is empty, reset-password emails will use the domain name taken from the URL.
+
+$noDiscordLogin = true; // true/false - This will enable login through discord.
+ // 1. Create a discord bot here -> https://discordapp.com/developers/applications/me
+ // 2. Install composer with "apt-get install composer".
+ // 3. Navigate to your website's root folder and type "composer install" to install the dependencies.
+ // 4. Add your callback-page as a REDIRECT URI to your discord bot. Should be the same as $discordBotRedirectUri.
+ // 5. Enter Client ID, Client Secret and Redirect URI below.
+$discordBotClientId = 0;
+$discordBotClientSecret = "";
+$discordBotRedirectUri = "https://example.com/discord-callback.php";
+
+$adminUsers = array('admin@example.com', 'Superadmin#13337'); // You can add multiple admins by adding them to the array.
+$logfile = '../members.log'; // Path to log file. Make sure this works as it will be your life saver if your db crashes.
+$daysMembershipPerQuantity = 31; // How many days membership one selly quantity will give.
+$sellyPage = ''; // Link to selly purchase page for membership renewal.
+$sellyWebhookSecret = ''; // Add a secret key at https://selly.gg/settings to make sure the payment webhook is sent from selly to prevent fake payments.
+ // Add the same key to the $sellyWebhookSecret variable.
+
//-----------------------------------------------------
// FRONTEND SETTINGS
//-----------------------------------------------------
+if ($noNativeLogin === true && $noDiscordLogin == true || (($noNativeLogin === false || $noDiscordLogin === false) && !empty($_SESSION['user']->expire_timestamp) && $_SESSION['user']->expire_timestamp > time())) {
+
+ /*
+ THESE SETTINGS WILL BE APPLIED IF:
+ - LOGIN IS DISABLED
+ - LOGIN IS ENABLED AND THE USER IS LOGGED ON
+ */
+
+ /* Marker Settings */
+ $noExcludeMinIV = false; // true/false
+ $noMinIV = false; // true/false
+ $noMinLevel = false; // true/false
+ $noHighLevelData = false; // true/false
+
+ /* Notification Settings */
+ $noNotifyPokemon = false; // true/false
+ $noNotifyRarity = false; // true/false
+ $noNotifyIv = false; // true/false
+ $noNotifyLevel = false; // true/false
+ $noNotifyRaid = false; // true/false
+ $noNotifySound = false; // true/false
+ $noCriesSound = false; // true/false
+ $noNotifyBounce = false; // true/false
+ $noNotifyNotification = false; // true/false
+
+ /* Style Settings */
+ $iconNotifySizeModifier = 15; // 0, 15, 30, 45
+} else {
+
+ /*
+ THESE SETTINGS WILL BE APPLIED IF:
+ - LOGIN IS ENABLED AND THE USER IS _NOT_ LOGGED ON
+ */
+
+ /* Marker Settings */
+ $noExcludeMinIV = true; // true/false
+ $noMinIV = true; // true/false
+ $noMinLevel = true; // true/false
+ $noHighLevelData = true; // true/false
+
+ /* Notification Settings */
+ $noNotifyPokemon = true; // true/false
+ $noNotifyRarity = true; // true/false
+ $noNotifyIv = true; // true/false
+ $noNotifyLevel = true; // true/false
+ $noNotifyRaid = true; // true/false
+ $noNotifySound = true; // true/false
+ $noCriesSound = true; // true/false
+ $noNotifyBounce = true; // true/false
+ $noNotifyNotification = true; // true/false
+
+ /* Style Settings */
+ $iconNotifySizeModifier = 0; // 0, 15, 30, 45
+}
+
/* Marker Settings */
$noPokemon = false; // true/false
$enablePokemon = 'true'; // true/false
$noPokemonNumbers = false; // true/false
-$noHighLevelData = false; // true/false
$noHidePokemon = false; // true/false
$hidePokemon = '[10, 13, 16, 19, 21, 29, 32, 41, 46, 48, 50, 52, 56, 74, 77, 96, 111, 133,
161, 163, 167, 177, 183, 191, 194, 168]'; // [] for empty
$hidePokemonCoords = false; // true/false
-$noExcludeMinIV = false; // true/false
$excludeMinIV = '[131, 143, 147, 148, 149, 248]'; // [] for empty
-$noMinIV = false; // true/false
$minIV = '0'; // "0" for empty or a number
-
-$noMinLevel = false; // true/false
$minLevel = '0'; // "0" for empty or a number
$noBigKarp = false; // true/false
@@ -138,31 +212,22 @@
/* Notification Settings */
-$noNotifyPokemon = false; // true/false
$notifyPokemon = '[201]'; // [] for empty
-$noNotifyRarity = false; // true/false
$notifyRarity = '[]'; // "Common", "Uncommon", "Rare", "Very Rare", "Ultra Rare"
-$noNotifyIv = false; // true/false
$notifyIv = '""'; // "" for empty or a number
-$noNotifyLevel = false; // true/false
$notifyLevel = '""'; // "" for empty or a number
-$noNotifyRaid = false; // true/false
$notifyRaid = 5; // O to disable
-$noNotifySound = false; // true/false
$notifySound = 'false'; // true/false
-$noCriesSound = false; // true/false
$criesSound = 'false'; // true/false
-$noNotifyBounce = false; // true/false
$notifyBounce = 'true'; // true/false
-$noNotifyNotification = false; // true/false
$notifyNotification = 'true'; // true/false
/* Style Settings */
@@ -179,7 +244,6 @@
$iconSize = 0; // -8, 0, 10, 20
$noIconNotifySizeModifier = false; // true/false | Increase size of notified Pokemon
-$iconNotifySizeModifier = 15; // 0, 15, 30, 45
$noGymStyle = false; // true/false
$gymStyle = 'ingame'; // ingame, shield
diff --git a/discord-callback.php b/discord-callback.php
new file mode 100644
index 000000000..4c28562fa
--- /dev/null
+++ b/discord-callback.php
@@ -0,0 +1,47 @@
+handleAuthorizationResponse($_GET);
+ $user = json_decode($auth->get("/api/users/@me"));
+
+ $count = $db->count("users", [
+ "id" => $user->{'id'},
+ "login_system" => 'discord'
+ ]);
+
+ if ($count === 0) {
+ $db->insert("users", [
+ "id" => $user->{'id'},
+ "user" => $user->{'username'} . "#" . $user->{'discriminator'},
+ "expire_timestamp" => time(),
+ "login_system" => 'discord'
+ ]);
+
+ $logMsg = "INSERT INTO users (id, user, expire_timestamp, login_system) VALUES ('{$user->id}', '{$user->username}" . "#" . "{$user->discriminator}', '" . time() ."', 'discord'); -- " . date('Y-m-d H:i:s') . "\r\n";
+ file_put_contents($logfile, $logMsg, FILE_APPEND);
+ }
+
+ setcookie("LoginCookie", session_id(), time()+60*60*24*7);
+
+ $db->update("users", [
+ "session_id" => session_id(),
+ "user" => $user->{'username'} . "#" . $user->{'discriminator'}
+ ], [
+ "id" => $user->{'id'},
+ "login_system" => 'discord'
+ ]);
+ }
+ header("Location: .");
+ die();
+ } catch (Exception $e) {
+ header("Location: ./discord-login");
+ }
+} else {
+ header("Location: .");
+}
diff --git a/discord-login.php b/discord-login.php
new file mode 100644
index 000000000..edf30334e
--- /dev/null
+++ b/discord-login.php
@@ -0,0 +1,12 @@
+gotoDiscord();
+} else {
+ header("Location: .");
+}
diff --git a/logout.php b/logout.php
new file mode 100644
index 000000000..3c228058b
--- /dev/null
+++ b/logout.php
@@ -0,0 +1,7 @@
+
+
+ id)) {
+ $info = $db->query(
+ "SELECT expire_timestamp FROM users WHERE id = :id AND login_system = :login_system", [
+ ":id" => $_SESSION['user']->id,
+ ":login_system" => $_SESSION['user']->login_system
+ ]
+ )->fetch();
+
+ $_SESSION['user']->expire_timestamp = $info['expire_timestamp'];
+
+ if (!empty($_SESSION['user']->updatePwd) && $_SESSION['user']->updatePwd === 1) {
+ header("Location: ./user");
+ die();
+ }
+
+ if ($info['expire_timestamp'] > time()) {
+ $color = "green";
+ } else {
+ $color = "red";
+ }
+
+ echo "" . substr($_SESSION['user']->user, 0, 3) . "...";
+ } else {
+ echo "" . i8ln('Login') . "";
+ }
+ }
+ ?>
@@ -594,7 +629,7 @@ class="onoffswitch-checkbox"/>
}
?>
' . i8ln('Notification') . '
+ expire_timestamp);
+
+ echo $_SESSION['user']->user . "
";
+ if ($_SESSION['user']->expire_timestamp > time()) {
+ echo "" . i8ln('Membership expires on') . " {$time}";
+ } else {
+ echo "" . i8ln('Membership expired on') . " {$time}";
+ } ?>
+