File size: 4,984 Bytes
6cfe55f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | from __future__ import annotations
import hashlib
import json
from datetime import datetime
from app.article_fetchers.base import ArticleContent
from app.db.engine import get_db
from app.db.models.articles import ArticleItem, ArticleSubscription, ArticleSubscriptionItem
def url_hash(url: str) -> str:
return hashlib.sha256(url.encode("utf-8")).hexdigest()
def _detach(obj):
data = {key: value for key, value in obj.__dict__.items() if not key.startswith("_")}
obj.__dict__.clear()
obj.__dict__.update(data)
return obj
def upsert_article_item(article: ArticleContent) -> ArticleItem:
db = next(get_db())
try:
digest = url_hash(article.url)
item = None
if article.article_id:
item = (
db.query(ArticleItem)
.filter_by(platform=article.platform, article_id=article.article_id)
.first()
)
if item is None:
item = db.query(ArticleItem).filter_by(platform=article.platform, url_hash=digest).first()
if item is None:
item = ArticleItem(
platform=article.platform,
article_id=article.article_id,
url_hash=digest,
url=article.url,
title=article.title,
)
db.add(item)
item.url = article.url
item.title = article.title
item.author_name = article.author_name
item.author_id = article.author_id
item.cover_url = article.cover_url
item.published_at = article.published_at
item.content_text = article.content_text
item.raw_metadata = json.dumps(article.raw_metadata or {}, ensure_ascii=False)
db.commit()
db.refresh(item)
return _detach(item)
finally:
db.close()
def get_article_item(item_id: int) -> ArticleItem | None:
db = next(get_db())
try:
item = db.query(ArticleItem).filter_by(id=item_id).first()
return _detach(item) if item else None
finally:
db.close()
def list_article_items(subscription_id: int | None = None) -> list[ArticleItem]:
db = next(get_db())
try:
query = db.query(ArticleItem)
if subscription_id is not None:
query = query.join(
ArticleSubscriptionItem,
ArticleSubscriptionItem.article_item_id == ArticleItem.id,
).filter(ArticleSubscriptionItem.subscription_id == subscription_id)
return [_detach(item) for item in query.order_by(ArticleItem.id.desc()).all()]
finally:
db.close()
def mark_article_summarized(item_id: int, task_id: str) -> None:
db = next(get_db())
try:
item = db.query(ArticleItem).filter_by(id=item_id).first()
if item:
item.summary_status = "summarized"
item.task_id = task_id
db.commit()
finally:
db.close()
def create_subscription(
platform: str,
subscription_type: str,
query: str,
label: str = "",
) -> ArticleSubscription:
db = next(get_db())
try:
subscription = ArticleSubscription(
platform=platform,
type=subscription_type,
query=query,
label=label or query,
)
db.add(subscription)
db.commit()
db.refresh(subscription)
return _detach(subscription)
finally:
db.close()
def list_subscriptions() -> list[ArticleSubscription]:
db = next(get_db())
try:
return [
_detach(item)
for item in db.query(ArticleSubscription).order_by(ArticleSubscription.id.desc()).all()
]
finally:
db.close()
def get_subscription(subscription_id: int) -> ArticleSubscription | None:
db = next(get_db())
try:
item = db.query(ArticleSubscription).filter_by(id=subscription_id).first()
return _detach(item) if item else None
finally:
db.close()
def update_subscription_refresh(subscription_id: int, error: str = "") -> None:
db = next(get_db())
try:
item = db.query(ArticleSubscription).filter_by(id=subscription_id).first()
if item:
item.last_refresh_at = datetime.now()
item.last_error = error
db.commit()
finally:
db.close()
def link_subscription_item(subscription_id: int, article_item_id: int, match_reason: str) -> None:
db = next(get_db())
try:
existing = (
db.query(ArticleSubscriptionItem)
.filter_by(subscription_id=subscription_id, article_item_id=article_item_id)
.first()
)
if existing is None:
db.add(
ArticleSubscriptionItem(
subscription_id=subscription_id,
article_item_id=article_item_id,
match_reason=match_reason,
)
)
db.commit()
finally:
db.close()
|