Skip to content

Commit

Permalink
Merge pull request #5 from adnene-guessoum/dev
Browse files Browse the repository at this point in the history
add: response filter function with tests
  • Loading branch information
adnene-guessoum authored Dec 22, 2024
2 parents 7e0e74c + 2a2e211 commit 0f775be
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 14 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@

PERSONAL_GITHUB_USERNAME = "your_github_username"
PERSONAL_GITHUB_TOKEN = "your_github_token" # you can create a token from "https://github.com/settings/apps"

# the person you want to follow
TARGET_GITHUB_USERNAME = "target_username"
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
poetry.lock
.env
run.sh

# python package
__pycache__/
*.pyc
temp_*.py
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ readme = "README.md"
python = "^3.10"
python-dotenv = "^1.0.1"
requests = "^2.32.3"
python-dateutil = "^2.9.0.post0"

[tool.poetry.group.dev.dependencies]
flake8 = "^5.0.4"
Expand Down
41 changes: 35 additions & 6 deletions script/panopticron.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
""" Script to check on specific gh user's contributions, and send an email. """
import datetime
import logging
import os
from urllib.parse import urljoin

import requests
from dateutil import parser
from dotenv import load_dotenv

logger = logging.getLogger(__name__)
load_dotenv()
PERSONAL_GITHUB_USERNAME = os.getenv("PERSONAL_GITHUB_USERNAME")
PERSONAL_GITHUB_TOKEN = os.getenv("PERSONAL_GITHUB_TOKEN")
TARGET_GITHUB_USERNAME = os.getenv("TARGET_GITHUB_USERNAME")


def get_user_activity(username):
Expand Down Expand Up @@ -53,11 +56,37 @@ def check_sanity_github_api_response(response, username):
return response.json()


def main():
"""TODO"""
print("TODO")
return 0
def filter_last_24_hours_activity(user_activity):
"""extract relevant info from response"""

today = datetime.datetime.now(datetime.timezone.utc)
user_activity_last_24_hours = []
for event in user_activity:
if not today - parser.parse(event["created_at"]) < datetime.timedelta(days=1):
continue
event_type = event["type"]
repo_name = event["repo"]["name"]
created_at = event["created_at"]
body = (
f"\n ===================== \n"
f"New activity by {TARGET_GITHUB_USERNAME}:\n\n"
f"Url: {event.get('url', '')}"
f"Event Type: {event_type}\n"
f"Repository: {repo_name}\n"
f"Time: {created_at}\n"
f"Repo_URL: {urljoin('https://github.com/', repo_name)}\n"
f"author_URL: {urljoin('https://github.com/', TARGET_GITHUB_USERNAME)}"
f"\n ===================== \n"
)
user_activity_last_24_hours.append(body)

return user_activity_last_24_hours


def main(username):
"""main function when running the script"""
return username


if __name__ == "__main__":
main()
main(TARGET_GITHUB_USERNAME)
67 changes: 59 additions & 8 deletions tests/test_panopticron.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,60 @@
"""test file for panopticron.py script"""
import datetime

from script import panopticron

TARGET_GITHUB_USERNAME = "testuser"


class MockEmptyResponse:
def json(self):
return {}


class ValidUserActivity:
"""mock response for user activity to keep."""

@staticmethod
def get_user_activity():
now = datetime.datetime.now(datetime.timezone.utc)
return [
{
"created_at": (now - datetime.timedelta(hours=1)).isoformat(),
"type": "PushEvent",
"repo": {"name": "testuser/test-repo"},
"url": "https://api.github.com/events/123456789",
},
{
"created_at": (now - datetime.timedelta(hours=3)).isoformat(),
"type": "PullRequestEvent",
"repo": {"name": "testuser/another-repo"},
"url": "https://api.github.com/events/987654321",
},
]


class InvalidUserActivity:
"""mock response for user activity from 2 days ago."""

@staticmethod
def get_user_activity():
now = datetime.datetime.now(datetime.timezone.utc)
return [
{
"created_at": (now - datetime.timedelta(days=2)).isoformat(),
"type": "IssueCommentEvent",
"repo": {"name": "testuser/old-repo"},
"url": "https://api.github.com/events/111111111",
}
]


class TestPanopticron:
def test_panopticron(self, capsys):
return_value = panopticron.main()
capture = capsys.readouterr()
assert capture.out == "TODO\n"
assert capture.err == ""
assert return_value == 0

def test_sanity_check_user_activity_wrong_username(self, capsys, caplog):
def test_main(self):
result = panopticron.main(TARGET_GITHUB_USERNAME)
assert result == TARGET_GITHUB_USERNAME

def test_check_sanity_github_api_response_wrong_username(self, capsys, caplog):
username = "nonexistentuser"
response = MockEmptyResponse() # github api response for nonexistent user
sanity_check = panopticron.check_sanity_github_api_response(response, username)
Expand All @@ -25,3 +64,15 @@ def test_sanity_check_user_activity_wrong_username(self, capsys, caplog):
assert capture_out_err.err == ""
assert f"No data found for {username}" in capture_log
assert sanity_check is None

def test_filter_last_24_hours_activity_valid(self):
user_activity = ValidUserActivity.get_user_activity()
result = panopticron.filter_last_24_hours_activity(user_activity)
assert len(result) == 2
assert "PushEvent" in result[0]
assert "PullRequestEvent" in result[1]

def test_filter_last_24_hours_activity_invalid(self):
user_activity = InvalidUserActivity.get_user_activity()
result = panopticron.filter_last_24_hours_activity(user_activity)
assert len(result) == 0

0 comments on commit 0f775be

Please sign in to comment.