-
Notifications
You must be signed in to change notification settings - Fork 0
implement articles from daily sun #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
mateow99
wants to merge
2
commits into
master
Choose a base branch
from
maw346/add-daily-sun
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ YOUTUBE_API_KEY= | |
MONGO_URI= | ||
MONGO_DB= | ||
STAGE= | ||
DAILY_SUN_URL= |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
from .game import Game | ||
from .team import Team | ||
from .youtube_video import YoutubeVideo | ||
from .youtube_video import YoutubeVideo | ||
from .article import Article |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
from bson.objectid import ObjectId | ||
from datetime import datetime | ||
|
||
class Article: | ||
""" | ||
A model representing a news article. | ||
|
||
Attributes: | ||
- title: The title of the article | ||
- image: The filename of the article's main image | ||
- sports_type: The specific sport category | ||
- published_at: The publication date | ||
- url: The URL to the full article | ||
- slug: Unique identifier from the source | ||
- created_at: When the article was added to our DB | ||
""" | ||
def __init__(self, title, sports_type, published_at, url, slug, image=None, id=None, created_at=None): | ||
self.id = id if id else str(ObjectId()) | ||
self.title = title | ||
self.image = image | ||
self.sports_type = sports_type | ||
self.published_at = published_at | ||
self.url = url | ||
self.slug = slug | ||
self.created_at = created_at if created_at else datetime.now() | ||
|
||
def to_dict(self): | ||
""" | ||
Converts the Article object to a dictionary format for MongoDB storage. | ||
""" | ||
return { | ||
"_id": self.id, | ||
"title": self.title, | ||
"image": self.image, | ||
"sports_type": self.sports_type, | ||
"published_at": self.published_at, | ||
"url": self.url, | ||
"slug": self.slug, | ||
"created_at": self.created_at | ||
} | ||
|
||
@staticmethod | ||
def from_dict(data): | ||
""" | ||
Converts a MongoDB document to an Article object. | ||
""" | ||
return Article( | ||
id=data.get("_id"), | ||
title=data.get("title"), | ||
image=data.get("image"), | ||
sports_type=data.get("sports_type"), | ||
published_at=data.get("published_at"), | ||
url=data.get("url"), | ||
slug=data.get("slug"), | ||
created_at=data.get("created_at") | ||
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
from .create_game import CreateGame | ||
from .create_team import CreateTeam | ||
from .create_youtube_video import CreateYoutubeVideo | ||
from .create_youtube_video import CreateYoutubeVideo | ||
from .create_article import CreateArticle |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
from graphene import Mutation, String, Field | ||
from src.types import ArticleType | ||
from src.services.article_service import ArticleService | ||
|
||
class CreateArticle(Mutation): | ||
class Arguments: | ||
title = String(required=True) | ||
sports_type = String(required=True) | ||
published_at = String(required=True) | ||
url = String(required=True) | ||
slug = String(required=True) | ||
image = String(required=False) | ||
|
||
article = Field(lambda: ArticleType) | ||
|
||
def mutate(self, info, title, sports_type, published_at, url, slug, image=None): | ||
from datetime import datetime | ||
article_data = { | ||
"title": title, | ||
"sports_type": sports_type, | ||
"published_at": datetime.fromisoformat(published_at), | ||
"url": url, | ||
"slug": slug, | ||
"image": image | ||
} | ||
new_article = ArticleService.create_article(article_data) | ||
return CreateArticle(article=new_article) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
from .game_query import GameQuery | ||
from .team_query import TeamQuery | ||
from .youtube_video_query import YoutubeVideoQuery | ||
from .article_query import ArticleQuery |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
from graphene import ObjectType, List, String | ||
from src.services.article_service import ArticleService | ||
from src.types import ArticleType | ||
|
||
class ArticleQuery(ObjectType): | ||
articles = List(ArticleType, sports_type=String()) | ||
|
||
def resolve_articles(self, info, sports_type=None): | ||
""" | ||
Resolver for retrieving news articles, optionally filtered by sports_type. | ||
""" | ||
return ArticleService.get_articles(sports_type) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
from .game_repository import GameRepository | ||
from .team_repository import TeamRepository | ||
from .youtube_video_repository import YoutubeVideoRepository | ||
from .article_repository import ArticleRepository |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
from src.database import daily_sun_db | ||
from src.models.article import Article | ||
from pymongo import UpdateOne | ||
from datetime import datetime, timedelta | ||
|
||
class ArticleRepository: | ||
@staticmethod | ||
def upsert(article): | ||
""" | ||
Upsert an article into the 'news_articles' collection in MongoDB. | ||
""" | ||
article_collection = daily_sun_db["news_articles"] | ||
article_collection.update_one( | ||
{"slug": article.slug}, | ||
{"$set": article.to_dict()}, | ||
upsert=True | ||
) | ||
|
||
@staticmethod | ||
def bulk_upsert(articles): | ||
""" | ||
Bulk upsert articles into the 'news_articles' collection based on slug. | ||
""" | ||
if not articles: | ||
return | ||
|
||
article_collection = daily_sun_db["news_articles"] | ||
operations = [ | ||
UpdateOne( | ||
{"slug": article.slug}, | ||
{"$set": article.to_dict()}, | ||
upsert=True | ||
) | ||
for article in articles | ||
] | ||
if operations: | ||
article_collection.bulk_write(operations) | ||
|
||
@staticmethod | ||
def find_recent(limit_days=3): | ||
""" | ||
Retrieve articles from the last N days, sorted by published_at descending. | ||
""" | ||
article_collection = daily_sun_db["news_articles"] | ||
query = {"published_at": {"$gte": datetime.now() - timedelta(days=limit_days)}} | ||
articles = article_collection.find(query).sort("published_at", -1) | ||
return [Article.from_dict(article) for article in articles] | ||
|
||
@staticmethod | ||
def find_by_sports_type(sports_type, limit_days=3): | ||
""" | ||
Retrieve articles by sports_type from the last N days, sorted by published_at descending. | ||
""" | ||
article_collection = daily_sun_db["news_articles"] | ||
query = { | ||
"sports_type": sports_type, | ||
"published_at": {"$gte": datetime.now() - timedelta(days=limit_days)} | ||
} | ||
articles = article_collection.find(query).sort("published_at", -1) | ||
return [Article.from_dict(article) for article in articles] | ||
|
||
@staticmethod | ||
def delete_not_recent(limit_days=3): | ||
""" | ||
Delete articles older than N days, sorted by published_at descending. | ||
""" | ||
article_collection = daily_sun_db["news_articles"] | ||
query = {"published_at": {"$lt": datetime.now() - timedelta(days=limit_days)}} | ||
article_collection.delete_many(query) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,17 @@ | ||
from graphene import ObjectType, Schema, Mutation | ||
from src.mutations import CreateGame, CreateTeam, CreateYoutubeVideo | ||
from src.queries import GameQuery, TeamQuery, YoutubeVideoQuery | ||
from src.mutations import CreateGame, CreateTeam, CreateYoutubeVideo, CreateArticle | ||
from src.queries import GameQuery, TeamQuery, YoutubeVideoQuery, ArticleQuery | ||
|
||
|
||
class Query(TeamQuery, GameQuery, YoutubeVideoQuery, ObjectType): | ||
class Query(TeamQuery, GameQuery, YoutubeVideoQuery, ArticleQuery, ObjectType): | ||
pass | ||
|
||
|
||
class Mutation(ObjectType): | ||
create_game = CreateGame.Field(description="Creates a new game.") | ||
create_team = CreateTeam.Field(description="Creates a new team.") | ||
create_youtube_video = CreateYoutubeVideo.Field(description="Creates a new youtube video.") | ||
create_article = CreateArticle.Field(description="Creates a new article.") | ||
|
||
|
||
schema = Schema(query=Query, mutation=Mutation) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import os | ||
import requests | ||
from datetime import datetime, timedelta | ||
from dotenv import load_dotenv | ||
from ..services import ArticleService | ||
import logging | ||
|
||
load_dotenv() | ||
|
||
|
||
def fetch_news(): | ||
try: | ||
url = os.getenv("DAILY_SUN_URL") | ||
response = requests.get( | ||
url, | ||
headers={ | ||
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" | ||
} | ||
) | ||
response.raise_for_status() | ||
data = response.json() | ||
|
||
# Current date and 3-day threshold | ||
current_date = datetime.now() | ||
three_days_ago = current_date - timedelta(days=3) | ||
|
||
# Process articles | ||
articles_to_store = [] | ||
for article in data.get("articles", []): | ||
published_at = datetime.strptime(article["published_at"], "%Y-%m-%d %H:%M:%S") | ||
|
||
if published_at >= three_days_ago: | ||
sports_type = next( | ||
(tag["name"] for tag in article["tags"] if tag["name"] not in ["Sports", "Top Stories"]), | ||
"General" | ||
) | ||
article_url = f"https://cornellsun.com/article/{article['slug']}" | ||
|
||
article_doc = { | ||
"title": article["headline"], | ||
"image": article["dominantMedia"]["title"] if article["dominantMedia"] else None, | ||
"sports_type": sports_type, | ||
"published_at": published_at, | ||
"url": article_url, | ||
"slug": article["slug"], | ||
"created_at": datetime.now() | ||
} | ||
articles_to_store.append(article_doc) | ||
|
||
if articles_to_store: | ||
ArticleService.create_articles_bulk(articles_to_store) | ||
logging.info(f"Stored/Updated {len(articles_to_store)} recent articles") | ||
else: | ||
logging.info("No recent articles to store") | ||
return True | ||
|
||
except Exception as e: | ||
logging.error(f"Error fetching news: {str(e)}") | ||
return False |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
from .game_service import GameService | ||
from .team_service import TeamService | ||
from .youtube_video_service import YoutubeVideoService | ||
from .youtube_video_service import YoutubeVideoService | ||
from .article_service import ArticleService |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.