diff --git a/src/pages/TopFlix.tsx b/src/pages/TopFlix.tsx
index e2121989..5ef8f8cc 100644
--- a/src/pages/TopFlix.tsx
+++ b/src/pages/TopFlix.tsx
@@ -1,6 +1,6 @@
import classNames from "classnames";
import { ReactNode, useEffect, useState } from "react";
-import { useNavigate } from "react-router-dom"; // Import Link from react-router-dom
+import { Link, useNavigate } from "react-router-dom"; // Import Link from react-router-dom
import { ThiccContainer } from "@/components/layout/ThinContainer";
import { Divider } from "@/components/utils/Divider";
@@ -183,6 +183,7 @@ export function TopFlix() {
const [timeSinceProcessStart, setTimeSinceProcessStart] = useState<
string | null
>(null);
+ const navigate = useNavigate();
useEffect(() => {
getRecentPlayedItems()
@@ -252,6 +253,12 @@ export function TopFlix() {
+ {/* */}
diff --git a/src/pages/TopSources.tsx b/src/pages/TopSources.tsx
new file mode 100644
index 00000000..b366372d
--- /dev/null
+++ b/src/pages/TopSources.tsx
@@ -0,0 +1,115 @@
+import { ReactNode, useEffect, useState } from "react";
+import { useNavigate } from "react-router-dom"; // Import Link from react-router-dom
+
+import { ThiccContainer } from "@/components/layout/ThinContainer";
+import { Divider } from "@/components/utils/Divider";
+import { Heading1, Paragraph } from "@/components/utils/Text";
+
+import { SubPageLayout } from "./layouts/SubPageLayout";
+// import { MediaGrid } from "@/components/media/MediaGrid"
+// import { TopFlixCard } from "@/components/media/FlixCard";
+
+function ConfigValue(props: { name: string; children?: ReactNode }) {
+ return (
+ <>
+
+
+
{props.name}
+
+
{props.children}
+
+
+ {/* props.type.charAt(0).toUpperCase() + props.type.slice(1) */}
+
+
+ >
+ );
+}
+
+async function getRecentPlayedItems() {
+ const response = await fetch("https://backend.sudo-flix.lol/metrics");
+ const text = await response.text();
+
+ const regex =
+ /mw_provider_status_count{provider_id="([^"]+)",status="([^"]+)"} (\d+)/g;
+ let match = regex.exec(text);
+ const items: { [key: string]: any } = {};
+
+ while (match !== null) {
+ const [_, providerId, status, count] = match;
+ if (items[providerId]) {
+ items[providerId].count += parseInt(count, 10);
+ } else {
+ items[providerId] = {
+ providerId,
+ status,
+ count: parseInt(count, 10),
+ };
+ }
+ match = regex.exec(text);
+ }
+
+ if (Object.keys(items).length > 0) {
+ return Object.values(items);
+ }
+ throw new Error("RECENT_PLAYED_ITEMS not found");
+}
+
+export function TopSources() {
+ const [recentPlayedItems, setRecentPlayedItems] = useState
([]);
+
+ useEffect(() => {
+ getRecentPlayedItems()
+ .then((items) => {
+ const limitedItems = items.filter(
+ (item, index, self) =>
+ index === self.findIndex((t2) => t2.providerId === item.providerId),
+ );
+ setRecentPlayedItems(limitedItems);
+ })
+ .catch((error) => {
+ console.error("Error fetching recent played items:", error);
+ });
+ }, []);
+
+ function getItemsForCurrentPage() {
+ const sortedItems = recentPlayedItems.sort((a, b) => b.count - a.count);
+
+ return sortedItems.map((item, index) => ({
+ ...item,
+ rank: index + 1,
+ }));
+ }
+
+ return (
+
+
+
+
Top sources
+
+ The most used providers on sudo-flix.lol, this data is fetched from
+ the current backend deployment too.
+
+
+
+
+
+ {getItemsForCurrentPage().map((item) => {
+ return (
+
+ {`Requests: `}
+ {item.count}
+
+ );
+ })}
+
+
+
+ );
+}
diff --git a/src/setup/App.tsx b/src/setup/App.tsx
index 9d54fbd7..6728311c 100644
--- a/src/setup/App.tsx
+++ b/src/setup/App.tsx
@@ -26,6 +26,7 @@ import { OnboardingProxyPage } from "@/pages/onboarding/OnboardingProxy";
import { RegisterPage } from "@/pages/Register";
import { SupportPage } from "@/pages/Support";
import { TopFlix } from "@/pages/TopFlix";
+import { TopSources } from "@/pages/TopSources";
import { Layout } from "@/setup/Layout";
import { useHistoryListener } from "@/stores/history";
import { LanguageProvider } from "@/stores/language";
@@ -152,6 +153,7 @@ function App() {
} />
{/* Top flix page */}
} />
+ } />
{/* Settings page */}