Skip to content

Instantly share code, notes, and snippets.

@Arti3DPlayer
Created December 11, 2014 20:13
Show Gist options
  • Save Arti3DPlayer/e48dff5244ad39db0fb9 to your computer and use it in GitHub Desktop.
Save Arti3DPlayer/e48dff5244ad39db0fb9 to your computer and use it in GitHub Desktop.
# -*- 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&timestamp=%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