Commit c2138759 authored by echel0n's avatar echel0n
Browse files

added missing code for storing SR API Key

added code to run SiCKRAGE as a Windows service
refactored misc depreciated code
parent e30b90e6
......@@ -3,6 +3,8 @@
.gitignore
.gitattributes
.eslintc
**/__pycache__
**/*.py[cod]
src
tests
runscripts
......
......@@ -2,4 +2,8 @@ include README.txt
include COPYING.txt
include CHANGELOG.md
include requirements.txt
recursive-include sickrage *
\ No newline at end of file
recursive-include sickrage *
global-exclude __pycache__
global-exclude *.py[cod]
\ No newline at end of file
......@@ -19,17 +19,7 @@
# You should have received a copy of the GNU General Public License
# along with SiCKRAGE. If not, see <http://www.gnu.org/licenses/>.
# ##############################################################################
import os
import pathlib
import shutil
from sickrage import main
if __name__ == '__main__':
# remove pyc and pyo files
[p.unlink() for p in pathlib.Path(os.path.dirname(__file__)).rglob('*.py[co]')]
# remove __pycache__ folder
[shutil.rmtree(str(p)) for p in pathlib.Path(os.path.dirname(__file__)).rglob('__pycache__')]
from sickrage import main
main()
twine
crowdin-cli-py
babel
wheel
tox
vcrpy-unittest
Mako
\ No newline at end of file
......@@ -76,6 +76,7 @@ python-twitter==3.5
pytz==2020.1
pyxdg==0.26
PyYAML==5.4.1
pywin32==304; sys_platform == 'win32'
rarfile==3.1
rebulk==2.0.1
requests==2.24.0
......@@ -93,6 +94,7 @@ SQLAlchemy==1.4.32
SQLAlchemy-Utils==0.38.2
stevedore==3.2.0
subliminal==2.1.0
telnetlib3==1.0.4
tornado==6.1
twilio==6.44.2
typing-extensions==4.1.1
......
......@@ -22,33 +22,98 @@
__version__ = "10.0.64.dev0"
__install_type__ = ""
import sys
# sickrage requires python 3.6+
if sys.version_info < (3, 6, 0):
sys.exit("Sorry, SiCKRAGE requires Python 3.6+")
import argparse
import atexit
import gettext
import multiprocessing
import os
import pathlib
import re
import site
import subprocess
import sys
import threading
import time
import traceback
from signal import SIGTERM
import pkg_resources
# pywin32 for windows service
try:
import win32api
import win32serviceutil
import win32evtlogutil
import win32event
import win32service
import win32ts
import servicemanager
from win32com.shell import shell, shellcon
except ImportError:
if __install_type__ == 'windows':
sys.exit("Sorry, SiCKRAGE requires Python module PyWin32.")
from signal import SIGTERM
app = None
MAIN_DIR = os.path.abspath(os.path.realpath(os.path.expanduser(os.path.dirname(os.path.dirname(__file__)))))
PROG_DIR = os.path.abspath(os.path.realpath(os.path.expanduser(os.path.dirname(__file__))))
LOCALE_DIR = os.path.join(PROG_DIR, 'locale')
LIBS_DIR = os.path.join(PROG_DIR, 'libs')
CHANGELOG_FILE = os.path.join(MAIN_DIR, 'CHANGELOG.md')
REQS_FILE = os.path.join(MAIN_DIR, 'requirements.txt')
CHECKSUM_FILE = os.path.join(PROG_DIR, 'checksums.md5')
AUTO_PROCESS_TV_CFG_FILE = os.path.join(*[PROG_DIR, 'autoProcessTV', 'autoProcessTV.cfg'])
# add sickrage libs path to python system path
LIBS_DIR = os.path.join(PROG_DIR, 'libs')
if not (LIBS_DIR in sys.path) and not getattr(sys, 'frozen', False):
sys.path, remainder = sys.path[:1], sys.path[1:]
site.addsitedir(LIBS_DIR)
sys.path.extend(remainder)
# set system default language
gettext.install('messages', LOCALE_DIR, codeset='UTF-8', names=["ngettext"])
if __install_type__ == 'windows':
class SiCKRAGEService(win32serviceutil.ServiceFramework):
_svc_name_ = "SiCKRAGE"
_svc_display_name_ = "SiCKRAGE"
_svc_description_ = (
"Automated video library manager for TV shows. "
'Set to "automatic" to start the service at system startup. '
"You may need to login with a real user account when you need "
"access to network shares."
)
if hasattr(sys, "frozen"):
_exe_name_ = "SiCKRAGE.exe"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
def SvcDoRun(self):
msg = "SiCKRAGE-service %s" % __version__
self.Logger(servicemanager.PYS_SERVICE_STARTED, msg + " has started")
start()
self.Logger(servicemanager.PYS_SERVICE_STOPPED, msg + " has stopped")
def SvcStop(self):
if app:
app.shutdown()
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
def Logger(self, state, msg):
win32evtlogutil.ReportEvent(
self._svc_display_name_, state, 0, servicemanager.EVENTLOG_INFORMATION_TYPE, (self._svc_name_, msg)
)
class Daemon(object):
"""
......@@ -239,26 +304,43 @@ def verify_checksums(remove_unverified=False):
print('Unable to delete unverified filename {} during checksum verification, you should delete this file manually!'.format(full_filename))
def handle_windows_service():
if hasattr(sys, "frozen") and win32ts.ProcessIdToSessionId(win32api.GetCurrentProcessId()) == 0:
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(SiCKRAGEService)
servicemanager.StartServiceCtrlDispatcher()
return True
if len(sys.argv) > 1 and sys.argv[1] in ("install", "update", "remove", "start", "stop", "restart", "debug"):
win32serviceutil.HandleCommandLine(SiCKRAGEService)
del sys.argv[1]
return True
def main():
global app
multiprocessing.freeze_support()
# set thread name
threading.currentThread().setName('MAIN')
threading.current_thread().name = 'MAIN'
# fix threading time bug
time.strptime("2012", "%Y")
# add sickrage libs path to python system path
if not (LIBS_DIR in sys.path):
sys.path, remainder = sys.path[:1], sys.path[1:]
site.addsitedir(LIBS_DIR)
sys.path.extend(remainder)
if __install_type__ == 'windows':
if not handle_windows_service():
start()
else:
start()
# set system default language
gettext.install('messages', LOCALE_DIR, codeset='UTF-8', names=["ngettext"])
def start():
global app
parser = argparse.ArgumentParser(
prog='sickrage',
description='Automated video library manager for TV shows'
)
# sickrage startup options
parser = argparse.ArgumentParser(prog='sickrage')
parser.add_argument('-v', '--version',
action='version',
version=version())
......@@ -325,22 +407,19 @@ def main():
# Parse startup args
args = parser.parse_args()
# sickrage requires python 3.6+
if sys.version_info < (3, 6, 0):
sys.exit("Sorry, SiCKRAGE requires Python 3.6+")
# check lib requirements
if install_type() not in ['windows', 'synology', 'docker', 'qnap', 'readynas', 'pip']:
check_requirements()
# check requirements
# if install_type() not in ['windows', 'synology', 'docker', 'qnap', 'readynas', 'pip']:
# check_requirements()
# verify file checksums, remove unverified files
verify_checksums(remove_unverified=not args.no_clean)
# verify_checksums(remove_unverified=not args.no_clean)
try:
from sickrage.core import Core
# main app instance
app = Core()
try:
from sickrage.core import Core
app = Core()
except ImportError:
sys.exit("Sorry, SiCKRAGE requirements need to be installed.")
app.quiet = args.quiet
app.web_host = args.host
......@@ -369,7 +448,7 @@ def main():
pid_file = os.path.join(app.data_dir, pid_file)
# add sickrage module to python system path
if not (PROG_DIR in sys.path):
if not (PROG_DIR in sys.path) and not getattr(sys, 'frozen', False):
sys.path, remainder = sys.path[:1], sys.path[1:]
site.addsitedir(PROG_DIR)
sys.path.extend(remainder)
......@@ -404,7 +483,6 @@ def main():
app.daemon.daemonize()
app.pid = app.daemon.pid
# start app
app.start()
except (SystemExit, KeyboardInterrupt):
if app:
......
......@@ -18,6 +18,7 @@
# You should have received a copy of the GNU General Public License
# along with SiCKRAGE. If not, see <http://www.gnu.org/licenses/>.
# ##############################################################################
import asyncio
import datetime
import locale
import logging
......@@ -43,6 +44,7 @@ from dateutil import tz
from fake_useragent import UserAgent
from sentry_sdk.integrations.logging import LoggingIntegration, ignore_logger
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado.platform.asyncio import AnyThreadEventLoopPolicy
import sickrage
from sickrage.core.amqp.consumer import AMQPConsumer
......@@ -234,7 +236,10 @@ class Core(object):
self.started = True
# thread name
threading.currentThread().setName('CORE')
threading.current_thread().name = 'CORE'
# set event loop policy
asyncio.set_event_loop_policy(AnyThreadEventLoopPolicy())
# init sentry
self.init_sentry()
......@@ -651,7 +656,7 @@ class Core(object):
)
def load_shows(self):
threading.currentThread().setName('CORE')
threading.current_thread().name = 'CORE'
session = self.main_db.session()
......
# ##############################################################################
# Author: echel0n <[email protected]>
# URL: https://sickrage.ca/
# Git: https://git.sickrage.ca/SiCKRAGE/sickrage.git
# -
# This file is part of SiCKRAGE.
# -
# SiCKRAGE is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# -
# SiCKRAGE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# -
# You should have received a copy of the GNU General Public License
# along with SiCKRAGE. If not, see <http://www.gnu.org/licenses/>.
# ##############################################################################
def cmp(a, b):
return (a > b) - (a < b)
......@@ -45,7 +45,7 @@ class AutoPostProcessor(object):
self.running = True
# set thread name
threading.currentThread().setName(self.name)
threading.current_thread().name = self.name
sickrage.app.postprocessor_queue.put(sickrage.app.config.general.tv_download_dir, force=force)
finally:
......
......@@ -352,7 +352,7 @@ def search_providers(series_id, series_provider_id, season, episode, manualSearc
search_count += 1
try:
threading.currentThread().setName(orig_thread_name + "::[" + providerObj.name + "]")
threading.current_thread().name = orig_thread_name + "::[" + providerObj.name + "]"
if episode and search_mode == 'eponly':
sickrage.app.log.info("Performing episode search for " + show_object.name)
......@@ -375,7 +375,7 @@ def search_providers(series_id, series_provider_id, season, episode, manualSearc
sickrage.app.log.error("Error while searching " + providerObj.name + ", skipping: {}".format(e))
break
finally:
threading.currentThread().setName(orig_thread_name)
threading.current_thread().name = orig_thread_name
if len(found_results):
# make a list of all the results for this provider
......
......@@ -47,7 +47,7 @@ class BacklogSearcher(object):
self.running = True
# set thread name
threading.currentThread().setName(self.name)
threading.current_thread().name = self.name
# set cycle time
self.cycleTime = sickrage.app.config.general.backlog_searcher_freq / 60 / 24
......
......@@ -45,7 +45,7 @@ class DailySearcher(object):
self.running = True
# set thread name
threading.currentThread().setName(self.name)
threading.current_thread().name = self.name
# find new released episodes and update their statuses
for curShow in get_show_list():
......
......@@ -48,7 +48,7 @@ class FailedSnatchSearcher(object):
self.running = True
# set thread name
threading.currentThread().setName(self.name)
threading.current_thread().name = self.name
# trim failed download history
FailedHistory.trim_history()
......
......@@ -55,7 +55,7 @@ class ProperSearcher(object):
self.running = True
# set thread name
threading.currentThread().setName(self.name)
threading.current_thread().name = self.name
sickrage.app.log.info("Beginning the search for new propers")
......@@ -101,7 +101,7 @@ class ProperSearcher(object):
elif not providerObj.is_enabled:
continue
threading.currentThread().setName(orig_thread_name + " :: [" + providerObj.name + "]")
threading.current_thread().name = orig_thread_name + " :: [" + providerObj.name + "]"
sickrage.app.log.info("Searching for any new PROPER releases from " + providerObj.name)
......@@ -125,7 +125,7 @@ class ProperSearcher(object):
sickrage.app.log.debug(traceback.format_exc())
continue
threading.currentThread().setName(orig_thread_name)
threading.current_thread().name = orig_thread_name
self._set_last_proper_search(show.series_id, show.series_provider_id, datetime.datetime.now())
......
......@@ -47,7 +47,7 @@ class SubtitleSearcher(object):
self.running = True
# set thread name
threading.currentThread().setName(self.name)
threading.current_thread().name = self.name
if len(Subtitles().getEnabledServiceList()) < 1:
sickrage.app.log.warning('Not enough services selected. At least 1 service is required to search subtitles in the background')
......
......@@ -72,7 +72,7 @@ class TraktSearcher(object):
self.running = True
# set thread name
threading.currentThread().setName(self.name)
threading.current_thread().name = self.name
self.todoWanted = [] # its about to all get re-added
if len(sickrage.app.config.general.root_dirs.split('|')) < 2:
......
......@@ -20,7 +20,7 @@ class RSSCacheUpdater(object):
for providerID, providerObj in sickrage.app.search_providers.sort().items():
if providerObj.is_enabled:
threading.currentThread().setName('{}::{}'.format(self.name, providerObj.name.upper()))
threading.current_thread().name = f'{self.name}::{providerObj.name.upper()}'
providerObj.cache.update(force)
finally:
self.running = False
......@@ -44,7 +44,7 @@ class ShowUpdater(object):
self.running = True
# set thread name
threading.currentThread().setName(self.name)
threading.current_thread().name = self.name
session = sickrage.app.cache_db.session()
......
......@@ -44,7 +44,7 @@ class UPNPClient(object):
try:
self.running = True
threading.currentThread().setName(self.name)
threading.current_thread().name = self.name
self.add_nat_portmap()
finally:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment