Skip to content

Commit c9d4592

Browse files
author
mithmith
committed
add_channel_history + add_video_history
1 parent 5eadabe commit c9d4592

File tree

4 files changed

+71
-16
lines changed

4 files changed

+71
-16
lines changed

TODO.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# TODO List для проекта Youtube Parser Downloader
22

3-
## Основные функции
3+
## Основные функции (backend)
44

55
- [x] **Парсинг информации**:
66
- [x] Сбор информации о каналах и видео с помощью `yt-dlp`.
77
- [x] Сбор информации с использованием YouTube API.
88

99
- [ ] **Мониторинг и статистика**:
10-
- [ ] Получение новых видео и мониторинг каналов.
10+
- [x] Получение новых видео и мониторинг каналов.
1111
- [ ] Добавление и обновление статистической информации по каналам и видео.
1212
- [ ] Выборка статистической информацией по каналам и видео, включая просмотры, лайки, количество подписчиков, количество видео, новые видео и другие метрики.
1313

@@ -21,7 +21,7 @@
2121
- [ ] **Локализация контента**:
2222
- [ ] Перевод описаний, названий, аудио дорожек и субтитров.
2323
- [ ] Перевод аудио дорожки с помощью внешнего сервиса.
24-
- [ ] Определение языка аудио дорожки.
24+
- [ ] Определение языка аудио дорожки (присылает youtube API).
2525

2626
- [ ] **Создание субтитров и краткого пересказа**:
2727
- [ ] Автоматическое создание субтитров в случае их отсутствия с помощью внешнего сервиса.
@@ -34,4 +34,9 @@
3434

3535
- [ ] **Интеграция с сервером Peertube**:
3636
- [ ] Зеркальное размещение видео на децентрализованном хостинге.
37-
37+
38+
## Frontend:
39+
- [ ] **Сделать фронт-дашбоард для визуализации данных**
40+
41+
## Docker-контейнер:
42+
- [ ] **Собрать контейнер с postgres, peertube и всем необходимым для работы**

app/__main__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import json
2-
31
from loguru import logger
42

53
from app.const import channels_list

app/db/repository.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from sqlalchemy.exc import IntegrityError, NoResultFound, SQLAlchemyError
88

99
from app.db.base import BaseRepository
10-
from app.db.data_table import Channel, Tag, Thumbnail, Video, VideoTag, YTFormat
10+
from app.db.data_table import Channel, ChannelHistory, Tag, Thumbnail, Video, VideoHistory, VideoTag, YTFormat
1111
from app.schema import ChannelAPIInfoSchema, ChannelInfoSchema, ThumbnailSchema, VideoSchema, YTFormatSchema
1212

1313

@@ -39,7 +39,7 @@ def add_video(
3939
video = Video(video_id=video_schema.id, channel_id=channel_id)
4040
self._session.add(video)
4141

42-
upload_date = datetime.utcfromtimestamp(video_schema.timestamp) if video_schema.timestamp else None
42+
upload_date = datetime.fromtimestamp(video_schema.timestamp) if video_schema.timestamp else None
4343
video.title = video_schema.title
4444
video.description = video_schema.description
4545
video.url = video_schema.url
@@ -346,3 +346,21 @@ def update_thumbnail_path(self, video_id: UUID, thumbnail_url: str, thumbnail_pa
346346
self._session.commit()
347347
else:
348348
logger.warning(f"Thumbnail not found for video ID {video_id} with URL {thumbnail_url}.")
349+
350+
def add_channel_history(self, channel_info: Channel):
351+
history: ChannelHistory = ChannelHistory(
352+
channel_id=channel_info.id,
353+
follower_count=channel_info.channel_follower_count,
354+
view_count=channel_info.viewCount,
355+
video_count=channel_info.videoCount,
356+
)
357+
self.add(history)
358+
359+
def add_video_history(self, video_info: Video):
360+
history: VideoHistory = VideoHistory(
361+
video_id=video_info.id,
362+
view_count=video_info.view_count,
363+
like_count=video_info.like_count,
364+
comment_count=video_info.comment_count,
365+
)
366+
self.add(history)

app/service/yt_monitor.py

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,48 @@
1+
from time import sleep
2+
13
from loguru import logger
24

35
from app.db.data_table import Channel, Thumbnail, Video
6+
from app.db.repository import YoutubeDataRepository
47
from app.integrations.ytapi import YTApiClient
58
from app.integrations.ytdlp import YTChannelDownloader
6-
from app.schema import ChannelAPIInfoSchema, ChannelInfoSchema
9+
from app.schema import ChannelAPIInfoSchema, ChannelInfoSchema, VideoSchema
710

811

912
class YTMonitorService:
10-
def __init__(self, channels_list: list[str]) -> None:
13+
def __init__(self, channels_list: list[str], timeout: int = 300) -> None:
1114
self._channels_list = channels_list
1215
self._api_client: YTApiClient
1316
self._yt_dlp_client: YTChannelDownloader
17+
self._repository = YoutubeDataRepository()
18+
self._timeout = timeout
19+
20+
def run(self):
21+
while True:
22+
self.monitor_channels_for_newold_videos()
23+
sleep(self._timeout)
1424

15-
def monitor_channels_for_new_videos(self) -> list[Video]:
16-
channels_new_videos: list[Video] = []
25+
def monitor_channels_for_newold_videos(self) -> None:
1726
for channel_url in self._channels_list:
1827
logger.info(f"Getting video from: {channel_url}")
1928
self._yt_dlp_client = YTChannelDownloader(channel_url)
29+
self._api_client = YTApiClient()
30+
2031
# Получаем список видео и id канала
21-
# ytdlp_channel_info: ChannelInfoSchema = self._yt_dlp_client.get_channel_info()
32+
ytdlp_channel_info: ChannelInfoSchema = self._yt_dlp_client.get_channel_info()
33+
ytapi_channels_info: ChannelAPIInfoSchema = self._api_client.get_channel_info(
34+
[ytdlp_channel_info.channel_id]
35+
)
36+
channel_info: Channel = self._combine_channel_info(ytdlp_channel_info, ytapi_channels_info[0])
2237
video_list, channel_id = self._yt_dlp_client.get_video_list()
2338
new_videos, old_videos = self._yt_dlp_client.filter_new_old(video_list, channel_id)
24-
if new_videos:
25-
channels_new_videos.extend(new_videos)
2639

27-
return channels_new_videos
40+
if channel_info:
41+
self._process_channel_info(channel_info)
42+
if new_videos:
43+
self._process_new_videos(new_videos, channel_id)
44+
if old_videos:
45+
self._process_old_videos(old_videos, channel_id)
2846

2947
def _combine_channel_info(
3048
self, ytdlp_channel_info: ChannelInfoSchema, ytapi_channel_info: ChannelAPIInfoSchema
@@ -44,3 +62,19 @@ def _combine_channel_info(
4462
thumbnails=[Thumbnail(**thumb.model_dump()) for thumb in ytdlp_channel_info.thumbnails],
4563
)
4664
return combined_channel
65+
66+
def _process_channel_info(self, channel_info):
67+
existing_channel = self._repository.get_channel_by_id(channel_info.channel_id)
68+
if not existing_channel:
69+
self._repository.add_channel(channel_info)
70+
self._repository.add_channel_history(channel_info)
71+
72+
def _process_new_videos(self, new_videos, channel_id):
73+
for video in new_videos:
74+
self._repository.add_video(video)
75+
self._repository.add_video_history(video, channel_id)
76+
77+
def _process_old_videos(self, old_videos, channel_id):
78+
for video in old_videos:
79+
self._repository.add_video_history(video, channel_id)
80+

0 commit comments

Comments
 (0)