├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── examples ├── currentTrack.php ├── getFiles.php └── renameInstance.php └── src ├── API.php ├── File.php ├── Folder.php ├── Instance.php ├── Playlist.php ├── RestClient.php ├── User.php └── autoload.php /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | before_script: 3 | - cd $TRAVIS_BUILD_DIR 4 | - composer self-update 5 | - composer install --no-interaction 6 | script: 7 | - cd $TRAVIS_BUILD_DIR 8 | - ./vendor/bin/phpcs --standard=PSR2 src 9 | - ./vendor/bin/phpcbf --standard=PSR2 src 10 | - php vendor/bin/phpdoc -d src -t docs --ignore vendor/,docs/,examples/ 11 | # add the SinusBot favicon 12 | - wget -q -O docs/images/favicon.ico https://sinusbot.github.io/favicon.ico 13 | deploy: 14 | provider: pages 15 | github-token: $GITHUB_TOKEN 16 | skip-cleanup: true 17 | local-dir: docs 18 | on: 19 | branch: master 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SinusBot API PHP Class 2 | 3 | [![Build Status](https://travis-ci.org/SinusBot/api-php.svg?branch=master)](https://travis-ci.org/SinusBot/api-php) 4 | [![Packagist](https://img.shields.io/packagist/v/sinusbot/sinusbot-api-php.svg)](https://packagist.org/packages/sinusbot/sinusbot-api-php) 5 | 6 | > PHP Wrapper to communicate with the [SinusBot API](https://www.sinusbot.com/api/). 7 | 8 | ## Usage 9 | 10 | ### via Composer 11 | 12 | ```bash 13 | composer require sinusbot/sinusbot-api-php 14 | ``` 15 | 16 | Require the composer's `autoload.php` in the top of your `php` file: 17 | 18 | ```php 19 | require __DIR__ . '/vendor/autoload.php'; 20 | ``` 21 | 22 | Then you can use the SinusBot API via the `SinusBot\API` class. 23 | 24 | ### via Source 25 | 26 | Download and extract the latest release [here](https://github.com/SinusBot/api-php/releases/latest). Rename the folder to `sinusbot`, after that require the `autoload.php`: 27 | 28 | ```php 29 | require __DIR__ . '/sinusbot/src/autoload.php'; 30 | ``` 31 | 32 | Then you can use the SinusBot API via the `SinusBot\API` class. 33 | 34 | ## Examples 35 | 36 | There are a few examples located in the [examples](examples/) directory. 37 | 38 | ## Documentation 39 | 40 | A complete list of methods can be found in the [documenation](https://sinusbot.github.io/api-php). 41 | 42 | ## Compatibility 43 | 44 | It's compatible with the consumer and hosting version of the SinusBot. 45 | 46 | ## Copyright 47 | 48 | This libary was originally created by [Manuel Hettche](https://github.com/marburger93) from [TS3index](https://ts3index.com). 49 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sinusbot/sinusbot-api-php", 3 | "type": "library", 4 | "description": "PHP Wrapper to communicate with the SinusBot API.", 5 | "keywords": [ 6 | "php", 7 | "sinusbot", 8 | "api", 9 | "http" 10 | ], 11 | "homepage": "https://github.com/SinusBot/api-php", 12 | "license": "GPL-2.0", 13 | "authors": [ 14 | {"name": "Max Schmitt", "email": "max@schmitt.mx"}, 15 | {"name": "Manuel Hettche", "email": "info@ts3index.com"} 16 | ], 17 | "require-dev": { 18 | "phpdocumentor/phpdocumentor": "2.*", 19 | "squizlabs/php_codesniffer": "3.*" 20 | }, 21 | "autoload": { 22 | "psr-4": { 23 | "SinusBot\\": "src/" 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /examples/currentTrack.php: -------------------------------------------------------------------------------- 1 | login("admin", "foobar"); 7 | 8 | $instances = $sinusbot->getInstances(); 9 | 10 | foreach ($instances as $instance) { 11 | $isPlaying = $instance->isPlaying(); 12 | if ($isPlaying) { 13 | echo "Instance: ".$instance->getNick()." is playing"; 14 | } else { 15 | echo "Instance: ".$instance->getNick()." is not playing"; 16 | } 17 | echo "\n"; 18 | } 19 | ?> 20 | -------------------------------------------------------------------------------- /examples/getFiles.php: -------------------------------------------------------------------------------- 1 | login("admin", "foobar"); 7 | 8 | $files = $sinusbot->getFiles(); 9 | 10 | function return_if_exists($key, $arr) { 11 | if (array_key_exists($key, $arr)) { 12 | return $arr[$key]; 13 | } 14 | return "-"; 15 | } 16 | 17 | foreach ($files as $file) { 18 | echo "uuid: ".$file['uuid'].' artist: '.return_if_exists("artist", $file).' title: '.return_if_exists("title", $file)." album: ".(array_key_exists("album", $file)?("(".$file['album'].")"):"")."\n"; 19 | } 20 | ?> 21 | -------------------------------------------------------------------------------- /examples/renameInstance.php: -------------------------------------------------------------------------------- 1 | login("admin", "foobar"); 7 | 8 | $instances = $sinusbot->getInstances(); 9 | 10 | $instance = $instances[0]; 11 | 12 | $settings = $instance->getSettings(); 13 | 14 | $settings["name"] = $settings["nick"]." changed by php"; 15 | 16 | $instance->setSettings($settings); 17 | -------------------------------------------------------------------------------- /src/API.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | 11 | namespace SinusBot; 12 | 13 | /** 14 | * Class API 15 | * 16 | * API is the main class which will be used to connect to the SinusBot 17 | */ 18 | class API extends RestClient 19 | { 20 | /** 21 | * UUID stores the SinusBot Bot UUID 22 | * @var string 23 | */ 24 | public $uuid = null; 25 | /** 26 | * __construct 27 | * 28 | * @param string $url SinusBot Bot URL 29 | * @param string $timeout HTTP Timeout which is used to perform HTTP API requests 30 | * @return void 31 | */ 32 | public function __construct($url = 'http://127.0.0.1:8087', $timeout = 8000) 33 | { 34 | $this->url = $url; 35 | $this->timeout = $timeout; 36 | } 37 | 38 | /** 39 | * login logs on to the SinusBot and retrieves the token 40 | * 41 | * @param string $username SinusBot username 42 | * @param string $password SinusBot password 43 | * @param string $uuid SinusBot Bot UUID 44 | * @return boolean success 45 | */ 46 | public function login($username, $password, $uuid = null) 47 | { 48 | $this->uuid = !$uuid?$this->getDefaultBot():$uuid; 49 | $login = $this->request('/bot/login', 'POST', [ 50 | 'username' => $username, 51 | 'password' => $password, 52 | 'botId' => $this->uuid, 53 | ]); 54 | if ($login != null and isset($login['token'])) { 55 | $this->token = $login['token']; 56 | } 57 | return $login['success']; 58 | } 59 | 60 | /** 61 | * getFiles returns the files for the user account 62 | * 63 | * @return array files 64 | */ 65 | public function getFiles() 66 | { 67 | $files = $this->request('/bot/files'); 68 | $out = []; 69 | $todo = []; 70 | foreach ($files as $file) { 71 | if ($file["parent"] === "") { 72 | if ($file["type"] === "folder") { 73 | array_push($out, new Folder($this, $file)); 74 | } else { 75 | array_push($out, new File($this, $file)); 76 | } 77 | } else { 78 | array_push($todo, $file); 79 | } 80 | } 81 | foreach ($out as $o) { 82 | if ($o->getType() === "folder") { 83 | foreach ($todo as $key => $t) { 84 | $curr = null; 85 | if ($file["type"] === "folder") { 86 | $curr = new Folder($this, $t); 87 | } else { 88 | $curr = new File($this, $t); 89 | } 90 | if ($o->addChildrenIfOK($curr)) { 91 | unset($todo[$key]); 92 | } 93 | } 94 | } 95 | } 96 | if (count($todo) !== 0) { 97 | throw new \Exception('Invalid parent'); 98 | } 99 | return $out; 100 | } 101 | 102 | /** 103 | * getRadioStations returns the imported radio stations 104 | * 105 | * @param string $search optional name of the search query 106 | * @return array radio stations 107 | */ 108 | public function getRadioStations($search = "") 109 | { 110 | return $this->request('/bot/stations?q='.urlencode($search)); 111 | } 112 | 113 | /** 114 | * getInfo returns the bot infos 115 | * 116 | * @return array bot infos 117 | */ 118 | public function getInfo() 119 | { 120 | return $this->request('/bot/info'); 121 | } 122 | 123 | /** 124 | * getPlaylists returns the playlists 125 | * 126 | * @return array playlists 127 | */ 128 | public function getPlaylists() 129 | { 130 | $playlists = $this->request('/bot/playlists'); 131 | $out = []; 132 | foreach ($playlists as $playlist) { 133 | array_push($out, new Playlist($this, $playlist)); 134 | } 135 | return $out; 136 | } 137 | 138 | /** 139 | * createPlaylist creates a new playlist 140 | * 141 | * @param string $playlistName name of the playlist 142 | * @return array status 143 | */ 144 | public function createPlaylist($playlistName) 145 | { 146 | $resp = $this->request('/bot/playlists', 'POST', [ 147 | "name" => $playlistName, 148 | ]); 149 | $resp['name'] = $playlistName; 150 | return new Playlist($this, $resp); 151 | } 152 | 153 | /** 154 | * importPlaylist imports a new playlist from youtube-dl 155 | * 156 | * @param string $url youtube-dl URL 157 | * @return array status 158 | */ 159 | public function importPlaylist($url) 160 | { 161 | return $this->request('/bot/playlists', 'POST', [ 162 | "importFrom" => $url, 163 | ]); 164 | } 165 | 166 | /** 167 | * addURL 168 | * 169 | * @param string $url stream URL 170 | * @param string $title track title 171 | * @param string $parent subfolder UUID, empty value means root folder 172 | * @return array status 173 | */ 174 | public function addURL($url, $title, $parent = "") 175 | { 176 | return $this->request('/bot/url', 'POST', [ 177 | "url" => $url, 178 | "title" => $title, 179 | "parent" => $parent, 180 | ]); 181 | } 182 | 183 | /** 184 | * addFolder 185 | * 186 | * @param string $folderName folder name 187 | * @param string $parent subfolder UUID, empty value means root folder 188 | * @return array status 189 | */ 190 | public function addFolder($folderName = "Folder", $parent = "") 191 | { 192 | return $this->request('/bot/folders', 'POST', [ 193 | "name" => $folderName, 194 | "parent" => $parent, 195 | ]); 196 | } 197 | 198 | /** 199 | * moveFolder 200 | * 201 | * @param string $folderUUID folder uuid 202 | * @param string $parent subfolder UUID, empty value means root folder 203 | * @return array status 204 | */ 205 | public function moveFolder($folderUUID, $parent = "") 206 | { 207 | return $this->moveTrack($folderUUID, $parent); 208 | } 209 | 210 | /** 211 | * renameFolder 212 | * 213 | * @param string $folderName Folder name 214 | * @param string $folderUUID uuid of the folder 215 | * @return array status 216 | */ 217 | public function renameFolder($folderName, $folderUUID) 218 | { 219 | return $this->request('/bot/files/'.$folderUUID, 'PATCH', [ 220 | "uuid" => $folderUUID, 221 | "type" => "folder", 222 | "title" => $folderName, 223 | ]); 224 | } 225 | 226 | /** 227 | * getJobs 228 | * 229 | * @return array 230 | */ 231 | public function getJobs() 232 | { 233 | return $this->request('/bot/jobs'); 234 | } 235 | 236 | /** 237 | * addJob 238 | * 239 | * @param string $URL {YouTube-URL, SoundCloud-URL, Directfile} 240 | * @return array status 241 | */ 242 | public function addJob($URL) 243 | { 244 | return $this->request('/bot/jobs', 'POST', [ 245 | 'url'=>$URL, 246 | ]); 247 | } 248 | 249 | /** 250 | * deleteJob 251 | * 252 | * @param string $jobUUID job uuid 253 | * @return array status 254 | */ 255 | public function deleteJob($jobUUID) 256 | { 257 | return $this->request('/bot/jobs/'.$jobUUID, 'DELETE'); 258 | } 259 | 260 | /** 261 | * deleteFinishedJobs 262 | * 263 | * @return array status 264 | */ 265 | public function deleteFinishedJobs() 266 | { 267 | return $this->request('/bot/jobs', 'DELETE'); 268 | } 269 | 270 | /** 271 | * uploadTrack 272 | * 273 | * @param string $path /var/www/song.mp3 274 | * @return array status 275 | */ 276 | public function uploadTrack($path) 277 | { 278 | return $this->request('/bot/upload', 'POST', file_get_contents($path)); 279 | } 280 | 281 | /** 282 | * getUsers 283 | * 284 | * @return User[] users 285 | */ 286 | public function getUsers() 287 | { 288 | $users = $this->request('/bot/users'); 289 | $out = []; 290 | foreach ($users as $user) { 291 | array_push($out, new User($this, $user)); 292 | } 293 | return $out; 294 | } 295 | 296 | /** 297 | * addUser 298 | * 299 | * @param string $username Username 300 | * @param string $password Password 301 | * @param integer $privileges Bitmask-Value 302 | * @return User user object 303 | */ 304 | public function addUser($username, $password, $privileges = 0) 305 | { 306 | $this->request('/bot/users', 'POST', [ 307 | 'username'=>$username, 308 | 'password'=>$password, 309 | 'privileges'=>$privileges, 310 | ]); 311 | $users = $this->getUsers(); 312 | foreach ($users as $user) { 313 | if ($user->getName() === $username) { 314 | return $user; 315 | } 316 | } 317 | } 318 | 319 | /** 320 | * getUserByUUID 321 | * 322 | * @param string $uuid User ID 323 | * @return User user object 324 | */ 325 | public function getUserByUUID($uuid) 326 | { 327 | $users = $this->getUsers(); 328 | foreach ($users as $user) { 329 | if ($user->getUUID() === $uuid) { 330 | return $user; 331 | } 332 | } 333 | } 334 | 335 | /** 336 | * getUserByName 337 | * 338 | * @param string $username Username 339 | * @return User user object 340 | */ 341 | public function getUserByName($username) 342 | { 343 | $users = $this->getUsers(); 344 | foreach ($users as $user) { 345 | if ($user->getName() === $username) { 346 | return $user; 347 | } 348 | } 349 | } 350 | 351 | /** 352 | * getInstances 353 | * 354 | * @return []Instance 355 | * @api 356 | */ 357 | public function getInstances() 358 | { 359 | $instances = $this->request('/bot/instances'); 360 | $out = []; 361 | foreach ($instances as $instance) { 362 | array_push($out, new Instance($this, $instance)); 363 | } 364 | return $out; 365 | } 366 | 367 | /** 368 | * createInstance 369 | * 370 | * @param string $nickname Name of the Bot 371 | * @param string $backend SinusBot backend (Discord or TS³) 372 | * @return array status 373 | */ 374 | public function createInstance($nickname = "SinusBot MusicBot", $backend = "ts3") 375 | { 376 | $resp = $this->request('/bot/instances', 'POST', [ 377 | "backend" => $backend, 378 | "nick" => $nickname, 379 | ]); 380 | return $this->getInstanceByUUID($resp['uuid']); 381 | } 382 | 383 | /** 384 | * getDefaultBot 385 | * 386 | * @return string 387 | */ 388 | public function getDefaultBot() 389 | { 390 | $req = $this->request('/botId'); 391 | return (isset($req['defaultBotId'])) ? $req['defaultBotId'] : null; 392 | } 393 | 394 | /** 395 | * getBotLog 396 | * 397 | * @return array log 398 | */ 399 | public function getBotLog() 400 | { 401 | return $this->request('/bot/log'); 402 | } 403 | 404 | /** 405 | * getInstanceByUUID 406 | * 407 | * @param string $uuid SinusBot instance UUID 408 | * @return Instance 409 | */ 410 | public function getInstanceByUUID($uuid) 411 | { 412 | $instance = $this->request("/bot/i/".$uuid."/settings"); 413 | $instance['uuid'] = $uuid; 414 | return new Instance($this, $instance); 415 | } 416 | } 417 | -------------------------------------------------------------------------------- /src/File.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | 11 | namespace SinusBot; 12 | 13 | /** 14 | * Class File 15 | * 16 | * File represents a single File of the SinusBot 17 | */ 18 | class File extends RestClient 19 | { 20 | /** 21 | * UUID holds the File UUID 22 | * @var array 23 | */ 24 | public $uuid = null; 25 | /** 26 | * File stores the initial received file data 27 | * @var array 28 | */ 29 | private $file = null; 30 | /** 31 | * __construct 32 | * 33 | * @param API $api SinusBot API 34 | * @param array $file SiusBot File array 35 | */ 36 | public function __construct($api, $file) 37 | { 38 | parent::__construct($api); 39 | $this->uuid = $file['uuid']; 40 | $this->file = $file; 41 | } 42 | 43 | /** 44 | * getTitle returns the title 45 | * 46 | * @return string filename 47 | * @api 48 | */ 49 | public function getTitle() 50 | { 51 | return array_key_exists('title', $this->file)?$this->file['title']:$this->file["filename"]; 52 | } 53 | 54 | /** 55 | * getUUID returns the uuid 56 | * 57 | * @return string file UUID 58 | * @api 59 | */ 60 | public function getUUID() 61 | { 62 | return $this->uuid; 63 | } 64 | 65 | /** 66 | * getType returns the file type 67 | * 68 | * @return string type: url, folder 69 | * @api 70 | */ 71 | public function getType() 72 | { 73 | return array_key_exists('type', $this->file)?$this->file['type']:''; 74 | } 75 | 76 | /** 77 | * getArtist returns the artist 78 | * 79 | * @return string file UUID 80 | * @api 81 | */ 82 | public function getArtist() 83 | { 84 | return array_key_exists('artist', $this->file)?$this->file['artist']:''; 85 | } 86 | 87 | /** 88 | * getUUID returns the uuid 89 | * 90 | * @return string file UUID 91 | * @api 92 | */ 93 | public function getParent() 94 | { 95 | return $this->file["parent"]; 96 | } 97 | 98 | /** 99 | * delete 100 | * 101 | * @return array status 102 | * @api 103 | */ 104 | public function delete() 105 | { 106 | return $this->request('/bot/files/'.$this->uuid, 'DELETE'); 107 | } 108 | 109 | /** 110 | * getThumbnail 111 | * 112 | * @return string url 113 | */ 114 | public function getThumbnail() 115 | { 116 | return array_key_exists('thumbnail', $this->file)?$this->url.'/cache/'.$this->file["thumbnail"]:null; 117 | } 118 | 119 | 120 | /** 121 | * edit 122 | * 123 | * @param Array $options - keys: displayTitle, title, artist, album... 124 | * @return array status 125 | * @api 126 | */ 127 | public function edit($options) 128 | { 129 | return $this->request('/bot/files/'.$this->uuid, 'PATCH', $options); 130 | } 131 | 132 | /** 133 | * move 134 | * 135 | * @param string $parent subfolder UUID, empty value means root folder 136 | * @return array status 137 | */ 138 | public function move($parent = "") 139 | { 140 | return $this->request('/bot/files/'.$this->uuid, 'PATCH', [ 141 | "parent" => $parent, 142 | ]); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/Folder.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | 11 | namespace SinusBot; 12 | 13 | /** 14 | * Class Folder 15 | * 16 | * Folder represents a single Folder of the SinusBot 17 | */ 18 | class Folder extends RestClient 19 | { 20 | /** 21 | * UUID holds the Folder UUID 22 | * @var array 23 | */ 24 | public $uuid = null; 25 | /** 26 | * Folder stores the initial received folder data 27 | * @var array 28 | */ 29 | private $folder = null; 30 | /** 31 | * Children stores the folder childrens 32 | * @var array 33 | */ 34 | private $children = []; 35 | /** 36 | * __construct 37 | * 38 | * @param API $api SinusBot API 39 | * @param array $folder SiusBot Folder array 40 | */ 41 | public function __construct($api, $folder) 42 | { 43 | parent::__construct($api); 44 | $this->uuid = $folder['uuid']; 45 | $this->folder = $folder; 46 | } 47 | 48 | /** 49 | * getTitle returns the title 50 | * 51 | * @return string foldername 52 | * @api 53 | */ 54 | public function getTitle() 55 | { 56 | return $this->folder['title']; 57 | } 58 | 59 | /** 60 | * getType returns the file type 61 | * 62 | * @return string type: url, folder 63 | * @api 64 | */ 65 | public function getType() 66 | { 67 | return array_key_exists('type', $this->folder)?$this->folder['type']:''; 68 | } 69 | 70 | /** 71 | * getUUID returns the uuid 72 | * 73 | * @return string folder UUID 74 | * @api 75 | */ 76 | public function getUUID() 77 | { 78 | return $this->uuid; 79 | } 80 | 81 | /** 82 | * getUUID returns the uuid 83 | * 84 | * @return string folder UUID 85 | * @api 86 | */ 87 | public function getParent() 88 | { 89 | return $this->folder["parent"]; 90 | } 91 | 92 | /** 93 | * addChildrenIfOK checks recursive if the given file should be 94 | * added as a child element. Determined via the "parent" attribute 95 | * 96 | * @return File file 97 | * @api 98 | */ 99 | public function addChildrenIfOK($file) 100 | { 101 | if ($this->getUUID()=== $file->getParent()) { 102 | array_push($this->children, $file); 103 | return true; 104 | } 105 | foreach ($this->children as $children) { 106 | if ($children->getType() === "folder") { 107 | if ($children->addChildrenIfOK($file)) { 108 | return true; 109 | } 110 | } 111 | } 112 | return false; 113 | } 114 | 115 | /** 116 | * getChildren returns the children of the folder 117 | * 118 | * @return (\File|\Folder)[] 119 | * @api 120 | */ 121 | public function getChildren() 122 | { 123 | return $this->children; 124 | } 125 | 126 | /** 127 | * delete 128 | * 129 | * @return array status 130 | * @api 131 | */ 132 | public function delete() 133 | { 134 | return $this->request('/bot/files/'.$this->uuid, 'DELETE'); 135 | } 136 | 137 | /** 138 | * edit 139 | * 140 | * @param Array $options - keys: displayTitle, title, artist, album... 141 | * @return array status 142 | * @api 143 | */ 144 | public function edit($options) 145 | { 146 | return $this->request('/bot/files/'.$this->uuid, 'PATCH', $options); 147 | } 148 | 149 | /** 150 | * move 151 | * 152 | * @param string $parent subfolder UUID, empty value means root folder 153 | * @return array status 154 | */ 155 | public function move($parent = "") 156 | { 157 | return $this->request('/bot/files/'.$this->uuid, 'PATCH', [ 158 | "parent" => $parent, 159 | ]); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/Instance.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | 11 | namespace SinusBot; 12 | 13 | /** 14 | * Class Instance 15 | * 16 | * Instance represents a single instance of the SinusBot 17 | */ 18 | class Instance extends RestClient 19 | { 20 | /** 21 | * UUID stores the SinusBot Instance UUID 22 | * @var string 23 | */ 24 | public $uuid = null; 25 | /** 26 | * Instance stores the initial received instance data 27 | * @var array 28 | */ 29 | private $instance = null; 30 | /** 31 | * __construct 32 | * 33 | * @param API $api SinusBot API 34 | * @param array $instance SinusBot Instance array 35 | * @return void 36 | */ 37 | public function __construct($api, $instance) 38 | { 39 | parent::__construct($api); 40 | $this->uuid = $instance['uuid']; 41 | $this->instance = $instance; 42 | } 43 | /** 44 | * isPlaying returns true when the instance is playing something 45 | * 46 | * @return boolean 47 | */ 48 | public function isPlaying() 49 | { 50 | return $this->instance['playing']; 51 | } 52 | 53 | /** 54 | * isRunning returns true when the instance is running 55 | * 56 | * @return boolean 57 | */ 58 | public function isRunning() 59 | { 60 | return $this->instance['running']; 61 | } 62 | 63 | /** 64 | * getBackend returns the SinusBot backend (Discord, TS³) 65 | * 66 | * @return string instance backend 67 | */ 68 | public function getBackend() 69 | { 70 | return $this->instance['backend']; 71 | } 72 | 73 | /** 74 | * getNick returns the Bot's nickname 75 | * 76 | * @return string nick 77 | */ 78 | public function getNick() 79 | { 80 | return $this->instance['nick']; 81 | } 82 | 83 | /** 84 | * getName returns the Bot's name 85 | * 86 | * @return string name 87 | */ 88 | public function getName() 89 | { 90 | return $this->instance['name']; 91 | } 92 | 93 | /** 94 | * getServerHost returns the Bot's server host 95 | * 96 | * @return string host 97 | */ 98 | public function getServerHost() 99 | { 100 | return $this->instance['serverHost']; 101 | } 102 | 103 | /** 104 | * getServerPort returns the Bot's server port 105 | * 106 | * @return string port 107 | */ 108 | public function getServerPort() 109 | { 110 | return $this->instance['serverPort']; 111 | } 112 | 113 | /** 114 | * delete deletes the instance 115 | * 116 | * @return array status 117 | */ 118 | public function delete() 119 | { 120 | return $this->request('/bot/instances/'.$this->uuid, 'DELETE'); 121 | } 122 | 123 | /** 124 | * spawn spawns the instance 125 | * 126 | * @return array status 127 | */ 128 | public function spawn() 129 | { 130 | return $this->request('/bot/i/'.$this->uuid.'/spawn', 'POST', ''); 131 | } 132 | 133 | /** 134 | * respawn restarts the instance 135 | * 136 | * @return array status 137 | */ 138 | public function respawn() 139 | { 140 | return $this->request('/bot/i/'.$this->uuid.'/respawn', 'POST', ''); 141 | } 142 | 143 | /** 144 | * kill kills the instance 145 | * 146 | * @param string $instanceUUID UUID of the SinusBot instance 147 | * @return array status 148 | */ 149 | public function kill() 150 | { 151 | return $this->request('/bot/i/'.$this->uuid.'/kill', 'POST', ''); 152 | } 153 | 154 | /** 155 | * getWebStream returns the webstream URL of the instance 156 | * 157 | * requires: EnableWebStream = true 158 | * 159 | * @param string $instanceUUID UUID of the SinusBot instance 160 | * @return string url (opus-encoded-ogg-stream) 161 | * @api 162 | */ 163 | public function getWebStream() 164 | { 165 | $token = $this->getWebStreamToken(); 166 | if ($token == null) { 167 | return null; 168 | } 169 | 170 | return $this->url.'/api/v1/b/bot/i/'.$this->uuid.'/stream/'.$token; 171 | } 172 | 173 | /** 174 | * getWebStreamToken returns the webstream token 175 | * 176 | * requires: EnableWebStream = true 177 | * 178 | * @param string $instanceUUID UUID of the SinusBot instance 179 | * @return string token 180 | * @api 181 | */ 182 | public function getWebStreamToken() 183 | { 184 | $tokenRequest = $this->request('/bot/i/'.$this->uuid.'/streamToken', 'POST', ''); 185 | return (isset($tokenRequest['token'])) ? $tokenRequest['token'] : null; 186 | } 187 | 188 | /** 189 | * getVolume returns the current volume 190 | * 191 | * @return integer 192 | * @api 193 | */ 194 | public function getVolume() 195 | { 196 | return $this->getStatus()['volume']; 197 | } 198 | 199 | /** 200 | * setVolume sets the volume to a given one 201 | * 202 | * @param string $volume {0-100} 203 | * @return array status 204 | * @api 205 | */ 206 | public function setVolume($volume = 50) 207 | { 208 | return $this->request('/bot/i/'.$this->uuid.'/volume/set/'.$volume, 'POST', ''); 209 | } 210 | 211 | /** 212 | * setVolumeUp increases the volume by 5 213 | * 214 | * @return array status 215 | * @api 216 | */ 217 | public function setVolumeUp() 218 | { 219 | return $this->request('/bot/i/'.$this->uuid.'/volume/up', 'POST', ''); 220 | } 221 | 222 | /** 223 | * setVolumeDown reduces the volume by 5 224 | * 225 | * @return array status 226 | * @api 227 | */ 228 | public function setVolumeDown() 229 | { 230 | return $this->request('/bot/i/'.$this->uuid.'/volume/down', 'POST', ''); 231 | } 232 | 233 | /** 234 | * getStatus returns the current instance status 235 | * 236 | * @return array status 237 | * @api 238 | */ 239 | public function getStatus() 240 | { 241 | return $this->request('/bot/i/'.$this->uuid.'/status'); 242 | } 243 | 244 | /** 245 | * getLog returns the instance log 246 | * 247 | * @return array log 248 | * @api 249 | */ 250 | public function getLog() 251 | { 252 | return $this->request('/bot/i/'.$this->uuid.'/log'); 253 | } 254 | 255 | /** 256 | * getSettings returns the instance settings 257 | * 258 | * @return array users 259 | * @api 260 | */ 261 | public function getSettings() 262 | { 263 | return $this->request('/bot/i/'.$this->uuid.'/settings'); 264 | } 265 | 266 | /** 267 | * setSettings updates the instance settings 268 | * 269 | * @param array $data array of properties 270 | * @return array status 271 | * @api 272 | */ 273 | public function setSettings($data) 274 | { 275 | return $this->request('/bot/i/'.$this->uuid.'/settings', 'POST', $data); 276 | } 277 | 278 | /** 279 | * getChannels returns the channels of the connected TS³ or Discord server 280 | * 281 | * @return array channels 282 | * @api 283 | */ 284 | public function getChannels() 285 | { 286 | return $this->request('/bot/i/'.$this->uuid.'/channels'); 287 | } 288 | 289 | /** 290 | * uploadAvatar uploads a avatar from a local file 291 | * 292 | * @param string $path /var/www/image.jpg 293 | * @return array status 294 | */ 295 | public function uploadAvatar($path) 296 | { 297 | return $this->request('/bot/i/'.$this->uuid.'/avatar', 'POST', file_get_contents($path), true); 298 | } 299 | 300 | /** 301 | * deleteAvatar deletes the current avatar 302 | * 303 | * @return array status 304 | */ 305 | public function deleteAvatar() 306 | { 307 | return $this->request('/bot/i/'.$this->uuid.'/avatar', 'DELETE'); 308 | } 309 | 310 | /** 311 | * getQueueTracks returns the tracks in the queue 312 | * 313 | * @return array files 314 | */ 315 | public function getQueueTracks() 316 | { 317 | return $this->request('/bot/i/'.$this->uuid.'/queue'); 318 | } 319 | 320 | /** 321 | * appendQueueTrack adds a track to the queue 322 | * 323 | * @param string $trackUUID uuid of the track 324 | * @return array status 325 | */ 326 | public function appendQueueTrack($trackUUID) 327 | { 328 | return $this->request('/bot/i/'.$this->uuid.'/queue/append/'.$trackUUID, 'POST', ""); 329 | } 330 | 331 | /** 332 | * prependQueueTrack adds a track to the beginning of the queue 333 | * 334 | * @param string $trackUUID track uuid 335 | * @return array status 336 | */ 337 | public function prependQueueTrack($trackUUID) 338 | { 339 | return $this->request('/bot/i/'.$this->uuid.'/queue/prepend/'.$trackUUID, 'POST', ""); 340 | } 341 | 342 | /** 343 | * deleteQueueTrack deletes a track in the queue 344 | * 345 | * @param integer $trackPosition first entry = 0 346 | * @return array status 347 | */ 348 | public function deleteQueueTrack($trackPosition) 349 | { 350 | $currentTracks = $this->getQueueTracks(); 351 | if ($currentTracks == null or !is_array($currentTracks)) { 352 | return null; 353 | } 354 | unset($currentTracks[$trackPosition]); 355 | 356 | return $this->request('/bot/i/'.$this->uuid.'/queue', 'PATCH', array_values($currentTracks)); 357 | } 358 | 359 | /** 360 | * deleteQueueTracks deletes all the tracks in the queue 361 | * 362 | * @return array status 363 | */ 364 | public function deleteQueueTracks() 365 | { 366 | return $this->request('/bot/i/'.$this->uuid.'/queue', 'PATCH', []); 367 | } 368 | 369 | /** 370 | * say will say the given text via the tts 371 | * 372 | * @param string $text Welcome 373 | * @param string $locale en 374 | * @return array status 375 | */ 376 | public function say($text, $locale) 377 | { 378 | return $this->request('/bot/i/'.$this->uuid.'/say', 'POST', [ 379 | "text" => $text, 380 | "locale" => $locale, 381 | ]); 382 | } 383 | 384 | /** 385 | * playTrack will play the given track 386 | * 387 | * @param string $trackUUID UUID of the track 388 | * @return array status 389 | */ 390 | public function playTrack($trackUUID) 391 | { 392 | return $this->request('/bot/i/'.$this->uuid.'/play/byId/'.$trackUUID, 'POST', ''); 393 | } 394 | 395 | /** 396 | * playURL will play the given URL 397 | * 398 | * @param string $url stream url 399 | * @return array status 400 | */ 401 | public function playURL($url) 402 | { 403 | return $this->request('/bot/i/'.$this->uuid.'/playUrl?url='.urlencode($url), 'POST', ''); 404 | } 405 | 406 | /** 407 | * playPlaylist will play the given playlist 408 | * 409 | * @param string $playlistUUID uuid of a playlist 410 | * @param string $playlistIndex 0 411 | * @return array status 412 | */ 413 | public function playPlaylist($playlistUUID, $playlistIndex = 0) 414 | { 415 | return $this->request('/bot/i/'.$this->uuid.'/play/byList/'.$playlistUUID.'/'.$playlistIndex, 'POST', ''); 416 | } 417 | 418 | /** 419 | * playPrevious will play the previous track 420 | * 421 | * @return array status 422 | */ 423 | public function playPrevious() 424 | { 425 | return $this->request('/bot/i/'.$this->uuid.'/playPrevious', 'POST', ''); 426 | } 427 | 428 | /** 429 | * playNext will play the next track 430 | * 431 | * @return array status 432 | */ 433 | public function playNext() 434 | { 435 | return $this->request('/bot/i/'.$this->uuid.'/playNext', 'POST', ''); 436 | } 437 | 438 | /** 439 | * playRepeat enables the play repeat 440 | * 441 | * @param integer $repeatState {0=disable,1=enable} 442 | * @return array status 443 | */ 444 | public function playRepeat($repeatState = 1) 445 | { 446 | return $this->request('/bot/i/'.$this->uuid.'/repeat/'.$repeatState, 'POST', ''); 447 | } 448 | 449 | /** 450 | * playShuffle enables the shuffly functionality 451 | * 452 | * @param integer $shuffleState {0=disable,1=enable} 453 | * @return array status 454 | */ 455 | public function playShuffle($shuffleState = 1) 456 | { 457 | return $this->request('/bot/i/'.$this->uuid.'/shuffle/'.$shuffleState, 'POST', ''); 458 | } 459 | 460 | /** 461 | * stop stops the playback 462 | * 463 | * @return array status 464 | */ 465 | public function stop() 466 | { 467 | return $this->request('/bot/i/'.$this->uuid.'/stop', 'POST', ''); 468 | } 469 | 470 | /** 471 | * seekPlayback seeks to a given position 472 | * 473 | * @param integer $position 0 474 | * @return array status 475 | */ 476 | public function seekPlayback($position = 0) 477 | { 478 | return $this->request('/bot/i/'.$this->uuid.'/seek/'.$position, 'POST', ''); 479 | } 480 | 481 | /** 482 | * getPlayedTracks will return the played tracks 483 | * 484 | * @return array array of uuids 485 | */ 486 | public function getPlayedTracks() 487 | { 488 | return $this->request('/bot/i/'.$this->uuid.'/recent', 'POST', ''); 489 | } 490 | 491 | /** 492 | * getCurrentTrack returns the current track which will be played 493 | * 494 | * @return File 495 | */ 496 | public function getCurrentTrack() 497 | { 498 | return new File($this, $this->getStatus()['currentTrack']); 499 | } 500 | } 501 | -------------------------------------------------------------------------------- /src/Playlist.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | 11 | namespace SinusBot; 12 | 13 | /** 14 | * Class Playlist 15 | * 16 | * Playlist represents a single Playlist of the SinusBot 17 | */ 18 | class Playlist extends RestClient 19 | { 20 | /** 21 | * UUID holds the Playlist UUID 22 | * @var array 23 | */ 24 | public $uuid = null; 25 | /** 26 | * Playlist stores the initial received playlist data 27 | * @var array 28 | */ 29 | private $playlist = null; 30 | /** 31 | * __construct 32 | * 33 | * @param API $api SinusBot API 34 | * @param array $playlist SinusBot Playlist array. 35 | * @return void 36 | */ 37 | public function __construct($api, $playlist) 38 | { 39 | parent::__construct($api); 40 | $this->uuid = $playlist['uuid']; 41 | $this->playlist = $playlist; 42 | } 43 | 44 | /** 45 | * rename renames a playlist 46 | * 47 | * @param string $playlistName new name for the playlist 48 | * @return array status 49 | */ 50 | public function rename($playlistName) 51 | { 52 | return $this->request('/bot/playlists/'.$this->uuid, 'PATCH', [ 53 | "name" => $playlistName, 54 | ]); 55 | } 56 | 57 | /** 58 | * getPlaylistTracks returns the tracks of the playlist 59 | * 60 | * @return array files 61 | */ 62 | public function getTracks() 63 | { 64 | return $this->request('/bot/playlists/'.$this->uuid); 65 | } 66 | 67 | /** 68 | * getName returns the name of the playlist 69 | * 70 | * @return string name 71 | */ 72 | public function getName() 73 | { 74 | return array_key_exists('name', $this->playlist)?$this->playlist['name']:''; 75 | } 76 | 77 | /** 78 | * getEntries returns the track entries 79 | * 80 | * @return array track entries 81 | */ 82 | public function getEntries() 83 | { 84 | return array_key_exists('entries', $this->playlist)?$this->playlist['entries']:[]; 85 | } 86 | 87 | /** 88 | * getSource returns the source of the playlist 89 | * 90 | * @return string source 91 | */ 92 | public function getSource() 93 | { 94 | return array_key_exists('source', $this->playlist)?$this->playlist['source']:''; 95 | } 96 | 97 | /** 98 | * addPlaylistTrack adds a track to the playlist 99 | * 100 | * @param string $trackUUID uuid of the track 101 | * @return array status 102 | */ 103 | public function addTrack($trackUUID) 104 | { 105 | return $this->request('/bot/playlists/'.$this->uuid, 'POST', [ 106 | "uuid" => $trackUUID, 107 | ]); 108 | } 109 | 110 | /** 111 | * deleteTrack deletes a track from the playlist 112 | * 113 | * @param integer $trackPosition first entry = 0 114 | * @return array status 115 | */ 116 | public function deleteTrack($trackPosition) 117 | { 118 | return $this->request('/bot/playlists/'.$this->uuid.'/'.$trackPosition, 'DELETE'); 119 | } 120 | 121 | /** 122 | * deleteTracks deletes all the tracks in the playlist 123 | * 124 | * @return array status 125 | */ 126 | public function deleteTracks() 127 | { 128 | $currentTracks = $this->getTracks(); 129 | if ($currentTracks == null or !is_array($currentTracks)) { 130 | return null; 131 | } 132 | 133 | return $this->request('/bot/bulk/playlist/'.$this->uuid.'/files', 'POST', [ 134 | "op" => "delete", 135 | "files" => array_keys($currentTracks['entries']), 136 | ]); 137 | } 138 | 139 | /** 140 | * delete deletes a playlist 141 | * 142 | * @return array status 143 | */ 144 | public function delete() 145 | { 146 | return $this->request('/bot/playlists/'.$this->uuid, 'DELETE'); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/RestClient.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | 11 | namespace SinusBot; 12 | 13 | /** 14 | * Class RestClient 15 | * 16 | * RestClient is used to perform the http requests to the SinusBot API 17 | */ 18 | class RestClient 19 | { 20 | /** 21 | * Timeout represents the HTTP timeout when HTTP requests to the SinusBot API are performed 22 | * @var int 23 | */ 24 | protected $timeout = null; 25 | /** 26 | * Token is the SinusBot auth token which will be there temporary stored. 27 | * @var string 28 | */ 29 | protected $token = null; 30 | /** 31 | * URL is the SinusBot URL with the port and the HTTP protocol 32 | * @var string 33 | */ 34 | protected $url = null; 35 | /** 36 | * headers are http headers which will be added on every request 37 | * @var array 38 | */ 39 | protected $headers = []; 40 | /** 41 | * __construct 42 | * 43 | * @param API $api SinusBot API 44 | */ 45 | protected function __construct($api) 46 | { 47 | $this->token = $api->token; 48 | $this->url = $api->url; 49 | $this->timeout = $api->timeout; 50 | $this->headers = $api->headers; 51 | } 52 | 53 | /** 54 | * request executes a request to the SinusBot API 55 | * 56 | * @param string $path /api/v1/ 57 | * @param string $method http method 58 | * @param string $payload http POST payload 59 | * @param boolean $encoded when not encoded it will be JSON marshalled 60 | * @return array decoded JSON response 61 | */ 62 | protected function request($path, $method = "GET", $payload = null, $encoded = false) 63 | { 64 | $ch = curl_init(); 65 | curl_setopt_array($ch, [ 66 | CURLOPT_URL => $this->url.'/api/v1'.$path, 67 | CURLOPT_HTTPHEADER => array_merge([ 68 | "Accept: application/json, text/plain, */*", 69 | "Content-Type: application/json", 70 | "Authorization: Bearer ".$this->token 71 | ], $this->headers), 72 | CURLOPT_CUSTOMREQUEST => $method, 73 | CURLOPT_RETURNTRANSFER => true, 74 | CURLOPT_SSL_VERIFYHOST => false, 75 | CURLOPT_SSL_VERIFYPEER => false, 76 | CURLOPT_TIMEOUT_MS => $this->timeout 77 | ]); 78 | if ($payload != null) { 79 | if ($encoded) { 80 | curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); 81 | } else { 82 | curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); 83 | } 84 | } 85 | $data = curl_exec($ch); 86 | $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 87 | if ($httpcode != 200 && $httpcode != 201) { 88 | throw new \Exception('Not expected http status code: '.$httpcode." (".$this->getError($httpcode).")"); 89 | } 90 | 91 | curl_close($ch); 92 | return (is_array($data)) ? $data : json_decode($data, true); 93 | } 94 | 95 | /** 96 | * addHeader adds a header to every http request 97 | * 98 | * @param string $key http header key 99 | * @param string $value http header value 100 | */ 101 | public function addHeader($key, $value) 102 | { 103 | array_push($this->headers, $key.": ".$value); 104 | } 105 | 106 | /** 107 | * setAuthToken overrides the auth token 108 | * 109 | * @param string $token Auth-Token, when you want to override 110 | */ 111 | public function setAuthToken($token) 112 | { 113 | $this->token = $token; 114 | } 115 | 116 | /** 117 | * getError returns the string representive to the given http status code 118 | * 119 | * @param integer $code http status code 120 | * @return string http status code string representive 121 | */ 122 | private function getError($code = 0) 123 | { 124 | switch ($code) { 125 | case 100: 126 | return 'Continue'; 127 | case 101: 128 | return 'Switching Protocols'; 129 | case 200: 130 | return 'OK'; 131 | case 201: 132 | return 'Created'; 133 | case 202: 134 | return 'Accepted'; 135 | case 203: 136 | return 'Non-Authoritative Information'; 137 | case 204: 138 | return 'No Content'; 139 | case 205: 140 | return 'Reset Content'; 141 | case 206: 142 | return 'Partial Content'; 143 | case 300: 144 | return 'Multiple Choices'; 145 | case 301: 146 | return 'Moved Permanently'; 147 | case 302: 148 | return 'Moved Temporarily'; 149 | case 303: 150 | return 'See Other'; 151 | case 304: 152 | return 'Not Modified'; 153 | case 305: 154 | return 'Use Proxy'; 155 | case 400: 156 | return 'Bad Request'; 157 | case 401: 158 | return 'Unauthorized'; 159 | case 402: 160 | return 'Payment Required'; 161 | case 403: 162 | return 'Forbidden'; 163 | case 404: 164 | return 'Not Found'; 165 | case 405: 166 | return 'Method Not Allowed'; 167 | case 406: 168 | return 'Not Acceptable'; 169 | case 407: 170 | return 'Proxy Authentication Required'; 171 | case 408: 172 | return 'Request Time-out'; 173 | case 409: 174 | return 'Conflict'; 175 | case 410: 176 | return 'Gone'; 177 | case 411: 178 | return 'Length Required'; 179 | case 412: 180 | return 'Precondition Failed'; 181 | case 413: 182 | return 'Request Entity Too Large'; 183 | case 414: 184 | return 'Request-URI Too Large'; 185 | case 415: 186 | return 'Unsupported Media Type'; 187 | case 500: 188 | return 'Internal Server Error'; 189 | case 501: 190 | return 'Not Implemented'; 191 | case 502: 192 | return 'Bad Gateway'; 193 | case 503: 194 | return 'Service Unavailable'; 195 | case 504: 196 | return 'Gateway Time-out'; 197 | case 505: 198 | return 'HTTP Version not supported'; 199 | default: 200 | return 'Unknown HTTP status code: ' . $code; 201 | } 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /src/User.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | 11 | namespace SinusBot; 12 | 13 | /** 14 | * Class User 15 | * 16 | * User represents a single User of the SinusBot 17 | */ 18 | class User extends RestClient 19 | { 20 | /** 21 | * UUID holds the User UUID 22 | * @var array 23 | */ 24 | public $uuid = null; 25 | /** 26 | * User stores the initial received user data 27 | * @var array 28 | */ 29 | private $user = null; 30 | /** 31 | * __construct 32 | * 33 | * @param API $api SinusBot API 34 | * @param array $user SiusBot User array 35 | */ 36 | public function __construct($api, $user) 37 | { 38 | parent::__construct($api); 39 | $this->uuid = $user['id']; 40 | $this->user = $user; 41 | } 42 | 43 | /** 44 | * getName returns the username 45 | * 46 | * @return string username 47 | * @api 48 | */ 49 | public function getName() 50 | { 51 | return array_key_exists('username', $this->user)?$this->user['username']:''; 52 | } 53 | 54 | /** 55 | * getUUID returns the uuid 56 | * 57 | * @return string user UUID 58 | * @api 59 | */ 60 | public function getUUID() 61 | { 62 | return $this->uuid; 63 | } 64 | 65 | /** 66 | * setPassword 67 | * 68 | * @param string $password Password 69 | * @return array status 70 | * @api 71 | */ 72 | public function setPassword($password) 73 | { 74 | return $this->request('/bot/users/'.$this->uuid, 'PATCH', [ 75 | 'password'=>$password, 76 | ]); 77 | } 78 | 79 | /** 80 | * setPrivileges 81 | * 82 | * @param integer $privileges Bitmask-Value 83 | * @return array status 84 | * @api 85 | */ 86 | public function setPrivileges($privileges) 87 | { 88 | return $this->request('/bot/users/'.$this->uuid, 'PATCH', [ 89 | 'privileges'=>$privileges, 90 | ]); 91 | } 92 | 93 | /** 94 | * setIdentity 95 | * 96 | * @param string $identity teamspeak identity 97 | * @return array status 98 | * @api 99 | */ 100 | public function setIdentity($identity) 101 | { 102 | return $this->request('/bot/users/'.$this->uuid, 'PATCH', [ 103 | 'tsuid'=>$identity, 104 | ]); 105 | } 106 | 107 | /** 108 | * setServergroup 109 | * 110 | * @param string $groupID TeamSpeak Group ID 111 | * @return array status 112 | * @api 113 | */ 114 | public function setServergroup($groupID) 115 | { 116 | return $this->request('/bot/users/'.$this->uuid, 'PATCH', [ 117 | 'tsgid'=>strval($groupID), 118 | ]); 119 | } 120 | 121 | /** 122 | * delete 123 | * 124 | * @return array status 125 | * @api 126 | */ 127 | public function delete() 128 | { 129 | return $this->request('/bot/users/'.$this->uuid, 'DELETE'); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/autoload.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | 11 | include_once("RestClient.php"); 12 | include_once("Instance.php"); 13 | include_once("Playlist.php"); 14 | include_once("User.php"); 15 | include_once("File.php"); 16 | include_once("Folder.php"); 17 | include_once("API.php"); 18 | --------------------------------------------------------------------------------