├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md └── workflows │ └── docker-image.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── LICENSE.md ├── README.md ├── TESTING.md ├── _config.yml ├── composer.json ├── composer.lock ├── composer.phar ├── docker-compose.dev.yml ├── docker-compose.yml ├── fuel ├── .htaccess └── app │ ├── bootstrap.php │ ├── cache │ └── .gitkeep │ ├── classes │ ├── controller │ │ ├── admin.php │ │ ├── admin │ │ │ ├── libraries.php │ │ │ └── users.php │ │ ├── cover.php │ │ ├── episode.php │ │ ├── home.php │ │ ├── index.php │ │ ├── install.php │ │ ├── library.php │ │ ├── login.php │ │ ├── logout.php │ │ ├── movie.php │ │ ├── register.php │ │ ├── rest │ │ │ ├── browse.php │ │ │ ├── index.php │ │ │ ├── install.php │ │ │ ├── library.php │ │ │ ├── movie.php │ │ │ ├── player.php │ │ │ ├── search.php │ │ │ └── settings.php │ │ ├── season.php │ │ ├── security.php │ │ ├── settings.php │ │ ├── settings │ │ │ └── libraries.php │ │ └── tvshow.php │ ├── database │ │ └── query │ │ │ └── builder │ │ │ └── insert.php │ ├── file.php │ └── model │ │ ├── library.php │ │ ├── library │ │ └── permission.php │ │ ├── movie.php │ │ ├── overwrite.php │ │ ├── permission.php │ │ ├── season.php │ │ ├── server.php │ │ ├── trailer.php │ │ ├── tvshow.php │ │ ├── user.php │ │ └── user │ │ ├── download.php │ │ ├── history.php │ │ └── settings.php │ ├── config │ ├── config.php │ ├── db.php │ ├── migrations.php │ ├── panel.php │ ├── routes.php │ ├── session.php │ ├── staging │ │ └── db.php │ ├── test │ │ └── db.php │ └── user_settings.php │ ├── lang │ └── en │ │ ├── action.php │ │ ├── home.php │ │ ├── menu.php │ │ ├── movie.php │ │ ├── permissions.php │ │ ├── player.php │ │ ├── season.php │ │ ├── settings.php │ │ └── tv_show.php │ ├── logs │ └── .gitkeep │ ├── migrations │ ├── 001_create_library.php │ ├── 002_create_library_permission.php │ ├── 003_create_movie.php │ ├── 004_create_permission.php │ ├── 005_create_season.php │ ├── 006_create_server.php │ ├── 007_create_tvshow.php │ ├── 008_create_user.php │ ├── 009_create_user_download.php │ ├── 010_create_user_history.php │ ├── 011_create_user_permission.php │ ├── 012_create_user_settings.php │ └── 013_add_originaltitle_to_tvshow.php │ ├── modules │ └── .gitkeep │ ├── tasks │ ├── clean.php │ ├── robots.php │ └── server.php │ ├── tests │ ├── controller │ │ └── .gitkeep │ ├── model │ │ └── .gitkeep │ ├── presenter │ │ └── .gitkeep │ └── view │ │ └── .gitkeep │ ├── themes │ └── .gitkeep │ ├── tmp │ └── .gitkeep │ ├── vendor │ └── .gitkeep │ └── views │ ├── admin │ ├── body.php │ ├── index.php │ ├── libraries.php │ ├── servers.php │ └── users.php │ ├── episode │ └── index.php │ ├── home │ └── index.php │ ├── install │ └── index.php │ ├── layout │ ├── body.php │ ├── header.php │ ├── index.php │ ├── nav_bar_header.php │ ├── nav_bar_vertical.php │ └── search.php │ ├── libraries │ └── list.php │ ├── login │ └── index.php │ ├── modal │ ├── modal_back.php │ └── server.php │ ├── movie │ ├── index.php │ └── list.php │ ├── player │ └── index.php │ ├── register │ └── index.php │ ├── season │ └── index.php │ ├── settings │ ├── body.php │ ├── index.php │ ├── libraries.php │ ├── libraries │ │ └── permissions.php │ └── servers.php │ └── tvshow │ └── index.php ├── oil ├── public ├── .htaccess ├── assets │ ├── css │ │ ├── bootstrap-LICENSE │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.css │ │ ├── bootstrap.min.css │ │ ├── index.html │ │ ├── main.css │ │ ├── normalize.css │ │ ├── normalize_login.css │ │ ├── plex.css │ │ ├── plex_login.css │ │ └── settings.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── index.html │ ├── img │ │ └── index.html │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ ├── clappr.js │ │ ├── clappr.min.js │ │ ├── index.html │ │ ├── jquery.min.js │ │ ├── player.js │ │ ├── plex_alert.js │ │ ├── pwstrength-bootstrap.min.js │ │ └── server_refresh.js ├── favicon.ico ├── index.php └── web.config └── screenshots ├── README.MD ├── Screenshot from 2018-03-16 19.48.24.png ├── Screenshot from 2018-03-16 19.49.08.png ├── Screenshot from 2018-03-16 19.49.28.png ├── Screenshot from 2018-03-16 22-08-40.png ├── admin_users.jpg ├── all_movies.jpg ├── episode.jpg ├── homepage.jpg ├── movie.jpg ├── season.jpg ├── settings_add_server.png ├── settings_libraries.jpg ├── settings_server.jpg └── tv_show.jpg /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | *Dont Forget to set your ENVIRONMENT variable to DEVELOPMENT* 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 1. Go to '...' 15 | 2. Click on '....' 16 | 3. Scroll down to '....' 17 | 4. See error 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Screenshots** 23 | If applicable, add screenshots to help explain your problem. 24 | 25 | **Desktop (please complete the following information):** 26 | - OS: [e.g. iOS] 27 | - Browser [e.g. chrome, safari] 28 | - Version [e.g. 22] 29 | 30 | **Smartphone (please complete the following information):** 31 | - Device: [e.g. iPhone6] 32 | - OS: [e.g. iOS8.1] 33 | - Browser [e.g. stock browser, safari] 34 | - Version [e.g. 22] 35 | 36 | **Additional context** 37 | Add any other context about the problem here. 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | 5 | --- 6 | 7 | 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image CI 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | 9 | build: 10 | 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | - 16 | name: Set up QEMU 17 | uses: docker/setup-qemu-action@v2 18 | - 19 | name: Set up Docker Buildx 20 | uses: docker/setup-buildx-action@v2 21 | - 22 | name: Docker Login 23 | uses: docker/login-action@v2.1.0 24 | with: 25 | username: ${{ secrets.DOCKERHUB_USERNAME }} 26 | password: ${{ secrets.DOCKERHUB_TOKEN }} 27 | - 28 | name: Build and push 29 | uses: docker/build-push-action@v3 30 | with: 31 | push: true 32 | tags: chewbaka/plexshare:${{ github.event.release.tag_name }},chewbaka/plexshare:latest 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # the composer package lock file and install directory 2 | # Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file 3 | # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file 4 | # /composer.lock 5 | /fuel/core 6 | /fuel/vendor 7 | /fuel/packages 8 | 9 | # the fuelphp document 10 | /docs/ 11 | 12 | # you may install these packages with `oil package`. 13 | # http://fuelphp.com/docs/packages/oil/package.html 14 | # /fuel/packages/auth/ 15 | # /fuel/packages/email/ 16 | # /fuel/packages/oil/ 17 | # /fuel/packages/orm/ 18 | # /fuel/packages/parser/ 19 | 20 | # dynamically generated files 21 | /fuel/app/logs/*/*/* 22 | /fuel/app/cache/*/* 23 | /fuel/app/config/plex.php 24 | /fuel/app/config/db.php 25 | /fuel/app/config/crypt.php 26 | /fuel/app/config/lock.php 27 | /fuel/app/config/development/ 28 | 29 | /packages 30 | /vendor 31 | /.idea 32 | composer.lock 33 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 5.3 4 | - 5.4 5 | - 5.5 6 | - 7.0 7 | 8 | before_script: 9 | - curl -s http://getcomposer.org/installer | php 10 | - php composer.phar install --dev 11 | 12 | script: php oil test 13 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at NOT_A_THIS_TIME. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Please read the project contibuting guidelines before creating an issue of sending in a pull request: 2 | 3 | https://github.com/fuel/fuel/wiki/Contributing 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM webdevops/php-nginx:7.4-alpine 2 | 3 | USER application 4 | 5 | WORKDIR /app 6 | 7 | COPY --chown=application:application ./ /app 8 | 9 | RUN php -v 10 | 11 | RUN composer install 12 | 13 | RUN (crontab -l ; echo "*/2 * * * * /usr/local/bin/php /app/oil refine server:ping")| crontab - 14 | RUN (crontab -l ; echo "*/2 * * * * /usr/local/bin/php /app/oil refine server:ping")| crontab - 15 | RUN (crontab -l ; echo "*/5 * * * * /usr/local/bin/php /app/oil refine server:browseServers")| crontab - 16 | RUN (crontab -l ; echo "*/5 * * * * /usr/local/bin/php /app/oil refine server:browseServers")| crontab - 17 | RUN (crontab -l ; echo "0 5 1 * * /usr/local/bin/php /app/oil refine server:checkNotFound")| crontab - 18 | RUN (crontab -l ; echo "0 5 1 * * /usr/local/bin/php /app/oil refine server:checkNotFound")| crontab - 19 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2016 Fuel Development Team 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![PHP](https://img.shields.io/badge/PHP->=_8.0-738bd7.svg?style=flat-square) 2 | ![PHP](https://img.shields.io/badge/FuelPhp-1.8.2-8304d7.svg?style=flat-square) 3 | ![Extension](https://img.shields.io/badge/Needed-Curl-blue.svg?style=flat-square) 4 | ![Database](https://img.shields.io/badge/Needed-MySQL-blue.svg?style=flat-square) 5 | ![PlexServer](https://img.shields.io/badge/Needed-PlexServer-yellow.svg?style=flat-square) 6 | 7 | # PlexShare 8 | Web Application standalone that provide the management of local users, many server and the libraries. 9 | 10 | ## V2 started 11 | Why starting a V2, while V1 is not Finish? 12 | Because the technology use is no more what i want for this app. 13 | 14 | So the V2 will use NextJS and Laravel 15 | New design for the FrontEnd and new Code for the Backend :) 16 | 17 | ### Little issue 18 | Issue with NextJS 15... 19 | Trying to fix it 20 | 21 | # Description 22 | With this web application, anyone can create an account directly this app. 23 | Every body can add his PlexServer to the list. 24 | When you are connected by default you have access to all servers. 25 | But the admin can manage permission by user or by library like limit of number streaming, the quality and other 26 | 27 | With only one interface and without plex.tv registration, everybody can have access to the libraries of all the servers you have registered. 28 | 29 | ![Flyer](https://i.imgur.com/TxMPjKm.png) 30 | 31 | # Features 32 | - Register and Login without plex.tv account 33 | - Manage some PlexServer to share theirs libraries 34 | - Manage permission to limit access to the users 35 | 36 | # Tehcnologies 37 | - MySQL 38 | - PHP 39 | - Framework FuelPHP 1.8 40 | - Bootstrap 41 | - jQuery 42 | - jQuery widget pwstrength [Github](https://github.com/ablanco/jquery.pwstrength.bootstrap) 43 | - Video Player [Clappr](https://github.com/clappr/clappr) 44 | 45 | # Preview 46 | [SCREENSHOT](https://github.com/Chewbaka69/PlexShare/tree/master/screenshots) 47 | 48 | # Installation And Support 49 | [Wiki](https://github.com/Chewbaka69/PlexShare/wiki) 50 | 51 | # Todo-List 52 | [TODO LIST](https://github.com/Chewbaka69/PlexShare/blob/master/TODO_LIST.md) 53 | 54 | # Sponsors 55 | | Termius | 56 | | ------------- | 57 | | [![termius-icon-64](https://github.com/user-attachments/assets/a0061114-3370-403d-841c-b1c257af792d)](https://termius.com/) | 58 | | [Termius](https://termius.com/) provides a secure, reliable, and collaborative SSH client. | 59 | 60 | 61 | # Licence 62 | This is free software under the GPL v3 open source license. Feel free to do with it what you wish, but any modification must be open sourced. A copy of the license is included. 63 | -------------------------------------------------------------------------------- /TESTING.md: -------------------------------------------------------------------------------- 1 | # Testing FuelPHP 2 | 3 | FuelPHP uses [PHPUnit](https://github.com/sebastianbergmann/phpunit/) for it's Unit Testing needs. It must be installed for the tests to run. 4 | 5 | **NOTE: No code will be accepted without tests written.** 6 | 7 | ## Running Tests 8 | 9 | Running the unit tests is as simple as navigating to the root install folder on the command line and running the following: 10 | 11 | $ php oil test 12 | 13 | That's it! You can also tell it specific groups (which we will get into in minute) to run. For example to run only the core tests: 14 | 15 | $ php oil test --group=Core 16 | 17 | As you can see we've wrapped the phpunit command with our own Oil utility which will in time become more and more useful. If you wish to get right at the phpunit tests manually you can point it to our .xml configuration file: 18 | 19 | $ phpunit -c fuel/core/phpunit.xml --group Core 20 | 21 | This may break or change in future versions so it's suggested you stick with using Oil for your testing. 22 | 23 | ## Writing Tests 24 | 25 | ### Where do they go? 26 | 27 | All tests are to go in the **tests** folders inside their respective parent folder. For instance: 28 | 29 | * App tests go in *fuel/app/tests* 30 | * Core tests go in *fuel/core/tests* 31 | * Package tests go in *fuel/packages/package_name/tests* 32 | 33 | ### File / Class Naming 34 | 35 | The Test class names should be in the form of **Tests_Whatever**. 36 | 37 | Filenames should be all lower case and be the class name minus the "Tests_" part. 38 | 39 | Some example names: 40 | 41 | // Good 42 | Tests_Arr in fuel/core/tests/arr.php 43 | Tests_Image in fuel/core/tests/image.php 44 | Tests_Fuel in fuel/core/tests/fuel.php 45 | 46 | // Bad 47 | Arrtests 48 | Somestuff 49 | 50 | ### Test Grouping 51 | 52 | All tests inside the **core** folder must be in the **core** group. A classes test's should also be grouped together under the name of the class. 53 | 54 | Here is an example of a core class test with proper DocBlocks: 55 | 56 | /** 57 | * Arr class tests 58 | * 59 | * @group Core 60 | * @group Arr 61 | */ 62 | class Tests_Arr extends TestCase { 63 | 64 | /** 65 | * Tests Arr::get() 66 | * 67 | * @test 68 | */ 69 | public function test_get() 70 | { 71 | // Test code here 72 | } 73 | } 74 | 75 | All App tests should be in the **app** group. 76 | 77 | ### Namespaces 78 | 79 | All **core** tests should be in the **Fuel\Core** namespace. This is so that we are sure we are testing the core classes, 80 | not any extensions that may be in *app*. 81 | 82 | App tests can be in any namespace. 83 | 84 | ### What class do I extend? 85 | 86 | All tests should extend the **Fuel\Core\TestCase** class. 87 | 88 | **NOTE: if you are in the Fuel\Core namespace you can leave off the Fuel\Core namespace and just extend **TestCase**. 89 | 90 | ## Example 91 | 92 | namespace Fuel\Core; 93 | 94 | /** 95 | * Arr class tests 96 | * 97 | * @group Core 98 | * @group Arr 99 | */ 100 | class Tests_Arr extends TestCase { 101 | 102 | /** 103 | * Tests Arr::flatten_assoc() 104 | * 105 | * @test 106 | */ 107 | public function test_flatten_assoc() 108 | { 109 | $people = array( 110 | array( 111 | "name" => "Jack", 112 | "age" => 21 113 | ), 114 | array( 115 | "name" => "Jill", 116 | "age" => 23 117 | ) 118 | ); 119 | 120 | $expected = array( 121 | "0:name" => "Jack", 122 | "0:age" => 21, 123 | "1:name" => "Jill", 124 | "1:age" => 23 125 | ); 126 | 127 | $output = Arr::flatten_assoc($people); 128 | $this->assertEquals($expected, $output); 129 | } 130 | 131 | } 132 | 133 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fuel/fuel", 3 | "type": "project", 4 | "description" : "FuelPHP is a simple, flexible, community driven PHP 5.3.3+ framework, based on the best ideas of other frameworks, with a fresh start!", 5 | "keywords": ["application", "website", "development", "framework", "PHP", "PHP7"], 6 | "license": "MIT", 7 | "require": { 8 | "php": "7.4.*", 9 | "composer/installers": "~1.0", 10 | "fuel/core": "1.8.*", 11 | "fuel/auth": "1.8.*", 12 | "fuel/email": "1.8.*", 13 | "fuel/oil": "1.8.*", 14 | "fuel/orm": "1.8.*", 15 | "fuel/parser": "1.8.*", 16 | "fuelphp/upload": "2.0.6", 17 | "monolog/monolog": "^1.18", 18 | "phpseclib/phpseclib": "2.0.31", 19 | "michelf/php-markdown": "1.7.0" 20 | }, 21 | "require-dev": { 22 | "fuel/docs": "1.8.*" 23 | }, 24 | "suggest": { 25 | "dwoo/dwoo" : "Allow Dwoo templating with the Parser package", 26 | "mustache/mustache": "Allow Mustache templating with the Parser package", 27 | "smarty/smarty": "Allow Smarty templating with the Parser package", 28 | "twig/twig": "Allow Twig templating with the Parser package", 29 | "pyrocms/lex": "Allow Lex templating with the Parser package", 30 | "mthaml/mthaml": "Allow Haml templating with Twig supports with the Parser package" 31 | }, 32 | "config": { 33 | "vendor-dir": "fuel/vendor" 34 | }, 35 | "extra": { 36 | "installer-paths": { 37 | "fuel/{$name}": ["fuel/core"], 38 | "{$name}": ["fuel/docs"] 39 | } 40 | }, 41 | "scripts": { 42 | "post-install-cmd": [ 43 | "php oil r install" 44 | ] 45 | }, 46 | "minimum-stability": "stable" 47 | } 48 | 49 | -------------------------------------------------------------------------------- /composer.phar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chewbaka69/PlexShare/b8ae75a015569c22dce7c0e3427897c3275f21fb/composer.phar -------------------------------------------------------------------------------- /docker-compose.dev.yml: -------------------------------------------------------------------------------- 1 | version: '3.2' 2 | 3 | services: 4 | plexshare: 5 | # Image doc here: https://dockerfile.readthedocs.io/en/latest/content/DockerImages/dockerfiles/php-nginx.html 6 | container_name: plexshare-dev 7 | image: chewbaka69/plexshare-dev 8 | build: . 9 | working_dir: /app 10 | ports: 11 | - '80:80' 12 | restart: unless-stopped 13 | environment: 14 | # NGINX 15 | # FOR the BASE_URL never forget the last / 16 | # BASE_URL: http://your-domain.here/ 17 | WEB_DOCUMENT_ROOT: /app/public 18 | WEB_DOCUMENT_INDEX: index.php 19 | 20 | # LOGS 21 | LOG_STDOUT: ./var/log/plexshare.stdout.log 22 | LOG_STDERR: ./var/log/plexshare.stderr.log 23 | 24 | # PHP CONFIG 25 | php.error_reporting: 1 26 | PHP_DISPLAY_ERRORS: E_ALL 27 | 28 | PHP_POST_MAX_SIZE: 20M 29 | PHP_MEMORY_LIMIT: 521M 30 | PHP_MAX_EXECUTION_TIME: 300 31 | 32 | PHP_DATE_TIMEZONE: Europe/Paris 33 | 34 | # COMPOSER 35 | COMPOSER_VERSION: 1 36 | volumes: 37 | - .:/app -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.2' 2 | 3 | services: 4 | plexshare: 5 | # Image doc here: https://dockerfile.readthedocs.io/en/latest/content/DockerImages/dockerfiles/php-nginx.html 6 | container_name: plexshare 7 | image: chewbaka/plexshare:latest 8 | working_dir: /app 9 | # If you use a reverse PROXY you can comment those 2 lines below 10 | ports: 11 | - '80:80' 12 | restart: unless-stopped 13 | environment: 14 | # NGINX 15 | # FOR the BASE_URL never forget the last / 16 | # BASE_URL: http://your-domain.here/ 17 | WEB_DOCUMENT_ROOT: /app/public 18 | WEB_DOCUMENT_INDEX: index.php 19 | 20 | # LOGS 21 | LOG_STDOUT: ./var/log/plexshare.stdout.log 22 | LOG_STDERR: ./var/log/plexshare.stderr.log 23 | 24 | # PHP CONFIG 25 | # PHP_DISMOD: 26 | 27 | PHP_POST_MAX_SIZE: 20M 28 | PHP_MEMORY_LIMIT: 521M 29 | PHP_MAX_EXECUTION_TIME: 300 30 | 31 | PHP_DATE_TIMEZONE: Europe/Paris 32 | 33 | # COMPOSER 34 | COMPOSER_VERSION: 1 35 | -------------------------------------------------------------------------------- /fuel/.htaccess: -------------------------------------------------------------------------------- 1 | deny from all -------------------------------------------------------------------------------- /fuel/app/bootstrap.php: -------------------------------------------------------------------------------- 1 | APPPATH.'classes/view.php', 8 | 'Database_Query_Builder_Insert' => APPPATH.'classes/database/query/builder/insert.php', 9 | 'File' => APPPATH.'classes/file.php', 10 | )); 11 | 12 | // Register the autoloader 13 | \Autoloader::register(); 14 | 15 | /** 16 | * Your environment. Can be set to any of the following: 17 | * 18 | * Fuel::DEVELOPMENT 19 | * Fuel::TEST 20 | * Fuel::STAGING 21 | * Fuel::PRODUCTION 22 | */ 23 | \Fuel::$env = \Arr::get($_SERVER, 'FUEL_ENV', \Arr::get($_ENV, 'FUEL_ENV', \Fuel::DEVELOPMENT)); 24 | 25 | // Initialize the framework with the config file. 26 | \Fuel::init('config.php'); 27 | -------------------------------------------------------------------------------- /fuel/app/cache/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chewbaka69/PlexShare/b8ae75a015569c22dce7c0e3427897c3275f21fb/fuel/app/cache/.gitkeep -------------------------------------------------------------------------------- /fuel/app/classes/controller/admin.php: -------------------------------------------------------------------------------- 1 | admin) 21 | Response::redirect('/home'); 22 | 23 | Lang::load('menu'); 24 | Lang::load('action'); 25 | 26 | $this->template->user = Session::get('user'); 27 | 28 | $this->template->js_bottom = ['plex_alert.js']; 29 | } 30 | 31 | public function action_index() 32 | { 33 | $body = View::forge('admin/index'); 34 | 35 | $this->template->body = $body; 36 | } 37 | 38 | public function action_servers() 39 | { 40 | $this->template->js_bottom = ['plex_alert.js', 'server_refresh.js']; 41 | 42 | $body = View::forge('admin/servers'); 43 | 44 | $servers = Model_Server::find_all(); 45 | 46 | $body->set('servers', $servers); 47 | 48 | $this->template->body = $body; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /fuel/app/classes/controller/admin/libraries.php: -------------------------------------------------------------------------------- 1 | template->js_bottom = ['plex_alert.js', 'server_refresh.js']; 11 | 12 | $body = View::forge('admin/libraries'); 13 | 14 | $libraries = Model_Library::find_all(); 15 | 16 | $body->set('libraries', $libraries); 17 | 18 | $this->template->body = $body; 19 | } 20 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/admin/users.php: -------------------------------------------------------------------------------- 1 | template->js_bottom = ['plex_alert.js']; 12 | 13 | $body = View::forge('admin/users'); 14 | 15 | $users = Model_User::find_all(); 16 | 17 | $body->set('users', $users); 18 | 19 | $this->template->body = $body; 20 | } 21 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/cover.php: -------------------------------------------------------------------------------- 1 | getArt($width, $height); 29 | else if($thumb === null && $art === null) 30 | $images = $movie->getCover($width, $height); 31 | else 32 | $images = $movie->getThumb($width, $height); 33 | 34 | $response = new Response(); 35 | $response->set_header('Content-Type', 'image/jpeg'); 36 | $response->set_header('Content-Length',strlen($images)); 37 | $response->body($images); 38 | 39 | return $response; 40 | } 41 | 42 | public function get_tvshow() 43 | { 44 | $tvshow_id = Input::get('tvshow_id'); 45 | 46 | if(!$tvshow_id) 47 | throw new FuelException(); 48 | 49 | $width = Input::get('width'); 50 | $height = Input::get('height'); 51 | 52 | $tv_show = Model_Tvshow::find_by_pk($tvshow_id); 53 | 54 | if(!$tv_show) 55 | throw new FuelException(); 56 | 57 | $images = $tv_show->getCover($width, $height); 58 | 59 | $response = new Response(); 60 | $response->set_header('Content-Type', 'image/jpeg'); 61 | $response->set_header('Content-Length',strlen($images)); 62 | $response->body($images); 63 | 64 | return $response; 65 | } 66 | 67 | public function get_season() 68 | { 69 | try { 70 | $season_id = Input::get('season_id'); 71 | 72 | if (!$season_id) 73 | throw new FuelException(); 74 | 75 | $width = Input::get('width'); 76 | $height = Input::get('height'); 77 | 78 | $thumb = Input::get('thumb') ?: null; 79 | 80 | $season = Model_Season::find_by_pk($season_id); 81 | 82 | if (!$season) 83 | throw new FuelException(); 84 | 85 | if (!$thumb) 86 | $images = $season->getCover($width, $height); 87 | else 88 | $images = $season->getThumb($width, $height); 89 | 90 | $response = new Response(); 91 | $response->set_header('Content-Type', 'image/jpeg'); 92 | $response->set_header('Content-Length', strlen($images)); 93 | $response->body($images); 94 | 95 | return $response; 96 | } catch (Exception $e) { 97 | Debug::dump($e);die(); 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/episode.php: -------------------------------------------------------------------------------- 1 | param('episode_id'); 12 | 13 | if(!$episode_id) 14 | Response::redirect('/home'); 15 | 16 | $episode = Model_Movie::find_by_pk($episode_id); 17 | 18 | if(!$episode) 19 | Response::redirect('/home'); 20 | 21 | Lang::load('movie'); 22 | Lang::load('action'); 23 | 24 | $body = View::forge('episode/index'); 25 | 26 | $this->template->title = $episode->getTvShow()->title . ' S' . $episode->getSeason()->number . ' - E' .$episode->number . ' ' . $episode->title; 27 | 28 | $seasons = $episode->getTvShow()->getSeasons(); 29 | $episodes = $episode->getSeason()->getEpisodes(); 30 | $subtitles = $episode->getMetaData()['Stream']['SubTitle']; 31 | 32 | $body->set('episode', $episode); 33 | $body->set('seasons', $seasons); 34 | $body->set('episodes', $episodes); 35 | $body->set('subtitles', $subtitles); 36 | 37 | $this->template->body = $body; 38 | } 39 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/home.php: -------------------------------------------------------------------------------- 1 | _user = $user; 25 | 26 | $server = $sessionServer ? Model_Server::find_by_pk($sessionServer->id) : Model_Server::find_one_by([ 27 | ['online', '=', 1], 28 | ['disable', '=', 0], 29 | ]); 30 | 31 | Lang::load('menu'); 32 | Lang::load('settings'); 33 | 34 | $this->template->title = 'Home'; 35 | 36 | $libraries = $server? $server->getLibraries() : null; 37 | 38 | $this->template->servers = Model_Server::find([ 39 | 'where' => [ 40 | ['online', '=', 1], 41 | ['disable', '=', 0], 42 | ], 43 | ]); 44 | $this->template->user = Session::get('user'); 45 | $this->template->MenuServer = $server; 46 | $this->template->MenuLibraries = $libraries; 47 | 48 | $this->template->js_bottom = ['clappr.min.js', 'player.js', 'plex_alert.js']; 49 | } 50 | 51 | public function action_index() 52 | { 53 | Lang::load('home'); 54 | Lang::load('season'); 55 | 56 | $body = View::forge('home/index'); 57 | 58 | $server_id = $this->param('server_id'); 59 | 60 | if ($server_id !== NULL) { 61 | $server = Model_Server::find_by_pk($server_id); 62 | 63 | if ($server) 64 | $this->template->MenuServer = $server; 65 | } 66 | 67 | Session::delete('server'); 68 | Session::set('server', $this->template->MenuServer); 69 | 70 | $this->template->MenuLibraries = $this->template->MenuServer ? $this->template->MenuServer->getLibraries() : null; 71 | 72 | $watching_movies = Model_User_History::find_by([ 73 | ['user_id', '=', $this->_user->id], 74 | ['is_ended', '=', 0] 75 | ]); 76 | 77 | $episodes = $this->template->MenuServer ? $this->template->MenuServer->getThirtyLastedTvShows() : null; 78 | 79 | $movies = $this->template->MenuServer ? $this->template->MenuServer->getThirtyLastedMovies() : null; 80 | 81 | $body->set('watching_movies', $watching_movies); 82 | $body->set('episodes', $episodes); 83 | $body->set('movies', $movies); 84 | 85 | $this->template->body = $body; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /fuel/app/classes/controller/index.php: -------------------------------------------------------------------------------- 1 | set_safe('end_js', $js); 28 | 29 | $config_db = Config::load('db', true); 30 | $config_db = $config_db['default']; 31 | 32 | $view->set('db_host', isset($config_db['connection']['hostname']) ? $config_db['connection']['hostname'] : null); 33 | $view->set('db_port', isset($config_db['connection']['port']) ? $config_db['connection']['port'] : null); 34 | $view->set('db_database', isset($config_db['connection']['database']) ? $config_db['connection']['database'] : null); 35 | $view->set('db_prefix', isset($config_db['table_prefix']) ? $config_db['table_prefix'] : null); 36 | $view->set('db_username', isset($config_db['connection']['username']) ? $config_db['connection']['username'] : null); 37 | $view->set('db_password', isset($config_db['connection']['password']) ? $config_db['connection']['password'] : null); 38 | 39 | try { 40 | $config_plex = Model_Server::find() ? Model_Server::find()[0] : null; 41 | 42 | if($config_plex) { 43 | $view->set('plex_url', $config_plex ? $config_plex->url : null); 44 | $view->set('plex_port', $config_plex ? $config_plex->port : null); 45 | $view->set('plex_token', $config_plex ? $config_plex->token : null); 46 | } 47 | }catch (FuelException $e){ 48 | //@TODO 49 | } 50 | 51 | return $view; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /fuel/app/classes/controller/library.php: -------------------------------------------------------------------------------- 1 | param('library_id'); 11 | 12 | if(!$library_id) 13 | Response::redirect('/home'); 14 | 15 | $library = Model_Library::find_by_pk($library_id); 16 | 17 | if(!$library) 18 | Response::redirect('/home'); 19 | 20 | $this->template->title = $library->name . ' in '. $library->getServer()->name; 21 | 22 | $body = View::forge('libraries/list'); 23 | 24 | $content = null; 25 | 26 | if($library->type === 'movie') { 27 | $content = Model_Movie::find_by(function ($query) use ($library_id){ 28 | $query->where('library_id', $library_id) 29 | ->order_by('title', 'ASC') 30 | ; 31 | }); 32 | } else if($library->type === 'show') { 33 | $content = Model_Tvshow::find_by(function ($query) use ($library_id){ 34 | $query->where('library_id', $library_id) 35 | ->order_by('title', 'ASC') 36 | ; 37 | }); 38 | } 39 | 40 | $body->set('movies', $content); 41 | 42 | $this->template->body = $body; 43 | } 44 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/login.php: -------------------------------------------------------------------------------- 1 | set('registration', (bool)$panel['registration']); 37 | 38 | try { 39 | 40 | if (Input::method() === 'POST') { 41 | $configdb = Config::load('db', true); 42 | $configCrypt = Config::load('crypt', true); 43 | 44 | $login = Input::post('email'); 45 | $password = Input::post('password'); 46 | $passwordHash = hash('sha512', $configCrypt['sodium']['cipherkey'] . $password); 47 | 48 | if($user = Model_User::Login($login, $passwordHash)) { 49 | $user->lastlogin = time(); 50 | $user->save(); 51 | 52 | Session::set('user', $user); 53 | Response::redirect('/home'); 54 | } else { 55 | $view->set('error','Username or password is incorrect.'); 56 | } 57 | } 58 | } catch (FuelException $e) { 59 | $view->set('error', $e->getMessage()); 60 | } 61 | 62 | $view->set_safe('start_js', $start_js); 63 | 64 | return Response::forge($view); 65 | } 66 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/logout.php: -------------------------------------------------------------------------------- 1 | set(array( 60 | 'username' => $username, 61 | 'email' => $email, 62 | 'password' => hash('sha512', $config['default']['hash'] . $password), 63 | 'admin' => 0, 64 | 'lastlogin' => time() 65 | )); 66 | 67 | $user->save(); 68 | 69 | Session::set('user', $user); 70 | Response::redirect('/home'); 71 | } 72 | } catch (FuelException $e) { 73 | $view->set('error', $e->getMessage()); 74 | } 75 | 76 | $view->set_safe('start_js', $start_js); 77 | $view->set_safe('end_js', $end_js); 78 | 79 | return $view; 80 | } 81 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/rest/browse.php: -------------------------------------------------------------------------------- 1 | admin) { 12 | $server = Model_Server::find(array( 13 | 'select' => array('id', 'name', 'url', 'port', 'token'), 14 | 'where' => array( 15 | 'id' => Input::get('server_id'), 16 | 'user_id' => Session::get('user')->id 17 | ) 18 | )); 19 | } else { 20 | $server = Model_Server::find(array( 21 | 'select' => array('*'), 22 | 'where' => array( 23 | 'id' => Input::get('server_id') 24 | ) 25 | )); 26 | } 27 | 28 | if(!$server) 29 | return $this->response(array('error' => true, 'message' => 'No server found!')); 30 | 31 | $this->response($server); 32 | } 33 | 34 | public function get_library() 35 | { 36 | $library_id = Input::get('library_id'); 37 | 38 | $library = Model_Library::find_one_by(function($query) use ($library_id) { 39 | $query 40 | ->select_array([ 41 | 'library.*', 42 | ['server.id', 'server_id'], 43 | ['server.name', 'server_name'] 44 | ]) 45 | ->join('server', 'LEFT') 46 | ->on('server.id', '=','library.server_id' ) 47 | ->where('server.user_id', Session::get('user')->id) 48 | ->and_where('library.id', $library_id) 49 | ->and_where('server.disable', 0) 50 | ; 51 | }); 52 | 53 | if(!$library) 54 | return $this->response(array('error' => true, 'message' => 'No server found!')); 55 | 56 | $this->response($library); 57 | } 58 | 59 | public function get_my_servers() 60 | { 61 | $servers = Model_Server::find(array( 62 | 'select' => array('id','name'), 63 | 'where' => array( 64 | 'user_id' => Session::get('user')->id, 65 | ) 66 | )); 67 | 68 | return $this->response($servers); 69 | } 70 | 71 | public function put_server() 72 | { 73 | try { 74 | $server_id = Input::put('server_id'); 75 | 76 | $server = Model_Server::find_by('id', $server_id); 77 | 78 | if (!$server) 79 | return $this->response(array('error' => true, 'message' => 'No server found!')); 80 | 81 | Model_Server::BrowseServeur($server); 82 | 83 | return $this->response(['error' => false, 'message' => 'Servers informations update!']); 84 | } catch (Exception $e) { 85 | return $this->response(['error' => true, 'message' => $e->getMessage()]); 86 | } 87 | } 88 | 89 | public function get_libraries() 90 | { 91 | $server_id = Input::get('server_id'); 92 | 93 | $server = Model_Server::find_by_pk($server_id); 94 | 95 | if(!$server) 96 | return $this->response(array('error' => true, 'message' => 'No server found!')); 97 | 98 | $libraries = Model_Library::BrowseLibraries($server); 99 | 100 | if(!$libraries) 101 | return $this->response(array('error' => true, 'message' => 'No library found!')); 102 | 103 | $this->response(['error' => false, 'libraries' => $libraries]); 104 | } 105 | 106 | public function get_subcontent() 107 | { 108 | $server_id = Input::get('server_id'); 109 | $library_id = Input::get('library_id'); 110 | 111 | $server = Model_Server::find_by_pk($server_id); 112 | $library = Model_Library::find_by_pk($library_id); 113 | 114 | if(!$server) 115 | return $this->response(array('error' => true, 'message' => 'No server found!')); 116 | 117 | if(!$library) 118 | return $this->response(array('error' => true, 'message' => 'No library found!')); 119 | 120 | return Model_Library::getLibraryContents($server, $library); 121 | } 122 | 123 | public function get_seasons() 124 | { 125 | $server_id = Input::get('server_id'); 126 | $tvshow_id = Input::get('tvshow_id'); 127 | 128 | $server = Model_Server::find_by_pk($server_id); 129 | $tvshow = Model_Tvshow::find_by_pk($tvshow_id); 130 | 131 | if(!$server) 132 | return $this->response(array('error' => true, 'message' => 'No server found!')); 133 | 134 | if(!$tvshow) 135 | return $this->response(array('error' => true, 'message' => 'No tvshow found!')); 136 | 137 | $seasons = Model_Tvshow::getTvShowSeasons($server,$tvshow); 138 | 139 | if(!$seasons) 140 | return $this->response(array('error' => true, 'message' => 'No season found!')); 141 | 142 | $this->response(['error' => false, 'seasons' => $seasons]); 143 | } 144 | 145 | public function get_movies() 146 | { 147 | $server_id = Input::get('server_id'); 148 | $season_id = Input::get('season_id'); 149 | 150 | $server = Model_Server::find_by_pk($server_id); 151 | $season = Model_Season::find_by_pk($season_id); 152 | 153 | if(!$server) 154 | return $this->response(array('error' => true, 'message' => 'No server found!')); 155 | 156 | if(!$season) 157 | return $this->response(array('error' => true, 'message' => 'No season found!')); 158 | 159 | $movies = Model_Season::getMovies($server,$season); 160 | 161 | if(!$movies) 162 | return $this->response(array('error' => true, 'message' => 'No movie found!')); 163 | 164 | $this->response(array_merge(['error' => false], $movies)); 165 | } 166 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/rest/index.php: -------------------------------------------------------------------------------- 1 | ='); 30 | $result['version'] = $version ? true : false; 31 | 32 | $result['mysql'] = extension_loaded('mysql') || extension_loaded('mysqli') ? true : false; 33 | $result['pdo_mysql'] = extension_loaded('pdo_mysql') ? true : false; 34 | $result['simplexml'] = extension_loaded('SimpleXML') ? true : false; 35 | $result['curl'] = function_exists('curl_version') ? true : false; 36 | $result['config'] = is_writable('../fuel/app/config/') ? true : false; 37 | 38 | return $this->response($result); 39 | } 40 | 41 | public function post_config() 42 | { 43 | try { 44 | $host = Input::post('host'); 45 | $port = Input::post('port'); 46 | $dbname = Input::post('database'); 47 | $username = Input::post('username'); 48 | $password = Input::post('password'); 49 | 50 | $boolean = Config::load('db', true); 51 | 52 | if(!$boolean) 53 | throw new FuelException('Config db.php not work!'); 54 | 55 | $config = array( 56 | 'active' => 'default', 57 | 'default' => array( 58 | 'type' => 'pdo', 59 | 'connection' => array( 60 | 'dsn' => 'mysql:host=' . $host . ($port ? ';port=' . $port : '') . ';dbname=' . $dbname, 61 | 'hostname' => $host, 62 | 'port' => $port, 63 | 'database' => $dbname, 64 | 'username' => $username, 65 | 'password' => $password, 66 | ), 67 | 'table_prefix' => 'plex_', 68 | 'charset' => 'utf8', 69 | 'enable_cache' => true, 70 | 'hash' => Str::random('alnum', 32) 71 | ), 72 | ); 73 | 74 | Config::save('db', $config); 75 | 76 | return $this->response(array('error' => false)); 77 | }catch (FuelException $e) { 78 | return $this->response(array('error' => true, 'message' => $e->getMessage()), 400); 79 | } 80 | } 81 | 82 | public function post_tables() 83 | { 84 | 85 | Config::load('db', true); 86 | 87 | try { 88 | $migration = Migrate::current(); 89 | 90 | $logs = 'All Tables and Foreign Key are successfully install!'."\r\n"; 91 | 92 | return $this->response(['error' => false, 'message' => $logs]); 93 | } catch (FuelException $e) { 94 | try { 95 | DBUtil::drop_table('user_history'); 96 | DBUtil::drop_table('user_permission'); 97 | DBUtil::drop_table('user_settings'); 98 | DBUtil::drop_table('library_permission'); 99 | DBUtil::drop_table('movie'); 100 | DBUtil::drop_table('season'); 101 | DBUtil::drop_table('tvshow'); 102 | DBUtil::drop_table('library'); 103 | DBUtil::drop_table('server'); 104 | DBUtil::drop_table('configurations'); 105 | DBUtil::drop_table('user'); 106 | DBUtil::drop_table('permission'); 107 | DBUtil::drop_table('library'); 108 | 109 | return $this->response(array('error' => true, 'message' => $e->getMessage()), 400); 110 | } catch (FuelException $e) { 111 | return $this->response(array('error' => true, 'message' => $e->getMessage()), 400); 112 | } 113 | } 114 | } 115 | 116 | public function post_admin() 117 | { 118 | try { 119 | $configCrypt = Config::load('crypt', true); 120 | 121 | $email = Input::post('email'); 122 | $username = Input::post('username'); 123 | $password = Input::post('password'); 124 | $Cpassword = Input::post('cpassword'); 125 | 126 | if($password !== $Cpassword) 127 | throw new FuelException('Password match error!'); 128 | 129 | $user = Model_User::forge(array( 130 | 'username' => $username, 131 | 'email' => $email, 132 | 'password' => hash('sha512', $configCrypt['sodium']['cipherkey'] . $password), 133 | 'admin' => 1, 134 | 'lastlogin' => time() 135 | )); 136 | 137 | if(!$user->validates()) { 138 | throw new FuelException($user->validation()->show_errors()); 139 | } 140 | 141 | $user->save(); 142 | 143 | return $this->response(array('error' => false)); 144 | } catch (Exception $e) { 145 | return $this->response(array('error' => true, 'message' => $e->getMessage()), 404); 146 | } 147 | } 148 | 149 | public function post_plex() 150 | { 151 | try { 152 | $url = Input::post('url'); 153 | $https = Input::post('https'); 154 | $port = Input::post('port'); 155 | $token = Input::post('token'); 156 | 157 | $curl = Request::forge(($https === '1' ? 'https' : 'http') . '://' . $url . ($port ? ':' . $port : '') . '/?X-Plex-Token=' . $token, 'curl'); 158 | $result = $curl->execute(); 159 | 160 | if(!$result) 161 | throw new FuelException('Can not connect to your server!'); 162 | 163 | $user = Model_User::find_one_by('admin', 1); 164 | 165 | $server = Model_Server::forge(); 166 | $server->set([ 167 | 'user_id' => $user->id, 168 | 'https' => (int)$https, 169 | 'url' => $url, 170 | 'port' => (int)$port, 171 | 'token' => $token, 172 | 'lastcheck' => time() 173 | ]); 174 | $server->save(); 175 | 176 | Config::save('lock', array('FUCK OFF!')); 177 | 178 | return $this->response(array('error' => false)); 179 | } catch (FuelException $e) { 180 | return $this->response(array('error' => true, 'message' => $e->getMessage()), 400); 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /fuel/app/classes/controller/rest/library.php: -------------------------------------------------------------------------------- 1 | id; 26 | 27 | $library_permission = Model_Library_Permission::find_one_by(function ($query) use ($library_id, $permission_id) { 28 | $query 29 | ->where('library_id', $library_id) 30 | ->and_where('permission_id', $permission_id); 31 | }); 32 | 33 | 34 | if ($library_permission === null) { 35 | $library_permission = new Model_Library_Permission(); 36 | $library_permission->library_id = $library_id; 37 | $library_permission->permission_id = $permission_id; 38 | } 39 | 40 | if ($checked === 'false') 41 | $library_permission->disable = true; 42 | else 43 | $library_permission->disable = false; 44 | 45 | if($parameter !== null) 46 | $library_permission->value = $parameter; 47 | 48 | $library_permission->save(); 49 | 50 | return $this->response(['error' => false, 'message' => 'Permission modify successfully']); 51 | } catch (Exception $exception) { 52 | return $this->response(['error' => true, 'message' => $exception->getMessage()]); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /fuel/app/classes/controller/rest/movie.php: -------------------------------------------------------------------------------- 1 | id; 27 | 28 | $user_histories = Model_User_History::find(function ($query) use ($movie_id, $user_id) { 29 | $startOfDay = date("Y-m-d 00:00:00"); 30 | $endOfDay = date("Y-m-d 23:59:59"); 31 | $query->select(DB::expr('count(id) as count')) 32 | ->where('user_id', $user_id) 33 | ->and_where('movie_id', '<>', $movie_id) 34 | ->and_where('date', '>=', strtotime($startOfDay)) 35 | ->and_where('date', '<=', strtotime($endOfDay)) 36 | ; 37 | }); 38 | 39 | if (Model_Permission::isGranted('RIGHT_WATCH_DISABLED', $movie->getLibrary())) 40 | throw new FuelException('You dont have the permission to watch in this library!'); 41 | 42 | if (!Model_Permission::isGranted('RIGHT_MAX_WATCH', $movie->getLibrary(), $user_histories[0]->count)) 43 | throw new FuelException('You have reach the maximum number of watch in this library for today!'); 44 | 45 | $user_settings = Model_User_Settings::find_one_by('user_id', Session::get('user')->id); 46 | 47 | if ($movie->type !== 'movie') 48 | $episodes = $movie->getSeason()->getEpisodes(); 49 | else 50 | $episodes = [$movie]; 51 | 52 | $view = View::forge('player/index'); 53 | 54 | $view->set('user_settings', $user_settings); 55 | $view->set('movie', $movie); 56 | $view->set('episodes', $episodes); 57 | 58 | return $this->response($view->render()); 59 | } catch (Exception $exception) { 60 | return $this->response($exception->getMessage(), 500); 61 | } 62 | } 63 | 64 | public function post_watching() 65 | { 66 | try { 67 | $user_id = Session::get('user')->id; 68 | $movie_id = Input::post('movie_id'); 69 | $totaltime = Input::post('totaltime'); 70 | $timeplay = Input::post('timeplay'); 71 | $is_ended = Input::post('is_ended') === 'true'; 72 | 73 | if (!$movie_id) 74 | throw new FuelException('No movie id'); 75 | 76 | $movie = Model_Movie::find_by_pk($movie_id); 77 | 78 | if (!$movie) 79 | throw new FuelException('No movie found'); 80 | 81 | $user_histories = Model_User_History::find(function ($query) use ($movie_id, $user_id) { 82 | $startOfDay = date("Y-m-d 00:00:00"); 83 | $endOfDay = date("Y-m-d 23:59:59"); 84 | $query->select(DB::expr('count(id) as count')) 85 | ->where('user_id', $user_id) 86 | ->and_where('movie_id', '<>', $movie_id) 87 | ->and_where('date', '>=', strtotime($startOfDay)) 88 | ->and_where('date', '<=', strtotime($endOfDay)) 89 | ; 90 | }); 91 | 92 | if (Model_Permission::isGranted('RIGHT_WATCH_DISABLED', $movie->getLibrary())) 93 | throw new FuelException('You dont have the permission to watch in this library!'); 94 | 95 | if (!Model_Permission::isGranted('RIGHT_MAX_WATCH', $movie->getLibrary(), $user_histories[0]->count)) 96 | throw new FuelException('You have reach the maximum number of watch in this library for today!'); 97 | 98 | $watching = Model_User_History::find_one_by([ 99 | ['movie_id', '=', $movie_id], 100 | ['user_id', '=', $user_id], 101 | ['is_ended', '=', 0] 102 | ]); 103 | 104 | $params = []; 105 | 106 | if($watching && $watching->date + (24 * 60 * 60) < time()) 107 | { 108 | $watching->set(['is_ended' => $is_ended]); 109 | $watching->save(); 110 | 111 | $watching = null; 112 | } 113 | 114 | if($watching === null){ 115 | $watching = new Model_User_History(); 116 | $params['date'] = time(); 117 | } 118 | 119 | $params = array_merge($params, ['user_id' => $user_id, 120 | 'movie_id' => $movie_id, 121 | 'watching_time' => $timeplay, 122 | 'ended_time' => $totaltime, 123 | 'is_ended' => $is_ended]); 124 | 125 | $watching->set($params); 126 | 127 | $watching->save(); 128 | 129 | return $this->response('OK', 200); 130 | 131 | } catch (Exception $exception) { 132 | return $this->response($exception->getMessage(), 500); 133 | } 134 | } 135 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/rest/player.php: -------------------------------------------------------------------------------- 1 | id] 30 | ]) ?: new Model_User_History(); 31 | 32 | return $this->response(['error' => false, 'message' => 'OK!'], 200); 33 | } catch (Exception $exception) { 34 | return $this->response($exception->getMessage(), 500); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/rest/search.php: -------------------------------------------------------------------------------- 1 | bind('search', $search); 22 | $movies = $query->execute(); 23 | 24 | $query = DB::query('SELECT * FROM '.DB::table_prefix('tvshow').' 25 | WHERE MATCH('.DB::table_prefix('tvshow').'.`title`) AGAINST(:search IN BOOLEAN MODE) 26 | ORDER BY MATCH('.DB::table_prefix('tvshow').'.`title`) AGAINST(:search IN BOOLEAN MODE) DESC LIMIT 4'); 27 | $query->bind('search', $search); 28 | $tv_shows = $query->execute(); 29 | 30 | $results = []; 31 | 32 | foreach ($movies as $movie) { 33 | $data = [ 34 | 'id' => $movie['id'], 35 | 'type' => $movie['type'], 36 | 'title' => $movie['title'], 37 | 'year' => $movie['type'] === 'movie' ? $movie['year'] : '', 38 | 'tvshow' => $movie['tvshow'] ?? '', 39 | ]; 40 | 41 | $results[] = $data; 42 | } 43 | 44 | foreach ($tv_shows as $movie) { 45 | $data = [ 46 | 'id' => $movie['id'], 47 | 'type' => 'tvshow', 48 | 'title' => $movie['title'], 49 | 'year' => $movie['year'], 50 | 'tvshow' => $movie['tvshow'] ?? '', 51 | ]; 52 | 53 | $results[] = $data; 54 | } 55 | 56 | return $this->response($results); 57 | } 58 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/rest/settings.php: -------------------------------------------------------------------------------- 1 | response($view->render()); 17 | } 18 | 19 | public function post_server() 20 | { 21 | try { 22 | $server_id = Input::post('server_id'); 23 | $url = Input::post('url'); 24 | $port = Input::post('port'); 25 | $token = Input::post('token'); 26 | $https = Input::post('https') === 'true' ? true : false; 27 | 28 | //@TODO CHECK AND REMOVE HTTP AND HTTPS 29 | $curl = Request::forge(($https ? 'https' : 'http') . '://' . $url . (!empty($port) ? ':' . $port : '') . '/?X-Plex-Token=' . $token, 'curl'); 30 | 31 | if($https) { 32 | $curl->set_options([ 33 | CURLOPT_SSL_VERIFYPEER => false, 34 | CURLOPT_SSL_VERIFYHOST => false 35 | ]); 36 | } 37 | 38 | $result = $curl->execute(); 39 | 40 | if(!$result) 41 | throw new FuelException('Can not connect to your server!'); 42 | 43 | $server = ($server_id === '' ? Model_Server::forge() : Model_Server::find_by_pk($server_id)); 44 | $server->set([ 45 | 'user_id' => Session::get('user')->id, 46 | 'https' => $https, 47 | 'url' => $url, 48 | 'port' => !empty($port) ? $port : null, 49 | 'token' => $token, 50 | 'lastcheck' => time() 51 | ]); 52 | $server->save(); 53 | 54 | return $this->response(['error' => false]); 55 | } catch (FuelException $e) { 56 | return $this->response(['error' => true, 'message' => $e->getMessage() ?: 'Wrong parameters'], $e->getCode() > 100 ? $e->getCode() : null); 57 | } 58 | } 59 | 60 | public function delete_server() 61 | { 62 | try { 63 | $server = Input::delete('server_id'); 64 | $user = Session::get('user'); 65 | 66 | $server = Model_Server::find_by_pk($server); 67 | 68 | if(!$server || $server->user_id !== $user->id) 69 | throw new FuelException('No server found!'); 70 | 71 | $server->set(['disable' => 1]); 72 | $server->save(); 73 | 74 | return $this->response(array('error' => false)); 75 | } catch (FuelException $e) { 76 | return $this->response(array('error' => true, 'message' => $e->getMessage() ?: 'Wrong parameters'), 400); 77 | } 78 | } 79 | 80 | public function put_library() 81 | { 82 | try { 83 | $library = Input::put('library_id'); 84 | 85 | $library = Model_Library::find_one_by(function($query) use($library) { 86 | $query 87 | ->join('server', 'LEFT') 88 | ->on('server.id', '=','library.server_id' ) 89 | ->where('server.user_id', Session::get('user')->id) 90 | ->and_where('library.id', $library) 91 | ->and_where('library.disable', 1) 92 | ->and_where('server.disable', 0) 93 | ; 94 | }); 95 | 96 | if(!$library) 97 | throw new FuelException('No disable library found!'); 98 | 99 | $library->set(['disable' => 0]); 100 | $library->save(); 101 | 102 | return $this->response(array('error' => false)); 103 | } catch (FuelException $e) { 104 | return $this->response(array('error' => true, 'message' => $e->getMessage() ?: 'Wrong parameters'), 400); 105 | } 106 | } 107 | 108 | public function delete_library() 109 | { 110 | try { 111 | $library = Input::delete('library_id'); 112 | 113 | $library = Model_Library::find_one_by(function($query) use($library) { 114 | $query 115 | ->join('server', 'LEFT') 116 | ->on('server.id', '=','library.server_id' ) 117 | ->where('server.user_id', Session::get('user')->id) 118 | ->and_where('library.id', $library) 119 | ->and_where('library.disable', 0) 120 | ->and_where('server.disable', 0) 121 | ; 122 | }); 123 | 124 | if(!$library) 125 | throw new FuelException('No active library found!'); 126 | 127 | $library->set(['disable' => 1]); 128 | $library->save(); 129 | 130 | return $this->response(array('error' => false)); 131 | } catch (FuelException $e) { 132 | return $this->response(array('error' => true, 'message' => $e->getMessage() ?: 'Wrong parameters'), 400); 133 | } 134 | } 135 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/season.php: -------------------------------------------------------------------------------- 1 | param('season_id'); 12 | 13 | $season = Model_Season::find_by_pk($season_id); 14 | 15 | if(!$season) 16 | Response::redirect('/home'); 17 | 18 | Lang::load('movie'); 19 | Lang::load('season'); 20 | Lang::load('action'); 21 | 22 | $body = View::forge('season/index'); 23 | 24 | $seasons = $season->getTvShow()->getSeasons(); 25 | 26 | $this->template->title = $season->getTvShow()->title . ' S' . $season->number; 27 | 28 | $body->set('season', $season); 29 | $body->set('seasons', $seasons); 30 | 31 | $this->template->body = $body; 32 | } 33 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/security.php: -------------------------------------------------------------------------------- 1 | _user = Session::get('user'); 21 | 22 | if(!$this->_user) 23 | Response::redirect('/login'); 24 | 25 | Lang::load('menu'); 26 | Lang::load('settings'); 27 | Lang::load('action'); 28 | 29 | $user_id = $this->_user->id; 30 | 31 | $servers = Model_Server::find(function($query) use($user_id) { 32 | $query 33 | ->where('user_id', $user_id) 34 | ; 35 | }); 36 | 37 | $libraries = Model_Library::find(function($query) use($user_id) { 38 | $query 39 | ->select('library.*') 40 | ->join('server', 'LEFT') 41 | ->on('server.id', '=','library.server_id' ) 42 | ->where('server.user_id', $user_id) 43 | ->and_where('server.disable', 0) 44 | ->and_where('server.online', 1) 45 | ; 46 | }); 47 | 48 | $this->template->countServers = $servers ? count($servers) : 0; 49 | 50 | $this->template->countLibraries = $libraries ? count($libraries): 0; 51 | 52 | $this->template->servers = $servers; 53 | 54 | $this->template->libraries = $libraries; 55 | 56 | $this->template->user = $this->_user; 57 | 58 | $this->template->js_bottom = []; 59 | } 60 | 61 | public function action_index() 62 | { 63 | $body = View::forge('settings/index'); 64 | 65 | $default_settings = Config::load('user_settings'); 66 | 67 | $settings = Model_User_Settings::find_one_by('user_id', Session::get('user')->id); 68 | 69 | $is_submit = Input::post('submit'); 70 | 71 | if(isset($is_submit)) { 72 | $settings = !empty($settings) ? $settings : new Model_User_Settings(); 73 | $settings->set([ 74 | 'user_id' => $this->_user->id, 75 | 'language' => Input::post('language'), 76 | 'trailer_type'=> Input::post('typeTrailer'), 77 | 'trailer' => Input::post('trailerCount'), 78 | 'subtitle' => Input::post('subtitleSize'), 79 | 'maxdownloadspeed' => Input::post('maxdownloadspeed') 80 | ]); 81 | $settings->save(); 82 | } 83 | 84 | $body->set('default_settings', $default_settings); 85 | $body->set('settings', $settings); 86 | 87 | $this->template->body = $body; 88 | } 89 | 90 | public function action_servers() 91 | { 92 | Lang::load('settings'); 93 | 94 | $this->template->js_bottom = ['plex_alert.js', 'server_refresh.js']; 95 | 96 | $body = View::forge('settings/servers'); 97 | 98 | $body->set('countServers',$this->template->countServers); 99 | $body->set('servers', $this->template->servers); 100 | $body->set('user', Session::get('user')); 101 | 102 | $this->template->body = $body; 103 | } 104 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/settings/libraries.php: -------------------------------------------------------------------------------- 1 | template->js_bottom = ['plex_alert.js', 'server_refresh.js']; 12 | $this->template->css = ['settings.css']; 13 | 14 | $body = View::forge('settings/libraries'); 15 | 16 | $body->set('countLibraries', $this->template->countLibraries); 17 | $body->set('libraries', $this->template->libraries); 18 | $body->set('user', Session::get('user')); 19 | 20 | $this->template->body = $body; 21 | } 22 | 23 | public function action_permissions() 24 | { 25 | $this->template->js_bottom = ['plex_alert.js']; 26 | 27 | Lang::load('permissions'); 28 | 29 | $body = View::forge('settings/libraries/permissions'); 30 | 31 | $library_id = $this->param('library_id'); 32 | 33 | $library = Model_Library::find_by_pk($library_id); 34 | 35 | if($library === null) 36 | Response::redirect('/settings/libraries'); 37 | 38 | $permissions = Model_Permission::find_by('disable', 0); 39 | 40 | $library_permissions = Model_Library_Permission::find_by('library_id', $library_id) ?: []; 41 | 42 | $temp = []; 43 | 44 | // ORDER ARRAY BY PERMISSION ID 45 | // MORE EASY TO DISPLAY 46 | foreach ($library_permissions as $library_permission) { 47 | $temp[$library_permission->permission_id] = $library_permission; 48 | } 49 | 50 | $library_permissions = $temp; 51 | 52 | $body->set('library', $library); 53 | $body->set('permissions', $permissions); 54 | $body->set('library_permissions', $library_permissions); 55 | $body->set('user', Session::get('user')); 56 | 57 | $this->template->body = $body; 58 | } 59 | } -------------------------------------------------------------------------------- /fuel/app/classes/controller/tvshow.php: -------------------------------------------------------------------------------- 1 | param('tvshow_id'); 12 | 13 | $tvshow = Model_Tvshow::find_by_pk($tvshow_id); 14 | 15 | if(!$tvshow) 16 | Response::redirect('/home'); 17 | 18 | Lang::load('movie'); 19 | Lang::load('season'); 20 | Lang::load('action'); 21 | 22 | $body = View::forge('tvshow/index'); 23 | 24 | $this->template->title = $tvshow->title; 25 | 26 | $tvshow->getMetaData(); 27 | 28 | $body->set('tvshow', $tvshow); 29 | 30 | $this->template->body = $body; 31 | } 32 | } -------------------------------------------------------------------------------- /fuel/app/classes/database/query/builder/insert.php: -------------------------------------------------------------------------------- 1 | _values)) 20 | { 21 | throw new \FuelException('INSERT INTO ... SELECT statements cannot be combined with INSERT INTO ... VALUES'); 22 | } 23 | 24 | // Get all of the passed values 25 | $values = func_get_args(); 26 | 27 | //OVERRIDE 28 | if (isset($this->_values) && !empty($this->_values)) { 29 | $this->_values[0] = array_merge($this->_values[0], $values[0]); 30 | } else { 31 | $this->_values = array_merge($this->_values, $values); 32 | } 33 | 34 | return $this; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /fuel/app/classes/file.php: -------------------------------------------------------------------------------- 1 | _server) 27 | $this->_server = Model_Server::find_by_pk($this->server_id); 28 | 29 | return $this->_server; 30 | } 31 | 32 | public function getLastUpdate() 33 | { 34 | $dateString = date('Y/m/d H:i:s', time()); 35 | $now = new DateTime($dateString); 36 | 37 | $dateString = date('Y-m-d H:i:s', $this->updatedAt); 38 | $time = new DateTime($dateString); 39 | 40 | $diff = date_diff($now, $time); 41 | 42 | $days = $diff->days . 'd '; 43 | $hours = $diff->h . 'h '; 44 | $minutes = $diff->i . 'min '; 45 | $seconds = $diff->s . 's'; 46 | 47 | return $days.$hours.$minutes.$seconds; 48 | } 49 | 50 | /** 51 | * List all libraries and register it in database 52 | * @param $server 53 | * @return bool | array 54 | * @throws FuelException 55 | */ 56 | public static function BrowseLibraries($server) 57 | { 58 | try { 59 | $libraries_id_array = []; 60 | 61 | $curl = Request::forge(($server->https ? 'https' : 'http') . '://' . $server->url . ($server->port ? ':' . $server->port : '') . '/library/sections?X-Plex-Token=' . $server->token, 'curl'); 62 | 63 | if($server->https) { 64 | $curl->set_options([ 65 | CURLOPT_SSL_VERIFYPEER => false, 66 | CURLOPT_SSL_VERIFYHOST => false 67 | ]); 68 | } 69 | 70 | $curl->execute(); 71 | 72 | if ($curl->response()->status !== 200) 73 | return false; 74 | 75 | $list_libraries = Format::forge($curl->response()->body, 'xml')->to_array(); 76 | 77 | if (!isset($list_libraries['Directory'])) 78 | return false; 79 | 80 | $list_libraries = $list_libraries['Directory']; 81 | 82 | foreach ($list_libraries as $index => $library) { 83 | $library = !isset($list_libraries['@attributes']) ? $library : $list_libraries; 84 | 85 | $new_library = Model_Library::find_by_pk($library['@attributes']['uuid']) ?: Model_Library::forge(); 86 | 87 | if ((isset($new_library->disable) && $new_library->disable) || ($library['@attributes']['type'] !== 'show' && $library['@attributes']['type'] !== 'movie')) 88 | continue; 89 | 90 | $libraries_id_array[] = ['id' => $library['@attributes']['uuid'], 'name' => $library['@attributes']['title']]; 91 | 92 | $new_library->set(array( 93 | 'id' => $library['@attributes']['uuid'], 94 | 'plex_key' => $library['@attributes']['key'], 95 | 'server_id' => $server->id, 96 | 'name' => $library['@attributes']['title'], 97 | 'type' => $library['@attributes']['type'], 98 | 'updatedAt' => time(), 99 | 'createdAt' => $library['@attributes']['createdAt'], 100 | 'scannedAt' => $library['@attributes']['scannedAt'] 101 | )); 102 | 103 | $new_library->save(); 104 | 105 | //self::getSectionsContent($server, $new_library); 106 | 107 | if (isset($list_libraries['@attributes'])) 108 | break; 109 | } 110 | 111 | return $libraries_id_array; 112 | } catch (Exception $exception) { 113 | throw new FuelException($exception->getMessage(),$exception->getCode()); 114 | } 115 | } 116 | 117 | /** 118 | * @param $server 119 | * @param $library 120 | * @return bool 121 | * @throws FuelException 122 | */ 123 | public static function getLibraryContents($server, $library) 124 | { 125 | $curl = Request::forge(($server->https ? 'https' : 'http').'://' . $server->url . ($server->port? ':' . $server->port : '') . '/library/sections/' . $library->plex_key . '/all?X-Plex-Token=' . $server->token, 'curl'); 126 | 127 | if($server->https) { 128 | $curl->set_options([ 129 | CURLOPT_SSL_VERIFYPEER => false, 130 | CURLOPT_SSL_VERIFYHOST => false 131 | ]); 132 | } 133 | 134 | $curl->execute(); 135 | 136 | if($curl->response()->status !== 200) 137 | return false; 138 | 139 | $section_content = Format::forge($curl->response()->body, 'xml')->to_array(); 140 | 141 | if(isset($section_content['Directory'])) 142 | return ['tvshows' => Model_Tvshow::BrowseTvShow($server, $section_content['Directory'], $library)]; 143 | else if(isset($section_content['Video'])) 144 | return ['movies' => Model_Movie::BrowseMovies($server, $section_content['Video'], $library)]; 145 | } 146 | } -------------------------------------------------------------------------------- /fuel/app/classes/model/library/permission.php: -------------------------------------------------------------------------------- 1 | value('disable', 1) 22 | ->where(static::primary_key(), '=', $this->{static::primary_key()}) : null; 23 | 24 | $this->pre_delete($query); 25 | $result = $query ? $query->execute(static::get_connection(true)) : null; 26 | 27 | return $this->post_delete($result); 28 | } 29 | 30 | /** 31 | * Use it to force to use UUID to primary key 32 | * @param \Fuel\Core\Database_Query $query 33 | */ 34 | protected function pre_save(&$query) 35 | { 36 | if($this->is_new()) { 37 | if(!isset($this->{static::primary_key()}) || !$this->{static::primary_key()} || $this->{static::primary_key()} === null) { 38 | $this->{static::primary_key()} = Str::random('uuid'); 39 | $query->set([static::primary_key() => $this->{static::primary_key()}]); 40 | } 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /fuel/app/classes/model/permission.php: -------------------------------------------------------------------------------- 1 | id], 45 | ['permission_id', '=', $permission->id], 46 | ['disable', '=', 0] 47 | ]); 48 | 49 | if ($permission->name === 'RIGHT_WATCH_DISABLED') { 50 | if($library_permission === null) 51 | return false; 52 | else 53 | return true; 54 | } 55 | 56 | if ($permission->name === 'RIGHT_DOWNLOAD_DISABLED') { 57 | if($library_permission === null) 58 | return false; 59 | else 60 | return true; 61 | } 62 | 63 | if ($permission->name === 'RIGHT_TRAILER_DISABLED') { 64 | if($library_permission === null) 65 | return false; 66 | else 67 | return true; 68 | } 69 | 70 | if ($permission->name === 'RIGHT_MAX_DOWNLOAD') { 71 | /** @TODO IF (MAX_DOWNLOAD > NUMBER_DOWNLOAD) // in last 24h 72 | * RETURN FALSE 73 | * ELSE 74 | * RETURN TRUE 75 | */ 76 | if($library_permission === NULL) 77 | return true; 78 | else if((int)$library_permission->value > $data) 79 | return true; 80 | else 81 | return false; 82 | } 83 | 84 | if ($permission->name === 'RIGHT_MAX_DOWNLOAD_SPEED') { 85 | /** @TODO IF (ENABLED) 86 | * RETURN VALUE 87 | * ELSE 88 | * RETURN 0 89 | */ 90 | return true; 91 | } 92 | 93 | if ($permission->name === 'RIGHT_MAX_WATCH') { 94 | /** @TODO IF (MAX_WATCH > NUMBER_WATCH) // in last 24h 95 | * RETURN FALSE 96 | * ELSE 97 | * RETURN TRUE 98 | */ 99 | if($library_permission === NULL) 100 | return true; 101 | else if((int)$library_permission->value > $data) 102 | return true; 103 | else 104 | return false; 105 | } 106 | 107 | if ($permission->name === 'RIGHT_MAX_QUALITY') { 108 | /** @TODO IF (VIDEO SETTINGS QUALITY <= MAX_QUALITY) 109 | * RETURN TRUE 110 | * ELSE 111 | * RETURN FALSE 112 | */ 113 | return true; 114 | } 115 | 116 | if ($permission->name === 'RIGHT_MAX_CONCURRENT_STREAM') { 117 | /** @TODO IF (CURRENT STREAMING <= MAX_CONCURRENT_STREAM) 118 | * RETURN TRUE 119 | * ELSE 120 | * RETURN FALSE 121 | */ 122 | return true; 123 | } 124 | 125 | return false; 126 | } 127 | } -------------------------------------------------------------------------------- /fuel/app/classes/model/trailer.php: -------------------------------------------------------------------------------- 1 | _id = $id; 23 | $this->_title = $title; 24 | $this->_year = $year; 25 | $this->_type = $type; 26 | } 27 | 28 | /** 29 | * @return mixed 30 | */ 31 | public function getTrailer() 32 | { 33 | try { 34 | throw new CacheNotFoundException(''); 35 | $this->_trailer = Cache::get($this->_id.'.trailer'); 36 | return $this->_trailer; 37 | } catch (CacheNotFoundException $e) 38 | { 39 | $this->getUrl(); 40 | 41 | if(!$this->_trailer_url) 42 | return null; 43 | 44 | $this->_getTrailer(); 45 | 46 | if(!$this->_trailer) 47 | $this->_getTeaser(); 48 | 49 | if(!$this->_trailer) 50 | return null; 51 | 52 | Cache::set($this->_id . '.trailer', $this->_trailer, 24 * 60 * 60); 53 | return $this->_trailer; 54 | } 55 | } 56 | 57 | private function getUrl() 58 | { 59 | try { 60 | $this->_trailer_url = Cache::get($this->_id.'.trailer_url'); 61 | return $this->_trailer_url; 62 | } catch (CacheNotFoundException $e) 63 | { 64 | $type = $this->_type === 'movie' ? 'movie' : 'tv'; 65 | 66 | $entities = array('%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D', '%2B', '%24', '%2C', '%2F', '%3F', '%25', '%23', '%5B', '%5D'); 67 | $replacements = array('!', '*', "'", "(", ")", ";", ":", "@", "&", "=", "+", "$", ",", "/", "?", "%", "#", "[", "]"); 68 | $title = str_replace($entities, $replacements, urlencode(htmlspecialchars_decode($this->_title, ENT_QUOTES))); 69 | 70 | $html = Request::forge('https://www.themoviedb.org/search/' . $type . '?query=' . $title . '+y%3A' . $this->_year . '&language=us', 'curl'); 71 | $html->set_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0'); 72 | 73 | $html->execute(); 74 | 75 | if ($html->response()->status !== 200) 76 | return false; 77 | 78 | $media = $html->response()->body; 79 | 80 | $regex = '//i'; 81 | 82 | preg_match($regex, $media, $urls); 83 | 84 | if (!isset($urls[1])) 85 | return false; 86 | 87 | $this->_trailer_url = explode('?', $urls[1])[0]; 88 | 89 | Cache::set($this->_id . '.trailer_url', $this->_trailer_url, 24 * 60 * 60); 90 | 91 | return true; 92 | } 93 | } 94 | 95 | private function _getTrailer() 96 | { 97 | $html = Request::forge('https://www.themoviedb.org' . $this->getUrl() . '/videos?active_nav_item=Trailers&video_language=en-US&language=en-US', 'curl'); 98 | $html->set_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0'); 99 | $html->set_options(array( 100 | CURLOPT_FOLLOWLOCATION => true, 101 | ) 102 | ); 103 | $html->execute(); 104 | 105 | if ($html->response()->status !== 200) 106 | return false; 107 | 108 | $media = $html->response()->body; 109 | 110 | $regex = '/.*<\/a>/'; 111 | 112 | preg_match($regex, $media, $youtube); 113 | 114 | if (!isset($youtube[1])) 115 | return false; 116 | 117 | $youtube = '//www.youtube.com/embed/'.$youtube[1].'?enablejsapi=1&autoplay=0&hl=en-US&modestbranding=1&fs=1'; 118 | 119 | $this->_trailer = $youtube; 120 | 121 | return true; 122 | } 123 | 124 | private function _getTeaser() 125 | { 126 | $html = Request::forge('https://www.themoviedb.org' . $this->getUrl() . '/videos?active_nav_item=Teasers&video_language=en-US&language=en-US', 'curl'); 127 | $html->set_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0'); 128 | $html->set_options([CURLOPT_FOLLOWLOCATION => true,]); 129 | $html->execute(); 130 | 131 | if ($html->response()->status !== 200) 132 | return false; 133 | 134 | $media = $html->response()->body; 135 | 136 | $regex = '/