youare
Version:
displays github activity of user
333 lines (256 loc) β’ 10.9 kB
JavaScript
import cli from './utils/cli.js';
import init from './utils/init.js';
import log from './utils/log.js';
import dotenv from 'dotenv'
import { Octokit } from 'octokit';
import fs from 'fs'
dotenv.config()
const octokit = new Octokit({ })
const CACHE = './cache.json'
const MAX_SIZE = 7
function loadCache() {
try {
if (!fs.existsSync(CACHE)) {
fs.writeFileSync(CACHE, JSON.stringify({ init_data: "data" }, null, 2))
return {}
}
else {
const content = fs.readFileSync(CACHE, "utf-8").trim()
return JSON.parse(content)
}
} catch (error) {
console.log(`ERROR- There has been an error ${error}`);
return {}
}
}
function saveCache(data) {
let entries = Object.entries(data).sort((a,b) => b[1].timestamp - a[1].timestamp)
if(entries.length > MAX_SIZE){
entries = entries.slice(0,MAX_SIZE)
console.log(`Implementing LRU`);
}
const updatedCache = Object.fromEntries(entries)
fs.writeFileSync(CACHE, JSON.stringify(updatedCache, null, 2))
}
function formatDate(rawDate) {
return new Date(rawDate).toLocaleString("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: true, // Ensures AM/PM format
timeZoneName: "short"
});
}
async function fetchWithPagination(endpoint, params, cacheKey) {
const content = loadCache()
if (Object.keys(content).includes(cacheKey)) {
console.log(`Cache hit!`);
content[cacheKey].timestamp = Date.now()
saveCache(content)
return content[cacheKey]["data"]
}
try {
const response = await octokit.request(endpoint, params)
const data = response.data
content[cacheKey] = {data, timestamp: Date.now() }
saveCache(content)
return data
} catch (error) {
console.error(`ERROR: ${error.message}`)
}
}
const { flags, input } = cli;
const { clear, debug } = flags;
(async () => {
await init({ clear });
debug && log(flags);
// input.includes(`help`) && showHelp(0);
if (input.includes(`help`)) {
console.log(`
Usage: youare [options]
GitHub CLI Tool for fetching user activity, profile details, starred repositories, pull requests, and more.
Options:
help - Show help information.
event <username> <page_number> - Fetch the recent activity of a GitHub user.
checkStarred <username> <page_number> - Fetch the starred repositories of a GitHub user.
profile <username> - Fetch the profile details of a GitHub user.
pulls <username> <page_number> - Fetch the pull requests created by a GitHub user in the last 30 days.
issues <repo> <page_number> - Fetch the open issues for a specific repository.
checklimit - Checks rate limit of GitHub API and displays reset time.
repos <username> <page_number> - Fetch all repositories and metadata of user.
commits <username/repo> <page_number> - Fetch commit information of repository.
Description:
This tool allows you to interact with the GitHub API to fetch various types of data including but not limited to:
- Recent user activity (commits, issues, pull requests, etc.)
- Profile information (bio, followers, repositories, etc.)
- Starred repositories and their topics
- Open issues for a specific repository
- Pagination is now available! Allowing users to look through responses in a convenient manner.
EXAMPLE USAGE:
youare event <username>
youare issues <repo_name>
`);
}
if (input.includes(`event`)) {
const username = input[1];
const page = input[2]
const data = await fetchWithPagination("GET /users/{username}/events", { username: username, per_page: 5, page }, `events_${username}_${page}`)
if (!Array.isArray(data) || data.length === 0) {
console.log("β οΈ No recent activity found.");
return;
}
let prevRepo = "";
data.forEach((element) => {
let eventType = element.type;
let currentRepo = element.repo.name;
let formattedDate = formatDate(element.created_at);
let commits = element.payload?.commits;
let isPublic = element.public;
if (currentRepo !== prevRepo) {
prevRepo = currentRepo;
let visibility = isPublic ? "π Public" : "π Private";
console.log(`\nπ Repository: ${prevRepo}`);
console.log(`π Visibility: ${visibility}`);
console.log("π Events in this repository: \n");
}
console.log(`πΉ Event: ${eventType}`);
console.log(`π
Date: ${formattedDate}`);
if (!commits) {
console.log("π No commits in this event.\n");
} else {
console.log(`π Total commits: ${commits.length}\n`);
}
});
}
if (input.includes(`checkStarred`)) {
let username = input[1]
const page = input[2]
const data = await fetchWithPagination("GET /users/{username}/starred", { username: username, per_page: 5, page }, `starred_${username}_${page}`)
if (!data) {
console.log(`No starred repositories!`);
return;
}
if (data.length === 0) {
console.log(`No repositories starred`);
}
data.forEach((element) => {
console.log(`β Starred ${element.name}`)
console.log(`π Access it at - ${element.owner.html_url}`);
if (element.topics.length !== 0) {
console.log(`πΉ Topics are - `);
element.topics.slice(0, 5).forEach((index) => {
console.log(index);
});
console.log(`\n`);
}
else {
console.log(`No topics \n`);
}
})
}
if (input.includes(`profile`)) {
const username = input[1];
console.log(`\nπ Fetching profile details for: ${username}`);
const data = await fetchWithPagination("GET /users/{username}", { username: username }, `profile_${username}`)
console.log(`
π Name: ${data.name || "N/A"}
πΌ Bio: ${data.bio || "No bio available"}
π₯ Followers: ${data.followers} | Following: ${data.following}
π Public Repos: ${data.public_repos}
π Location: ${data.location || "Unknown"}
π Profile: ${data.html_url}
`);
}
if (input.includes(`pulls`)) {
const username = input[1];
const page = input[2]
const since = new Date();
since.setDate(since.getDate() - 30);
const data = await fetchWithPagination("GET /search/issues", {
q: `author:${username} type:pr created:>=${since.toISOString().split("T")[0]}`,
sort: "created",
order: "desc",
per_page: 5,
page
}, `pulls_${username}_${page}`);
if (data.total_count === 0) {
console.log(`No pull requests for ${username}`);
}
data?.items?.forEach(pr => console.log(`πΉ PR: ${pr.title} | π ${pr.html_url}`));
}
if (input.includes(`issues`)) {
const repo = input[1];
const page = input[2]
const inParameter2 = repo.split('/')[1]
const inParameter1 = repo.split('/')[0]
const issues = await fetchWithPagination("GET /repos/{owner}/{repo}/issues", { owner: inParameter1, repo: inParameter2, per_page: 5, page }, `repo_${repo}_${page}`)
console.log(issues);
if (issues.length === 0) {
console.log("β
No open issues found.");
return;
}
issues.forEach(issue => {
console.log(`\nπΉ Issue: ${issue.title}`);
console.log(`π ${issue.html_url}`);
console.log(`π
Created: ${formatDate(issue.created_at)}`);
});
}
if (input.includes(`checklimit`)) {
const data = await fetchWithPagination("GET /rate_limit", {}, `rate_limit_${Date.now()}`)
let { limit, remaining, reset } = data.rate
let rate = remaining / limit
reset = formatDate(reset * 1000)
console.log(`Rate is ${rate}`);
console.log(`Reset is ${reset}`);
}
if (input.includes(`repos`)) {
const username = input[1]
const page = input[2]
const data = await fetchWithPagination("GET /users/{username}/repos", { username: username, per_page: 5, page }, `${username}_${page}`)
let topics = []
data?.forEach((element) => {
console.log(`π Name of repository - ${element.name}`)
console.log(`π Full name of repository - ${element.full_name}`);
console.log(`π URL of repository - ${element.html_url}`);
console.log(`π Languages used - ${element.language}`);
console.log(`π΄ Forks - ${element.forks_count}`);
console.log(`π¦
Default branch - ${element.default_branch}`);
console.log(`License - ${element.license?.name}`);
if (topics.length === 0) {
console.log(`πΊοΈ No topics \n`);
}
else {
console.log(`πΊοΈ Topics are....`);
topics.slice(0, 5).map((ele) => console.log(`${ele}`)
)
console.log(`\n`);
}
})
}
if (input.includes(`commits`)) {
const repo = input[1]
const page = input[2]
const inParameter1 = repo.split('/')[0]
const inParameter2 = repo.split('/')[1]
const data = await fetchWithPagination("GET /repos/{owner}/{repo}/commits", {
owner: inParameter1,
repo: inParameter2,
per_page: 5,
page
}, `repo_${repo}_${page}`)
// console.log(data);
data.forEach((ele) => {
console.log(`π Message: ${ele.commit.message}`);
console.log(`π€ Author : ${ele.commit.author.name}`);
console.log(`π Date : ${ele.commit.author.date} \n`);
})
}
if (input.includes(`endSession`)) {
fs.unlinkSync(CACHE)
}
})();