<s> from datetime import datetime <EOL> import bcrypt <EOL> import hashlib <EOL> import os <EOL> import uuid <EOL> from flask import current_app as app <EOL> from flask . ext . sqlalchemy import SQLAlchemy <EOL> from itsdangerous import ( BadSignature , SignatureExpired , <EOL> TimedJSONWebSignatureSerializer as Serializer ) <EOL> from sqlalchemy . exc import OperationalError <EOL> from sqlalchemy . sql . expression import func <EOL> from slugify import slugify <EOL> from shiva import dbtypes <EOL> from shiva . auth import Roles <EOL> from shiva . utils import MetadataManager <EOL> db = SQLAlchemy ( ) <EOL> __all__ = ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ) <EOL> def random_row ( model ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> instance = model . query . order_by ( func . random ( ) ) . limit ( <NUM_LIT:1> ) . first ( ) <EOL> except OperationalError : <EOL> instance = model . query . order_by ( func . rand ( ) ) . limit ( <NUM_LIT:1> ) . first ( ) <EOL> return instance <EOL> track_artist = db . Table ( '<STR_LIT>' , <EOL> db . Column ( '<STR_LIT>' , dbtypes . GUID , db . ForeignKey ( '<STR_LIT>' ) ) , <EOL> db . Column ( '<STR_LIT>' , dbtypes . GUID , db . ForeignKey ( '<STR_LIT>' ) ) , <EOL> ) <EOL> track_album = db . Table ( '<STR_LIT>' , <EOL> db . Column ( '<STR_LIT>' , dbtypes . GUID , db . ForeignKey ( '<STR_LIT>' ) ) , <EOL> db . Column ( '<STR_LIT>' , dbtypes . GUID , db . ForeignKey ( '<STR_LIT>' ) ) , <EOL> ) <EOL> class Artist ( db . Model ) : <EOL> __tablename__ = '<STR_LIT>' <EOL> pk = db . Column ( dbtypes . GUID , default = uuid . uuid4 , primary_key = True ) <EOL> name = db . Column ( db . String ( <NUM_LIT> ) , unique = True , nullable = False ) <EOL> slug = db . Column ( db . String ( <NUM_LIT> ) ) <EOL> image = db . Column ( db . String ( <NUM_LIT> ) ) <EOL> events = db . Column ( db . String ( <NUM_LIT> ) ) <EOL> date_added = db . Column ( db . Date ( ) , nullable = False ) <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> if '<STR_LIT>' not in kwargs : <EOL> kwargs [ '<STR_LIT>' ] = datetime . today ( ) <EOL> super ( Artist , self ) . __init__ ( * args , ** kwargs ) <EOL> @ property <EOL> def albums ( self ) : <EOL> albums = [ ] <EOL> for track in self . tracks : <EOL> for album in track . albums : <EOL> if album not in albums : <EOL> albums . append ( album ) <EOL> return albums <EOL> @ classmethod <EOL> def random ( cls ) : <EOL> return random_row ( cls ) <EOL> def __setattr__ ( self , attr , value ) : <EOL> if attr == '<STR_LIT:name>' : <EOL> super ( Artist , self ) . __setattr__ ( '<STR_LIT>' , slugify ( value ) ) <EOL> super ( Artist , self ) . __setattr__ ( attr , value ) <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % self . name <EOL> class Album ( db . Model ) : <EOL> __tablename__ = '<STR_LIT>' <EOL> pk = db . Column ( dbtypes . GUID , default = uuid . uuid4 , primary_key = True ) <EOL> name = db . Column ( db . String ( <NUM_LIT> ) , nullable = False ) <EOL> slug = db . Column ( db . String ( <NUM_LIT> ) ) <EOL> year = db . Column ( db . Integer ) <EOL> cover = db . Column ( db . String ( <NUM_LIT> ) ) <EOL> date_added = db . Column ( db . Date ( ) , nullable = False ) <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> if '<STR_LIT>' not in kwargs : <EOL> kwargs [ '<STR_LIT>' ] = datetime . today ( ) <EOL> super ( Album , self ) . __init__ ( * args , ** kwargs ) <EOL> @ property <EOL> def artists ( self ) : <EOL> """<STR_LIT>""" <EOL> artists = [ ] <EOL> for track in self . tracks : <EOL> for artist in track . artists : <EOL> if artist not in artists : <EOL> artists . append ( artist ) <EOL> return artists <EOL> @ classmethod <EOL> def random ( cls ) : <EOL> return random_row ( cls ) <EOL> def __setattr__ ( self , attr , value ) : <EOL> if attr == '<STR_LIT:name>' : <EOL> super ( Album , self ) . __setattr__ ( '<STR_LIT>' , slugify ( value ) ) <EOL> super ( Album , self ) . __setattr__ ( attr , value ) <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % self . name <EOL> class Track ( db . Model ) : <EOL> __tablename__ = '<STR_LIT>' <EOL> pk = db . Column ( dbtypes . GUID , default = uuid . uuid4 , primary_key = True ) <EOL> path = db . Column ( db . Unicode ( <NUM_LIT> ) , unique = True , nullable = False ) <EOL> title = db . Column ( db . String ( <NUM_LIT> ) ) <EOL> slug = db . Column ( db . String ( <NUM_LIT> ) ) <EOL> bitrate = db . Column ( db . Integer ) <EOL> file_size = db . Column ( db . Integer ) <EOL> length = db . Column ( db . Integer ) <EOL> ordinal = db . Column ( db . Integer ) <EOL> date_added = db . Column ( db . Date ( ) , nullable = False ) <EOL> hash = db . Column ( db . String ( <NUM_LIT:32> ) ) <EOL> lyrics = db . relationship ( '<STR_LIT>' , backref = '<STR_LIT>' , uselist = False ) <EOL> albums = db . relationship ( '<STR_LIT>' , secondary = track_album , lazy = '<STR_LIT>' , <EOL> backref = db . backref ( '<STR_LIT>' , lazy = '<STR_LIT>' ) ) <EOL> artists = db . relationship ( '<STR_LIT>' , secondary = track_artist , lazy = '<STR_LIT>' , <EOL> backref = db . backref ( '<STR_LIT>' , lazy = '<STR_LIT>' ) ) <EOL> def __init__ ( self , path , * args , ** kwargs ) : <EOL> if not isinstance ( path , ( basestring , file ) ) : <EOL> raise ValueError ( '<STR_LIT>' <EOL> '<STR_LIT>' % type ( path ) ) <EOL> _path = path <EOL> if isinstance ( path , file ) : <EOL> _path = path . name <EOL> no_metadata = kwargs . get ( '<STR_LIT>' , False ) <EOL> if '<STR_LIT>' in kwargs : <EOL> del ( kwargs [ '<STR_LIT>' ] ) <EOL> hash_file = kwargs . get ( '<STR_LIT>' , False ) <EOL> if '<STR_LIT>' in kwargs : <EOL> del ( kwargs [ '<STR_LIT>' ] ) <EOL> self . _meta = None <EOL> self . set_path ( _path , no_metadata = no_metadata ) <EOL> if hash_file : <EOL> self . hash = self . calculate_hash ( ) <EOL> if '<STR_LIT>' not in kwargs : <EOL> kwargs [ '<STR_LIT>' ] = datetime . today ( ) <EOL> super ( Track , self ) . __init__ ( * args , ** kwargs ) <EOL> @ classmethod <EOL> def random ( cls ) : <EOL> return random_row ( cls ) <EOL> def __setattr__ ( self , attr , value ) : <EOL> if attr == '<STR_LIT:title>' : <EOL> slug = slugify ( value ) if value else None <EOL> super ( Track , self ) . __setattr__ ( '<STR_LIT>' , slug ) <EOL> super ( Track , self ) . __setattr__ ( attr , value ) <EOL> def get_path ( self ) : <EOL> if self . path : <EOL> return self . path . encode ( '<STR_LIT:utf-8>' ) <EOL> return None <EOL> def set_path ( self , path , no_metadata = False ) : <EOL> if path != self . get_path ( ) : <EOL> self . path = path <EOL> if no_metadata : <EOL> return None <EOL> if os . path . exists ( self . get_path ( ) ) : <EOL> meta = self . get_metadata_reader ( ) <EOL> self . file_size = meta . filesize <EOL> self . bitrate = meta . bitrate <EOL> self . length = meta . length <EOL> self . ordinal = meta . track_number <EOL> self . title = meta . title <EOL> def calculate_hash ( self ) : <EOL> md5 = hashlib . md5 ( ) <EOL> block_size = <NUM_LIT> * md5 . block_size <EOL> with open ( self . get_path ( ) , '<STR_LIT:rb>' ) as f : <EOL> for chunk in iter ( lambda : f . read ( block_size ) , b'<STR_LIT>' ) : <EOL> md5 . update ( chunk ) <EOL> return md5 . hexdigest ( ) <EOL> def get_metadata_reader ( self ) : <EOL> """<STR_LIT>""" <EOL> if not getattr ( self , '<STR_LIT>' , None ) : <EOL> self . _meta = MetadataManager ( self . get_path ( ) ) <EOL> return self . _meta <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % self . title <EOL> class TrackPlaylistRelationship ( db . Model ) : <EOL> __tablename__ = '<STR_LIT>' <EOL> pk = db . Column ( dbtypes . GUID , default = uuid . uuid4 , primary_key = True ) <EOL> track_pk = db . Column ( dbtypes . GUID , db . ForeignKey ( '<STR_LIT>' ) , <EOL> nullable = False ) <EOL> playlist_pk = db . Column ( dbtypes . GUID , db . ForeignKey ( '<STR_LIT>' ) , <EOL> nullable = False ) <EOL> previous_track_pk = db . Column ( dbtypes . GUID , <EOL> db . ForeignKey ( '<STR_LIT>' ) ) <EOL> track = db . relationship ( '<STR_LIT>' ) <EOL> playlist = db . relationship ( '<STR_LIT>' ) <EOL> previous_track = db . relationship ( '<STR_LIT>' , <EOL> uselist = False ) <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % ( self . pk ) <EOL> class Playlist ( db . Model ) : <EOL> __tablename__ = '<STR_LIT>' <EOL> pk = db . Column ( dbtypes . GUID , default = uuid . uuid4 , primary_key = True ) <EOL> name = db . Column ( db . String ( <NUM_LIT> ) , nullable = False ) <EOL> read_only = db . Column ( db . Boolean , nullable = False , default = True ) <EOL> user_pk = db . Column ( dbtypes . GUID , db . ForeignKey ( '<STR_LIT>' ) , <EOL> nullable = False ) <EOL> creation_date = db . Column ( db . DateTime , nullable = False ) <EOL> user = db . relationship ( '<STR_LIT>' ) <EOL> tracks = db . relationship ( '<STR_LIT>' , backref = '<STR_LIT>' , lazy = '<STR_LIT>' , <EOL> secondary = '<STR_LIT>' , <EOL> primaryjoin = ( pk == TrackPlaylistRelationship . playlist_pk ) ) <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> kwargs [ '<STR_LIT>' ] = datetime . now ( ) <EOL> super ( Playlist , self ) . __init__ ( * args , ** kwargs ) <EOL> def remove_at ( self , index = None ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> index = int ( index ) <EOL> except : <EOL> raise ValueError <EOL> if index < <NUM_LIT:0> : <EOL> raise ValueError <EOL> query = TrackPlaylistRelationship . query . filter_by ( playlist = self ) <EOL> count = query . count ( ) <EOL> if index >= count : <EOL> raise IndexError <EOL> r_track = self . get_track_at ( index ) <EOL> next_track = TrackPlaylistRelationship . query . filter ( <EOL> TrackPlaylistRelationship . playlist == self , <EOL> TrackPlaylistRelationship . previous_track == r_track ) . first ( ) <EOL> if next_track : <EOL> next_track . previous_track = r_track . previous_track <EOL> db . session . add ( next_track ) <EOL> db . session . delete ( r_track ) <EOL> db . session . commit ( ) <EOL> def insert ( self , index , track ) : <EOL> """<STR_LIT>""" <EOL> if index is not None : <EOL> try : <EOL> index = int ( index ) <EOL> except : <EOL> raise ValueError <EOL> if index < <NUM_LIT:0> : <EOL> raise ValueError <EOL> if track is None : <EOL> raise ValueError <EOL> rel = TrackPlaylistRelationship ( playlist = self , track = track ) <EOL> query = TrackPlaylistRelationship . query . filter_by ( playlist = self ) <EOL> count = query . count ( ) <EOL> if index is None : <EOL> index = count <EOL> if count == <NUM_LIT:0> and index > <NUM_LIT:0> : <EOL> raise ValueError <EOL> if count > <NUM_LIT:0> : <EOL> if index > count : <EOL> raise ValueError <EOL> if index == count : <EOL> r_track = self . get_track_at ( index - <NUM_LIT:1> ) <EOL> rel . previous_track = r_track <EOL> else : <EOL> r_track = self . get_track_at ( index ) <EOL> if not r_track : <EOL> raise ValueError <EOL> rel . previous_track = r_track . previous_track <EOL> r_track . previous_track = rel <EOL> db . session . add ( r_track ) <EOL> db . session . add ( rel ) <EOL> db . session . commit ( ) <EOL> def get_track_at ( self , index ) : <EOL> """<STR_LIT>""" <EOL> counter = <NUM_LIT:0> <EOL> track = TrackPlaylistRelationship . query . filter_by ( <EOL> playlist = self , previous_track = None ) . first ( ) <EOL> while True : <EOL> if counter == index : <EOL> return track <EOL> elif counter > index : <EOL> return None <EOL> track = TrackPlaylistRelationship . query . filter ( <EOL> TrackPlaylistRelationship . playlist == self , <EOL> TrackPlaylistRelationship . previous_track == track ) . first ( ) <EOL> counter += <NUM_LIT:1> <EOL> @ property <EOL> def length ( self ) : <EOL> query = TrackPlaylistRelationship . query . filter_by ( playlist = self ) <EOL> return query . count ( ) <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % self . name <EOL> class LyricsCache ( db . Model ) : <EOL> __tablename__ = '<STR_LIT>' <EOL> pk = db . Column ( dbtypes . GUID , default = uuid . uuid4 , primary_key = True ) <EOL> text = db . Column ( db . Text ) <EOL> source = db . Column ( db . String ( <NUM_LIT> ) ) <EOL> track_pk = db . Column ( dbtypes . GUID , db . ForeignKey ( '<STR_LIT>' ) , <EOL> nullable = False ) <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % self . track . title <EOL> class User ( db . Model ) : <EOL> __tablename__ = '<STR_LIT>' <EOL> pk = db . Column ( dbtypes . GUID , default = uuid . uuid4 , primary_key = True ) <EOL> display_name = db . Column ( db . String ( <NUM_LIT> ) ) <EOL> email = db . Column ( db . String ( <NUM_LIT> ) , unique = True , nullable = False ) <EOL> password = db . Column ( db . String ( <NUM_LIT> ) , nullable = True ) <EOL> salt = db . Column ( db . String ( <NUM_LIT> ) , nullable = True ) <EOL> is_public = db . Column ( db . Boolean , nullable = False , default = False ) <EOL> is_active = db . Column ( db . Boolean , nullable = False , default = False ) <EOL> role = db . Column ( db . Enum ( * Roles . as_tuple ( ) , name = "<STR_LIT>" ) , <EOL> nullable = False , default = Roles . USER ) <EOL> creation_date = db . Column ( db . DateTime , nullable = False ) <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> kwargs [ '<STR_LIT>' ] = datetime . now ( ) <EOL> super ( User , self ) . __init__ ( * args , ** kwargs ) <EOL> def __setattr__ ( self , * args , ** kwargs ) : <EOL> if args [ <NUM_LIT:0> ] == '<STR_LIT:password>' : <EOL> password = args [ <NUM_LIT:1> ] <EOL> salt = None <EOL> if password not in ( None , '<STR_LIT>' ) : <EOL> password , salt = self . hash_password ( password ) <EOL> self . salt = salt <EOL> args = ( '<STR_LIT:password>' , password ) <EOL> super ( User , self ) . __setattr__ ( * args , ** kwargs ) <EOL> def hash_password ( self , password , salt = None ) : <EOL> salt = salt or self . salt or bcrypt . gensalt ( ) <EOL> _pass = bcrypt . hashpw ( password . encode ( '<STR_LIT:utf-8>' ) , salt . encode ( '<STR_LIT:utf-8>' ) ) <EOL> return ( _pass , salt ) <EOL> def verify_password ( self , password ) : <EOL> _password , salt = self . hash_password ( password ) <EOL> return _password == self . password <EOL> def generate_auth_token ( self , expiration = None ) : <EOL> if not expiration : <EOL> expiration = app . config . get ( '<STR_LIT>' , <NUM_LIT> ) <EOL> if not isinstance ( expiration , int ) : <EOL> raise ValueError <EOL> s = Serializer ( app . config [ '<STR_LIT>' ] , expires_in = expiration ) <EOL> return s . dumps ( { '<STR_LIT>' : str ( self . pk ) } ) <EOL> @ staticmethod <EOL> def verify_auth_token ( token ) : <EOL> s = Serializer ( app . config [ '<STR_LIT>' ] ) <EOL> try : <EOL> data = s . loads ( token ) <EOL> except ( SignatureExpired , BadSignature ) : <EOL> return None <EOL> user = User . query . get ( data [ '<STR_LIT>' ] ) <EOL> return user <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % self . email </s>
