Compare commits
6 Commits
2d42b60e26
...
v0.38.11
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4b3fb215c | ||
|
|
2fc6d792bc | ||
|
|
c9f1a2d93a | ||
|
|
bbdd11d1b5 | ||
|
|
1827908936 | ||
|
|
8b99a744e2 |
30
README.md
30
README.md
@@ -20,6 +20,9 @@ comparison to Stremio? That's because Torsearch uses the same source for media f
|
|||||||
|
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
For all pieces to work, you will need to serve the application over HTTPS. Running behind an SSL terminating
|
||||||
|
reverse proxy is the recommended approach.
|
||||||
|
|
||||||
1. Create a `compose.yml` file
|
1. Create a `compose.yml` file
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
@@ -116,7 +119,7 @@ TZ=America/Chicago
|
|||||||
###################
|
###################
|
||||||
# Symfony #
|
# Symfony #
|
||||||
###################
|
###################
|
||||||
# The external URL of the application where it can be reached by a browser.
|
# The external URL of the application where it can be reached by a browser. Should start with https://
|
||||||
APP_URL="<enter url>"
|
APP_URL="<enter url>"
|
||||||
# Requried by Symfony Framework. Feel free to change.
|
# Requried by Symfony Framework. Feel free to change.
|
||||||
APP_SECRET="70169beadfbc8101c393cbfbba27a313"
|
APP_SECRET="70169beadfbc8101c393cbfbba27a313"
|
||||||
@@ -154,7 +157,7 @@ DATABASE_URL="mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@${MYSQL_HOST}:3306/${MYSQL
|
|||||||
###################
|
###################
|
||||||
# Real Debrid #
|
# Real Debrid #
|
||||||
###################
|
###################
|
||||||
# Enter your Real Debrid API key is passed to Torrentio to retrieve download options
|
# Enter your Real Debrid API key which is passed to Torrentio to retrieve download options
|
||||||
REAL_DEBRID_KEY="<enter real debrid api key>"
|
REAL_DEBRID_KEY="<enter real debrid api key>"
|
||||||
|
|
||||||
|
|
||||||
@@ -185,10 +188,29 @@ AUTH_METHOD=form_login
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Run `docker compose up -d`
|
3. Enter the `APP_URL` in the .env file
|
||||||
|
4. Enter the `REAL_DEBRID_KEY` in the .env file
|
||||||
|
5. Enter a new `WEB_PORT` if the default doesn't work for you
|
||||||
|
4. Run `docker compose up -d`
|
||||||
4. Visit the app in the browser
|
4. Visit the app in the browser
|
||||||
5. Create your first user
|
5. Create a user
|
||||||
6. Visit the Preferences page to set your filter. This filter is used whenever you don't choose a specific file to
|
6. Visit the Preferences page to set your filter. This filter is used whenever you don't choose a specific file to
|
||||||
download (e.g. downloading via Monitor or clicking the "Download Season", "Download Selected", or "Download Episode" buttons).
|
download (e.g. downloading via Monitor or clicking the "Download Season", "Download Selected", or "Download Episode" buttons).
|
||||||
7. Start downloading media!
|
7. Start downloading media!
|
||||||
|
|
||||||
|
## Having issues?
|
||||||
|
Submit an issue in the repo, and I'll try to address it as soon as possible. I do have a full-time job and family, so my
|
||||||
|
time is limited, but I'll do my best!
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
This is my first contribution to open-source, the community that's given me so much over the years!
|
||||||
|
This project has been my personal hobby project for the last 1.5 years. I've written and re-written it several times.
|
||||||
|
It's been my testing ground for trying new things, so if the code looks like shit, my bad. I'm a PHP developer by day and
|
||||||
|
tinkerer by night - this was my first go with Symfony/Twig components, tailwind, the Symfony RICH bundle, and a lot more.
|
||||||
|
At some point, I'll put together a contribution guide, so others can hack on it too.
|
||||||
|
|
||||||
|
No AI was used for development (only to generate a list of countries with their flag emojis). If the code is bad, it's my fault.
|
||||||
|
|
||||||
|
# Disclaimer
|
||||||
|
Torsearch does not host any media; it only combines API results from multiple sources to make browsing them easier.
|
||||||
|
Torsearch is not affiliated with Real Debrid, Torrentio, or TMDB.
|
||||||
|
|||||||
2
assets/bootstrap.js
vendored
2
assets/bootstrap.js
vendored
@@ -5,6 +5,7 @@ import DownloadOptionTr from './components/download-option-tr.js';
|
|||||||
import DownloadListRow from './components/download-list-row.js';
|
import DownloadListRow from './components/download-list-row.js';
|
||||||
import MonitorListRow from './components/monitor-list-row.js';
|
import MonitorListRow from './components/monitor-list-row.js';
|
||||||
import MovieContainer from "./components/movie-container.js";
|
import MovieContainer from "./components/movie-container.js";
|
||||||
|
import StatusCheckerSpan from "./components/status-checker-span.js";
|
||||||
|
|
||||||
import { startStimulusApp } from '@symfony/stimulus-bundle';
|
import { startStimulusApp } from '@symfony/stimulus-bundle';
|
||||||
import Popover from '@stimulus-components/popover';
|
import Popover from '@stimulus-components/popover';
|
||||||
@@ -24,3 +25,4 @@ customElements.define('movie-container', MovieContainer);
|
|||||||
customElements.define('dl-tr', DownloadOptionTr, {extends: 'tr'});
|
customElements.define('dl-tr', DownloadOptionTr, {extends: 'tr'});
|
||||||
customElements.define('download-list-row', DownloadListRow, {extends: 'tr'});
|
customElements.define('download-list-row', DownloadListRow, {extends: 'tr'});
|
||||||
customElements.define('monitor-list-row', MonitorListRow, {extends: 'tr'});
|
customElements.define('monitor-list-row', MonitorListRow, {extends: 'tr'});
|
||||||
|
customElements.define('status-checker-span', StatusCheckerSpan, {extends: 'span'});
|
||||||
|
|||||||
40
assets/components/status-checker-span.js
Normal file
40
assets/components/status-checker-span.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
export default class PreviewContentDialog extends HTMLSpanElement {
|
||||||
|
#url;
|
||||||
|
#service;
|
||||||
|
#status;
|
||||||
|
|
||||||
|
#statusTexts = {
|
||||||
|
200: 'up',
|
||||||
|
204: 'up'
|
||||||
|
}
|
||||||
|
|
||||||
|
#statusColors = {
|
||||||
|
200: 'bg-green-500',
|
||||||
|
204: 'bg-green-500'
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.#url = this.getAttribute('url');
|
||||||
|
this.#service = this.getAttribute('service');
|
||||||
|
|
||||||
|
(async () => await this.checkStatus())();
|
||||||
|
setInterval(async () => await this.checkStatus(), 1000 * 60 * 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkStatus() {
|
||||||
|
const response = await fetch(this.#url);
|
||||||
|
this.#status = response.status;
|
||||||
|
this.setAttribute('title', this.getTitle());
|
||||||
|
this.classList.remove('bg-red-500', 'bg-green-500');
|
||||||
|
this.classList.add(this.getColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
getTitle() {
|
||||||
|
return `${this.#service} is ${this.#statusTexts[this.#status] ?? 'down'}`
|
||||||
|
}
|
||||||
|
|
||||||
|
getColor() {
|
||||||
|
return this.#statusColors[this.#status] ?? 'bg-red-500';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ class RegistrationFormType extends AbstractType
|
|||||||
->add('plainPassword', PasswordType::class, [
|
->add('plainPassword', PasswordType::class, [
|
||||||
// instead of being set onto the object directly,
|
// instead of being set onto the object directly,
|
||||||
// this is read and encoded in the controller
|
// this is read and encoded in the controller
|
||||||
|
'label' => 'Password',
|
||||||
'mapped' => false,
|
'mapped' => false,
|
||||||
'attr' => ['autocomplete' => 'new-password'],
|
'attr' => ['autocomplete' => 'new-password'],
|
||||||
'constraints' => [
|
'constraints' => [
|
||||||
|
|||||||
@@ -18,9 +18,13 @@ module.exports = {
|
|||||||
"bg-green-400",
|
"bg-green-400",
|
||||||
"bg-purple-400",
|
"bg-purple-400",
|
||||||
"bg-orange-400",
|
"bg-orange-400",
|
||||||
|
"bg-red-500",
|
||||||
|
"bg-green-500",
|
||||||
"bg-blue-600",
|
"bg-blue-600",
|
||||||
"bg-rose-600",
|
"bg-rose-600",
|
||||||
"bg-black/20",
|
"bg-black/20",
|
||||||
|
"text-red-500",
|
||||||
|
"text-green-500",
|
||||||
"alert-success",
|
"alert-success",
|
||||||
"alert-warning",
|
"alert-warning",
|
||||||
"font-bold",
|
"font-bold",
|
||||||
|
|||||||
@@ -6,6 +6,20 @@
|
|||||||
<div class="md:flex md:items-center md:gap-12">
|
<div class="md:flex md:items-center md:gap-12">
|
||||||
<nav aria-label="Global" class="md:block">
|
<nav aria-label="Global" class="md:block">
|
||||||
<ul class="ml-4 flex items-end md:items-center md:gap-6 text-sm">
|
<ul class="ml-4 flex items-end md:items-center md:gap-6 text-sm">
|
||||||
|
<li>
|
||||||
|
<div class="flex flex-row justify-center items-start gap-2 p-2 w-10 mt-1 h-6 rounded-lg border border-orange-500 text-orange-500">
|
||||||
|
<status-checker-span
|
||||||
|
class="h-2 w-2 rounded-full text-green-600 bg-green-600"
|
||||||
|
url="https://torrentio.strem.fun"
|
||||||
|
service="Torrentio">
|
||||||
|
</status-checker-span>
|
||||||
|
<status-checker-span
|
||||||
|
class="h-2 w-2 rounded-full text-green-600 bg-green-600"
|
||||||
|
url="https://api.themoviedb.org/3"
|
||||||
|
service="TMDB">
|
||||||
|
</status-checker-span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ path('app.monitor.upcoming-episodes') }}" data-turbo="false" title="View upcoming episodes of the shows you're subscribed to.">
|
<a href="{{ path('app.monitor.upcoming-episodes') }}" data-turbo="false" title="View upcoming episodes of the shows you're subscribed to.">
|
||||||
<twig:ux:icon name="solar:calendar-linear" width="25px" class="text-orange-500" />
|
<twig:ux:icon name="solar:calendar-linear" width="25px" class="text-orange-500" />
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<div class="flex flex-row gap-2 mb-2">
|
<div class="flex flex-row gap-2 mb-2">
|
||||||
<input type="hidden" name="movie_folder" id="movie_folder_hidden" value="0" />
|
<input type="hidden" name="movie_folder" id="movie_folder_hidden" value="0" />
|
||||||
<input type="checkbox" name="movie_folder" id="movie_folder" value="1" {{ downloadPreferences['movie_folder'].getPreferenceValue() == true ? 'checked' }} />
|
<input type="checkbox" name="movie_folder" id="movie_folder" value="1" {{ downloadPreferences['movie_folder'].getPreferenceValue() == true ? 'checked' }} />
|
||||||
<label class="text-gray-50" for="movie_folder">Store movies in a new directory?</label>
|
<label class="text-gray-50" for="movie_folder">Create a new directory for each movie?</label>
|
||||||
</div>
|
</div>
|
||||||
<button class="px-1.5 py-1 max-w-20 rounded-md bg-green-600 text-white" type="submit">Submit</button>
|
<button class="px-1.5 py-1 max-w-20 rounded-md bg-green-600 text-white" type="submit">Submit</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
Reference in New Issue
Block a user