Created
December 11, 2014 20:13
-
-
Save Arti3DPlayer/e48dff5244ad39db0fb9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
import random | |
import vk_api | |
import soundcloud | |
import urllib | |
import urllib2 | |
import time | |
import hashlib | |
import json | |
import decimal | |
from mutagen.mp3 import MP3 | |
from django.shortcuts import render | |
from django.core.urlresolvers import reverse_lazy | |
from django.http import HttpResponse, HttpResponseForbidden | |
from django.conf import settings | |
from django.shortcuts import get_object_or_404 | |
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger | |
from django.views.generic import TemplateView, ListView, DetailView, View | |
from django.template.loader import render_to_string | |
from django_socketio import broadcast, broadcast_channel, NoSocket | |
from apps.profile.models import Payment | |
from apps.profile.utils import MusicBoxMachineRequiredMixin | |
from apps.music_box.models import Genre | |
from apps.profile.models import User, MusicBoxMachine, KeyStorage | |
class Base(View): | |
parent_template = 'music_box/home.html' | |
def dispatch(self, request, *args, **kwargs): | |
if not request.is_ajax() and self.parent_template: | |
return render(request, self.parent_template, {}) | |
return super(Base, self).dispatch(request, *args, **kwargs) | |
def send_lastfm_request(self, method, params): | |
params = dict((k, v.encode('utf-8')) for k, v in params.items()) | |
params.update({ | |
'method': method, | |
'api_key': self.request.user.lastfm_api_key, | |
'format': 'json', | |
}) | |
params = urllib.urlencode(params) | |
try: | |
response = urllib2.urlopen(self.request.user.lastfm_url, params, timeout=10) | |
except urllib2.URLError: | |
response = {} | |
return json.load(response) | |
def get_lastfm_image_url(self, dict, size=3): | |
image_url = '' | |
if dict.get('image'): | |
try: | |
dict_image = dict.get('image')[size] | |
image_url = dict_image.get('#text') | |
except IndexError: | |
image_url = '/static/img/banner.png' | |
return image_url | |
def panginate(self, obj_list=list(), per_page=6): | |
paginator = Paginator(obj_list, per_page) | |
page = self.request.GET.get('page') | |
try: | |
objs = paginator.page(page) | |
except PageNotAnInteger: | |
objs = paginator.page(1) | |
except EmptyPage: | |
objs = paginator.page(paginator.num_pages) | |
return objs | |
def return_error_json_response(self, data): | |
return HttpResponse(json.dumps(data), content_type="application/json") | |
def get_track_url(self, request, track_info): | |
data = dict() | |
if not track_info.get('title'): | |
data['status'] = "error" | |
data['message'] = u'Данные о треке не были переданы, проигрывание не возможно.' | |
return self.return_error_json_response(data) | |
response = self.send_lastfm_request('track.getInfo', { | |
'track': track_info.get('title'), | |
'artist': track_info.get('artist') | |
}) | |
try: | |
track = response['track'] | |
except KeyError: | |
data['status'] = "error" | |
data['message'] = u'Песня не была найдена в нашей базе данных. Попробуйте другую.' | |
return self.return_error_json_response(data) | |
try: | |
album = track['album']['title'] | |
album_image_url = self.get_lastfm_image_url(track['album']) | |
except KeyError: | |
album = u'Неизвестно' | |
album_image_url = '/static/img/banner.png' | |
if request.user.service == 'vkontakte': | |
try: | |
vk = vk_api.VkApi(login=self.request.user.vk_login, | |
password=self.request.user.vk_password, | |
app_id=self.request.user.vk_app_id) | |
except vk_api.AuthorizationError as error_msg: | |
data['status'] = "error" | |
data['message'] = u'Ошибка авторизации: %s' % error_msg | |
return self.return_error_json_response(data) | |
try: | |
params = {'q': track.get('name'), 'performer_only': '0', 'count': '1'} | |
data['track'] = vk.method('audio.search', params)['items'][0] | |
except IndexError: | |
data['status'] = "error" | |
data['message'] = u'Песня не была найдена в нашей базе данных. Попробуйте другую.' | |
return self.return_error_json_response(data) | |
elif request.user.service == 'soundcloud': | |
client = soundcloud.Client(client_id=request.user.soundcloud_client_id) | |
try: | |
data['track'] = client.get('/tracks', q=track.get('name'), filter='public', limit=1)[0].__dict__['obj'] | |
except IndexError: | |
data['status'] = "error" | |
data['message'] = u'Песня не была найдена в нашей базе данных. Попробуйте другую.' | |
return self.return_error_json_response(data) | |
try: | |
stream_url = client.get(data['track']['stream_url'], allow_redirects=False) | |
except AttributeError: | |
data['status'] = "error" | |
data['message'] = u'Трек не доступен. Попробуйте другой.' | |
return self.return_error_json_response(data) | |
data['track']['url'] = stream_url.location | |
data['track']['duration'] /= 1000 # fix time of track | |
else: | |
data['status'] = "error" | |
data['message'] = u'Не выбран сервис для получения музыки.' | |
return self.return_error_json_response(data) | |
#check if received url returns 200 | |
req = urllib2.Request(data['track']['url']) | |
try: | |
resp = urllib2.urlopen(req) | |
except urllib2.URLError, e: | |
data['status'] = "error" | |
data['message'] = u'Песня не была найдена в нашей базе данных. Код ошибки: %s' % e | |
return self.return_error_json_response(data) | |
data['track'].update({ | |
'title': track['name'], | |
'artist': track['artist']['name'], | |
'album_name': album, | |
'album_preview': album_image_url | |
}) | |
return data['track'] | |
class GenresListView(MusicBoxMachineRequiredMixin, Base): | |
template_name = 'music_box/inclusion/genre_list.html' | |
def get(self, request, *args, **kwargs): | |
data = dict() | |
data['genres'] = Genre.objects.filter(is_hidden=False) | |
data['genres'] = self.panginate(obj_list=data['genres'], per_page=9) | |
return render(request, self.template_name, data) | |
class GenreDetailView(MusicBoxMachineRequiredMixin, Base): | |
template_name = 'music_box/inclusion/music_list.html' | |
def get(self, request, *args, **kwargs): | |
genre = Genre.objects.get(pk=kwargs['pk']) | |
response = self.send_lastfm_request('tag.gettoptracks', { | |
'tag': genre.name_en, | |
'limit': '40' | |
}) | |
tracks = response['toptracks']['track'] | |
data = dict() | |
data['tracks'] = [] | |
for track in tracks: | |
image_url = self.get_lastfm_image_url(track) | |
data['tracks'].append({ | |
'title': track['name'], | |
'artist': track['artist']['name'], | |
'album_preview': image_url | |
}) | |
data['tracks'] = self.panginate(obj_list=data['tracks'], per_page=15) | |
return render(request, self.template_name, data) | |
class TopTracksListView(MusicBoxMachineRequiredMixin, Base): | |
template_name = 'music_box/inclusion/music_list.html' | |
def get(self, request, *args, **kwargs): | |
response = self.send_lastfm_request('geo.gettoptracks', { | |
'country': 'russia', | |
'limit': '40' | |
}) | |
tracks = response['toptracks']['track'] | |
data = dict() | |
data['tracks'] = [] | |
for track in tracks: | |
image_url = self.get_lastfm_image_url(track) | |
data['tracks'].append({ | |
'title': track.get('name'), | |
'artist': track['artist']['name'], | |
'duration': track.get('duration'), | |
'album_preview': image_url | |
}) | |
data['tracks'] = self.panginate(obj_list=data['tracks'], per_page=15) | |
return render(request, self.template_name, data) | |
class ArtistListView(MusicBoxMachineRequiredMixin, Base): | |
template_name = 'music_box/inclusion/artist_list.html' | |
def get(self, request, *args, **kwargs): | |
response = self.send_lastfm_request('geo.gettopartists', { | |
'country': 'russia', | |
'limit': '24' | |
}) | |
artists = response['topartists']['artist'] | |
data = dict() | |
data['artists'] = [] | |
for artist in artists: | |
image_url = self.get_lastfm_image_url(artist) | |
data['artists'].append({ | |
'name': artist.get('name'), | |
'preview': image_url | |
}) | |
data['artists'] = self.panginate(obj_list=data['artists'], per_page=9) | |
return render(request, self.template_name, data) | |
class ArtistDetailView(MusicBoxMachineRequiredMixin, Base): | |
template_name = 'music_box/inclusion/music_list.html' | |
def get(self, request, *args, **kwargs): | |
response = self.send_lastfm_request('artist.gettoptracks', { | |
'artist': request.GET.get('name', ''), | |
'limit': '40' | |
}) | |
tracks = response['toptracks']['track'] | |
data = dict() | |
data['tracks'] = [] | |
for track in tracks: | |
image_url = self.get_lastfm_image_url(track) | |
data['tracks'].append({ | |
'title': track['name'], | |
'artist': track['artist']['name'], | |
'duration': track['duration'], | |
'album_preview': image_url | |
}) | |
data['tracks'] = self.panginate(obj_list=data['tracks'], per_page=15) | |
return render(request, self.template_name, data) | |
class AlbumListView(MusicBoxMachineRequiredMixin, Base): | |
template_name = 'music_box/inclusion/album_list.html' | |
def get(self, request, *args, **kwargs): | |
genre = Genre.objects.filter(is_hidden=False).order_by('?').first() | |
if not genre: | |
genre_name = u'Rock' | |
else: | |
genre_name = genre.name_en | |
response = self.send_lastfm_request('tag.gettopalbums', { | |
'tag': genre_name, | |
'limit': '24' | |
}) | |
albums = response['topalbums']['album'] | |
data = dict() | |
data['albums'] = [] | |
for album in albums: | |
image_url = self.get_lastfm_image_url(album) | |
data['albums'].append({ | |
'name': album.get('name'), | |
'artist': album['artist']['name'], | |
'preview': image_url | |
}) | |
data['albums'] = self.panginate(obj_list=data['albums'], per_page=9) | |
return render(request, self.template_name, data) | |
class AlbumDetailView(MusicBoxMachineRequiredMixin, Base): | |
template_name = 'music_box/inclusion/music_list.html' | |
def get(self, request, *args, **kwargs): | |
response = self.send_lastfm_request('album.getinfo', { | |
'album': request.GET.get('album', ''), | |
'artist': request.GET.get('artist', ''), | |
'limit': '40' | |
}) | |
album = response['album'] | |
image_url = self.get_lastfm_image_url(album) | |
tracks = album['tracks']['track'] | |
data = dict() | |
data['tracks'] = [] | |
for track in tracks: | |
data['tracks'].append({ | |
'title': track.get('name'), | |
'artist': track['artist']['name'], | |
'duration': track.get('duration'), | |
'album_preview': image_url | |
}) | |
data['tracks'] = self.panginate(obj_list=data['tracks'], per_page=15) | |
return render(request, self.template_name, data) | |
class SearchTrackView(MusicBoxMachineRequiredMixin, Base): | |
template_name = 'music_box/inclusion/music_list.html' | |
def get(self, request, *args, **kwargs): | |
response = self.send_lastfm_request('track.search', { | |
'track': request.GET.get('name', ''), | |
'limit': '40' | |
}) | |
data = dict() | |
if response['results']['trackmatches'] != '\n': | |
tracks = response['results']['trackmatches']['track'] | |
data['tracks'] = [] | |
for track in tracks: | |
image_url = self.get_lastfm_image_url(track) | |
data['tracks'].append({ | |
'title': track.get('name'), | |
'artist': track['artist'], | |
'duration': track.get('duration'), | |
'album_preview': image_url | |
}) | |
data['tracks'] = self.panginate(obj_list=data['tracks'], per_page=15) | |
return render(request, self.template_name, data) | |
class RandomTrackView(MusicBoxMachineRequiredMixin, Base): | |
parent_template = '' | |
def get(self, request, *args, **kwargs): | |
data = dict() | |
response = self.send_lastfm_request('geo.gettoptracks', { | |
'country': 'russia', | |
'limit': '21' | |
}) | |
tracks = response['toptracks']['track'] | |
random_track = random.choice(tracks) | |
data['track'] = self.get_track_url(request, { | |
'title': random_track['name'], | |
'artist': random_track['artist']['name'] | |
}) | |
data['track'].update({ | |
'random_track': True | |
}) | |
return HttpResponse(json.dumps(data), content_type="application/json") | |
class BuyTrackView(MusicBoxMachineRequiredMixin, Base): | |
parent_template = '' | |
def post(self, request, *args, **kwargs): | |
data = dict() | |
if request.user.cash < request.user.price: | |
data['status'] = "error" | |
data['message'] = u'Недостаточно денег для покупки трека. Пожалуйста пополните баланс.' | |
return self.return_error_json_response(data) | |
track_info = json.loads(request.POST.get('track')) | |
data['track'] = self.get_track_url(request, track_info) | |
request.user.cash -= request.user.price | |
request.user.save() | |
description = u'Название: %s\n Исполнитель: %s \n Длительность: %s' \ | |
% (data['track']['title'], | |
data['track']['artist'], | |
data['track']['duration']) | |
payment = Payment(machine=request.user, | |
description=description, | |
payment_type='buy_track', | |
price=request.user.price) | |
payment.save() | |
data['status'] = "success" | |
data['message'] = request.user.success_text | |
data['cash'] = float(request.user.cash) | |
return HttpResponse(json.dumps(data), content_type="application/json") | |
class GetMusicBoxMachineSettingsView(MusicBoxMachineRequiredMixin, View): | |
def get(self, request, *args, **kwargs): | |
advert_sound_file = dict() | |
if request.user.advert_sound_file: | |
audio = MP3(request.user.advert_sound_file.path) | |
advert_sound_file = { | |
'title': u'Автомат', | |
'artist': u'Заходи', | |
'url': request.user.advert_sound_file.url, | |
'duration': audio.info.length, | |
'album_name': u'Покупай', | |
'random_track': True | |
} | |
machine = { | |
'cash': float(request.user.cash), | |
'price': float(request.user.price), | |
'delay_before_playing_random_music': request.user.delay_before_playing_random_music*1000, | |
'delay_before_starting_advertising': request.user.delay_before_starting_advertising*1000, | |
'delay_before_playing_music': request.user.delay_before_playing_music*1000, | |
'advert_sound_file': advert_sound_file, | |
'delay_before_advert_sound_file': request.user.delay_before_advert_sound_file, | |
'advert_slider_pk': request.user.advert_slider.pk if request.user.advert_slider else None, | |
'success_text': request.user.success_text, | |
} | |
return HttpResponse(json.dumps(machine), content_type="application/json") | |
class MusicBoxMachineAdvertismentSliderView(MusicBoxMachineRequiredMixin, TemplateView): | |
template_name = 'music_box/inclusion/advertisment_slider.html' | |
class SendMoneyView(View): | |
def get(self, request, *args, **kwargs): | |
key = request.GET.get('key') | |
amount = request.GET.get('amount') | |
timestamp = int(request.GET.get('timestamp')) | |
remote_signature = request.GET.get('signature') | |
time_now = int(time.time()) | |
machine = get_object_or_404(MusicBoxMachine, key_machine=key) | |
s = "%samount=%s×tamp=%i" % (machine.secret_key_machine, amount, timestamp) | |
signature = hashlib.sha256(s).hexdigest() | |
#TODO сделать проверку на время | |
#if time_now < timestamp+30: | |
if signature == remote_signature: | |
amount = decimal.Decimal(amount) | |
payment = Payment(machine=machine, | |
description=u'Пополнение счета', | |
payment_type='refill', | |
price=0) | |
if amount > machine.price and machine.hopper_enabled: | |
machine.cash += machine.price | |
machine.credit_cash += amount-machine.price | |
payment.price = machine.price | |
else: | |
machine.cash += amount | |
payment.price = amount | |
machine.save() | |
payment.save() | |
try: | |
data = { | |
'action': 'update_cash', | |
'cash': float(machine.cash), | |
'credit_cash': float(machine.credit_cash), | |
'message': render_to_string('music_box/inclusion/update_cash_message.html', | |
{'machine': machine}) | |
} | |
broadcast_channel(data, "machine-%s" % machine.id) | |
except NoSocket, e: | |
machine.cash += machine.credit_cash | |
payment.price += machine.credit_cash | |
payment.save() | |
machine.credit_cash = 0 | |
machine.save() | |
return HttpResponse(u"Cash update.") | |
else: | |
return HttpResponse(u"Key failed.") | |
#else: | |
# return HttpResponse(u"Request is too old.") | |
class ConvertCreditToBalanceView(View): | |
def get(self, request, *args, **kwargs): | |
request.user.cash += request.user.credit_cash | |
payment = Payment(machine=request.user, | |
description=u'Пополнение счета', | |
payment_type='refill', | |
price=request.user.credit_cash) | |
payment.save() | |
request.user.credit_cash = 0 | |
request.user.save() | |
data = { | |
'cash': float(request.user.cash), | |
} | |
return HttpResponse(json.dumps(data), content_type="application/json") | |
class GiveChangeConfirmView(View): | |
def get(self, request, *args, **kwargs): | |
data = dict() | |
if not request.user.hopper_enabled: | |
data['message'] = u'В автомате отключена возможность выдачи сдачи. Обратитесь к администратору.' | |
return HttpResponse(json.dumps(data), content_type="application/json") | |
if request.user.credit_cash == 0: | |
data['message'] = u'Сдача отсутствует. Нечего выдать.' | |
return HttpResponse(json.dumps(data), content_type="application/json") | |
if request.user.give_change_confirm: | |
data['message'] = u'Сдача в процессе выдачи. Подождите пожалуйста.' | |
return HttpResponse(json.dumps(data), content_type="application/json") | |
residue = 0 | |
if request.user.credit_cash % request.user.hopper_nominal != 0: | |
residue = request.user.credit_cash % 5 | |
request.user.cash += residue | |
request.user.credit_cash -= residue | |
if request.user.hopper_cash < request.user.credit_cash: | |
old_cash = request.user.credit_cash | |
residue = request.user.credit_cash - request.user.hopper_cash | |
request.user.cash += residue | |
request.user.credit_cash -= residue | |
data['message'] = u'В автомате не достаточно средств для выдачи %s руб. сдачи.<br>' \ | |
u'Выдано: %s руб., остаток переведён на баланс.' % (old_cash, request.user.credit_cash) | |
else: | |
if residue == 0: | |
data['message'] = u'Выдано: %s рублей.' % request.user.credit_cash | |
else: | |
data['message'] = u'Выдано: %s рублей, остаток: %s перенесен в кредит.' % (request.user.credit_cash, residue) | |
data['cash'] = float(request.user.cash) | |
request.user.give_change_confirm = True | |
request.user.save() | |
return HttpResponse(json.dumps(data), content_type="application/json") | |
class GiveChangeView(View): | |
def get(self, request, *args, **kwargs): | |
data = dict() | |
key = request.GET.get('key') | |
remote_signature = request.GET.get('signature') | |
machine = get_object_or_404(MusicBoxMachine, key_machine=key) | |
line = '%s%s' % (key, machine.secret_key_machine) | |
signature = hashlib.sha256(line).hexdigest() | |
if signature != remote_signature: | |
return HttpResponseForbidden() | |
if machine.give_change_confirm: | |
payment = Payment(machine=machine, | |
description=u'Выдача сдачи', | |
payment_type='give_change', | |
price=machine.credit_cash) | |
payment.save() | |
machine.hopper_cash -= machine.credit_cash | |
signals = machine.credit_cash / machine.hopper_nominal | |
machine.give_change_confirm = False | |
machine.credit_cash = 0 | |
machine.save() | |
return HttpResponse(signals) | |
else: | |
return HttpResponseForbidden() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment