|
@@ -1,6 +1,7 @@ |
|
|
from __future__ import annotations |
|
|
from __future__ import annotations |
|
|
|
|
|
|
|
|
import asyncio |
|
|
import asyncio |
|
|
|
|
|
import random |
|
|
from datetime import date, datetime, time, timedelta |
|
|
from datetime import date, datetime, time, timedelta |
|
|
from typing import TypedDict, cast |
|
|
from typing import TypedDict, cast |
|
|
|
|
|
|
|
@@ -9,7 +10,9 @@ from bs4 import BeautifulSoup |
|
|
from requests.exceptions import Timeout |
|
|
from requests.exceptions import Timeout |
|
|
|
|
|
|
|
|
import queries_to_answers as q2a |
|
|
import queries_to_answers as q2a |
|
|
from db.models import Video, VideoHistory |
|
|
|
|
|
|
|
|
from db.models import Comment, Video, VideoHistory |
|
|
|
|
|
from nizika_ai.consts import Character, GPTModel, QueryType |
|
|
|
|
|
from nizika_ai.models import Query |
|
|
|
|
|
|
|
|
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), |
|
@@ -44,28 +47,16 @@ async def report_kiriban ( |
|
|
(views_count, video_info, uploaded_at) = ( |
|
|
(views_count, video_info, uploaded_at) = ( |
|
|
kiriban_list.pop (random.randint (0, len (kiriban_list) - 1))) |
|
|
kiriban_list.pop (random.randint (0, len (kiriban_list) - 1))) |
|
|
since_posted = datetime.now () - uploaded_at |
|
|
since_posted = datetime.now () - uploaded_at |
|
|
uri = f"https://www.nicovideo.jp/watch/{ video_info['contentId'] }" |
|
|
|
|
|
(title, description, thumbnail) = fetch_embed_info (uri) |
|
|
|
|
|
try: |
|
|
|
|
|
upload = client.com.atproto.repo.upload_blob ( |
|
|
|
|
|
io.BytesIO (requests.get (thumbnail, |
|
|
|
|
|
timeout = 60).content)) |
|
|
|
|
|
thumb = upload.blob |
|
|
|
|
|
except Timeout: |
|
|
|
|
|
thumb = None |
|
|
|
|
|
comments = nico.get_comments (video_info['contentId']) |
|
|
|
|
|
|
|
|
video_code = video_info['contentId'] |
|
|
|
|
|
uri = f"https://www.nicovideo.jp/watch/{ video_code }" |
|
|
|
|
|
(title, description, _) = fetch_embed_info (uri) |
|
|
|
|
|
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] |
|
|
embed_external = models.AppBskyEmbedExternal.Main ( |
|
|
|
|
|
external = models.AppBskyEmbedExternal.External ( |
|
|
|
|
|
title = title, |
|
|
|
|
|
description = description, |
|
|
|
|
|
thumb = thumb, |
|
|
|
|
|
uri = uri)) |
|
|
|
|
|
prompt = f"{ since_posted.days }日と{ since_posted.seconds }秒前にニコニコに投稿された『{ video_info['title'] }』という動画が{ views_count }再生を突破しました。\n" |
|
|
prompt = f"{ since_posted.days }日と{ since_posted.seconds }秒前にニコニコに投稿された『{ video_info['title'] }』という動画が{ views_count }再生を突破しました。\n" |
|
|
prompt += f"コメント数は{ len (comments) }件です。\n" |
|
|
prompt += f"コメント数は{ len (comments) }件です。\n" |
|
|
if video_info['tags']: |
|
|
if video_info['tags']: |
|
@@ -78,10 +69,19 @@ async def report_kiriban ( |
|
|
```html |
|
|
```html |
|
|
{ video_info['description'] } |
|
|
{ video_info['description'] } |
|
|
``` |
|
|
``` |
|
|
このことについて、ニジカちゃんからのお祝いメッセージを下さい。 |
|
|
|
|
|
ただし、そのメッセージ内には再生数の数値とその多さに応じたリアクションを添えてください。 |
|
|
|
|
|
また、ぜひ投稿からこの再生数に至るまでにかかった時間や、つけられたタグ、コメントに対して思いを馳せてください。 |
|
|
|
|
|
好きなコメントがあったら教えてね。""" |
|
|
|
|
|
|
|
|
このことについて、何かお祝いメッセージを下さい。 |
|
|
|
|
|
ただし、そのメッセージ内には再生数の数値を添えてください。 |
|
|
|
|
|
また、つけられたタグ、コメントからどのような動画か想像し、説明してください。""" |
|
|
|
|
|
query = Query () |
|
|
|
|
|
query.user_id = None |
|
|
|
|
|
query.target_character = Character.DEERJIKA.value |
|
|
|
|
|
query.content = prompt |
|
|
|
|
|
query.query_type = QueryType.KIRIBAN.value |
|
|
|
|
|
query.model = GPTModel.GPT3_TURBO.value |
|
|
|
|
|
query.sent_at = datetime.now () |
|
|
|
|
|
query.answered = False |
|
|
|
|
|
query.transfer_data = { 'video_code': video_code } |
|
|
|
|
|
query.save () |
|
|
# 待ち時間計算 |
|
|
# 待ち時間計算 |
|
|
dt = datetime.now () |
|
|
dt = datetime.now () |
|
|
d = dt.date () |
|
|
d = dt.date () |
|
@@ -195,6 +195,53 @@ def create_bs_from_url ( |
|
|
return BeautifulSoup (req.text, 'hecoml.parser') |
|
|
return BeautifulSoup (req.text, 'hecoml.parser') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def fetch_embed_info ( |
|
|
|
|
|
url: str, |
|
|
|
|
|
) -> tuple[str, str, str]: |
|
|
|
|
|
title: str = '' |
|
|
|
|
|
description: str = '' |
|
|
|
|
|
thumbnail: str = '' |
|
|
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
|
res = requests.get (url, timeout = 60) |
|
|
|
|
|
except Timeout: |
|
|
|
|
|
return ('', '', '') |
|
|
|
|
|
|
|
|
|
|
|
if res.status_code != 200: |
|
|
|
|
|
return ('', '', '') |
|
|
|
|
|
|
|
|
|
|
|
soup = BeautifulSoup (res.text, 'html.parser') |
|
|
|
|
|
|
|
|
|
|
|
tmp = soup.find ('title') |
|
|
|
|
|
if tmp is not None: |
|
|
|
|
|
title = tmp.text |
|
|
|
|
|
|
|
|
|
|
|
tmp = soup.find ('meta', attrs = { 'name': 'description' }) |
|
|
|
|
|
if tmp is not None and hasattr (tmp, 'get'): |
|
|
|
|
|
try: |
|
|
|
|
|
description = cast (str, tmp.get ('content')) |
|
|
|
|
|
except Exception: |
|
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
tmp = soup.find ('meta', attrs = { 'name': 'thumbnail' }) |
|
|
|
|
|
if tmp is not None and hasattr (tmp, 'get'): |
|
|
|
|
|
try: |
|
|
|
|
|
thumbnail = cast (str, tmp.get ('content')) |
|
|
|
|
|
except Exception: |
|
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
return (title, description, thumbnail) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def fetch_comments ( |
|
|
|
|
|
video_code: str, |
|
|
|
|
|
) -> list[Comment]: |
|
|
|
|
|
video = Video.where ('code', video_code).first () |
|
|
|
|
|
if video is None: |
|
|
|
|
|
return [] |
|
|
|
|
|
return video.comments |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def report_nico ( |
|
|
async def report_nico ( |
|
|
) -> None: |
|
|
) -> None: |
|
|
... |
|
|
... |
|
|