@@ -1,10 +1,13 @@ | |||
from __future__ import annotations | |||
# pylint: disable = missing-class-docstring | |||
# pylint: disable = missing-function-docstring | |||
# pylint: disable = missing-module-docstring | |||
# pylint: disable = unused-argument | |||
from typing import Any, Generic, Type, TypeVar, overload | |||
from __future__ import annotations | |||
from eloquent.orm.relations.dynamic_property import DynamicProperty | |||
from typing import Any, Generic, Self, Type, TypeVar, overload | |||
_TModel = TypeVar ('_TModel', bound = 'Model') | |||
_ModelT = TypeVar ('_ModelT', bound = 'Model') | |||
class Connection: | |||
@@ -48,66 +51,78 @@ class DatabaseManager: | |||
class Model: | |||
id: int | |||
def has_one ( | |||
self, | |||
related_model: Type[Model], | |||
foreign_key: str | None = None, | |||
) -> DynamicProperty: ... | |||
related_model: Type[_ModelT], | |||
foreign_key: str | None = None, | |||
) -> _ModelT: ... | |||
def has_many ( | |||
self, | |||
related_model: Type[Model], | |||
foreign_key: str | None = None, | |||
) -> DynamicProperty: ... | |||
related_model: Type[_ModelT], | |||
foreign_key: str | None = None, | |||
) -> _ModelT: ... | |||
def belongs_to ( | |||
self, | |||
related_model: Type[Model], | |||
foreign_key: str | None = None, | |||
) -> DynamicProperty: ... | |||
related_model: Type[_ModelT], | |||
foreign_key: str | None = None, | |||
) -> _ModelT: ... | |||
def belongs_to_many ( | |||
self, | |||
related_model: Type[Model], | |||
foreign_key: str | None = None, | |||
) -> DynamicProperty: ... | |||
related_model: Type[_ModelT], | |||
foreign_key: str | None = None, | |||
) -> _ModelT: ... | |||
def save (self) -> None: ... | |||
def delete (self) -> None: ... | |||
@classmethod | |||
def find (cls, id: int) -> Model | None: ... | |||
def find (cls, id_: int) -> Self | None: ... | |||
@overload | |||
@classmethod | |||
def where (cls, field: str, operator: str, value: Any) -> QueryBuilder: ... | |||
def where ( | |||
cls, | |||
field: str, | |||
operator: str, | |||
value: Any, | |||
) -> QueryBuilder[Self]: ... | |||
@overload | |||
@classmethod | |||
def where (cls, field: str, value: Any) -> QueryBuilder: ... | |||
def where (cls, field: str, value: Any) -> QueryBuilder[Self]: ... | |||
@classmethod | |||
def where_not_in (cls, column: str, values: list[Any] | tuple) -> QueryBuilder: ... | |||
def where_not_in ( | |||
cls, | |||
column: str, | |||
values: list[Any] | tuple | |||
) -> QueryBuilder[Self]: ... | |||
@classmethod | |||
def where_not_null (cls, field: str) -> QueryBuilder: ... | |||
def where_not_null (cls, field: str) -> QueryBuilder[Self]: ... | |||
@classmethod | |||
def set_connection_resolver (cls, resolver: DatabaseManager) -> None: ... | |||
class QueryBuilder (Generic[_TModel]): | |||
def first (self) -> _TModel | None: ... | |||
class QueryBuilder (Generic[_ModelT]): | |||
def first (self) -> _ModelT | None: ... | |||
def get (self) -> list[_TModel]: ... | |||
def get (self) -> list[_ModelT]: ... | |||
@overload | |||
def where (self, field: str, operator: str, value: Any) -> QueryBuilder: ... | |||
def where ( | |||
self, | |||
field: str, | |||
operator: str, | |||
value: Any, | |||
) -> QueryBuilder[_ModelT]: ... | |||
@overload | |||
def where (self, field: str, value: Any) -> QueryBuilder: ... | |||
def where (self, field: str, value: Any) -> QueryBuilder[_ModelT]: ... | |||
def where_null (self, field: str) -> QueryBuilder: ... | |||
def where_null (self, field: str) -> QueryBuilder[_ModelT]: ... |
@@ -1,4 +0,0 @@ | |||
from eloquent import Model | |||
class DynamicProperty (Model): ... |
@@ -1,3 +1,6 @@ | |||
# pylint: disable = missing-class-docstring | |||
# pylint: disable = missing-function-docstring | |||
""" | |||
日次で実行し,ぼざクリ DB を最新に更新する. | |||
""" | |||
@@ -10,13 +13,11 @@ import random | |||
import string | |||
import time | |||
import unicodedata | |||
from dataclasses import dataclass | |||
from datetime import date, datetime, timedelta | |||
from typing import Any, Type, TypedDict, cast | |||
from typing import Any, TypedDict, cast | |||
import requests | |||
from eloquent import DatabaseManager, Model | |||
from eloquent.orm.relations.dynamic_property import DynamicProperty | |||
config: dict[str, DbConfig] = { 'mysql': { 'driver': 'mysql', | |||
'host': 'localhost', | |||
@@ -58,6 +59,8 @@ def update_tables ( | |||
video_history.views_count = datum['viewCounter'] | |||
video_history.save () | |||
video_tags = video.video_tags.where_not_null ('untagged_at').get () | |||
tag: Tag | None | |||
video_tag: VideoTag | None | |||
for video_tag in video_tags: | |||
tag = video_tag.tag | |||
if (tag is not None | |||
@@ -70,10 +73,10 @@ def update_tables ( | |||
tag = Tag () | |||
tag.name = tag_name | |||
tag.save () | |||
video_tag = (Video.where ('video_id', video.id) | |||
.where ('tag_id', tag.id) | |||
.where_null ('untagged_at') | |||
.first ()) | |||
video_tag = (VideoTag.where ('video_id', video.id) | |||
.where ('tag_id', tag.id) | |||
.where_null ('untagged_at') | |||
.first ()) | |||
if video_tag is None: | |||
video_tag = VideoTag () | |||
video_tag.video_id = video.id | |||
@@ -173,12 +176,15 @@ def search_nico_by_tags ( | |||
while to <= today: | |||
time.sleep (1.2) | |||
until = to + timedelta (days = 14) | |||
# pylint: disable = consider-using-f-string | |||
query_filter = json.dumps ({ 'type': 'or', | |||
'filters': [ | |||
{ 'type': 'range', | |||
'field': 'startTime', | |||
'from': '%04d-%02d-%02dT00:00:00+09:00' % (to.year, to.month, to.day), | |||
'to': '%04d-%02d-%02dT23:59:59+09:00' % (until.year, until.month, until.day), | |||
'from': ('%04d-%02d-%02dT00:00:00+09:00' | |||
% (to.year, to.month, to.day)), | |||
'to': ('%04d-%02d-%02dT23:59:59+09:00' | |||
% (until.year, until.month, until.day)), | |||
'include_lower': True }] }) | |||
params: VideoSearchParam = { 'q': ' OR '.join (tags), | |||
'targets': 'tagsExact', | |||
@@ -202,8 +208,9 @@ def search_nico_by_tags ( | |||
class Comment (Model): | |||
__timestamps__ = False | |||
# pylint: disable = too-many-instance-attributes | |||
id: int | |||
video_id: int | |||
comment_no: int | |||
user_id: int | |||
@@ -212,16 +219,18 @@ class Comment (Model): | |||
nico_count: int | |||
vpos_ms: int | |||
__timestamps__ = False | |||
@property | |||
def video ( | |||
self, | |||
) -> DynamicProperty: | |||
) -> Video: | |||
return self.belongs_to (Video) | |||
@property | |||
def user ( | |||
self, | |||
) -> DynamicProperty: | |||
) -> User: | |||
return self.belongs_to (User) | |||
def upsert ( | |||
@@ -232,58 +241,62 @@ class Comment (Model): | |||
.first ()) | |||
if row is not None: | |||
self.id = row.id | |||
self.__exists = True # pylint: disable = unused-private-member | |||
self.save () | |||
class Tag (Model): | |||
__timestamps__ = False | |||
id: int | |||
name: str | |||
__timestamps__ = False | |||
@property | |||
def video_tags ( | |||
self, | |||
) -> DynamicProperty: | |||
) -> VideoTag: | |||
return self.has_many (VideoTag) | |||
class User (Model): | |||
__timestamps__ = False | |||
id: int | |||
code: str | |||
__timestamps__ = False | |||
@property | |||
def comments ( | |||
self, | |||
) -> DynamicProperty: | |||
) -> Comment: | |||
return self.has_many (Comment) | |||
class Video (Model): | |||
__timestamps__ = False | |||
id: int | |||
code: str | |||
title: str | |||
description: str | |||
uploaded_at: datetime | |||
deleted_at: datetime | None | |||
__timestamps__ = False | |||
@property | |||
def video_histories ( | |||
self, | |||
) -> DynamicProperty: | |||
) -> VideoHistory: | |||
return self.has_many (VideoHistory) | |||
@property | |||
def video_tags ( | |||
self, | |||
) -> DynamicProperty: | |||
) -> VideoTag: | |||
return self.has_many (VideoTag) | |||
@property | |||
def comments ( | |||
self, | |||
) -> DynamicProperty: | |||
) -> Comment: | |||
return self.has_many (Comment) | |||
def upsert ( | |||
@@ -292,20 +305,22 @@ class Video (Model): | |||
row = Video.where ('code', self.code).first () | |||
if row is not None: | |||
self.id = row.id | |||
self.__exists = True # pylint: disable = unused-private-member | |||
self.save () | |||
class VideoHistory (Model): | |||
__timestamps__ = False | |||
id: int | |||
video_id: int | |||
fetched_at: date | |||
views_count: int | |||
__timestamps__ = False | |||
@property | |||
def video ( | |||
self, | |||
) -> DynamicProperty: | |||
) -> Video: | |||
return self.belongs_to (Video) | |||
def upsert ( | |||
@@ -316,27 +331,29 @@ class VideoHistory (Model): | |||
.first ()) | |||
if row is not None: | |||
self.id = row.id | |||
self.__exists = True # pylint: disable = unused-private-member | |||
self.save () | |||
class VideoTag (Model): | |||
__timestamps__ = False | |||
id: int | |||
video_id: int | |||
tag_id: int | |||
tagged_at: date | |||
untagged_at: date | None | |||
__timestamps__ = False | |||
@property | |||
def video ( | |||
self, | |||
) -> DynamicProperty: | |||
) -> Video: | |||
return self.belongs_to (Video) | |||
@property | |||
def tag ( | |||
self, | |||
) -> DynamicProperty: | |||
) -> Tag: | |||
return self.belongs_to (Tag) | |||
def upsert ( | |||
@@ -347,6 +364,7 @@ class VideoTag (Model): | |||
.first ()) | |||
if row is not None: | |||
self.id = row.id | |||
self.__exists = True # pylint: disable = unused-private-member | |||
self.save () | |||