├── .gitignore ├── LICENSE ├── README.md ├── plexrequests ├── __init__.py ├── admin.py ├── migrations │ └── __init__.py ├── models.py ├── templates │ └── plexrequests │ │ ├── add.html │ │ ├── base.html │ │ ├── results.html │ │ └── search.html ├── tests.py ├── urls.py └── views.py ├── requirements.txt └── screenshots ├── 1plexrequests_search.png ├── 2plexrequests_results.png └── 3plexrequests_add.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # PyInstaller 26 | # Usually these files are written by a python script from a template 27 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 28 | *.manifest 29 | *.spec 30 | 31 | # Installer logs 32 | pip-log.txt 33 | pip-delete-this-directory.txt 34 | 35 | # Unit test / coverage reports 36 | htmlcov/ 37 | .tox/ 38 | .coverage 39 | .cache 40 | nosetests.xml 41 | coverage.xml 42 | 43 | # Translations 44 | *.mo 45 | *.pot 46 | 47 | # Django stuff: 48 | *.log 49 | 50 | # Sphinx documentation 51 | docs/_build/ 52 | 53 | # PyBuilder 54 | target/ 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 lokenx 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Plex Requests 2 | 3 | **This project is no longer maintained. Please checkout [plexrequests-meteor](https://github.com/lokenx/plexrequests-meteor) for an updated project!** 4 | 5 | --- 6 | 7 | __Update 2:__ The meteor version of plex requests has switched to my main focus for now. It's got the same features as this version including CP integration. I'm putting a hold on this version for the time being. Check the meteor repo out [here](https://github.com/lokenx/plexrequests-meteor)! 8 | 9 | __Update:__ I've also started working on a meteor application that does most of what the Django version does. Why the change? I was playing around with the JS version and wondered if I could make the whole application that way...enter Meteor! I'm bringing it up to the same features the Django one has, and it includes the extra ability to view requested movies as well! Check the repo out [here](https://github.com/lokenx/plexrequests-meteor)! 10 | 11 | --- 12 | 13 | This is a simple Django application that relies on IMDB, CouchPotato and PushBullet to allow Plex users to request movies to be queued for downloading. For those of us with family and friends using our Plex Servers it allows a friendly way for them to requests new Movies with out having to bug you directly! 14 | 15 | This is my first django app/app just in general so it'll be rough around the edges and wrong in many places with unpleasant breakages I haven't found yet. I've warned you! 16 | 17 | ![plex_requests_search](/screenshots/1plexrequests_search.png) 18 | 19 | ## Requirements 20 | 21 | There is a pip requirements file included. I'm assuming you've a Django project already that you can add this app too, but if not you can create a simple one and import this application. Also I haven't tested this with the Django app and CouchPotato not being on the same LAN 22 | 23 | ##Quick Start 24 | 25 | 1. Clone the repository into your Django project 26 | 2. Add "plexrequests" to your INSTALLED_APPS setting at the bottom of the list of your settings.py file and a reference to the templates if you don't already have one 27 | `TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'templates')]` 28 | 3. Include the plexrequests URLconf into your projects urls.py as seen below (adjust as per your project needs): 29 | `url(r'^', include('plexrequests.urls', namespace="plexrequests")),` 30 | 4. Open the views.py file within the plexrequests directory as two smal changes need to be made 31 | - For CouchPotato to work you need to get your servers IP and API from within settings and copy it in on line 57 for variable cp_url. It should look like example below 32 | `http://192.168.0.100:5050/api/abcdefghijk0123456/` 33 | - For PushBullet enter your API key on line 67 such as below 34 | `Pushbullet("abcdefghijk0123456")` 35 | 5. Run `./manage.py migrate` to get the non-exist models created (they're coming!) 36 | 6. Start up the development server or reset your existing server and you should be able to see the app on `http://127.0.0.1:8000/` or whatever base URL you used in step 2. 37 | -------------------------------------------------------------------------------- /plexrequests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lokenx/plexrequests-django/bbb2cc9d72250558b8bbff39e8cb187aab7d2c11/plexrequests/__init__.py -------------------------------------------------------------------------------- /plexrequests/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | -------------------------------------------------------------------------------- /plexrequests/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lokenx/plexrequests-django/bbb2cc9d72250558b8bbff39e8cb187aab7d2c11/plexrequests/migrations/__init__.py -------------------------------------------------------------------------------- /plexrequests/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | -------------------------------------------------------------------------------- /plexrequests/templates/plexrequests/add.html: -------------------------------------------------------------------------------- 1 | {% extends "plexrequests/base.html" %} 2 | 3 | {% block content %} 4 |
5 | {% if a == "true" %} 6 |

Succes!

7 |

The movie has been successfully added to the downloader queue and will be added to Plex as soon as possible! If you want to look for another movie hit the link below!

8 | {% else %} 9 |

Opps!

10 |

The movie you've requested appears to already be downloaded or in the download queue. If you want to look for another movie hit the link below!

11 | {% endif %} 12 |

Search again!

13 |
14 | {% endblock %} -------------------------------------------------------------------------------- /plexrequests/templates/plexrequests/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Plex Requests 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 18 | 19 | 20 | 21 |
22 | {% block content %}{% endblock %} 23 |
24 | 25 | -------------------------------------------------------------------------------- /plexrequests/templates/plexrequests/results.html: -------------------------------------------------------------------------------- 1 | {% extends "plexrequests/base.html" %} 2 | 3 | {% block content %} 4 |
5 |

Search results

6 | {% if list %} 7 |

Found the below movies from IMDB.

8 | 9 |
10 | {% csrf_token %} 11 | {% for movie, id in list %} 12 |
13 | 16 |
17 | {% endfor %} 18 |
19 | 20 |
21 | {% endif %} 22 |
23 |

Not find what you were looking for? Try another search here!

24 |
25 | {% endblock %} -------------------------------------------------------------------------------- /plexrequests/templates/plexrequests/search.html: -------------------------------------------------------------------------------- 1 | {% extends "plexrequests/base.html" %} 2 | 3 | {% block content %} 4 |
5 |

Plex Requests!

6 |

Want to watch a movie but it's not currently on Plex?
7 | Use the search box below to do a quick IMDB search for a movie! 8 |

9 |
10 | {% csrf_token %} 11 |
12 | 13 |
14 |
15 | 16 |
17 |
18 |
19 | {% endblock %} -------------------------------------------------------------------------------- /plexrequests/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | -------------------------------------------------------------------------------- /plexrequests/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, url 2 | from plexrequests import views 3 | 4 | 5 | urlpatterns = patterns('', 6 | url(r'^$', views.search, name='search'), 7 | url(r'^results/$', views.results, name='results'), 8 | url(r'^add/$', views.add, name='add') 9 | ) -------------------------------------------------------------------------------- /plexrequests/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | import requests 3 | from bs4 import BeautifulSoup 4 | from pushbullet import Pushbullet 5 | 6 | 7 | def search(request): 8 | return render(request, 'plexrequests/search.html') 9 | 10 | 11 | def results(request): 12 | if 'q' in request.POST: 13 | q = request.POST['q'] 14 | m_list = get_movies(q) 15 | i_list = get_imdb(q) 16 | if not m_list: 17 | return redirect('/') 18 | else: 19 | c_list = zip(m_list, i_list) 20 | return render(request, 'plexrequests/results.html', 21 | {'list': c_list}) 22 | else: 23 | return redirect('/') 24 | 25 | 26 | def add(request): 27 | if 'movies' in request.POST: 28 | ma = request.POST['movies'] 29 | am = add_to_cp(ma) 30 | return render(request, 'plexrequests/add.html', 31 | {'a': am}) 32 | else: 33 | return redirect('/') 34 | 35 | 36 | def get_movies(search_for): 37 | url = "http://www.imdb.com/search/title?title_type=feature&title=" + search_for 38 | response = requests.get(url) 39 | movies_list = [] 40 | for each_url in BeautifulSoup(response.text).select(".image"): 41 | movie_title = each_url.a.get('title') 42 | movies_list.append(movie_title) 43 | return movies_list 44 | 45 | 46 | def get_imdb(search_for): 47 | url = "http://www.imdb.com/search/title?title_type=feature&title=" + search_for 48 | response = requests.get(url) 49 | movies_list = [] 50 | for each_url in BeautifulSoup(response.text).select(".image"): 51 | movie_imdb = each_url.a.get('href') 52 | movies_list.append(movie_imdb) 53 | return movies_list 54 | 55 | 56 | def add_to_cp(movie_req): 57 | cp_url = "youripofcouchpotatowithport+apikey/" 58 | url2 = cp_url + "media.get/?id=" + movie_req 59 | cp_reg = requests.get(url2) 60 | cp_json = cp_reg.json() 61 | if cp_json['success'] is False: 62 | url3 = cp_url + "movie.add/?identifier=" + movie_req 63 | requests.post(url3) 64 | url4 = url2 65 | cp_reg2 = requests.get(url4) 66 | cp_json2 = cp_reg2.json() 67 | pb_key = Pushbullet("yourpushbulletapi") 68 | pb_key.push_note("Plex Request", cp_json2['media']['title']) 69 | cp = "true" 70 | return cp 71 | else: 72 | cp = "false" 73 | return cp 74 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | beautifulsoup4==4.3.2 2 | Django==1.7.5 3 | pushbullet.py==0.8.1 4 | python-magic==0.4.6 5 | requests==2.5.3 6 | -------------------------------------------------------------------------------- /screenshots/1plexrequests_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lokenx/plexrequests-django/bbb2cc9d72250558b8bbff39e8cb187aab7d2c11/screenshots/1plexrequests_search.png -------------------------------------------------------------------------------- /screenshots/2plexrequests_results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lokenx/plexrequests-django/bbb2cc9d72250558b8bbff39e8cb187aab7d2c11/screenshots/2plexrequests_results.png -------------------------------------------------------------------------------- /screenshots/3plexrequests_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lokenx/plexrequests-django/bbb2cc9d72250558b8bbff39e8cb187aab7d2c11/screenshots/3plexrequests_add.png --------------------------------------------------------------------------------