Skip to content

Commit

Permalink
Merge pull request #130 from plura-ai/feat/landing-page
Browse files Browse the repository at this point in the history
core: update landing page ⚡
  • Loading branch information
SkidGod4444 authored Jan 6, 2025
2 parents 2a8a5c7 + 8163c51 commit 93935e7
Show file tree
Hide file tree
Showing 31 changed files with 589 additions and 472 deletions.
9 changes: 9 additions & 0 deletions .github/SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Reporting Security Issues

If you believe you have found a security vulnerability in the Plura App, we encourage you to let us know right away.

We will investigate all legitimate reports and do our best to quickly fix the problem.

Email `[email protected]` to disclose any security vulnerabilities.

Report in the server: https://l.devwtf.in/plura-dc
2 changes: 1 addition & 1 deletion .github/workflows/test-multiple-node-versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.18.0, 18.20.4, 22.11.0, 19.9.0, 23.1.0] # Ensure all versions are >= v18
node-version: [19.9.0, 18.20.4, 23.5.0] # Ensure all versions are >= v18

steps:
- name: Checkout
Expand Down
21 changes: 21 additions & 0 deletions apps/api/app/v1/[[...route]]/checkout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { type NextRequest, NextResponse } from 'next/server'
import { polar } from "@plura/mor";

export async function GET(req: NextRequest) {
const url = new URL(req.url)
const productPriceId = url.searchParams.get('priceId') ?? ''
// Polar will replace {CHECKOUT_ID} with the actual checkout ID upon a confirmed checkout
const confirmationUrl = `${req.nextUrl.protocol}//${req.nextUrl.host}/confirmation?checkout_id={CHECKOUT_ID}`

try {
const result = await polar.checkouts.custom.create({
productPriceId,
successUrl: confirmationUrl,
})

return NextResponse.redirect(result.url)
} catch (error) {
console.error(error)
return NextResponse.error()
}
}
3 changes: 3 additions & 0 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
"@plura/mail": "workspace:*",
"@prisma/client": "^5.22.0",
"@repo/types": "workspace:*",
"@plura/cache": "workspace:*",
"@plura/crypt":"workspace:*",
"@plura/mor":"workspace:*",
"@upstash/ratelimit": "^2.0.5",
"@upstash/redis": "^1.34.3",
"hono": "^4.6.9",
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions apps/triggers/package.json → apps/api/triggers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
"@plura/cache": "workspace:*",
"@plura/db": "workspace:*",
"@supabase/supabase-js": "^2.46.1",
"@trigger.dev/sdk": "3.3.5"
"@trigger.dev/sdk": "3.3.7"
},
"devDependencies": {
"@trigger.dev/build": "3.3.5"
"@trigger.dev/build": "3.3.7"
}
}
Empty file added apps/api/triggers/src/.gitkeep
Empty file.
105 changes: 105 additions & 0 deletions apps/api/triggers/src/contributors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { cache } from '@plura/cache';
import { logger, schedules } from '@trigger.dev/sdk/v3';

type ContributorData = {
login: string;
id: number;
avatar_url?: string;
html_url: string;
contributions: number;
};

export const publishContributorsTask = schedules.task({
id: "publish-contributors",
cron: "0 0 * * 0", // Runs every Sunday at midnight
maxDuration: 60,
run: async () => {
const owner = 'plura-ai';
const repos = ['plura', 'docs', 'agents', 'chatbot'];
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;

const MAX_PAGES = 50; // Limit total pages to prevent excessive API calls
const redisKey = 'contributors';
const contributorsMap: Record<number, ContributorData> = {};

const fetchContributors = async (repo: string) => {
let contributors: ContributorData[] = [];
let page = 1;

try {
do {
if (page > MAX_PAGES) {
logger.warn(`Reached maximum page limit of ${MAX_PAGES} for ${repo}`);
break;
}

const response = await fetch(
`https://api.github.com/repos/${owner}/${repo}/contributors?per_page=100&page=${page}`,
{
headers: {
Authorization: `token ${GITHUB_TOKEN}`,
Accept: 'application/vnd.github.v3+json',
},
}
);

const rateLimit = response.headers.get('x-ratelimit-remaining');
if (rateLimit === '0') {
logger.error(`GitHub API rate limit exceeded for ${repo}`);
return [];
}

if (!response.ok) {
logger.error(`GitHub API request failed for ${repo} with status ${response.status}`);
return [];
}

const data = await response.json();
if (data.length === 0) break;

contributors = contributors.concat(
data.filter((contributor: any) => !contributor.login.toLowerCase().includes('bot'))
);
page += 1;
} while (page <= MAX_PAGES);
} catch (error) {
logger.error(`Error fetching contributors for ${repo}`, { error });
throw error;
}

return contributors.map((contributor: any) => ({
login: contributor.login,
id: contributor.id,
avatar_url: contributor.avatar_url,
html_url: contributor.html_url,
contributions: contributor.contributions,
}));
};

try {
// Fetch and process contributors for each repository
for (const repo of repos) {
const repoContributors = await fetchContributors(repo);

repoContributors.forEach((contributor) => {
const existingContributor = contributorsMap[contributor.id];
if (existingContributor) {
existingContributor.contributions += contributor.contributions;
} else {
contributorsMap[contributor.id] = { ...contributor };
}
});
}

const finalContributors = Object.values(contributorsMap);

await cache.del(redisKey); // Clear previous data
await cache.rpush(redisKey, ...finalContributors.map((c) => JSON.stringify(c)));

logger.log('Published contributors data', { finalContributors });
} catch (error) {
logger.error('Error processing contributors', { error });
throw error;
}
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const dbStatusTask = schedules.task({
id: "db-status",
cron: "*/12 * * * *",
maxDuration: 600,
run: async (payload, { ctx }) => {
run: async () => {
const latencies: Record<string, number | null> = {};
let totalLatency = 0;
let operationCount = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { cache } from "@plura/cache";
import { logger, schedules } from "@trigger.dev/sdk/v3";

const DISCORD_WEBHOOK_URL = process.env.DISCORD_WEBHOOK!;
const LATENCY_THRESHOLD = 1000;
const LATENCY_THRESHOLD = 1500;

export const siteStatusTask = schedules.task({
id: "site-status",
Expand Down Expand Up @@ -71,15 +71,16 @@ async function sendDiscordNotification(
const downMsg = `🚨 Service **${serviceName}** is experiencing issues! 🚨`;
const upMsg = `⚠️ Service **${serviceName}** is having high latency! ⚠️`;
const NotifyMsg = status === "UP" ? upMsg : downMsg;
const mention = status === "UP" ? '' : `<@&${ROLE_ID}>`;
const message = {
content: `
<@&${ROLE_ID}>
${mention}
${NotifyMsg}
`,
embeds: [
{
title: `Status Alert for ${serviceName}`,
description: `Service **${serviceName}** is currently **${status}**.`,
description: `Service **[${serviceName}](https://status.plura.pro/)** is currently **${status}**.`,
color: status === "UP" ? 3066993 : 15158332, // Green for UP, Red for DOWN
fields: [
{
Expand All @@ -92,6 +93,11 @@ ${NotifyMsg}
value: error || "None",
inline: true,
},
{
name: "Source",
value: "[Status Page](https://status.plura.pro/)",
inline: true,
},
],
timestamp: new Date().toISOString(),
},
Expand Down
File renamed without changes.
5 changes: 4 additions & 1 deletion apps/api/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@
".next/types/**/*.ts",
"src/**/*.ts",
"src/**/*.d.ts"
, "../../packages/types/auth.ts" ],
,
"../../packages/types/auth.ts",
"trigger.config.ts"
],
"exclude": [
"node_modules"
]
Expand Down
8 changes: 8 additions & 0 deletions apps/services/slack/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "plura-slack",
"version": "1.0.0",
"main": "index.js",
"keywords": [],
"author": "",
"license": "ISC"
}
87 changes: 0 additions & 87 deletions apps/triggers/src/contributors.ts

This file was deleted.

27 changes: 20 additions & 7 deletions apps/www/app/(routes)/about/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,17 @@ import { siteConfig } from "@/config/site.config";
import Image from "next/image";
import React, { useEffect, useState } from "react";

type ContributorData = {
interface ContributorData {
login: string;
id: number;
avatar_url?: string;
github_link: string;
};
contributions: number;
}

export default function About() {
const [contributors, setContributors] = useState<ContributorData[]>([]);
const fetchUrl =
process.env.NODE_ENV === "production"
? "https://api.plura.pro/v1/contributors"
: "http://localhost:3001/v1/contributors";
const fetchUrl = "https://api.plura.pro/v1/contributors";

useEffect(() => {
const fetchContributors = async () => {
Expand Down Expand Up @@ -72,7 +70,22 @@ export default function About() {
/>
</Card>
</div>
<ContributorsGrid data={contributors} />
</section>
<section
id="contributors"
className="flex flex-col items-center justify-center w-full border-t-2 border-dashed"
>
<SectionHeader>
<SectionHeaderHeading className="text-3xl md:text-4xl">
Made with ❤️ by our contributors
</SectionHeaderHeading>
<SectionHeaderDescription>
Thanks to all of our great contributors!Thanks to all of our great contributors!Thanks to all of our great contributors!
</SectionHeaderDescription>
</SectionHeader>
<div className="px-8 md:px-12">
<ContributorsGrid data={contributors} />
</div>
</section>
</div>
</section>
Expand Down
5 changes: 0 additions & 5 deletions apps/www/app/(routes)/integrations/page.tsx

This file was deleted.

Loading

0 comments on commit 93935e7

Please sign in to comment.