большой рефакторинг readme и добавление модели Подкасты

This commit is contained in:
Mike0001-droid 2024-06-26 16:33:08 +05:00
parent 43cae25e18
commit 8b07bf6972
28 changed files with 249 additions and 40 deletions

View File

@ -2,10 +2,53 @@
IT-Радио — радиостанция про сферу технологийи развитие в IT
***
![Static Badge](https://img.shields.io/badge/Flexites-white?link=https%3A%2F%2Fflexites.org%2F)
![Static Badge](https://img.shields.io/badge/AzuraCast-blue?link=https%3A%2F%2Fwww.azuracast.com%2F)
![Static Badge](https://img.shields.io/badge/Python-ffd429?logo=Python&logoSize=3&link=https%3A%2F%2Fwww.python.org%2F)
![Static Badge](https://img.shields.io/badge/Quasar-87cefa?logo=Quasar&logoSize=3&link=https%3A%2F%2Fquasar.dev%2F)
[![Flexites](https://img.shields.io/badge/Flexites-white)](https://flexites.org/)
[![AzuraCast](https://img.shields.io/badge/AzuraCast-blue)](https://www.azuracast.com/)
[![Python](https://img.shields.io/badge/Python-ffd429?logo=Python&logoSize=3)](https://www.python.org/)
[![Quasar](https://img.shields.io/badge/Quasar-87cefa?logo=Quasar&logoSize=3)](https://quasar.dev/)
[![DRF](https://img.shields.io/badge/Django_REST_Framework-red)](https://www.django-rest-framework.org/)
[![Nginx](https://img.shields.io/badge/Nginx-green?logo=Nginx)](https://nginx.org/ru/)
[![Gunicorn](https://img.shields.io/badge/Gunicorn-white?logo=Gunicorn)](https://gunicorn.org/)
[![IT-Radio-Logo](docs/logo-it-radio.jpg)](https://itradio.team)
## Установка
У вас должны быть установлены [зависимости проекта](https://git.flexites.org/Students/ITRadio/src/branch/master/server/requirements.txt)
1. Клонирование репозитория
```git clone https://git.flexites.org/Students/ITRadio.git```
2. Переход в директорию ITRadio
```cd ITRadio```
3. Создание виртуального окружения
```python -m venv venv```
4. Активация виртуального окружения
```cd venv/```
```scripts/activate```
5. Установка зависимостей
```cd server/```
```pip install -r requirements.txt```
<!--Пользовательская документация-->
## Документация
Пользовательскую документацию можно получить по [этой ссылке](./docs/ru/index.md).
<!--Поддержка-->
<!-- ## Поддержка
Если у вас возникли сложности или вопросы по использованию сайта напишите на электронную почту <bro.alexeev@inbox.com> -->
<!--Пользовательская документация-->
## Инструкция для работы в панели администратора
Инструкцию можно получить по [этой ссылке](./docs/ru/instruk.md).
<!--Документация для разработчиков-->
## Документация для разработчиков
Проект развёрнут с помощью Gunicorn и Nginx. API документация находится по [адресу](https://itradio.team/api/). Там же и описаны все контроллеры (views), используемые в проекте
[![](docs/logo-it-radio.jpg)](https://itradio.team)

49
docs/ru/admin_django.md Normal file
View File

@ -0,0 +1,49 @@
# IT-Радио Docs RU
Инструкция по навигации в панели администратора проекта IT-Радио
### [Оглавление](./instruk.md)
С добавлением треков разобрались, плавно перейдем к панели администратора _Django_
___
На данный момент в панели администратора доступны следующие приложения и таблицы: ![alt text](image-4.png)
Пойдем по порядку:
1. То, что написано на синим фоне, допустим, "AUDIO" - является приложением внутри нашего сайта, грубо говоря раздел, в котором доступны некоторые _таблицы_
1. На примере приложения "AUDIO", разберем сущность _таблицы_
* Избранные треки
* Плейлисты
* Подкасты
* Треки
1. Но прежде чем, мы перейдем к таблицам, разберемся в кнопках
* Ссылка на таблицу ![alt text](image-11.png) позволяет перейти в таблицу и посмотреть существующие записи
* Кнопка ![alt text](image-10.png) - позволяет добавить запись в таблицу
* Кнопки ![alt text](image-12.png) - содержатся внутри записи и позволяют создать новую запись, сохранить и создать еще одну запись, сохранить и продолжить редактирование __соответственно__
* Ах да, не стоит обделять вниманием кнопку ![alt text](image-13.png), которая отображается при редактировании существующего объекта. Думаю, что ее назначение объяснять не нужно
1. Описанные в первом пункте таблицы хранят уникальные записи, например, в таблице **Избранные треки** мы храним всего лишь два идентификатора:
название поля | тип поля | обязательное ?
:-------------|:--------:|---------------:
id Пользователя | целое число | Да
id Трека | целое число | Да
![alt text](image-6.png)
1. Перейдем к плейлистам. Здесь ситуация немного поинтереснее, так как для грамотного создания нам нужно указать:
название поля | тип поля | обязательное ?
:-------------|:--------:|---------------:
Название плейлиста | строка | Нет
Добавленные треки | целое число | Нет
Пользователь | целое число | Нет
Изображение плейлиста | строка | Нет
![alt text](image-7.png)
На картинке выше видно, что мы можем просмотреть какие треки мы хотим добавить, эти треки уже существуют в базе данных
1. С подкастам ситуация полегче:
название поля | тип поля | обязательное ?
:-------------|:--------:|---------------:
Название подкаста | строка | Да
Файл подкаста | строка | Да
Изображение подкаста | строка | Нет
![alt text](image-8.png)
На данный момент, файлом подкаста может являться только _аудио_

23
docs/ru/admin_song.md Normal file
View File

@ -0,0 +1,23 @@
# IT-Радио Docs RU
Инструкция по навигации в панели администратора проекта IT-Радио
### [Оглавление](./instruk.md)
Для того, чтобы добавить очередной трек в базу данных, необходимо перейти в панель [AzuraCast](https://azuracast.itradio.team/station/1/files). Здесь мы наблюдаем следущую картину: ![alt text](image.png)
1. Сверху объявлена область, в которую мы можем перенести загруженные треки и они появятся в трансляции
1. Не стоит забывать о том, что трек появляется в трансляции, только в том случае, когда __находится в плейлисте _default___
1. Для того, чтобы добавить трек в плейлист, необходимо нажать кнопку "Редактировать", в котором будет доступно некоторое количество параметров для трека, такие как:
* __название файла__
* __название песни__
* __исполнитель__
и так далее
![alt text](image-1.png)
1. Но в нашем случае, нам необходимо перейти во вкладку "Плейлисты" и выбрать необходимый плейлист ![alt text](image-2.png)
1. Наслаждаемся добавленным в трансляцию треком :) ![alt text](image-3.png)

16
docs/ru/azuracast.md Normal file
View File

@ -0,0 +1,16 @@
# IT-Радио Docs RU
Пользовательская документация IT-Радио на русском
### [Оглавление](./index.md)
## Что такое AzuraCast?
AzuraCast - это открытое программное обеспечение, предназначенное для упрощения управления интернет-радиостанциями. Оно представляет собой портативную веб-радиостанцию, которая включает в себя веб-радио-сервер, планировщик музыки и инструменты для управления медиафайлами.
___Почему выбрали данное решение?___
За счёт открытого исходного кода, примера интеграции с __Django__, относительно быстрой скорости подключения к проекту
___Технические характеристики___
AzuraCast работает на базе __Docker__ и __Ansible__, что обеспечивает его портативность и гибкость. Оно поддерживает различные форматы аудиофайлов и позволяет управлять плейлистами, включая автоматическое создание плейлистов на основе тегов.
___Интеграция и управление___
AzuraCast предоставляет API для интеграции с другими сервисами и поддерживает веб-интерфейс для управления радиостанцией. Он включает в себя функции, такие как управление DJ, управление рекламой, управление слушателями и статистика.

View File

@ -0,0 +1,9 @@
# IT-Радио Docs RU
Пользовательская документация IT-Радио на русском
### [Оглавление](./index.md)
## Введение
IT-радио — это уникальный проект, который объединяет в себе самых ярких представителей IT-индустрии, а также экспертов из различных областей, чтобы поделиться своими знаниями и опытом с широкой аудиторией.
Каждое шоу на IT-радио включает в себя актуальные темы, новости, обзоры, интервью с экспертами и многое другое

BIN
docs/ru/image-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
docs/ru/image-10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 B

BIN
docs/ru/image-11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
docs/ru/image-12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
docs/ru/image-13.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
docs/ru/image-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
docs/ru/image-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
docs/ru/image-4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
docs/ru/image-5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/ru/image-6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/ru/image-7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
docs/ru/image-8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
docs/ru/image-9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
docs/ru/image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

7
docs/ru/index.md Normal file
View File

@ -0,0 +1,7 @@
# IT-Радио Docs RU
Пользовательская документация IT-Радио на русском
## Оглавление
1. [Введение](./getting-started.md)
1. [Возможности IT-Радио](./itradio_func.md)
1. [Что такое AzuraCast?](./azuracast.md)

6
docs/ru/instruk.md Normal file
View File

@ -0,0 +1,6 @@
# IT-Радио Docs RU
Инструкция по навигации в панели администратора проекта IT-Радио
## Оглавление
1. [Добавление треков](./admin_song.md)
1. [Панель администратора Django](./azuracast.md)

13
docs/ru/itradio_func.md Normal file
View File

@ -0,0 +1,13 @@
# IT-Радио Docs RU
Пользовательская документация IT-Радио на русском
### [Оглавление](./index.md)
### Возможности IT-Радио
Проект IT-Радио предлагает следующий функционал
* Прослушивание _онлайн трансляции_
* Добавление треков в _избранное_
* Создание _плейлистов_ на свой вкус
* Прослушивание интересных _подкастов_
* Просмотр новостей об __IT__

View File

@ -1,9 +1,10 @@
from django.contrib import admin
from .models import Song, FavoriteSong, PlayList
from .models import Song, FavoriteSong, PlayList, Podkast
@admin.register(Song)
class SongAdmin(admin.ModelAdmin):
list_display = ('slug', 'title', 'artist', 'genre', 'album')
exclude = ('azura_id',)
readonly_fields = ['slug']
@admin.register(FavoriteSong)
@ -13,3 +14,7 @@ class FavoriteSongAdmin(admin.ModelAdmin):
@admin.register(PlayList)
class PlayListAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'user', 'playlist_art')
@admin.register(Podkast)
class PodkastAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'podkast_file', 'podkast_art')

View File

@ -4,14 +4,13 @@ from django.template.defaultfilters import slugify
class Song(models.Model):
unique_id = models.CharField('ID трека для плеера', max_length=255, blank=True, null=True)
slug = models.SlugField('Слаг трека', blank=True, null=True)
azura_id = models.CharField('ID трека с Азуры', max_length=255)
title = models.CharField('Название трека', max_length=255)
artist = models.CharField('Исполнитель', max_length=255)
album = models.CharField('Альбом трека', blank=True, null=True, max_length=255)
genre = models.CharField('Жанр трека', blank=True, null=True, max_length=50)
art = models.CharField('Изображение трека', blank=True, null=True, max_length=255)
slug = models.SlugField('Слаг трека', blank=True, null=True)
def save(self, *args, **kwargs):
if not self.id:
@ -44,7 +43,20 @@ class PlayList(models.Model):
song = models.ManyToManyField(Song, blank=True, null=True)
user = models.ForeignKey(MyUser, verbose_name='Пользователь', on_delete=models.CASCADE)
playlist_art = models.FileField('Изображение плейлиста', blank=True, null=True, upload_to="playlist_images/")
def __str__(self):
return f"{self.name}"
class Meta:
verbose_name = 'Плейлисты'
verbose_name_plural = 'Плейлисты'
verbose_name_plural = 'Плейлисты'
class Podkast(models.Model):
name = models.CharField('Название подкаста', max_length=100)
podkast_file = models.FileField('Файл подкаста', upload_to="podkasts/")
podkast_art = models.FileField('Изображение подкаста', blank=True, null=True, upload_to="podkast_images/")
def __str__(self):
return f"{self.name}"
class Meta:
verbose_name = 'Подкасты'
verbose_name_plural = 'Подкасты'

View File

@ -1,5 +1,5 @@
from rest_framework import serializers
from .models import Song, FavoriteSong, PlayList
from .models import Song, FavoriteSong, PlayList, Podkast
class SongSerializer(serializers.ModelSerializer):
class Meta:
@ -17,14 +17,11 @@ class PlayListSerializer(serializers.ModelSerializer):
instance.song.all(), many=True).data
return rep
class FavoriteSongSerializer(serializers.ModelSerializer):
class Meta:
model = FavoriteSong
fields = ('id', 'song', 'user')
def to_representation(self, instance):
rep = super().to_representation(instance)
@ -32,3 +29,8 @@ class FavoriteSongSerializer(serializers.ModelSerializer):
instance.song).data
return rep
class PodkastSerializer(serializers.ModelSerializer):
class Meta:
model = Podkast
fields = '__all__'

View File

@ -10,10 +10,39 @@ import requests
from django.http import HttpResponse
from .schemas import SongSchema, DeleteSongSchema, PlayListSchema
from .models import Song, FavoriteSong, PlayList
from .serializers import SongSerializer, FavoriteSongSerializer, PlayListSerializer
from .models import Song, FavoriteSong, PlayList, Podkast
from .serializers import SongSerializer, FavoriteSongSerializer, PlayListSerializer, PodkastSerializer
from conf.settings.base import AZURACAST_URL, AZURACAST_API_KEY
def authorize_url(url):
file_url = url
API_KEY = AZURACAST_API_KEY
headers = {
"Authorization": f"Bearer {API_KEY}"
}
return requests.get(file_url, headers=headers)
class PodkastViewSet(GenericViewSet):
queryset = Podkast
serializer_class = PodkastSerializer
permission_classes = (IsAuthenticated, )
def list(self, request):
queryset = self.get_queryset().objects.all()
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
def retrieve(self, request, pk):
try:
queryset = self.get_queryset().objects.get(pk=pk)
serializer = self.get_serializer(queryset)
return Response(serializer.data, status=status.HTTP_200_OK)
except ObjectDoesNotExist:
return Response(
{'detail': 'Объекта не существует', 'error': {'PlayList': 'Объекта не существует'}},
status=status.HTTP_404_NOT_FOUND)
class PlayListViewSet(GenericViewSet):
queryset = PlayList
serializer_class = PlayListSerializer
@ -104,11 +133,7 @@ class PlayListViewSet(GenericViewSet):
song = Song.objects.get(azura_id=request.data.get('azura_id')).pk
except ObjectDoesNotExist:
file_url = f"{AZURACAST_URL}api/station/it-radio/file/{request.data['azura_id']}"
API_KEY = AZURACAST_API_KEY
headers = {
"Authorization": f"Bearer {API_KEY}"
}
response = requests.get(file_url, headers=headers)
response = authorize_url(file_url)
data = request.data
file_play = f"{AZURACAST_URL}api/station/it-radio/file/{response.json()['unique_id']}/play"
data.update(unique_id=file_play)
@ -169,11 +194,7 @@ class SongViewSet(GenericViewSet):
try:
song_obj = self.get_queryset().objects.get(azura_id=azura_id)
file_url = song_obj.unique_id
API_KEY = AZURACAST_API_KEY
headers = {
"Authorization": f"Bearer {API_KEY}"
}
response = requests.get(file_url, headers=headers)
response = authorize_url(file_url)
response.raise_for_status()
file_response = HttpResponse(response.content, content_type='audio/mpeg')
@ -197,11 +218,7 @@ class SongViewSet(GenericViewSet):
}
except ObjectDoesNotExist:
file_url = f"{AZURACAST_URL}api/station/it-radio/file/{request.data['azura_id']}"
API_KEY = AZURACAST_API_KEY
headers = {
"Authorization": f"Bearer {API_KEY}"
}
response = requests.get(file_url, headers=headers)
response = authorize_url(file_url)
data = request.data
file_play = f"{AZURACAST_URL}/api/station/it-radio/file/{response.json()['unique_id']}/play"
data.update(unique_id=file_play)
@ -232,11 +249,7 @@ class SongViewSet(GenericViewSet):
@action(detail=False, methods=['get'])
def get_all_song(self, request):
file_url = F"{AZURACAST_URL}api/station/1/files"
API_KEY = AZURACAST_API_KEY
headers = {
"Authorization": f"Bearer {API_KEY}"
}
response = requests.get(file_url, headers=headers)
response = authorize_url(file_url)
data = []
for i in response.json():
i['azura_id'] = i.pop('song_id')
@ -246,11 +259,7 @@ class SongViewSet(GenericViewSet):
@action(detail=False, methods=['get'], permission_classes=(AllowAny,))
def get_nowplaying(self, request):
file_url = F"{AZURACAST_URL}api/nowplaying/it-radio"
API_KEY = AZURACAST_API_KEY
headers = {
"Authorization": f"Bearer {API_KEY}"
}
response = requests.get(file_url, headers=headers)
response = authorize_url(file_url)
return Response(response.json(), status=status.HTTP_200_OK)

View File

@ -164,3 +164,18 @@ MIN_LEN_PASSWORD = 8
AZURACAST_URL = 'https://azuracast.itradio.team/'
AZURACAST_API_KEY = config('AZURACAST_API_KEY')
""" ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1
ACCOUNT_USERNAME_MIN_LENGTH = 4
LOGIN_REDIRECT_URL = "/"
SITE_ID = 3
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.timeweb.ru'
EMAIL_PORT = 25
EMAIL_HOST_USER = 'mail@flexidev.ru'
EMAIL_HOST_PASSWORD = 'gea(X7i(?=e@L/'
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
EMAIL_USE_SSL = True
EMAIL_USE_TLS = False
EMAIL_USE_SSL = False """