|
|
@@ -5,25 +5,20 @@ AI ニジカ常時稼動バッチ |
|
|
from __future__ import annotations |
|
|
from __future__ import annotations |
|
|
|
|
|
|
|
|
import asyncio |
|
|
import asyncio |
|
|
|
|
|
import json |
|
|
|
|
|
import os |
|
|
import random |
|
|
import random |
|
|
|
|
|
import subprocess |
|
|
from asyncio import Lock |
|
|
from asyncio import Lock |
|
|
from datetime import date, datetime, time, timedelta |
|
|
from datetime import date, datetime, time, timedelta |
|
|
from typing import cast |
|
|
|
|
|
|
|
|
from typing import Any, cast |
|
|
|
|
|
|
|
|
import nicolib |
|
|
import nicolib |
|
|
import queries_to_answers as q2a |
|
|
import queries_to_answers as q2a |
|
|
from config import DB |
|
|
|
|
|
from db.models import Comment, Video, VideoHistory |
|
|
|
|
|
from nicolib import VideoInfo |
|
|
from nicolib import VideoInfo |
|
|
from nizika_ai.consts import Character, GPTModel, QueryType |
|
|
from nizika_ai.consts import Character, GPTModel, QueryType |
|
|
from nizika_ai.models import Query |
|
|
from nizika_ai.models import Query |
|
|
|
|
|
|
|
|
# DB 設定 |
|
|
|
|
|
DB |
|
|
|
|
|
for m in (Comment, Video, VideoHistory): |
|
|
|
|
|
m.__connection__ = 'nico' |
|
|
|
|
|
Query.__connection__ = 'ai' |
|
|
|
|
|
|
|
|
|
|
|
KIRIBAN_VIEWS_COUNTS: list[int] = sorted ({ *range (1_000, 10_000, 1_000), |
|
|
KIRIBAN_VIEWS_COUNTS: list[int] = sorted ({ *range (1_000, 10_000, 1_000), |
|
|
*range (10_000, 1_000_001, 10_000), |
|
|
*range (10_000, 1_000_001, 10_000), |
|
|
114_514, 1_940, 2_450, 5_100, |
|
|
114_514, 1_940, 2_450, 5_100, |
|
|
@@ -84,10 +79,10 @@ async def report_kiriban ( |
|
|
video_code = video_info['contentId'] |
|
|
video_code = video_info['contentId'] |
|
|
comments = fetch_comments (video_code) |
|
|
comments = fetch_comments (video_code) |
|
|
popular_comments = sorted (comments, |
|
|
popular_comments = sorted (comments, |
|
|
key = lambda c: c.nico_count, |
|
|
|
|
|
|
|
|
key = lambda c: c['nico_count'], |
|
|
reverse = True)[:10] |
|
|
reverse = True)[:10] |
|
|
latest_comments = sorted (comments, |
|
|
latest_comments = sorted (comments, |
|
|
key = lambda c: c.posted_at, |
|
|
|
|
|
|
|
|
key = lambda c: c['posted_at'], |
|
|
reverse = True)[:10] |
|
|
reverse = True)[:10] |
|
|
prompt = (f"{ _format_elapsed (uploaded_at) }前にニコニコに投稿された" |
|
|
prompt = (f"{ _format_elapsed (uploaded_at) }前にニコニコに投稿された" |
|
|
f"『{ video_info['title'] }』という動画が{ views_count }再生を突破しました。\n" |
|
|
f"『{ video_info['title'] }』という動画が{ views_count }再生を突破しました。\n" |
|
|
@@ -95,7 +90,7 @@ async def report_kiriban ( |
|
|
if video_info['tags']: |
|
|
if video_info['tags']: |
|
|
prompt += f"つけられたタグは「{ '」、「'.join (video_info['tags']) }」です。\n" |
|
|
prompt += f"つけられたタグは「{ '」、「'.join (video_info['tags']) }」です。\n" |
|
|
if comments: |
|
|
if comments: |
|
|
prompt += f"人気のコメントは次の通りです:「{ '」、「'.join (c.content for c in popular_comments) }」\n" |
|
|
|
|
|
|
|
|
prompt += f"人気のコメントは次の通りです:「{ '」、「'.join (c['content'] for c in popular_comments) }」\n" |
|
|
if latest_comments != popular_comments: |
|
|
if latest_comments != popular_comments: |
|
|
prompt += f"最新のコメントは次の通りです:「{ '」、「'.join (c.content for c in latest_comments) }」\n" |
|
|
prompt += f"最新のコメントは次の通りです:「{ '」、「'.join (c.content for c in latest_comments) }」\n" |
|
|
prompt += f""" |
|
|
prompt += f""" |
|
|
@@ -160,41 +155,22 @@ def fetch_kiriban_list ( |
|
|
動画リスト(キリ番基準再生数、対象動画情報、投稿日時のタプル) |
|
|
動画リスト(キリ番基準再生数、対象動画情報、投稿日時のタプル) |
|
|
""" |
|
|
""" |
|
|
|
|
|
|
|
|
_kiriban_list: list[tuple[int, VideoInfo, datetime]] = [] |
|
|
|
|
|
|
|
|
|
|
|
latest_fetched_at = cast (date, (VideoHistory |
|
|
|
|
|
.where ('fetched_at', '<=', base_date) |
|
|
|
|
|
.max ('fetched_at'))) |
|
|
|
|
|
|
|
|
|
|
|
for kiriban_views_count in KIRIBAN_VIEWS_COUNTS: |
|
|
|
|
|
targets = { vh.video.code for vh in (VideoHistory |
|
|
|
|
|
.where ('fetched_at', latest_fetched_at) |
|
|
|
|
|
.where ('views_count', '>=', kiriban_views_count) |
|
|
|
|
|
.get ()) } |
|
|
|
|
|
for code in targets: |
|
|
|
|
|
if code in [kiriban[1]['contentId'] for kiriban in _kiriban_list]: |
|
|
|
|
|
continue |
|
|
|
|
|
previous_views_count: int | None = ( |
|
|
|
|
|
VideoHistory |
|
|
|
|
|
.where_has ('video', lambda q, code = code: q.where ('code', code)) |
|
|
|
|
|
.where ('fetched_at', '<', latest_fetched_at) |
|
|
|
|
|
.max ('views_count')) |
|
|
|
|
|
if previous_views_count is None: |
|
|
|
|
|
previous_views_count = 0 |
|
|
|
|
|
if previous_views_count >= kiriban_views_count: |
|
|
|
|
|
continue |
|
|
|
|
|
video_info = nicolib.fetch_video_info (code) |
|
|
|
|
|
if video_info is not None: |
|
|
|
|
|
_kiriban_list.append ((kiriban_views_count, video_info, |
|
|
|
|
|
(cast (Video, Video.where ('code', code).first ()) |
|
|
|
|
|
.uploaded_at))) |
|
|
|
|
|
|
|
|
|
|
|
return _kiriban_list |
|
|
|
|
|
|
|
|
result = subprocess.run ( |
|
|
|
|
|
['python3', str (base_date), *map (str, KIRABAN_VIEWS_COUNTS)], |
|
|
|
|
|
cwd = '/root/nizika_nico', |
|
|
|
|
|
env = os.environ, |
|
|
|
|
|
capture_output = True, |
|
|
|
|
|
text = True) |
|
|
|
|
|
kl: list[list[int | str]] = json.loads (result.stdout) |
|
|
|
|
|
|
|
|
|
|
|
return map (lambda k: (cast (int, k[0]), |
|
|
|
|
|
nicolib.fetch_video_info (cast (str, k[1])), |
|
|
|
|
|
datetime.strptime (cast (str, k[2]), '%Y-%m-%d %H:%M:%S.%f')), kl) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def fetch_comments ( |
|
|
def fetch_comments ( |
|
|
video_code: str, |
|
|
video_code: str, |
|
|
) -> list[Comment]: |
|
|
|
|
|
|
|
|
) -> list[CommentDict]: |
|
|
""" |
|
|
""" |
|
|
動画のコメント・リストを取得する. |
|
|
動画のコメント・リストを取得する. |
|
|
|
|
|
|
|
|
@@ -205,14 +181,23 @@ def fetch_comments ( |
|
|
|
|
|
|
|
|
Return |
|
|
Return |
|
|
------ |
|
|
------ |
|
|
list[Comment] |
|
|
|
|
|
|
|
|
list[CommentDict] |
|
|
コメント・リスト |
|
|
コメント・リスト |
|
|
""" |
|
|
""" |
|
|
|
|
|
|
|
|
video = Video.where ('code', video_code).first () |
|
|
|
|
|
if video is None: |
|
|
|
|
|
return [] |
|
|
|
|
|
return video.comments |
|
|
|
|
|
|
|
|
result = subprocess.run ( |
|
|
|
|
|
['python3', video_code], |
|
|
|
|
|
cwd = '/root/nizika_nico', |
|
|
|
|
|
env = os.environ, |
|
|
|
|
|
capture_output = True, |
|
|
|
|
|
text = True) |
|
|
|
|
|
rows: list[dict[str, Any]] = json.loads (result.stdout) |
|
|
|
|
|
comments: list[CommentDict] = [] |
|
|
|
|
|
for row in comments: |
|
|
|
|
|
row['posted_at'] = datetime.strptime (row['posted_at'], '%Y-%m-%d %H:%M:%S.%f') |
|
|
|
|
|
comments.append (cast (CommentDict, row)) |
|
|
|
|
|
|
|
|
|
|
|
return comments |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def fetch_latest_deerjika ( |
|
|
def fetch_latest_deerjika ( |
|
|
@@ -339,6 +324,17 @@ def _format_elapsed ( |
|
|
return f"{ days }日{ hours }時間{ mins }分{ seconds }秒" |
|
|
return f"{ days }日{ hours }時間{ mins }分{ seconds }秒" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CommentDict (TypedDict): |
|
|
|
|
|
id: int |
|
|
|
|
|
video_id: int |
|
|
|
|
|
comment_no: int |
|
|
|
|
|
user_id: int |
|
|
|
|
|
content: str |
|
|
|
|
|
posted_at: datetime |
|
|
|
|
|
nico_count: int |
|
|
|
|
|
vpos_ms: int |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
kiriban_list = ( |
|
|
kiriban_list = ( |
|
|
fetch_kiriban_list ((now := datetime.now ()).date () |
|
|
fetch_kiriban_list ((now := datetime.now ()).date () |
|
|
- timedelta (days = 1 if now.hour < 15 else 0))) |
|
|
- timedelta (days = 1 if now.hour < 15 else 0))) |
|
|
|