mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-23 01:16:18 +00:00
parent
1b4415f98c
commit
811bbbe81f
20
README.md
20
README.md
@ -31,17 +31,19 @@ or as a WSGI application (on Apache for instance). But first:
|
|||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
|
|
||||||
Supysonic looks for two files for its configuration: `~/.supysonic` or `/etc/supysonic` (in this order).
|
Supysonic looks for two files for its configuration: `/etc/supysonic` and `~/.supysonic`, merging values from the two files.
|
||||||
Options are set using the `KEY = VALUE` syntax. String values must be quote-enclosed.
|
Configuration files must respect a structure similar to Windows INI file, with `[section]` headers and using a `KEY = VALUE`
|
||||||
|
or `KEY: VALUE` syntax.
|
||||||
|
|
||||||
Available settings are:
|
Available settings are:
|
||||||
* **DATABASE_URI**: a SQLAlchemy [database URI](http://docs.sqlalchemy.org/en/rel_0_8/core/engines.html#database-urls).
|
* Section **base**:
|
||||||
I personnaly use SQLite (`sqlite:////var/supysonic/supysonic.db`), but it might not be the brightest
|
* **database_uri**: required, a SQLAlchemy [database URI](http://docs.sqlalchemy.org/en/rel_0_8/core/engines.html#database-urls).
|
||||||
idea for large libraries.
|
I personnaly use SQLite (`sqlite:////var/supysonic/supysonic.db`), but it might not be the brightest idea for large libraries.
|
||||||
* **CACHE_DIR**: path to a cache folder. Mostly used for resized cover art images.
|
* **cache_dir**: path to a cache folder. Mostly used for resized cover art images. Defaults to `<system temp dir>/supysonic`.
|
||||||
* **LOG_FILE**: path and base name of a rolling log file.
|
* **log_file**: path and base name of a rolling log file.
|
||||||
* **LASTFM_KEY**: Last.FM [API key](http://www.last.fm/api/accounts) to enable scrobbling
|
* Section **lastfm**:
|
||||||
* **LASTFM_SECRET**: Last.FM API secret matching the key.
|
* **api_key**: Last.FM [API key](http://www.last.fm/api/accounts) to enable scrobbling
|
||||||
|
* **secret**: Last.FM API secret matching the key.
|
||||||
|
|
||||||
### Running as a standalone server
|
### Running as a standalone server
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ def cover_art():
|
|||||||
if size > im.size[0] and size > im.size[1]:
|
if size > im.size[0] and size > im.size[1]:
|
||||||
return send_file(os.path.join(res.path, 'cover.jpg'))
|
return send_file(os.path.join(res.path, 'cover.jpg'))
|
||||||
|
|
||||||
size_path = os.path.join(config.get('CACHE_DIR'), str(size))
|
size_path = os.path.join(config.get('base', 'cache_dir'), str(size))
|
||||||
path = os.path.join(size_path, str(res.id))
|
path = os.path.join(size_path, str(res.id))
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
return send_file(path)
|
return send_file(path)
|
||||||
|
42
config.py
42
config.py
@ -1,23 +1,31 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
import os
|
import os, sys, tempfile, ConfigParser
|
||||||
|
|
||||||
|
config = ConfigParser.RawConfigParser({ 'cache_dir': os.path.join(tempfile.gettempdir(), 'supysonic') })
|
||||||
|
|
||||||
def check():
|
def check():
|
||||||
path = os.path.join(os.path.expanduser('~'), '.supysonic')
|
try:
|
||||||
if os.path.exists(path):
|
ret = config.read([ '/etc/supysonic', os.path.expanduser('~/.supysonic') ])
|
||||||
return path
|
except (ConfigParser.MissingSectionHeaderError, ConfigParser.ParsingError), e:
|
||||||
path = '/etc/supysonic'
|
print >>sys.stderr, "Error while parsing the configuration file(s):\n%s" % str(e)
|
||||||
if os.path.exists(path):
|
return False
|
||||||
return path
|
|
||||||
return False
|
|
||||||
|
|
||||||
config_path = check()
|
if not ret:
|
||||||
config_dict = {}
|
print >>sys.stderr, "No configuration file found"
|
||||||
if config_path:
|
return False
|
||||||
with open(config_path) as f:
|
|
||||||
for line in f:
|
try:
|
||||||
spl = line.split('=')
|
config.get('base', 'database_uri')
|
||||||
config_dict[spl[0].strip()] = eval(spl[1])
|
except:
|
||||||
|
print >>sys.stderr, "No database URI set"
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get(section, name):
|
||||||
|
try:
|
||||||
|
return config.get(section, name)
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
def get(name):
|
|
||||||
return config_dict.get(name)
|
|
||||||
|
2
db.py
2
db.py
@ -42,7 +42,7 @@ class UUID(TypeDecorator):
|
|||||||
def now():
|
def now():
|
||||||
return datetime.datetime.now().replace(microsecond = 0)
|
return datetime.datetime.now().replace(microsecond = 0)
|
||||||
|
|
||||||
engine = create_engine(config.get('DATABASE_URI'), convert_unicode = True)
|
engine = create_engine(config.get('base', 'database_uri'), convert_unicode = True)
|
||||||
session = scoped_session(sessionmaker(autocommit = False, autoflush = False, bind = engine))
|
session = scoped_session(sessionmaker(autocommit = False, autoflush = False, bind = engine))
|
||||||
|
|
||||||
Base = declarative_base()
|
Base = declarative_base()
|
||||||
|
@ -7,9 +7,9 @@ from db import session
|
|||||||
class LastFm:
|
class LastFm:
|
||||||
def __init__(self, user, logger):
|
def __init__(self, user, logger):
|
||||||
self.__user = user
|
self.__user = user
|
||||||
self.__api_key = config.get('LASTFM_KEY')
|
self.__api_key = config.get('lastfm', 'api_key')
|
||||||
self.__api_secret = config.get('LASTFM_SECRET')
|
self.__api_secret = config.get('lastfm', 'secret')
|
||||||
self.__enabled = self.__api_key is not None
|
self.__enabled = self.__api_key is not None and self.__api_secret is not None
|
||||||
self.__logger = logger
|
self.__logger = logger
|
||||||
|
|
||||||
def link_account(self, token):
|
def link_account(self, token):
|
||||||
|
5
main.py
5
main.py
@ -5,11 +5,10 @@ import os.path, sys
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if not config.check():
|
if not config.check():
|
||||||
print >>sys.stderr, "Couldn't find configuration file"
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if not os.path.exists(config.get('CACHE_DIR')):
|
if not os.path.exists(config.get('base', 'cache_dir')):
|
||||||
os.makedirs(config.get('CACHE_DIR'))
|
os.makedirs(config.get('base', 'cache_dir'))
|
||||||
|
|
||||||
import db
|
import db
|
||||||
from web import app
|
from web import app
|
||||||
|
4
main.wsgi
Normal file → Executable file
4
main.wsgi
Normal file → Executable file
@ -7,8 +7,8 @@ import config
|
|||||||
if not config.check():
|
if not config.check():
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if not os.path.exists(config.get('CACHE_DIR')):
|
if not os.path.exists(config.get('base', 'cache_dir')):
|
||||||
os.makedirs(config.get('CACHE_DIR'))
|
os.makedirs(config.get('base', 'cache_dir'))
|
||||||
|
|
||||||
import db
|
import db
|
||||||
db.init_db()
|
db.init_db()
|
||||||
|
2
user.py
2
user.py
@ -26,7 +26,7 @@ def user_index():
|
|||||||
|
|
||||||
@app.route('/user/me')
|
@app.route('/user/me')
|
||||||
def user_profile():
|
def user_profile():
|
||||||
return render_template('profile.html', user = UserManager.get(session.get('userid'))[1], api_key = config.get('LASTFM_KEY'))
|
return render_template('profile.html', user = UserManager.get(session.get('userid'))[1], api_key = config.get('lastfm', 'api_key'))
|
||||||
|
|
||||||
@app.route('/user/changemail', methods = [ 'GET', 'POST' ])
|
@app.route('/user/changemail', methods = [ 'GET', 'POST' ])
|
||||||
def change_mail():
|
def change_mail():
|
||||||
|
4
web.py
4
web.py
@ -6,10 +6,10 @@ app = Flask(__name__)
|
|||||||
app.secret_key = '?9huDM\\H'
|
app.secret_key = '?9huDM\\H'
|
||||||
|
|
||||||
import config
|
import config
|
||||||
if config.get('LOG_FILE'):
|
if config.get('base', 'log_file'):
|
||||||
import logging
|
import logging
|
||||||
from logging.handlers import TimedRotatingFileHandler
|
from logging.handlers import TimedRotatingFileHandler
|
||||||
handler = TimedRotatingFileHandler(config.get('LOG_FILE'), when = 'midnight')
|
handler = TimedRotatingFileHandler(config.get('base', 'log_file'), when = 'midnight')
|
||||||
handler.setLevel(logging.WARNING)
|
handler.setLevel(logging.WARNING)
|
||||||
app.logger.addHandler(handler)
|
app.logger.addHandler(handler)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user