Code cleaning (remove python2)
This commit is contained in:
parent
50919d4721
commit
ed26d34961
11
cps.py
11
cps.py
|
@ -17,18 +17,13 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
# Insert local directories into path
|
# Insert local directories into path
|
||||||
if sys.version_info < (3, 0):
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||||
sys.path.append(os.path.dirname(os.path.abspath(__file__.decode('utf-8'))))
|
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'vendor'))
|
||||||
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__.decode('utf-8'))), 'vendor'))
|
|
||||||
else:
|
|
||||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'vendor'))
|
|
||||||
|
|
||||||
|
|
||||||
from cps import create_app
|
from cps import create_app
|
||||||
|
@ -49,7 +44,7 @@ try:
|
||||||
from cps.kobo import kobo, get_kobo_activated
|
from cps.kobo import kobo, get_kobo_activated
|
||||||
from cps.kobo_auth import kobo_auth
|
from cps.kobo_auth import kobo_auth
|
||||||
kobo_available = get_kobo_activated()
|
kobo_available = get_kobo_activated()
|
||||||
except (ImportError, AttributeError): # Catch also error for not installed flask-wtf (missing csrf decorator)
|
except (ImportError, AttributeError): # Catch also error for not installed flask-WTF (missing csrf decorator)
|
||||||
kobo_available = False
|
kobo_available = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import mimetypes
|
import mimetypes
|
||||||
|
@ -118,16 +117,11 @@ def create_app():
|
||||||
print('*** "lxml" is needed for calibre-web to run. Please install it using pip: "pip install lxml" ***')
|
print('*** "lxml" is needed for calibre-web to run. Please install it using pip: "pip install lxml" ***')
|
||||||
sys.exit(6)
|
sys.exit(6)
|
||||||
if not wtf_present:
|
if not wtf_present:
|
||||||
log.info('*** "flask-wtf" is needed for calibre-web to run. Please install it using pip: "pip install flask-wtf" ***')
|
log.info('*** "flask-WTF" is needed for calibre-web to run. Please install it using pip: "pip install flask-WTF" ***')
|
||||||
print('*** "flask-wtf" is needed for calibre-web to run. Please install it using pip: "pip install flask-wtf" ***')
|
print('*** "flask-WTF" is needed for calibre-web to run. Please install it using pip: "pip install flask-WTF" ***')
|
||||||
sys.exit(7)
|
# sys.exit(7)
|
||||||
|
|
||||||
app.wsgi_app = ReverseProxied(app.wsgi_app)
|
app.wsgi_app = ReverseProxied(app.wsgi_app)
|
||||||
# For python2 convert path to unicode
|
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
app.static_folder = app.static_folder.decode('utf-8')
|
|
||||||
app.root_path = app.root_path.decode('utf-8')
|
|
||||||
app.instance_path = app.instance_path.decode('utf-8')
|
|
||||||
|
|
||||||
if os.environ.get('FLASK_DEBUG'):
|
if os.environ.get('FLASK_DEBUG'):
|
||||||
cache_buster.init_cache_busting(app)
|
cache_buster.init_cache_busting(app)
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import sys
|
import sys
|
||||||
import platform
|
import platform
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import base64
|
import base64
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
# Inspired by https://github.com/ChrisTM/Flask-CacheBust
|
# Inspired by https://github.com/ChrisTM/Flask-CacheBust
|
||||||
# Uses query strings so CSS font files are found without having to resort to absolute URLs
|
# Uses query strings so CSS font files are found without having to resort to absolute URLs
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import os
|
import os
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
|
|
14
cps/cli.py
14
cps/cli.py
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import argparse
|
import argparse
|
||||||
|
@ -48,19 +47,6 @@ parser.add_argument('-s', metavar='user:pass', help='Sets specific username to n
|
||||||
parser.add_argument('-f', action='store_true', help='Flag is depreciated and will be removed in next version')
|
parser.add_argument('-f', action='store_true', help='Flag is depreciated and will be removed in next version')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
if args.p:
|
|
||||||
args.p = args.p.decode('utf-8')
|
|
||||||
if args.g:
|
|
||||||
args.g = args.g.decode('utf-8')
|
|
||||||
if args.k:
|
|
||||||
args.k = args.k.decode('utf-8')
|
|
||||||
if args.c:
|
|
||||||
args.c = args.c.decode('utf-8')
|
|
||||||
if args.s:
|
|
||||||
args.s = args.s.decode('utf-8')
|
|
||||||
|
|
||||||
|
|
||||||
settingspath = args.p or os.path.join(_CONFIG_DIR, "app.db")
|
settingspath = args.p or os.path.join(_CONFIG_DIR, "app.db")
|
||||||
gdpath = args.g or os.path.join(_CONFIG_DIR, "gdrive.db")
|
gdpath = args.g or os.path.join(_CONFIG_DIR, "gdrive.db")
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from . import logger, isoLanguages
|
from . import logger, isoLanguages
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
|
@ -361,10 +359,6 @@ def _migrate_table(session, orm_class):
|
||||||
session.query(column).first()
|
session.query(column).first()
|
||||||
except OperationalError as err:
|
except OperationalError as err:
|
||||||
log.debug("%s: %s", column_name, err.args[0])
|
log.debug("%s: %s", column_name, err.args[0])
|
||||||
if column.default is not None:
|
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
if isinstance(column.default.arg, unicode):
|
|
||||||
column.default.arg = column.default.arg.encode('utf-8')
|
|
||||||
if column.default is None:
|
if column.default is None:
|
||||||
column_default = ""
|
column_default = ""
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
@ -31,12 +30,7 @@ HOME_CONFIG = os.path.isfile(os.path.join(os.path.dirname(os.path.abspath(__file
|
||||||
UPDATER_AVAILABLE = True
|
UPDATER_AVAILABLE = True
|
||||||
|
|
||||||
# Base dir is parent of current file, necessary if called from different folder
|
# Base dir is parent of current file, necessary if called from different folder
|
||||||
if sys.version_info < (3, 0):
|
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),os.pardir))
|
||||||
BASE_DIR = os.path.abspath(os.path.join(
|
|
||||||
os.path.dirname(os.path.abspath(__file__)),os.pardir)).decode('utf-8')
|
|
||||||
else:
|
|
||||||
BASE_DIR = os.path.abspath(os.path.join(
|
|
||||||
os.path.dirname(os.path.abspath(__file__)),os.pardir))
|
|
||||||
STATIC_DIR = os.path.join(BASE_DIR, 'cps', 'static')
|
STATIC_DIR = os.path.join(BASE_DIR, 'cps', 'static')
|
||||||
TEMPLATES_DIR = os.path.join(BASE_DIR, 'cps', 'templates')
|
TEMPLATES_DIR = os.path.join(BASE_DIR, 'cps', 'templates')
|
||||||
TRANSLATIONS_DIR = os.path.join(BASE_DIR, 'cps', 'translations')
|
TRANSLATIONS_DIR = os.path.join(BASE_DIR, 'cps', 'translations')
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from flask_babel import gettext as _
|
from flask_babel import gettext as _
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -387,8 +386,6 @@ class Custom_Columns(Base):
|
||||||
|
|
||||||
def get_display_dict(self):
|
def get_display_dict(self):
|
||||||
display_dict = ast.literal_eval(self.display)
|
display_dict = ast.literal_eval(self.display)
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
display_dict['enum_values'] = [x.decode('unicode_escape') for x in display_dict['enum_values']]
|
|
||||||
return display_dict
|
return display_dict
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import json
|
import json
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import os
|
import os
|
||||||
import zipfile
|
import zipfile
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
from .constants import BookMeta
|
from .constants import BookMeta
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import hashlib
|
import hashlib
|
||||||
|
@ -137,10 +136,7 @@ def on_received_watch_confirmation():
|
||||||
response = gdriveutils.getChangeById(gdriveutils.Gdrive.Instance().drive, j['id'])
|
response = gdriveutils.getChangeById(gdriveutils.Gdrive.Instance().drive, j['id'])
|
||||||
log.debug('%r', response)
|
log.debug('%r', response)
|
||||||
if response:
|
if response:
|
||||||
if sys.version_info < (3, 0):
|
dbpath = os.path.join(config.config_calibre_dir, "metadata.db").encode()
|
||||||
dbpath = os.path.join(config.config_calibre_dir, "metadata.db")
|
|
||||||
else:
|
|
||||||
dbpath = os.path.join(config.config_calibre_dir, "metadata.db").encode()
|
|
||||||
if not response['deleted'] and response['file']['title'] == 'metadata.db' \
|
if not response['deleted'] and response['file']['title'] == 'metadata.db' \
|
||||||
and response['file']['md5Checksum'] != hashlib.md5(dbpath): # nosec
|
and response['file']['md5Checksum'] != hashlib.md5(dbpath): # nosec
|
||||||
tmp_dir = os.path.join(tempfile.gettempdir(), 'calibre_web')
|
tmp_dir = os.path.join(tempfile.gettempdir(), 'calibre_web')
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import shutil
|
import shutil
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import io
|
import io
|
||||||
|
@ -490,10 +489,7 @@ def reset_password(user_id):
|
||||||
def generate_random_password():
|
def generate_random_password():
|
||||||
s = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%&*()?"
|
s = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%&*()?"
|
||||||
passlen = 8
|
passlen = 8
|
||||||
if sys.version_info < (3, 0):
|
return "".join(s[c % len(s)] for c in os.urandom(passlen))
|
||||||
return "".join(s[ord(c) % len(s)] for c in os.urandom(passlen))
|
|
||||||
else:
|
|
||||||
return "".join(s[c % len(s)] for c in os.urandom(passlen))
|
|
||||||
|
|
||||||
|
|
||||||
def uniq(inpt):
|
def uniq(inpt):
|
||||||
|
@ -707,8 +703,6 @@ def check_unrar(unrarLocation):
|
||||||
return _('Unrar binary file not found')
|
return _('Unrar binary file not found')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
unrarLocation = unrarLocation.encode(sys.getfilesystemencoding())
|
|
||||||
unrarLocation = [unrarLocation]
|
unrarLocation = [unrarLocation]
|
||||||
value = process_wait(unrarLocation, pattern='UNRAR (.*) freeware')
|
value = process_wait(unrarLocation, pattern='UNRAR (.*) freeware')
|
||||||
if value:
|
if value:
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
|
|
||||||
from .iso_language_names import LANGUAGE_NAMES as _LANGUAGE_NAMES
|
from .iso_language_names import LANGUAGE_NAMES as _LANGUAGE_NAMES
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
|
|
||||||
# pylint: disable=too-many-lines,bad-continuation
|
# pylint: disable=too-many-lines,bad-continuation
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
# This file is autogenerated, do NOT add, change, or delete ANY string
|
# This file is autogenerated, do NOT add, change, or delete ANY string
|
||||||
# If you need help or assistance for adding a new language, please contact the project team
|
# If you need help or assistance for adding a new language, please contact the project team
|
||||||
|
|
||||||
|
@ -7855,4 +7853,4 @@ LANGUAGE_NAMES = {
|
||||||
"zxx": "No linguistic content",
|
"zxx": "No linguistic content",
|
||||||
"zza": "Zaza"
|
"zza": "Zaza"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
|
|
||||||
# custom jinja filters
|
# custom jinja filters
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import datetime
|
import datetime
|
||||||
import mimetypes
|
import mimetypes
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
|
@ -492,10 +492,7 @@ def get_metadata(book):
|
||||||
metadata.update(get_author(book))
|
metadata.update(get_author(book))
|
||||||
|
|
||||||
if get_series(book):
|
if get_series(book):
|
||||||
if sys.version_info < (3, 0):
|
name = get_series(book)
|
||||||
name = get_series(book).encode("utf-8")
|
|
||||||
else:
|
|
||||||
name = get_series(book)
|
|
||||||
metadata["Series"] = {
|
metadata["Series"] = {
|
||||||
"Name": get_series(book),
|
"Name": get_series(book),
|
||||||
"Number": get_seriesindex(book), # ToDo Check int() ?
|
"Number": get_seriesindex(book), # ToDo Check int() ?
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import inspect
|
import inspect
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
from flask import session
|
from flask import session
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import json
|
import json
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
|
|
10
cps/opds.py
10
cps/opds.py
|
@ -20,7 +20,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import sys
|
import sys
|
||||||
import datetime
|
import datetime
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
@ -537,11 +536,10 @@ def feed_search(term):
|
||||||
|
|
||||||
|
|
||||||
def check_auth(username, password):
|
def check_auth(username, password):
|
||||||
if sys.version_info.major == 3:
|
try:
|
||||||
try:
|
username = username.encode('windows-1252')
|
||||||
username = username.encode('windows-1252')
|
except UnicodeEncodeError:
|
||||||
except UnicodeEncodeError:
|
username = username.encode('utf-8')
|
||||||
username = username.encode('utf-8')
|
|
||||||
user = ub.session.query(ub.User).filter(func.lower(ub.User.name) ==
|
user = ub.session.query(ub.User).filter(func.lower(ub.User.name) ==
|
||||||
username.decode('utf-8').lower()).first()
|
username.decode('utf-8').lower()).first()
|
||||||
if bool(user and check_password_hash(str(user.password), password)):
|
if bool(user and check_password_hash(str(user.password), password)):
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
from math import ceil
|
from math import ceil
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
|
|
||||||
# http://flask.pocoo.org/snippets/62/
|
# http://flask.pocoo.org/snippets/62/
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
try:
|
try:
|
||||||
from urllib.parse import urlparse, urljoin
|
from urllib.parse import urlparse, urljoin
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|
|
@ -36,8 +36,6 @@
|
||||||
#
|
#
|
||||||
# Inspired by http://flask.pocoo.org/snippets/35/
|
# Inspired by http://flask.pocoo.org/snippets/35/
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
|
|
||||||
|
|
||||||
class ReverseProxied(object):
|
class ReverseProxied(object):
|
||||||
"""Wrap the application in this middleware and configure the
|
"""Wrap the application in this middleware and configure the
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import importlib
|
import importlib
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import errno
|
import errno
|
||||||
|
|
|
@ -35,10 +35,7 @@ log = logger.create()
|
||||||
|
|
||||||
|
|
||||||
def b64encode_json(json_data):
|
def b64encode_json(json_data):
|
||||||
if sys.version_info < (3, 0):
|
return b64encode(json.dumps(json_data).encode())
|
||||||
return b64encode(json.dumps(json_data))
|
|
||||||
else:
|
|
||||||
return b64encode(json.dumps(json_data).encode())
|
|
||||||
|
|
||||||
|
|
||||||
# Python3 has a timestamp() method we could be calling, however it's not avaiable in python2.
|
# Python3 has a timestamp() method we could be calling, however it's not avaiable in python2.
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
|
|
||||||
from .. import logger
|
from .. import logger
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,21 @@
|
||||||
from __future__ import print_function
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||||
|
# Copyright (C) 2021 OzzieIsaacs
|
||||||
|
#
|
||||||
|
# This program 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.
|
||||||
|
#
|
||||||
|
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
from google_auth_oauthlib.flow import InstalledAppFlow
|
from google_auth_oauthlib.flow import InstalledAppFlow
|
||||||
from google.auth.transport.requests import Request
|
from google.auth.transport.requests import Request
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import time
|
import time
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
from flask_simpleldap import LDAP, LDAPException
|
from flask_simpleldap import LDAP, LDAPException
|
||||||
|
|
|
@ -1,5 +1,21 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||||
|
# Copyright (C) 2020 pwr
|
||||||
|
#
|
||||||
|
# This program 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.
|
||||||
|
#
|
||||||
|
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import threading
|
import threading
|
||||||
import abc
|
import abc
|
||||||
import uuid
|
import uuid
|
||||||
|
|
|
@ -20,8 +20,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -33,13 +32,8 @@ def process_open(command, quotes=(), env=None, sout=subprocess.PIPE, serr=subpro
|
||||||
if key in quotes:
|
if key in quotes:
|
||||||
command[key] = '"' + element + '"'
|
command[key] = '"' + element + '"'
|
||||||
exc_command = " ".join(command)
|
exc_command = " ".join(command)
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
exc_command = exc_command.encode(sys.getfilesystemencoding())
|
|
||||||
else:
|
else:
|
||||||
if sys.version_info < (3, 0):
|
exc_command = [x for x in command]
|
||||||
exc_command = [x.encode(sys.getfilesystemencoding()) for x in command]
|
|
||||||
else:
|
|
||||||
exc_command = [x for x in command]
|
|
||||||
|
|
||||||
return subprocess.Popen(exc_command, shell=False, stdout=sout, stderr=serr, universal_newlines=newlines, env=env) # nosec
|
return subprocess.Popen(exc_command, shell=False, stdout=sout, stderr=serr, universal_newlines=newlines, env=env) # nosec
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,21 @@
|
||||||
from __future__ import division, print_function, unicode_literals
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||||
|
# Copyright (C) 2020 pwr
|
||||||
|
#
|
||||||
|
# This program 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.
|
||||||
|
#
|
||||||
|
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -161,8 +178,6 @@ class TaskConvert(CalibreTask):
|
||||||
while True:
|
while True:
|
||||||
nextline = p.stdout.readlines()
|
nextline = p.stdout.readlines()
|
||||||
nextline = [x.strip('\n') for x in nextline if x != '\n']
|
nextline = [x.strip('\n') for x in nextline if x != '\n']
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
nextline = [x.decode('utf-8') for x in nextline]
|
|
||||||
for line in nextline:
|
for line in nextline:
|
||||||
log.debug(line)
|
log.debug(line)
|
||||||
if p.poll() is not None:
|
if p.poll() is not None:
|
||||||
|
@ -207,10 +222,6 @@ class TaskConvert(CalibreTask):
|
||||||
|
|
||||||
while p.poll() is None:
|
while p.poll() is None:
|
||||||
nextline = p.stdout.readline()
|
nextline = p.stdout.readline()
|
||||||
if os.name == 'nt' and sys.version_info < (3, 0):
|
|
||||||
nextline = nextline.decode('windows-1252')
|
|
||||||
elif os.name == 'posix' and sys.version_info < (3, 0):
|
|
||||||
nextline = nextline.decode('utf-8')
|
|
||||||
log.debug(nextline.strip('\r\n'))
|
log.debug(nextline.strip('\r\n'))
|
||||||
# parse progress string from calibre-converter
|
# parse progress string from calibre-converter
|
||||||
progress = re.search(r"(\d+)%\s.*", nextline)
|
progress = re.search(r"(\d+)%\s.*", nextline)
|
||||||
|
@ -224,8 +235,6 @@ class TaskConvert(CalibreTask):
|
||||||
calibre_traceback = p.stderr.readlines()
|
calibre_traceback = p.stderr.readlines()
|
||||||
error_message = ""
|
error_message = ""
|
||||||
for ele in calibre_traceback:
|
for ele in calibre_traceback:
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
ele = ele.decode('utf-8')
|
|
||||||
log.debug(ele.strip('\n'))
|
log.debug(ele.strip('\n'))
|
||||||
if not ele.startswith('Traceback') and not ele.startswith(' File'):
|
if not ele.startswith('Traceback') and not ele.startswith(' File'):
|
||||||
error_message = _("Calibre failed with error: %(error)s", error=ele.strip('\n'))
|
error_message = _("Calibre failed with error: %(error)s", error=ele.strip('\n'))
|
||||||
|
|
|
@ -1,11 +1,27 @@
|
||||||
from __future__ import division, print_function, unicode_literals
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||||
|
# Copyright (C) 2020 pwr
|
||||||
|
#
|
||||||
|
# This program 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.
|
||||||
|
#
|
||||||
|
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import smtplib
|
import smtplib
|
||||||
import threading
|
import threading
|
||||||
import socket
|
import socket
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import base64
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
|
@ -162,17 +178,11 @@ class TaskEmail(CalibreTask):
|
||||||
log.debug_or_exception(ex)
|
log.debug_or_exception(ex)
|
||||||
self._handleError(u'Error sending e-mail: {}'.format(ex))
|
self._handleError(u'Error sending e-mail: {}'.format(ex))
|
||||||
|
|
||||||
|
|
||||||
def send_standard_email(self, msg):
|
def send_standard_email(self, msg):
|
||||||
use_ssl = int(self.settings.get('mail_use_ssl', 0))
|
use_ssl = int(self.settings.get('mail_use_ssl', 0))
|
||||||
timeout = 600 # set timeout to 5mins
|
timeout = 600 # set timeout to 5mins
|
||||||
|
|
||||||
# redirect output to logfile on python2 on python3 debugoutput is caught with overwritten
|
# on python3 debugoutput is caught with overwritten _print_debug function
|
||||||
# _print_debug function
|
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
org_smtpstderr = smtplib.stderr
|
|
||||||
smtplib.stderr = logger.StderrLogger('worker.smtp')
|
|
||||||
|
|
||||||
log.debug("Start sending e-mail")
|
log.debug("Start sending e-mail")
|
||||||
if use_ssl == 2:
|
if use_ssl == 2:
|
||||||
self.asyncSMTP = EmailSSL(self.settings["mail_server"], self.settings["mail_port"],
|
self.asyncSMTP = EmailSSL(self.settings["mail_server"], self.settings["mail_port"],
|
||||||
|
@ -198,9 +208,6 @@ class TaskEmail(CalibreTask):
|
||||||
self._handleSuccess()
|
self._handleSuccess()
|
||||||
log.debug("E-mail send successfully")
|
log.debug("E-mail send successfully")
|
||||||
|
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
smtplib.stderr = org_smtpstderr
|
|
||||||
|
|
||||||
def send_gmail_email(self, message):
|
def send_gmail_email(self, message):
|
||||||
return gmail.send_messsage(self.settings.get('mail_gmail_token', None), message)
|
return gmail.send_messsage(self.settings.get('mail_gmail_token', None), message)
|
||||||
|
|
||||||
|
@ -218,7 +225,6 @@ class TaskEmail(CalibreTask):
|
||||||
self.asyncSMTP = None
|
self.asyncSMTP = None
|
||||||
self._progress = x
|
self._progress = x
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_attachment(cls, bookpath, filename):
|
def _get_attachment(cls, bookpath, filename):
|
||||||
"""Get file as MIMEBase message"""
|
"""Get file as MIMEBase message"""
|
||||||
|
|
|
@ -1,4 +1,20 @@
|
||||||
from __future__ import division, print_function, unicode_literals
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||||
|
# Copyright (C) 2020 pwr
|
||||||
|
#
|
||||||
|
# This program 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.
|
||||||
|
#
|
||||||
|
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from cps.services.worker import CalibreTask, STAT_FINISH_SUCCESS
|
from cps.services.worker import CalibreTask, STAT_FINISH_SUCCESS
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import datetime
|
import datetime
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import datetime
|
import datetime
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import os
|
import os
|
||||||
import hashlib
|
import hashlib
|
||||||
from tempfile import gettempdir
|
from tempfile import gettempdir
|
||||||
|
|
10
cps/web.py
10
cps/web.py
|
@ -20,7 +20,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import json
|
import json
|
||||||
|
@ -30,7 +29,6 @@ import copy
|
||||||
|
|
||||||
from babel.dates import format_date
|
from babel.dates import format_date
|
||||||
from babel import Locale as LC
|
from babel import Locale as LC
|
||||||
from babel.core import UnknownLocaleError
|
|
||||||
from flask import Blueprint, jsonify
|
from flask import Blueprint, jsonify
|
||||||
from flask import request, redirect, send_from_directory, make_response, flash, abort, url_for
|
from flask import request, redirect, send_from_directory, make_response, flash, abort, url_for
|
||||||
from flask import session as flask_session
|
from flask import session as flask_session
|
||||||
|
@ -212,7 +210,7 @@ def toggle_archived(book_id):
|
||||||
@web.route("/ajax/view", methods=["POST"])
|
@web.route("/ajax/view", methods=["POST"])
|
||||||
@login_required_if_no_ano
|
@login_required_if_no_ano
|
||||||
def update_view():
|
def update_view():
|
||||||
to_save = request.get_json()
|
to_save = request.form.to_dict() # request.get_json()
|
||||||
try:
|
try:
|
||||||
for element in to_save:
|
for element in to_save:
|
||||||
for param in to_save[element]:
|
for param in to_save[element]:
|
||||||
|
@ -261,10 +259,7 @@ def get_comic_book(book_id, book_format, page):
|
||||||
log.error('unsupported comic format')
|
log.error('unsupported comic format')
|
||||||
return "", 204
|
return "", 204
|
||||||
|
|
||||||
if sys.version_info.major >= 3:
|
b64 = codecs.encode(extract(page), 'base64').decode()
|
||||||
b64 = codecs.encode(extract(page), 'base64').decode()
|
|
||||||
else:
|
|
||||||
b64 = extract(page).encode('base64')
|
|
||||||
ext = names[page].rpartition('.')[-1]
|
ext = names[page].rpartition('.')[-1]
|
||||||
if ext not in ('png', 'gif', 'jpg', 'jpeg', 'webp'):
|
if ext not in ('png', 'gif', 'jpg', 'jpeg', 'webp'):
|
||||||
ext = 'png'
|
ext = 'png'
|
||||||
|
@ -274,7 +269,6 @@ def get_comic_book(book_id, book_format, page):
|
||||||
return "", 204
|
return "", 204
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
# ################################### Typeahead ##################################################################
|
# ################################### Typeahead ##################################################################
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user