├── logo.png ├── .gitignore ├── .idea ├── php.xml ├── vcs.xml └── webResources.xml ├── .poggit.yml ├── plugin.yml ├── README.md ├── src └── Niekert │ └── DiscordMCPE │ ├── Tasks │ └── SendTaskAsync.php │ ├── Events │ └── EventListener.php │ └── Main.php ├── resources └── config.yml └── LICENSE /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiekertDev/Discord-MCPE/HEAD/logo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | images/Thumbs.db 2 | idea_temp_LocalResourceRootsList 3 | /config.yml 4 | \.idea/ 5 | -------------------------------------------------------------------------------- /.idea/php.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.poggit.yml: -------------------------------------------------------------------------------- 1 | --- # Poggit-CI Manifest. Open the CI at https://poggit.pmmp.io/ci/niekmussche/Discord-MCPE 2 | branches: 3 | - master 4 | projects: 5 | Discord-MCPE: 6 | icon: logo.png 7 | model: default 8 | path: "" 9 | ... -------------------------------------------------------------------------------- /plugin.yml: -------------------------------------------------------------------------------- 1 | name: Discord-MCPE 2 | author: Niekert 3 | version: "1.0.3" 4 | api: [3.0.0] 5 | softdepend: PurePerms 6 | main: Niekert\DiscordMCPE\Main 7 | commands: 8 | discord: 9 | description: Send an message to Discord! 10 | permission: discord.send 11 | usage: /discord MESSAGE 12 | aliases: [dc] 13 | permissions: 14 | discord.send: 15 | default: op 16 | -------------------------------------------------------------------------------- /.idea/webResources.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Discord-MCPE 2 | 3 | ##### 4 | 5 | ![Discord-MCPE Logo](logo.png) 6 | 7 | [](https://poggit.pmmp.io/ci/niekmussche/Discord-MCPE/Discord-MCPE) 8 | 9 | Connect your PocketMine server with Discord™! 10 | 11 | ## Installing: 12 | 1. Download phar from [Poggit™](https://poggit.pmmp.io/ci/NiekertDev/Discord-MCPE) 13 | 2. Put it in /plugins folder 14 | 3. Start server 15 | 4. Edit config 16 | 5. Reload server 17 | 18 | ## Config: 19 | webhook_url: Your discord webhook url. 20 | 21 | chat_url: Webhook url for the /discord command and when somebody chats. Set to 0 to use default. 22 | 23 | username: The username the plugin uses in discord. 24 | 25 | chat_username: The username of the plugin for /discord and when someone chats. Set to 0 to use default. 26 | 27 | chat_format: Format in discord that the plugin uses when sending a message. {player} and {message} can be used. 28 | 29 | start_message: Message sent when server starts. 30 | 31 | shutdown_message: Message sent when server stops. 32 | 33 | join_message: Message sent when player joins. {player} can be used. 34 | 35 | quit_message: Message sent when player leaves. {player} can be used. 36 | 37 | death_message: Message sent when player get killed. {player} can be used. 38 | 39 | command: Enable/disable "/discord" 40 | 41 | chat_prefix: Prefix for chat. When "!" and someone says !Hello, Hello is send to Discord 42 | 43 | chat: Send everything to Discord. Recommended to keep this disabled, but it can be used. 44 | 45 | pureperms: Support for PurePerms rank names. PurePerms ranks use the prefix {rank}. If not enabled, {rank} tags will show as "{rank}". 46 | 47 | debug: Show error messages. 48 | 49 | ## Making a Discord™ webhook: 50 | 1. Open Discord 51 | 2. Go to your server 52 | 3. Make a new chat channel / Open one 53 | 4. Click on the settings icon beside your chat channel name 54 | 5. Click Webhooks => New 55 | 6. Click "Copy" under Webhook URL 56 | 7. Paste it in the config 57 | 8. No more! 58 | -------------------------------------------------------------------------------- /src/Niekert/DiscordMCPE/Tasks/SendTaskAsync.php: -------------------------------------------------------------------------------- 1 | player = $player; 22 | $this->webhook = $webhook; 23 | $this->curlopts = $curlopts; 24 | } 25 | 26 | public function onRun() 27 | { 28 | $curl = curl_init(); 29 | curl_setopt($curl, CURLOPT_URL, $this->webhook); 30 | curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode(unserialize($this->curlopts))); 31 | curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); 32 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 33 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 34 | $response = curl_exec($curl); 35 | $curlerror = curl_error($curl); 36 | 37 | //Messy code incoming 38 | $responsejson = json_decode($response, true); 39 | $success = false; 40 | $error = 'IDK What happened'; 41 | if ($curlerror != '') { 42 | $error = $curlerror; 43 | } elseif (curl_getinfo($curl, CURLINFO_HTTP_CODE) != 204) { 44 | $error = $responsejson['message']; 45 | } elseif (curl_getinfo($curl, CURLINFO_HTTP_CODE) == 204 OR $response === '') { 46 | $success = true; 47 | } 48 | $result = ['Response' => $response, 'Error' => $error, 'success' => $success]; 49 | $this->setResult($result, true); 50 | } 51 | 52 | /** 53 | * @param Server $server 54 | */ 55 | public function onCompletion(Server $server) 56 | { 57 | $plugin = $server->getPluginManager()->getPlugin('Discord-MCPE'); 58 | if (!$plugin instanceof Main) { 59 | return; 60 | } 61 | if (!$plugin->isEnabled()) { 62 | return; 63 | } 64 | $plugin->notify($this->player, $this->getResult()); 65 | } 66 | } -------------------------------------------------------------------------------- /resources/config.yml: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # Discord-MCPE # 3 | # By: Niekert # 4 | # Support: # 5 | # https://github.com/NiekertDev/Discord-MCPE/issues/new # 6 | # Credit to Thunder33345 for helping with small things # 7 | # Credit to TheRoyalBlock for config design # 8 | # Main options section (below) # 9 | ############################################################ 10 | 11 | webhook_url: "" 12 | # Your discord webhook url. 13 | 14 | chat_url: "" 15 | # Webhook url for the /discord command and when somebody chats. Set to 0 to use default. 16 | 17 | username: "" 18 | # The username the plugin uses in discord. 19 | 20 | chat_username: "" 21 | # The username of the plugin for /discord and when someone chats. Set to 0 to use default. 22 | 23 | chat_format: "[{player}] {message}" 24 | # Format in discord that the plugin uses when sending a message. {rank}, {player}, and {message} can be used. 25 | 26 | ############################################################ 27 | # Messages on Event # 28 | # These messages are triggered on an event such as when # 29 | # the server starts or stops, or when a player joins or # 30 | # leaves. Also when a player dies. # 31 | # Tip: Set any of these to 0 to disable them # 32 | ############################################################ 33 | 34 | start_message: "" 35 | # Message sent when server starts. 36 | 37 | shutdown_message: "" 38 | # Message sent when server stops. 39 | 40 | join_message: "" 41 | # Message sent when player joins. {player} and {rank} can be used. 42 | 43 | quit_message: "" 44 | # Message sent when player leaves. {player} and {rank} can be used. 45 | 46 | death_message: "" 47 | # Message sent when player get killed. {player} and {rank} can be used. 48 | 49 | ############################################################ 50 | # Other Options # 51 | # It is not recommended that you change these, especially # 52 | # if you do not understand what they mean. # 53 | # Tip: Set any of these to false to disable them # 54 | # Tip: Set any of these to true to enable them # 55 | ############################################################ 56 | 57 | command: true 58 | # Enable/disable "/discord" 59 | 60 | chat_prefix: "!" 61 | # Prefix for chat. See README.md for more info. 62 | 63 | chat: false 64 | # Send everything to Discord. Recommended to keep this disabled, but it can be used. 65 | 66 | pureperms: false 67 | # Support for PurePerms rank names. PurePerms ranks use the prefix {rank}. 68 | # If not enabled, {rank} tags will show as "{rank}". 69 | 70 | debug: false 71 | # Show error messages. Set to 1 to enable. 72 | 73 | ##################################################### 74 | # UNDER NO CIRCUMSTANCES SHOULD YOU EDIT THE # 75 | # FOLLOWING LINE! # 76 | Version: "1.0.2" 77 | # Thank you for not editing the line above! # 78 | ##################################################### -------------------------------------------------------------------------------- /src/Niekert/DiscordMCPE/Events/EventListener.php: -------------------------------------------------------------------------------- 1 | main = $plugin; 22 | $this->config = new Config($plugin->getDataFolder() . 'config.yml', Config::YAML, array()); 23 | $this->webhook = $this->config->get('webhook_url'); 24 | $this->ppa = $plugin->getServer()->getPluginManager()->getPlugin('PurePerms'); 25 | } 26 | 27 | 28 | /** 29 | * @param PlayerJoinEvent $event 30 | */ 31 | public function onJoin(PlayerJoinEvent $event) 32 | { 33 | $playername = $event->getPlayer()->getDisplayName(); 34 | if ($this->main->joinopt !== '0') { 35 | if ($this->main->pp) { 36 | $this->main->sendMessage($this->webhook, str_replace('{rank}', C::clean($this->ppa->getUserDataMgr()->getGroup($event->getPlayer())), str_replace('{player}', C::clean($playername), $this->main->joinopt))); 37 | } else { 38 | $this->main->sendMessage($this->webhook, str_replace('{player}', C::clean($playername), $this->main->joinopt)); 39 | } 40 | } 41 | } 42 | 43 | /** 44 | * @param PlayerQuitEvent $event 45 | */ 46 | public function onQuit(PlayerQuitEvent $event) 47 | { 48 | $playername = $event->getPlayer()->getDisplayName(); 49 | if ($this->main->quitopt !== '0') { 50 | if ($this->main->pp) { 51 | $this->main->sendMessage($this->webhook, str_replace('{rank}', C::clean($this->ppa->getUserDataMgr()->getGroup($event->getPlayer())), str_replace('{player}', C::clean($playername), $this->main->quitopt))); 52 | } else { 53 | $this->main->sendMessage($this->webhook, str_replace('{player}', C::clean($playername), $this->main->quitopt)); 54 | } 55 | } 56 | } 57 | 58 | /** 59 | * @param PlayerDeathEvent $event 60 | */ 61 | public function onDeath(PlayerDeathEvent $event) 62 | { 63 | $playername = $event->getEntity()->getDisplayName(); 64 | if ($this->main->deathopt !== '0') { 65 | if ($this->main->pp) { 66 | $this->main->sendMessage($this->webhook, str_replace('{rank}', C::clean($this->ppa->getUserDataMgr()->getGroup($event->getPlayer())), str_replace('{player}', C::clean($playername), $this->main->deathopt))); 67 | } else { 68 | $this->main->sendMessage($this->webhook, str_replace('{player}', C::clean($playername), $this->main->deathopt)); 69 | } 70 | } 71 | } 72 | 73 | /** 74 | * @param PlayerChatEvent $event 75 | */ 76 | public function onChat(PlayerChatEvent $event) 77 | { 78 | if ($event->isCancelled()) return; 79 | $message = $event->getMessage(); 80 | $sender = $event->getPlayer(); 81 | $chaturl = $this->main->chaturl; 82 | if ($this->main->chatprefix !== '0') { 83 | if ($this->main->pp) { 84 | $format = str_replace(['{rank}', '{player}', '{message}'], [C::clean($this->ppa->getUserDataMgr()->getGroup($event->getPlayer())), C::clean($sender->getName()), ltrim($message, $this->main->chatprefix)], $this->main->chatformat); 85 | if (substr($message, 0, 1) === $this->main->chatprefix) { 86 | $event->setCancelled(); 87 | $this->main->sendMessage($chaturl, $format, $sender->getName(), $this->main->chatuser); 88 | } 89 | } else { 90 | $format = str_replace(['{player}', '{message}'], [C::clean($sender->getName()), ltrim($message, $this->main->chatprefix)], $this->main->chatformat); 91 | if (substr($message, 0, 1) === $this->main->chatprefix) { 92 | $event->setCancelled(); 93 | $this->main->sendMessage($chaturl, $format, $sender->getName(), $this->main->chatuser); 94 | } 95 | } 96 | if ($this->main->chatopt) { 97 | if ($this->main->pp) { 98 | $format = str_replace(array('{rank}', '{player}', '{message}'), array(C::clean($this->ppa->getUserDataMgr()->getGroup($event->getPlayer())), C::clean($sender->getName()), $message), $this->main->chatformat); 99 | $this->main->sendMessage($chaturl, $format, 'nolog', $this->main->chatuser); 100 | } else { 101 | $format = str_replace(array('{player}', '{message}'), array(C::clean($sender->getName()), $message), $this->main->chatformat); 102 | $this->main->sendMessage($chaturl, $format, 'nolog', $this->main->chatuser); 103 | } 104 | } 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /src/Niekert/DiscordMCPE/Main.php: -------------------------------------------------------------------------------- 1 | setvars(); 24 | if ($this->isDisabled()) { 25 | return; 26 | } 27 | if ($this->pp) { 28 | if ($this->getServer()->getPluginManager()->getPlugin('PurePerms') !== null) { 29 | $this->getLogger()->info('PurePerms Compatibility Enabled!'); 30 | } else { 31 | $this->getLogger()->alert('PurePerms Compatibility Enabled, but PurePerms could not be found!'); 32 | $this->getLogger()->alert('Edit your settings in config.yml!'); 33 | $this->getServer()->getPluginManager()->disablePlugin($this); 34 | return false; 35 | } 36 | } 37 | $this->getServer()->getPluginManager()->registerEvents(new EventListener($this), $this); 38 | if ($this->getConfig()->get('start_message') !== '0') { 39 | $this->sendMessage($this->webhook, $this->startupopt, 'CONSOLE'); 40 | } 41 | } 42 | 43 | public function onDisable() 44 | { 45 | if ($this->shutdownopt !== '0' AND !$this->isEnabled()) { 46 | $this->sendMessage($this->webhook, $this->shutdownopt); 47 | } 48 | } 49 | 50 | /** 51 | * @param CommandSender $sender 52 | * @param Command $cmd 53 | * @param string $label 54 | * @param array $args 55 | * @return bool 56 | */ 57 | public function onCommand(CommandSender $sender, Command $cmd, string $label, array $args): bool 58 | { 59 | if ($cmd->getName() == 'discord') { 60 | if ($this->commandopt) { 61 | $ppa = $this->getServer()->getPluginManager()->getPlugin('PurePerms'); 62 | if (!isset($args[0])) { 63 | $sender->sendMessage(C::RED . 'Please provide an argument! Usage: /discord (message).'); 64 | } elseif ($this->pp) { 65 | if ($sender instanceof Player) { 66 | $format = str_replace(['{rank}', '{player}', '{message}'], [C::clean($ppa->getUserDataMgr()->getGroup($sender)), $sender->getName(), implode(' ', $args)], $this->chatformat); 67 | $this->sendMessage($this->chaturl, $format, $sender->getName(), $this->chatuser); 68 | } else { 69 | $this->getLogger()->notice('You cannot execute this command as console!'); 70 | } 71 | } else { 72 | $format = str_replace(['{player}', '{message}'], [C::clean($sender->getName()), implode(' ', $args)], $this->chatformat); 73 | $this->sendMessage($this->chaturl, $format, $sender->getName(), $this->chatuser); 74 | } 75 | } else { 76 | $sender->sendMessage(C::RED . 'Sorry, but the owner disabled this option.'); 77 | } 78 | } 79 | return true; 80 | } 81 | 82 | private function setvars() 83 | { 84 | $this->saveDefaultConfig(); 85 | if (key_exists('Version', $this->getConfig()->getAll())) { 86 | if ($this->configversion !== $this->getConfig()->get('Version')) { 87 | $this->getLogger()->critical('Please update your config!'); 88 | $this->setEnabled(false); 89 | return; 90 | } 91 | } else { 92 | $this->getLogger()->critical('Please update your config!'); 93 | $this->setEnabled(false); 94 | return; 95 | } 96 | foreach ($this->getConfig()->getAll() as $item) { 97 | if (!isset($item) OR $item === '') { 98 | $this->getLogger()->info('Please edit your config!'); 99 | $this->setEnabled(false); 100 | return; 101 | } 102 | } 103 | $this->reloadConfig(); 104 | $this->webhook = $this->getConfig()->get('webhook_url'); 105 | $this->username = $this->getConfig()->get('username'); 106 | $this->startupopt = $this->getConfig()->get('start_message'); 107 | $this->shutdownopt = $this->getConfig()->get('shutdown_message'); 108 | $this->joinopt = $this->getConfig()->get('join_message'); 109 | $this->quitopt = $this->getConfig()->get('quit_message'); 110 | $this->deathopt = $this->getConfig()->get('death_message'); 111 | $this->debugopt = $this->getConfig()->get('debug'); 112 | $this->commandopt = $this->getConfig()->get('command'); 113 | $this->chatformat = $this->getConfig()->get('chat_format'); 114 | $this->chatprefix = $this->getConfig()->get('chat_prefix'); 115 | $this->chatopt = $this->getConfig()->get('chat'); 116 | $this->pp = $this->getConfig()->get('pureperms'); 117 | 118 | //Some statements 119 | if ($this->getConfig()->get('chat_username') === '0') { 120 | $this->chatuser = $this->username; 121 | } elseif ($this->getConfig()->get('chat_username') !== '0') { 122 | $this->chatuser = $this->getConfig()->get('chat_username'); 123 | } 124 | if ($this->getConfig()->get('chat_url') === '0') { 125 | $this->chaturl = $this->webhook; 126 | } elseif ($this->getConfig()->get('chat_url') !== '0') { 127 | $this->chaturl = $this->getConfig()->get('chat_url'); 128 | } 129 | } 130 | 131 | /** 132 | * @param $player 133 | * @param $result 134 | */ 135 | public function notify($player, $result) 136 | { 137 | if ($player === 'nolog') { 138 | return; 139 | } elseif ($player === 'CONSOLE') { 140 | $player = new ConsoleCommandSender(); 141 | } else { 142 | $playerinstance = $this->getServer()->getPlayerExact($player); 143 | if ($playerinstance === null) { 144 | return; 145 | } else { 146 | $player = $playerinstance; 147 | } 148 | } 149 | if ($result['success']) { 150 | $player->sendMessage(C::AQUA . '[Discord-MCPE] ' . C::GREEN . 'Discord message was sent!'); 151 | } else { 152 | if ($this->getConfig()->get('debug')) { 153 | $this->getLogger()->error(C::RED . 'Error: ' . $result['Error']); 154 | } else { 155 | $this->getLogger()->warning(C::RED . 'Something strange happened. Set debug in config to true to get error message'); 156 | } 157 | $player->sendMessage(C::AQUA . '[Discord-MCPE] ' . C::GREEN . 'Discord message wasn\'t sent!'); 158 | } 159 | } 160 | 161 | /** 162 | * @param $webhook 163 | * @param $message 164 | * @param string $player 165 | * @param null $username 166 | */ 167 | public function sendMessage($webhook, $message, string $player = 'nolog', $username = null) 168 | { 169 | if (!isset($username)) { 170 | $username = $this->username; 171 | } 172 | $curlopts = [ 173 | 'content' => $message, 174 | 'username' => $username 175 | ]; 176 | $this->getServer()->getAsyncPool()->submitTask(new Tasks\SendTaskAsync($player, $webhook, serialize($curlopts))); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BoxOfDevs General Software License 1.1.3 2 | ========================================= 3 | This license is designed to be used with any software which would like to have no selling for profits, nor any public redistribution without giving the original author credits. 4 | -------------------------------------------------------------------------------------------------------------------------------------- 5 | The License: refers to the BoxOfDevs International Software License 1.1.2 6 | The Software: refers to any works licensed under The License. 7 | The Modification: refers to any modified version of The Software. 8 | The Redistribution: refers to any redistributions of The Software/The Modification. 9 | The User: refers to any user of The Software licensed under The License. 10 | The Author: refers to any developer, organisation, legal owner, or creator of The Software that has been licensed under the The License. 11 | -------------------------------------------------------------------------------------------------------------------------------------- 12 | Section 1 - Allowances: 13 | 14 | 1. Both The User & The Author Can: 15 | a. Modify private copies of The Software and use in any way they wish. 16 | b. Change which license The Software/The Modification is licensed under. 17 | 18 | 2. The User Can: 19 | a. Request new features, support, or more rights from The Author. 20 | b. Redistribute The Software/The Modification, ensuring The User gives all appropriate credit to The Author and alerting The Author to The Redistribution. 21 | 22 | 3. The Author Can: 23 | a. Change or update The Software in any way they wish, ensuring they follow the other terms of The License. 24 | b. Grant extra rights to The User who has requested them. 25 | c. Reserve the right to request The User to take down their instance of The Software/The Modification/The Redistribution. 26 | 27 | Section 2 - Restrictions: 28 | 1. Both The User & The Author Cannot: 29 | a. Introduce any malicious code into The Software/The Modification. 30 | b. Sell any part of The Software/The Modification for profit. 31 | 32 | 2. The User Cannot: 33 | a. Hold The Author responsible for any unknown errors. 34 | b. Claim The Software/The Modification/The Redistribution as entirely The User's product. 35 | c. Use the software without crediting the Author. 36 | 37 | 3. The Author Cannot: 38 | a. Restrict The User in any way not specified by The License. 39 | b. Distribute any form of The Software without proper documentation. 40 | 41 | Term. The term of this License is specified in Section 6(a). 42 | Media and formats; technical modifications allowed. The Author authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Author waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this License, simply making modifications authorized by this Section 2(a)(4) never produces Modification. 43 | 44 | Downstream recipients. 45 | Offer from the Author – Software. Every recipient of the Software automatically receives an offer from the Author to exercise the Licensed Rights under the terms and conditions of this License. 46 | Additional offer from the Author – the Modification. Every recipient of the Modification from You automatically receives an offer from the Author to exercise the Licensed Rights in the Modification under the conditions of the Adapter’s License You apply. 47 | No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Software if doing so restricts exercise of the Licensed Rights by any recipient of the Software. 48 | No endorsement. Nothing in this License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Software is, connected with, or sponsored, endorsed, or granted official status by, the Author or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). 49 | 50 | Other rights. 51 | Moral rights, such as the right of integrity, are not licensed under this License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Author waives and/or agrees not to assert any such rights held by the Author to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 52 | Patent and trademark rights are not licensed under this License. 53 | To the extent possible, the Author waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Author expressly reserves any right to collect such royalties. 54 | 55 | Section 3 – License Conditions. 56 | Your exercise of the Licensed Rights is expressly made subject to the following conditions. 57 | 58 | a) Attribution. 59 | If You Share the Software (including in modified form), You must: 60 | retain the following if it is supplied by the Author with the Software: 61 | identification of the creator(s) of the Software and any others designated to receive attribution, in any reasonable manner requested by the Author (including by pseudonym if designated); 62 | a copyright notice; 63 | a notice that refers to this License; 64 | a notice that refers to the disclaimer of warranties; 65 | a URI or hyperlink to the Software to the extent reasonably practicable; 66 | indicate if You modified the Software and retain an indication of any previous modifications; and 67 | indicate the Software is licensed under this License, and include the text of, or the URI or hyperlink to, this License. 68 | You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Software. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 69 | If requested by the Author, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 70 | 71 | b) ShareAlike. 72 | In addition to the conditions in Section 3(a), if You Share the Modification You produce, the following conditions also apply. 73 | The Adapter’s License You apply must be a BoxOfDevs General License with the same License Elements, this version or later, or a BY-SA Compatible License. 74 | You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share the Modification. 75 | You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Modification that restrict exercise of the rights granted under the Adapter's License You apply. 76 | 77 | c) Forever Open Source. 78 | In addition to the conditions in Section 3(a) and Section 3(b), if You Share the Modification You produce, the following conditions also apply. 79 | The Adapted work must have an open source existing repertory, accessible by anyone anytime linked in the Redistribution Description/Documentation. 80 | You may not restrict anyone from accessing the source code, use it, and redistribute it under anything not explicily specified by the License. 81 | 82 | d) Free. 83 | In addition to the conditions in Section 3(a), Section 3(b) and Section 3(c), if You Share by any way Modification and/or the Software You produce, the following conditions also apply. 84 | The Work must be redistributed entirely free, under this license. 85 | You may not impose fees to anyone that gets the Modification/The Software. 86 | 87 | 88 | Section 4 – Sui Generis Database Rights. 89 | Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Software: 90 | 91 | for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; 92 | if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Modification, including for purposes of Section 3(b); and 93 | You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. 94 | 95 | For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this License where the Licensed Rights include other Copyright and Similar Rights. 96 | 97 | Section 5 – Disclaimer of Warranties and Limitation of Liability. 98 | 99 | Unless otherwise separately undertaken by the Author, to the extent possible, the Author offers the Software as-is and as-available, and makes no representations or warranties of any kind concerning the Software, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. 100 | To the extent possible, in no event will the Author be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this License or use of the Software, even if the Author has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. 101 | 102 | The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. 103 | 104 | Section 6 – Term and Termination. 105 | This License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this License, then Your rights under this License terminate automatically. 106 | 107 | Where Your right to use the Software has terminated under Section 6(a), it reinstates: 108 | automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 109 | upon express reinstatement by the Author. 110 | For the avoidance of doubt, this Section 6(b) does not affect any right the Author may have to seek remedies for Your violations of this License. 111 | For the avoidance of doubt, the Author may also offer the Software under separate terms or conditions or stop distributing the Software at any time; however, doing so will not terminate this License. 112 | Sections 1, 5, 6, 7, and 8 survive termination of this License. 113 | 114 | Section 7 – Other Terms and Conditions. 115 | 116 | The Author shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. 117 | Any arrangements, understandings, or agreements regarding the Software not stated herein are separate from and independent of the terms and conditions of this License. 118 | In the event that The License is updated/changed on the official github repository/on the official website, you automatically agree. 119 | The Author is not required to notify The User that The License has been updated/changed. 120 | 121 | Section 8 – Interpretation. 122 | For the avoidance of doubt, this License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Software that could lawfully be made without permission under this License. 123 | 124 | To the extent possible, if any provision of this License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this License without affecting the enforceability of the remaining terms and conditions. 125 | No term or condition of this License will be waived and no failure to comply consented to unless expressly agreed to by the Author. 126 | Nothing in this License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Author or You, including from the legal processes of any jurisdiction or authority. 127 | --------------------------------------------------------------------------------