Skip to content

Commit

Permalink
Merge pull request #10443 from pymedusa/release/release-0.5.26
Browse files Browse the repository at this point in the history
Release/release 0.5.26
  • Loading branch information
p0psicles authored Mar 28, 2022
2 parents 5de42f0 + b7dc14e commit 2105d6e
Show file tree
Hide file tree
Showing 162 changed files with 1,313 additions and 1,238 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## 0.5.26 (28-03-2022)

#### Improvements
- UI now behaves as a single page app ([10408](https://github.com/pymedusa/Medusa/pull/10408))
- Add ability to select Xem mapped seasons for season scene exceptions ([10438](https://github.com/pymedusa/Medusa/pull/10438))

#### Fixes
- Fix postprocessing loop when not using Failed Download Handling ([10435](https://github.com/pymedusa/Medusa/pull/10435))

## 0.5.25 (08-03-2022)

#### New Features
Expand Down
2 changes: 1 addition & 1 deletion medusa/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
log.logger.addHandler(logging.NullHandler())

INSTANCE_ID = text_type(uuid.uuid1())
VERSION = '0.5.25'
VERSION = '0.5.26'

USER_AGENT = 'Medusa/{version} ({system}; {release}; {instance})'.format(
version=VERSION, system=platform.system(), release=platform.release(),
Expand Down
5 changes: 4 additions & 1 deletion medusa/failed_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ def _process_release_name(self):
segment.append(parse_result.series.get_episode(parse_result.season_number, episode))

if segment:
self.log(logger.DEBUG, 'Adding this release to failed queue: {release}'.format(release=release_name))
self.log(logger.DEBUG, 'Created segment of episodes [{segment}] from release: {release}'.format(
segment=','.join(ep.episode for ep in segment),
release=release_name
))

return segment

Expand Down
2 changes: 1 addition & 1 deletion medusa/indexers/tmdb/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def _show_search(self, show, request_language='en'):
results = []
while page <= last:
search_result = self.tmdb.Search().tv(query=show,
language='request_language',
language=request_language,
page=page)
last = search_result.get('total_pages', 0)
results += search_result.get('results')
Expand Down
11 changes: 7 additions & 4 deletions medusa/process_tv.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,7 @@ def process_path(self):

# A user might want to use advanced post-processing, but opt-out of failed download handling.
if (
app.USE_FAILED_DOWNLOADS
and self.process_single_resource
self.process_single_resource
and (process_results.failed or not process_results.succeeded)
):
process_results.process_failed(self.path)
Expand Down Expand Up @@ -232,8 +231,9 @@ def run(self, force=False, **kwargs):
process_results = ProcessResult(path, process_method, failed=failed)
process_results.process(force=force, **kwargs)

# Only initiate failed download handling, if enabled.
if process_results.failed and app.USE_FAILED_DOWNLOADS:
# Only initiate failed download handling,
# if process result has failed and failed download handling is enabled.
if process_results.failed:
process_results.process_failed(path)

return process_results.output
Expand Down Expand Up @@ -927,6 +927,9 @@ def _process_postponed(self, processor, path, video, ignore_subs):

def process_failed(self, path, resource_name=None):
"""Process a download that did not complete correctly."""
if not app.USE_FAILED_DOWNLOADS:
return

try:
processor = failed_processor.FailedProcessor(
path, resource_name or self.resource_name, self.episodes
Expand Down
7 changes: 4 additions & 3 deletions medusa/server/api/v2/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,13 @@ def _check_authentication(self):
return

authorization = self.request.headers.get('Authorization')
if not authorization:
x_auth = self.request.headers.get('x-auth')
if not authorization and not x_auth:
return self._unauthorized('No authorization token.')

if authorization.startswith('Bearer'):
if x_auth and x_auth.startswith('Bearer'):
try:
token = authorization.replace('Bearer ', '')
token = x_auth.replace('Bearer ', '')
jwt.decode(token, app.ENCRYPTION_SECRET, algorithms=['HS256'])
except jwt.ExpiredSignatureError:
return self._unauthorized('Token has expired.')
Expand Down
29 changes: 29 additions & 0 deletions medusa/server/api/v2/internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import os
import re

import markdown2

from medusa import app, classes, db, network_timezones, providers
from medusa.common import (
DOWNLOADED, Overview, Quality,
Expand Down Expand Up @@ -699,3 +701,30 @@ def resource_search_missing_subtitles(self):
episode.download_subtitles(lang=language if language != 'all' else None)

return self._ok()

def resource_get_news(self):
"""Retrieve news and convert the markdown to html."""
news = app.version_check_scheduler.action.check_for_new_news(force=True)
if not news:
news = 'Could not load news from the repository. [Click here for news.md]({url})'.format(url=app.NEWS_URL)

app.NEWS_LAST_READ = app.NEWS_LATEST
app.NEWS_UNREAD = 0
app.instance.save_config()

data = markdown2.markdown(news if news else 'The was a problem connecting to GitHub, please refresh and try again', extras=['header-ids'])
return self._ok(data)

def resource_get_changelog(self):
"""Retrieve changelog and convert the markdown to html."""
# TODO: SESSION: Check if this needs some more explicit exception handling.
from medusa.session.core import MedusaSafeSession
changes = MedusaSafeSession().get_text(app.CHANGES_URL)

if not changes:
changes = 'Could not load changes from the repo. [Click here for CHANGES.md]({url})'.format(url=app.CHANGES_URL)

data = markdown2.markdown(
changes if changes else 'The was a problem connecting to github, please refresh and try again', extras=['header-ids']
)
return self._ok(data)
2 changes: 1 addition & 1 deletion medusa/server/web/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def write_error(self, status_code, **kwargs):
url = url[len(app.WEB_ROOT) + 1:]

if url[:3] != 'api':
t = PageTemplate(rh=self, filename='404.mako')
t = PageTemplate(rh=self, filename='index.mako')
return self.finish(t.render())
else:
self.finish('Wrong API key used')
Expand Down
22 changes: 20 additions & 2 deletions medusa/server/web/core/token.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
"""Handle the requests fro /token."""
from __future__ import unicode_literals

import random
import string
import time

import jwt

from medusa import app
from medusa.server.web.core.base import BaseHandler

Expand All @@ -17,5 +23,17 @@ def __init__(self, *args, **kwargs):

@authenticated
def get(self, *args, **kwargs):
"""Return the app.API_KEY for /token get requests."""
self.finish({'token': app.API_KEY})
"""Return a JWT for /token get requests."""
time_now = int(time.time())
self.finish(
jwt.encode({
'iss': f'Medusa {app.APP_VERSION}',
'iat': int(time.time()),
# @TODO: The jti should be saved so we can revoke tokens
'jti': ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(20)),
'exp': time_now + int(86400),
'username': app.WEB_USERNAME,
'apiKey': app.API_KEY,
'webRoot': app.WEB_ROOT
}, app.ENCRYPTION_SECRET, algorithm='HS256')
)
23 changes: 6 additions & 17 deletions medusa/server/web/home/change_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,23 @@

from __future__ import unicode_literals

import markdown2

from medusa import app, logger
from medusa.server.web.core import PageTemplate
from medusa.server.web.home.handler import Home
from medusa.session.core import MedusaSafeSession

from tornroutes import route


@route('/changes(/?.*)')
class HomeChangeLog(Home):
session = MedusaSafeSession()

def __init__(self, *args, **kwargs):
super(HomeChangeLog, self).__init__(*args, **kwargs)

def index(self):
# TODO: SESSION: Check if this needs some more explicit exception handling.
changes = HomeChangeLog.session.get_text(app.CHANGES_URL)

if not changes:
logger.log('Could not load changes from repo, giving a link!', logger.DEBUG)
changes = 'Could not load changes from the repo. [Click here for CHANGES.md]({url})'.format(url=app.CHANGES_URL)

t = PageTemplate(rh=self, filename='markdown.mako')
data = markdown2.markdown(
changes if changes else 'The was a problem connecting to github, please refresh and try again', extras=['header-ids']
)
"""
Render the IRC page.
return t.render(title='Changelog', header='Changelog', data=data, controller='changes', action='index')
[Converted to VueRouter]
"""
t = PageTemplate(rh=self, filename='index.mako')
return t.render()
20 changes: 6 additions & 14 deletions medusa/server/web/home/news.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@

from __future__ import unicode_literals

import markdown2

from medusa import app
from medusa.server.web.core import PageTemplate
from medusa.server.web.home.handler import Home

Expand All @@ -17,15 +14,10 @@ def __init__(self, *args, **kwargs):
super(HomeNews, self).__init__(*args, **kwargs)

def index(self):
news = app.version_check_scheduler.action.check_for_new_news(force=True)
if not news:
news = 'Could not load news from the repository. [Click here for news.md]({url})'.format(url=app.NEWS_URL)

app.NEWS_LAST_READ = app.NEWS_LATEST
app.NEWS_UNREAD = 0
app.instance.save_config()

t = PageTemplate(rh=self, filename='markdown.mako')
data = markdown2.markdown(news if news else 'The was a problem connecting to GitHub, please refresh and try again', extras=['header-ids'])
"""
Render the IRC page.
return t.render(title='News', header='News', data=data, controller='news', action='index')
[Converted to VueRouter]
"""
t = PageTemplate(rh=self, filename='index.mako')
return t.render()
1 change: 1 addition & 0 deletions themes-default/slim/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"vue-images-loaded": "1.1.2",
"vue-js-modal": "2.0.1",
"vue-js-toggle-button": "1.3.3",
"vue-jwt-decode": "0.1.0",
"vue-lazyload": "1.3.3",
"vue-meta": "2.4.0",
"vue-multiselect": "2.1.6",
Expand Down
64 changes: 27 additions & 37 deletions themes-default/slim/src/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,32 @@ import axios from 'axios';

// This should be more dynamic. As now when we change the apiKey in config-general.vue. This won't work anymore.
// Because of this, a page reload is required.
export const webRoot = document.body.getAttribute('web-root');
export const apiKey = document.body.getAttribute('api-key');

/**
* Api client based on the axios client, to communicate with medusa's web routes, which return json data.
*/
export const apiRoute = axios.create({
baseURL: webRoot + '/',
timeout: 60000,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
});
export default function() {
this.webRoot = document.body.getAttribute('web-root');
this.token = null;
this.getToken = () => {
return axios.get(`${this.webRoot}/token`)
.then(response => {
this.token = response.data;
this.apiRoute = axios.create({
baseURL: `${this.webRoot}/`,
timeout: 60000,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
});

/**
* Api client based on the axios client, to communicate with medusa's api v1.
*/
export const apiv1 = axios.create({
baseURL: webRoot + '/api/v1/' + apiKey + '/',
timeout: 30000,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
});

/**
* Api client based on the axios client, to communicate with medusa's api v2.
*/
export const api = axios.create({
baseURL: webRoot + '/api/v2/',
timeout: 30000,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'X-Api-Key': apiKey
}
});
this.api = axios.create({
baseURL: `${this.webRoot}/api/v2/`,
timeout: 30000,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'x-auth': `Bearer ${this.token}`
}
});
});
};
}
34 changes: 19 additions & 15 deletions themes-default/slim/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import Vue from 'vue';
import { registerGlobalComponents, registerPlugins } from './global-vue-shim';
import router from './router';
import store from './store';
import { mapActions, mapMutations, mapState } from 'vuex';
import { mapActions, mapMutations } from 'vuex';
import { isDevelopment } from './utils/core';
import { App } from './components';

Vue.config.devtools = true;
Vue.config.performance = true;
Expand All @@ -14,35 +15,33 @@ registerPlugins();
// @TODO: Remove this before v1.0.0
registerGlobalComponents();

const app = new Vue({
name: 'app',
export default new Vue({
name: 'index',
router,
store,
data() {
return {
globalLoading: false,
pageComponent: false
isAuthenticated: false
};
},
computed: {
...mapState({
showsLoading: state => state.shows.loading
})
},
mounted() {
async mounted() {
const { getShows, setLoadingDisplay, setLoadingFinished } = this;

if (isDevelopment) {
console.log('App Mounted!');
}

await this.$store.dispatch('auth');

if (!window.location.pathname.includes('/login')) {
const { $store } = this;
await $store.dispatch('login');
this.isAuthenticated = true;

Promise.all([
$store.dispatch('login', { username: window.username }),
$store.dispatch('getConfig'),
$store.dispatch('getStats')
]).then(([_, config]) => {
]).then(([config]) => {
if (isDevelopment) {
console.log('App Loaded!');
}
Expand Down Expand Up @@ -74,7 +73,12 @@ const app = new Vue({
'setLoadingDisplay',
'setLoadingFinished'
])
},
render(h) { // eslint-disable-line vue/require-render-return
// Do not start with rendering the app, before we're sure we authenticated.
if (this.isAuthenticated || window.location.pathname.includes('/login')) {
return h(App);
}
}
}).$mount('#vue-wrap');
}).$mount('#app-wrapper');

export default app;
Loading

0 comments on commit 2105d6e

Please sign in to comment.