このコミットが含まれているのは:
2025-10-21 22:27:37 +09:00
コミット 7ff729b256
5個のファイルの変更122行の追加173行の削除
-58
ファイルの表示
@@ -1,58 +0,0 @@
from datetime import datetime
from atproto.models.AppBskyFeedDefs import BlockedPost, NotFoundPost
from atproto_client.models.app.bsky.feed import get_timeline
class Client:
app: AppNamespace
def get_current_time_iso (self) -> datetime: ...
def get_post_thread (
self,
uri: str,
parent_height: int | None = None
) -> Response: ...
def get_timeline (self) -> get_timeline.Response: ...
def follow (self, did: str) -> None: ...
def like (self, uri: str, cid: str) -> None: ...
class AppNamespace:
bsky: AppBskyNamespace
class AppBskyNamespace:
notification: AppBskyNotificationNamespace
class AppBskyNotificationNamespace:
def list_notifications (self) -> Response: ...
def update_seen (self, seen: dict[str, datetime]) -> None: ...
class Response:
notifications: list[Notification]
thread: (ThreadViewPost
| NotFoundPost
| BlockedPost)
class ThreadViewPost:
pass
class Notification:
is_read: bool
reason: str
uri: str
author: ProfileView
class ProfileView:
did: str
-5
ファイルの表示
@@ -1,5 +0,0 @@
class NotFoundPost:
pass
class BlockedPost:
pass
-5
ファイルの表示
@@ -1,5 +0,0 @@
from atproto.models.AppBskyFeedDefs import FeedViewPost
class Response:
feed: list[FeedViewPost]
+45 -28
ファイルの表示
@@ -5,16 +5,14 @@ import os
import time
from datetime import datetime
from io import BytesIO
from typing import TypedDict
from typing import Any, TypedDict
import atproto
import atproto # type: ignore
import requests
from atproto import Client
from atproto.models import AppBskyEmbedExternal, AppBskyEmbedImages
from atproto.models.AppBskyFeedPost import ReplyRef
from atproto.models.app.bsky.embed import images
from atproto.models.com.atproto.repo import strong_ref
from atproto_client.models.app.bsky.feed.get_timeline import Response
from atproto import Client # type: ignore
from atproto.models import AppBskyEmbedExternal, AppBskyEmbedImages # type: ignore
from atproto.models.AppBskyFeedPost import ReplyRef # type: ignore
from atproto_client.models.app.bsky.feed.get_timeline import Response # type: ignore
from requests.exceptions import Timeout
import account
@@ -68,7 +66,6 @@ async def check_mentions (
records = fetch_thread_contents (uri, 20)
if records:
record = records[0]
content = record['text']
image_url: str | None = None
if record['embed'] and hasattr (record['embed'], 'images'):
image_url = ('https://cdn.bsky.app/img/feed_fullsize/plain'
@@ -86,29 +83,35 @@ async def check_mentions (
async def answer (
) -> None:
while True:
answered_flags = (
AnsweredFlag
.where ('platform', Platform.BLUESKY.value)
.where ('answered', False)
.get ())
for answered_flag in answered_flags:
td: dict[str, Any]
answer = answered_flag.answer
match QueryType (answer.query.query_type):
match QueryType (answer.query_rel.query_type):
case QueryType.BLUESKY_COMMENT:
td = answer.query.transfer_data or { }
td = answer.query_rel.transfer_data or { }
uri: str | None = td.get ('uri')
cid: str | None = td.get ('cid')
if (not uri) or (not cid):
continue
sref = { 'uri': uri, 'cid': cid }
strong_ref = atproto.models.create_strong_ref (sref)
strong_ref = atproto.models.create_strong_ref (sref) # type: ignore
reply_ref = ReplyRef (root = strong_ref, parent = strong_ref)
try:
client.post (answer.content, reply_to = reply_ref)
flag.answered = True
flag.save ()
except Exception as e:
print (f"[answer/reply] { type (e).__name__ }: { e }")
continue
answered_flag.answered = True
answered_flag.save ()
case QueryType.KIRIBAN | QueryType.NICO_REPORT:
td = answer.query.transfer_data or { }
td = answer.query_rel.transfer_data or { }
video_code: str | None = td.get ('video_code')
if not video_code:
continue
@@ -116,11 +119,15 @@ async def answer (
uri = f"https://www.nicovideo.jp/watch/{ video_code }"
(title, description, thumbnail) = nicolib.fetch_embed_info (uri)
try:
upload = client.com.atproto.repo.upload_blob (
BytesIO (requests.get (thumbnail, timeout = 60).content))
resp = requests.get (thumbnail, timeout = 60)
resp.raise_for_status ()
upload = client.com.atproto.repo.upload_blob (BytesIO (resp.content))
thumb = upload.blob
except Timeout:
thumb = None
except Exception as e:
print (f"[answer/nico-thumb] { type (e).__name__ }: { e }")
thumb = None
external = AppBskyEmbedExternal.External (
title = title,
@@ -128,9 +135,13 @@ async def answer (
thumb = thumb,
uri = uri)
embed_external = AppBskyEmbedExternal.Main (external = external)
try:
client.post (answer.content, embed = embed_external)
flag.answered = True
flag.save ()
except Exception as e:
print (f"[answer/nico-post] { type (e).__name__ }: { e }")
continue
answered_flag.answered = True
answered_flag.save ()
case QueryType.SNACK_TIME:
try:
with open ('./assets/snack-time.jpg', 'rb') as f:
@@ -150,8 +161,8 @@ async def answer (
image = client.com.atproto.repo.upload_blob (f).blob)
client.post (answer.content,
embed = AppBskyEmbedImages.Main (images = [image]))
flag.answered = True
flag.save ()
answered_flag.answered = True
answered_flag.save ()
except Exception:
pass
case QueryType.HOT_SPRING:
@@ -171,10 +182,11 @@ async def answer (
image = client.com.atproto.repo.upload_blob (f).blob)
client.post (answer.content,
embed = AppBskyEmbedImages.Main (images = [image]))
flag.answered = True
flag.save ()
answered_flag.answered = True
answered_flag.save ()
except Exception:
pass
await asyncio.sleep (10)
def check_notifications (
@@ -208,14 +220,19 @@ def fetch_thread_contents (
records: list[Record] = []
while res:
records.append ({ 'strong_ref': { 'uri': res.post.uri, 'cid': res.post.cid },
if hasattr (res, 'post'):
records.append ({ 'strong_ref': { 'uri': res.post.uri,
'cid': res.post.cid },
'did': res.post.author.did,
'handle': res.post.author.handle,
'name': res.post.author.display_name,
'name': (res.post.author.display_name
or res.post.author.handle),
'datetime': res.post.record.created_at,
'text': res.post.record.text,
'embed': res.post.record.embed })
'text': getattr (res.post.record, 'text', None) or '',
'embed': getattr (res.post.record, 'embed', None) })
res = res.parent
else:
break
return records
@@ -241,7 +258,7 @@ def _add_query (
user: User,
content: str,
image_url: str | None = None,
transfer_data: dict | None = None,
transfer_data: dict[str, Any] | None = None,
) -> None:
query = Query ()
query.user_id = user.id
サブモジュール nizika_ai が更新されました: 4e5bd13ab4...3be6d9063c