diff --git a/boofilsic/settings.py b/boofilsic/settings.py index 02eea413..c5abe792 100644 --- a/boofilsic/settings.py +++ b/boofilsic/settings.py @@ -210,6 +210,9 @@ GAME_MEDIA_PATH_ROOT = 'game/' DEFAULT_GAME_IMAGE = os.path.join(GAME_MEDIA_PATH_ROOT, 'default.svg') SYNC_FILE_PATH_ROOT = 'sync/' +# Allow user to login via any Mastodon/Pleroma sites +MASTODON_ALLOW_ANY_SITE = False + # Timeout of requests to Mastodon, in seconds MASTODON_TIMEOUT = 30 diff --git a/books/models.py b/books/models.py index 4f898709..012b96eb 100644 --- a/books/models.py +++ b/books/models.py @@ -6,12 +6,12 @@ from django.core.serializers.json import DjangoJSONEncoder from django.shortcuts import reverse from common.models import Entity, Mark, Review, Tag from common.utils import GenerateDateUUIDMediaFilePath -from boofilsic.settings import BOOK_MEDIA_PATH_ROOT, DEFAULT_BOOK_IMAGE from django.utils import timezone +from django.conf import settings def book_cover_path(instance, filename): - return GenerateDateUUIDMediaFilePath(instance, filename, BOOK_MEDIA_PATH_ROOT) + return GenerateDateUUIDMediaFilePath(instance, filename, settings.BOOK_MEDIA_PATH_ROOT) class Book(Entity): @@ -43,7 +43,7 @@ class Book(Entity): pages = models.PositiveIntegerField(_("pages"), null=True, blank=True) isbn = models.CharField(_("ISBN"), blank=True, null=False, max_length=20, db_index=True, default='') # to store previously scrapped data - cover = models.ImageField(_("cover picture"), upload_to=book_cover_path, default=DEFAULT_BOOK_IMAGE, blank=True) + cover = models.ImageField(_("cover picture"), upload_to=book_cover_path, default=settings.DEFAULT_BOOK_IMAGE, blank=True) contents = models.TextField(blank=True, default="") class Meta: diff --git a/books/views.py b/books/views.py index a06c31cf..bbc8f593 100644 --- a/books/views.py +++ b/books/views.py @@ -17,7 +17,7 @@ from common.models import SourceSiteEnum from .models import * from .forms import * from .forms import BookMarkStatusTranslator -from boofilsic.settings import MASTODON_TAGS +from django.conf import settings logger = logging.getLogger(__name__) @@ -314,7 +314,7 @@ def create_update_mark(request): f"《{book.title}》" + \ rating_to_emoji(form.cleaned_data['rating']) - # tags = MASTODON_TAGS % {'category': '书', 'type': '标记'} + # tags = settings.MASTODON_TAGS % {'category': '书', 'type': '标记'} tags = '' content = words + '\n' + url + '\n' + \ form.cleaned_data['text'] + '\n' + tags @@ -405,7 +405,7 @@ def create_review(request, book_id): url = "https://" + request.get_host() + reverse("books:retrieve_review", args=[form.instance.id]) words = "发布了关于" + f"《{form.instance.book.title}》" + "的评论" - # tags = MASTODON_TAGS % {'category': '书', 'type': '评论'} + # tags = settings.MASTODON_TAGS % {'category': '书', 'type': '评论'} tags = '' content = words + '\n' + url + \ '\n' + form.cleaned_data['title'] + '\n' + tags @@ -457,7 +457,7 @@ def update_review(request, id): url = "https://" + request.get_host() + reverse("books:retrieve_review", args=[form.instance.id]) words = "发布了关于" + f"《{form.instance.book.title}》" + "的评论" - # tags = MASTODON_TAGS % {'category': '书', 'type': '评论'} + # tags = settings.MASTODON_TAGS % {'category': '书', 'type': '评论'} tags = '' content = words + '\n' + url + \ '\n' + form.cleaned_data['title'] + '\n' + tags diff --git a/common/models.py b/common/models.py index c6bf6a70..feafd0ef 100644 --- a/common/models.py +++ b/common/models.py @@ -8,8 +8,8 @@ from django.db.models import Q from markdownx.models import MarkdownxField from users.models import User from mastodon.api import get_relationships, get_cross_site_id -from boofilsic.settings import CLIENT_NAME from django.utils import timezone +from django.conf import settings RE_HTML_TAG = re.compile(r"<[^>]*>") @@ -18,7 +18,7 @@ RE_HTML_TAG = re.compile(r"<[^>]*>") # abstract base classes ################################### class SourceSiteEnum(models.TextChoices): - IN_SITE = "in-site", CLIENT_NAME + IN_SITE = "in-site", settings.CLIENT_NAME DOUBAN = "douban", _("豆瓣") SPOTIFY = "spotify", _("Spotify") IMDB = "imdb", _("IMDb") diff --git a/common/scraper.py b/common/scraper.py index f5db791b..0005e958 100644 --- a/common/scraper.py +++ b/common/scraper.py @@ -9,8 +9,6 @@ import time from lxml import html from mimetypes import guess_extension from threading import Thread -from boofilsic.settings import LUMINATI_USERNAME, LUMINATI_PASSWORD, DEBUG, IMDB_API_KEY, SCRAPERAPI_KEY -from boofilsic.settings import SPOTIFY_CREDENTIAL from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from django.core.exceptions import ObjectDoesNotExist, ValidationError @@ -24,6 +22,7 @@ from music.models import Album, Song from music.forms import AlbumForm, SongForm from games.models import Game from games.forms import GameForm +from django.conf import settings RE_NUMBERS = re.compile(r"\d+\d*") @@ -152,12 +151,12 @@ class AbstractScraper: session_id = random.random() proxy_url = ('http://%s-country-cn-session-%s:%s@zproxy.lum-superproxy.io:%d' % - (LUMINATI_USERNAME, session_id, LUMINATI_PASSWORD, PORT)) + (settings.LUMINATI_USERNAME, session_id, settings.LUMINATI_PASSWORD, PORT)) proxies = { 'http': proxy_url, 'https': proxy_url, } - # if DEBUG: + # if settings.DEBUG: # proxies = None r = requests.get(url, proxies=proxies, headers=headers, timeout=TIMEOUT) @@ -175,12 +174,12 @@ class AbstractScraper: raw_img = None session_id = random.random() proxy_url = ('http://%s-country-cn-session-%s:%s@zproxy.lum-superproxy.io:%d' % - (LUMINATI_USERNAME, session_id, LUMINATI_PASSWORD, PORT)) + (settings.LUMINATI_USERNAME, session_id, settings.LUMINATI_PASSWORD, PORT)) proxies = { 'http': proxy_url, 'https': proxy_url, } - # if DEBUG: + # if settings.DEBUG: # proxies = None if url: img_response = requests.get( @@ -225,7 +224,7 @@ class DoubanScrapperMixin: def download_page(cls, url, headers): url = cls.get_effective_url(url) - scraper_api_endpoint = f'http://api.scraperapi.com?api_key={SCRAPERAPI_KEY}&url={url}' + scraper_api_endpoint = f'http://api.scraperapi.com?api_key={settings.SCRAPERAPI_KEY}&url={url}' r = requests.get(scraper_api_endpoint, timeout=TIMEOUT) @@ -926,7 +925,7 @@ def invoke_spotify_token(): "grant_type": "client_credentials" }, headers={ - "Authorization": f"Basic {SPOTIFY_CREDENTIAL}" + "Authorization": f"Basic {settings.SPOTIFY_CREDENTIAL}" } ) data = r.json() @@ -940,7 +939,7 @@ def invoke_spotify_token(): "grant_type": "client_credentials" }, headers={ - "Authorization": f"Basic {SPOTIFY_CREDENTIAL}" + "Authorization": f"Basic {settings.SPOTIFY_CREDENTIAL}" } ) data = r.json() @@ -1049,7 +1048,7 @@ class ImdbMovieScraper(AbstractScraper): @classmethod def get_api_url(cls, url): - return f"https://imdb-api.com/zh/API/Title/{IMDB_API_KEY}/{cls.regex.findall(url)[0]}/FullActor," + return f"https://imdb-api.com/zh/API/Title/{settings.IMDB_API_KEY}/{cls.regex.findall(url)[0]}/FullActor," class DoubanGameScraper(DoubanScrapperMixin, AbstractScraper): diff --git a/games/models.py b/games/models.py index a2614f0a..74a6dcf0 100644 --- a/games/models.py +++ b/games/models.py @@ -6,12 +6,12 @@ from django.core.serializers.json import DjangoJSONEncoder from django.shortcuts import reverse from common.models import Entity, Mark, Review, Tag from common.utils import ChoicesDictGenerator, GenerateDateUUIDMediaFilePath -from boofilsic.settings import GAME_MEDIA_PATH_ROOT, DEFAULT_GAME_IMAGE from django.utils import timezone +from django.conf import settings def game_cover_path(instance, filename): - return GenerateDateUUIDMediaFilePath(instance, filename, GAME_MEDIA_PATH_ROOT) + return GenerateDateUUIDMediaFilePath(instance, filename, settings.GAME_MEDIA_PATH_ROOT) class Game(Entity): @@ -68,7 +68,7 @@ class Game(Entity): verbose_name=_("平台") ) - cover = models.ImageField(_("封面"), upload_to=game_cover_path, default=DEFAULT_GAME_IMAGE, blank=True) + cover = models.ImageField(_("封面"), upload_to=game_cover_path, default=settings.DEFAULT_GAME_IMAGE, blank=True) diff --git a/games/views.py b/games/views.py index f69e4918..143213c8 100644 --- a/games/views.py +++ b/games/views.py @@ -16,7 +16,7 @@ from common.views import PAGE_LINK_NUMBER, jump_or_scrape from common.models import SourceSiteEnum from .models import * from .forms import * -from boofilsic.settings import MASTODON_TAGS +from django.conf import settings logger = logging.getLogger(__name__) @@ -316,7 +316,7 @@ def create_update_mark(request): f"《{game.title}》" + \ rating_to_emoji(form.cleaned_data['rating']) - # tags = MASTODON_TAGS % {'category': '书', 'type': '标记'} + # tags = settings.MASTODON_TAGS % {'category': '书', 'type': '标记'} tags = '' content = words + '\n' + url + '\n' + \ form.cleaned_data['text'] + '\n' + tags @@ -408,7 +408,7 @@ def create_review(request, game_id): url = "https://" + request.get_host() + reverse("games:retrieve_review", args=[form.instance.id]) words = "发布了关于" + f"《{form.instance.game.title}》" + "的评论" - # tags = MASTODON_TAGS % {'category': '书', 'type': '评论'} + # tags = settings.MASTODON_TAGS % {'category': '书', 'type': '评论'} tags = '' content = words + '\n' + url + \ '\n' + form.cleaned_data['title'] + '\n' + tags @@ -460,7 +460,7 @@ def update_review(request, id): url = "https://" + request.get_host() + reverse("games:retrieve_review", args=[form.instance.id]) words = "发布了关于" + f"《{form.instance.game.title}》" + "的评论" - # tags = MASTODON_TAGS % {'category': '书', 'type': '评论'} + # tags = settings.MASTODON_TAGS % {'category': '书', 'type': '评论'} tags = '' content = words + '\n' + url + \ '\n' + form.cleaned_data['title'] + '\n' + tags diff --git a/mastodon/api.py b/mastodon/api.py index 5e48c944..e9d17e1e 100644 --- a/mastodon/api.py +++ b/mastodon/api.py @@ -3,9 +3,8 @@ import string import random import functools from django.core.exceptions import ObjectDoesNotExist -from boofilsic.settings import MASTODON_TIMEOUT -from boofilsic.settings import CLIENT_NAME, APP_WEBSITE, REDIRECT_URIS from .models import CrossSiteUserInfo +from django.conf import settings # See https://docs.joinmastodon.org/methods/accounts/ @@ -47,8 +46,8 @@ API_CREATE_APP = '/api/v1/apps' API_SEARCH = '/api/v2/search' -get = functools.partial(requests.get, timeout=MASTODON_TIMEOUT) -post = functools.partial(requests.post, timeout=MASTODON_TIMEOUT) +get = functools.partial(requests.get, timeout=settings.MASTODON_TIMEOUT) +post = functools.partial(requests.post, timeout=settings.MASTODON_TIMEOUT) # low level api below @@ -96,14 +95,13 @@ def create_app(domain_name): url = 'http://' + domain_name + API_CREATE_APP payload = { - 'client_name': CLIENT_NAME, + 'client_name': settings.CLIENT_NAME, 'scopes': 'read write follow', - 'redirect_uris': REDIRECT_URIS, - 'website': APP_WEBSITE + 'redirect_uris': settings.REDIRECT_URIS, + 'website': settings.APP_WEBSITE } - from boofilsic.settings import DEBUG - if DEBUG: + if settings.DEBUG: payload['redirect_uris'] = 'http://localhost/users/OAuth2_login/\nurn:ietf:wg:oauth:2.0:oob' payload['client_name'] = 'test_do_not_authorise' diff --git a/mastodon/auth.py b/mastodon/auth.py index 29a691e8..7cbde87a 100644 --- a/mastodon/auth.py +++ b/mastodon/auth.py @@ -2,6 +2,7 @@ from django.contrib.auth.backends import ModelBackend, UserModel from django.shortcuts import reverse from .api import * from .models import MastodonApplication +from django.conf import settings def obtain_token(site, request, code): @@ -15,8 +16,7 @@ def obtain_token(site, request, code): 'code': code, 'scope': 'read write' } - from boofilsic.settings import DEBUG - if DEBUG: + if settings.DEBUG: payload['redirect_uri']= f"http://{request.get_host()}{reverse('users:OAuth2_login')}", if mast_app.is_proxy: url = 'https://' + mast_app.proxy_to + API_OBTAIN_TOKEN diff --git a/mastodon/utils.py b/mastodon/utils.py index 7da7f94e..7744aeaa 100644 --- a/mastodon/utils.py +++ b/mastodon/utils.py @@ -1,4 +1,4 @@ -from boofilsic.settings import STAR_EMPTY, STAR_HALF, STAR_SOLID +from django.conf import settings def rating_to_emoji(score): @@ -8,7 +8,7 @@ def rating_to_emoji(score): solid_stars = score // 2 half_star = int(bool(score % 2)) empty_stars = 5 - solid_stars if not half_star else 5 - solid_stars - 1 - emoji_code = STAR_SOLID * solid_stars + STAR_HALF * half_star + STAR_EMPTY * empty_stars + emoji_code = settings.STAR_SOLID * solid_stars + settings.STAR_HALF * half_star + settings.STAR_EMPTY * empty_stars emoji_code = emoji_code.replace("::", ": :") emoji_code = ' ' + emoji_code + ' ' return emoji_code \ No newline at end of file diff --git a/movies/models.py b/movies/models.py index be6d4ba3..1bee697c 100644 --- a/movies/models.py +++ b/movies/models.py @@ -6,12 +6,12 @@ from django.core.serializers.json import DjangoJSONEncoder from django.shortcuts import reverse from common.models import Entity, Mark, Review, Tag from common.utils import ChoicesDictGenerator, GenerateDateUUIDMediaFilePath -from boofilsic.settings import MOVIE_MEDIA_PATH_ROOT, DEFAULT_MOVIE_IMAGE from django.utils import timezone +from django.conf import settings def movie_cover_path(instance, filename): - return GenerateDateUUIDMediaFilePath(instance, filename, MOVIE_MEDIA_PATH_ROOT) + return GenerateDateUUIDMediaFilePath(instance, filename, settings.MOVIE_MEDIA_PATH_ROOT) class MovieGenreEnum(models.TextChoices): @@ -140,7 +140,7 @@ class Movie(Entity): year = models.PositiveIntegerField(null=True, blank=True) duration = models.CharField(blank=True, default='', max_length=200) - cover = models.ImageField(_("poster"), upload_to=movie_cover_path, default=DEFAULT_MOVIE_IMAGE, blank=True) + cover = models.ImageField(_("poster"), upload_to=movie_cover_path, default=settings.DEFAULT_MOVIE_IMAGE, blank=True) ############################################ # exclusive fields to series diff --git a/movies/views.py b/movies/views.py index f63cdeef..2423a3e6 100644 --- a/movies/views.py +++ b/movies/views.py @@ -16,7 +16,7 @@ from common.views import PAGE_LINK_NUMBER, jump_or_scrape from common.models import SourceSiteEnum from .models import * from .forms import * -from boofilsic.settings import MASTODON_TAGS +from django.conf import settings logger = logging.getLogger(__name__) @@ -315,7 +315,7 @@ def create_update_mark(request): f"《{movie.title}》" + \ rating_to_emoji(form.cleaned_data['rating']) - # tags = MASTODON_TAGS % {'category': '书', 'type': '标记'} + # tags = settings.MASTODON_TAGS % {'category': '书', 'type': '标记'} tags = '' content = words + '\n' + url + '\n' + \ form.cleaned_data['text'] + '\n' + tags @@ -407,7 +407,7 @@ def create_review(request, movie_id): url = "https://" + request.get_host() + reverse("movies:retrieve_review", args=[form.instance.id]) words = "发布了关于" + f"《{form.instance.movie.title}》" + "的评论" - # tags = MASTODON_TAGS % {'category': '书', 'type': '评论'} + # tags = settings.MASTODON_TAGS % {'category': '书', 'type': '评论'} tags = '' content = words + '\n' + url + \ '\n' + form.cleaned_data['title'] + '\n' + tags @@ -459,7 +459,7 @@ def update_review(request, id): url = "https://" + request.get_host() + reverse("movies:retrieve_review", args=[form.instance.id]) words = "发布了关于" + f"《{form.instance.movie.title}》" + "的评论" - # tags = MASTODON_TAGS % {'category': '书', 'type': '评论'} + # tags = settings.MASTODON_TAGS % {'category': '书', 'type': '评论'} tags = '' content = words + '\n' + url + \ '\n' + form.cleaned_data['title'] + '\n' + tags diff --git a/music/models.py b/music/models.py index c738db5b..1eb02f7b 100644 --- a/music/models.py +++ b/music/models.py @@ -6,16 +6,16 @@ from django.core.serializers.json import DjangoJSONEncoder from django.shortcuts import reverse from common.models import Entity, Mark, Review, Tag from common.utils import ChoicesDictGenerator, GenerateDateUUIDMediaFilePath -from boofilsic.settings import SONG_MEDIA_PATH_ROOT, DEFAULT_SONG_IMAGE, ALBUM_MEDIA_PATH_ROOT, DEFAULT_ALBUM_IMAGE from django.utils import timezone +from django.conf import settings def song_cover_path(instance, filename): - return GenerateDateUUIDMediaFilePath(instance, filename, SONG_MEDIA_PATH_ROOT) + return GenerateDateUUIDMediaFilePath(instance, filename, settings.SONG_MEDIA_PATH_ROOT) def album_cover_path(instance, filename): - return GenerateDateUUIDMediaFilePath(instance, filename, ALBUM_MEDIA_PATH_ROOT) + return GenerateDateUUIDMediaFilePath(instance, filename, settings.ALBUM_MEDIA_PATH_ROOT) class Album(Entity): @@ -23,7 +23,7 @@ class Album(Entity): release_date = models.DateField( _('发行日期'), auto_now=False, auto_now_add=False, null=True, blank=True) cover = models.ImageField( - _("封面"), upload_to=album_cover_path, default=DEFAULT_ALBUM_IMAGE, blank=True) + _("封面"), upload_to=album_cover_path, default=settings.DEFAULT_ALBUM_IMAGE, blank=True) duration = models.PositiveIntegerField(_("时长"), null=True, blank=True) artist = postgres.ArrayField( models.CharField(_("artist"), blank=True, @@ -70,7 +70,7 @@ class Song(Entity): # duration in ms duration = models.PositiveIntegerField(_("时长"), null=True, blank=True) cover = models.ImageField( - _("封面"), upload_to=song_cover_path, default=DEFAULT_SONG_IMAGE, blank=True) + _("封面"), upload_to=song_cover_path, default=settings.DEFAULT_SONG_IMAGE, blank=True) artist = postgres.ArrayField( models.CharField(blank=True, default='', max_length=100), diff --git a/music/views.py b/music/views.py index 993dae35..5a8fcb82 100644 --- a/music/views.py +++ b/music/views.py @@ -1,4 +1,3 @@ -# from boofilsic.settings import MASTODON_TAGS from .forms import * from .models import * from common.models import SourceSiteEnum @@ -20,7 +19,6 @@ import logging from django.shortcuts import render - logger = logging.getLogger(__name__) mastodon_logger = logging.getLogger("django.mastodon") diff --git a/sync/models.py b/sync/models.py index e5264477..ba74cd06 100644 --- a/sync/models.py +++ b/sync/models.py @@ -2,12 +2,12 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ import django.contrib.postgres.fields as postgres from users.models import User -from boofilsic.settings import SYNC_FILE_PATH_ROOT from common.utils import GenerateDateUUIDMediaFilePath +from django.conf import settings def sync_file_path(instance, filename): - return GenerateDateUUIDMediaFilePath(instance, filename, SYNC_FILE_PATH_ROOT) + return GenerateDateUUIDMediaFilePath(instance, filename, settings.SYNC_FILE_PATH_ROOT) class SyncTask(models.Model): diff --git a/users/models.py b/users/models.py index 7d35433f..ae8aed3c 100644 --- a/users/models.py +++ b/users/models.py @@ -3,14 +3,14 @@ import django.contrib.postgres.fields as postgres from django.db import models from django.contrib.auth.models import AbstractUser from django.utils import timezone -from boofilsic.settings import REPORT_MEDIA_PATH_ROOT, DEFAULT_PASSWORD from django.core.serializers.json import DjangoJSONEncoder from django.utils.translation import ugettext_lazy as _ from common.utils import GenerateDateUUIDMediaFilePath +from django.conf import settings def report_image_path(instance, filename): - return GenerateDateUUIDMediaFilePath(instance, filename, REPORT_MEDIA_PATH_ROOT) + return GenerateDateUUIDMediaFilePath(instance, filename, settings.REPORT_MEDIA_PATH_ROOT) class User(AbstractUser): @@ -28,8 +28,8 @@ class User(AbstractUser): ] def save(self, *args, **kwargs): - """ Automatically populate password field with DEFAULT_PASSWORD before saving.""" - self.set_password(DEFAULT_PASSWORD) + """ Automatically populate password field with settings.DEFAULT_PASSWORD before saving.""" + self.set_password(settings.DEFAULT_PASSWORD) return super().save(*args, **kwargs) def __str__(self): diff --git a/users/templates/users/login.html b/users/templates/users/login.html index 27a0a0fa..109b250b 100644 --- a/users/templates/users/login.html +++ b/users/templates/users/login.html @@ -35,6 +35,11 @@ {% if user.is_authenticated %} {% trans '前往我的主页' %} + {% elif allow_any_site %} +
+ + +
{% else %}