2020-07-27 03:04:49 +00:00
|
|
|
import base64
|
2022-10-16 23:08:31 +00:00
|
|
|
import os
|
2020-12-04 23:43:18 +00:00
|
|
|
import socket
|
2022-10-16 23:08:31 +00:00
|
|
|
import uuid
|
2020-06-13 06:37:05 +00:00
|
|
|
|
2022-08-07 16:28:50 +00:00
|
|
|
from flask import Flask
|
2020-06-21 13:32:31 +00:00
|
|
|
from flask_caching import Cache
|
2020-06-30 05:32:05 +00:00
|
|
|
from flask_compress import Compress
|
2022-10-16 23:08:31 +00:00
|
|
|
from pony.flask import Pony
|
2022-08-07 16:28:50 +00:00
|
|
|
from werkzeug.routing import BaseConverter
|
2020-06-16 09:26:54 +00:00
|
|
|
|
2022-08-09 20:21:45 +00:00
|
|
|
from Utils import title_sorted
|
2020-06-16 09:26:54 +00:00
|
|
|
|
2020-06-14 07:45:23 +00:00
|
|
|
UPLOAD_FOLDER = os.path.relpath('uploads')
|
|
|
|
LOGS_FOLDER = os.path.relpath('logs')
|
2020-06-13 08:16:29 +00:00
|
|
|
os.makedirs(LOGS_FOLDER, exist_ok=True)
|
2020-06-13 06:37:05 +00:00
|
|
|
|
|
|
|
app = Flask(__name__)
|
2020-06-20 18:03:06 +00:00
|
|
|
Pony(app)
|
2020-06-21 13:32:31 +00:00
|
|
|
|
2020-07-25 20:40:24 +00:00
|
|
|
app.jinja_env.filters['any'] = any
|
|
|
|
app.jinja_env.filters['all'] = all
|
|
|
|
|
2021-12-13 04:48:33 +00:00
|
|
|
app.config["SELFHOST"] = True # application process is in charge of running the websites
|
2020-08-17 23:18:37 +00:00
|
|
|
app.config["GENERATORS"] = 8 # maximum concurrent world gens
|
2024-05-17 10:21:01 +00:00
|
|
|
app.config["HOSTERS"] = 8 # maximum concurrent room hosters
|
2021-12-13 04:48:33 +00:00
|
|
|
app.config["SELFLAUNCH"] = True # application process is in charge of launching Rooms.
|
2023-01-21 16:29:27 +00:00
|
|
|
app.config["SELFLAUNCHCERT"] = None # can point to a SSL Certificate to encrypt Room websocket connections
|
|
|
|
app.config["SELFLAUNCHKEY"] = None # can point to a SSL Certificate Key to encrypt Room websocket connections
|
2021-12-13 04:48:33 +00:00
|
|
|
app.config["SELFGEN"] = True # application process is in charge of scheduling Generations.
|
2020-07-10 13:32:58 +00:00
|
|
|
app.config["DEBUG"] = False
|
|
|
|
app.config["PORT"] = 80
|
2020-06-13 06:37:05 +00:00
|
|
|
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
2021-10-16 18:11:26 +00:00
|
|
|
app.config['MAX_CONTENT_LENGTH'] = 64 * 1024 * 1024 # 64 megabyte limit
|
2020-12-04 23:43:18 +00:00
|
|
|
# if you want to deploy, make sure you have a non-guessable secret key
|
|
|
|
app.config["SECRET_KEY"] = bytes(socket.gethostname(), encoding="utf-8")
|
2022-11-06 20:37:11 +00:00
|
|
|
# at what amount of worlds should scheduling be used, instead of rolling in the web-thread
|
2023-04-30 05:13:24 +00:00
|
|
|
app.config["JOB_THRESHOLD"] = 1
|
2022-11-06 20:37:11 +00:00
|
|
|
# after what time in seconds should generation be aborted, freeing the queue slot. Can be set to None to disable.
|
|
|
|
app.config["JOB_TIME"] = 600
|
2020-06-20 18:03:06 +00:00
|
|
|
app.config['SESSION_PERMANENT'] = True
|
2020-07-27 02:05:42 +00:00
|
|
|
|
|
|
|
# waitress uses one thread for I/O, these are for processing of views that then get sent
|
2021-01-03 13:32:32 +00:00
|
|
|
# archipelago.gg uses gunicorn + nginx; ignoring this option
|
2020-07-27 02:05:42 +00:00
|
|
|
app.config["WAITRESS_THREADS"] = 10
|
2021-01-03 13:32:32 +00:00
|
|
|
# a default that just works. archipelago.gg runs on mariadb
|
2020-06-14 05:44:59 +00:00
|
|
|
app.config["PONY"] = {
|
|
|
|
'provider': 'sqlite',
|
2021-03-13 22:36:57 +00:00
|
|
|
'filename': os.path.abspath('ap.db3'),
|
2020-06-14 05:44:59 +00:00
|
|
|
'create_db': True
|
|
|
|
}
|
2020-08-02 20:11:52 +00:00
|
|
|
app.config["MAX_ROLL"] = 20
|
2023-09-09 03:02:05 +00:00
|
|
|
app.config["CACHE_TYPE"] = "SimpleCache"
|
2023-03-09 20:31:00 +00:00
|
|
|
app.config["HOST_ADDRESS"] = ""
|
2024-04-21 00:58:56 +00:00
|
|
|
app.config["ASSET_RIGHTS"] = False
|
2020-11-03 04:26:10 +00:00
|
|
|
|
2023-09-09 03:02:05 +00:00
|
|
|
cache = Cache()
|
2020-06-30 05:32:05 +00:00
|
|
|
Compress(app)
|
2020-06-13 06:37:05 +00:00
|
|
|
|
2020-07-27 03:04:49 +00:00
|
|
|
|
|
|
|
class B64UUIDConverter(BaseConverter):
|
|
|
|
|
|
|
|
def to_python(self, value):
|
|
|
|
return uuid.UUID(bytes=base64.urlsafe_b64decode(value + '=='))
|
|
|
|
|
|
|
|
def to_url(self, value):
|
|
|
|
return base64.urlsafe_b64encode(value.bytes).rstrip(b'=').decode('ascii')
|
|
|
|
|
|
|
|
|
|
|
|
# short UUID
|
|
|
|
app.url_map.converters["suuid"] = B64UUIDConverter
|
|
|
|
app.jinja_env.filters['suuid'] = lambda value: base64.urlsafe_b64encode(value.bytes).rstrip(b'=').decode('ascii')
|
2022-08-09 20:21:45 +00:00
|
|
|
app.jinja_env.filters["title_sorted"] = title_sorted
|
2020-06-13 06:37:05 +00:00
|
|
|
|
2022-04-05 05:14:30 +00:00
|
|
|
|
2022-08-07 16:28:50 +00:00
|
|
|
def register():
|
|
|
|
"""Import submodules, triggering their registering on flask routing.
|
|
|
|
Note: initializes worlds subsystem."""
|
|
|
|
# has automatic patch integration
|
2022-09-29 22:36:30 +00:00
|
|
|
import worlds.AutoWorld
|
|
|
|
import worlds.Files
|
|
|
|
app.jinja_env.filters['supports_apdeltapatch'] = lambda game_name: \
|
|
|
|
game_name in worlds.Files.AutoPatchRegister.patch_types
|
2022-04-05 05:14:30 +00:00
|
|
|
|
2022-08-07 16:28:50 +00:00
|
|
|
from WebHostLib.customserver import run_server_process
|
|
|
|
# to trigger app routing picking up on it
|
WebHost: Massive overhaul of options pages (#2614)
* Implement support for option groups. WebHost options pages still need to be updated.
* Remove debug output
* In-progress conversion of player-options to Jinja rendering
* Support "Randomize" button without JS, transpile SCSS to CSS, include map file for later editors
* Un-alphabetize options, add default group name for item/location Option classes, implement more option types
* Re-flow UI generation to avoid printing rows with unsupported or invalid option types, add support for TextChoice options
* Support all remaining option types
* Rendering improvements and CSS fixes for prettiness
* Wrap options in a form, update button styles, fix labels, disable inputs where the default is random, nuke the JS
* Minor CSS tweaks, as recommended by the designer
* Hide JS-required elements in noscript tag. Add JS reactivity to range, named-range, and randomize buttons.
* Fix labels, add JS handling for TextChoice
* Make option groups collapsable
* PEP8 current option_groups progress (#2604)
* Make the python more PEP8 and remove unneeded imports
* remove LocationSet from `Item & Location Options` group
* It's ugly, but YAML generation is working
* Stop generating JSON files for player-options pages
* Do not include ItemDict entries whose values are zero
* Properly format yaml output
* Save options when form is submitted, load options on page load
* Fix options being omitted from the page if a group has an even number of options
* Implement generate-game, escape option descriptions
* Fix "randomize" checkboxes not properly setting YAML options to "random"
* Add a separator between item/location groups and items/locations in their respective lists
* Implement option presets
* Fix docs to detail what actually ended up happening
* implement option groups on webworld to allow dev sorting (#2616)
* Force extremely long item/location/option names with no spaces to text-wrap
* Fix "randomize" button being too wide in single-column display, change page header to include game name
* Update preset select to read "custom" when updating form inputs. Show error message if the user doesn't input a name
* Un-break weighted-options, add option group names to weighted options
* Nuke weighted-options. Set up framework to rebuild it in Jinja.
* Generate styles with scss, remove styles which will be replaced, add placeholders for worlds
* Support Toggle, DefaultOnToggle, and Choice options in weighted-options
* Implement expand/collapse without JS for worlds and option groups
* Properly style set options
* Implement Range and NamedRange. Also, CSS is hard.
* Add support for remaining option types. JS and backend still forthcoming.
* Add JS functionality for collapsing game divs, populating span values on range updates. Add <noscript> tag to warn users with JS disabled.
* Support showing/hiding game divs based on range value for game
* Add support for adding/deleting range rows
* Save settings to localStorage on form submission
* Save deleted options on form submission
* Break weighted-options into a per-game page.
- Break weighted-options into a per-game page
- Add "advanced options" links to supported games page
- Use details/summary tags on supported games, player-options, and weighted-options
- Fix bug preventing previously deleted rows from being removed on page load if JS is enabled
- Move route handling for options pages to options.py
- Remove world handling from weighted-options
* Implement loading previous settings from localStorage on page load if JS is enabled
* Weighted options can now generate YAML files and single-player games
* options pages now respect option visibility settings for simple and complex pages
* Remove `/weighted-settings` redirect, fix weighted-options link on player-options page
* Fix instance of AutoWorld not having access to proper `random`
* Catch instances of frozenset along with set
* Restore word-wrap in tooltips
* Fix word wrap in player-options labels
* Add `dedent` filter to help with formatting tooltips in player-options
* Do not change the ordering of keys when printing yaml files
* Move necessary import out of conditional statement
* Expand only the first option group by default on both options pages
* Respect option visibility when generating yaml template files
* Swap to double quotes
* Replace instances of `/weighted-settings` with `/weighted-options`, swap out incomplete links
* Strip newlines and spaces after applying dedent filter
* Fix documentation for option groups
* Update site map
* Update various docs
* Sort OptionSet lists alphabetically
* Minor style tweak
* Fix extremely long text overflowing tooltips
* Convert player-options to use CSS grid instead of tables
* Do not display link to weighted-options page on supported games if the options page is an external link
* Update worlds/AutoWorld.py
Bugfix by @alwaysintreble
Co-authored-by: Aaron Wagener <mmmcheese158@gmail.com>
* Fix NamedRange options not being properly set if a preset it loaded
* Move option-presets route into options.py
* Include preset name in YAML if not "default" and not "custom"
* Removed macros for PlandoBosses and DefaultOnToggle, as they were handled by their parent classes
* Fix not disabling custom inputs when the randomize button is clicked
* Only sort OptionList and OptionSet valid_keys if they are unordered
* Quick style fixes for player-settings to give `select` elements `text-overflow: ellipsis` and increase base size of left-column
* Prevent showing a horizontal scroll bar on player-options if the browser width was beneath a certain threshold
* Fix a bug in weighted-options which prevented inputting a negative value for new range inputs
---------
Co-authored-by: Aaron Wagener <mmmcheese158@gmail.com>
2024-05-18 04:11:57 +00:00
|
|
|
from . import tracker, upload, landing, check, generate, downloads, api, stats, misc, robots, options
|
2021-07-25 03:09:34 +00:00
|
|
|
|
2022-08-07 16:28:50 +00:00
|
|
|
app.register_blueprint(api.api_endpoints)
|